aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <mail@isaacfreund.com>2023-11-17 19:48:32 +0100
committerIsaac Freund <mail@isaacfreund.com>2023-11-17 19:51:57 +0100
commit50ccd4c5b3cd700bed09d26eb75552f08f9af262 (patch)
tree47854658e78beaab2690faa367041e9e44314e33
parent68366c733176d131c9a64d51886f8428664148a1 (diff)
downloadriver-50ccd4c5b3cd700bed09d26eb75552f08f9af262.tar.gz
river-50ccd4c5b3cd700bed09d26eb75552f08f9af262.tar.xz
session-lock: fix pointer focus handling on map
-rw-r--r--river/LockManager.zig1
-rw-r--r--river/LockSurface.zig35
2 files changed, 27 insertions, 9 deletions
diff --git a/river/LockManager.zig b/river/LockManager.zig
index 8da7778..a500260 100644
--- a/river/LockManager.zig
+++ b/river/LockManager.zig
@@ -111,7 +111,6 @@ fn handleLock(listener: *wl.Listener(*wlr.SessionLockV1), lock: *wlr.SessionLock
while (it) |node| : (it = node.next) {
const seat = &node.data;
seat.setFocusRaw(.none);
- seat.cursor.updateState();
// Enter locked mode
seat.prev_mode_id = seat.mode_id;
diff --git a/river/LockSurface.zig b/river/LockSurface.zig
index c1bbfdd..2de43ee 100644
--- a/river/LockSurface.zig
+++ b/river/LockSurface.zig
@@ -31,6 +31,8 @@ const SceneNodeData = @import("SceneNodeData.zig");
wlr_lock_surface: *wlr.SessionLockSurfaceV1,
lock: *wlr.SessionLockV1,
+idle_update_focus: ?*wl.EventSource = null,
+
output_mode: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleOutputMode),
map: wl.Listener(void) = wl.Listener(void).init(handleMap),
surface_destroy: wl.Listener(void) = wl.Listener(void).init(handleDestroy),
@@ -78,6 +80,10 @@ pub fn destroy(lock_surface: *LockSurface) void {
}
}
+ if (lock_surface.idle_update_focus) |event_source| {
+ event_source.remove();
+ }
+
lock_surface.output_mode.link.remove();
lock_surface.map.link.remove();
lock_surface.surface_destroy.link.remove();
@@ -105,16 +111,29 @@ fn handleMap(listener: *wl.Listener(void)) void {
output.normal_content.node.setEnabled(false);
output.locked_content.node.setEnabled(true);
- {
- var it = server.input_manager.seats.first;
- while (it) |node| : (it = node.next) {
- const seat = &node.data;
- if (seat.focused != .lock_surface) {
- seat.setFocusRaw(.{ .lock_surface = lock_surface });
- }
- seat.cursor.updateState();
+ // Unfortunately the surface commit handlers for the scene subsurface tree corresponding to
+ // this lock surface won't be called until after this function returns, which means that we cannot
+ // update pointer focus yet as the nodes in the scene graph representing this lock surface are still
+ // 0x0 in size. To work around this, use an idle callback.
+ const event_loop = server.wl_server.getEventLoop();
+ assert(lock_surface.idle_update_focus == null);
+ lock_surface.idle_update_focus = event_loop.addIdle(*LockSurface, updateFocus, lock_surface) catch {
+ std.log.err("out of memory", .{});
+ return;
+ };
+}
+
+fn updateFocus(lock_surface: *LockSurface) void {
+ var it = server.input_manager.seats.first;
+ while (it) |node| : (it = node.next) {
+ const seat = &node.data;
+ if (seat.focused != .lock_surface) {
+ seat.setFocusRaw(.{ .lock_surface = lock_surface });
}
+ seat.cursor.updateState();
}
+
+ lock_surface.idle_update_focus = null;
}
fn handleDestroy(listener: *wl.Listener(void)) void {