Skip to content

Commit

Permalink
Cursor: add workaround in pointer drag termination
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ifreund committed Nov 23, 2021
1 parent 9212ac8 commit bd70c01
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 2 deletions.
23 changes: 22 additions & 1 deletion river/Seat.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand All @@ -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();
}
Expand Down

0 comments on commit bd70c01

Please sign in to comment.