From f1251a31e665202d2cb0ceb1bdd04f9f24af907e Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Sun, 18 Nov 2018 18:08:37 +0100 Subject: [PATCH] seat: user data mechanism for Seat --- Cargo.toml | 1 + src/lib.rs | 1 + src/wayland/seat/mod.rs | 80 +++++++++++++++++++++++++---------------- 3 files changed, 51 insertions(+), 31 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6407095..64de8fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ members = [ "anvil" ] [dependencies] wayland-server = "0.21.1" wayland-sys = "0.21.1" +wayland-commons = "0.21.1" nix = "0.11" xkbcommon = "0.2.1" tempfile = "2.1.5" diff --git a/src/lib.rs b/src/lib.rs index 1e00641..24e5b49 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ pub extern crate image; #[cfg_attr(feature = "backend_session", macro_use)] extern crate nix; extern crate tempfile; +pub extern crate wayland_commons; pub extern crate wayland_protocols; pub extern crate wayland_server; extern crate wayland_sys; diff --git a/src/wayland/seat/mod.rs b/src/wayland/seat/mod.rs index 5853475..242e472 100644 --- a/src/wayland/seat/mod.rs +++ b/src/wayland/seat/mod.rs @@ -64,19 +64,26 @@ pub use self::{ pointer::{AxisFrame, PointerGrab, PointerHandle, PointerInnerHandle}, }; +use wayland_commons::utils::UserDataMap; + use wayland_server::{ protocol::{wl_seat, wl_surface}, Display, Global, NewResource, Resource, }; struct Inner { - log: ::slog::Logger, - name: String, pointer: Option, keyboard: Option, known_seats: Vec>, } +struct SeatArc { + inner: Mutex, + user_data: UserDataMap, + log: ::slog::Logger, + name: String, +} + impl Inner { fn compute_caps(&self) -> wl_seat::Capability { let mut caps = wl_seat::Capability::empty(); @@ -110,7 +117,7 @@ impl Inner { /// See module-level documentation for details of use. #[derive(Clone)] pub struct Seat { - inner: Arc>, + arc: Arc, } impl Seat { @@ -127,20 +134,23 @@ impl Seat { L: Into>, { let log = ::slog_or_stdlog(logger); - let inner = Arc::new(Mutex::new(Inner { + let arc = Arc::new(SeatArc { + inner: Mutex::new(Inner { + pointer: None, + keyboard: None, + known_seats: Vec::new(), + }), log: log.new(o!("smithay_module" => "seat_handler", "seat_name" => name.clone())), name, - pointer: None, - keyboard: None, - known_seats: Vec::new(), - })); - let seat = Seat { inner: inner.clone() }; + user_data: UserDataMap::new(), + }); + let seat = Seat { arc: arc.clone() }; let global = display.create_global(5, move |new_seat, _version| { - let seat = implement_seat(new_seat, inner.clone()); - let mut inner = inner.lock().unwrap(); + let seat = implement_seat(new_seat, arc.clone()); + let mut inner = arc.inner.lock().unwrap(); if seat.version() >= 2 { seat.send(wl_seat::Event::Name { - name: inner.name.clone(), + name: arc.name.clone(), }); } seat.send(wl_seat::Event::Capabilities { @@ -153,9 +163,12 @@ impl Seat { /// Attempt to retrieve a `Seat` from an existing resource pub fn from_resource(seat: &Resource) -> Option { - seat.user_data::>>() - .cloned() - .map(|inner| Seat { inner }) + seat.user_data::>().cloned().map(|arc| Seat { arc }) + } + + /// Acces the `UserDataMap` associated with this `Seat` + pub fn user_data(&self) -> &UserDataMap { + &self.arc.user_data } /// Adds the pointer capability to this seat @@ -167,7 +180,7 @@ 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 mut inner = self.arc.inner.lock().unwrap(); let pointer = self::pointer::create_pointer_handler(); if inner.pointer.is_some() { // there is already a pointer, remove it and notify the clients @@ -182,14 +195,14 @@ impl Seat { /// Access the pointer of this seat if any pub fn get_pointer(&self) -> Option { - self.inner.lock().unwrap().pointer.clone() + self.arc.inner.lock().unwrap().pointer.clone() } /// Remove the pointer capability from this seat /// /// Clients will be appropriately notified. pub fn remove_pointer(&mut self) { - let mut inner = self.inner.lock().unwrap(); + let mut inner = self.arc.inner.lock().unwrap(); if inner.pointer.is_some() { inner.pointer = None; inner.send_all_caps(); @@ -242,12 +255,12 @@ impl Seat { F: FnMut(&Seat, Option<&Resource>) + 'static, { let me = self.clone(); - let mut inner = self.inner.lock().unwrap(); + let mut inner = self.arc.inner.lock().unwrap(); let keyboard = self::keyboard::create_keyboard_handler( xkb_config, repeat_delay, repeat_rate, - &inner.log, + &self.arc.log, move |focus| focus_hook(&me, focus), )?; if inner.keyboard.is_some() { @@ -263,14 +276,14 @@ impl Seat { /// Access the keyboard of this seat if any pub fn get_keyboard(&self) -> Option { - self.inner.lock().unwrap().keyboard.clone() + self.arc.inner.lock().unwrap().keyboard.clone() } /// Remove the keyboard capability from this seat /// /// Clients will be appropriately notified. pub fn remove_keyboard(&mut self) { - let mut inner = self.inner.lock().unwrap(); + let mut inner = self.arc.inner.lock().unwrap(); if inner.keyboard.is_some() { inner.keyboard = None; inner.send_all_caps(); @@ -279,19 +292,23 @@ impl Seat { /// Checks whether a given `WlSeat` is associated with this `Seat` pub fn owns(&self, seat: &Resource) -> bool { - let inner = self.inner.lock().unwrap(); + let inner = self.arc.inner.lock().unwrap(); inner.known_seats.iter().any(|s| s.equals(seat)) } } -fn implement_seat( - new_seat: NewResource, - inner: Arc>, -) -> Resource { - let dest_inner = inner.clone(); +impl ::std::cmp::PartialEq for Seat { + fn eq(&self, other: &Seat) -> bool { + Arc::ptr_eq(&self.arc, &other.arc) + } +} + +fn implement_seat(new_seat: NewResource, arc: Arc) -> Resource { + let dest_arc = arc.clone(); new_seat.implement( move |request, seat| { - let inner = seat.user_data::>>().unwrap().lock().unwrap(); + let arc = seat.user_data::>().unwrap(); + let inner = arc.inner.lock().unwrap(); match request { wl_seat::Request::GetPointer { id } => { let pointer = self::pointer::implement_pointer(id, inner.pointer.as_ref()); @@ -319,12 +336,13 @@ fn implement_seat( } }, Some(move |seat| { - dest_inner + dest_arc + .inner .lock() .unwrap() .known_seats .retain(|s| !s.equals(&seat)); }), - inner, + arc, ) }