From 43ebdd273c8c4a0afce1107a22107d434d5057f2 Mon Sep 17 00:00:00 2001 From: Ben Buhse Date: Sun, 15 Feb 2026 18:02:48 -0600 Subject: [PATCH] Refactor Bar/Output surfaces into anon struct Both the wl_surface and layer_surface in each are always expected to exist at the same time. Since they're optional, it makes more sense to combine them into a single optional struct. --- src/Bar.zig | 52 ++++++++++++++++++++++++++----------------------- src/Context.zig | 2 +- src/Output.zig | 41 +++++++++++++++++++++----------------- 3 files changed, 52 insertions(+), 43 deletions(-) diff --git a/src/Bar.zig b/src/Bar.zig index d205a15..9cba3d1 100644 --- a/src/Bar.zig +++ b/src/Bar.zig @@ -21,8 +21,10 @@ output: *Output, width: u31 = 0, height: u31 = 0, -wl_surface: ?*wl.Surface = null, -layer_surface: ?*zwlr.LayerSurfaceV1 = null, +surfaces: ?struct { + wl_surface: *wl.Surface, + layer_surface: *zwlr.LayerSurfaceV1, +} = null, configured: bool = false, @@ -43,34 +45,37 @@ pub fn init(context: *Context, output: *Output) !Bar { // TODO: Add config options for whether it's top or bottom pub fn initSurface(bar: *Bar) !void { - if (bar.layer_surface) |_| { - // This bar already has a layer surface, we can exit early + if (bar.surfaces) |_| { + // This bar already has a surface, we can exit early return; } const context = bar.context; - // TODO: Add padding to config - const vertical_padding = 5; - const bar_height: u31 = @intCast(bar.fonts.height + 2 * vertical_padding); - const wl_surface = try context.wl_compositor.createSurface(); errdefer wl_surface.destroy(); + const layer_surface = try context + .zwlr_layer_shell_v1 + .getLayerSurface(wl_surface, bar.output.wl_output, .top, "beansprout-bar"); + errdefer layer_surface.destroy(); + // TODO: Allow clicking on tags to switch between them? // We don't want our surface to have any input region (default is infinite) const empty_region = try context.wl_compositor.createRegion(); defer empty_region.destroy(); wl_surface.setInputRegion(empty_region); - const layer_surface = try context - .zwlr_layer_shell_v1 - .getLayerSurface(wl_surface, bar.output.wl_output, .top, "beansprout-bar"); + // TODO: Add padding to config + const vertical_padding = 5; + const bar_height: u31 = @intCast(bar.fonts.height + 2 * vertical_padding); layer_surface.setSize(0, bar_height); layer_surface.setAnchor(.{ .top = true, .right = true, .left = true }); - bar.wl_surface = wl_surface; - bar.layer_surface = layer_surface; + bar.surfaces = .{ + .wl_surface = wl_surface, + .layer_surface = layer_surface, + }; context.buffer_pool.surface_count += 1; layer_surface.setListener(*Bar, layerSurfaceListener, bar); @@ -81,11 +86,9 @@ pub fn deinit(bar: *Bar) void { bar.configured = false; bar.timezone.deinit(); bar.fonts.destroy(); - if (bar.wl_surface) |wl_surface| { - wl_surface.destroy(); - } - if (bar.layer_surface) |layer_surface| { - layer_surface.destroy(); + if (bar.surfaces) |surfaces| { + surfaces.wl_surface.destroy(); + surfaces.layer_surface.destroy(); bar.context.buffer_pool.surface_count -= 1; } } @@ -106,15 +109,15 @@ pub fn layerSurfaceListener( bar.height == height and bar.output.scale == bar.font_scale) { - if (bar.wl_surface) |wl_surface| { - wl_surface.commit(); + if (bar.surfaces) |surfaces| { + surfaces.wl_surface.commit(); } else { - log.warn("Bar is marked as configured but is missing a layer_surface for the wallpaper", .{}); + log.warn("Bar is marked as configured but is missing its surfaces.", .{}); } return; } - log.debug("configuring bar surface with width {} and height {}", .{ width, height }); + log.debug("Configuring bar surface with width {} and height {}", .{ width, height }); bar.width = width; bar.height = height; // Excluse zone == the bar's height @@ -128,7 +131,7 @@ pub fn layerSurfaceListener( // TODO: Need to change the x/y if we support anchoring to the bottom opaque_region.add(0, 0, bar.width, bar.height); defer opaque_region.destroy(); - bar.wl_surface.?.setOpaqueRegion(opaque_region); + bar.surfaces.?.wl_surface.setOpaqueRegion(opaque_region); bar.configured = true; @@ -222,7 +225,8 @@ pub fn render(bar: *Bar) !void { try bar.renderChars(codepoints, buffer, &x, y, color); // Finally, attach the buffer to the surface - const wl_surface = bar.wl_surface orelse return; + const surfaces = bar.surfaces orelse return error.NoSurfaces; + const wl_surface = surfaces.wl_surface; wl_surface.setBufferScale(scale); wl_surface.attach(buffer.wl_buffer, 0, 0); wl_surface.damageBuffer(0, 0, render_width, render_height); diff --git a/src/Context.zig b/src/Context.zig index d99d225..bcf0c69 100644 --- a/src/Context.zig +++ b/src/Context.zig @@ -143,7 +143,7 @@ pub fn manage(context: *Context) void { while (out_it.next()) |output| { if (context.wallpaper_image == null) { output.deinitWallpaperLayerSurface(); - } else if (output.wl_surface != null) { + } else if (output.surfaces != null) { output.renderWallpaper() catch |err| { log.err("Wallpaper re-render failed: {}", .{err}); }; diff --git a/src/Output.zig b/src/Output.zig index 02df08a..27206b1 100644 --- a/src/Output.zig +++ b/src/Output.zig @@ -32,8 +32,11 @@ usable_height: u31 = 0, wallpaper_render_scale: u31 = 0, wallpaper_render_width: u31 = 0, wallpaper_render_height: u31 = 0, -wl_surface: ?*wl.Surface = null, -layer_surface: ?*zwlr.LayerSurfaceV1 = null, + +surfaces: ?struct { + wl_surface: *wl.Surface, + layer_surface: *zwlr.LayerSurfaceV1, +} = null, // TODO: Make Bar a user option, can disable if they want // This Output's bar @@ -319,8 +322,8 @@ pub fn initWallpaperLayerSurface(output: *Output) !void { return; } - if (output.layer_surface) |_| { - // This output already has a layer surface, we can exit early + if (output.surfaces) |_| { + // This output already has a surface, we can exit early return; } @@ -329,6 +332,9 @@ pub fn initWallpaperLayerSurface(output: *Output) !void { const wl_surface = try context.wl_compositor.createSurface(); errdefer wl_surface.destroy(); + const layer_surface = try context.zwlr_layer_shell_v1.getLayerSurface(wl_surface, output.wl_output, .background, "beansprout-wallpaper"); + errdefer layer_surface.destroy(); + // We don't want our surface to have any input region (default is infinite) const empty_region = try context.wl_compositor.createRegion(); defer empty_region.destroy(); @@ -340,12 +346,13 @@ pub fn initWallpaperLayerSurface(output: *Output) !void { defer opaque_region.destroy(); wl_surface.setOpaqueRegion(opaque_region); - const layer_surface = try context.zwlr_layer_shell_v1.getLayerSurface(wl_surface, output.wl_output, .background, "beansprout-wallpaper"); layer_surface.setExclusiveZone(-1); layer_surface.setAnchor(.{ .top = true, .right = true, .bottom = true, .left = true }); - output.wl_surface = wl_surface; - output.layer_surface = layer_surface; + output.surfaces = .{ + .wl_surface = wl_surface, + .layer_surface = layer_surface, + }; context.buffer_pool.surface_count += 1; layer_surface.setListener(*Output, wallpaperLayerSurfaceListener, output); @@ -353,16 +360,13 @@ pub fn initWallpaperLayerSurface(output: *Output) !void { } pub fn deinitWallpaperLayerSurface(output: *Output) void { - if (output.layer_surface) |layer_surface| { - layer_surface.destroy(); - } - if (output.wl_surface) |wl_surface| { - wl_surface.destroy(); + if (output.surfaces) |surfaces| { + surfaces.wl_surface.destroy(); + surfaces.layer_surface.destroy(); output.context.buffer_pool.surface_count -= 1; } - output.layer_surface = null; - output.wl_surface = null; + output.surfaces = null; output.configured = false; } @@ -379,10 +383,10 @@ fn wallpaperLayerSurfaceListener(layer_surface: *zwlr.LayerSurfaceV1, event: zwl output.wallpaper_render_height == height and output.scale == output.wallpaper_render_scale) { - if (output.wl_surface) |wl_surface| { - wl_surface.commit(); + if (output.surfaces) |surfaces| { + surfaces.wl_surface.commit(); } else { - log.warn("Output is marked as configured but is missing a layer_surface for the wallpaper", .{}); + log.warn("Output is marked as configured but is missing its surfaces.", .{}); } return; } @@ -485,7 +489,8 @@ pub fn renderWallpaper(output: *Output) !void { log.info("render: {}x{} (scaled from {}x{})", .{ width * scale, height * scale, image_width, image_height }); // Attach the buffer to the surface - const wl_surface = output.wl_surface.?; + const surfaces = output.surfaces orelse return error.NoSurfaces; + const wl_surface = surfaces.wl_surface; wl_surface.setBufferScale(scale); wl_surface.attach(buffer.wl_buffer, 0, 0); wl_surface.damageBuffer(0, 0, width * scale, height * scale);