Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
protocol: add river_seat_v1.pointer_position
The motivating use case is determining window placement by relative
cursor position in the current window at the time a new window is
opened. This will certainly support other interesting use-cases as well.
protocol/river-window-management-v1.xml | 16 ++++++++++++++++
river/Seat.zig | 13 +++++++++++++
2 files changed, 29 insertions(+)
diff --git a/protocol/river-window-management-v1.xml b/protocol/river-window-management-v1.xml
index cdec753..cda16a5 100644
--- a/protocol/river-window-management-v1.xml
+++ b/protocol/river-window-management-v1.xml
@@ -1503,6 +1503,22 @@
<arg name="name" type="string"/>
<arg name="size" type="uint"/>
</request>
+
+ <event name="pointer_position" since="2">
+ <description summary="The current position of the pointer">
+ The current position of the pointer in the compositor's logical
+ coordinate space.
+
+ This state is special in that a change in pointer position alone must
+ not cause the compositor to start a manage sequence.
+
+ Assuming the seat has a pointer, this event must be sent in every manage
+ sequence unless there is no change in x/y position since the last time this
+ event was sent.
+ </description>
+ <arg name="x" type="int"/>
+ <arg name="y" type="int"/>
+ </event>
</interface>
<interface name="river_pointer_binding_v1" version="2">
diff --git a/river/Seat.zig b/river/Seat.zig
index 0fe675e..2993724 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -19,6 +19,7 @@ const Seat = @This();
const build_options = @import("build_options");
const std = @import("std");
const assert = std.debug.assert;
+const math = std.math;
const wlr = @import("wlroots");
const wayland = @import("wayland");
const wl = wayland.server.wl;
@@ -129,6 +130,8 @@ wm_scheduled: struct {
wm_sent: struct {
/// The window entered/hovered by the pointer, if any
hovered: ?Window.Ref = null,
+ x: i32 = 0,
+ y: i32 = 0,
} = .{},
link_sent: wl.list.Link,
@@ -361,6 +364,16 @@ pub fn manageStart(seat: *Seat) void {
}
}
+ {
+ const x = math.lossyCast(i32, seat.cursor.wlr_cursor.x);
+ const y = math.lossyCast(i32, seat.cursor.wlr_cursor.y);
+ if (new or x != seat.wm_sent.x or y != seat.wm_sent.y) {
+ if (seat_v1.getVersion() >= 2) {
+ seat_v1.sendPointerPosition(x, y);
+ }
+ }
+ }
+
switch (seat.wm_scheduled.interaction) {
.none => {},
.window => |ref| {