seat: add a keyboard focus hook

This commit is contained in:
Victor Berger 2018-11-18 10:58:04 +01:00
parent afd92d0a3d
commit 5e9ad96b0f
4 changed files with 55 additions and 14 deletions

View File

@ -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(

View File

@ -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(

View File

@ -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 {

View File

@ -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