session-lock: fix pointer focus handling on map

This commit is contained in:
Isaac Freund 2023-11-17 19:48:32 +01:00
parent 68366c7331
commit 50ccd4c5b3
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
2 changed files with 27 additions and 9 deletions

View File

@ -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;

View File

@ -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 {