seat: implementation
This commit is contained in:
parent
bb7d389be6
commit
e1ade4e2e9
|
@ -113,7 +113,13 @@ impl KbdInternal {
|
||||||
};
|
};
|
||||||
|
|
||||||
// update state
|
// update state
|
||||||
let state_components = self.state.update_key(keycode, direction);
|
// Offset the keycode by 8, as the evdev XKB rules reflect X's
|
||||||
|
// broken keycode system, which starts at 8.
|
||||||
|
let state_components = self.state.update_key(keycode + 8, direction);
|
||||||
|
|
||||||
|
println!("KEYCODE: {}", keycode);
|
||||||
|
println!("MODS: {:b}", state_components);
|
||||||
|
|
||||||
if state_components != 0 {
|
if state_components != 0 {
|
||||||
self.mods_state.update_with(&self.state);
|
self.mods_state.update_with(&self.state);
|
||||||
true
|
true
|
||||||
|
@ -156,6 +162,7 @@ impl KbdInternal {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Errors that can be encountered when creating a keyboard handler
|
/// Errors that can be encountered when creating a keyboard handler
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// libxkbcommon could not load the specified keymap
|
/// libxkbcommon could not load the specified keymap
|
||||||
BadKeymap,
|
BadKeymap,
|
||||||
|
@ -164,14 +171,12 @@ pub enum Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a keyboard handler from a set of RMLVO rules
|
/// Create a keyboard handler from a set of RMLVO rules
|
||||||
pub fn create_keyboard_handler<L>(rules: &str, model: &str, layout: &str, variant: &str,
|
pub(crate) fn create_keyboard_handler(rules: &str, model: &str, layout: &str, variant: &str,
|
||||||
options: Option<String>, repeat_delay: i32, repeat_rate: i32, logger: L)
|
options: Option<String>, repeat_delay: i32, repeat_rate: i32,
|
||||||
-> Result<KbdHandle, Error>
|
logger: ::slog::Logger)
|
||||||
where
|
-> Result<KbdHandle, Error> {
|
||||||
L: Into<Option<::slog::Logger>>,
|
let log = logger.new(o!("smithay_module" => "xkbcommon_handler"));
|
||||||
{
|
info!(log, "Initializing a xkbcommon handler with keymap query";
|
||||||
let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "xkbcommon_handler"));
|
|
||||||
info!(log, "Initializing a xkbcommon handler with keymap";
|
|
||||||
"rules" => rules, "model" => model, "layout" => layout, "variant" => variant,
|
"rules" => rules, "model" => model, "layout" => layout, "variant" => variant,
|
||||||
"options" => &options
|
"options" => &options
|
||||||
);
|
);
|
||||||
|
@ -188,6 +193,8 @@ where
|
||||||
Error::BadKeymap
|
Error::BadKeymap
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next());
|
||||||
|
|
||||||
|
|
||||||
// prepare a tempfile with the keymap, to send it to clients
|
// prepare a tempfile with the keymap, to send it to clients
|
||||||
let mut keymap_file = tempfile().map_err(Error::IoError)?;
|
let mut keymap_file = tempfile().map_err(Error::IoError)?;
|
||||||
|
@ -255,10 +262,11 @@ impl KbdHandle {
|
||||||
{
|
{
|
||||||
trace!(self.arc.logger, "Handling keystroke"; "keycode" => keycode, "state" => format_args!("{:?}", state));
|
trace!(self.arc.logger, "Handling keystroke"; "keycode" => keycode, "state" => format_args!("{:?}", state));
|
||||||
let mut guard = self.arc.internal.lock().unwrap();
|
let mut guard = self.arc.internal.lock().unwrap();
|
||||||
let mods_changed = guard.key_input(keycode, state);
|
|
||||||
|
|
||||||
let sym = guard.state.key_get_one_sym(keycode);
|
let sym = guard.state.key_get_one_sym(keycode);
|
||||||
|
|
||||||
|
let mods_changed = guard.key_input(keycode, state);
|
||||||
|
|
||||||
trace!(self.arc.logger, "Calling input filter";
|
trace!(self.arc.logger, "Calling input filter";
|
||||||
"mods_state" => format_args!("{:?}", guard.mods_state), "sym" => xkb::keysym_get_name(sym)
|
"mods_state" => format_args!("{:?}", guard.mods_state), "sym" => xkb::keysym_get_name(sym)
|
||||||
);
|
);
|
||||||
|
@ -294,18 +302,26 @@ impl KbdHandle {
|
||||||
|
|
||||||
/// Set the current focus of this keyboard
|
/// Set the current focus of this keyboard
|
||||||
///
|
///
|
||||||
/// Any previous focus will be sent a `wl_keyboard::leave` event, and if the new focus
|
/// If the ne focus is different from the previous one, any previous focus
|
||||||
/// is not `None`, a `wl_keyboard::enter` event will be sent.
|
/// will be sent a `wl_keyboard::leave` event, and if the new focus is not `None`,
|
||||||
pub fn set_focus(&self, focus: Option<wl_surface::WlSurface>, serial: u32) {
|
/// a `wl_keyboard::enter` event will be sent.
|
||||||
|
pub fn set_focus(&self, focus: Option<&wl_surface::WlSurface>, serial: u32) {
|
||||||
let mut guard = self.arc.internal.lock().unwrap();
|
let mut guard = self.arc.internal.lock().unwrap();
|
||||||
|
|
||||||
|
let same = guard
|
||||||
|
.focus
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|f| focus.map(|s| s.equals(f)))
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if !same {
|
||||||
// unset old focus
|
// unset old focus
|
||||||
guard.with_focused_kbds(|kbd, s| {
|
guard.with_focused_kbds(|kbd, s| {
|
||||||
kbd.leave(serial, s);
|
kbd.leave(serial, s);
|
||||||
});
|
});
|
||||||
|
|
||||||
// set new focus
|
// set new focus
|
||||||
guard.focus = focus;
|
guard.focus = focus.and_then(|s| s.clone());
|
||||||
let (dep, la, lo, gr) = guard.serialize_modifiers();
|
let (dep, la, lo, gr) = guard.serialize_modifiers();
|
||||||
let keys = guard.serialize_pressed_keys();
|
let keys = guard.serialize_pressed_keys();
|
||||||
guard.with_focused_kbds(|kbd, s| {
|
guard.with_focused_kbds(|kbd, s| {
|
||||||
|
@ -317,6 +333,9 @@ impl KbdHandle {
|
||||||
} else {
|
} else {
|
||||||
trace!(self.arc.logger, "Focus unset");
|
trace!(self.arc.logger, "Focus unset");
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
trace!(self.arc.logger, "Focus unchanged");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a new keyboard to this handler
|
/// Register a new keyboard to this handler
|
||||||
|
@ -324,7 +343,7 @@ impl KbdHandle {
|
||||||
/// The keymap will automatically be sent to it
|
/// The keymap will automatically be sent to it
|
||||||
///
|
///
|
||||||
/// This should be done first, before anything else is done with this keyboard.
|
/// This should be done first, before anything else is done with this keyboard.
|
||||||
pub fn new_kbd(&self, kbd: wl_keyboard::WlKeyboard) {
|
pub(crate) fn new_kbd(&self, kbd: wl_keyboard::WlKeyboard) {
|
||||||
trace!(self.arc.logger, "Sending keymap to client");
|
trace!(self.arc.logger, "Sending keymap to client");
|
||||||
kbd.keymap(
|
kbd.keymap(
|
||||||
wl_keyboard::KeymapFormat::XkbV1,
|
wl_keyboard::KeymapFormat::XkbV1,
|
||||||
|
@ -351,7 +370,7 @@ impl KbdHandle {
|
||||||
/// Performs an internal cleanup of known kbds
|
/// Performs an internal cleanup of known kbds
|
||||||
///
|
///
|
||||||
/// Drops any wl_keyboard that is no longer alive
|
/// Drops any wl_keyboard that is no longer alive
|
||||||
pub fn cleanup_old_kbds(&self) {
|
pub(crate) fn cleanup_old_kbds(&self) {
|
||||||
let mut guard = self.arc.internal.lock().unwrap();
|
let mut guard = self.arc.internal.lock().unwrap();
|
||||||
guard
|
guard
|
||||||
.known_kbds
|
.known_kbds
|
||||||
|
|
122
src/seat/mod.rs
122
src/seat/mod.rs
|
@ -1,3 +1,123 @@
|
||||||
mod keyboard;
|
mod keyboard;
|
||||||
|
mod pointer;
|
||||||
|
|
||||||
pub use self::keyboard::{create_keyboard_handler, Error as KbdError, KbdHandle};
|
pub use self::keyboard::{Error as KbdError, KbdHandle};
|
||||||
|
pub use self::pointer::PointerHandle;
|
||||||
|
use wayland_server::{Client, EventLoop, EventLoopHandle, Global, StateToken};
|
||||||
|
use wayland_server::protocol::{wl_keyboard, wl_pointer, wl_seat};
|
||||||
|
|
||||||
|
pub struct Seat {
|
||||||
|
log: ::slog::Logger,
|
||||||
|
name: String,
|
||||||
|
pointer: Option<PointerHandle>,
|
||||||
|
keyboard: Option<KbdHandle>,
|
||||||
|
known_seats: Vec<wl_seat::WlSeat>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Seat {
|
||||||
|
pub fn new<L>(evl: &mut EventLoop, name: String, logger: L)
|
||||||
|
-> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>)
|
||||||
|
where
|
||||||
|
L: Into<Option<::slog::Logger>>,
|
||||||
|
{
|
||||||
|
let log = ::slog_or_stdlog(logger);
|
||||||
|
let seat = Seat {
|
||||||
|
log: log.new(o!("smithay_module" => "seat_handler")),
|
||||||
|
name: name,
|
||||||
|
pointer: None,
|
||||||
|
keyboard: None,
|
||||||
|
known_seats: Vec::new(),
|
||||||
|
};
|
||||||
|
let token = evl.state().insert(seat);
|
||||||
|
// TODO: support version 5 (axis)
|
||||||
|
let global = evl.register_global(4, seat_global_bind, token.clone());
|
||||||
|
(token, global)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_pointer(&mut self) -> PointerHandle {
|
||||||
|
let pointer = self::pointer::create_pointer_handler();
|
||||||
|
self.pointer = Some(pointer.clone());
|
||||||
|
let caps = self.compute_caps();
|
||||||
|
for seat in &self.known_seats {
|
||||||
|
seat.capabilities(caps);
|
||||||
|
}
|
||||||
|
pointer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_keyboard(&mut self, model: &str, layout: &str, variant: &str, options: Option<String>,
|
||||||
|
repeat_delay: i32, repeat_rate: i32)
|
||||||
|
-> Result<KbdHandle, KbdError> {
|
||||||
|
let keyboard = self::keyboard::create_keyboard_handler(
|
||||||
|
"evdev", // we need this one
|
||||||
|
model,
|
||||||
|
layout,
|
||||||
|
variant,
|
||||||
|
options,
|
||||||
|
repeat_delay,
|
||||||
|
repeat_rate,
|
||||||
|
self.log.clone(),
|
||||||
|
)?;
|
||||||
|
self.keyboard = Some(keyboard.clone());
|
||||||
|
let caps = self.compute_caps();
|
||||||
|
for seat in &self.known_seats {
|
||||||
|
seat.capabilities(caps);
|
||||||
|
}
|
||||||
|
Ok(keyboard)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_caps(&self) -> wl_seat::Capability {
|
||||||
|
let mut caps = wl_seat::Capability::empty();
|
||||||
|
if self.pointer.is_some() {
|
||||||
|
caps |= wl_seat::Pointer;
|
||||||
|
}
|
||||||
|
if self.keyboard.is_some() {
|
||||||
|
caps |= wl_seat::Keyboard;
|
||||||
|
}
|
||||||
|
caps
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seat_global_bind(evlh: &mut EventLoopHandle, token: &mut StateToken<Seat>, _: &Client,
|
||||||
|
seat: wl_seat::WlSeat) {
|
||||||
|
evlh.register(&seat, seat_implementation(), token.clone(), None);
|
||||||
|
let mut seat_mgr = evlh.state().get_mut(token);
|
||||||
|
seat.name(seat_mgr.name.clone());
|
||||||
|
seat.capabilities(seat_mgr.compute_caps());
|
||||||
|
seat_mgr.known_seats.push(seat);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seat_implementation() -> wl_seat::Implementation<StateToken<Seat>> {
|
||||||
|
wl_seat::Implementation {
|
||||||
|
get_pointer: |evlh, token, _, seat, pointer| {
|
||||||
|
evlh.register(&pointer, pointer_implementation(), (), None);
|
||||||
|
if let Some(ref ptr_handle) = evlh.state().get(token).pointer {
|
||||||
|
ptr_handle.new_pointer(pointer);
|
||||||
|
}
|
||||||
|
// TODO: protocol error ?
|
||||||
|
},
|
||||||
|
get_keyboard: |evlh, token, _, seat, keyboard| {
|
||||||
|
evlh.register(&keyboard, keyboard_implementation(), (), None);
|
||||||
|
if let Some(ref kbd_handle) = evlh.state().get(token).keyboard {
|
||||||
|
kbd_handle.new_kbd(keyboard);
|
||||||
|
}
|
||||||
|
// TODO: protocol error ?
|
||||||
|
},
|
||||||
|
get_touch: |evlh, token, _, seat, touch| {
|
||||||
|
// TODO
|
||||||
|
},
|
||||||
|
release: |_, _, _, _| {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pointer_implementation() -> wl_pointer::Implementation<()> {
|
||||||
|
wl_pointer::Implementation {
|
||||||
|
set_cursor: |_, _, _, _, _, _, _, _| {},
|
||||||
|
release: |_, _, _, _| {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn keyboard_implementation() -> wl_keyboard::Implementation<()> {
|
||||||
|
wl_keyboard::Implementation {
|
||||||
|
release: |_, _, _, _| {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use wayland_server::{Liveness, Resource};
|
||||||
|
use wayland_server::protocol::{wl_pointer, wl_surface};
|
||||||
|
|
||||||
|
// TODO: handle pointer surface role
|
||||||
|
|
||||||
|
struct PointerInternal {
|
||||||
|
known_pointers: Vec<wl_pointer::WlPointer>,
|
||||||
|
focus: Option<wl_surface::WlSurface>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointerInternal {
|
||||||
|
fn new() -> PointerInternal {
|
||||||
|
PointerInternal {
|
||||||
|
known_pointers: Vec::new(),
|
||||||
|
focus: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_focused_pointers<F>(&self, mut f: F)
|
||||||
|
where
|
||||||
|
F: FnMut(&wl_pointer::WlPointer, &wl_surface::WlSurface),
|
||||||
|
{
|
||||||
|
if let Some(ref focus) = self.focus {
|
||||||
|
for ptr in &self.known_pointers {
|
||||||
|
if ptr.same_client_as(focus) {
|
||||||
|
f(ptr, focus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct PointerHandle {
|
||||||
|
inner: Arc<Mutex<PointerInternal>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PointerHandle {
|
||||||
|
pub(crate) fn new_pointer(&self, pointer: wl_pointer::WlPointer) {
|
||||||
|
let mut guard = self.inner.lock().unwrap();
|
||||||
|
guard.known_pointers.push(pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn motion(&self, location: Option<(&wl_surface::WlSurface, f64, f64)>, serial: u32, time: u32) {
|
||||||
|
let mut guard = self.inner.lock().unwrap();
|
||||||
|
// do we leave a surface ?
|
||||||
|
let mut leave = true;
|
||||||
|
if let Some(ref focus) = guard.focus {
|
||||||
|
if let Some((ref surface, _, _)) = location {
|
||||||
|
if focus.equals(surface) {
|
||||||
|
leave = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if leave {
|
||||||
|
guard.with_focused_pointers(|pointer, surface| {
|
||||||
|
pointer.leave(serial, surface);
|
||||||
|
});
|
||||||
|
guard.focus = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do we enter one ?
|
||||||
|
if let Some((surface, x, y)) = location {
|
||||||
|
if guard.focus.is_none() {
|
||||||
|
guard.focus = surface.clone();
|
||||||
|
guard.with_focused_pointers(|pointer, surface| {
|
||||||
|
pointer.enter(serial, surface, x, y);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// we were on top of a surface and remained on it
|
||||||
|
guard.with_focused_pointers(|pointer, surface| {
|
||||||
|
pointer.motion(time, x, y);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn button(&self, button: u32, state: wl_pointer::ButtonState, serial: u32, time: u32) {
|
||||||
|
let mut guard = self.inner.lock().unwrap();
|
||||||
|
guard.with_focused_pointers(|pointer, _| {
|
||||||
|
pointer.button(serial, time, button, state);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle axis
|
||||||
|
|
||||||
|
pub(crate) fn cleanup_old_pointers(&self) {
|
||||||
|
let mut guard = self.inner.lock().unwrap();
|
||||||
|
guard
|
||||||
|
.known_pointers
|
||||||
|
.retain(|p| p.status() != Liveness::Dead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn create_pointer_handler() -> PointerHandle {
|
||||||
|
PointerHandle {
|
||||||
|
inner: Arc::new(Mutex::new(PointerInternal::new())),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue