Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
Window: implement river_window_v1.set_borders
river/Config.zig | 6 ----
river/Window.zig | 78 ++++++++++++++++++++++++++++++++++++++++++++------
rivercompat/Window.zig | 9 ++++++
3 files changed, 79 insertions(+), 14 deletions(-)
diff --git a/river/Config.zig b/river/Config.zig
index 438cc9d..dcde0f1 100644
--- a/river/Config.zig
+++ b/river/Config.zig
@@ -31,12 +31,6 @@ const Switch = @import("Switch.zig");
/// Color of background in RGBA with premultiplied alpha (alpha should only affect nested sessions)
background_color: [4]f32 = [_]f32{ 0.0, 0.16862745, 0.21176471, 1.0 }, // Solarized base03
-/// Width of borders in pixels
-border_width: u31 = 2,
-
-/// Color of border in RGBA with premultiplied alpha
-border_color: [4]f32 = [_]f32{ 0.34509804, 0.43137255, 0.45882353, 1.0 }, // Solarized base01
-
switch_mappings: std.ArrayListUnmanaged(struct {
switch_type: Switch.Type,
switch_state: Switch.State,
diff --git a/river/Window.zig b/river/Window.zig
index 7a10c77..a62cc95 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -139,8 +139,12 @@ impl: Impl,
tree: *wlr.SceneTree,
surface_tree: *wlr.SceneTree,
saved_surface_tree: *wlr.SceneTree,
-/// Order is left, right, top, bottom
-borders: [4]*wlr.SceneRect,
+border: struct {
+ left: *wlr.SceneRect,
+ right: *wlr.SceneRect,
+ top: *wlr.SceneRect,
+ bottom: *wlr.SceneRect,
+},
popup_tree: *wlr.SceneTree,
/// Set to true once the window manager client has made its first commit
@@ -216,11 +220,11 @@ pub fn create(impl: Impl) error{OutOfMemory}!*Window {
.tree = tree,
.surface_tree = try tree.createSceneTree(),
.saved_surface_tree = try tree.createSceneTree(),
- .borders = .{
- try tree.createSceneRect(0, 0, &server.config.border_color),
- try tree.createSceneRect(0, 0, &server.config.border_color),
- try tree.createSceneRect(0, 0, &server.config.border_color),
- try tree.createSceneRect(0, 0, &server.config.border_color),
+ .border = .{
+ .left = try tree.createSceneRect(0, 0, &.{ 0, 0, 0, 0 }),
+ .right = try tree.createSceneRect(0, 0, &.{ 0, 0, 0, 0 }),
+ .top = try tree.createSceneRect(0, 0, &.{ 0, 0, 0, 0 }),
+ .bottom = try tree.createSceneRect(0, 0, &.{ 0, 0, 0, 0 }),
},
.popup_tree = popup_tree,
.link = undefined,
@@ -636,7 +640,65 @@ pub fn updateSceneState(window: *Window) void {
window.tree.node.setPosition(box.x, box.y);
window.popup_tree.node.setPosition(box.x, box.y);
- // TODO borders
+ // f32 cannot represent all u32 values exactly, therefore we must initially use f64
+ // (which can) and then cast to f32, potentially losing precision.
+ const border = &window.sent.border;
+ const color: [4]f32 = .{
+ @floatCast(@as(f64, @floatFromInt(border.r)) / math.maxInt(u32)),
+ @floatCast(@as(f64, @floatFromInt(border.g)) / math.maxInt(u32)),
+ @floatCast(@as(f64, @floatFromInt(border.b)) / math.maxInt(u32)),
+ @floatCast(@as(f64, @floatFromInt(border.a)) / math.maxInt(u32)),
+ };
+
+ var left: wlr.Box = .{
+ .x = -@as(i32, border.width),
+ .y = 0,
+ .width = border.width,
+ .height = box.height,
+ };
+ var right: wlr.Box = .{
+ .x = box.width,
+ .y = 0,
+ .width = border.width,
+ .height = box.height,
+ };
+ const top: wlr.Box = .{
+ .x = 0,
+ .y = -@as(i32, border.width),
+ .width = box.width,
+ .height = border.width,
+ };
+ const bottom: wlr.Box = .{
+ .x = 0,
+ .y = box.height,
+ .width = box.width,
+ .height = border.width,
+ };
+
+ // Use left and right scene rects to draw the corners if needed
+ if (border.edges.top) {
+ left.y -= border.width;
+ left.height += border.width;
+ right.y -= border.width;
+ right.height += border.width;
+ }
+ if (border.edges.bottom) {
+ left.height += border.width;
+ right.height += border.width;
+ }
+
+ inline for (.{
+ .{ .name = "left", .box = left },
+ .{ .name = "right", .box = right },
+ .{ .name = "top", .box = top },
+ .{ .name = "bottom", .box = bottom },
+ }) |edge| {
+ const rect = @field(window.border, edge.name);
+ rect.node.setEnabled(@field(border.edges, edge.name));
+ rect.node.setPosition(edge.box.x, edge.box.y);
+ rect.setSize(edge.box.width, edge.box.height);
+ rect.setColor(&color);
+ }
}
/// Returns null if the window is currently being destroyed and no longer has
diff --git a/rivercompat/Window.zig b/rivercompat/Window.zig
index 75c8ff7..cc87ef4 100644
--- a/rivercompat/Window.zig
+++ b/rivercompat/Window.zig
@@ -42,6 +42,15 @@ pub fn create(window_v1: *river.WindowV1, wm: *WindowManager) void {
wm.windows.append(window);
window_v1.setListener(*Window, handleEvent, window);
window.node_v1.placeTop();
+ window_v1.useSsd();
+ window_v1.setBorders(
+ .{ .left = true, .bottom = true, .top = false, .right = true },
+ 6, // width
+ std.math.maxInt(u32),
+ std.math.maxInt(u32),
+ std.math.maxInt(u32),
+ std.math.maxInt(u32),
+ );
}
fn handleEvent(window_v1: *river.WindowV1, event: river.WindowV1.Event, window: *Window) void {