feat: wayland
This commit is contained in:
183
src/wayland/core/pointer.rs
Normal file
183
src/wayland/core/pointer.rs
Normal file
@@ -0,0 +1,183 @@
|
||||
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,
|
||||
focused_surface: Mutex<Weak<Surface>>,
|
||||
}
|
||||
impl Pointer {
|
||||
pub fn new(id: ObjectId) -> Self {
|
||||
Self {
|
||||
id,
|
||||
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?;
|
||||
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 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
|
||||
}
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user