aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--river/Cursor.zig4
-rw-r--r--river/Output.zig31
-rw-r--r--river/OutputStatus.zig2
-rw-r--r--river/Root.zig11
-rw-r--r--river/Seat.zig6
-rw-r--r--river/Server.zig4
-rw-r--r--river/View.zig1
-rw-r--r--river/command/focus_view.zig8
-rw-r--r--river/command/tags.zig8
-rw-r--r--river/command/zoom.zig2
-rw-r--r--river/render.zig6
11 files changed, 42 insertions, 41 deletions
diff --git a/river/Cursor.zig b/river/Cursor.zig
index c38c0dd..a6dba22 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -360,13 +360,13 @@ fn layerSurfaceAt(
/// Find the topmost visible view surface (incl. popups) at ox,oy.
fn viewSurfaceAt(output: Output, ox: f64, oy: f64, sx: *f64, sy: *f64) ?*c.wlr_surface {
// Focused views are rendered on top, so look for them first.
- var it = ViewStack(View).iterator(output.views.first, output.current_focused_tags);
+ var it = ViewStack(View).iterator(output.views.first, output.current.tags);
while (it.next()) |node| {
if (!node.view.focused) continue;
if (node.view.surfaceAt(ox, oy, sx, sy)) |found| return found;
}
- it = ViewStack(View).iterator(output.views.first, output.current_focused_tags);
+ it = ViewStack(View).iterator(output.views.first, output.current.tags);
while (it.next()) |node| {
if (node.view.surfaceAt(ox, oy, sx, sy)) |found| return found;
}
diff --git a/river/Output.zig b/river/Output.zig
index e4e688a..1b29db5 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -40,6 +40,11 @@ const OutputStatus = @import("OutputStatus.zig");
// that it should never be encountered during normal usage.
const minimum_size = 50;
+const State = struct {
+ /// A bit field of focused tags
+ tags: u32,
+};
+
root: *Root,
wlr_output: *c.wlr_output,
@@ -48,14 +53,15 @@ layers: [4]std.TailQueue(LayerSurface),
/// The area left for views and other layer surfaces after applying the
/// exclusive zones of exclusive layer surfaces.
+/// TODO: this should be part of the output's State
usable_box: Box,
/// The top of the stack is the "most important" view.
views: ViewStack(View),
-/// A bit field of focused tags
-current_focused_tags: u32,
-pending_focused_tags: ?u32,
+/// The double-buffered state of the output.
+current: State,
+pending: State,
/// Number of views in "master" section of the screen.
master_count: u32,
@@ -98,8 +104,10 @@ pub fn init(self: *Self, root: *Root, wlr_output: *c.wlr_output) !void {
self.views.init();
- self.current_focused_tags = 1 << 0;
- self.pending_focused_tags = null;
+ self.current = .{
+ .tags = 1 << 0,
+ };
+ self.pending = self.current;
self.master_count = 1;
@@ -297,17 +305,12 @@ fn layoutExternal(self: *Self, visible_count: u32, output_tags: u32) !void {
/// pending state, the changes are not appplied until a transaction is started
/// and completed.
pub fn arrangeViews(self: *Self) void {
- const output_tags = if (self.pending_focused_tags) |tags|
- tags
- else
- self.current_focused_tags;
-
const full_area = Box.fromWlrBox(c.wlr_output_layout_get_box(self.root.wlr_output_layout, self.wlr_output).*);
// Make fullscreen views take the full area, count up views that will be
// arranged by the layout.
var layout_count: u32 = 0;
- var it = ViewStack(View).pendingIterator(self.views.first, output_tags);
+ var it = ViewStack(View).pendingIterator(self.views.first, self.pending.tags);
while (it.next()) |node| {
const view = &node.view;
if (view.pending.fullscreen) {
@@ -321,9 +324,9 @@ pub fn arrangeViews(self: *Self) void {
// would cause an underflow and is pointless anyway.
if (layout_count == 0 or self.usable_box.width == 0 or self.usable_box.height == 0) return;
- if (std.mem.eql(u8, self.layout, "full")) return layoutFull(self, layout_count, output_tags);
+ if (std.mem.eql(u8, self.layout, "full")) return layoutFull(self, layout_count, self.pending.tags);
- layoutExternal(self, layout_count, output_tags) catch |err| {
+ layoutExternal(self, layout_count, self.pending.tags) catch |err| {
switch (err) {
LayoutError.BadExitCode => log.err(.layout, "layout command exited with non-zero return code", .{}),
LayoutError.BadWindowConfiguration => log.err(.layout, "invalid window configuration", .{}),
@@ -331,7 +334,7 @@ pub fn arrangeViews(self: *Self) void {
else => log.err(.layout, "'{}' error while trying to use external layout", .{err}),
}
log.err(.layout, "falling back to internal layout", .{});
- layoutFull(self, layout_count, output_tags);
+ layoutFull(self, layout_count, self.pending.tags);
};
}
diff --git a/river/OutputStatus.zig b/river/OutputStatus.zig
index be0568f..eac2bbd 100644
--- a/river/OutputStatus.zig
+++ b/river/OutputStatus.zig
@@ -78,5 +78,5 @@ pub fn sendViewTags(self: Self) void {
/// Send the currently focused tags of the output to the client.
pub fn sendFocusedTags(self: Self) void {
- c.zriver_output_status_v1_send_focused_tags(self.wl_resource, self.output.current_focused_tags);
+ c.zriver_output_status_v1_send_focused_tags(self.wl_resource, self.output.current.tags);
}
diff --git a/river/Root.zig b/river/Root.zig
index 81478c8..381ce89 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -207,25 +207,24 @@ fn commitTransaction(self: *Self) void {
while (output_it) |output_node| : (output_it = output_node.next) {
const output = &output_node.data;
- // If there were pending focused tags, make them the current focus
- if (output.pending_focused_tags) |tags| {
+ // Apply pending state of the output
+ if (output.pending.tags != output.current.tags) {
log.debug(
.output,
"changing current focus: {b:0>10} to {b:0>10}",
- .{ output.current_focused_tags, tags },
+ .{ output.current.tags, output.pending.tags },
);
- output.current_focused_tags = tags;
- output.pending_focused_tags = null;
var it = output.status_trackers.first;
while (it) |node| : (it = node.next) node.data.sendFocusedTags();
}
+ output.current = output.pending;
var view_tags_changed = false;
var view_it = ViewStack(View).iterator(output.views.first, std.math.maxInt(u32));
while (view_it.next()) |view_node| {
const view = &view_node.view;
- // Apply pending state
+ // Apply pending state of the view
view.pending_serial = null;
if (view.pending.tags != view.current.tags) view_tags_changed = true;
view.current = view.pending;
diff --git a/river/Seat.zig b/river/Seat.zig
index c043b83..f1991f9 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -125,13 +125,13 @@ 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_focused_tags == 0) view = null;
+ v.current.tags & self.focused_output.current.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_focused_tags);
+ var it = ViewStack(*View).iterator(self.focus_stack.first, self.focused_output.current.tags);
view = while (it.next()) |node| {
if (node.view.output == self.focused_output and node.view.current.fullscreen) break node.view;
} else view;
@@ -139,7 +139,7 @@ pub fn focus(self: *Self, _view: ?*View) void {
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_focused_tags);
+ var it = ViewStack(*View).iterator(self.focus_stack.first, self.focused_output.current.tags);
view = while (it.next()) |node| {
if (node.view.output == self.focused_output) break node.view;
} else null;
diff --git a/river/Server.zig b/river/Server.zig
index b31858a..90f6b19 100644
--- a/river/Server.zig
+++ b/river/Server.zig
@@ -181,7 +181,7 @@ fn handleNewXdgSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) v
// The View will add itself to the output's view stack on map
const output = self.input_manager.default_seat.focused_output;
const node = util.gpa.create(ViewStack(View).Node) catch unreachable;
- node.view.init(output, output.current_focused_tags, wlr_xdg_surface);
+ node.view.init(output, output.current.tags, wlr_xdg_surface);
}
/// This event is raised when the layer_shell recieves a new surface from a client.
@@ -256,5 +256,5 @@ fn handleNewXwaylandSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(
// The View will add itself to the output's view stack on map
const output = self.input_manager.default_seat.focused_output;
const node = util.gpa.create(ViewStack(View).Node) catch unreachable;
- node.view.init(output, output.current_focused_tags, wlr_xwayland_surface);
+ node.view.init(output, output.current.tags, wlr_xwayland_surface);
}
diff --git a/river/View.zig b/river/View.zig
index 8b99481..cdd7d02 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -107,7 +107,6 @@ pub fn init(self: *Self, output: *Output, tags: u32, surface: var) void {
.float = false,
.fullscreen = false,
};
-
self.pending = self.current;
self.pending_serial = null;
diff --git a/river/command/focus_view.zig b/river/command/focus_view.zig
index 134aa35..2c66045 100644
--- a/river/command/focus_view.zig
+++ b/river/command/focus_view.zig
@@ -44,8 +44,8 @@ pub fn focusView(
// If there is a currently focused view, focus the next visible view in the stack.
const focused_node = @fieldParentPtr(ViewStack(View).Node, "view", current_focus);
var it = switch (direction) {
- .Next => ViewStack(View).iterator(focused_node, output.current_focused_tags),
- .Prev => ViewStack(View).reverseIterator(focused_node, output.current_focused_tags),
+ .Next => ViewStack(View).iterator(focused_node, output.current.tags),
+ .Prev => ViewStack(View).reverseIterator(focused_node, output.current.tags),
};
// Skip past the focused node
@@ -60,8 +60,8 @@ pub fn focusView(
// There is either no currently focused view or the last visible view in the
// stack is focused and we need to wrap.
var it = switch (direction) {
- .Next => ViewStack(View).iterator(output.views.first, output.current_focused_tags),
- .Prev => ViewStack(View).reverseIterator(output.views.last, output.current_focused_tags),
+ .Next => ViewStack(View).iterator(output.views.first, output.current.tags),
+ .Prev => ViewStack(View).reverseIterator(output.views.last, output.current.tags),
};
seat.focus(if (it.next()) |node| &node.view else null);
diff --git a/river/command/tags.zig b/river/command/tags.zig
index 5c14aaa..795129c 100644
--- a/river/command/tags.zig
+++ b/river/command/tags.zig
@@ -28,8 +28,8 @@ pub fn setFocusedTags(
out: *?[]const u8,
) Error!void {
const tags = try parseTags(allocator, args, out);
- if (seat.focused_output.current_focused_tags != tags) {
- seat.focused_output.pending_focused_tags = tags;
+ if (seat.focused_output.pending.tags != tags) {
+ seat.focused_output.pending.tags = tags;
seat.input_manager.server.root.arrange();
}
}
@@ -57,9 +57,9 @@ pub fn toggleFocusedTags(
) Error!void {
const tags = try parseTags(allocator, args, out);
const output = seat.focused_output;
- const new_focused_tags = output.current_focused_tags ^ tags;
+ const new_focused_tags = output.pending.tags ^ tags;
if (new_focused_tags != 0) {
- output.pending_focused_tags = new_focused_tags;
+ output.pending.tags = new_focused_tags;
seat.input_manager.server.root.arrange();
}
}
diff --git a/river/command/zoom.zig b/river/command/zoom.zig
index 5c17260..69ba58a 100644
--- a/river/command/zoom.zig
+++ b/river/command/zoom.zig
@@ -41,7 +41,7 @@ pub fn zoom(
// If the the first view that is part of the layout is focused, zoom
// the next view in the layout. Otherwise zoom the focused view.
- var it = ViewStack(View).iterator(output.views.first, output.current_focused_tags);
+ var it = ViewStack(View).iterator(output.views.first, output.current.tags);
const layout_first = while (it.next()) |node| {
if (!node.view.pending.float and !node.view.pending.fullscreen) break node;
} else unreachable;
diff --git a/river/render.zig b/river/render.zig
index 975db52..16d9d97 100644
--- a/river/render.zig
+++ b/river/render.zig
@@ -57,7 +57,7 @@ pub fn renderOutput(output: *Output) void {
c.wlr_renderer_begin(wlr_renderer, width, height);
// Find the first visible fullscreen view in the stack if there is one
- var it = ViewStack(View).iterator(output.views.first, output.current_focused_tags);
+ var it = ViewStack(View).iterator(output.views.first, output.current.tags);
const fullscreen_view = while (it.next()) |node| {
if (node.view.current.fullscreen) break &node.view;
} else null;
@@ -76,7 +76,7 @@ pub fn renderOutput(output: *Output) void {
renderLayer(output.*, output.layers[c.ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], &now);
// The first view in the list is "on top" so iterate in reverse.
- it = ViewStack(View).reverseIterator(output.views.last, output.current_focused_tags);
+ it = ViewStack(View).reverseIterator(output.views.last, output.current.tags);
while (it.next()) |node| {
const view = &node.view;
@@ -92,7 +92,7 @@ pub fn renderOutput(output: *Output) void {
}
// Render focused views
- it = ViewStack(View).reverseIterator(output.views.last, output.current_focused_tags);
+ it = ViewStack(View).reverseIterator(output.views.last, output.current.tags);
while (it.next()) |node| {
const view = &node.view;