aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <mail@isaacfreund.com>2021-11-23 22:51:29 +0100
committerIsaac Freund <mail@isaacfreund.com>2021-11-23 22:54:19 +0100
commitbd70c010e9861df105db7cf25f57762a661873ec (patch)
treef669437f31dbfc592d6fd8abe44717fd2181ae29
parent9212ac89fa4c1a540798143a33dd3e331c31a76c (diff)
downloadriver-bd70c010e9861df105db7cf25f57762a661873ec.tar.gz
river-bd70c010e9861df105db7cf25f57762a661873ec.tar.xz
Cursor: add workaround in pointer drag termination
Currently wlroots sends use the drag destroy event before sending the wl_data_device.leave event to the client, which makes things a bit awkward. My patch fixing this has been merged to wlroots master so we can remove this when upgrading to wlroots 0.15, but until then this workaround will fix the issue.
m---------deps/zig-wayland0
-rw-r--r--river/Seat.zig23
2 files changed, 22 insertions, 1 deletions
diff --git a/deps/zig-wayland b/deps/zig-wayland
-Subproject a8e1efcfd34ac798f19d8a62ebe3bb368c17f58
+Subproject 38b5de89b3e3de670bb2496de56e5173d626fad
diff --git a/river/Seat.zig b/river/Seat.zig
index ad94fc8..8cf98c3 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -84,6 +84,7 @@ status_trackers: std.SinglyLinkedList(SeatStatus) = .{},
/// True if a pointer drag is currently in progress
pointer_drag: bool = false,
+pointer_drag_idle_source: ?*wl.EventSource = null,
request_set_selection: wl.Listener(*wlr.Seat.event.RequestSetSelection) =
wl.Listener(*wlr.Seat.event.RequestSetSelection).init(handleRequestSetSelection),
@@ -128,6 +129,8 @@ pub fn deinit(self: *Self) void {
self.focus_stack.remove(node);
util.gpa.destroy(node);
}
+
+ if (self.pointer_drag_idle_source) |idle_source| idle_source.remove();
}
/// Set the current focus. If a visible view is passed it will be focused.
@@ -476,6 +479,7 @@ fn handleStartDrag(listener: *wl.Listener(*wlr.Drag), wlr_drag: *wlr.Drag) void
if (wlr_drag.icon) |wlr_drag_icon| {
const node = util.gpa.create(std.SinglyLinkedList(DragIcon).Node) catch {
log.crit("out of memory", .{});
+ wlr_drag.seat_client.client.postNoMemory();
return;
};
node.data.init(self, wlr_drag_icon);
@@ -486,8 +490,25 @@ fn handleStartDrag(listener: *wl.Listener(*wlr.Drag), wlr_drag: *wlr.Drag) void
fn handlePointerDragDestroy(listener: *wl.Listener(*wlr.Drag), wlr_drag: *wlr.Drag) void {
const self = @fieldParentPtr(Self, "pointer_drag_destroy", listener);
- self.pointer_drag = false;
self.pointer_drag_destroy.link.remove();
+
+ // TODO(wlroots): wlroots 0.14 doesn't send the wl_data_device.leave event
+ // until after this signal has been emitted. Triggering a wl_pointer.enter
+ // before the wl_data_device.leave breaks clients, so use an idle event
+ // source as a workaround. This has been fixed on the wlroots master branch
+ // in commit c9ba9e82.
+ const event_loop = server.wl_server.getEventLoop();
+ assert(self.pointer_drag_idle_source == null);
+ self.pointer_drag_idle_source = event_loop.addIdle(*Self, finishPointerDragDestroy, self) catch {
+ log.crit("out of memory", .{});
+ wlr_drag.seat_client.client.postNoMemory();
+ return;
+ };
+}
+
+fn finishPointerDragDestroy(self: *Self) callconv(.C) void {
+ self.pointer_drag_idle_source = null;
+ self.pointer_drag = false;
self.cursor.checkFocusFollowsCursor();
self.cursor.updateState();
}