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(); } } }