seat: implementation

This commit is contained in:
Victor Berger 2017-09-22 14:54:18 +02:00
parent bb7d389be6
commit e1ade4e2e9
3 changed files with 270 additions and 31 deletions

View File

@ -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,28 +302,39 @@ 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();
// unset old focus
guard.with_focused_kbds(|kbd, s| {
kbd.leave(serial, s);
});
let same = guard
.focus
.as_ref()
.and_then(|f| focus.map(|s| s.equals(f)))
.unwrap_or(false);
// set new focus
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);
kbd.enter(serial, s, keys.clone());
});
if guard.focus.is_some() {
trace!(self.arc.logger, "Focus set to new surface");
if !same {
// unset old focus
guard.with_focused_kbds(|kbd, s| {
kbd.leave(serial, s);
});
// set new 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| {
kbd.modifiers(serial, dep, la, lo, gr);
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");
}
} else {
trace!(self.arc.logger, "Focus unset");
trace!(self.arc.logger, "Focus unchanged");
}
}
@ -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

View File

@ -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: |_, _, _, _| {},
}
}

100
src/seat/pointer.rs Normal file
View File

@ -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())),
}
}