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 pointer = w_seat.add_pointer();
|
||||||
let keyboard = w_seat
|
let keyboard = w_seat
|
||||||
.add_keyboard(XkbConfig::default(), 1000, 500)
|
.add_keyboard(XkbConfig::default(), 1000, 500, |_, _| {})
|
||||||
.expect("Failed to initialize the keyboard");
|
.expect("Failed to initialize the keyboard");
|
||||||
|
|
||||||
let (output, _output_global) = Output::new(
|
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 pointer = seat.add_pointer();
|
||||||
let keyboard = seat
|
let keyboard = seat
|
||||||
.add_keyboard(XkbConfig::default(), 1000, 500)
|
.add_keyboard(XkbConfig::default(), 1000, 500, |_, _| {})
|
||||||
.expect("Failed to initialize the keyboard");
|
.expect("Failed to initialize the keyboard");
|
||||||
|
|
||||||
let (output, _) = Output::new(
|
let (output, _) = Output::new(
|
||||||
|
|
|
@ -112,6 +112,7 @@ struct KbdInternal {
|
||||||
state: xkb::State,
|
state: xkb::State,
|
||||||
repeat_rate: i32,
|
repeat_rate: i32,
|
||||||
repeat_delay: i32,
|
repeat_delay: i32,
|
||||||
|
focus_hook: Box<FnMut(Option<&Resource<WlSurface>>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is OK because all parts of `xkb` will remain on the
|
// This is OK because all parts of `xkb` will remain on the
|
||||||
|
@ -119,7 +120,12 @@ struct KbdInternal {
|
||||||
unsafe impl Send for KbdInternal {}
|
unsafe impl Send for KbdInternal {}
|
||||||
|
|
||||||
impl 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
|
// 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
|
// so confining it inside the KbdInternal allows us to use Rusts mutability rules to make
|
||||||
// sure nothing goes wrong.
|
// sure nothing goes wrong.
|
||||||
|
@ -146,6 +152,7 @@ impl KbdInternal {
|
||||||
state,
|
state,
|
||||||
repeat_rate,
|
repeat_rate,
|
||||||
repeat_delay,
|
repeat_delay,
|
||||||
|
focus_hook,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,21 +226,26 @@ pub enum Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a keyboard handler from a set of RMLVO rules
|
/// 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,
|
xkb_config: XkbConfig,
|
||||||
repeat_delay: i32,
|
repeat_delay: i32,
|
||||||
repeat_rate: i32,
|
repeat_rate: i32,
|
||||||
logger: &::slog::Logger,
|
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"));
|
let log = logger.new(o!("smithay_module" => "xkbcommon_handler"));
|
||||||
info!(log, "Initializing a xkbcommon handler with keymap query";
|
info!(log, "Initializing a xkbcommon handler with keymap query";
|
||||||
"rules" => xkb_config.rules, "model" => xkb_config.model, "layout" => xkb_config.layout,
|
"rules" => xkb_config.rules, "model" => xkb_config.model, "layout" => xkb_config.layout,
|
||||||
"variant" => xkb_config.variant, "options" => &xkb_config.options
|
"variant" => xkb_config.variant, "options" => &xkb_config.options
|
||||||
);
|
);
|
||||||
let internal = KbdInternal::new(xkb_config, repeat_rate, repeat_delay).map_err(|_| {
|
let internal =
|
||||||
debug!(log, "Loading keymap failed");
|
KbdInternal::new(xkb_config, repeat_rate, repeat_delay, Box::new(focus_hook)).map_err(|_| {
|
||||||
Error::BadKeymap
|
debug!(log, "Loading keymap failed");
|
||||||
})?;
|
Error::BadKeymap
|
||||||
|
})?;
|
||||||
|
|
||||||
info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next());
|
info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next());
|
||||||
|
|
||||||
|
@ -382,6 +394,14 @@ impl KeyboardHandle {
|
||||||
keys: keys.clone(),
|
keys: keys.clone(),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
{
|
||||||
|
let KbdInternal {
|
||||||
|
ref focus,
|
||||||
|
ref mut focus_hook,
|
||||||
|
..
|
||||||
|
} = *guard;
|
||||||
|
focus_hook(focus.as_ref());
|
||||||
|
}
|
||||||
if guard.focus.is_some() {
|
if guard.focus.is_some() {
|
||||||
trace!(self.arc.logger, "Focus set to new surface");
|
trace!(self.arc.logger, "Focus set to new surface");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -64,7 +64,10 @@ pub use self::{
|
||||||
pointer::{AxisFrame, PointerGrab, PointerHandle, PointerInnerHandle},
|
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 {
|
struct Inner {
|
||||||
log: ::slog::Logger,
|
log: ::slog::Logger,
|
||||||
|
@ -101,7 +104,11 @@ impl Inner {
|
||||||
///
|
///
|
||||||
/// It is directly inserted in the event loop by its `new` method.
|
/// 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.
|
/// See module-level documentation for details of use.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Seat {
|
pub struct Seat {
|
||||||
inner: Arc<Mutex<Inner>>,
|
inner: Arc<Mutex<Inner>>,
|
||||||
}
|
}
|
||||||
|
@ -217,18 +224,32 @@ impl Seat {
|
||||||
/// },
|
/// },
|
||||||
/// 1000,
|
/// 1000,
|
||||||
/// 500,
|
/// 500,
|
||||||
|
/// |seat, focus| {
|
||||||
|
/// /* This closure is called whenever the keyboard focus
|
||||||
|
/// * changes, with the new focus as argument */
|
||||||
|
/// }
|
||||||
/// )
|
/// )
|
||||||
/// .expect("Failed to initialize the keyboard");
|
/// .expect("Failed to initialize the keyboard");
|
||||||
/// ```
|
/// ```
|
||||||
pub fn add_keyboard(
|
pub fn add_keyboard<F>(
|
||||||
&mut self,
|
&mut self,
|
||||||
xkb_config: keyboard::XkbConfig,
|
xkb_config: keyboard::XkbConfig,
|
||||||
repeat_delay: i32,
|
repeat_delay: i32,
|
||||||
repeat_rate: 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 mut inner = self.inner.lock().unwrap();
|
||||||
let keyboard =
|
let keyboard = self::keyboard::create_keyboard_handler(
|
||||||
self::keyboard::create_keyboard_handler(xkb_config, repeat_delay, repeat_rate, &inner.log)?;
|
xkb_config,
|
||||||
|
repeat_delay,
|
||||||
|
repeat_rate,
|
||||||
|
&inner.log,
|
||||||
|
move |focus| focus_hook(&me, focus),
|
||||||
|
)?;
|
||||||
if inner.keyboard.is_some() {
|
if inner.keyboard.is_some() {
|
||||||
// there is already a keyboard, remove it and notify the clients
|
// there is already a keyboard, remove it and notify the clients
|
||||||
// of the change
|
// of the change
|
||||||
|
|
Loading…
Reference in New Issue