From 86e582472d1e01dcdc243113d4275f58ee06283e Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Wed, 6 Mar 2024 13:44:15 +0100 Subject: [PATCH] config: accept FnMut instead of Fn for callbacks --- jay-config/src/_private/client.rs | 90 +++++++++++++++++++------------ jay-config/src/input.rs | 6 +-- jay-config/src/lib.rs | 2 +- jay-config/src/timer.rs | 2 +- jay-config/src/video.rs | 8 +-- 5 files changed, 64 insertions(+), 44 deletions(-) diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index 496692bc..d78c76df 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -41,23 +41,36 @@ use { }, }; +type Callback = Rc>; + +fn cb(f: F) -> Callback { + Rc::new(RefCell::new(f)) +} + +fn run_cb(name: &str, cb: &Callback, t: T) { + match cb.try_borrow_mut() { + Ok(mut cb) => cb(t), + Err(_) => log::error!("Cannot invoke {name} callback because it is already running"), + } +} + pub(crate) struct Client { configure: extern "C" fn(), srv_data: *const u8, srv_unref: unsafe extern "C" fn(data: *const u8), srv_handler: unsafe extern "C" fn(data: *const u8, msg: *const u8, size: usize), - key_handlers: RefCell>>, - timer_handlers: RefCell>>, + key_handlers: RefCell>, + timer_handlers: RefCell>, response: RefCell>, - on_new_seat: RefCell>>, - on_new_input_device: RefCell>>, - on_connector_connected: RefCell>>, + on_new_seat: RefCell>>, + on_new_input_device: RefCell>>, + on_connector_connected: RefCell>>, on_graphics_initialized: Cell>>, on_devices_enumerated: Cell>>, - on_new_connector: RefCell>>, - on_new_drm_device: RefCell>>, - on_del_drm_device: RefCell>>, - on_idle: RefCell>>, + on_new_connector: RefCell>>, + on_new_drm_device: RefCell>>, + on_del_drm_device: RefCell>>, + on_idle: RefCell>, bufs: RefCell>>, reload: Cell, read_interests: RefCell>, @@ -319,8 +332,10 @@ impl Client { }); } - pub fn on_timer_tick(&self, timer: Timer, f: F) { - self.timer_handlers.borrow_mut().insert(timer, Rc::new(f)); + pub fn on_timer_tick(&self, timer: Timer, mut f: F) { + self.timer_handlers + .borrow_mut() + .insert(timer, cb(move |_| f())); } pub fn get_workspace(&self, name: &str) -> Workspace { @@ -496,8 +511,8 @@ impl Client { devices } - pub fn on_new_seat(&self, f: F) { - *self.on_new_seat.borrow_mut() = Some(Rc::new(f)); + pub fn on_new_seat(&self, f: F) { + *self.on_new_seat.borrow_mut() = Some(cb(f)); } pub fn quit(&self) { @@ -508,8 +523,8 @@ impl Client { self.send(&ClientMessage::SwitchTo { vtnr }) } - pub fn on_new_input_device(&self, f: F) { - *self.on_new_input_device.borrow_mut() = Some(Rc::new(f)); + pub fn on_new_input_device(&self, f: F) { + *self.on_new_input_device.borrow_mut() = Some(cb(f)); } pub fn set_double_click_interval(&self, usec: u64) { @@ -639,24 +654,24 @@ impl Client { devices } - pub fn on_new_drm_device(&self, f: F) { - *self.on_new_drm_device.borrow_mut() = Some(Rc::new(f)); + pub fn on_new_drm_device(&self, f: F) { + *self.on_new_drm_device.borrow_mut() = Some(cb(f)); } - pub fn on_del_drm_device(&self, f: F) { - *self.on_del_drm_device.borrow_mut() = Some(Rc::new(f)); + pub fn on_del_drm_device(&self, f: F) { + *self.on_del_drm_device.borrow_mut() = Some(cb(f)); } - pub fn on_new_connector(&self, f: F) { - *self.on_new_connector.borrow_mut() = Some(Rc::new(f)); + pub fn on_new_connector(&self, f: F) { + *self.on_new_connector.borrow_mut() = Some(cb(f)); } - pub fn on_idle(&self, f: F) { - *self.on_idle.borrow_mut() = Some(Rc::new(f)); + pub fn on_idle(&self, mut f: F) { + *self.on_idle.borrow_mut() = Some(cb(move |_| f())); } - pub fn on_connector_connected(&self, f: F) { - *self.on_connector_connected.borrow_mut() = Some(Rc::new(f)); + pub fn on_connector_connected(&self, f: F) { + *self.on_connector_connected.borrow_mut() = Some(cb(f)); } pub fn on_graphics_initialized(&self, f: F) { @@ -742,11 +757,16 @@ impl Client { keymap } - pub fn bind, F: Fn() + 'static>(&self, seat: Seat, mod_sym: T, f: F) { + pub fn bind, F: FnMut() + 'static>( + &self, + seat: Seat, + mod_sym: T, + mut f: F, + ) { let mod_sym = mod_sym.into(); let register = { let mut kh = self.key_handlers.borrow_mut(); - let f = Rc::new(f); + let f = cb(move |_| f()); match kh.entry((seat, mod_sym)) { Entry::Occupied(mut o) => { *o.get_mut() = f; @@ -914,34 +934,34 @@ impl Client { let ms = ModifiedKeySym { mods, sym }; let handler = self.key_handlers.borrow_mut().get(&(seat, ms)).cloned(); if let Some(handler) = handler { - handler(); + run_cb("shortcut", &handler, ()); } } ServerMessage::NewInputDevice { device } => { let handler = self.on_new_input_device.borrow_mut().clone(); if let Some(handler) = handler { - handler(device); + run_cb("new input device", &handler, device); } } ServerMessage::DelInputDevice { .. } => {} ServerMessage::ConnectorConnect { device } => { let handler = self.on_connector_connected.borrow_mut().clone(); if let Some(handler) = handler { - handler(device); + run_cb("connector connected", &handler, device); } } ServerMessage::ConnectorDisconnect { .. } => {} ServerMessage::NewConnector { device } => { let handler = self.on_new_connector.borrow_mut().clone(); if let Some(handler) = handler { - handler(device); + run_cb("new connector", &handler, device); } } ServerMessage::DelConnector { .. } => {} ServerMessage::TimerExpired { timer } => { let handler = self.timer_handlers.borrow_mut().get(&timer).cloned(); if let Some(handler) = handler { - handler(); + run_cb("timer", &handler, ()); } } ServerMessage::GraphicsInitialized => { @@ -955,19 +975,19 @@ impl Client { ServerMessage::NewDrmDev { device } => { let handler = self.on_new_drm_device.borrow_mut(); if let Some(handler) = handler.deref() { - handler(device); + run_cb("new drm device", handler, device); } } ServerMessage::DelDrmDev { device } => { let handler = self.on_del_drm_device.borrow_mut(); if let Some(handler) = handler.deref() { - handler(device); + run_cb("del drm device", handler, device); } } ServerMessage::Idle => { let handler = self.on_idle.borrow_mut(); if let Some(handler) = handler.deref() { - handler(); + run_cb("idle", handler, ()); } } ServerMessage::DevicesEnumerated => { diff --git a/jay-config/src/input.rs b/jay-config/src/input.rs index 96edc040..a3999ec6 100644 --- a/jay-config/src/input.rs +++ b/jay-config/src/input.rs @@ -161,7 +161,7 @@ impl Seat { /// /// CapsLock and NumLock are ignored during modifier evaluation. Therefore, bindings /// containing these modifiers will never be invoked. - pub fn bind, F: Fn() + 'static>(self, mod_sym: T, f: F) { + pub fn bind, F: FnMut() + 'static>(self, mod_sym: T, f: F) { get!().bind(self, mod_sym, f) } @@ -324,12 +324,12 @@ pub fn get_seat(name: &str) -> Seat { } /// Sets a closure to run when a new seat has been created. -pub fn on_new_seat(f: F) { +pub fn on_new_seat(f: F) { get!().on_new_seat(f) } /// Sets a closure to run when a new input device has been added. -pub fn on_new_input_device(f: F) { +pub fn on_new_input_device(f: F) { get!().on_new_input_device(f) } diff --git a/jay-config/src/lib.rs b/jay-config/src/lib.rs index e0ac9b58..533e0d77 100644 --- a/jay-config/src/lib.rs +++ b/jay-config/src/lib.rs @@ -185,7 +185,7 @@ impl Display for PciId { } /// Sets the callback to be called when the display goes idle. -pub fn on_idle(f: F) { +pub fn on_idle(f: F) { get!().on_idle(f) } diff --git a/jay-config/src/timer.rs b/jay-config/src/timer.rs index 9953198a..0a97ae99 100644 --- a/jay-config/src/timer.rs +++ b/jay-config/src/timer.rs @@ -53,7 +53,7 @@ impl Timer { } /// Sets the function to be executed when the timer expires. - pub fn on_tick(self, f: F) { + pub fn on_tick(self, f: F) { get!().on_timer_tick(self, f); } } diff --git a/jay-config/src/video.rs b/jay-config/src/video.rs index a41a2f8f..c01fa2bf 100644 --- a/jay-config/src/video.rs +++ b/jay-config/src/video.rs @@ -220,22 +220,22 @@ pub fn drm_devices() -> Vec { } /// Sets the callback to be called when a new DRM device appears. -pub fn on_new_drm_device(f: F) { +pub fn on_new_drm_device(f: F) { get!().on_new_drm_device(f) } /// Sets the callback to be called when a DRM device is removed. -pub fn on_drm_device_removed(f: F) { +pub fn on_drm_device_removed(f: F) { get!().on_del_drm_device(f) } /// Sets the callback to be called when a new connector appears. -pub fn on_new_connector(f: F) { +pub fn on_new_connector(f: F) { get!().on_new_connector(f) } /// Sets the callback to be called when a connector becomes connected to an output device. -pub fn on_connector_connected(f: F) { +pub fn on_connector_connected(f: F) { get!().on_connector_connected(f) }