session-lock: fix potential race
Currently the session lock client has no 100% safe way to know when it is safe to suspend after requesting that the session be locked. For a suspend to be safe the compositor must have either blanked or rendered a lock surface on all outputs before suspending. This is because the current framebuffer on suspend appears to be saved and displayed again after suspend, at least on my Linux system. If a new "locked" frame for all outputs is not rendered before suspend, an "unlocked" frame or frames will likely be briefly displayed on resume before the lock surfaces are rendered or the screen is blanked. To fix this, wait until a lock surface has been rendered on all outputs, or if that times out until all outputs have been blanked, before sending the locked event to the client. Resolving this race on the compositor side without protocol changes is the most effective way to avoid this potential information leak, regardless of which session lock client is used.
This commit is contained in:
@ -151,7 +151,7 @@ pub fn focus(self: *Self, _target: ?*View) void {
|
||||
var target = _target;
|
||||
|
||||
// Views may not recieve focus while locked.
|
||||
if (server.lock_manager.locked) return;
|
||||
if (server.lock_manager.state != .unlocked) return;
|
||||
|
||||
// While a layer surface is focused, views may not recieve focus
|
||||
if (self.focused == .layer) return;
|
||||
@ -242,17 +242,17 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
|
||||
// Set the new focus
|
||||
switch (new_focus) {
|
||||
.view => |target_view| {
|
||||
assert(!server.lock_manager.locked);
|
||||
assert(server.lock_manager.state == .unlocked);
|
||||
assert(self.focused_output == target_view.output);
|
||||
if (target_view.pending.focus == 0) target_view.setActivated(true);
|
||||
target_view.pending.focus += 1;
|
||||
target_view.pending.urgent = false;
|
||||
},
|
||||
.layer => |target_layer| {
|
||||
assert(!server.lock_manager.locked);
|
||||
assert(server.lock_manager.state == .unlocked);
|
||||
assert(self.focused_output == target_layer.output);
|
||||
},
|
||||
.lock_surface => assert(server.lock_manager.locked),
|
||||
.lock_surface => assert(server.lock_manager.state != .unlocked),
|
||||
.xwayland_override_redirect, .none => {},
|
||||
}
|
||||
self.focused = new_focus;
|
||||
|
Reference in New Issue
Block a user