Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
Cursor: fix DnD related assertion failure
On drag and drop end:
thread 3498 panic: reached unreachable code
/river/river/Cursor.zig:486:33: 0x1145fb2 in processButton (river)
.passthrough => unreachable,
^
/river/river/Seat.zig:269:62: 0x1132465 in processEvents (river)
.pointer_button => |ev| seat.cursor.processButton(&ev),
^
/river/river/Seat.zig:246:27: 0x1131f2e in queueEvent (river)
seat.processEvents();
^
/river/river/Cursor.zig:759:27: 0x112325c in wrapper (river)
cursor.seat.queueEvent(.{ .pointer_button = event.* }) catch {};
^
protocol/river-window-management-v1.xml | 2 +-
river/Cursor.zig | 24 ++++++++++++++++++------
river/Seat.zig | 2 +-
3 files changed, 20 insertions(+), 8 deletions(-)
diff --git a/protocol/river-window-management-v1.xml b/protocol/river-window-management-v1.xml
index 1942c9f..31a48ca 100644
--- a/protocol/river-window-management-v1.xml
+++ b/protocol/river-window-management-v1.xml
@@ -80,7 +80,7 @@
manage sequence in between, for example during interactive move/resize of
windows or if a window independently changes its own dimensions.
- To summarize the main loop of this protocol is as follows:
+ To summarize, the main loop of this protocol is as follows:
1. The server sends events indicating all changes since the last
manage sequence followed by the manage_start event.
diff --git a/river/Cursor.zig b/river/Cursor.zig
index b32f24d..997eef8 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -51,6 +51,8 @@ const Mode = union(enum) {
/// This mode is entered when a binding is triggered and exited when there
/// are no longer any buttons pressed.
ignore,
+ /// A drag and drop is in progress.
+ drag,
down: struct {
// TODO: To handle the surface with pointer focus being moved during
// down mode we need to store the starting location of the surface as
@@ -330,11 +332,11 @@ pub fn processMotionRelative(cursor: *Cursor, event: *const wlr.Pointer.event.Mo
}
switch (cursor.mode) {
- .passthrough, .ignore, .down => {
+ .passthrough, .drag, .ignore, .down => {
cursor.wlr_cursor.move(event.device, dx, dy);
switch (cursor.mode) {
- .passthrough => {
+ .passthrough, .drag => {
cursor.updateHovered();
cursor.passthrough(event.time_msec);
},
@@ -467,6 +469,16 @@ pub fn processButton(cursor: *Cursor, event: *const wlr.Pointer.event.Button) vo
cursor.clearFocus();
return;
},
+ .drag => {
+ if (server.scene.at(cursor.wlr_cursor.x, cursor.wlr_cursor.y)) |at| {
+ cursor.interact(at);
+ if (at.surface != null) {
+ _ = cursor.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state);
+ return;
+ }
+ }
+ cursor.clearFocus();
+ },
// Pointer focus does not change while in down mode.
.down => {
_ = cursor.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state);
@@ -484,8 +496,8 @@ pub fn processButton(cursor: *Cursor, event: *const wlr.Pointer.event.Button) vo
switch (cursor.mode) {
.passthrough => unreachable,
- .down, .ignore => {
- if (cursor.mode == .down) {
+ .drag, .down, .ignore => {
+ if (cursor.mode != .ignore) {
_ = cursor.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state);
}
if (cursor.pressed.count() == 0) {
@@ -699,7 +711,7 @@ pub fn updateState(cursor: *Cursor) void {
}
switch (cursor.mode) {
- .passthrough => {
+ .passthrough, .drag => {
cursor.updateHovered();
const now = posix.clock_gettime(posix.CLOCK.MONOTONIC) catch @panic("CLOCK_MONOTONIC not supported");
@@ -714,7 +726,7 @@ pub fn updateState(cursor: *Cursor) void {
/// Pass an event on to the surface under the cursor, if any.
fn passthrough(cursor: *Cursor, time: u32) void {
- assert(cursor.mode == .passthrough);
+ assert(cursor.mode == .passthrough or cursor.mode == .drag);
if (server.scene.at(cursor.wlr_cursor.x, cursor.wlr_cursor.y)) |result| {
if (result.data == .lock_surface) {
diff --git a/river/Seat.zig b/river/Seat.zig
index 8ad11a3..b2e9e0f 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -802,7 +802,7 @@ fn handleStartDrag(listener: *wl.Listener(*wlr.Drag), wlr_drag: *wlr.Drag) void
switch (wlr_drag.grab_type) {
.keyboard_pointer => {
seat.drag = .pointer;
- seat.cursor.mode = .passthrough;
+ seat.cursor.mode = .drag;
},
.keyboard_touch => seat.drag = .touch,
.keyboard => unreachable,