wayland.seat: migrate to wayland_rs-0.20

This commit is contained in:
Victor Berger 2018-04-15 11:44:56 +02:00
parent 93050e2683
commit e44b0e596e
7 changed files with 376 additions and 269 deletions

View File

@ -2,7 +2,6 @@
use std::error::Error;
use std::string::ToString;
use wayland_server::EventLoopHandle;
/// A seat describes a group of input devices and at least one
/// graphics device belonging together.
@ -521,31 +520,31 @@ pub trait InputBackend: Sized {
type TouchFrameEvent: TouchFrameEvent;
/// Sets a new handler for this `InputBackend`
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, evlh: &mut EventLoopHandle, handler: H);
fn set_handler<H: InputHandler<Self> + 'static>(&mut self, handler: H);
/// Get a reference to the currently set handler, if any
fn get_handler(&mut self) -> Option<&mut InputHandler<Self>>;
/// Clears the currently handler, if one is set
fn clear_handler(&mut self, evlh: &mut EventLoopHandle);
fn clear_handler(&mut self);
/// Get current `InputConfig`
fn input_config(&mut self) -> &mut Self::InputConfig;
/// Processes new events of the underlying backend and drives the `InputHandler`.
fn dispatch_new_events(&mut self, evlh: &mut EventLoopHandle) -> Result<(), Self::EventError>;
fn dispatch_new_events(&mut self) -> Result<(), Self::EventError>;
}
/// Implement to receive input events from any `InputBackend`.
pub trait InputHandler<B: InputBackend> {
/// Called when a new `Seat` has been created
fn on_seat_created(&mut self, evlh: &mut EventLoopHandle, seat: &Seat);
fn on_seat_created(&mut self, seat: &Seat);
/// Called when an existing `Seat` has been destroyed.
fn on_seat_destroyed(&mut self, evlh: &mut EventLoopHandle, seat: &Seat);
fn on_seat_destroyed(&mut self, seat: &Seat);
/// Called when a `Seat`'s properties have changed.
///
/// ## Note:
///
/// It is not guaranteed that any change has actually happened.
fn on_seat_changed(&mut self, evlh: &mut EventLoopHandle, seat: &Seat);
fn on_seat_changed(&mut self, seat: &Seat);
/// Called when a new keyboard event was received.
///
@ -554,7 +553,7 @@ pub trait InputHandler<B: InputBackend> {
/// - `seat` - The `Seat` the event belongs to
/// - `event` - The keyboard event
///
fn on_keyboard_key(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::KeyboardKeyEvent);
fn on_keyboard_key(&mut self, seat: &Seat, event: B::KeyboardKeyEvent);
/// Called when a new pointer movement event was received.
///
@ -562,30 +561,28 @@ pub trait InputHandler<B: InputBackend> {
///
/// - `seat` - The `Seat` the event belongs to
/// - `event` - The pointer movement event
fn on_pointer_move(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::PointerMotionEvent);
fn on_pointer_move(&mut self, seat: &Seat, event: B::PointerMotionEvent);
/// Called when a new pointer absolute movement event was received.
///
/// # Arguments
///
/// - `seat` - The `Seat` the event belongs to
/// - `event` - The pointer absolute movement event
fn on_pointer_move_absolute(
&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::PointerMotionAbsoluteEvent
);
fn on_pointer_move_absolute(&mut self, seat: &Seat, event: B::PointerMotionAbsoluteEvent);
/// Called when a new pointer button event was received.
///
/// # Arguments
///
/// - `seat` - The `Seat` the event belongs to
/// - `event` - The pointer button event
fn on_pointer_button(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::PointerButtonEvent);
fn on_pointer_button(&mut self, seat: &Seat, event: B::PointerButtonEvent);
/// Called when a new pointer scroll event was received.
///
/// # Arguments
///
/// - `seat` - The `Seat` the event belongs to
/// - `event` - A upward counting variable useful for event ordering. Makes no gurantees about actual time passed between events.
fn on_pointer_axis(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::PointerAxisEvent);
fn on_pointer_axis(&mut self, seat: &Seat, event: B::PointerAxisEvent);
/// Called when a new touch down event was received.
///
@ -593,99 +590,97 @@ pub trait InputHandler<B: InputBackend> {
///
/// - `seat` - The `Seat` the event belongs to
/// - `event` - The touch down event
fn on_touch_down(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::TouchDownEvent);
fn on_touch_down(&mut self, seat: &Seat, event: B::TouchDownEvent);
/// Called when a new touch motion event was received.
///
/// # Arguments
///
/// - `seat` - The `Seat` the event belongs to
/// - `event` - The touch motion event.
fn on_touch_motion(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::TouchMotionEvent);
fn on_touch_motion(&mut self, seat: &Seat, event: B::TouchMotionEvent);
/// Called when a new touch up event was received.
///
/// # Arguments
///
/// - `seat` - The `Seat` the event belongs to
/// - `event` - The touch up event.
fn on_touch_up(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::TouchUpEvent);
fn on_touch_up(&mut self, seat: &Seat, event: B::TouchUpEvent);
/// Called when a new touch cancel event was received.
///
/// # Arguments
///
/// - `seat` - The `Seat` the event belongs to
/// - `event` - The touch cancel event.
fn on_touch_cancel(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::TouchCancelEvent);
fn on_touch_cancel(&mut self, seat: &Seat, event: B::TouchCancelEvent);
/// Called when a new touch frame event was received.
///
/// # Arguments
///
/// - `seat` - The `Seat` the event belongs to
/// - `event` - The touch frame event.
fn on_touch_frame(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::TouchFrameEvent);
fn on_touch_frame(&mut self, seat: &Seat, event: B::TouchFrameEvent);
/// Called when the `InputConfig` was changed through an external event.
///
/// What kind of events can trigger this call is completely backend dependent.
/// E.g. an input devices was attached/detached or changed it's own configuration.
fn on_input_config_changed(&mut self, evlh: &mut EventLoopHandle, config: &mut B::InputConfig);
fn on_input_config_changed(&mut self, config: &mut B::InputConfig);
}
impl<B: InputBackend> InputHandler<B> for Box<InputHandler<B>> {
fn on_seat_created(&mut self, evlh: &mut EventLoopHandle, seat: &Seat) {
(**self).on_seat_created(evlh, seat)
fn on_seat_created(&mut self, seat: &Seat) {
(**self).on_seat_created(seat)
}
fn on_seat_destroyed(&mut self, evlh: &mut EventLoopHandle, seat: &Seat) {
(**self).on_seat_destroyed(evlh, seat)
fn on_seat_destroyed(&mut self, seat: &Seat) {
(**self).on_seat_destroyed(seat)
}
fn on_seat_changed(&mut self, evlh: &mut EventLoopHandle, seat: &Seat) {
(**self).on_seat_changed(evlh, seat)
fn on_seat_changed(&mut self, seat: &Seat) {
(**self).on_seat_changed(seat)
}
fn on_keyboard_key(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::KeyboardKeyEvent) {
(**self).on_keyboard_key(evlh, seat, event)
fn on_keyboard_key(&mut self, seat: &Seat, event: B::KeyboardKeyEvent) {
(**self).on_keyboard_key(seat, event)
}
fn on_pointer_move(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::PointerMotionEvent) {
(**self).on_pointer_move(evlh, seat, event)
fn on_pointer_move(&mut self, seat: &Seat, event: B::PointerMotionEvent) {
(**self).on_pointer_move(seat, event)
}
fn on_pointer_move_absolute(
&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::PointerMotionAbsoluteEvent
) {
(**self).on_pointer_move_absolute(evlh, seat, event)
fn on_pointer_move_absolute(&mut self, seat: &Seat, event: B::PointerMotionAbsoluteEvent) {
(**self).on_pointer_move_absolute(seat, event)
}
fn on_pointer_button(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::PointerButtonEvent) {
(**self).on_pointer_button(evlh, seat, event)
fn on_pointer_button(&mut self, seat: &Seat, event: B::PointerButtonEvent) {
(**self).on_pointer_button(seat, event)
}
fn on_pointer_axis(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::PointerAxisEvent) {
(**self).on_pointer_axis(evlh, seat, event)
fn on_pointer_axis(&mut self, seat: &Seat, event: B::PointerAxisEvent) {
(**self).on_pointer_axis(seat, event)
}
fn on_touch_down(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::TouchDownEvent) {
(**self).on_touch_down(evlh, seat, event)
fn on_touch_down(&mut self, seat: &Seat, event: B::TouchDownEvent) {
(**self).on_touch_down(seat, event)
}
fn on_touch_motion(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::TouchMotionEvent) {
(**self).on_touch_motion(evlh, seat, event)
fn on_touch_motion(&mut self, seat: &Seat, event: B::TouchMotionEvent) {
(**self).on_touch_motion(seat, event)
}
fn on_touch_up(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::TouchUpEvent) {
(**self).on_touch_up(evlh, seat, event)
fn on_touch_up(&mut self, seat: &Seat, event: B::TouchUpEvent) {
(**self).on_touch_up(seat, event)
}
fn on_touch_cancel(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::TouchCancelEvent) {
(**self).on_touch_cancel(evlh, seat, event)
fn on_touch_cancel(&mut self, seat: &Seat, event: B::TouchCancelEvent) {
(**self).on_touch_cancel(seat, event)
}
fn on_touch_frame(&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::TouchFrameEvent) {
(**self).on_touch_frame(evlh, seat, event)
fn on_touch_frame(&mut self, seat: &Seat, event: B::TouchFrameEvent) {
(**self).on_touch_frame(seat, event)
}
fn on_input_config_changed(&mut self, evlh: &mut EventLoopHandle, config: &mut B::InputConfig) {
(**self).on_input_config_changed(evlh, config)
fn on_input_config_changed(&mut self, config: &mut B::InputConfig) {
(**self).on_input_config_changed(config)
}
}

View File

@ -15,15 +15,15 @@
//! - libinput
pub mod input;
pub mod graphics;
//pub mod graphics;
#[cfg(feature = "backend_winit")]
pub mod winit;
#[cfg(feature = "backend_drm")]
pub mod drm;
#[cfg(feature = "backend_libinput")]
pub mod libinput;
#[cfg(feature = "backend_session")]
pub mod session;
#[cfg(feature = "backend_udev")]
pub mod udev;
//#[cfg(feature = "backend_winit")]
//pub mod winit;
//#[cfg(feature = "backend_drm")]
//pub mod drm;
//#[cfg(feature = "backend_libinput")]
//pub mod libinput;
//#[cfg(feature = "backend_session")]
//pub mod session;
//#[cfg(feature = "backend_udev")]
//pub mod udev;

View File

@ -48,7 +48,7 @@ extern crate error_chain;
#[macro_use]
extern crate lazy_static;
//pub mod backend;
pub mod backend;
pub mod wayland;
pub mod utils;

View File

@ -20,6 +20,6 @@
//pub mod compositor;
pub mod output;
//pub mod seat;
pub mod seat;
pub mod shm;
//pub mod shell;

View File

@ -3,8 +3,9 @@ use std::io::{Error as IoError, Write};
use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex};
use tempfile::tempfile;
use wayland_server::{Liveness, Resource};
use wayland_server::protocol::{wl_keyboard, wl_surface};
use wayland_server::{NewResource, Resource};
use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::protocol::wl_keyboard::{Event, KeyState as WlKeyState, KeymapFormat, Request, WlKeyboard};
use xkbcommon::xkb;
pub use xkbcommon::xkb::{keysyms, Keysym};
@ -55,8 +56,8 @@ impl ModifiersState {
}
struct KbdInternal {
known_kbds: Vec<wl_keyboard::WlKeyboard>,
focus: Option<wl_surface::WlSurface>,
known_kbds: Vec<Resource<WlKeyboard>>,
focus: Option<Resource<WlSurface>>,
pressed_keys: Vec<u32>,
mods_state: ModifiersState,
keymap: xkb::Keymap,
@ -65,9 +66,18 @@ struct KbdInternal {
repeat_delay: i32,
}
// This is OK because all parts of `xkb` will remain on the
// same thread
unsafe impl Send for KbdInternal {}
impl KbdInternal {
fn new(
rules: &str, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_rate: i32,
rules: &str,
model: &str,
layout: &str,
variant: &str,
options: Option<String>,
repeat_rate: i32,
repeat_delay: i32,
) -> Result<KbdInternal, ()> {
// we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe
@ -147,7 +157,7 @@ impl KbdInternal {
fn with_focused_kbds<F>(&self, mut f: F)
where
F: FnMut(&wl_keyboard::WlKeyboard, &wl_surface::WlSurface),
F: FnMut(&Resource<WlKeyboard>, &Resource<WlSurface>),
{
if let Some(ref surface) = self.focus {
for kbd in &self.known_kbds {
@ -170,8 +180,14 @@ pub enum Error {
/// Create a keyboard handler from a set of RMLVO rules
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,
rules: &str,
model: &str,
layout: &str,
variant: &str,
options: Option<String>,
repeat_delay: i32,
repeat_rate: i32,
logger: &::slog::Logger,
) -> Result<KeyboardHandle, Error> {
let log = logger.new(o!("smithay_module" => "xkbcommon_handler"));
info!(log, "Initializing a xkbcommon handler with keymap query";
@ -252,7 +268,7 @@ impl KeyboardHandle {
///
/// The module `smithay::keyboard::keysyms` exposes definitions of all possible keysyms
/// to be compared against. This includes non-characted keysyms, such as XF86 special keys.
pub fn input<F>(&self, keycode: u32, state: KeyState, serial: u32, filter: F)
pub fn input<F>(&self, keycode: u32, state: KeyState, serial: u32, time: u32, filter: F)
where
F: FnOnce(&ModifiersState, Keysym) -> bool,
{
@ -282,14 +298,25 @@ impl KeyboardHandle {
None
};
let wl_state = match state {
KeyState::Pressed => wl_keyboard::KeyState::Pressed,
KeyState::Released => wl_keyboard::KeyState::Released,
KeyState::Pressed => WlKeyState::Pressed,
KeyState::Released => WlKeyState::Released,
};
guard.with_focused_kbds(|kbd, _| {
if let Some((dep, la, lo, gr)) = modifiers {
kbd.modifiers(serial, dep, la, lo, gr);
kbd.send(Event::Modifiers {
serial,
mods_depressed: dep,
mods_latched: la,
mods_locked: lo,
group: gr,
});
}
kbd.key(serial, 0, keycode, wl_state);
kbd.send(Event::Key {
serial,
time,
key: keycode,
state: wl_state,
});
});
if guard.focus.is_some() {
trace!(self.arc.logger, "Input forwarded to client");
@ -303,7 +330,7 @@ impl KeyboardHandle {
/// 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) {
pub fn set_focus(&self, focus: Option<&Resource<WlSurface>>, serial: u32) {
let mut guard = self.arc.internal.lock().unwrap();
let same = guard
@ -315,16 +342,29 @@ impl KeyboardHandle {
if !same {
// unset old focus
guard.with_focused_kbds(|kbd, s| {
kbd.leave(serial, s);
kbd.send(Event::Leave {
serial,
surface: s.clone(),
});
});
// set new focus
guard.focus = focus.and_then(|s| s.clone());
guard.focus = focus.map(|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());
guard.with_focused_kbds(|kbd, surface| {
kbd.send(Event::Modifiers {
serial,
mods_depressed: dep,
mods_latched: la,
mods_locked: lo,
group: gr,
});
kbd.send(Event::Enter {
serial,
surface: surface.clone(),
keys: keys.clone(),
});
});
if guard.focus.is_some() {
trace!(self.arc.logger, "Focus set to new surface");
@ -341,16 +381,19 @@ impl KeyboardHandle {
/// The keymap will automatically be sent to it
///
/// This should be done first, before anything else is done with this keyboard.
pub(crate) fn new_kbd(&self, kbd: wl_keyboard::WlKeyboard) {
pub(crate) fn new_kbd(&self, kbd: Resource<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,
);
kbd.send(Event::Keymap {
format: KeymapFormat::XkbV1,
fd: self.arc.keymap_file.as_raw_fd(),
size: self.arc.keymap_len,
});
let mut guard = self.arc.internal.lock().unwrap();
if kbd.version() >= 4 {
kbd.repeat_info(guard.repeat_rate, guard.repeat_delay);
kbd.send(Event::RepeatInfo {
rate: guard.repeat_rate,
delay: guard.repeat_delay,
});
}
guard.known_kbds.push(kbd);
}
@ -361,17 +404,36 @@ impl KeyboardHandle {
guard.repeat_delay = delay;
guard.repeat_rate = rate;
for kbd in &guard.known_kbds {
kbd.repeat_info(rate, delay);
kbd.send(Event::RepeatInfo { rate, delay });
}
}
/// Performs an internal cleanup of known kbds
///
/// Drops any wl_keyboard that is no longer alive
pub(crate) fn cleanup_old_kbds(&self) {
let mut guard = self.arc.internal.lock().unwrap();
guard
.known_kbds
.retain(|kbd| kbd.status() != Liveness::Dead);
}
}
pub(crate) fn implement_keyboard(
new_keyboard: NewResource<WlKeyboard>,
handle: Option<&KeyboardHandle>,
) -> Resource<WlKeyboard> {
let destructor = match handle {
Some(h) => {
let arc = h.arc.clone();
Some(move |keyboard: Resource<_>, _| {
arc.internal
.lock()
.unwrap()
.known_kbds
.retain(|k| !k.equals(&keyboard))
})
}
None => None,
};
new_keyboard.implement(
|request, _keyboard| {
match request {
Request::Release => {
// Our destructors already handle it
}
}
},
destructor,
)
}

View File

@ -10,14 +10,14 @@
//! ```
//! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay;
//!
//! use smithay::wayland::seat::Seat;
//!
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! # let (mut display, event_loop) = wayland_server::Display::new();
//! // insert the seat:
//! let (seat_state_token, seat_global) = Seat::new(
//! &mut event_loop,
//! let (seat, seat_global) = Seat::new(
//! &mut display, // the display
//! event_loop.token(), // a LoopToken
//! "seat-0".into(), // the name of the seat, will be advertize to clients
//! None /* insert a logger here*/
//! );
@ -31,8 +31,7 @@
//! Currently, only pointer and keyboard capabilities are supported by
//! smithay.
//!
//! You can add these capabilities via methods of the `Seat` struct that was
//! inserted in the event loop, that you can retreive via its token:
//! You can add these capabilities via methods of the `Seat` struct:
//!
//! ```
//! # extern crate wayland_server;
@ -41,28 +40,59 @@
//! # use smithay::wayland::seat::Seat;
//! #
//! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display();
//! # let (seat_state_token, seat_global) = Seat::new(
//! # &mut event_loop,
//! # let (mut display, event_loop) = wayland_server::Display::new();
//! # let (mut seat, seat_global) = Seat::new(
//! # &mut display,
//! # event_loop.token(),
//! # "seat-0".into(), // the name of the seat, will be advertize to clients
//! # None /* insert a logger here*/
//! # );
//! let pointer_handle = event_loop.state().get_mut(&seat_state_token).add_pointer();
//! let pointer_handle = seat.add_pointer();
//! # }
//! ```
//!
//! These handles can be cloned and sent accross thread, so you can keep one around
//! in your event-handling code to forward inputs to your clients.
use std::sync::{Arc, Mutex};
mod keyboard;
mod pointer;
pub use self::keyboard::{Error as KeyboardError, KeyboardHandle, ModifiersState};
pub use self::pointer::{PointerAxisHandle, PointerHandle};
use wayland_server::{Client, EventLoopHandle, Global, Liveness, Resource, StateToken};
use wayland_server::protocol::{wl_keyboard, wl_pointer, wl_seat};
use wayland_server::{Display, Global, LoopToken, NewResource, Resource};
use wayland_server::protocol::wl_seat;
/// Internal data of a seat global
struct Inner {
log: ::slog::Logger,
name: String,
pointer: Option<PointerHandle>,
keyboard: Option<KeyboardHandle>,
known_seats: Vec<Resource<wl_seat::WlSeat>>,
}
impl Inner {
fn compute_caps(&self) -> wl_seat::Capability {
let mut caps = wl_seat::Capability::empty();
if self.pointer.is_some() {
caps |= wl_seat::Capability::Pointer;
}
if self.keyboard.is_some() {
caps |= wl_seat::Capability::Keyboard;
}
caps
}
fn send_all_caps(&self) {
let capabilities = self.compute_caps();
for seat in &self.known_seats {
seat.send(wl_seat::Event::Capabilities { capabilities });
}
}
}
/// A Seat handle
///
/// This struct gives you access to the control of the
/// capabilities of the associated seat.
@ -71,11 +101,7 @@ use wayland_server::protocol::{wl_keyboard, wl_pointer, wl_seat};
///
/// See module-level documentation for details of use.
pub struct Seat {
log: ::slog::Logger,
name: String,
pointer: Option<PointerHandle>,
keyboard: Option<KeyboardHandle>,
known_seats: Vec<wl_seat::WlSeat>,
inner: Arc<Mutex<Inner>>,
}
impl Seat {
@ -88,22 +114,39 @@ impl Seat {
/// you to add or remove capabilities from it), and the global handle,
/// in case you want to remove it.
pub fn new<L>(
evlh: &mut EventLoopHandle, name: String, logger: L
) -> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>)
display: &mut Display,
token: LoopToken,
name: String,
logger: L,
) -> (Seat, Global<wl_seat::WlSeat>)
where
L: Into<Option<::slog::Logger>>,
{
let log = ::slog_or_stdlog(logger);
let seat = Seat {
let inner = Arc::new(Mutex::new(Inner {
log: log.new(o!("smithay_module" => "seat_handler", "seat_name" => name.clone())),
name: name,
pointer: None,
keyboard: None,
known_seats: Vec::new(),
}));
let seat = Seat {
inner: inner.clone(),
};
let token = evlh.state().insert(seat);
let global = evlh.register_global(5, seat_global_bind, token.clone());
(token, global)
let global = display.create_global(&token, 5, move |_version, new_seat| {
let seat = implement_seat(new_seat, inner.clone());
let mut inner = inner.lock().unwrap();
if seat.version() >= 2 {
seat.send(wl_seat::Event::Name {
name: inner.name.clone(),
});
}
seat.send(wl_seat::Event::Capabilities {
capabilities: inner.compute_caps(),
});
inner.known_seats.push(seat);
});
(seat, global)
}
/// Adds the pointer capability to this seat
@ -115,21 +158,16 @@ impl Seat {
/// will overwrite it, and will be seen by the clients as if the
/// mouse was unplugged and a new one was plugged.
pub fn add_pointer(&mut self) -> PointerHandle {
let mut inner = self.inner.lock().unwrap();
let pointer = self::pointer::create_pointer_handler();
if self.pointer.is_some() {
if inner.pointer.is_some() {
// there is already a pointer, remove it and notify the clients
// of the change
self.pointer = None;
let caps = self.compute_caps();
for seat in &self.known_seats {
seat.capabilities(caps);
}
}
self.pointer = Some(pointer.clone());
let caps = self.compute_caps();
for seat in &self.known_seats {
seat.capabilities(caps);
inner.pointer = None;
inner.send_all_caps();
}
inner.pointer = Some(pointer.clone());
inner.send_all_caps();
pointer
}
@ -137,12 +175,10 @@ impl Seat {
///
/// Clients will be appropriately notified.
pub fn remove_pointer(&mut self) {
if self.pointer.is_some() {
self.pointer = None;
let caps = self.compute_caps();
for seat in &self.known_seats {
seat.capabilities(caps);
}
let mut inner = self.inner.lock().unwrap();
if inner.pointer.is_some() {
inner.pointer = None;
inner.send_all_caps();
}
}
@ -159,9 +195,15 @@ impl Seat {
/// will overwrite it, and will be seen by the clients as if the
/// keyboard was unplugged and a new one was plugged.
pub fn add_keyboard(
&mut self, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_delay: i32,
&mut self,
model: &str,
layout: &str,
variant: &str,
options: Option<String>,
repeat_delay: i32,
repeat_rate: i32,
) -> Result<KeyboardHandle, KeyboardError> {
let mut inner = self.inner.lock().unwrap();
let keyboard = self::keyboard::create_keyboard_handler(
"evdev", // we need this one
model,
@ -170,22 +212,16 @@ impl Seat {
options,
repeat_delay,
repeat_rate,
&self.log,
&inner.log,
)?;
if self.keyboard.is_some() {
if inner.keyboard.is_some() {
// there is already a keyboard, remove it and notify the clients
// of the change
self.keyboard = None;
let caps = self.compute_caps();
for seat in &self.known_seats {
seat.capabilities(caps);
}
}
self.keyboard = Some(keyboard.clone());
let caps = self.compute_caps();
for seat in &self.known_seats {
seat.capabilities(caps);
inner.keyboard = None;
inner.send_all_caps();
}
inner.keyboard = Some(keyboard.clone());
inner.send_all_caps();
Ok(keyboard)
}
@ -193,95 +229,60 @@ impl Seat {
///
/// Clients will be appropriately notified.
pub fn remove_keyboard(&mut self) {
if self.keyboard.is_some() {
self.keyboard = None;
let caps = self.compute_caps();
for seat in &self.known_seats {
seat.capabilities(caps);
}
let mut inner = self.inner.lock().unwrap();
if inner.keyboard.is_some() {
inner.keyboard = None;
inner.send_all_caps();
}
}
/// Checks wether a given `WlSeat` is associated with this `Seat`
pub fn owns(&self, seat: &wl_seat::WlSeat) -> bool {
self.known_seats.iter().any(|s| s.equals(seat))
}
/// Cleanup internal states from old resources
///
/// Deletes all remnnant of ressources from clients that
/// are now disconnected.
///
/// It can be wise to run this from time to time.
pub fn cleanup(&mut self) {
if let Some(ref pointer) = self.pointer {
pointer.cleanup_old_pointers();
}
if let Some(ref kbd) = self.keyboard {
kbd.cleanup_old_kbds();
}
self.known_seats.retain(|s| s.status() == Liveness::Alive);
}
fn compute_caps(&self) -> wl_seat::Capability {
let mut caps = wl_seat::Capability::empty();
if self.pointer.is_some() {
caps |= wl_seat::Capability::Pointer;
}
if self.keyboard.is_some() {
caps |= wl_seat::Capability::Keyboard;
}
caps
pub fn owns(&self, seat: &Resource<wl_seat::WlSeat>) -> bool {
let inner = self.inner.lock().unwrap();
inner.known_seats.iter().any(|s| s.equals(seat))
}
}
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 seat_mgr = evlh.state().get_mut(token);
if seat.version() >= 2 {
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, _, _, pointer| {
evlh.register(&pointer, pointer_implementation(), (), None);
if let Some(ref ptr_handle) = evlh.state().get(token).pointer {
ptr_handle.new_pointer(pointer);
} else {
// we should send a protocol error... but the protocol does not allow
// us, so this pointer will just remain inactive ¯\_(ツ)_/¯
fn implement_seat(
new_seat: NewResource<wl_seat::WlSeat>,
inner: Arc<Mutex<Inner>>,
) -> Resource<wl_seat::WlSeat> {
let dest_inner = inner.clone();
new_seat.implement(
move |request, _seat| {
let inner = inner.lock().unwrap();
match request {
wl_seat::Request::GetPointer { id } => {
let pointer = self::pointer::implement_pointer(id, inner.pointer.as_ref());
if let Some(ref ptr_handle) = inner.pointer {
ptr_handle.new_pointer(pointer);
} else {
// we should send a protocol error... but the protocol does not allow
// us, so this pointer will just remain inactive ¯\_(ツ)_/¯
}
}
wl_seat::Request::GetKeyboard { id } => {
let keyboard = self::keyboard::implement_keyboard(id, inner.keyboard.as_ref());
if let Some(ref kbd_handle) = inner.keyboard {
kbd_handle.new_kbd(keyboard);
} else {
// same as pointer, should error but cannot
}
}
wl_seat::Request::GetTouch { id: _ } => {
// TODO
}
wl_seat::Request::Release => {
// Our destructors already handle it
}
}
},
get_keyboard: |evlh, token, _, _, keyboard| {
evlh.register(&keyboard, keyboard_implementation(), (), None);
if let Some(ref kbd_handle) = evlh.state().get(token).keyboard {
kbd_handle.new_kbd(keyboard);
} else {
// same, should error but cant
}
},
get_touch: |_evlh, _token, _, _, _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: |_, _, _, _| {},
}
Some(move |seat, _| {
dest_inner
.lock()
.unwrap()
.known_seats
.retain(|s| !s.equals(&seat));
}),
)
}

View File

@ -1,12 +1,13 @@
use std::sync::{Arc, Mutex, MutexGuard};
use wayland_server::{Liveness, Resource};
use wayland_server::protocol::{wl_pointer, wl_surface};
use wayland_server::{NewResource, Resource};
use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::protocol::wl_pointer::{Axis, AxisSource, ButtonState, Event, Request, WlPointer};
// TODO: handle pointer surface role
struct PointerInternal {
known_pointers: Vec<wl_pointer::WlPointer>,
focus: Option<wl_surface::WlSurface>,
known_pointers: Vec<Resource<WlPointer>>,
focus: Option<Resource<WlSurface>>,
}
impl PointerInternal {
@ -19,7 +20,7 @@ impl PointerInternal {
fn with_focused_pointers<F>(&self, mut f: F)
where
F: FnMut(&wl_pointer::WlPointer, &wl_surface::WlSurface),
F: FnMut(&Resource<WlPointer>, &Resource<WlSurface>),
{
if let Some(ref focus) = self.focus {
for ptr in &self.known_pointers {
@ -44,7 +45,7 @@ pub struct PointerHandle {
}
impl PointerHandle {
pub(crate) fn new_pointer(&self, pointer: wl_pointer::WlPointer) {
pub(crate) fn new_pointer(&self, pointer: Resource<WlPointer>) {
let mut guard = self.inner.lock().unwrap();
guard.known_pointers.push(pointer);
}
@ -59,7 +60,7 @@ impl PointerHandle {
///
/// This will internally take care of notifying the appropriate client objects
/// of enter/motion/leave events.
pub fn motion(&self, location: Option<(&wl_surface::WlSurface, f64, f64)>, serial: u32, time: u32) {
pub fn motion(&self, location: Option<(&Resource<WlSurface>, f64, f64)>, serial: u32, time: u32) {
let mut guard = self.inner.lock().unwrap();
// do we leave a surface ?
let mut leave = true;
@ -72,9 +73,12 @@ impl PointerHandle {
}
if leave {
guard.with_focused_pointers(|pointer, surface| {
pointer.leave(serial, surface);
pointer.send(Event::Leave {
serial,
surface: surface.clone(),
});
if pointer.version() >= 5 {
pointer.frame();
pointer.send(Event::Frame);
}
});
guard.focus = None;
@ -83,19 +87,28 @@ impl PointerHandle {
// do we enter one ?
if let Some((surface, x, y)) = location {
if guard.focus.is_none() {
guard.focus = surface.clone();
guard.focus = Some(surface.clone());
guard.with_focused_pointers(|pointer, surface| {
pointer.enter(serial, surface, x, y);
pointer.send(Event::Enter {
serial,
surface: surface.clone(),
surface_x: x,
surface_y: y,
});
if pointer.version() >= 5 {
pointer.frame();
pointer.send(Event::Frame);
}
})
} else {
// we were on top of a surface and remained on it
guard.with_focused_pointers(|pointer, _| {
pointer.motion(time, x, y);
pointer.send(Event::Motion {
time,
surface_x: x,
surface_y: y,
});
if pointer.version() >= 5 {
pointer.frame();
pointer.send(Event::Frame);
}
})
}
@ -106,12 +119,17 @@ impl PointerHandle {
///
/// This will internally send the appropriate button event to the client
/// objects matching with the currently focused surface.
pub fn button(&self, button: u32, state: wl_pointer::ButtonState, serial: u32, time: u32) {
pub fn button(&self, button: u32, state: ButtonState, serial: u32, time: u32) {
let guard = self.inner.lock().unwrap();
guard.with_focused_pointers(|pointer, _| {
pointer.button(serial, time, button, state);
pointer.send(Event::Button {
serial,
time,
button,
state,
});
if pointer.version() >= 5 {
pointer.frame();
pointer.send(Event::Frame);
}
})
}
@ -125,18 +143,12 @@ impl PointerHandle {
inner: self.inner.lock().unwrap(),
}
}
pub(crate) fn cleanup_old_pointers(&self) {
let mut guard = self.inner.lock().unwrap();
guard
.known_pointers
.retain(|p| p.status() != Liveness::Dead);
}
}
/// A frame of pointer axis events.
///
/// Can be used with the builder pattern, e.g.:
///
/// ```ignore
/// pointer.axis()
/// .source(AxisSource::Wheel)
@ -156,10 +168,12 @@ impl<'a> PointerAxisHandle<'a> {
///
/// Using the `AxisSource::Finger` requires a stop event to be send,
/// when the user lifts off the finger (not necessarily in the same frame).
pub fn source(&mut self, source: wl_pointer::AxisSource) -> &mut Self {
pub fn source(&mut self, source: AxisSource) -> &mut Self {
self.inner.with_focused_pointers(|pointer, _| {
if pointer.version() >= 5 {
pointer.axis_source(source);
pointer.send(Event::AxisSource {
axis_source: source,
});
}
});
self
@ -170,10 +184,13 @@ impl<'a> PointerAxisHandle<'a> {
/// This event is optional and gives the client additional information about
/// the nature of the axis event. E.g. a scroll wheel might issue separate steps,
/// while a touchpad may never issue this event as it has no steps.
pub fn discrete(&mut self, axis: wl_pointer::Axis, steps: i32) -> &mut Self {
pub fn discrete(&mut self, axis: Axis, steps: i32) -> &mut Self {
self.inner.with_focused_pointers(|pointer, _| {
if pointer.version() >= 5 {
pointer.axis_discrete(axis, steps);
pointer.send(Event::AxisDiscrete {
axis,
discrete: steps,
});
}
});
self
@ -181,9 +198,9 @@ impl<'a> PointerAxisHandle<'a> {
/// The actual scroll value. This event is the only required one, but can also
/// be send multiple times. The values off one frame will be accumulated by the client.
pub fn value(&mut self, axis: wl_pointer::Axis, value: f64, time: u32) -> &mut Self {
pub fn value(&mut self, axis: Axis, value: f64, time: u32) -> &mut Self {
self.inner.with_focused_pointers(|pointer, _| {
pointer.axis(time, axis, value);
pointer.send(Event::Axis { time, axis, value });
});
self
}
@ -192,10 +209,10 @@ impl<'a> PointerAxisHandle<'a> {
///
/// This event is required for sources of the `AxisSource::Finger` type
/// and otherwise optional.
pub fn stop(&mut self, axis: wl_pointer::Axis, time: u32) -> &mut Self {
pub fn stop(&mut self, axis: Axis, time: u32) -> &mut Self {
self.inner.with_focused_pointers(|pointer, _| {
if pointer.version() >= 5 {
pointer.axis_stop(time, axis);
pointer.send(Event::AxisStop { time, axis });
}
});
self
@ -209,7 +226,7 @@ impl<'a> PointerAxisHandle<'a> {
pub fn done(&mut self) {
self.inner.with_focused_pointers(|pointer, _| {
if pointer.version() >= 5 {
pointer.frame();
pointer.send(Event::Frame);
}
})
}
@ -220,3 +237,35 @@ pub(crate) fn create_pointer_handler() -> PointerHandle {
inner: Arc::new(Mutex::new(PointerInternal::new())),
}
}
pub(crate) fn implement_pointer(
new_pointer: NewResource<WlPointer>,
handle: Option<&PointerHandle>,
) -> Resource<WlPointer> {
let destructor = match handle {
Some(h) => {
let inner = h.inner.clone();
Some(move |pointer: Resource<_>, _| {
inner
.lock()
.unwrap()
.known_pointers
.retain(|p| !p.equals(&pointer))
})
}
None => None,
};
new_pointer.implement(
|request, _pointer| {
match request {
Request::SetCursor { .. } => {
// TODO
}
Request::Release => {
// Our destructors already handle it
}
}
},
destructor,
)
}