From cd05818465310b3e4b40cefa0752f3e81c932cbc Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Sat, 21 Jun 2025 21:13:33 +0900 Subject: [PATCH] widget event handling into macro --- uidev/assets/watch/controller.svg | 1 - wgui/src/components/button.rs | 6 +- wgui/src/event.rs | 14 +- wgui/src/widget/mod.rs | 182 +++++------------- wlx-overlay-s/src/assets/gui/watch.xml | 16 +- wlx-overlay-s/src/assets/watch/controller.svg | 1 - .../src/overlays/keyboard/builder.rs | 6 +- wlx-overlay-s/src/overlays/keyboard/mod.rs | 15 +- 8 files changed, 86 insertions(+), 155 deletions(-) delete mode 120000 uidev/assets/watch/controller.svg delete mode 100644 wlx-overlay-s/src/assets/watch/controller.svg diff --git a/uidev/assets/watch/controller.svg b/uidev/assets/watch/controller.svg deleted file mode 120000 index a80e2d5..0000000 --- a/uidev/assets/watch/controller.svg +++ /dev/null @@ -1 +0,0 @@ -../../../wlx-overlay-s/src/assets/watch/controller.svg \ No newline at end of file diff --git a/wgui/src/components/button.rs b/wgui/src/components/button.rs index fce6731..9bf9be7 100644 --- a/wgui/src/components/button.rs +++ b/wgui/src/components/button.rs @@ -147,7 +147,7 @@ pub fn construct( // Highlight background on mouse enter { let button = button.clone(); - widget.add_event_listener(EventListener::MouseEnter(Box::new(move |data| { + widget.add_event_listener(EventListener::MouseEnter(Box::new(move |data, _| { data .animations .push(anim_hover_in(button.clone(), data.widget_id)); @@ -157,7 +157,7 @@ pub fn construct( // Bring back old color on mouse leave { let button = button.clone(); - widget.add_event_listener(EventListener::MouseLeave(Box::new(move |data| { + widget.add_event_listener(EventListener::MouseLeave(Box::new(move |data, _| { data .animations .push(anim_hover_out(button.clone(), data.widget_id)); @@ -165,4 +165,4 @@ pub fn construct( } Ok(button) -} +} \ No newline at end of file diff --git a/wgui/src/event.rs b/wgui/src/event.rs index 0d5b01a..9f6988c 100644 --- a/wgui/src/event.rs +++ b/wgui/src/event.rs @@ -41,8 +41,12 @@ pub struct MouseWheelEvent { pub device: usize, } +pub struct InternalStateChangeEvent { + pub metadata: usize, +} + pub enum Event { - InternalStateChange, + InternalStateChange(InternalStateChangeEvent), MouseDown(MouseDownEvent), MouseLeave(MouseLeaveEvent), MouseMotion(MouseMotionEvent), @@ -117,11 +121,11 @@ impl<'a> WidgetCallback<'a> for CallbackData<'a> { } } -pub type MouseEnterCallback = Box; -pub type MouseLeaveCallback = Box; +pub type MouseEnterCallback = Box; +pub type MouseLeaveCallback = Box; pub type MousePressCallback = Box; pub type MouseReleaseCallback = Box; -pub type InternalStateChangeCallback = Box; +pub type InternalStateChangeCallback = Box; pub enum EventListener { MouseEnter(MouseEnterCallback), @@ -129,4 +133,4 @@ pub enum EventListener { MousePress(MousePressCallback), MouseRelease(MouseReleaseCallback), InternalStateChange(InternalStateChangeCallback), -} +} \ No newline at end of file diff --git a/wgui/src/widget/mod.rs b/wgui/src/widget/mod.rs index d77cc54..d912c52 100644 --- a/wgui/src/widget/mod.rs +++ b/wgui/src/widget/mod.rs @@ -181,6 +181,33 @@ impl dyn WidgetObj { } } +macro_rules! call_event { + ($self:ident, $widget_id:ident, $node_id:ident, $params:ident, $ev:ident, $cb_arg:expr) => { + for listener in &$self.event_listeners { + if let EventListener::$ev(callback) = listener { + let mut data = CallbackData { + obj: $self.obj.as_mut(), + widget_data: &mut $self.data, + widgets: $params.widgets, + animations: $params.animations, + dirty_nodes: $params.dirty_nodes, + $widget_id, + $node_id, + needs_redraw: false, + trigger_haptics: false, + }; + callback(&mut data, $cb_arg); + if data.trigger_haptics { + *$params.trigger_haptics = true; + } + if data.needs_redraw { + *$params.needs_redraw = true; + } + } + } + }; +} + impl WidgetState { pub fn add_event_listener(&mut self, listener: EventListener) { self.event_listeners.push(listener); @@ -304,24 +331,16 @@ impl WidgetState { ) -> EventResult { let hovered = event.test_mouse_within_transform(params.transform_stack.get()); - // buttons don't need to be tracked separately as long as we stick to VR use. - let mut pressed_changed_button = None; - let mut hovered_changed = false; - match &event { Event::MouseDown(e) => { - if hovered { - pressed_changed_button = self - .data - .set_device_pressed(e.device, true) - .then_some(e.button); + if hovered && self.data.set_device_pressed(e.device, true) { + call_event!(self, widget_id, node_id, params, MousePress, e.button); } } Event::MouseUp(e) => { - pressed_changed_button = self - .data - .set_device_pressed(e.device, false) - .then_some(e.button); + if self.data.set_device_pressed(e.device, false) { + call_event!(self, widget_id, node_id, params, MouseRelease, e.button); + } } Event::MouseWheel(e) => { if hovered && self.process_wheel(params, e) { @@ -329,127 +348,30 @@ impl WidgetState { } } Event::MouseMotion(e) => { - hovered_changed |= self.data.set_device_hovered(e.device, hovered); + if self.data.set_device_hovered(e.device, hovered) { + if self.data.is_hovered() { + call_event!(self, widget_id, node_id, params, MouseEnter, ()); + } else { + call_event!(self, widget_id, node_id, params, MouseLeave, ()); + } + } } Event::MouseLeave(e) => { - hovered_changed |= self.data.set_device_hovered(e.device, false); - } - _ => {} - } - - for listener in &self.event_listeners { - match listener { - EventListener::MouseEnter(callback) => { - if hovered_changed && self.data.is_hovered() { - let mut data = CallbackData { - obj: self.obj.as_mut(), - widget_data: &mut self.data, - widgets: params.widgets, - animations: params.animations, - dirty_nodes: params.dirty_nodes, - widget_id, - node_id, - needs_redraw: false, - trigger_haptics: false, - }; - callback(&mut data); - if data.trigger_haptics { - *params.trigger_haptics = true; - } - if data.needs_redraw { - *params.needs_redraw = true; - } - } - } - EventListener::MouseLeave(callback) => { - if hovered_changed && !self.data.is_hovered() { - let mut data = CallbackData { - obj: self.obj.as_mut(), - widget_data: &mut self.data, - widgets: params.widgets, - animations: params.animations, - dirty_nodes: params.dirty_nodes, - widget_id, - node_id, - needs_redraw: false, - trigger_haptics: false, - }; - callback(&mut data); - if data.trigger_haptics { - *params.trigger_haptics = true; - } - if data.needs_redraw { - *params.needs_redraw = true; - } - } - } - EventListener::MousePress(callback) => { - if let Some(button) = pressed_changed_button.filter(|_| self.data.is_pressed()) { - let mut data = CallbackData { - obj: self.obj.as_mut(), - widget_data: &mut self.data, - widgets: params.widgets, - animations: params.animations, - dirty_nodes: params.dirty_nodes, - widget_id, - node_id, - needs_redraw: false, - trigger_haptics: false, - }; - callback(&mut data, button); - if data.trigger_haptics { - *params.trigger_haptics = true; - } - if data.needs_redraw { - *params.needs_redraw = true; - } - } - } - EventListener::MouseRelease(callback) => { - if let Some(button) = pressed_changed_button.filter(|_| !self.data.is_pressed()) { - let mut data = CallbackData { - obj: self.obj.as_mut(), - widget_data: &mut self.data, - widgets: params.widgets, - animations: params.animations, - dirty_nodes: params.dirty_nodes, - widget_id, - node_id, - needs_redraw: false, - trigger_haptics: false, - }; - callback(&mut data, button); - if data.trigger_haptics { - *params.trigger_haptics = true; - } - if data.needs_redraw { - *params.needs_redraw = true; - } - } - } - EventListener::InternalStateChange(callback) => { - let mut data = CallbackData { - obj: self.obj.as_mut(), - widget_data: &mut self.data, - widgets: params.widgets, - animations: params.animations, - dirty_nodes: params.dirty_nodes, - widget_id, - node_id, - needs_redraw: false, - trigger_haptics: false, - }; - callback(&mut data); - if data.trigger_haptics { - *params.trigger_haptics = true; - } - if data.needs_redraw { - *params.needs_redraw = true; - } + if self.data.set_device_hovered(e.device, false) { + call_event!(self, widget_id, node_id, params, MouseLeave, ()); } } + Event::InternalStateChange(e) => { + call_event!( + self, + widget_id, + node_id, + params, + InternalStateChange, + e.metadata + ); + } } - EventResult::Pass } -} +} \ No newline at end of file diff --git a/wlx-overlay-s/src/assets/gui/watch.xml b/wlx-overlay-s/src/assets/gui/watch.xml index 8a6b148..54ce61d 100644 --- a/wlx-overlay-s/src/assets/gui/watch.xml +++ b/wlx-overlay-s/src/assets/gui/watch.xml @@ -17,19 +17,19 @@
- - - - - - + + + + + +
@@ -51,4 +51,4 @@
- \ No newline at end of file + diff --git a/wlx-overlay-s/src/assets/watch/controller.svg b/wlx-overlay-s/src/assets/watch/controller.svg deleted file mode 100644 index b788296..0000000 --- a/wlx-overlay-s/src/assets/watch/controller.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/wlx-overlay-s/src/overlays/keyboard/builder.rs b/wlx-overlay-s/src/overlays/keyboard/builder.rs index c367d8d..e8ee6a7 100644 --- a/wlx-overlay-s/src/overlays/keyboard/builder.rs +++ b/wlx-overlay-s/src/overlays/keyboard/builder.rs @@ -183,7 +183,7 @@ where *widget_id, EventListener::MouseEnter(Box::new({ let (k, kb) = (key_state.clone(), state.clone()); - move |data| { + move |data, ()| { data.trigger_haptics = true; on_enter_anim(k.clone(), kb.clone(), data); } @@ -193,7 +193,7 @@ where *widget_id, EventListener::MouseLeave(Box::new({ let (k, kb) = (key_state.clone(), state.clone()); - move |data| { + move |data, ()| { data.trigger_haptics = true; on_leave_anim(k.clone(), kb.clone(), data); } @@ -235,7 +235,7 @@ where *widget_id, EventListener::InternalStateChange(Box::new({ let (k, kb) = (key_state.clone(), state.clone()); - move |data| { + move |data, _| { if (kb.borrow().modifiers & modifier) != 0 { on_press_anim(k.clone(), data); } else { diff --git a/wlx-overlay-s/src/overlays/keyboard/mod.rs b/wlx-overlay-s/src/overlays/keyboard/mod.rs index 4e9e804..86899f1 100644 --- a/wlx-overlay-s/src/overlays/keyboard/mod.rs +++ b/wlx-overlay-s/src/overlays/keyboard/mod.rs @@ -6,7 +6,10 @@ use std::{ }; use vulkano::image::view::ImageView; -use wgui::{drawing, event::MouseButton}; +use wgui::{ + drawing, + event::{InternalStateChangeEvent, MouseButton}, +}; use crate::{ backend::{ @@ -57,11 +60,13 @@ impl OverlayBackend for KeyboardBackend { impl InteractionHandler for KeyboardBackend { fn on_pointer(&mut self, app: &mut AppState, hit: &PointerHit, pressed: bool) { self.panel.on_pointer(app, hit, pressed); + self.handle_invoke(app); let _ = self .panel .layout - .push_event(&wgui::event::Event::InternalStateChange); - self.handle_invoke(app); + .push_event(&wgui::event::Event::InternalStateChange( + InternalStateChangeEvent { metadata: 0 }, + )); } fn on_scroll(&mut self, app: &mut AppState, hit: &PointerHit, delta_y: f32, delta_x: f32) { self.panel.on_scroll(app, hit, delta_y, delta_x); @@ -102,7 +107,9 @@ impl OverlayRenderer for KeyboardBackend { self.panel.resume(app)?; self.panel .layout - .push_event(&wgui::event::Event::InternalStateChange)?; + .push_event(&wgui::event::Event::InternalStateChange( + InternalStateChangeEvent { metadata: 0 }, + ))?; Ok(()) } }