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::error::Error;
use std::string::ToString; use std::string::ToString;
use wayland_server::EventLoopHandle;
/// A seat describes a group of input devices and at least one /// A seat describes a group of input devices and at least one
/// graphics device belonging together. /// graphics device belonging together.
@ -521,31 +520,31 @@ pub trait InputBackend: Sized {
type TouchFrameEvent: TouchFrameEvent; type TouchFrameEvent: TouchFrameEvent;
/// Sets a new handler for this `InputBackend` /// 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 /// Get a reference to the currently set handler, if any
fn get_handler(&mut self) -> Option<&mut InputHandler<Self>>; fn get_handler(&mut self) -> Option<&mut InputHandler<Self>>;
/// Clears the currently handler, if one is set /// Clears the currently handler, if one is set
fn clear_handler(&mut self, evlh: &mut EventLoopHandle); fn clear_handler(&mut self);
/// Get current `InputConfig` /// Get current `InputConfig`
fn input_config(&mut self) -> &mut Self::InputConfig; fn input_config(&mut self) -> &mut Self::InputConfig;
/// Processes new events of the underlying backend and drives the `InputHandler`. /// 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`. /// Implement to receive input events from any `InputBackend`.
pub trait InputHandler<B: InputBackend> { pub trait InputHandler<B: InputBackend> {
/// Called when a new `Seat` has been created /// 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. /// 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. /// Called when a `Seat`'s properties have changed.
/// ///
/// ## Note: /// ## Note:
/// ///
/// It is not guaranteed that any change has actually happened. /// 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. /// Called when a new keyboard event was received.
/// ///
@ -554,7 +553,7 @@ pub trait InputHandler<B: InputBackend> {
/// - `seat` - The `Seat` the event belongs to /// - `seat` - The `Seat` the event belongs to
/// - `event` - The keyboard event /// - `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. /// 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 /// - `seat` - The `Seat` the event belongs to
/// - `event` - The pointer movement event /// - `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. /// Called when a new pointer absolute movement event was received.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `seat` - The `Seat` the event belongs to /// - `seat` - The `Seat` the event belongs to
/// - `event` - The pointer absolute movement event /// - `event` - The pointer absolute movement event
fn on_pointer_move_absolute( fn on_pointer_move_absolute(&mut self, seat: &Seat, event: B::PointerMotionAbsoluteEvent);
&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::PointerMotionAbsoluteEvent
);
/// Called when a new pointer button event was received. /// Called when a new pointer button event was received.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `seat` - The `Seat` the event belongs to /// - `seat` - The `Seat` the event belongs to
/// - `event` - The pointer button event /// - `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. /// Called when a new pointer scroll event was received.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `seat` - The `Seat` the event belongs to /// - `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. /// - `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. /// 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 /// - `seat` - The `Seat` the event belongs to
/// - `event` - The touch down event /// - `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. /// Called when a new touch motion event was received.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `seat` - The `Seat` the event belongs to /// - `seat` - The `Seat` the event belongs to
/// - `event` - The touch motion event. /// - `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. /// Called when a new touch up event was received.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `seat` - The `Seat` the event belongs to /// - `seat` - The `Seat` the event belongs to
/// - `event` - The touch up event. /// - `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. /// Called when a new touch cancel event was received.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `seat` - The `Seat` the event belongs to /// - `seat` - The `Seat` the event belongs to
/// - `event` - The touch cancel event. /// - `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. /// Called when a new touch frame event was received.
/// ///
/// # Arguments /// # Arguments
/// ///
/// - `seat` - The `Seat` the event belongs to /// - `seat` - The `Seat` the event belongs to
/// - `event` - The touch frame event. /// - `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. /// Called when the `InputConfig` was changed through an external event.
/// ///
/// What kind of events can trigger this call is completely backend dependent. /// 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. /// 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>> { impl<B: InputBackend> InputHandler<B> for Box<InputHandler<B>> {
fn on_seat_created(&mut self, evlh: &mut EventLoopHandle, seat: &Seat) { fn on_seat_created(&mut self, seat: &Seat) {
(**self).on_seat_created(evlh, seat) (**self).on_seat_created(seat)
} }
fn on_seat_destroyed(&mut self, evlh: &mut EventLoopHandle, seat: &Seat) { fn on_seat_destroyed(&mut self, seat: &Seat) {
(**self).on_seat_destroyed(evlh, seat) (**self).on_seat_destroyed(seat)
} }
fn on_seat_changed(&mut self, evlh: &mut EventLoopHandle, seat: &Seat) { fn on_seat_changed(&mut self, seat: &Seat) {
(**self).on_seat_changed(evlh, seat) (**self).on_seat_changed(seat)
} }
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) {
(**self).on_keyboard_key(evlh, seat, event) (**self).on_keyboard_key(seat, 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) {
(**self).on_pointer_move(evlh, seat, event) (**self).on_pointer_move(seat, event)
} }
fn on_pointer_move_absolute( fn on_pointer_move_absolute(&mut self, seat: &Seat, event: B::PointerMotionAbsoluteEvent) {
&mut self, evlh: &mut EventLoopHandle, seat: &Seat, event: B::PointerMotionAbsoluteEvent (**self).on_pointer_move_absolute(seat, event)
) {
(**self).on_pointer_move_absolute(evlh, seat, 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) {
(**self).on_pointer_button(evlh, seat, event) (**self).on_pointer_button(seat, event)
} }
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) {
(**self).on_pointer_axis(evlh, seat, event) (**self).on_pointer_axis(seat, 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) {
(**self).on_touch_down(evlh, seat, event) (**self).on_touch_down(seat, 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) {
(**self).on_touch_motion(evlh, seat, event) (**self).on_touch_motion(seat, 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) {
(**self).on_touch_up(evlh, seat, event) (**self).on_touch_up(seat, 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) {
(**self).on_touch_cancel(evlh, seat, event) (**self).on_touch_cancel(seat, 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) {
(**self).on_touch_frame(evlh, seat, event) (**self).on_touch_frame(seat, event)
} }
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) {
(**self).on_input_config_changed(evlh, config) (**self).on_input_config_changed(config)
} }
} }

View File

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

View File

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

View File

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

View File

@ -3,8 +3,9 @@ use std::io::{Error as IoError, Write};
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use tempfile::tempfile; use tempfile::tempfile;
use wayland_server::{Liveness, Resource}; use wayland_server::{NewResource, Resource};
use wayland_server::protocol::{wl_keyboard, wl_surface}; use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::protocol::wl_keyboard::{Event, KeyState as WlKeyState, KeymapFormat, Request, WlKeyboard};
use xkbcommon::xkb; use xkbcommon::xkb;
pub use xkbcommon::xkb::{keysyms, Keysym}; pub use xkbcommon::xkb::{keysyms, Keysym};
@ -55,8 +56,8 @@ impl ModifiersState {
} }
struct KbdInternal { struct KbdInternal {
known_kbds: Vec<wl_keyboard::WlKeyboard>, known_kbds: Vec<Resource<WlKeyboard>>,
focus: Option<wl_surface::WlSurface>, focus: Option<Resource<WlSurface>>,
pressed_keys: Vec<u32>, pressed_keys: Vec<u32>,
mods_state: ModifiersState, mods_state: ModifiersState,
keymap: xkb::Keymap, keymap: xkb::Keymap,
@ -65,9 +66,18 @@ struct KbdInternal {
repeat_delay: i32, repeat_delay: i32,
} }
// This is OK because all parts of `xkb` will remain on the
// same thread
unsafe impl Send for KbdInternal {}
impl KbdInternal { impl KbdInternal {
fn new( 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, repeat_delay: i32,
) -> Result<KbdInternal, ()> { ) -> Result<KbdInternal, ()> {
// we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe // 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) fn with_focused_kbds<F>(&self, mut f: F)
where where
F: FnMut(&wl_keyboard::WlKeyboard, &wl_surface::WlSurface), F: FnMut(&Resource<WlKeyboard>, &Resource<WlSurface>),
{ {
if let Some(ref surface) = self.focus { if let Some(ref surface) = self.focus {
for kbd in &self.known_kbds { for kbd in &self.known_kbds {
@ -170,8 +180,14 @@ pub enum Error {
/// Create a keyboard handler from a set of RMLVO rules /// Create a keyboard handler from a set of RMLVO rules
pub(crate) fn create_keyboard_handler( pub(crate) fn create_keyboard_handler(
rules: &str, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_delay: i32, rules: &str,
repeat_rate: i32, logger: &::slog::Logger, model: &str,
layout: &str,
variant: &str,
options: Option<String>,
repeat_delay: i32,
repeat_rate: i32,
logger: &::slog::Logger,
) -> Result<KeyboardHandle, Error> { ) -> Result<KeyboardHandle, Error> {
let log = logger.new(o!("smithay_module" => "xkbcommon_handler")); let log = logger.new(o!("smithay_module" => "xkbcommon_handler"));
info!(log, "Initializing a xkbcommon handler with keymap query"; 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 /// 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. /// 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 where
F: FnOnce(&ModifiersState, Keysym) -> bool, F: FnOnce(&ModifiersState, Keysym) -> bool,
{ {
@ -282,14 +298,25 @@ impl KeyboardHandle {
None None
}; };
let wl_state = match state { let wl_state = match state {
KeyState::Pressed => wl_keyboard::KeyState::Pressed, KeyState::Pressed => WlKeyState::Pressed,
KeyState::Released => wl_keyboard::KeyState::Released, KeyState::Released => WlKeyState::Released,
}; };
guard.with_focused_kbds(|kbd, _| { guard.with_focused_kbds(|kbd, _| {
if let Some((dep, la, lo, gr)) = modifiers { 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() { if guard.focus.is_some() {
trace!(self.arc.logger, "Input forwarded to client"); 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 /// 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`, /// will be sent a `wl_keyboard::leave` event, and if the new focus is not `None`,
/// a `wl_keyboard::enter` event will be sent. /// 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 mut guard = self.arc.internal.lock().unwrap();
let same = guard let same = guard
@ -315,16 +342,29 @@ impl KeyboardHandle {
if !same { 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.send(Event::Leave {
serial,
surface: s.clone(),
});
}); });
// set new focus // 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 (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, surface| {
kbd.modifiers(serial, dep, la, lo, gr); kbd.send(Event::Modifiers {
kbd.enter(serial, s, keys.clone()); 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() { if guard.focus.is_some() {
trace!(self.arc.logger, "Focus set to new surface"); trace!(self.arc.logger, "Focus set to new surface");
@ -341,16 +381,19 @@ impl KeyboardHandle {
/// 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(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"); trace!(self.arc.logger, "Sending keymap to client");
kbd.keymap( kbd.send(Event::Keymap {
wl_keyboard::KeymapFormat::XkbV1, format: KeymapFormat::XkbV1,
self.arc.keymap_file.as_raw_fd(), fd: self.arc.keymap_file.as_raw_fd(),
self.arc.keymap_len, size: self.arc.keymap_len,
); });
let mut guard = self.arc.internal.lock().unwrap(); let mut guard = self.arc.internal.lock().unwrap();
if kbd.version() >= 4 { 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); guard.known_kbds.push(kbd);
} }
@ -361,17 +404,36 @@ impl KeyboardHandle {
guard.repeat_delay = delay; guard.repeat_delay = delay;
guard.repeat_rate = rate; guard.repeat_rate = rate;
for kbd in &guard.known_kbds { for kbd in &guard.known_kbds {
kbd.repeat_info(rate, delay); kbd.send(Event::RepeatInfo { rate, delay });
}
} }
} }
/// Performs an internal cleanup of known kbds pub(crate) fn implement_keyboard(
/// new_keyboard: NewResource<WlKeyboard>,
/// Drops any wl_keyboard that is no longer alive handle: Option<&KeyboardHandle>,
pub(crate) fn cleanup_old_kbds(&self) { ) -> Resource<WlKeyboard> {
let mut guard = self.arc.internal.lock().unwrap(); let destructor = match handle {
guard Some(h) => {
let arc = h.arc.clone();
Some(move |keyboard: Resource<_>, _| {
arc.internal
.lock()
.unwrap()
.known_kbds .known_kbds
.retain(|kbd| kbd.status() != Liveness::Dead); .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; //! # extern crate wayland_server;
//! # #[macro_use] extern crate smithay; //! # #[macro_use] extern crate smithay;
//!
//! use smithay::wayland::seat::Seat; //! use smithay::wayland::seat::Seat;
//! //!
//! # fn main(){ //! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display(); //! # let (mut display, event_loop) = wayland_server::Display::new();
//! // insert the seat: //! // insert the seat:
//! let (seat_state_token, seat_global) = Seat::new( //! let (seat, seat_global) = Seat::new(
//! &mut event_loop, //! &mut display, // the display
//! event_loop.token(), // a LoopToken
//! "seat-0".into(), // the name of the seat, will be advertize to clients //! "seat-0".into(), // the name of the seat, will be advertize to clients
//! None /* insert a logger here*/ //! None /* insert a logger here*/
//! ); //! );
@ -31,8 +31,7 @@
//! Currently, only pointer and keyboard capabilities are supported by //! Currently, only pointer and keyboard capabilities are supported by
//! smithay. //! smithay.
//! //!
//! You can add these capabilities via methods of the `Seat` struct that was //! You can add these capabilities via methods of the `Seat` struct:
//! inserted in the event loop, that you can retreive via its token:
//! //!
//! ``` //! ```
//! # extern crate wayland_server; //! # extern crate wayland_server;
@ -41,28 +40,59 @@
//! # use smithay::wayland::seat::Seat; //! # use smithay::wayland::seat::Seat;
//! # //! #
//! # fn main(){ //! # fn main(){
//! # let (_display, mut event_loop) = wayland_server::create_display(); //! # let (mut display, event_loop) = wayland_server::Display::new();
//! # let (seat_state_token, seat_global) = Seat::new( //! # let (mut seat, seat_global) = Seat::new(
//! # &mut event_loop, //! # &mut display,
//! # event_loop.token(),
//! # "seat-0".into(), // the name of the seat, will be advertize to clients //! # "seat-0".into(), // the name of the seat, will be advertize to clients
//! # None /* insert a logger here*/ //! # 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 //! 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. //! in your event-handling code to forward inputs to your clients.
use std::sync::{Arc, Mutex};
mod keyboard; mod keyboard;
mod pointer; mod pointer;
pub use self::keyboard::{Error as KeyboardError, KeyboardHandle, ModifiersState}; pub use self::keyboard::{Error as KeyboardError, KeyboardHandle, ModifiersState};
pub use self::pointer::{PointerAxisHandle, PointerHandle}; pub use self::pointer::{PointerAxisHandle, PointerHandle};
use wayland_server::{Client, EventLoopHandle, Global, Liveness, Resource, StateToken}; use wayland_server::{Display, Global, LoopToken, NewResource, Resource};
use wayland_server::protocol::{wl_keyboard, wl_pointer, wl_seat}; 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 /// This struct gives you access to the control of the
/// capabilities of the associated seat. /// 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. /// See module-level documentation for details of use.
pub struct Seat { pub struct Seat {
log: ::slog::Logger, inner: Arc<Mutex<Inner>>,
name: String,
pointer: Option<PointerHandle>,
keyboard: Option<KeyboardHandle>,
known_seats: Vec<wl_seat::WlSeat>,
} }
impl Seat { impl Seat {
@ -88,22 +114,39 @@ impl Seat {
/// you to add or remove capabilities from it), and the global handle, /// you to add or remove capabilities from it), and the global handle,
/// in case you want to remove it. /// in case you want to remove it.
pub fn new<L>( pub fn new<L>(
evlh: &mut EventLoopHandle, name: String, logger: L display: &mut Display,
) -> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>) token: LoopToken,
name: String,
logger: L,
) -> (Seat, Global<wl_seat::WlSeat>)
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
let log = ::slog_or_stdlog(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())), log: log.new(o!("smithay_module" => "seat_handler", "seat_name" => name.clone())),
name: name, name: name,
pointer: None, pointer: None,
keyboard: None, keyboard: None,
known_seats: Vec::new(), known_seats: Vec::new(),
}));
let seat = Seat {
inner: inner.clone(),
}; };
let token = evlh.state().insert(seat); let global = display.create_global(&token, 5, move |_version, new_seat| {
let global = evlh.register_global(5, seat_global_bind, token.clone()); let seat = implement_seat(new_seat, inner.clone());
(token, global) 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 /// 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 /// will overwrite it, and will be seen by the clients as if the
/// mouse was unplugged and a new one was plugged. /// mouse was unplugged and a new one was plugged.
pub fn add_pointer(&mut self) -> PointerHandle { pub fn add_pointer(&mut self) -> PointerHandle {
let mut inner = self.inner.lock().unwrap();
let pointer = self::pointer::create_pointer_handler(); 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 // there is already a pointer, remove it and notify the clients
// of the change // of the change
self.pointer = None; inner.pointer = None;
let caps = self.compute_caps(); inner.send_all_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 = Some(pointer.clone());
inner.send_all_caps();
pointer pointer
} }
@ -137,12 +175,10 @@ impl Seat {
/// ///
/// Clients will be appropriately notified. /// Clients will be appropriately notified.
pub fn remove_pointer(&mut self) { pub fn remove_pointer(&mut self) {
if self.pointer.is_some() { let mut inner = self.inner.lock().unwrap();
self.pointer = None; if inner.pointer.is_some() {
let caps = self.compute_caps(); inner.pointer = None;
for seat in &self.known_seats { inner.send_all_caps();
seat.capabilities(caps);
}
} }
} }
@ -159,9 +195,15 @@ impl Seat {
/// will overwrite it, and will be seen by the clients as if the /// will overwrite it, and will be seen by the clients as if the
/// keyboard was unplugged and a new one was plugged. /// keyboard was unplugged and a new one was plugged.
pub fn add_keyboard( 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, repeat_rate: i32,
) -> Result<KeyboardHandle, KeyboardError> { ) -> Result<KeyboardHandle, KeyboardError> {
let mut inner = self.inner.lock().unwrap();
let keyboard = self::keyboard::create_keyboard_handler( let keyboard = self::keyboard::create_keyboard_handler(
"evdev", // we need this one "evdev", // we need this one
model, model,
@ -170,22 +212,16 @@ impl Seat {
options, options,
repeat_delay, repeat_delay,
repeat_rate, 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 // there is already a keyboard, remove it and notify the clients
// of the change // of the change
self.keyboard = None; inner.keyboard = None;
let caps = self.compute_caps(); inner.send_all_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 = Some(keyboard.clone());
inner.send_all_caps();
Ok(keyboard) Ok(keyboard)
} }
@ -193,95 +229,60 @@ impl Seat {
/// ///
/// Clients will be appropriately notified. /// Clients will be appropriately notified.
pub fn remove_keyboard(&mut self) { pub fn remove_keyboard(&mut self) {
if self.keyboard.is_some() { let mut inner = self.inner.lock().unwrap();
self.keyboard = None; if inner.keyboard.is_some() {
let caps = self.compute_caps(); inner.keyboard = None;
for seat in &self.known_seats { inner.send_all_caps();
seat.capabilities(caps);
}
} }
} }
/// Checks wether a given `WlSeat` is associated with this `Seat` /// Checks wether a given `WlSeat` is associated with this `Seat`
pub fn owns(&self, seat: &wl_seat::WlSeat) -> bool { pub fn owns(&self, seat: &Resource<wl_seat::WlSeat>) -> bool {
self.known_seats.iter().any(|s| s.equals(seat)) let inner = self.inner.lock().unwrap();
} inner.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
} }
} }
fn seat_global_bind( fn implement_seat(
evlh: &mut EventLoopHandle, token: &mut StateToken<Seat>, _: &Client, seat: wl_seat::WlSeat new_seat: NewResource<wl_seat::WlSeat>,
) { inner: Arc<Mutex<Inner>>,
evlh.register(&seat, seat_implementation(), token.clone(), None); ) -> Resource<wl_seat::WlSeat> {
let seat_mgr = evlh.state().get_mut(token); let dest_inner = inner.clone();
if seat.version() >= 2 { new_seat.implement(
seat.name(seat_mgr.name.clone()); move |request, _seat| {
} let inner = inner.lock().unwrap();
seat.capabilities(seat_mgr.compute_caps()); match request {
seat_mgr.known_seats.push(seat); wl_seat::Request::GetPointer { id } => {
} let pointer = self::pointer::implement_pointer(id, inner.pointer.as_ref());
if let Some(ref ptr_handle) = inner.pointer {
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); ptr_handle.new_pointer(pointer);
} else { } else {
// we should send a protocol error... but the protocol does not allow // we should send a protocol error... but the protocol does not allow
// us, so this pointer will just remain inactive ¯\_(ツ)_/¯ // us, so this pointer will just remain inactive ¯\_(ツ)_/¯
} }
}, }
get_keyboard: |evlh, token, _, _, keyboard| { wl_seat::Request::GetKeyboard { id } => {
evlh.register(&keyboard, keyboard_implementation(), (), None); let keyboard = self::keyboard::implement_keyboard(id, inner.keyboard.as_ref());
if let Some(ref kbd_handle) = evlh.state().get(token).keyboard { if let Some(ref kbd_handle) = inner.keyboard {
kbd_handle.new_kbd(keyboard); kbd_handle.new_kbd(keyboard);
} else { } else {
// same, should error but cant // same as pointer, should error but cannot
} }
}, }
get_touch: |_evlh, _token, _, _, _touch| { wl_seat::Request::GetTouch { id: _ } => {
// TODO // TODO
}
wl_seat::Request::Release => {
// Our destructors already handle it
}
}
}, },
release: |_, _, _, _| {}, Some(move |seat, _| {
} dest_inner
} .lock()
.unwrap()
fn pointer_implementation() -> wl_pointer::Implementation<()> { .known_seats
wl_pointer::Implementation { .retain(|s| !s.equals(&seat));
set_cursor: |_, _, _, _, _, _, _, _| {}, }),
release: |_, _, _, _| {}, )
}
}
fn keyboard_implementation() -> wl_keyboard::Implementation<()> {
wl_keyboard::Implementation {
release: |_, _, _, _| {},
}
} }

View File

@ -1,12 +1,13 @@
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use wayland_server::{Liveness, Resource}; use wayland_server::{NewResource, Resource};
use wayland_server::protocol::{wl_pointer, wl_surface}; use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::protocol::wl_pointer::{Axis, AxisSource, ButtonState, Event, Request, WlPointer};
// TODO: handle pointer surface role // TODO: handle pointer surface role
struct PointerInternal { struct PointerInternal {
known_pointers: Vec<wl_pointer::WlPointer>, known_pointers: Vec<Resource<WlPointer>>,
focus: Option<wl_surface::WlSurface>, focus: Option<Resource<WlSurface>>,
} }
impl PointerInternal { impl PointerInternal {
@ -19,7 +20,7 @@ impl PointerInternal {
fn with_focused_pointers<F>(&self, mut f: F) fn with_focused_pointers<F>(&self, mut f: F)
where where
F: FnMut(&wl_pointer::WlPointer, &wl_surface::WlSurface), F: FnMut(&Resource<WlPointer>, &Resource<WlSurface>),
{ {
if let Some(ref focus) = self.focus { if let Some(ref focus) = self.focus {
for ptr in &self.known_pointers { for ptr in &self.known_pointers {
@ -44,7 +45,7 @@ pub struct PointerHandle {
} }
impl 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(); let mut guard = self.inner.lock().unwrap();
guard.known_pointers.push(pointer); guard.known_pointers.push(pointer);
} }
@ -59,7 +60,7 @@ impl PointerHandle {
/// ///
/// This will internally take care of notifying the appropriate client objects /// This will internally take care of notifying the appropriate client objects
/// of enter/motion/leave events. /// 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(); let mut guard = self.inner.lock().unwrap();
// do we leave a surface ? // do we leave a surface ?
let mut leave = true; let mut leave = true;
@ -72,9 +73,12 @@ impl PointerHandle {
} }
if leave { if leave {
guard.with_focused_pointers(|pointer, surface| { guard.with_focused_pointers(|pointer, surface| {
pointer.leave(serial, surface); pointer.send(Event::Leave {
serial,
surface: surface.clone(),
});
if pointer.version() >= 5 { if pointer.version() >= 5 {
pointer.frame(); pointer.send(Event::Frame);
} }
}); });
guard.focus = None; guard.focus = None;
@ -83,19 +87,28 @@ impl PointerHandle {
// do we enter one ? // do we enter one ?
if let Some((surface, x, y)) = location { if let Some((surface, x, y)) = location {
if guard.focus.is_none() { if guard.focus.is_none() {
guard.focus = surface.clone(); guard.focus = Some(surface.clone());
guard.with_focused_pointers(|pointer, surface| { 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 { if pointer.version() >= 5 {
pointer.frame(); pointer.send(Event::Frame);
} }
}) })
} else { } else {
// we were on top of a surface and remained on it // we were on top of a surface and remained on it
guard.with_focused_pointers(|pointer, _| { 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 { 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 /// This will internally send the appropriate button event to the client
/// objects matching with the currently focused surface. /// 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(); let guard = self.inner.lock().unwrap();
guard.with_focused_pointers(|pointer, _| { guard.with_focused_pointers(|pointer, _| {
pointer.button(serial, time, button, state); pointer.send(Event::Button {
serial,
time,
button,
state,
});
if pointer.version() >= 5 { if pointer.version() >= 5 {
pointer.frame(); pointer.send(Event::Frame);
} }
}) })
} }
@ -125,18 +143,12 @@ impl PointerHandle {
inner: self.inner.lock().unwrap(), 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. /// A frame of pointer axis events.
/// ///
/// Can be used with the builder pattern, e.g.: /// Can be used with the builder pattern, e.g.:
///
/// ```ignore /// ```ignore
/// pointer.axis() /// pointer.axis()
/// .source(AxisSource::Wheel) /// .source(AxisSource::Wheel)
@ -156,10 +168,12 @@ impl<'a> PointerAxisHandle<'a> {
/// ///
/// Using the `AxisSource::Finger` requires a stop event to be send, /// Using the `AxisSource::Finger` requires a stop event to be send,
/// when the user lifts off the finger (not necessarily in the same frame). /// 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, _| { self.inner.with_focused_pointers(|pointer, _| {
if pointer.version() >= 5 { if pointer.version() >= 5 {
pointer.axis_source(source); pointer.send(Event::AxisSource {
axis_source: source,
});
} }
}); });
self self
@ -170,10 +184,13 @@ impl<'a> PointerAxisHandle<'a> {
/// This event is optional and gives the client additional information about /// 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, /// 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. /// 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, _| { self.inner.with_focused_pointers(|pointer, _| {
if pointer.version() >= 5 { if pointer.version() >= 5 {
pointer.axis_discrete(axis, steps); pointer.send(Event::AxisDiscrete {
axis,
discrete: steps,
});
} }
}); });
self self
@ -181,9 +198,9 @@ impl<'a> PointerAxisHandle<'a> {
/// The actual scroll value. This event is the only required one, but can also /// 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. /// 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, _| { self.inner.with_focused_pointers(|pointer, _| {
pointer.axis(time, axis, value); pointer.send(Event::Axis { time, axis, value });
}); });
self self
} }
@ -192,10 +209,10 @@ impl<'a> PointerAxisHandle<'a> {
/// ///
/// This event is required for sources of the `AxisSource::Finger` type /// This event is required for sources of the `AxisSource::Finger` type
/// and otherwise optional. /// 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, _| { self.inner.with_focused_pointers(|pointer, _| {
if pointer.version() >= 5 { if pointer.version() >= 5 {
pointer.axis_stop(time, axis); pointer.send(Event::AxisStop { time, axis });
} }
}); });
self self
@ -209,7 +226,7 @@ impl<'a> PointerAxisHandle<'a> {
pub fn done(&mut self) { pub fn done(&mut self) {
self.inner.with_focused_pointers(|pointer, _| { self.inner.with_focused_pointers(|pointer, _| {
if pointer.version() >= 5 { 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())), 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,
)
}