Rework keyboard handler
This commit is contained in:
parent
c5048fea71
commit
2850def0f4
|
@ -5,7 +5,7 @@ authors = ["Victor Berger <victor.berger@thalesgroup.com>"]
|
|||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
wayland-server = "0.10.1"
|
||||
wayland-server = "0.10.2"
|
||||
nix = "0.7.0"
|
||||
xkbcommon = "0.2.1"
|
||||
tempfile = "2.1.5"
|
||||
|
@ -20,7 +20,7 @@ glium = { version = "0.17.1", optional = true, default-features = false }
|
|||
input = { version = "0.2.0", optional = true }
|
||||
clippy = { version = "*", optional = true }
|
||||
rental = "0.4.11"
|
||||
wayland-protocols = { version = "0.10.1", features = ["unstable_protocols", "server"] }
|
||||
wayland-protocols = { version = "0.10.2", features = ["unstable_protocols", "server"] }
|
||||
image = "0.15.0"
|
||||
error-chain = "0.11.0"
|
||||
|
||||
|
|
|
@ -74,7 +74,8 @@ impl ModifiersState {
|
|||
}
|
||||
|
||||
struct KbdInternal {
|
||||
focus: Option<(wl_surface::WlSurface, wl_keyboard::WlKeyboard)>,
|
||||
known_kbds: Vec<wl_keyboard::WlKeyboard>,
|
||||
focus: Option<wl_surface::WlSurface>,
|
||||
pressed_keys: Vec<u32>,
|
||||
mods_state: ModifiersState,
|
||||
keymap: xkb::Keymap,
|
||||
|
@ -102,6 +103,7 @@ impl KbdInternal {
|
|||
).ok_or(())?;
|
||||
let state = xkb::State::new(&keymap);
|
||||
Ok(KbdInternal {
|
||||
known_kbds: Vec::new(),
|
||||
focus: None,
|
||||
pressed_keys: Vec::new(),
|
||||
mods_state: ModifiersState::new(),
|
||||
|
@ -152,6 +154,18 @@ impl KbdInternal {
|
|||
};
|
||||
serialized.into()
|
||||
}
|
||||
|
||||
fn with_focused_kbds<F>(&self, mut f: F)
|
||||
where F: FnMut(&wl_keyboard::WlKeyboard, &wl_surface::WlSurface)
|
||||
{
|
||||
if let Some(ref surface) = self.focus {
|
||||
for kbd in &self.known_kbds {
|
||||
if kbd.same_client_as(surface) {
|
||||
f(kbd, surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Errors that can be encountered when creating a keyboard handler
|
||||
|
@ -227,7 +241,7 @@ impl KbdHandle {
|
|||
/// keyboard handler. It will internally track the state of the keymap.
|
||||
///
|
||||
/// The `filter` argument is expected to be a closure which will peek at the generated input
|
||||
/// as interpreted by the keymap befor it is forwarded to the focused client. If this closure
|
||||
/// as interpreted by the keymap before it is forwarded to the focused client. If this closure
|
||||
/// returns false, the input will not be sent to the client. This mechanism can be used to
|
||||
/// implement compositor-level key bindings for example.
|
||||
///
|
||||
|
@ -254,16 +268,22 @@ impl KbdHandle {
|
|||
}
|
||||
|
||||
// forward to client if no keybinding is triggered
|
||||
if let Some((_, ref kbd)) = guard.focus {
|
||||
if mods_changed {
|
||||
let (dep, la, lo, gr) = guard.serialize_modifiers();
|
||||
kbd.modifiers(serial, dep, la, lo, gr);
|
||||
}
|
||||
let modifiers = if mods_changed {
|
||||
Some(guard.serialize_modifiers())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let wl_state = match state {
|
||||
KeyState::Pressed => wl_keyboard::KeyState::Pressed,
|
||||
KeyState::Released => wl_keyboard::KeyState::Released,
|
||||
};
|
||||
guard.with_focused_kbds(|kbd, _| {
|
||||
if let Some((dep, la, lo, gr)) = modifiers {
|
||||
kbd.modifiers(serial, dep, la, lo, gr);
|
||||
}
|
||||
kbd.key(serial, 0, keycode, wl_state);
|
||||
});
|
||||
if guard.focus.is_some() {
|
||||
trace!(self.arc.logger, "Input forwarded to client");
|
||||
} else {
|
||||
trace!(self.arc.logger, "No client currently focused");
|
||||
|
@ -274,51 +294,50 @@ impl KbdHandle {
|
|||
///
|
||||
/// Any previous focus will be sent a `wl_keyboard::leave` event, and if the new focus
|
||||
/// is not `None`, a `wl_keyboard::enter` event will be sent.
|
||||
pub fn set_focus(&self, focus: Option<(wl_surface::WlSurface, wl_keyboard::WlKeyboard)>, serial: u32) {
|
||||
// TODO: check surface and keyboard are from the same client
|
||||
|
||||
pub fn set_focus(&self, focus: Option<wl_surface::WlSurface>, serial: u32) {
|
||||
let mut guard = self.arc.internal.lock().unwrap();
|
||||
|
||||
// remove current focus
|
||||
let old_kbd = if let Some((old_surface, old_kbd)) = guard.focus.take() {
|
||||
if old_surface.status() != Liveness::Dead {
|
||||
old_kbd.leave(serial, &old_surface);
|
||||
}
|
||||
Some(old_kbd)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
// unset old focus
|
||||
guard.with_focused_kbds(|kbd, s| {
|
||||
kbd.leave(serial, s);
|
||||
});
|
||||
|
||||
// set new focus
|
||||
if let Some((surface, kbd)) = focus {
|
||||
if surface.status() != Liveness::Dead {
|
||||
// send new mods status if client instance changed
|
||||
match old_kbd {
|
||||
Some(ref okbd) if okbd.equals(&kbd) => {}
|
||||
_ => {
|
||||
guard.focus = focus;
|
||||
let (dep, la, lo, gr) = guard.serialize_modifiers();
|
||||
let keys = guard.serialize_pressed_keys();
|
||||
guard.with_focused_kbds(|kbd, s| {
|
||||
kbd.modifiers(serial, dep, la, lo, gr);
|
||||
}
|
||||
}
|
||||
// send enter event
|
||||
kbd.enter(serial, &surface, guard.serialize_pressed_keys());
|
||||
}
|
||||
guard.focus = Some((surface, kbd));
|
||||
kbd.enter(serial, s, keys.clone());
|
||||
});
|
||||
if guard.focus.is_some() {
|
||||
trace!(self.arc.logger, "Focus set to new surface");
|
||||
} else {
|
||||
trace!(self.arc.logger, "Focus unset");
|
||||
}
|
||||
}
|
||||
|
||||
/// Send the keymap to this keyboard
|
||||
/// Register a new keyboard to this handler
|
||||
///
|
||||
/// The keymap will automatically be sent to it
|
||||
///
|
||||
/// This should be done first, before anything else is done with this keyboard.
|
||||
pub fn send_keymap(&self, kbd: &wl_keyboard::WlKeyboard) {
|
||||
pub fn new_kbd(&self, kbd: wl_keyboard::WlKeyboard) {
|
||||
trace!(self.arc.logger, "Sending keymap to client");
|
||||
kbd.keymap(
|
||||
wl_keyboard::KeymapFormat::XkbV1,
|
||||
self.arc.keymap_file.as_raw_fd(),
|
||||
self.arc.keymap_len,
|
||||
);
|
||||
let mut guard = self.arc.internal.lock().unwrap();
|
||||
guard.known_kbds.push(kbd);
|
||||
}
|
||||
|
||||
/// Performs an internal cleanup of known kbds
|
||||
///
|
||||
/// Drops any wl_keyboard that is no longer alive
|
||||
pub fn cleanup_old_kbds(&self) {
|
||||
let mut guard = self.arc.internal.lock().unwrap();
|
||||
guard.known_kbds.retain(|kbd| kbd.status() != Liveness::Dead);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue