use crate::wayland::core::{keyboard::Keyboard, pointer::Pointer, surface::Surface, touch::Touch}; use mint::Vector2; use std::sync::Arc; use std::sync::OnceLock; pub use waynest::server::protocol::core::wayland::wl_seat::*; use waynest::server::{Client, Dispatcher, Result}; use waynest::wire::{Fixed, ObjectId}; #[derive(Debug)] pub enum SeatMessage { PointerMotion { surface: Arc, position: Vector2, }, PointerButton { surface: Arc, button: u32, pressed: bool, }, PointerScroll { surface: Arc, scroll_distance: Option>, scroll_steps: Option>, }, KeyboardKey { surface: Arc, keymap_id: u64, key: u32, pressed: bool, }, TouchDown { surface: Arc, id: u32, position: Vector2, }, TouchMove { id: u32, position: Vector2, }, TouchUp { id: u32, }, Reset, } pub fn fixed_from_f32(f: f32) -> Fixed { unsafe { Fixed::from_raw((f * 256.0).round() as u32) } } #[derive(Default, Dispatcher)] pub struct Seat { pointer: OnceLock>, keyboard: OnceLock>, touch: OnceLock>, } impl Seat { pub fn new() -> Self { Self::default() } pub async fn advertise_capabilities(&self, client: &mut Client, id: ObjectId) -> Result<()> { tracing::debug!("Advertising seat capabilities with id {}", id); let capabilities = Capability::Pointer | Capability::Keyboard | Capability::Touch; WlSeat::capabilities(self, client, id, capabilities).await?; tracing::debug!("Capabilities advertised: {:?}", capabilities); Ok(()) } pub async fn handle_message(&self, client: &mut Client, message: SeatMessage) -> Result<()> { match message { SeatMessage::PointerMotion { surface, position } => { if let Some(pointer) = self.pointer.get() { pointer .handle_pointer_motion(client, surface, position) .await?; } } SeatMessage::PointerButton { surface, button, pressed, } => { if let Some(pointer) = self.pointer.get() { pointer .handle_pointer_button(client, surface, button, pressed) .await?; } } SeatMessage::PointerScroll { surface, scroll_distance, scroll_steps, } => { if let Some(pointer) = self.pointer.get() { pointer .handle_pointer_scroll(client, surface, scroll_distance, scroll_steps) .await?; } } SeatMessage::KeyboardKey { surface, keymap_id, key, pressed, } => { if let Some(keyboard) = self.keyboard.get() { keyboard .handle_keyboard_key(client, surface, keymap_id, key - 8, pressed) .await?; } } SeatMessage::TouchDown { surface, id, position, } => { if let Some(touch) = self.touch.get() { touch .handle_touch_down(client, surface, id, position) .await?; } } SeatMessage::TouchMove { id, position } => { if let Some(touch) = self.touch.get() { touch.handle_touch_move(client, id, position).await?; } } SeatMessage::TouchUp { id } => { if let Some(touch) = self.touch.get() { touch.handle_touch_up(client, id).await?; } } SeatMessage::Reset => { if let Some(pointer) = self.pointer.get() { pointer.reset(client).await?; } if let Some(keyboard) = self.keyboard.get() { keyboard.reset(client).await?; } if let Some(touch) = self.touch.get() { touch.reset(client).await?; } } } Ok(()) } } impl WlSeat for Seat { /// https://wayland.app/protocols/wayland#wl_seat:request:get_pointer async fn get_pointer( &self, client: &mut Client, _sender_id: ObjectId, id: ObjectId, ) -> Result<()> { let pointer = client.insert(id, Pointer::new(id)); let _ = self.pointer.set(pointer); Ok(()) } /// https://wayland.app/protocols/wayland#wl_seat:request:get_keyboard async fn get_keyboard( &self, client: &mut Client, _sender_id: ObjectId, id: ObjectId, ) -> Result<()> { tracing::info!("Getting keyboard"); let keyboard = client.insert(id, Keyboard::new(id)); let _ = self.keyboard.set(keyboard); Ok(()) } /// https://wayland.app/protocols/wayland#wl_seat:request:get_touch async fn get_touch( &self, client: &mut Client, _sender_id: ObjectId, id: ObjectId, ) -> Result<()> { let touch = client.insert(id, Touch(id)); let _ = self.touch.set(touch); Ok(()) } /// https://wayland.app/protocols/wayland#wl_seat:request:release async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { Ok(()) } }