Apply Rect to Output

This commit is contained in:
Ben Buhse 2026-02-16 17:27:31 -06:00
commit 515e94320b
No known key found for this signature in database
GPG key ID: 7916ACFCD38FD0B4
3 changed files with 51 additions and 58 deletions

View file

@ -17,16 +17,20 @@ name: ?[]const u8 = null,
// Output geometry // Output geometry
scale: u31 = 1, scale: u31 = 1,
x: i32 = 0, geometry: Rect = .{
y: i32 = 0, .x = 0,
width: u31 = 0, .y = 0,
height: u31 = 0, .width = 0,
.height = 0,
},
// Area left after layer shell surfaces take exclusive area // Area left after layer shell surfaces take exclusive area
usable_x: i32 = 0, usable_geometry: Rect = .{
usable_y: i32 = 0, .x = 0,
usable_width: u31 = 0, .y = 0,
usable_height: u31 = 0, .width = 0,
.height = 0,
},
// Information for this Output's wallpaper // Information for this Output's wallpaper
wallpaper_render_scale: u31 = 0, wallpaper_render_scale: u31 = 0,
@ -73,15 +77,10 @@ pub const TagLayoutOverride = struct {
}; };
pub const PendingManage = struct { pub const PendingManage = struct {
x: ?i32 = null, position: ?struct { x: i32, y: i32 } = null,
y: ?i32 = null, dimensions: ?struct { width: u31, height: u31 } = null,
width: ?u31 = null,
height: ?u31 = null,
usable_x: ?i32 = null, usable_geometry: ?Rect = null,
usable_y: ?i32 = null,
usable_width: ?u31 = null,
usable_height: ?u31 = null,
tags: ?u32 = null, tags: ?u32 = null,
primary_ratio: ?f32 = null, primary_ratio: ?f32 = null,
@ -252,12 +251,16 @@ fn riverOutputListener(river_output_v1: *river.OutputV1, event: river.OutputV1.E
.dimensions => |ev| { .dimensions => |ev| {
// Protocol guarantees that width and height are strictly greater than zero // Protocol guarantees that width and height are strictly greater than zero
assert(ev.width > 0 and ev.height > 0); assert(ev.width > 0 and ev.height > 0);
output.pending_manage.width = @intCast(ev.width); output.pending_manage.dimensions = .{
output.pending_manage.height = @intCast(ev.height); .width = @intCast(ev.width),
.height = @intCast(ev.height),
};
}, },
.position => |ev| { .position => |ev| {
output.pending_manage.x = ev.x; output.pending_manage.position = .{
output.pending_manage.y = ev.y; .x = ev.x,
.y = ev.y,
};
}, },
} }
} }
@ -272,8 +275,8 @@ fn wlOutputListener(_: *wl.Output, event: wl.Output.Event, output: *Output) void
return; return;
} }
output.width = @intCast(ev.width); output.geometry.width = @intCast(ev.width);
output.height = @intCast(ev.height); output.geometry.height = @intCast(ev.height);
}, },
.done => { .done => {
output.initWallpaperLayerSurface() catch |err| { output.initWallpaperLayerSurface() catch |err| {
@ -325,10 +328,12 @@ fn riverLayerShellOutputListener(
assert(output.river_layer_shell_output_v1 == river_layer_shell_output_v1); assert(output.river_layer_shell_output_v1 == river_layer_shell_output_v1);
switch (event) { switch (event) {
.non_exclusive_area => |ev| { .non_exclusive_area => |ev| {
output.pending_manage.usable_x = ev.x; output.pending_manage.usable_geometry = .{
output.pending_manage.usable_y = ev.y; .x = ev.x,
output.pending_manage.usable_width = @intCast(ev.width); .y = ev.y,
output.pending_manage.usable_height = @intCast(ev.height); .width = @intCast(ev.width),
.height = @intCast(ev.height),
};
output.context.wm.river_window_manager_v1.manageDirty(); output.context.wm.river_window_manager_v1.manageDirty();
}, },
} }
@ -360,7 +365,7 @@ pub fn initWallpaperLayerSurface(output: *Output) !void {
// Full surface should be opaque // Full surface should be opaque
const opaque_region = try context.wl_compositor.createRegion(); const opaque_region = try context.wl_compositor.createRegion();
opaque_region.add(0, 0, output.width, output.height); opaque_region.add(0, 0, output.geometry.width, output.geometry.height);
defer opaque_region.destroy(); defer opaque_region.destroy();
wl_surface.setOpaqueRegion(opaque_region); wl_surface.setOpaqueRegion(opaque_region);
@ -520,30 +525,17 @@ pub fn renderWallpaper(output: *Output) !void {
pub fn manage(output: *Output) void { pub fn manage(output: *Output) void {
defer output.pending_manage = .{}; defer output.pending_manage = .{};
if (output.pending_manage.x) |x| { if (output.pending_manage.position) |position| {
output.x = x; output.geometry.x = position.x;
output.geometry.y = position.y;
} }
if (output.pending_manage.y) |y| { if (output.pending_manage.dimensions) |dimensions| {
output.y = y; output.geometry.width = dimensions.width;
} output.geometry.height = dimensions.height;
if (output.pending_manage.width) |width| {
output.width = width;
}
if (output.pending_manage.height) |height| {
output.height = height;
} }
if (output.pending_manage.usable_x) |usable_x| { if (output.pending_manage.usable_geometry) |usable_geometry| {
output.usable_x = usable_x; output.usable_geometry = usable_geometry;
}
if (output.pending_manage.usable_y) |usable_y| {
output.usable_y = usable_y;
}
if (output.pending_manage.usable_width) |usable_width| {
output.usable_width = usable_width;
}
if (output.pending_manage.usable_height) |usable_height| {
output.usable_height = usable_height;
} }
if (output.pending_manage.primary_ratio) |primary_ratio| { if (output.pending_manage.primary_ratio) |primary_ratio| {
@ -657,10 +649,10 @@ fn calculatePrimaryStackLayout(output: *Output) void {
if (active_count == 0) return; if (active_count == 0) return;
// We have to use the usable area for the layout so windows don't overlap with widgets // We have to use the usable area for the layout so windows don't overlap with widgets
const output_x = output.usable_x; const output_x = output.usable_geometry.x;
const output_y = output.usable_y; const output_y = output.usable_geometry.y;
const output_width = output.usable_width; const output_width = output.usable_geometry.width;
const output_height = output.usable_height; const output_height = output.usable_geometry.height;
const border_width = output.context.config.border_width; const border_width = output.context.config.border_width;
// Single window: maximize and return early // Single window: maximize and return early
@ -767,6 +759,7 @@ const zwlr = wayland.client.zwlr;
const pixman = @import("pixman"); const pixman = @import("pixman");
const utils = @import("utils.zig"); const utils = @import("utils.zig");
const Rect = utils.Rect;
const Bar = @import("Bar.zig"); const Bar = @import("Bar.zig");
const Buffer = @import("Buffer.zig"); const Buffer = @import("Buffer.zig");
const Context = @import("Context.zig"); const Context = @import("Context.zig");

View file

@ -189,10 +189,10 @@ pub fn manage(window: *Window) void {
if (window.floating_rect.width == 0) { if (window.floating_rect.width == 0) {
// Never floated before; use 75% of usable area, centered on output // Never floated before; use 75% of usable area, centered on output
if (window.output) |output| { if (window.output) |output| {
window.floating_rect.width = @divFloor(output.usable_width * 3, 4); window.floating_rect.width = @divFloor(output.usable_geometry.width * 3, 4);
window.floating_rect.height = @divFloor(output.usable_height * 3, 4); window.floating_rect.height = @divFloor(output.usable_geometry.height * 3, 4);
window.floating_rect.x = output.usable_x + @divFloor(output.usable_width, 2) - @divFloor(window.floating_rect.width, 2); window.floating_rect.x = output.usable_geometry.x + @divFloor(output.usable_geometry.width, 2) - @divFloor(window.floating_rect.width, 2);
window.floating_rect.y = output.usable_y + @divFloor(output.usable_height, 2) - @divFloor(window.floating_rect.height, 2); window.floating_rect.y = output.usable_geometry.y + @divFloor(output.usable_geometry.height, 2) - @divFloor(window.floating_rect.height, 2);
} else { } else {
window.floating_rect.width = window.rect.width; window.floating_rect.width = window.rect.width;
window.floating_rect.height = window.rect.height; window.floating_rect.height = window.rect.height;

View file

@ -367,8 +367,8 @@ const XkbBinding = struct {
if (!window.floating) return; if (!window.floating) return;
const output = window.output orelse return; const output = window.output orelse return;
window.floating_rect.x = output.usable_x + @divFloor(output.usable_width, 2) - @divFloor(window.floating_rect.width, 2); window.floating_rect.x = output.usable_geometry.x + @divFloor(output.usable_geometry.width, 2) - @divFloor(window.floating_rect.width, 2);
window.floating_rect.y = output.usable_y + @divFloor(output.usable_height, 2) - @divFloor(window.floating_rect.height, 2); window.floating_rect.y = output.usable_geometry.y + @divFloor(output.usable_geometry.height, 2) - @divFloor(window.floating_rect.height, 2);
window.pending_render.position = .{ .x = window.floating_rect.x, .y = window.floating_rect.y }; window.pending_render.position = .{ .x = window.floating_rect.x, .y = window.floating_rect.y };
context.wm.river_window_manager_v1.manageDirty(); context.wm.river_window_manager_v1.manageDirty();
} }