aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <mail@isaacfreund.com>2023-03-01 10:49:44 +0100
committerIsaac Freund <mail@isaacfreund.com>2023-03-01 10:49:44 +0100
commit6411c71151b206876a71d923cbaf15d5388dbb0b (patch)
tree86aeab6bf0bc7f162e7531dc0166d07d6c79705f
parent07154720fa81c5ef12e28bc4ec9632657a431c9e (diff)
downloadriver-6411c71151b206876a71d923cbaf15d5388dbb0b.tar.gz
river-6411c71151b206876a71d923cbaf15d5388dbb0b.tar.xz
Root: centralize focus(null) calls in applyPending()
-rw-r--r--river/Cursor.zig5
-rw-r--r--river/LayerSurface.zig2
-rw-r--r--river/LockManager.zig4
-rw-r--r--river/Output.zig1
-rw-r--r--river/Root.zig11
-rw-r--r--river/Seat.zig1
-rw-r--r--river/View.zig10
-rw-r--r--river/XwaylandOverrideRedirect.zig14
-rw-r--r--river/command/output.zig3
-rw-r--r--river/command/tags.zig6
-rw-r--r--river/command/toggle_fullscreen.zig3
11 files changed, 21 insertions, 39 deletions
diff --git a/river/Cursor.zig b/river/Cursor.zig
index 84cda6a..829afe7 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -337,6 +337,7 @@ fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.P
server.root.applyPending();
}
+/// Requires a call to Root.applyPending()
fn updateKeyboardFocus(self: Self, result: Root.AtResult) void {
switch (result.node) {
.view => |view| {
@@ -348,8 +349,6 @@ fn updateKeyboardFocus(self: Self, result: Root.AtResult) void {
// give it keyboard focus.
if (layer_surface.wlr_layer_surface.current.keyboard_interactive != .none) {
self.seat.setFocusRaw(.{ .layer = layer_surface });
- } else {
- self.seat.focus(null);
}
},
.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
+/// Requires a call to Root.applyPending()
fn updateOutputFocus(self: Self, lx: f64, ly: f64) void {
if (server.root.output_layout.outputAt(lx, ly)) |wlr_output| {
const output = @intToPtr(*Output, wlr_output.data);
self.seat.focusOutput(output);
- self.seat.focus(null);
}
}
diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig
index b3cdec3..fd294f2 100644
--- a/river/LayerSurface.zig
+++ b/river/LayerSurface.zig
@@ -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 {
if (server.lock_manager.state != .unlocked) return;
@@ -174,7 +175,6 @@ fn handleKeyboardInteractiveExclusive(output: *Output) void {
// without keyboard interactivity, stop focusing that layer surface.
if (!current_focus.mapped or current_focus.current.keyboard_interactive == .none) {
seat.setFocusRaw(.{ .none = {} });
- seat.focus(null);
}
}
}
diff --git a/river/LockManager.zig b/river/LockManager.zig
index 9757d93..e5467ac 100644
--- a/river/LockManager.zig
+++ b/river/LockManager.zig
@@ -223,8 +223,6 @@ fn handleUnlock(listener: *wl.Listener(void)) void {
while (it) |node| : (it = node.next) {
const seat = &node.data;
seat.setFocusRaw(.none);
- seat.focus(null);
- seat.cursor.updateState();
// Exit locked mode
seat.enterMode(seat.prev_mode_id);
@@ -232,6 +230,8 @@ fn handleUnlock(listener: *wl.Listener(void)) void {
}
handleDestroy(&manager.destroy);
+
+ server.root.applyPending();
}
fn handleDestroy(listener: *wl.Listener(void)) void {
diff --git a/river/Output.zig b/river/Output.zig
index adbded4..95dde75 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -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.
/// Will arrange views as well if the usable area changes.
+/// Requires a call to Root.applyPending()
pub fn arrangeLayers(self: *Self) void {
var full_box: wlr.Box = .{
.x = 0,
diff --git a/river/Root.zig b/river/Root.zig
index 4f08d38..7603705 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -294,7 +294,6 @@ pub fn removeOutput(root: *Self, output: *Output) void {
const seat = &seat_node.data;
if (seat.focused_output == 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) {
const seat = &seat_node.data;
seat.focusOutput(output);
- seat.focus(null);
}
}
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
/// configure and commit a new buffer.
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 (root.inflight_layout_demands > 0 or root.inflight_configures > 0) {
root.pending_state_dirty = true;
diff --git a/river/Seat.zig b/river/Seat.zig
index d3c22d9..802a5ce 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -138,6 +138,7 @@ pub fn deinit(self: *Self) void {
/// 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.
+/// Requires a call to Root.applyPending()
pub fn focus(self: *Self, _target: ?*View) void {
var target = _target;
diff --git a/river/View.zig b/river/View.zig
index 399dcdd..45d8906 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -478,16 +478,6 @@ pub fn unmap(view: *Self) void {
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();
server.root.applyPending();
diff --git a/river/XwaylandOverrideRedirect.zig b/river/XwaylandOverrideRedirect.zig
index e87ce77..cb0686a 100644
--- a/river/XwaylandOverrideRedirect.zig
+++ b/river/XwaylandOverrideRedirect.zig
@@ -138,15 +138,11 @@ fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSur
var seat_it = server.input_manager.seats.first;
while (seat_it) |seat_node| : (seat_it = seat_node.next) {
const seat = &seat_node.data;
- switch (seat.focused) {
- .view => |focused| if (focused.impl == .xwayland_view 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.keyboardEnterOrLeave(focused.rootSurface());
- },
- .xwayland_override_redirect => |focused| if (focused == self) seat.focus(null),
- .layer, .lock_surface, .none => {},
+ if (seat.focused == .view and seat.focused.view.impl == .xwayland_view and
+ seat.focused.view.impl.xwayland_view.xwayland_surface.pid == self.xwayland_surface.pid and
+ seat.wlr_seat.keyboard_state.focused_surface == self.xwayland_surface.surface)
+ {
+ seat.keyboardEnterOrLeave(seat.focused.view.rootSurface());
}
}
diff --git a/river/command/output.zig b/river/command/output.zig
index dc72323..64d021e 100644
--- a/river/command/output.zig
+++ b/river/command/output.zig
@@ -43,7 +43,6 @@ pub fn focusOutput(
}
seat.focusOutput((try getOutput(seat, args[1])) orelse return);
- seat.focus(null);
server.root.applyPending();
}
@@ -68,8 +67,6 @@ pub fn sendToOutput(
if (seat.focused.view.pending.output == destination_output) return;
seat.focused.view.setPendingOutput(destination_output);
- // Handle the change and focus whatever's next in the focus stack
- seat.focus(null);
server.root.applyPending();
}
}
diff --git a/river/command/tags.zig b/river/command/tags.zig
index 3eac000..d1ac8da 100644
--- a/river/command/tags.zig
+++ b/river/command/tags.zig
@@ -34,7 +34,6 @@ pub fn setFocusedTags(
if (output.pending.tags != tags) {
output.previous_tags = output.pending.tags;
output.pending.tags = tags;
- seat.focus(null);
server.root.applyPending();
}
}
@@ -58,7 +57,6 @@ pub fn setViewTags(
if (seat.focused == .view) {
const view = seat.focused.view;
view.pending.tags = tags;
- seat.focus(null);
server.root.applyPending();
}
}
@@ -75,7 +73,6 @@ pub fn toggleFocusedTags(
if (new_focused_tags != 0) {
output.previous_tags = output.pending.tags;
output.pending.tags = new_focused_tags;
- seat.focus(null);
server.root.applyPending();
}
}
@@ -92,7 +89,6 @@ pub fn toggleViewTags(
if (new_tags != 0) {
const view = seat.focused.view;
view.pending.tags = new_tags;
- seat.focus(null);
server.root.applyPending();
}
}
@@ -110,7 +106,6 @@ pub fn focusPreviousTags(
if (output.pending.tags != previous_tags) {
output.previous_tags = output.pending.tags;
output.pending.tags = previous_tags;
- seat.focus(null);
server.root.applyPending();
}
}
@@ -127,7 +122,6 @@ pub fn sendToPreviousTags(
if (seat.focused == .view) {
const view = seat.focused.view;
view.pending.tags = output.previous_tags;
- seat.focus(null);
server.root.applyPending();
}
}
diff --git a/river/command/toggle_fullscreen.zig b/river/command/toggle_fullscreen.zig
index 402cce3..5dfef41 100644
--- a/river/command/toggle_fullscreen.zig
+++ b/river/command/toggle_fullscreen.zig
@@ -33,9 +33,6 @@ pub fn toggleFullscreen(
const view = seat.focused.view;
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();
}
}