seat: user data mechanism for Seat

This commit is contained in:
Victor Berger 2018-11-18 18:08:37 +01:00
parent 5e9ad96b0f
commit f1251a31e6
3 changed files with 51 additions and 31 deletions

View File

@ -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"

View File

@ -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;

View File

@ -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<PointerHandle>,
keyboard: Option<KeyboardHandle>,
known_seats: Vec<Resource<wl_seat::WlSeat>>,
}
struct SeatArc {
inner: Mutex<Inner>,
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<Mutex<Inner>>,
arc: Arc<SeatArc>,
}
impl Seat {
@ -127,20 +134,23 @@ impl Seat {
L: Into<Option<::slog::Logger>>,
{
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<wl_seat::WlSeat>) -> Option<Seat> {
seat.user_data::<Arc<Mutex<Inner>>>()
.cloned()
.map(|inner| Seat { inner })
seat.user_data::<Arc<SeatArc>>().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<PointerHandle> {
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<wl_surface::WlSurface>>) + '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<KeyboardHandle> {
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<wl_seat::WlSeat>) -> 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<wl_seat::WlSeat>,
inner: Arc<Mutex<Inner>>,
) -> Resource<wl_seat::WlSeat> {
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<wl_seat::WlSeat>, arc: Arc<SeatArc>) -> Resource<wl_seat::WlSeat> {
let dest_arc = arc.clone();
new_seat.implement(
move |request, seat| {
let inner = seat.user_data::<Arc<Mutex<Inner>>>().unwrap().lock().unwrap();
let arc = seat.user_data::<Arc<SeatArc>>().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,
)
}