Merge pull request 'Convert Bar to use river shell surface' (#1) from new-bar into main
Reviewed-on: https://codeberg.org/beansprout/beansprout/pulls/1
This commit is contained in:
commit
f00c8dbc37
6 changed files with 160 additions and 153 deletions
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
These are in rough order of my priority, though no promises I do them in this order.
|
These are in rough order of my priority, though no promises I do them in this order.
|
||||||
|
|
||||||
- [ ] Support switch handling (e.g. lid close)
|
- [ ] Add build-time options for including the wallpaper (and maybe bar)
|
||||||
- [ ] Check pointer position and only warp if not on focused window already
|
- [ ] Check pointer position and only warp if not on focused window already
|
||||||
- [ ] Change focus direction when closing window
|
- [ ] Change focus direction when closing window
|
||||||
- [ ] Use set_xcursor_theme request
|
- [ ] Use set_xcursor_theme request
|
||||||
|
- [ ] Support configuring bar item positions (left/center/right)
|
||||||
- [ ] Add focused window title to bar
|
- [ ] Add focused window title to bar
|
||||||
- [ ] Support overriding config location
|
- [ ] Support overriding config location
|
||||||
- [ ] Add support for center-primary layout
|
- [ ] Add support for center-primary layout
|
||||||
|
|
@ -25,6 +26,7 @@ These are in rough order of my priority, though no promises I do them in this or
|
||||||
- [ ] Support configurable prepend/append on send-to-output
|
- [ ] Support configurable prepend/append on send-to-output
|
||||||
- [ ] Support taking new output's tags on send-to-output
|
- [ ] Support taking new output's tags on send-to-output
|
||||||
- [ ] Add `spawn_tagmask`, `focus_previous_tags`, `send_to_previous_tags` commands
|
- [ ] Add `spawn_tagmask`, `focus_previous_tags`, `send_to_previous_tags` commands
|
||||||
|
- [ ] Support switch handling (e.g. lid close)
|
||||||
- [x] Support changeable primary ratio
|
- [x] Support changeable primary ratio
|
||||||
- [x] Support changeable primary count
|
- [x] Support changeable primary count
|
||||||
- [x] Support multiple outputs
|
- [x] Support multiple outputs
|
||||||
|
|
|
||||||
205
src/Bar.zig
205
src/Bar.zig
|
|
@ -20,16 +20,28 @@ font_scale: u31 = 1,
|
||||||
output: *Output,
|
output: *Output,
|
||||||
|
|
||||||
// Bar geometry
|
// Bar geometry
|
||||||
width: u31 = 0,
|
geometry: Rect = .{},
|
||||||
height: u31 = 0,
|
|
||||||
|
|
||||||
surfaces: ?struct {
|
surfaces: ?struct {
|
||||||
wl_surface: *wl.Surface,
|
wl_surface: *wl.Surface,
|
||||||
layer_surface: *zwlr.LayerSurfaceV1,
|
river_shell_surface: *river.ShellSurfaceV1,
|
||||||
|
node: *river.NodeV1,
|
||||||
} = null,
|
} = null,
|
||||||
|
|
||||||
|
pending_manage: PendingManage = .{},
|
||||||
|
pending_render: PendingRender = .{},
|
||||||
|
|
||||||
configured: bool = false,
|
configured: bool = false,
|
||||||
|
|
||||||
|
pub const PendingManage = struct {
|
||||||
|
output_geometry: bool = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const PendingRender = struct {
|
||||||
|
position: ?struct { x: i32, y: i32 } = null,
|
||||||
|
draw: bool = false,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Position = enum { top, bottom };
|
pub const Position = enum { top, bottom };
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
|
|
@ -54,6 +66,25 @@ pub fn init(context: *Context, output: *Output, options: Options) !Bar {
|
||||||
const fcft_fonts = try getFcftFonts(options.fonts, scale);
|
const fcft_fonts = try getFcftFonts(options.fonts, scale);
|
||||||
errdefer fcft_fonts.destroy();
|
errdefer fcft_fonts.destroy();
|
||||||
|
|
||||||
|
const wl_surface = try context.wl_compositor.createSurface();
|
||||||
|
errdefer wl_surface.destroy();
|
||||||
|
|
||||||
|
const river_shell_surface = try context
|
||||||
|
.wm
|
||||||
|
.river_window_manager_v1
|
||||||
|
.getShellSurface(wl_surface);
|
||||||
|
errdefer river_shell_surface.destroy();
|
||||||
|
|
||||||
|
const node = try river_shell_surface.getNode();
|
||||||
|
errdefer node.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();
|
||||||
|
wl_surface.setInputRegion(empty_region);
|
||||||
|
|
||||||
|
context.buffer_pool.surface_count += 1;
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.context = context,
|
.context = context,
|
||||||
.options = options,
|
.options = options,
|
||||||
|
|
@ -61,125 +92,97 @@ pub fn init(context: *Context, output: *Output, options: Options) !Bar {
|
||||||
.font_scale = scale,
|
.font_scale = scale,
|
||||||
.timezone = timezone,
|
.timezone = timezone,
|
||||||
.output = output,
|
.output = output,
|
||||||
|
.surfaces = .{
|
||||||
|
.wl_surface = wl_surface,
|
||||||
|
.river_shell_surface = river_shell_surface,
|
||||||
|
.node = node,
|
||||||
|
},
|
||||||
|
.configured = true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initSurface(bar: *Bar) !void {
|
|
||||||
if (bar.surfaces) |_| {
|
|
||||||
// This bar already has a surface, we can exit early
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const context = bar.context;
|
|
||||||
const options = bar.options;
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
// 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 vertical_padding = 5;
|
|
||||||
// Set size wants logical pixels, so we have to scale the height
|
|
||||||
const logical_font_height = @divFloor(bar.fcft_fonts.height, @as(i32, bar.font_scale));
|
|
||||||
const bar_height: u31 = @intCast(logical_font_height + 2 * vertical_padding);
|
|
||||||
layer_surface.setSize(0, bar_height);
|
|
||||||
|
|
||||||
layer_surface.setAnchor(.{ .top = options.position == .top, .bottom = options.position == .bottom, .left = true, .right = true });
|
|
||||||
layer_surface.setMargin(options.margins.top, options.margins.right, options.margins.bottom, options.margins.left);
|
|
||||||
|
|
||||||
bar.surfaces = .{
|
|
||||||
.wl_surface = wl_surface,
|
|
||||||
.layer_surface = layer_surface,
|
|
||||||
};
|
|
||||||
context.buffer_pool.surface_count += 1;
|
|
||||||
|
|
||||||
layer_surface.setListener(*Bar, layerSurfaceListener, bar);
|
|
||||||
wl_surface.commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(bar: *Bar) void {
|
pub fn deinit(bar: *Bar) void {
|
||||||
bar.configured = false;
|
bar.configured = false;
|
||||||
bar.timezone.deinit();
|
bar.timezone.deinit();
|
||||||
if (bar.surfaces) |surfaces| {
|
if (bar.surfaces) |surfaces| {
|
||||||
surfaces.layer_surface.destroy();
|
surfaces.node.destroy();
|
||||||
|
surfaces.river_shell_surface.destroy();
|
||||||
surfaces.wl_surface.destroy();
|
surfaces.wl_surface.destroy();
|
||||||
bar.context.buffer_pool.surface_count -= 1;
|
bar.context.buffer_pool.surface_count -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layerSurfaceListener(
|
pub fn manage(bar: *Bar) !void {
|
||||||
layer_surface: *zwlr.LayerSurfaceV1,
|
if (!bar.configured) return;
|
||||||
event: zwlr.LayerSurfaceV1.Event,
|
defer bar.pending_manage = .{};
|
||||||
bar: *Bar,
|
|
||||||
) void {
|
|
||||||
assert(bar.surfaces.?.layer_surface == layer_surface);
|
|
||||||
switch (event) {
|
|
||||||
.configure => |ev| {
|
|
||||||
layer_surface.ackConfigure(ev.serial);
|
|
||||||
const width: u31 = @intCast(ev.width);
|
|
||||||
const height: u31 = @intCast(ev.height);
|
|
||||||
|
|
||||||
if (bar.configured and
|
// The only manage actions we need to do are when the output changes geometry
|
||||||
bar.width == width and
|
if (!bar.pending_manage.output_geometry) return;
|
||||||
bar.height == height and
|
|
||||||
bar.output.scale == bar.font_scale)
|
|
||||||
{
|
|
||||||
bar.surfaces.?.wl_surface.commit();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log.debug("Configuring bar surface with width {} and height {}", .{ width, height });
|
const output = bar.output;
|
||||||
bar.width = width;
|
|
||||||
bar.height = height;
|
|
||||||
// Exclusive zone == the bar's height
|
|
||||||
layer_surface.setExclusiveZone(bar.height);
|
|
||||||
|
|
||||||
// Full surface should be opaque
|
|
||||||
const opaque_region: *wl.Region = bar.context.wl_compositor.createRegion() catch |e| {
|
|
||||||
log.err("Failed to create opaque region for bar: {}", .{e});
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
defer opaque_region.destroy();
|
|
||||||
opaque_region.add(0, 0, bar.width, bar.height);
|
|
||||||
bar.surfaces.?.wl_surface.setOpaqueRegion(opaque_region);
|
|
||||||
|
|
||||||
bar.configured = true;
|
|
||||||
|
|
||||||
bar.render() catch |err| {
|
|
||||||
log.err("Bar render failed: {}", .{err});
|
|
||||||
};
|
|
||||||
},
|
|
||||||
.closed => {
|
|
||||||
bar.deinit();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Renders the bar and its components
|
|
||||||
pub fn render(bar: *Bar) !void {
|
|
||||||
const context = bar.context;
|
|
||||||
const options = bar.options;
|
const options = bar.options;
|
||||||
|
|
||||||
const scale = bar.output.scale;
|
// Recreate fonts if the output scale changed, so geometry calculations
|
||||||
|
// below use the correct font metrics.
|
||||||
// Recreate fonts at the output's new scale
|
const scale = output.scale;
|
||||||
if (scale != bar.font_scale) {
|
if (scale != bar.font_scale) {
|
||||||
bar.fcft_fonts.destroy();
|
bar.fcft_fonts.destroy();
|
||||||
bar.fcft_fonts = try getFcftFonts(bar.options.fonts, scale);
|
bar.fcft_fonts = try getFcftFonts(bar.options.fonts, scale);
|
||||||
bar.font_scale = scale;
|
bar.font_scale = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const vertical_padding = 5;
|
||||||
|
const logical_font_height = @divFloor(bar.fcft_fonts.height, @as(i32, bar.font_scale));
|
||||||
|
const height: u31 = @intCast(logical_font_height + 2 * vertical_padding);
|
||||||
|
const width: u31 = output.geometry.width;
|
||||||
|
|
||||||
|
if (bar.geometry.width != width or bar.geometry.height != height) {
|
||||||
|
bar.geometry.width = width;
|
||||||
|
bar.geometry.height = height;
|
||||||
|
|
||||||
|
const opaque_region = try bar.context.wl_compositor.createRegion();
|
||||||
|
defer opaque_region.destroy();
|
||||||
|
opaque_region.add(0, 0, width, height);
|
||||||
|
bar.surfaces.?.wl_surface.setOpaqueRegion(opaque_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
const x = output.geometry.x + options.margins.left;
|
||||||
|
const y = switch (options.position) {
|
||||||
|
.top => output.geometry.y + options.margins.top,
|
||||||
|
.bottom => output.geometry.y + output.geometry.height - bar.geometry.height - options.margins.bottom,
|
||||||
|
};
|
||||||
|
bar.pending_render.position = .{ .x = x, .y = y };
|
||||||
|
bar.pending_render.draw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render(bar: *Bar) void {
|
||||||
|
if (!bar.configured) return;
|
||||||
|
defer bar.pending_render = .{};
|
||||||
|
|
||||||
|
const surfaces = bar.surfaces orelse return;
|
||||||
|
|
||||||
|
if (bar.pending_render.position) |position| {
|
||||||
|
surfaces.node.setPosition(position.x, position.y);
|
||||||
|
surfaces.node.placeTop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bar.pending_render.draw) {
|
||||||
|
bar.draw() catch |err| {
|
||||||
|
log.err("Bar draw failed: {}", .{err});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw the bar and its components (clock, title, etc.)
|
||||||
|
pub fn draw(bar: *Bar) !void {
|
||||||
|
const context = bar.context;
|
||||||
|
const options = bar.options;
|
||||||
|
|
||||||
|
const scale = bar.font_scale;
|
||||||
|
|
||||||
// Scaled width/height
|
// Scaled width/height
|
||||||
const render_width = bar.width * scale;
|
const render_width = bar.geometry.width * scale;
|
||||||
const render_height = bar.height * scale;
|
const render_height = bar.geometry.height * scale;
|
||||||
|
|
||||||
// Don't have anything to render
|
// Don't have anything to render
|
||||||
if (render_width == 0 or render_height == 0 or scale == 0) {
|
if (render_width == 0 or render_height == 0 or scale == 0) {
|
||||||
|
|
@ -243,6 +246,7 @@ pub fn render(bar: *Bar) !void {
|
||||||
// Finally, attach the buffer to the surface
|
// Finally, attach the buffer to the surface
|
||||||
const surfaces = bar.surfaces orelse return error.NoSurfaces;
|
const surfaces = bar.surfaces orelse return error.NoSurfaces;
|
||||||
const wl_surface = surfaces.wl_surface;
|
const wl_surface = surfaces.wl_surface;
|
||||||
|
surfaces.river_shell_surface.syncNextCommit();
|
||||||
wl_surface.setBufferScale(scale);
|
wl_surface.setBufferScale(scale);
|
||||||
wl_surface.attach(buffer.wl_buffer, 0, 0);
|
wl_surface.attach(buffer.wl_buffer, 0, 0);
|
||||||
wl_surface.damageBuffer(0, 0, render_width, render_height);
|
wl_surface.damageBuffer(0, 0, render_width, render_height);
|
||||||
|
|
@ -393,12 +397,13 @@ const unicode = std.unicode;
|
||||||
|
|
||||||
const wayland = @import("wayland");
|
const wayland = @import("wayland");
|
||||||
const wl = wayland.client.wl;
|
const wl = wayland.client.wl;
|
||||||
const zwlr = wayland.client.zwlr;
|
const river = wayland.client.river;
|
||||||
const fcft = @import("fcft");
|
const fcft = @import("fcft");
|
||||||
const pixman = @import("pixman");
|
const pixman = @import("pixman");
|
||||||
const zeit = @import("zeit");
|
const zeit = @import("zeit");
|
||||||
|
|
||||||
const utils = @import("utils.zig");
|
const utils = @import("utils.zig");
|
||||||
|
const Rect = utils.Rect;
|
||||||
const Buffer = @import("Buffer.zig");
|
const Buffer = @import("Buffer.zig");
|
||||||
const Context = @import("Context.zig");
|
const Context = @import("Context.zig");
|
||||||
const Output = @import("Output.zig");
|
const Output = @import("Output.zig");
|
||||||
|
|
|
||||||
|
|
@ -216,12 +216,7 @@ pub fn manage(context: *Context) void {
|
||||||
log.err("Failed to create bar: {}", .{e});
|
log.err("Failed to create bar: {}", .{e});
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
// If the output already has a wl_output, init the surface immediately
|
output.bar.?.pending_manage.output_geometry = true;
|
||||||
if (output.wl_output != null) {
|
|
||||||
output.bar.?.initSurface() catch |e| {
|
|
||||||
log.err("Failed to init bar surface: {}", .{e});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,11 @@ name: ?[]const u8 = null,
|
||||||
scale: u31 = 1,
|
scale: u31 = 1,
|
||||||
geometry: Rect = .{},
|
geometry: Rect = .{},
|
||||||
|
|
||||||
// Area left after layer shell surfaces take exclusive area
|
// Area available for window layout (output geometry minus bar space)
|
||||||
|
// Maybe I'll re-add support for layer shell exclusive areas later,
|
||||||
|
// but adding that makes it more work for me and I don't personally
|
||||||
|
// know of anything that makes me want them since external bars won't
|
||||||
|
// work with beansprout.
|
||||||
usable_geometry: Rect = .{},
|
usable_geometry: Rect = .{},
|
||||||
|
|
||||||
// Information for this Output's wallpaper
|
// Information for this Output's wallpaper
|
||||||
|
|
@ -72,8 +76,6 @@ pub const PendingManage = struct {
|
||||||
position: ?struct { x: i32, y: i32 } = null,
|
position: ?struct { x: i32, y: i32 } = null,
|
||||||
dimensions: ?struct { width: u31, height: u31 } = null,
|
dimensions: ?struct { width: u31, height: u31 } = null,
|
||||||
|
|
||||||
usable_geometry: ?Rect = null,
|
|
||||||
|
|
||||||
tags: ?u32 = null,
|
tags: ?u32 = null,
|
||||||
primary_ratio: ?f32 = null,
|
primary_ratio: ?f32 = null,
|
||||||
primary_count: ?u8 = null,
|
primary_count: ?u8 = null,
|
||||||
|
|
@ -116,7 +118,6 @@ pub fn create(context: *Context, river_output_v1: *river.OutputV1) !*Output {
|
||||||
output.windows.init();
|
output.windows.init();
|
||||||
|
|
||||||
output.river_output_v1.setListener(*Output, riverOutputListener, output);
|
output.river_output_v1.setListener(*Output, riverOutputListener, output);
|
||||||
output.river_layer_shell_output_v1.setListener(*Output, riverLayerShellOutputListener, output);
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
@ -285,16 +286,10 @@ fn wlOutputListener(_: *wl.Output, event: wl.Output.Event, output: *Output) void
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if (output.bar) |*bar| {
|
if (output.bar) |*bar| {
|
||||||
bar.initSurface() catch |err| {
|
// Trigger a full manage cycle if the scale changed so that
|
||||||
const output_name = output.name orelse "some output";
|
// fonts are reloaded and bar geometry is recalculated.
|
||||||
log.err("failed to init bar for {s}: {}", .{ output_name, err });
|
if (output.scale != bar.font_scale) {
|
||||||
return;
|
bar.pending_manage.output_geometry = true;
|
||||||
};
|
|
||||||
// Re-render bar if the scale changed
|
|
||||||
if (bar.configured and output.scale != bar.font_scale) {
|
|
||||||
bar.render() catch |err| {
|
|
||||||
log.err("Bar render failed: {}", .{err});
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Re-render wallpaper if scale changed
|
// Re-render wallpaper if scale changed
|
||||||
|
|
@ -320,26 +315,6 @@ fn wlOutputListener(_: *wl.Output, event: wl.Output.Event, output: *Output) void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used for the river_layer_shell_output_v1 interface
|
|
||||||
fn riverLayerShellOutputListener(
|
|
||||||
river_layer_shell_output_v1: *river.LayerShellOutputV1,
|
|
||||||
event: river.LayerShellOutputV1.Event,
|
|
||||||
output: *Output,
|
|
||||||
) void {
|
|
||||||
assert(output.river_layer_shell_output_v1 == river_layer_shell_output_v1);
|
|
||||||
switch (event) {
|
|
||||||
.non_exclusive_area => |ev| {
|
|
||||||
output.pending_manage.usable_geometry = .{
|
|
||||||
.x = ev.x,
|
|
||||||
.y = ev.y,
|
|
||||||
.width = @intCast(ev.width),
|
|
||||||
.height = @intCast(ev.height),
|
|
||||||
};
|
|
||||||
output.context.wm.river_window_manager_v1.manageDirty();
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initWallpaperLayerSurface(output: *Output) !void {
|
pub fn initWallpaperLayerSurface(output: *Output) !void {
|
||||||
if (output.context.wallpaper_image == null) {
|
if (output.context.wallpaper_image == null) {
|
||||||
// No wallpaper image, so we don't need any surfaces
|
// No wallpaper image, so we don't need any surfaces
|
||||||
|
|
@ -535,8 +510,10 @@ pub fn manage(output: *Output) void {
|
||||||
output.geometry.height = dimensions.height;
|
output.geometry.height = dimensions.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.pending_manage.usable_geometry) |usable_geometry| {
|
if (output.pending_manage.position != null or output.pending_manage.dimensions != null) {
|
||||||
output.usable_geometry = usable_geometry;
|
if (output.bar) |*bar| {
|
||||||
|
bar.pending_manage.output_geometry = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (output.pending_manage.primary_ratio) |primary_ratio| {
|
if (output.pending_manage.primary_ratio) |primary_ratio| {
|
||||||
|
|
@ -605,6 +582,34 @@ pub fn manage(output: *Output) void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (output.bar) |*bar| {
|
||||||
|
bar.manage() catch |err| {
|
||||||
|
log.err("Bar manage failed: {}", .{err});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute usable geometry from output geometry minus bar space.
|
||||||
|
// We don't use non_exclusive_area from layer shell since we don't support
|
||||||
|
// other layer shell clients with exclusive zones (layer shell clients that
|
||||||
|
// don't use exclusive areas are fine).
|
||||||
|
output.usable_geometry = output.geometry;
|
||||||
|
if (output.bar) |bar| {
|
||||||
|
if (bar.geometry.height > 0) {
|
||||||
|
const bar_height: i32 = bar.geometry.height;
|
||||||
|
const margins = bar.options.margins;
|
||||||
|
const reserved: u31 = @intCast(bar_height + margins.top + margins.bottom);
|
||||||
|
switch (bar.options.position) {
|
||||||
|
.top => {
|
||||||
|
output.usable_geometry.y += bar_height + margins.top + margins.bottom;
|
||||||
|
output.usable_geometry.height -|= reserved;
|
||||||
|
},
|
||||||
|
.bottom => {
|
||||||
|
output.usable_geometry.height -|= reserved;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate layout before managing windows, but only if output dimensions are initialized
|
// Calculate layout before managing windows, but only if output dimensions are initialized
|
||||||
if (output.usable_geometry.width > 0 and output.usable_geometry.height > 0) {
|
if (output.usable_geometry.width > 0 and output.usable_geometry.height > 0) {
|
||||||
output.calculateLayout();
|
output.calculateLayout();
|
||||||
|
|
@ -617,6 +622,10 @@ pub fn manage(output: *Output) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(output: *Output) void {
|
pub fn render(output: *Output) void {
|
||||||
|
if (output.bar) |*bar| {
|
||||||
|
bar.render();
|
||||||
|
}
|
||||||
|
|
||||||
const seat = output.context.wm.seats.first();
|
const seat = output.context.wm.seats.first();
|
||||||
const focused = if (seat) |s| s.focused_window else null;
|
const focused = if (seat) |s| s.focused_window else null;
|
||||||
|
|
||||||
|
|
@ -670,7 +679,7 @@ fn calculateLayout(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
|
// Use the usable area for layout so windows don't overlap the bar
|
||||||
const output_x = output.usable_geometry.x;
|
const output_x = output.usable_geometry.x;
|
||||||
const output_y = output.usable_geometry.y;
|
const output_y = output.usable_geometry.y;
|
||||||
const output_width = output.usable_geometry.width;
|
const output_width = output.usable_geometry.width;
|
||||||
|
|
@ -681,14 +690,14 @@ fn calculateLayout(output: *Output) void {
|
||||||
if (active_count == 1) {
|
if (active_count == 1) {
|
||||||
const window: *Window = @fieldParentPtr("active_list_node", active_list.popFirst().?);
|
const window: *Window = @fieldParentPtr("active_list_node", active_list.popFirst().?);
|
||||||
|
|
||||||
const width = @as(u31, @intFromFloat(@as(f32, @floatFromInt(output_width)) * output.single_window_ratio)) -
|
const width = @as(u31, @intFromFloat(@as(f32, @floatFromInt(output_width)) * output.single_window_ratio)) -|
|
||||||
2 * border_width;
|
2 * border_width;
|
||||||
const x = output_x + @divFloor(output_width - width, 2);
|
const x = output_x + @divFloor(output_width - width, 2);
|
||||||
|
|
||||||
window.pending_render.position = .{ .x = x, .y = output_y + border_width };
|
window.pending_render.position = .{ .x = x, .y = output_y + border_width };
|
||||||
window.pending_manage.dimensions = .{
|
window.pending_manage.dimensions = .{
|
||||||
.width = width,
|
.width = width,
|
||||||
.height = output_height - 2 * border_width,
|
.height = output_height -| 2 * border_width,
|
||||||
};
|
};
|
||||||
window.pending_manage.maximized = true;
|
window.pending_manage.maximized = true;
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -56,10 +56,7 @@ pub const PendingManage = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PendingRender = struct {
|
pub const PendingRender = struct {
|
||||||
position: ?struct {
|
position: ?struct { x: i32, y: i32 } = null,
|
||||||
x: i32,
|
|
||||||
y: i32,
|
|
||||||
} = null,
|
|
||||||
|
|
||||||
focused: ?bool = null,
|
focused: ?bool = null,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -146,9 +146,8 @@ fn run(wl_display: *wl.Display, context: *Context) !void {
|
||||||
var it = context.wm.outputs.iterator(.forward);
|
var it = context.wm.outputs.iterator(.forward);
|
||||||
while (it.next()) |output| {
|
while (it.next()) |output| {
|
||||||
if (output.bar) |*bar| {
|
if (output.bar) |*bar| {
|
||||||
bar.render() catch |err| {
|
bar.pending_render.draw = true;
|
||||||
log.err("Bar timer render failed: {}", .{err});
|
context.wm.river_window_manager_v1.manageDirty();
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue