From 95e1046b0f427b018c666ae46dcd4159490400eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?W=C3=B6lfchen?= <115360611+W-lfchen@users.noreply.github.com> Date: Sun, 1 Sep 2024 21:30:18 +0200 Subject: [PATCH] feat: add keyboard support for button presses Co-authored-by: Julian Schuler <31921487+julianschuler@users.noreply.github.com> --- crates/eww/src/widgets/widget_definitions.rs | 34 +++++++++++++------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/crates/eww/src/widgets/widget_definitions.rs b/crates/eww/src/widgets/widget_definitions.rs index 0fb88f13..b120390a 100644 --- a/crates/eww/src/widgets/widget_definitions.rs +++ b/crates/eww/src/widgets/widget_definitions.rs @@ -38,16 +38,16 @@ use yuck::{ /// thus not connecting a new handler unless the condition is met. macro_rules! connect_signal_handler { ($widget:ident, if $cond:expr, $connect_expr:expr) => {{ + const KEY:&str = std::concat!("signal-handler:", std::line!()); unsafe { - let key = ::std::concat!("signal-handler:", ::std::line!()); - let old = $widget.data::(key); + let old = $widget.data::(KEY); if let Some(old) = old { let a = old.as_ref().as_raw(); $widget.disconnect(gtk::glib::SignalHandlerId::from_glib(a)); } - $widget.set_data::(key, $connect_expr); + $widget.set_data::(KEY, $connect_expr); } }}; ($widget:ident, $connect_expr:expr) => {{ @@ -494,7 +494,6 @@ fn build_gtk_input(bargs: &mut BuilderArgs) -> Result { prop(value: as_string) { gtk_widget.set_text(&value); }, - // @prop onchange - Command to run when the text changes. The placeholder `{}` will be replaced by the value // @prop timeout - timeout of the command. Default: "200ms" prop(timeout: as_duration = Duration::from_millis(200), onchange: as_string) { @@ -534,8 +533,15 @@ fn build_gtk_button(bargs: &mut BuilderArgs) -> Result { // @prop onrightclick - a command that get's run when the button is rightclicked onrightclick: as_string = "" ) { - gtk_widget.add_events(gdk::EventMask::BUTTON_PRESS_MASK); - connect_signal_handler!(gtk_widget, gtk_widget.connect_button_press_event(move |_, evt| { + // animate button upon right-/middleclick (if gtk theme supports it) + // since we do this, we can't use `connect_clicked` as that would always run `onclick` as well + connect_signal_handler!(gtk_widget, gtk_widget.connect_button_press_event(move |button, _| { + button.emit_activate(); + glib::Propagation::Proceed + })); + let onclick_ = onclick.clone(); + // mouse click events + connect_signal_handler!(gtk_widget, gtk_widget.connect_button_release_event(move |_, evt| { match evt.button() { 1 => run_command(timeout, &onclick, &[] as &[&str]), 2 => run_command(timeout, &onmiddleclick, &[] as &[&str]), @@ -544,8 +550,18 @@ fn build_gtk_button(bargs: &mut BuilderArgs) -> Result { } glib::Propagation::Proceed })); + // keyboard events + connect_signal_handler!(gtk_widget, gtk_widget.connect_key_release_event(move |_, evt| { + match evt.scancode() { + // return + 36 => run_command(timeout, &onclick_, &[] as &[&str]), + // space + 65 => run_command(timeout, &onclick_, &[] as &[&str]), + _ => {}, + } + glib::Propagation::Proceed + })); } - }); Ok(gtk_widget) } @@ -915,9 +931,6 @@ fn build_gtk_event_box(bargs: &mut BuilderArgs) -> Result { }; })); }, - - // TODO the fact that we have the same code here as for button is ugly, as we want to keep consistency - prop( // @prop timeout - timeout of the command. Default: "200ms" timeout: as_duration = Duration::from_millis(200), @@ -940,7 +953,6 @@ fn build_gtk_event_box(bargs: &mut BuilderArgs) -> Result { })); } }); - Ok(gtk_widget) }