seat: implementation
This commit is contained in:
parent
bb7d389be6
commit
e1ade4e2e9
|
@ -113,7 +113,13 @@ impl KbdInternal {
|
|||
};
|
||||
|
||||
// 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 {
|
||||
self.mods_state.update_with(&self.state);
|
||||
true
|
||||
|
@ -156,6 +162,7 @@ impl KbdInternal {
|
|||
}
|
||||
|
||||
/// Errors that can be encountered when creating a keyboard handler
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// libxkbcommon could not load the specified keymap
|
||||
BadKeymap,
|
||||
|
@ -164,14 +171,12 @@ pub enum Error {
|
|||
}
|
||||
|
||||
/// Create a keyboard handler from a set of RMLVO rules
|
||||
pub fn create_keyboard_handler<L>(rules: &str, model: &str, layout: &str, variant: &str,
|
||||
options: Option<String>, repeat_delay: i32, repeat_rate: i32, logger: L)
|
||||
-> Result<KbdHandle, Error>
|
||||
where
|
||||
L: Into<Option<::slog::Logger>>,
|
||||
{
|
||||
let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "xkbcommon_handler"));
|
||||
info!(log, "Initializing a xkbcommon handler with keymap";
|
||||
pub(crate) fn create_keyboard_handler(rules: &str, model: &str, layout: &str, variant: &str,
|
||||
options: Option<String>, repeat_delay: i32, repeat_rate: i32,
|
||||
logger: ::slog::Logger)
|
||||
-> Result<KbdHandle, Error> {
|
||||
let log = logger.new(o!("smithay_module" => "xkbcommon_handler"));
|
||||
info!(log, "Initializing a xkbcommon handler with keymap query";
|
||||
"rules" => rules, "model" => model, "layout" => layout, "variant" => variant,
|
||||
"options" => &options
|
||||
);
|
||||
|
@ -188,6 +193,8 @@ where
|
|||
Error::BadKeymap
|
||||
})?;
|
||||
|
||||
info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next());
|
||||
|
||||
|
||||
// prepare a tempfile with the keymap, to send it to clients
|
||||
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));
|
||||
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 mods_changed = guard.key_input(keycode, state);
|
||||
|
||||
trace!(self.arc.logger, "Calling input filter";
|
||||
"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
|
||||
///
|
||||
/// 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>, serial: u32) {
|
||||
/// If the ne focus is different from the previous one, 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>, serial: u32) {
|
||||
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
|
||||
guard.with_focused_kbds(|kbd, s| {
|
||||
kbd.leave(serial, s);
|
||||
});
|
||||
|
||||
// set new focus
|
||||
guard.focus = focus;
|
||||
guard.focus = focus.and_then(|s| s.clone());
|
||||
let (dep, la, lo, gr) = guard.serialize_modifiers();
|
||||
let keys = guard.serialize_pressed_keys();
|
||||
guard.with_focused_kbds(|kbd, s| {
|
||||
|
@ -317,6 +333,9 @@ impl KbdHandle {
|
|||
} else {
|
||||
trace!(self.arc.logger, "Focus unset");
|
||||
}
|
||||
} else {
|
||||
trace!(self.arc.logger, "Focus unchanged");
|
||||
}
|
||||
}
|
||||
|
||||
/// Register a new keyboard to this handler
|
||||
|
@ -324,7 +343,7 @@ impl KbdHandle {
|
|||
/// The keymap will automatically be sent to it
|
||||
///
|
||||
/// 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");
|
||||
kbd.keymap(
|
||||
wl_keyboard::KeymapFormat::XkbV1,
|
||||
|
@ -351,7 +370,7 @@ impl KbdHandle {
|
|||
/// Performs an internal cleanup of known kbds
|
||||
///
|
||||
/// 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();
|
||||
guard
|
||||
.known_kbds
|
||||
|
|
122
src/seat/mod.rs
122
src/seat/mod.rs
|
@ -1,3 +1,123 @@
|
|||
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