Skip to content

Commit a10b070

Browse files
committed
feat(wayland): relative pointer
1 parent ce2e025 commit a10b070

File tree

9 files changed

+178
-23
lines changed

9 files changed

+178
-23
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ waynest = { git = "https://github.com/verdiwm/waynest.git", default-features = f
144144
waynest-protocols = { git = "https://github.com/verdiwm/waynest.git", features = [
145145
"server",
146146
"stable",
147+
"unstable",
147148
"mesa",
148149
"tracing",
149150
], default-features = false, optional = true }

src/nodes/items/panel.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ pub trait Backend: Send + Sync + 'static {
6868
fn set_toplevel_size(&self, size: Vector2<u32>);
6969
fn set_toplevel_focused_visuals(&self, focused: bool);
7070

71-
fn pointer_motion(&self, surface: &SurfaceId, position: Vector2<f32>);
71+
fn absolute_pointer_motion(&self, surface: &SurfaceId, position: Vector2<f32>);
72+
fn relative_pointer_motion(&self, surface: &SurfaceId, delta: Vector2<f32>);
7273
fn pointer_button(&self, surface: &SurfaceId, button: u32, pressed: bool);
7374
fn pointer_scroll(
7475
&self,
@@ -297,7 +298,7 @@ impl<B: Backend> PanelItemAspect for PanelItem<B> {
297298
}
298299

299300
#[doc = "Send an event to set the pointer's position (in pixels, relative to top-left of surface). This will activate the pointer."]
300-
fn pointer_motion(
301+
fn absolute_pointer_motion(
301302
node: Arc<Node>,
302303
_calling_client: Arc<Client>,
303304
surface: SurfaceId,
@@ -306,7 +307,25 @@ impl<B: Backend> PanelItemAspect for PanelItem<B> {
306307
let Some(panel_item) = panel_item_from_node(&node) else {
307308
return Ok(());
308309
};
309-
panel_item.backend().pointer_motion(&surface, position);
310+
panel_item
311+
.backend()
312+
.absolute_pointer_motion(&surface, position);
313+
Ok(())
314+
}
315+
316+
#[doc = "Send an event that the pointer moved a relative amount (in pixels)."]
317+
fn relative_pointer_motion(
318+
node: Arc<Node>,
319+
_calling_client: Arc<Client>,
320+
surface: SurfaceId,
321+
delta: Vector2<f32>,
322+
) -> Result<()> {
323+
let Some(panel_item) = panel_item_from_node(&node) else {
324+
return Ok(());
325+
};
326+
panel_item
327+
.backend()
328+
.relative_pointer_motion(&surface, delta);
310329
Ok(())
311330
}
312331

src/wayland/core/pointer.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
use super::surface::SurfaceRole;
22
use crate::nodes::items::panel::Geometry;
33
use crate::wayland::core::surface::Surface;
4+
use crate::wayland::relative_pointer::RelativePointer;
45
use crate::wayland::{Client, WaylandResult};
56
use mint::Vector2;
67
use std::sync::Arc;
78
use std::sync::Weak;
8-
use tokio::sync::Mutex;
9+
use tokio::sync::{Mutex, RwLock};
910
use tracing;
1011
use waynest::ObjectId;
1112
use waynest_server::Client as _;
@@ -19,6 +20,7 @@ pub struct Pointer {
1920
version: u32,
2021
focused_surface: Mutex<Weak<Surface>>,
2122
cursor_surface: Mutex<Option<Arc<Surface>>>,
23+
pub relative_pointer: RwLock<Weak<RelativePointer>>,
2224
}
2325
impl Pointer {
2426
pub fn new(id: ObjectId, version: u32) -> Self {
@@ -27,17 +29,18 @@ impl Pointer {
2729
version,
2830
focused_surface: Mutex::new(Weak::new()),
2931
cursor_surface: Mutex::new(None),
32+
relative_pointer: RwLock::new(Weak::new()),
3033
}
3134
}
3235

33-
pub async fn handle_pointer_motion(
36+
pub async fn handle_absolute_pointer_motion(
3437
&self,
3538
client: &mut Client,
3639
surface: Arc<Surface>,
3740
position: Vector2<f32>,
3841
) -> WaylandResult<()> {
3942
tracing::debug!(
40-
"Handling pointer motion at ({}, {})",
43+
"Handling absolute pointer motion at ({}, {})",
4144
position.x,
4245
position.y
4346
);
@@ -91,6 +94,24 @@ impl Pointer {
9194
Ok(())
9295
}
9396

97+
pub async fn handle_relative_pointer_motion(
98+
&self,
99+
client: &mut Client,
100+
delta: Vector2<f32>,
101+
) -> WaylandResult<()> {
102+
tracing::debug!(
103+
"Handling relative pointer motion of ({}, {})",
104+
delta.x,
105+
delta.y
106+
);
107+
108+
let Some(relative_pointer) = self.relative_pointer.read().await.upgrade() else {
109+
return Ok(());
110+
};
111+
112+
relative_pointer.send_relative_motion(client, delta).await
113+
}
114+
94115
pub async fn handle_pointer_button(
95116
&self,
96117
client: &mut Client,

src/wayland/core/seat.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ use waynest_server::Client as _;
1111

1212
#[derive(Debug)]
1313
pub enum SeatMessage {
14-
PointerMotion {
14+
AbsolutePointerMotion {
1515
surface: Arc<Surface>,
1616
position: Vector2<f32>,
1717
},
18+
RelativePointerMotion {
19+
delta: Vector2<f32>,
20+
},
1821
PointerButton {
1922
surface: Arc<Surface>,
2023
button: u32,
@@ -82,10 +85,17 @@ impl Seat {
8285
message: SeatMessage,
8386
) -> WaylandResult<()> {
8487
match message {
85-
SeatMessage::PointerMotion { surface, position } => {
88+
SeatMessage::AbsolutePointerMotion { surface, position } => {
89+
if let Some(pointer) = self.pointer.get() {
90+
pointer
91+
.handle_absolute_pointer_motion(client, surface, position)
92+
.await?;
93+
}
94+
}
95+
SeatMessage::RelativePointerMotion { delta } => {
8696
if let Some(pointer) = self.pointer.get() {
8797
pointer
88-
.handle_pointer_motion(client, surface, position)
98+
.handle_relative_pointer_motion(client, delta)
8999
.await?;
90100
}
91101
}

src/wayland/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod dmabuf;
44
mod mesa_drm;
55
mod presentation;
66
mod registry;
7+
mod relative_pointer;
78
mod util;
89
mod viewporter;
910
mod vulkano_data;

src/wayland/registry.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::wayland::relative_pointer::RelativePointerManager;
12
use crate::wayland::{Client, WaylandResult};
23
use crate::wayland::{
34
WaylandError,
@@ -24,6 +25,7 @@ use waynest_protocols::server::{
2425
presentation_time::wp_presentation::WpPresentation,
2526
viewporter::wp_viewporter::WpViewporter,
2627
},
28+
unstable::relative_pointer_unstable_v1::zwp_relative_pointer_manager_v1::ZwpRelativePointerManagerV1,
2729
};
2830
use waynest_server::Client as _;
2931

@@ -39,6 +41,7 @@ impl RegistryGlobals {
3941
pub const WL_DRM: u32 = 7;
4042
pub const PRESENTATION: u32 = 8;
4143
pub const VIEWPORTER: u32 = 9;
44+
pub const RELATIVE_POINTER: u32 = 10;
4245
}
4346

4447
#[derive(Debug, waynest_server::RequestDispatcher, Default)]
@@ -141,6 +144,15 @@ impl Registry {
141144
)
142145
.await?;
143146

147+
self.global(
148+
client,
149+
sender_id,
150+
RegistryGlobals::RELATIVE_POINTER,
151+
RelativePointerManager::INTERFACE.to_string(),
152+
RelativePointerManager::VERSION,
153+
)
154+
.await?;
155+
144156
Ok(())
145157
}
146158
}
@@ -225,6 +237,11 @@ impl WlRegistry for Registry {
225237

226238
client.insert(new_id.object_id, Viewporter::new(new_id.object_id))?;
227239
}
240+
RegistryGlobals::RELATIVE_POINTER => {
241+
tracing::info!("Binding zwp_relative_pointer_manager_v1");
242+
243+
client.insert(new_id.object_id, RelativePointerManager(new_id.object_id))?;
244+
}
228245
id => {
229246
tracing::error!(id, "Wayland: failed to bind to registry global");
230247
return Err(WaylandError::UnknownGlobal(name));

src/wayland/relative_pointer.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use crate::wayland::{WaylandError, WaylandResult, core::pointer::Pointer};
2+
use mint::Vector2;
3+
use std::sync::Arc;
4+
use waynest::ObjectId;
5+
use waynest_protocols::server::unstable::relative_pointer_unstable_v1::{
6+
zwp_relative_pointer_manager_v1::*, zwp_relative_pointer_v1::*,
7+
};
8+
use waynest_server::Client as _;
9+
10+
#[derive(Debug, waynest_server::RequestDispatcher)]
11+
#[waynest(error = crate::wayland::WaylandError, connection = crate::wayland::Client)]
12+
pub struct RelativePointerManager(pub ObjectId);
13+
impl ZwpRelativePointerManagerV1 for RelativePointerManager {
14+
type Connection = crate::wayland::Client;
15+
16+
async fn destroy(
17+
&self,
18+
client: &mut Self::Connection,
19+
_sender_id: ObjectId,
20+
) -> WaylandResult<()> {
21+
client.remove(self.0);
22+
Ok(())
23+
}
24+
25+
async fn get_relative_pointer(
26+
&self,
27+
client: &mut Self::Connection,
28+
_sender_id: ObjectId,
29+
id: ObjectId,
30+
pointer: ObjectId,
31+
) -> WaylandResult<()> {
32+
let Some(pointer) = client.get::<Pointer>(pointer) else {
33+
return Err(WaylandError::MissingObject(pointer));
34+
};
35+
36+
let relative_pointer = client.insert(id, RelativePointer(id))?;
37+
38+
*pointer.relative_pointer.write().await = Arc::downgrade(&relative_pointer);
39+
40+
Ok(())
41+
}
42+
}
43+
44+
#[derive(Debug, waynest_server::RequestDispatcher)]
45+
#[waynest(error = crate::wayland::WaylandError, connection = crate::wayland::Client)]
46+
pub struct RelativePointer(pub ObjectId);
47+
impl RelativePointer {
48+
pub async fn send_relative_motion(
49+
&self,
50+
client: &mut crate::wayland::Client,
51+
delta: Vector2<f32>,
52+
) -> WaylandResult<()> {
53+
self.relative_motion(
54+
client,
55+
self.0,
56+
0,
57+
0,
58+
(delta.x as f64).into(),
59+
(delta.y as f64).into(),
60+
(delta.x as f64).into(),
61+
(delta.y as f64).into(),
62+
)
63+
.await
64+
}
65+
}
66+
impl ZwpRelativePointerV1 for RelativePointer {
67+
type Connection = crate::wayland::Client;
68+
69+
async fn destroy(
70+
&self,
71+
client: &mut Self::Connection,
72+
_sender_id: ObjectId,
73+
) -> WaylandResult<()> {
74+
client.remove(self.0);
75+
Ok(())
76+
}
77+
}

src/wayland/xdg/backend.rs

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -191,17 +191,26 @@ impl Backend for XdgBackend {
191191
});
192192
}
193193

194-
fn pointer_motion(&self, surface: &SurfaceId, position: Vector2<f32>) {
195-
if let Some(surface) = self.surface_from_id(surface) {
196-
let _ = self
197-
.toplevel()
198-
.wl_surface()
199-
.message_sink
200-
.send(Message::Seat(SeatMessage::PointerMotion {
201-
surface,
202-
position,
203-
}));
204-
}
194+
fn absolute_pointer_motion(&self, surface: &SurfaceId, position: Vector2<f32>) {
195+
let Some(surface) = self.surface_from_id(surface) else {
196+
return;
197+
};
198+
let _ = self
199+
.toplevel()
200+
.wl_surface()
201+
.message_sink
202+
.send(Message::Seat(SeatMessage::AbsolutePointerMotion {
203+
surface,
204+
position,
205+
}));
206+
}
207+
208+
fn relative_pointer_motion(&self, _surface: &SurfaceId, delta: Vector2<f32>) {
209+
let _ = self
210+
.toplevel()
211+
.wl_surface()
212+
.message_sink
213+
.send(Message::Seat(SeatMessage::RelativePointerMotion { delta }));
205214
}
206215

207216
fn pointer_button(&self, surface: &SurfaceId, button: u32, pressed: bool) {

0 commit comments

Comments
 (0)