diff --git a/anvil/src/udev.rs b/anvil/src/udev.rs index 97695ce..3232fcf 100644 --- a/anvil/src/udev.rs +++ b/anvil/src/udev.rs @@ -111,7 +111,7 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger let pointer = w_seat.add_pointer(); let keyboard = w_seat - .add_keyboard(XkbConfig::default(), 1000, 500) + .add_keyboard(XkbConfig::default(), 1000, 500, |_, _| {}) .expect("Failed to initialize the keyboard"); let (output, _output_global) = Output::new( diff --git a/anvil/src/winit.rs b/anvil/src/winit.rs index 29566bb..9d4d479 100644 --- a/anvil/src/winit.rs +++ b/anvil/src/winit.rs @@ -57,7 +57,7 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log let pointer = seat.add_pointer(); let keyboard = seat - .add_keyboard(XkbConfig::default(), 1000, 500) + .add_keyboard(XkbConfig::default(), 1000, 500, |_, _| {}) .expect("Failed to initialize the keyboard"); let (output, _) = Output::new( diff --git a/src/wayland/seat/keyboard.rs b/src/wayland/seat/keyboard.rs index 2aaa0e2..55c2622 100644 --- a/src/wayland/seat/keyboard.rs +++ b/src/wayland/seat/keyboard.rs @@ -112,6 +112,7 @@ struct KbdInternal { state: xkb::State, repeat_rate: i32, repeat_delay: i32, + focus_hook: Box>)>, } // This is OK because all parts of `xkb` will remain on the @@ -119,7 +120,12 @@ struct KbdInternal { unsafe impl Send for KbdInternal {} impl KbdInternal { - fn new(xkb_config: XkbConfig, repeat_rate: i32, repeat_delay: i32) -> Result { + fn new( + xkb_config: XkbConfig, + repeat_rate: i32, + repeat_delay: i32, + focus_hook: Box>)>, + ) -> Result { // we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe // so confining it inside the KbdInternal allows us to use Rusts mutability rules to make // sure nothing goes wrong. @@ -146,6 +152,7 @@ impl KbdInternal { state, repeat_rate, repeat_delay, + focus_hook, }) } @@ -219,21 +226,26 @@ pub enum Error { } /// Create a keyboard handler from a set of RMLVO rules -pub(crate) fn create_keyboard_handler( +pub(crate) fn create_keyboard_handler( xkb_config: XkbConfig, repeat_delay: i32, repeat_rate: i32, logger: &::slog::Logger, -) -> Result { + focus_hook: F, +) -> Result +where + F: FnMut(Option<&Resource>) + 'static, +{ let log = logger.new(o!("smithay_module" => "xkbcommon_handler")); info!(log, "Initializing a xkbcommon handler with keymap query"; "rules" => xkb_config.rules, "model" => xkb_config.model, "layout" => xkb_config.layout, "variant" => xkb_config.variant, "options" => &xkb_config.options ); - let internal = KbdInternal::new(xkb_config, repeat_rate, repeat_delay).map_err(|_| { - debug!(log, "Loading keymap failed"); - Error::BadKeymap - })?; + let internal = + KbdInternal::new(xkb_config, repeat_rate, repeat_delay, Box::new(focus_hook)).map_err(|_| { + debug!(log, "Loading keymap failed"); + Error::BadKeymap + })?; info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next()); @@ -382,6 +394,14 @@ impl KeyboardHandle { keys: keys.clone(), }); }); + { + let KbdInternal { + ref focus, + ref mut focus_hook, + .. + } = *guard; + focus_hook(focus.as_ref()); + } if guard.focus.is_some() { trace!(self.arc.logger, "Focus set to new surface"); } else { diff --git a/src/wayland/seat/mod.rs b/src/wayland/seat/mod.rs index 41e60d1..5853475 100644 --- a/src/wayland/seat/mod.rs +++ b/src/wayland/seat/mod.rs @@ -64,7 +64,10 @@ pub use self::{ pointer::{AxisFrame, PointerGrab, PointerHandle, PointerInnerHandle}, }; -use wayland_server::{protocol::wl_seat, Display, Global, NewResource, Resource}; +use wayland_server::{ + protocol::{wl_seat, wl_surface}, + Display, Global, NewResource, Resource, +}; struct Inner { log: ::slog::Logger, @@ -101,7 +104,11 @@ impl Inner { /// /// It is directly inserted in the event loop by its `new` method. /// +/// This is an handle to the inner logic, it can be cloned and shared accross +/// threads. +/// /// See module-level documentation for details of use. +#[derive(Clone)] pub struct Seat { inner: Arc>, } @@ -217,18 +224,32 @@ impl Seat { /// }, /// 1000, /// 500, + /// |seat, focus| { + /// /* This closure is called whenever the keyboard focus + /// * changes, with the new focus as argument */ + /// } /// ) /// .expect("Failed to initialize the keyboard"); /// ``` - pub fn add_keyboard( + pub fn add_keyboard( &mut self, xkb_config: keyboard::XkbConfig, repeat_delay: i32, repeat_rate: i32, - ) -> Result { + mut focus_hook: F, + ) -> Result + where + F: FnMut(&Seat, Option<&Resource>) + 'static, + { + let me = self.clone(); let mut inner = self.inner.lock().unwrap(); - let keyboard = - self::keyboard::create_keyboard_handler(xkb_config, repeat_delay, repeat_rate, &inner.log)?; + let keyboard = self::keyboard::create_keyboard_handler( + xkb_config, + repeat_delay, + repeat_rate, + &inner.log, + move |focus| focus_hook(&me, focus), + )?; if inner.keyboard.is_some() { // there is already a keyboard, remove it and notify the clients // of the change