Search code examples
rustgtkgtk4

Detect that user presses spacebar GTK4


I am using gtk4-rs to make a GUI app for a music player. I would like to hit spacebar to play/pause songs, so I wanted to detect that a user hit spacebar in the app

I tried using EventControllerKey to detect the keypress, e.g. something like this

use gtk4::prelude::*;

fn main() {
    let application =
        gtk4::Application::new(Some("com.github.gtk-rs.examples.basic"), Default::default());
    application.connect_activate(build_ui);
    application.run();
}

fn build_ui(application: &gtk4::Application) {
    let window = gtk4::ApplicationWindow::new(application);

    window.set_title(Some("First GTK Program"));
    window.set_default_size(350, 70);

    let evk = gtk4::EventControllerKey::new(); //builder().
    evk.connect_key_pressed(|a, b, c, d| {
        println!("{:?} {} {} {}", a, b, c, d);
        // gtk::Inhibit(false)
        false.into()
    });
    window.add_controller(evk);

    let button = gtk4::Button::with_label("Click me!");

    window.set_child(Some(&button));

    window.show();
}

And this intercepts many letters that I type, but not spacebar (which seems to try to perform an action of clicking the button, which I also do not want)

sample output, no spacebars

EventControllerKey { inner: TypedObjectRef { inner: 0x55e61ba114c0, type: GtkEventControllerKey } } Key { name: Some("f"), is_lower: true, is_upper: false } 41 (empty)
EventControllerKey { inner: TypedObjectRef { inner: 0x55e61ba114c0, type: GtkEventControllerKey } } Key { name: Some("s"), is_lower: true, is_upper: false } 39 (empty)
EventControllerKey { inner: TypedObjectRef { inner: 0x55e61ba114c0, type: GtkEventControllerKey } } Key { name: Some("a"), is_lower: true, is_upper: false } 38 (empty)
EventControllerKey { inner: TypedObjectRef { inner: 0x55e61ba114c0, type: GtkEventControllerKey } } Key { name: Some("d"), is_lower: true, is_upper: false } 40 (empty)
EventControllerKey { inner: TypedObjectRef { inner: 0x55e61ba114c0, type: GtkEventControllerKey } } Key { name: Some("f"), is_lower: true, is_upper: false } 41 (empty)



Solution

  • As you have noticed, the button does consume the keypress event when spacebar is pressed. That is because taking care of those key pressed are how buttons work. Widgets do get a chance to handle events during the capture phase, which happens before the bubble phase where any application specific actions to still available events can be taken.

    The above section is a summary of gtk4's documentation of it's input handling.

    If the button widget is desired, do capture clicks of it instead of spacebar.