use super::WaylandState; use nanoid::nanoid; use once_cell::sync::OnceCell; use parking_lot::Mutex; use smithay::reexports::wayland_server::{ backend::{ClientId, GlobalId}, delegate_dispatch, delegate_global_dispatch, protocol::{ wl_keyboard::{self, WlKeyboard}, wl_pointer::{self, WlPointer}, wl_seat::{self, Capability, WlSeat, EVT_NAME_SINCE}, wl_touch::{self, WlTouch}, }, Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, }; use std::ops::Deref; use std::sync::Arc; pub struct SeatDelegate; #[derive(Clone)] pub struct SeatData(Arc); impl SeatData { pub fn new(dh: &DisplayHandle, client: ClientId) -> Self { let seat_data = SeatData(Arc::new(SeatDataInner { client, global_id: OnceCell::new(), pointer: OnceCell::new(), pointer_active: Mutex::new(false), keyboard: OnceCell::new(), keyboard_active: Mutex::new(false), touch: OnceCell::new(), })); seat_data .global_id .set(dh.create_global::(7, seat_data.clone())) .unwrap(); seat_data } } impl Deref for SeatData { type Target = SeatDataInner; fn deref(&self) -> &Self::Target { &self.0 } } pub struct SeatDataInner { client: ClientId, pub global_id: OnceCell, pointer: OnceCell, pub pointer_active: Mutex, keyboard: OnceCell, pub keyboard_active: Mutex, touch: OnceCell, } impl SeatDataInner { pub fn pointer(&self) -> Option<&WlPointer> { self.pointer.get() } pub fn keyboard(&self) -> Option<&WlKeyboard> { self.keyboard.get() } pub fn touch(&self) -> Option<&WlTouch> { self.touch.get() } } impl GlobalDispatch for SeatDelegate { fn bind( _state: &mut WaylandState, _handle: &DisplayHandle, _client: &Client, resource: New, data: &SeatData, data_init: &mut DataInit<'_, WaylandState>, ) { let resource = data_init.init(resource, data.clone()); if resource.version() >= EVT_NAME_SINCE { resource.name(nanoid!()); } resource.capabilities(Capability::Pointer | Capability::Keyboard); } fn can_view(client: Client, data: &SeatData) -> bool { client.id() == data.0.client } } delegate_global_dispatch!(WaylandState: [WlSeat: SeatData] => SeatDelegate); impl Dispatch for SeatDelegate { fn request( _state: &mut WaylandState, _client: &Client, _resource: &WlSeat, request: ::Request, data: &SeatData, _dh: &DisplayHandle, data_init: &mut DataInit<'_, WaylandState>, ) { match request { wl_seat::Request::GetPointer { id } => { let _ = data.0.pointer.set(data_init.init(id, data.clone())); } wl_seat::Request::GetKeyboard { id } => { let _ = data.0.keyboard.set(data_init.init(id, data.clone())); } wl_seat::Request::GetTouch { id } => { let _ = data.0.touch.set(data_init.init(id, data.clone())); } wl_seat::Request::Release => (), _ => unreachable!(), } } } delegate_dispatch!(WaylandState: [WlSeat: SeatData] => SeatDelegate); impl Dispatch for SeatDelegate { fn request( _state: &mut WaylandState, _client: &Client, _resource: &WlPointer, request: ::Request, _data: &SeatData, _dh: &DisplayHandle, _data_init: &mut DataInit<'_, WaylandState>, ) { match request { wl_pointer::Request::SetCursor { serial: _, surface: _, hotspot_x: _, hotspot_y: _, } => (), wl_pointer::Request::Release => (), _ => unreachable!(), } } } delegate_dispatch!(WaylandState: [WlPointer: SeatData] => SeatDelegate); impl Dispatch for SeatDelegate { fn request( _state: &mut WaylandState, _client: &Client, _resource: &WlKeyboard, request: ::Request, _data: &SeatData, _dh: &DisplayHandle, _data_init: &mut DataInit<'_, WaylandState>, ) { match request { wl_keyboard::Request::Release => (), _ => unreachable!(), } } } delegate_dispatch!(WaylandState: [WlKeyboard: SeatData] => SeatDelegate); impl Dispatch for SeatDelegate { fn request( _state: &mut WaylandState, _client: &Client, _resource: &WlTouch, request: ::Request, _data: &SeatData, _dh: &DisplayHandle, _data_init: &mut DataInit<'_, WaylandState>, ) { match request { wl_touch::Request::Release => (), _ => unreachable!(), } } } delegate_dispatch!(WaylandState: [WlTouch: SeatData] => SeatDelegate);