From 50ccd4c5b3cd700bed09d26eb75552f08f9af262 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Fri, 17 Nov 2023 19:48:32 +0100 Subject: [PATCH] session-lock: fix pointer focus handling on map --- river/LockManager.zig | 1 - river/LockSurface.zig | 35 +++++++++++++++++++++++++++-------- 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 {