diff --git a/src/backend/input.rs b/src/backend/input.rs index bed7877..0bc4769 100644 --- a/src/backend/input.rs +++ b/src/backend/input.rs @@ -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 + 'static>(&mut self, evlh: &mut EventLoopHandle, handler: H); + fn set_handler + 'static>(&mut self, handler: H); /// Get a reference to the currently set handler, if any fn get_handler(&mut self) -> Option<&mut InputHandler>; /// 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 { /// 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 { /// - `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 { /// /// - `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 { /// /// - `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 InputHandler for Box> { - 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) } } diff --git a/src/backend/mod.rs b/src/backend/mod.rs index f73914a..de44d15 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -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; diff --git a/src/lib.rs b/src/lib.rs index c7116d5..ec1d923 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index daada11..54331f6 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -20,6 +20,6 @@ //pub mod compositor; pub mod output; -//pub mod seat; +pub mod seat; pub mod shm; //pub mod shell; diff --git a/src/wayland/seat/keyboard.rs b/src/wayland/seat/keyboard.rs index 08ba1a3..f7996cc 100644 --- a/src/wayland/seat/keyboard.rs +++ b/src/wayland/seat/keyboard.rs @@ -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, - focus: Option, + known_kbds: Vec>, + focus: Option>, pressed_keys: Vec, 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, repeat_rate: i32, + rules: &str, + model: &str, + layout: &str, + variant: &str, + options: Option, + repeat_rate: i32, repeat_delay: i32, ) -> Result { // we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe @@ -147,7 +157,7 @@ impl KbdInternal { fn with_focused_kbds(&self, mut f: F) where - F: FnMut(&wl_keyboard::WlKeyboard, &wl_surface::WlSurface), + F: FnMut(&Resource, &Resource), { 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, repeat_delay: i32, - repeat_rate: i32, logger: &::slog::Logger, + rules: &str, + model: &str, + layout: &str, + variant: &str, + options: Option, + repeat_delay: i32, + repeat_rate: i32, + logger: &::slog::Logger, ) -> Result { 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(&self, keycode: u32, state: KeyState, serial: u32, filter: F) + pub fn input(&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>, 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) { 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, + handle: Option<&KeyboardHandle>, +) -> Resource { + 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, + ) } diff --git a/src/wayland/seat/mod.rs b/src/wayland/seat/mod.rs index 092b85b..9684636 100644 --- a/src/wayland/seat/mod.rs +++ b/src/wayland/seat/mod.rs @@ -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, + keyboard: Option, + known_seats: Vec>, +} + +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, - keyboard: Option, - known_seats: Vec, + inner: Arc>, } 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( - evlh: &mut EventLoopHandle, name: String, logger: L - ) -> (StateToken, Global>) + display: &mut Display, + token: LoopToken, + name: String, + logger: L, + ) -> (Seat, Global) where L: Into>, { 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, repeat_delay: i32, + &mut self, + model: &str, + layout: &str, + variant: &str, + options: Option, + repeat_delay: i32, repeat_rate: i32, ) -> Result { + 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) -> 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, _: &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> { - 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, + inner: Arc>, +) -> Resource { + 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)); + }), + ) } diff --git a/src/wayland/seat/pointer.rs b/src/wayland/seat/pointer.rs index 10522e2..9ed7a5d 100644 --- a/src/wayland/seat/pointer.rs +++ b/src/wayland/seat/pointer.rs @@ -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, - focus: Option, + known_pointers: Vec>, + focus: Option>, } impl PointerInternal { @@ -19,7 +20,7 @@ impl PointerInternal { fn with_focused_pointers(&self, mut f: F) where - F: FnMut(&wl_pointer::WlPointer, &wl_surface::WlSurface), + F: FnMut(&Resource, &Resource), { 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) { 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, 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, + handle: Option<&PointerHandle>, +) -> Resource { + 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, + ) +}