diff --git a/river/View.zig b/river/View.zig index 5a1e4c4..adb3002 100644 --- a/river/View.zig +++ b/river/View.zig @@ -264,6 +264,16 @@ pub fn getDefaultFloatBox(self: Self) Box { }; } +/// Return the dimensions of the actual "visible bounds" that the client has +/// committed. This excludes any "invisible" areas of the surface that show +/// useless stuff like CSD shadows. +pub fn getActualBox(self: Self) Box { + return switch (self.impl) { + .xdg_toplevel => |xdg_toplevel| xdg_toplevel.getActualBox(), + .xwayland_view => |xwayland_view| xwayland_view.getActualBox(), + }; +} + /// Called by the impl when the surface is ready to be displayed pub fn map(self: *Self) void { const root = self.output.root; diff --git a/river/VoidView.zig b/river/VoidView.zig index 81392ff..1ddc8bf 100644 --- a/river/VoidView.zig +++ b/river/VoidView.zig @@ -54,3 +54,7 @@ pub fn surfaceAt(self: Self, ox: f64, oy: f64, sx: *f64, sy: *f64) ?*c.wlr_surfa pub fn getTitle(self: Self) [*:0]const u8 { unreachable; } + +pub fn getActualBox(self: Self) Box { + unreachable; +} diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig index 607bb92..7d71bd4 100644 --- a/river/XdgToplevel.zig +++ b/river/XdgToplevel.zig @@ -123,6 +123,15 @@ pub fn getTitle(self: Self) [*:0]const u8 { return wlr_xdg_toplevel.title orelse "NULL"; } +pub fn getActualBox(self: Self) Box { + return .{ + .x = self.wlr_xdg_surface.geometry.x, + .y = self.wlr_xdg_surface.geometry.y, + .width = @intCast(u32, self.wlr_xdg_surface.geometry.width), + .height = @intCast(u32, self.wlr_xdg_surface.geometry.height), + }; +} + /// Called when the xdg surface is destroyed fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_destroy", listener.?); diff --git a/river/XwaylandView.zig b/river/XwaylandView.zig index 1cd0143..fdc6ddf 100644 --- a/river/XwaylandView.zig +++ b/river/XwaylandView.zig @@ -114,6 +114,15 @@ pub fn getTitle(self: Self) [*:0]const u8 { return self.wlr_xwayland_surface.title; } +pub fn getActualBox(self: Self) Box { + return .{ + .x = self.wlr_xwayland_surface.x, + .y = self.wlr_xwayland_surface.y, + .width = self.wlr_xwayland_surface.width, + .height = self.wlr_xwayland_surface.height, + }; +} + /// Called when the xwayland surface is destroyed fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_destroy", listener.?); diff --git a/river/render.zig b/river/render.zig index 6847ffe..433ce9c 100644 --- a/river/render.zig +++ b/river/render.zig @@ -241,28 +241,26 @@ fn renderTexture( fn renderBorders(output: Output, view: *View, now: *c.timespec) void { const config = &output.root.server.config; var border: Box = undefined; - const color = if (view.focused) - &output.root.server.config.border_color_focused - else - &output.root.server.config.border_color_unfocused; - const border_width = output.root.server.config.border_width; + const color = if (view.focused) &config.border_color_focused else &config.border_color_unfocused; + const border_width = config.border_width; + const actual_box = view.getActualBox(); // left and right, covering the corners as well border.y = view.current.box.y - @intCast(i32, border_width); border.width = border_width; - border.height = view.current.box.height + border_width * 2; + border.height = actual_box.height + border_width * 2; // left border.x = view.current.box.x - @intCast(i32, border_width); renderRect(output, border, color); // right - border.x = view.current.box.x + @intCast(i32, view.current.box.width); + border.x = view.current.box.x + @intCast(i32, actual_box.width); renderRect(output, border, color); // top and bottom border.x = view.current.box.x; - border.width = view.current.box.width; + border.width = actual_box.width; border.height = border_width; // top @@ -270,7 +268,7 @@ fn renderBorders(output: Output, view: *View, now: *c.timespec) void { renderRect(output, border, color); // bottom border - border.y = view.current.box.y + @intCast(i32, view.current.box.height); + border.y = view.current.box.y + @intCast(i32, actual_box.height); renderRect(output, border, color); }