191 lines
4.2 KiB
Rust
191 lines
4.2 KiB
Rust
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<Weak<Surface>>,
|
|
}
|
|
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<Surface>,
|
|
position: Vector2<f32>,
|
|
) -> 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<Surface>,
|
|
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<Surface>,
|
|
scroll_distance: Option<Vector2<f32>>,
|
|
scroll_steps: Option<Vector2<f32>>,
|
|
) -> 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<ObjectId>,
|
|
_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(())
|
|
}
|
|
}
|