I am using gtk-rs
and want to be able to detect when any key is pressed.
From some searching online, it seems like the way to do that in C is with gtk_widget_add_events
and then g_signal_connect
. This answer has a good explanation.
In Rust, I can call Widget::add_events
. I also found several definitions for g_signal_connect_*
. But, these functions are unsafe
, undocumented, and seem to take C types as arguments.
My question is:
gobject_sys::g_signal_connect_closure
, how do I create a GObject
and GClosure
. In Rust? Can rust structs and closures be converted to that?I figured it out.
Thansk @Jmb, Widget::connect
was the right way to go. But, that function is undocumented and has some very weird types. Here's how I figured out how to use it:
window
.connect("key_press_event", false, |values| {
// "values" is a 2-long slice of glib::value::Value, which wrap G-types
// You can unwrap them if you know what type they are going to be ahead of time
// values[0] is the window and values[1] is the event
let raw_event = &values[1].get::<gdk::Event>().unwrap().unwrap();
// You have to cast to the correct event type to access some of the fields
match raw_event.downcast_ref::<gdk::EventKey>() {
Some(event) => {
println!("key value: {:?}", std::char::from_u32(event.get_keyval()));
println!("modifiers: {:?}", event.get_state());
},
None => {},
}
// You need to return Some() of a glib Value wrapping a bool
let result = glib::value::Value::from_type(glib::types::Type::Bool);
// I can't figure out how to actually set the value of result
// Luckally returning false is good enough for now.
Some(result)
})
.unwrap();