From 7a6ac8eb6e57ca8eb821ffb798a76348f264c9b2 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Wed, 12 Aug 2020 11:07:29 +0200 Subject: [PATCH] seat: set focus before starting transactions Focus was made double-buffered in 96a91fd. However, much of the code still behaved as if focus was separate from the transaction system. This commit completes the work started in 96a91fd and ensures that focus is applied consistently in a single transaction. --- river/Cursor.zig | 9 ++++++--- river/InputManager.zig | 2 ++ river/LayerSurface.zig | 3 +++ river/Output.zig | 6 ++---- river/Root.zig | 4 ---- river/Seat.zig | 13 +++++-------- river/View.zig | 10 +++++----- river/command/focus_view.zig | 2 ++ river/command/tags.zig | 16 +++++++++++----- 9 files changed, 36 insertions(+), 29 deletions(-) diff --git a/river/Cursor.zig b/river/Cursor.zig index 626e988..d2a2e17 100644 --- a/river/Cursor.zig +++ b/river/Cursor.zig @@ -48,9 +48,14 @@ const Mode = union(enum) { fn enter(self: *Self, mode: @TagType(Mode), event: *c.wlr_event_pointer_button, view: *View) void { log.debug(.cursor, "enter {} mode", .{@tagName(mode)}); + self.seat.focus(view); + switch (mode) { .passthrough => unreachable, - .down => self.mode = .{ .down = view }, + .down => { + self.mode = .{ .down = view }; + view.output.root.startTransaction(); + }, .move, .resize => { const cur_box = &view.current.box; self.mode = switch (mode) { @@ -366,8 +371,6 @@ fn handleButton(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { // If the target surface has a view, give that view keyboard focus and // perhaps enter move/resize mode. if (View.fromWlrSurface(wlr_surface)) |view| { - self.seat.focus(view); - if (event.state == .WLR_BUTTON_PRESSED and self.pressed_count == 1) { // If the button is pressed and the pointer modifier is // active, enter cursor mode or close view and return. diff --git a/river/InputManager.zig b/river/InputManager.zig index ab6dda4..ea79db8 100644 --- a/river/InputManager.zig +++ b/river/InputManager.zig @@ -149,6 +149,8 @@ fn handleInhibitDeactivate(listener: ?*c.wl_listener, data: ?*c_void) callconv(. while (seat_it) |seat_node| : (seat_it = seat_node.next) { seat_node.data.focus(null); } + + self.server.root.startTransaction(); } /// This event is raised by the backend when a new input device becomes available. diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig index 1f5971f..e8ce1fc 100644 --- a/river/LayerSurface.zig +++ b/river/LayerSurface.zig @@ -154,6 +154,8 @@ fn handleUnmap(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const seat = &node.data; seat.focus(null); } + + self.output.root.startTransaction(); } fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { @@ -181,6 +183,7 @@ fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { // TODO: only reconfigure if things haven't changed // https://github.com/swaywm/wlroots/issues/1079 self.output.arrangeLayers(); + self.output.root.startTransaction(); } fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { diff --git a/river/Output.zig b/river/Output.zig index a7f400d..a62c724 100644 --- a/river/Output.zig +++ b/river/Output.zig @@ -304,7 +304,7 @@ pub fn arrangeViews(self: *Self) void { var it = ViewStack(View).pendingIterator(self.views.first, self.pending.tags); while (it.next()) |node| { const view = &node.view; - if (!view.pending.float) layout_count += 1; + if (!view.pending.float and !view.pending.fullscreen) layout_count += 1; } // If the usable area has a zero dimension, trying to arrange the layout @@ -394,8 +394,6 @@ pub fn arrangeLayers(self: *Self) void { } } } - - self.root.startTransaction(); } /// Arrange the layer surfaces of a given layer @@ -585,7 +583,7 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { while (seat_it) |seat_node| : (seat_it = seat_node.next) { const seat = &seat_node.data; if (seat.focused_output == self) { - seat.focusOutput(self); + seat.focusOutput(fallback_output); seat.focus(null); } } diff --git a/river/Root.zig b/river/Root.zig index 2fb1a9f..03ab9b3 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -241,8 +241,4 @@ fn commitTransaction(self: *Self) void { if (view_tags_changed) output.sendViewTags(); } - - // Iterate over all seats and update focus - var it = self.server.input_manager.seats.first; - while (it) |seat_node| : (it = seat_node.next) seat_node.data.focus(null); } diff --git a/river/Seat.zig b/river/Seat.zig index 52aae7c..d988610 100644 --- a/river/Seat.zig +++ b/river/Seat.zig @@ -120,21 +120,21 @@ pub fn focus(self: *Self, _view: ?*View) void { // If the view is not currently visible, behave as if null was passed if (view) |v| { if (v.output != self.focused_output or - v.current.tags & self.focused_output.current.tags == 0) view = null; + v.pending.tags & self.focused_output.pending.tags == 0) view = null; } // If the target view is not fullscreen or null, then a fullscreen view // will grab focus if visible. - if (if (view) |v| !v.current.fullscreen else true) { - var it = ViewStack(*View).iterator(self.focus_stack.first, self.focused_output.current.tags); + if (if (view) |v| !v.pending.fullscreen else true) { + var it = ViewStack(*View).pendingIterator(self.focus_stack.first, self.focused_output.pending.tags); view = while (it.next()) |node| { - if (node.view.output == self.focused_output and node.view.current.fullscreen) break node.view; + if (node.view.output == self.focused_output and node.view.pending.fullscreen) break node.view; } else view; } if (view == null) { // Set view to the first currently visible view in the focus stack if any - var it = ViewStack(*View).iterator(self.focus_stack.first, self.focused_output.current.tags); + var it = ViewStack(*View).pendingIterator(self.focus_stack.first, self.focused_output.pending.tags); view = while (it.next()) |node| { if (node.view.output == self.focused_output) break node.view; } else null; @@ -223,9 +223,6 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void { // Inform any clients tracking status of the change var it = self.status_trackers.first; while (it) |node| : (it = node.next) node.data.sendFocusedView(); - - // Start a transaction to apply the pending focus state - self.input_manager.server.root.startTransaction(); } /// Focus the given output, notifying any listening clients of the change. diff --git a/river/View.zig b/river/View.zig index 8e102b8..d745f6d 100644 --- a/river/View.zig +++ b/river/View.zig @@ -351,7 +351,8 @@ pub fn map(self: *Self) void { self.output.sendViewTags(); - self.output.arrangeViews(); + if (!self.current.float) self.output.arrangeViews(); + self.output.root.startTransaction(); } @@ -377,10 +378,9 @@ pub fn unmap(self: *Self) void { self.output.sendViewTags(); // Still need to arrange if fullscreened from the layout - if (!self.current.float) { - self.output.arrangeViews(); - root.startTransaction(); - } + if (!self.current.float) self.output.arrangeViews(); + + root.startTransaction(); } /// Destory the view and free the ViewStack node holding it. diff --git a/river/command/focus_view.zig b/river/command/focus_view.zig index cc1b26e..4e77665 100644 --- a/river/command/focus_view.zig +++ b/river/command/focus_view.zig @@ -53,6 +53,7 @@ pub fn focusView( // Focus the next visible node if there is one if (it.next()) |node| { seat.focus(&node.view); + output.root.startTransaction(); return; } } @@ -65,4 +66,5 @@ pub fn focusView( }; seat.focus(if (it.next()) |node| &node.view else null); + output.root.startTransaction(); } diff --git a/river/command/tags.zig b/river/command/tags.zig index 5e4d6e2..243b286 100644 --- a/river/command/tags.zig +++ b/river/command/tags.zig @@ -31,6 +31,7 @@ pub fn setFocusedTags( if (seat.focused_output.pending.tags != tags) { seat.focused_output.pending.tags = tags; seat.focused_output.arrangeViews(); + seat.focus(null); seat.focused_output.root.startTransaction(); } } @@ -44,8 +45,10 @@ pub fn setViewTags( ) Error!void { const tags = try parseTags(allocator, args, out); if (seat.focused == .view) { - seat.focused.view.pending.tags = tags; - seat.focused.view.applyPending(); + const view = seat.focused.view; + view.pending.tags = tags; + seat.focus(null); + view.applyPending(); } } @@ -62,6 +65,7 @@ pub fn toggleFocusedTags( if (new_focused_tags != 0) { output.pending.tags = new_focused_tags; output.arrangeViews(); + seat.focus(null); output.root.startTransaction(); } } @@ -75,10 +79,12 @@ pub fn toggleViewTags( ) Error!void { const tags = try parseTags(allocator, args, out); if (seat.focused == .view) { - const new_tags = seat.focused.view.current.tags ^ tags; + const new_tags = seat.focused.view.pending.tags ^ tags; if (new_tags != 0) { - seat.focused.view.pending.tags = new_tags; - seat.focused.view.applyPending(); + const view = seat.focused.view; + view.pending.tags = new_tags; + seat.focus(null); + view.applyPending(); } } }