<NME> mod.rs
<BEF> //! Seat global utilities
//!
//! This module provides you with utilities for handling the seat globals
//! and the associated input Wayland objects.
//!
//! ## How to use it
//!
//! ### Initialization
//!
//! ```
//! use smithay::delegate_seat;
//! use smithay::input::{Seat, SeatState, SeatHandler, pointer::CursorImageStatus};
//! use smithay::reexports::wayland_server::{Display, protocol::wl_surface::WlSurface};
//!
//! # struct State { seat_state: SeatState<Self> };
//! # let mut display = Display::<State>::new().unwrap();
//! # let display_handle = display.handle();
//!
//! let mut seat_state = SeatState::<State>::new();
//! // add the seat state to your state
//! // ...
//!
//! // create the wl_seat
//! let seat = seat_state.new_wl_seat(
//!     &display_handle,          // the display
//!     "seat-0",                 // the name of the seat, will be advertized to clients
//!     None                      // insert a logger here
//! );
//!
//! // implement the required traits
//! impl SeatHandler for State {
//!     type KeyboardFocus = WlSurface;
//!     type PointerFocus = WlSurface;
//!     fn seat_state(&mut self) -> &mut SeatState<Self> {
//!         &mut self.seat_state
//!     }
//!     fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&WlSurface>) {
//!         // ...
//!     }
//!     fn cursor_image(&mut self, seat: &Seat<Self>, image: CursorImageStatus) {
//!         // ...
//!     }
//! }
//! delegate_seat!(State);
//! ```
//!
//! ### Run usage
//!
//! Once the seat is initialized, you can add capabilities to it.
//!
//! Currently, only pointer and keyboard capabilities are supported by smithay.
//!
//! You can add these capabilities via methods of the [`Seat`] struct:
//! [`Seat::add_keyboard`] and [`Seat::add_pointer`].
//! These methods return handles that can be cloned and sent across thread, so you can keep one around
//! in your event-handling code to forward inputs to your clients.
//!
//! This module further defines the `"cursor_image"` role, that is assigned to surfaces used by clients
//! to change the cursor icon.

pub(crate) mod keyboard;
mod pointer;
mod touch;
    pointer::{AxisFrame, PointerGrab, PointerHandle, PointerInnerHandle},
};

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>>,
}

impl Inner {
    fn compute_caps(&self) -> wl_seat::Capability {
        let mut caps = wl_seat::Capability::empty();
    ///
    /// *Note*: This has to return `Some`, if `same_client_as` can return true
    /// for any provided `ObjectId`
    fn wl_surface(&self) -> Option<wl_surface::WlSurface>;
    /// Returns true, if the underlying wayland object originates from
    /// the same client connection as the provided `ObjectId`.
    ///
    /// *Must* return false, if there is not underlying wayland object.
    fn same_client_as(&self, object_id: &ObjectId) -> bool {
        self.wl_surface()
            .map(|s| s.id().same_client_as(object_id))
            .unwrap_or(false)
    }
}

impl WaylandFocus for wl_surface::WlSurface {
    fn wl_surface(&self) -> Option<wl_surface::WlSurface> {
        Some(self.clone())
    }
}

impl<D: SeatHandler> Inner<D> {
    fn compute_caps(&self) -> wl_seat::Capability {
        let mut caps = wl_seat::Capability::empty();
        if self.pointer.is_some() {
            caps |= wl_seat::Capability::Pointer;
        }
/// See module-level documentation for details of use.
#[derive(Clone)]
pub struct Seat {
    inner: Arc<Mutex<Inner>>,
}

impl Seat {
    }

    pub(crate) fn send_all_caps(&self) {
        let capabilities = self.compute_caps();
        for seat in &self.known_seats {
            seat.capabilities(capabilities);
        }
    }
}

        L: Into<Option<::slog::Logger>>,
    {
        let log = ::slog_or_stdlog(logger);
        let inner = Arc::new(Mutex::new(Inner {
            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() };
        let global = display.create_global(5, move |new_seat, _version| {
            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 {
    /// in case you want to remove it.
    pub fn new_wl_seat<N, L>(&mut self, display: &DisplayHandle, name: N, logger: L) -> Seat<D>
    where
        D: GlobalDispatch<WlSeat, SeatGlobalData<D>> + SeatHandler + 'static,
        <D as SeatHandler>::PointerFocus: WaylandFocus,
        <D as SeatHandler>::KeyboardFocus: WaylandFocus,

    /// 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 })
    }

    /// Adds the pointer capability to this seat
impl<D: SeatHandler + 'static> Seat<D> {
    /// Checks whether a given [`WlSeat`](wl_seat::WlSeat) is associated with this [`Seat`]
    pub fn owns(&self, seat: &wl_seat::WlSeat) -> bool {
        let inner = self.arc.inner.lock().unwrap();
        inner.known_seats.iter().any(|s| s == 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 inner.pointer.is_some() {
            // there is already a pointer, remove it and notify the clients
    }

    /// Retrieves [`WlSeat`](wl_seat::WlSeat) resources for a given client
    pub fn client_seats(&self, client: &Client) -> Vec<WlSeat> {
        self.arc
            .inner
            .lock()
            .unwrap()

    /// Access the pointer of this seat if any
    pub fn get_pointer(&self) -> Option<PointerHandle> {
        self.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();
        if inner.pointer.is_some() {
            inner.pointer = None;
            inner.send_all_caps();
    /// You are provided a [`TouchHandle`], which allows you to send input events
    /// to this pointer. This handle can be cloned.
    ///
    /// Calling this method on a seat that already has a touch capability
    /// will overwrite it, and will be seen by the clients as if the
    /// touchscreen was unplugged and a new one was plugged in.
    ///
    /// # Examples
    ///
    /// ```no_run
    /// # use smithay::input::{Seat, SeatState, SeatHandler, pointer::CursorImageStatus};
    /// # use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
    /// #
    /// # struct State;
    /// # impl SeatHandler for State {
    /// #     type KeyboardFocus = WlSurface;
    /// #     type PointerFocus = WlSurface;
    /// #     fn seat_state(&mut self) -> &mut SeatState<Self> { unimplemented!() }
    /// #     fn focus_changed(&mut self, seat: &Seat<Self>, focused: Option<&WlSurface>) { unimplemented!() }
    /// #     fn cursor_image(&mut self, seat: &Seat<Self>, image: CursorImageStatus) { unimplemented!() }
    /// # }
    /// # let mut seat: Seat<State> = unimplemented!();
    /// let touch_handle = seat.add_touch();
    /// ```
    pub fn add_touch(&mut self) -> TouchHandle {
        let mut inner = self.arc.inner.lock().unwrap();
        let touch = TouchHandle::new();
        if inner.touch.is_some() {
            // If there's already a tocuh device, remove it notify the clients about the change.
            inner.touch = None;
            inner.send_all_caps();
        }
        inner.touch = Some(touch.clone());
        inner.send_all_caps();
        touch
    }

    /// Access the touch device of this seat, if any.
    pub fn get_touch(&self) -> Option<TouchHandle> {
        self.arc.inner.lock().unwrap().touch.clone()
    }

    /// Remove the touch capability from this seat
    ///
    /// Clients will be appropriately notified.
    pub fn remove_touch(&mut self) {
        F: FnMut(&Seat, Option<&Resource<wl_surface::WlSurface>>) + 'static,
    {
        let me = self.clone();
        let mut inner = self.inner.lock().unwrap();
        let keyboard = self::keyboard::create_keyboard_handler(
            xkb_config,
            repeat_delay,
            repeat_rate,
            &inner.log,
            move |focus| focus_hook(&me, focus),
        )?;
        if inner.keyboard.is_some() {

impl<D: SeatHandler> fmt::Debug for SeatUserData<D>
where
    <D as SeatHandler>::KeyboardFocus: fmt::Debug,
    <D as SeatHandler>::PointerFocus: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("SeatUserData").field("arc", &self.arc).finish()
    }

    /// Access the keyboard of this seat if any
    pub fn get_keyboard(&self) -> Option<KeyboardHandle> {
        self.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();
        if inner.keyboard.is_some() {
            inner.keyboard = None;
            inner.send_all_caps();
            $crate::reexports::wayland_server::protocol::wl_pointer::WlPointer: $crate::wayland::seat::PointerUserData<$ty>
        ] => $crate::input::SeatState<$ty>);

    /// 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();
        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();
    new_seat.implement(
        move |request, seat| {
            let inner = seat.user_data::<Arc<Mutex<Inner>>>().unwrap().lock().unwrap();
            match request {
                wl_seat::Request::GetPointer { id } => {
                    let pointer = self::pointer::implement_pointer(id, inner.pointer.as_ref());
        request: wl_seat::Request,
        data: &SeatUserData<D>,
        _dh: &DisplayHandle,
        data_init: &mut wayland_server::DataInit<'_, D>,
    ) {
        match request {
            wl_seat::Request::GetPointer { id } => {
                let inner = data.arc.inner.lock().unwrap();

                let pointer = data_init.init(
                    id,
                    PointerUserData {
                        handle: inner.pointer.clone(),
                    },
                );

                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 ¯\_(ツ)_/¯
            }
        },
        Some(move |seat| {
            dest_inner
                .lock()
                .unwrap()
                .known_seats
                .retain(|s| !s.equals(&seat));
        }),
        inner,
    )
}
                    h.new_kbd(keyboard);
                } else {
                    // same as pointer, should error but cannot
                }
            }
            wl_seat::Request::GetTouch { id } => {
                let inner = data.arc.inner.lock().unwrap();

                let touch = data_init.init(
                    id,
                    TouchUserData {
                        handle: inner.touch.clone(),
                    },
                );

                if let Some(ref h) = inner.touch {
                    h.new_touch(touch);
                } else {
                    // same as pointer, should error but cannot
                }
            }
            wl_seat::Request::Release => {
                // Our destructors already handle it
            }
            _ => unreachable!(),
        }
    }

    fn destroyed(_state: &mut D, _: ClientId, object_id: ObjectId, data: &SeatUserData<D>) {
        data.arc
            .inner
            .lock()
            .unwrap()
            .known_seats
            .retain(|s| s.id() != object_id);
    }
}

impl<D> GlobalDispatch<WlSeat, SeatGlobalData<D>, D> for SeatState<D>
where
    D: GlobalDispatch<WlSeat, SeatGlobalData<D>>,
    D: Dispatch<WlSeat, SeatUserData<D>>,
    D: Dispatch<WlKeyboard, KeyboardUserData<D>>,
    D: Dispatch<WlPointer, PointerUserData<D>>,
    D: Dispatch<WlTouch, TouchUserData>,
    D: SeatHandler,
    D: 'static,
{
    fn bind(
        _state: &mut D,
        _dh: &DisplayHandle,
        _client: &wayland_server::Client,
        resource: New<WlSeat>,
        global_data: &SeatGlobalData<D>,
        data_init: &mut DataInit<'_, D>,
    ) {
        let data = SeatUserData {
            arc: global_data.arc.clone(),
        };

        let resource = data_init.init(resource, data);

        if resource.version() >= 2 {
            resource.name(global_data.arc.name.clone());
        }

        let mut inner = global_data.arc.inner.lock().unwrap();
        resource.capabilities(inner.compute_caps());
        inner.known_seats.push(resource);
    }
}

<MSG> seat: user data mechanism for Seat

<DFF> @@ -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,
     )
 }

seat: user data mechanism for Seat