From ffc38fed7e8c513db359c11a4f44be88ae439a02 Mon Sep 17 00:00:00 2001 From: Alexandre Picavet Date: Mon, 13 Jan 2025 03:20:39 +0100 Subject: [PATCH] feat(eventbox-keypress-command): Add keypress property to eventbox --- CHANGELOG.md | 1 + crates/eww/src/widgets/widget_definitions.rs | 48 +++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96154b33..59fc51e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ All notable changes to eww will be listed here, starting at changes since versio - Add keyboard support for button presses (By: julianschuler) - Support empty string for safe access operator (By: ModProg) - Add `log` function calls to simplexpr (By: topongo) +- Add support for `:keypress` for eventbox (By: AlexandrePicavet) ## [0.6.0] (21.04.2024) diff --git a/crates/eww/src/widgets/widget_definitions.rs b/crates/eww/src/widgets/widget_definitions.rs index 29c14a08..709f4164 100644 --- a/crates/eww/src/widgets/widget_definitions.rs +++ b/crates/eww/src/widgets/widget_definitions.rs @@ -952,7 +952,16 @@ fn build_gtk_event_box(bargs: &mut BuilderArgs) -> Result { } glib::Propagation::Proceed })); - } + }, + // @prop keypress - The key to press followed by the separator '|>' then followed by the + // command to execute. + // @prop timeout - timeout of the command. Default "200ms" + prop( + timeout: as_duration = Duration::from_millis(200), + keypress: as_string + ) { + parse_keypress(gtk_widget.as_ref(), timeout, keypress); + }, }); Ok(gtk_widget) } @@ -1398,3 +1407,40 @@ fn connect_first_map, F: Fn(&W) + 'static>(widget: &W, func: } })); } + +const KEYPRESS_COMMAND_SEPARATOR: &str = "|>"; +fn parse_keypress(gtk_widget: >k::Widget, timeout: Duration, keypress: String) -> () { + let parsed_keypress = keypress + .split_once(KEYPRESS_COMMAND_SEPARATOR) + .map(|(key_name, command)| (key_name.trim().to_owned(), command.trim().to_owned())); + + match parsed_keypress { + Some((wanted_key_name, command)) => handle_keypress(gtk_widget, timeout, wanted_key_name, command), + None => log::error!( + "The 'keypress' property must be in the format: '[KEY] {} [COMMAND]', but got: {}", + KEYPRESS_COMMAND_SEPARATOR, + keypress + ), + }; +} + +/// Connect a keypress to a gtk widget allowing to execute a given command +fn handle_keypress(gtk_widget: >k::Widget, timeout: Duration, wanted_key_name: String, command: String) -> () { + connect_signal_handler!( + gtk_widget, + gtk_widget.connect_key_press_event(move |gtk_widget, event_key| { + match event_key.keyval().name().map(|pressed_key_name| pressed_key_name.to_string()) { + Some(pressed_key_name) => { + log::debug!("Key '{}' pressed on widget: {}", pressed_key_name, gtk_widget.path()); + + if wanted_key_name == pressed_key_name { + run_command(timeout, &command, &[] as &[&str]); + }; + } + None => (), + }; + + glib::Propagation::Proceed + }) + ); +}