From a545a06c5b2eab76adb4b0009ee24fc69fbae0f2 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Wed, 1 Feb 2023 22:30:17 +0100 Subject: [PATCH] View: implement borders with scene graph --- river/Root.zig | 5 +--- river/View.zig | 49 ++++++++++++++++++++++++++++++++++++++++ river/XdgToplevel.zig | 11 +++------ river/command/config.zig | 3 +++ 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/river/Root.zig b/river/Root.zig index 4ef1260..8711ea4 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -455,11 +455,8 @@ fn commitTransaction(self: *Self) void { if (view.pending.tags != view.current.tags) view_tags_changed = true; if (view.pending.urgent != view.current.urgent) urgent_tags_dirty = true; if (view.pending.urgent and view_tags_changed) urgent_tags_dirty = true; - view.current = view.pending; - view.tree.node.setPosition(view.current.box.x, view.current.box.y); - - view.dropSavedBuffers(); + view.updateCurrent(); } if (view_tags_changed) output.sendViewTags(); diff --git a/river/View.zig b/river/View.zig index 9d932f0..bb73335 100644 --- a/river/View.zig +++ b/river/View.zig @@ -78,6 +78,12 @@ impl: Impl, output: *Output, tree: *wlr.SceneTree, +borders: struct { + left: *wlr.SceneRect, + right: *wlr.SceneRect, + top: *wlr.SceneRect, + bottom: *wlr.SceneRect, +}, /// This indicates that the view should be destroyed when the current /// transaction completes. See View.destroy() @@ -126,6 +132,12 @@ pub fn init(self: *Self, output: *Output, tree: *wlr.SceneTree, impl: Impl) erro .impl = impl, .output = output, .tree = tree, + .borders = .{ + .left = try tree.createSceneRect(0, 0, &server.config.border_color_unfocused), + .right = try tree.createSceneRect(0, 0, &server.config.border_color_unfocused), + .top = try tree.createSceneRect(0, 0, &server.config.border_color_unfocused), + .bottom = try tree.createSceneRect(0, 0, &server.config.border_color_unfocused), + }, .current = .{ .tags = initial_tags }, .pending = .{ .tags = initial_tags }, }; @@ -185,6 +197,39 @@ pub fn applyPending(self: *Self) void { server.root.startTransaction(); } +pub fn updateCurrent(self: *Self) void { + const config = &server.config; + + self.current = self.pending; + self.dropSavedBuffers(); + + const color = blk: { + if (self.current.urgent) break :blk &config.border_color_urgent; + if (self.current.focus != 0) break :blk &config.border_color_focused; + break :blk &config.border_color_unfocused; + }; + + const box = &self.current.box; + self.tree.node.setPosition(box.x, box.y); + + const border_width: c_int = config.border_width; + self.borders.left.node.setPosition(-border_width, -border_width); + self.borders.left.setSize(border_width, box.height + 2 * border_width); + self.borders.left.setColor(color); + + self.borders.right.node.setPosition(box.width, -border_width); + self.borders.right.setSize(border_width, box.height + 2 * border_width); + self.borders.right.setColor(color); + + self.borders.top.node.setPosition(0, -border_width); + self.borders.top.setSize(box.width, border_width); + self.borders.top.setColor(color); + + self.borders.bottom.node.setPosition(0, box.height); + self.borders.bottom.setSize(box.width, border_width); + self.borders.bottom.setColor(color); +} + pub fn needsConfigure(self: Self) bool { return switch (self.impl) { .xdg_toplevel => |xdg_toplevel| xdg_toplevel.needsConfigure(), @@ -459,6 +504,8 @@ pub fn shouldTrackConfigure(self: Self) bool { pub fn map(self: *Self) !void { log.debug("view '{?s}' mapped", .{self.getTitle()}); + self.tree.node.setEnabled(true); + server.xdg_activation.events.request_activate.add(&self.request_activate); // Add the view to the stack of its output @@ -480,6 +527,8 @@ pub fn map(self: *Self) !void { pub fn unmap(self: *Self) void { log.debug("view '{?s}' unmapped", .{self.getTitle()}); + self.tree.node.setEnabled(false); + if (self.saved_buffers.items.len == 0) self.saveBuffers(); // Inform all seats that the view has been unmapped so they can handle focus diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig index 4a78d1b..a5aa128 100644 --- a/river/XdgToplevel.zig +++ b/river/XdgToplevel.zig @@ -63,8 +63,8 @@ pub fn create(output: *Output, xdg_toplevel: *wlr.XdgToplevel) error{OutOfMemory errdefer util.gpa.destroy(node); const view = &node.view; - const tree = try output.layers.views.createSceneXdgSurface(xdg_toplevel.base); - errdefer tree.node.destroy(); + const tree = try output.layers.views.createSceneTree(); + _ = try tree.createSceneXdgSurface(xdg_toplevel.base); try view.init(output, tree, .{ .xdg_toplevel = .{ .view = view, @@ -269,16 +269,11 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void { const urgent_tags_dirty = view.pending.urgent != view.current.urgent or (view.pending.urgent and self_tags_changed); - view.current = view.pending; - view.tree.node.setPosition(view.current.box.x, view.current.box.y); + view.updateCurrent(); if (self_tags_changed) view.output.sendViewTags(); if (urgent_tags_dirty) view.output.sendUrgentTags(); - // This is necessary if this view was part of a transaction that didn't get completed - // before some change occured that caused shouldTrackConfigure() to return false. - view.dropSavedBuffers(); - server.input_manager.updateCursorState(); } } else { diff --git a/river/command/config.zig b/river/command/config.zig index 88ad1f4..c657a5f 100644 --- a/river/command/config.zig +++ b/river/command/config.zig @@ -62,6 +62,7 @@ pub fn borderColorFocused( if (args.len > 2) return Error.TooManyArguments; server.config.border_color_focused = try parseRgba(args[1]); + server.root.startTransaction(); } pub fn borderColorUnfocused( @@ -73,6 +74,7 @@ pub fn borderColorUnfocused( if (args.len > 2) return Error.TooManyArguments; server.config.border_color_unfocused = try parseRgba(args[1]); + server.root.startTransaction(); } pub fn borderColorUrgent( @@ -84,6 +86,7 @@ pub fn borderColorUrgent( if (args.len > 2) return Error.TooManyArguments; server.config.border_color_urgent = try parseRgba(args[1]); + server.root.startTransaction(); } pub fn setCursorWarp(