seat: add a keyboard focus hook
This commit is contained in:
parent
afd92d0a3d
commit
5e9ad96b0f
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -112,6 +112,7 @@ struct KbdInternal {
|
|||
state: xkb::State,
|
||||
repeat_rate: i32,
|
||||
repeat_delay: i32,
|
||||
focus_hook: Box<FnMut(Option<&Resource<WlSurface>>)>,
|
||||
}
|
||||
|
||||
// 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<KbdInternal, ()> {
|
||||
fn new(
|
||||
xkb_config: XkbConfig,
|
||||
repeat_rate: i32,
|
||||
repeat_delay: i32,
|
||||
focus_hook: Box<FnMut(Option<&Resource<WlSurface>>)>,
|
||||
) -> Result<KbdInternal, ()> {
|
||||
// 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<F>(
|
||||
xkb_config: XkbConfig,
|
||||
repeat_delay: i32,
|
||||
repeat_rate: i32,
|
||||
logger: &::slog::Logger,
|
||||
) -> Result<KeyboardHandle, Error> {
|
||||
focus_hook: F,
|
||||
) -> Result<KeyboardHandle, Error>
|
||||
where
|
||||
F: FnMut(Option<&Resource<WlSurface>>) + '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 {
|
||||
|
|
|
@ -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<Mutex<Inner>>,
|
||||
}
|
||||
|
@ -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<F>(
|
||||
&mut self,
|
||||
xkb_config: keyboard::XkbConfig,
|
||||
repeat_delay: i32,
|
||||
repeat_rate: i32,
|
||||
) -> Result<KeyboardHandle, KeyboardError> {
|
||||
mut focus_hook: F,
|
||||
) -> Result<KeyboardHandle, KeyboardError>
|
||||
where
|
||||
F: FnMut(&Seat, Option<&Resource<wl_surface::WlSurface>>) + '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
|
||||
|
|
Loading…
Reference in New Issue