Root: centralize focus(null) calls in applyPending()

This commit is contained in:
Isaac Freund 2023-03-01 10:49:44 +01:00
parent 07154720fa
commit 6411c71151
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
11 changed files with 21 additions and 39 deletions

View File

@ -337,6 +337,7 @@ fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.P
server.root.applyPending(); server.root.applyPending();
} }
/// Requires a call to Root.applyPending()
fn updateKeyboardFocus(self: Self, result: Root.AtResult) void { fn updateKeyboardFocus(self: Self, result: Root.AtResult) void {
switch (result.node) { switch (result.node) {
.view => |view| { .view => |view| {
@ -348,8 +349,6 @@ fn updateKeyboardFocus(self: Self, result: Root.AtResult) void {
// give it keyboard focus. // give it keyboard focus.
if (layer_surface.wlr_layer_surface.current.keyboard_interactive != .none) { if (layer_surface.wlr_layer_surface.current.keyboard_interactive != .none) {
self.seat.setFocusRaw(.{ .layer = layer_surface }); self.seat.setFocusRaw(.{ .layer = layer_surface });
} else {
self.seat.focus(null);
} }
}, },
.lock_surface => |lock_surface| { .lock_surface => |lock_surface| {
@ -364,11 +363,11 @@ fn updateKeyboardFocus(self: Self, result: Root.AtResult) void {
} }
/// Focus the output at the given layout coordinates, if any /// Focus the output at the given layout coordinates, if any
/// Requires a call to Root.applyPending()
fn updateOutputFocus(self: Self, lx: f64, ly: f64) void { fn updateOutputFocus(self: Self, lx: f64, ly: f64) void {
if (server.root.output_layout.outputAt(lx, ly)) |wlr_output| { if (server.root.output_layout.outputAt(lx, ly)) |wlr_output| {
const output = @intToPtr(*Output, wlr_output.data); const output = @intToPtr(*Output, wlr_output.data);
self.seat.focusOutput(output); self.seat.focusOutput(output);
self.seat.focus(null);
} }
} }

View File

@ -134,6 +134,7 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
} }
} }
/// Requires a call to Root.applyPending()
fn handleKeyboardInteractiveExclusive(output: *Output) void { fn handleKeyboardInteractiveExclusive(output: *Output) void {
if (server.lock_manager.state != .unlocked) return; if (server.lock_manager.state != .unlocked) return;
@ -174,7 +175,6 @@ fn handleKeyboardInteractiveExclusive(output: *Output) void {
// without keyboard interactivity, stop focusing that layer surface. // without keyboard interactivity, stop focusing that layer surface.
if (!current_focus.mapped or current_focus.current.keyboard_interactive == .none) { if (!current_focus.mapped or current_focus.current.keyboard_interactive == .none) {
seat.setFocusRaw(.{ .none = {} }); seat.setFocusRaw(.{ .none = {} });
seat.focus(null);
} }
} }
} }

View File

@ -223,8 +223,6 @@ fn handleUnlock(listener: *wl.Listener(void)) void {
while (it) |node| : (it = node.next) { while (it) |node| : (it = node.next) {
const seat = &node.data; const seat = &node.data;
seat.setFocusRaw(.none); seat.setFocusRaw(.none);
seat.focus(null);
seat.cursor.updateState();
// Exit locked mode // Exit locked mode
seat.enterMode(seat.prev_mode_id); seat.enterMode(seat.prev_mode_id);
@ -232,6 +230,8 @@ fn handleUnlock(listener: *wl.Listener(void)) void {
} }
handleDestroy(&manager.destroy); handleDestroy(&manager.destroy);
server.root.applyPending();
} }
fn handleDestroy(listener: *wl.Listener(void)) void { fn handleDestroy(listener: *wl.Listener(void)) void {

View File

@ -293,6 +293,7 @@ pub fn layerSurfaceTree(self: Self, layer: zwlr.LayerShellV1.Layer) *wlr.SceneTr
/// Arrange all layer surfaces of this output and adjust the usable area. /// Arrange all layer surfaces of this output and adjust the usable area.
/// Will arrange views as well if the usable area changes. /// Will arrange views as well if the usable area changes.
/// Requires a call to Root.applyPending()
pub fn arrangeLayers(self: *Self) void { pub fn arrangeLayers(self: *Self) void {
var full_box: wlr.Box = .{ var full_box: wlr.Box = .{
.x = 0, .x = 0,

View File

@ -294,7 +294,6 @@ pub fn removeOutput(root: *Self, output: *Output) void {
const seat = &seat_node.data; const seat = &seat_node.data;
if (seat.focused_output == output) { if (seat.focused_output == output) {
seat.focusOutput(fallback_output); seat.focusOutput(fallback_output);
seat.focus(null);
} }
} }
@ -340,7 +339,6 @@ pub fn addOutput(root: *Self, output: *Output) void {
while (it) |seat_node| : (it = seat_node.next) { while (it) |seat_node| : (it = seat_node.next) {
const seat = &seat_node.data; const seat = &seat_node.data;
seat.focusOutput(output); seat.focusOutput(output);
seat.focus(null);
} }
} }
root.applyPending(); root.applyPending();
@ -352,6 +350,15 @@ pub fn addOutput(root: *Self, output: *Output) void {
/// generates a new layout for all outputs and all affected clients ack a /// generates a new layout for all outputs and all affected clients ack a
/// configure and commit a new buffer. /// configure and commit a new buffer.
pub fn applyPending(root: *Self) void { pub fn applyPending(root: *Self) void {
{
// Changes to the pending state may require a focus update to keep
// state consistent. Instead of having focus(null) calls spread all
// around the codebase and risk forgetting one, always ensure focus
// state is synchronized here.
var it = server.input_manager.seats.first;
while (it) |node| : (it = node.next) node.data.focus(null);
}
// If there is already a transaction inflight, wait until it completes. // If there is already a transaction inflight, wait until it completes.
if (root.inflight_layout_demands > 0 or root.inflight_configures > 0) { if (root.inflight_layout_demands > 0 or root.inflight_configures > 0) {
root.pending_state_dirty = true; root.pending_state_dirty = true;

View File

@ -138,6 +138,7 @@ pub fn deinit(self: *Self) void {
/// Set the current focus. If a visible view is passed it will be focused. /// Set the current focus. If a visible view is passed it will be focused.
/// If null is passed, the top view in the stack of the focused output will be focused. /// If null is passed, the top view in the stack of the focused output will be focused.
/// Requires a call to Root.applyPending()
pub fn focus(self: *Self, _target: ?*View) void { pub fn focus(self: *Self, _target: ?*View) void {
var target = _target; var target = _target;

View File

@ -478,16 +478,6 @@ pub fn unmap(view: *Self) void {
server.root.hidden.pending.wm_stack.prepend(view); server.root.hidden.pending.wm_stack.prepend(view);
} }
{
var it = server.input_manager.seats.first;
while (it) |node| : (it = node.next) {
const seat = &node.data;
if (seat.focused == .view and seat.focused.view == view) {
seat.focus(null);
}
}
}
view.request_activate.link.remove(); view.request_activate.link.remove();
server.root.applyPending(); server.root.applyPending();

View File

@ -138,15 +138,11 @@ fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSur
var seat_it = server.input_manager.seats.first; var seat_it = server.input_manager.seats.first;
while (seat_it) |seat_node| : (seat_it = seat_node.next) { while (seat_it) |seat_node| : (seat_it = seat_node.next) {
const seat = &seat_node.data; const seat = &seat_node.data;
switch (seat.focused) { if (seat.focused == .view and seat.focused.view.impl == .xwayland_view and
.view => |focused| if (focused.impl == .xwayland_view and seat.focused.view.impl.xwayland_view.xwayland_surface.pid == self.xwayland_surface.pid and
focused.impl.xwayland_view.xwayland_surface.pid == self.xwayland_surface.pid and
seat.wlr_seat.keyboard_state.focused_surface == self.xwayland_surface.surface) seat.wlr_seat.keyboard_state.focused_surface == self.xwayland_surface.surface)
{ {
seat.keyboardEnterOrLeave(focused.rootSurface()); seat.keyboardEnterOrLeave(seat.focused.view.rootSurface());
},
.xwayland_override_redirect => |focused| if (focused == self) seat.focus(null),
.layer, .lock_surface, .none => {},
} }
} }

View File

@ -43,7 +43,6 @@ pub fn focusOutput(
} }
seat.focusOutput((try getOutput(seat, args[1])) orelse return); seat.focusOutput((try getOutput(seat, args[1])) orelse return);
seat.focus(null);
server.root.applyPending(); server.root.applyPending();
} }
@ -68,8 +67,6 @@ pub fn sendToOutput(
if (seat.focused.view.pending.output == destination_output) return; if (seat.focused.view.pending.output == destination_output) return;
seat.focused.view.setPendingOutput(destination_output); seat.focused.view.setPendingOutput(destination_output);
// Handle the change and focus whatever's next in the focus stack
seat.focus(null);
server.root.applyPending(); server.root.applyPending();
} }
} }

View File

@ -34,7 +34,6 @@ pub fn setFocusedTags(
if (output.pending.tags != tags) { if (output.pending.tags != tags) {
output.previous_tags = output.pending.tags; output.previous_tags = output.pending.tags;
output.pending.tags = tags; output.pending.tags = tags;
seat.focus(null);
server.root.applyPending(); server.root.applyPending();
} }
} }
@ -58,7 +57,6 @@ pub fn setViewTags(
if (seat.focused == .view) { if (seat.focused == .view) {
const view = seat.focused.view; const view = seat.focused.view;
view.pending.tags = tags; view.pending.tags = tags;
seat.focus(null);
server.root.applyPending(); server.root.applyPending();
} }
} }
@ -75,7 +73,6 @@ pub fn toggleFocusedTags(
if (new_focused_tags != 0) { if (new_focused_tags != 0) {
output.previous_tags = output.pending.tags; output.previous_tags = output.pending.tags;
output.pending.tags = new_focused_tags; output.pending.tags = new_focused_tags;
seat.focus(null);
server.root.applyPending(); server.root.applyPending();
} }
} }
@ -92,7 +89,6 @@ pub fn toggleViewTags(
if (new_tags != 0) { if (new_tags != 0) {
const view = seat.focused.view; const view = seat.focused.view;
view.pending.tags = new_tags; view.pending.tags = new_tags;
seat.focus(null);
server.root.applyPending(); server.root.applyPending();
} }
} }
@ -110,7 +106,6 @@ pub fn focusPreviousTags(
if (output.pending.tags != previous_tags) { if (output.pending.tags != previous_tags) {
output.previous_tags = output.pending.tags; output.previous_tags = output.pending.tags;
output.pending.tags = previous_tags; output.pending.tags = previous_tags;
seat.focus(null);
server.root.applyPending(); server.root.applyPending();
} }
} }
@ -127,7 +122,6 @@ pub fn sendToPreviousTags(
if (seat.focused == .view) { if (seat.focused == .view) {
const view = seat.focused.view; const view = seat.focused.view;
view.pending.tags = output.previous_tags; view.pending.tags = output.previous_tags;
seat.focus(null);
server.root.applyPending(); server.root.applyPending();
} }
} }

View File

@ -33,9 +33,6 @@ pub fn toggleFullscreen(
const view = seat.focused.view; const view = seat.focused.view;
view.pending.fullscreen = !view.pending.fullscreen; view.pending.fullscreen = !view.pending.fullscreen;
// It is possible to end up with multiple fullscreen views in which
// case making one non-fullscreen should switch focus to the next.
seat.focus(null);
server.root.applyPending(); server.root.applyPending();
} }
} }