use crate::wayland::core::{seat::fixed_from_f32, surface::Surface}; use mint::Vector2; use std::sync::Arc; use std::sync::Weak; use tokio::sync::Mutex; use tracing; pub use waynest::server::protocol::core::wayland::wl_pointer::*; use waynest::{ server::{Client, Dispatcher, Result}, wire::ObjectId, }; #[derive(Dispatcher)] pub struct Pointer { pub id: ObjectId, version: u32, focused_surface: Mutex>, } impl Pointer { pub fn new(id: ObjectId, version: u32) -> Self { Self { id, version, focused_surface: Mutex::new(Weak::new()), } } pub async fn handle_pointer_motion( &self, client: &mut Client, surface: Arc, position: Vector2, ) -> Result<()> { tracing::debug!( "Handling pointer motion at ({}, {})", position.x, position.y ); let mut focused = self.focused_surface.lock().await; // If we're entering a new surface if focused.as_ptr() != Arc::as_ptr(&surface) { tracing::debug!("Surface transition detected"); // Send leave to old surface if it exists and is still alive if let Some(old_surface) = focused.upgrade() { let serial = client.next_event_serial(); tracing::debug!("Sending leave event with serial {}", serial); self.leave(client, self.id, serial, old_surface.id).await?; } // Send enter to new surface let serial = client.next_event_serial(); tracing::debug!( "Sending enter event with serial {} to surface {:?}", serial, surface.id ); self.enter( client, self.id, serial, surface.id, fixed_from_f32(position.x), fixed_from_f32(position.y), ) .await?; // Update focused surface *focused = Arc::downgrade(&surface); } // Send motion event to current surface tracing::debug!("Sending motion event to surface"); self.motion( client, self.id, 0, // time fixed_from_f32(position.x), fixed_from_f32(position.y), ) .await?; if self.version >= 5 { self.frame(client, self.id).await?; } Ok(()) } pub async fn handle_pointer_button( &self, client: &mut Client, surface: Arc, button: u32, pressed: bool, ) -> Result<()> { tracing::debug!( "Handling pointer button {} {} on surface {:?}", button, if pressed { "pressed" } else { "released" }, surface.id ); let serial = client.next_event_serial(); self.button( client, self.id, serial, 0, // time button, if pressed { ButtonState::Pressed } else { ButtonState::Released }, ) .await?; self.frame(client, self.id).await } pub async fn handle_pointer_scroll( &self, client: &mut Client, _surface: Arc, scroll_distance: Option>, scroll_steps: Option>, ) -> Result<()> { tracing::debug!( "Handling pointer scroll: distance={:?}, steps={:?}", scroll_distance, scroll_steps ); if let Some(distance) = scroll_distance { self.axis( client, self.id, 0, // time Axis::HorizontalScroll, fixed_from_f32(distance.x), ) .await?; self.axis( client, self.id, 0, // time Axis::VerticalScroll, fixed_from_f32(distance.y), ) .await?; } if self.version >= 5 { if let Some(steps) = scroll_steps { self.axis_discrete(client, self.id, Axis::HorizontalScroll, steps.x as i32) .await?; self.axis_discrete(client, self.id, Axis::VerticalScroll, steps.y as i32) .await?; } self.frame(client, self.id).await?; } Ok(()) } pub async fn reset(&self, client: &mut Client) -> Result<()> { let mut focused = self.focused_surface.lock().await; if let Some(old_surface) = focused.upgrade() { let serial = client.next_event_serial(); self.leave(client, self.id, serial, old_surface.id).await?; self.frame(client, self.id).await?; } *focused = Weak::new(); Ok(()) } } impl WlPointer for Pointer { /// https://wayland.app/protocols/wayland#wl_pointer:request:set_cursor async fn set_cursor( &self, _client: &mut Client, _sender_id: ObjectId, _serial: u32, _surface: Option, _hotspot_x: i32, _hotspot_y: i32, ) -> Result<()> { Ok(()) } /// https://wayland.app/protocols/wayland#wl_pointer:request:release async fn release(&self, _client: &mut Client, _sender_id: ObjectId) -> Result<()> { Ok(()) } }