Fix wallpaper and bar rendering when scale >1
We track the scale for wallpaper and render now and have to re-render when the scale changes. For the bar, this includes recreated the fcft fonts.
This commit is contained in:
parent
1cfafc4fb3
commit
83946ce97a
5 changed files with 77 additions and 18 deletions
|
|
@ -3,7 +3,7 @@
|
|||
These are in rough order of my priority, though no promises I do them in this order.
|
||||
|
||||
- [ ] Implement a river-tag-overlay clone
|
||||
- [ ] Implement an optional clock bar
|
||||
- [ ] Add options to the bar and river-tag-overlay
|
||||
- [ ] Make a Rect struct to combine x, y, width, and height
|
||||
- [ ] Support window rules (float/tags/SSD by app-id/title)
|
||||
- [ ] Support overriding config location
|
||||
|
|
@ -28,3 +28,4 @@ These are in rough order of my priority, though no promises I do them in this or
|
|||
- [x] Support per-host config using properties
|
||||
- [x] Implement primary count/ratio per tagmask
|
||||
- [x] Add primary_count and primary_ratio to Config
|
||||
- [x] Implement an optional clock bar
|
||||
|
|
|
|||
44
src/Bar.zig
44
src/Bar.zig
|
|
@ -4,14 +4,17 @@
|
|||
|
||||
const Bar = @This();
|
||||
|
||||
/// Standard base DPI at a scale of 1
|
||||
const base_dpi = 96;
|
||||
|
||||
context: *Context,
|
||||
|
||||
// TODO: Get this in Config then save in Context
|
||||
fonts: *fcft.Font,
|
||||
/// The timezone of the computer.
|
||||
timezone: zeit.timezone.TimeZone,
|
||||
|
||||
/// The output that this Bar is on
|
||||
fonts: *fcft.Font,
|
||||
font_scale: u31 = 0,
|
||||
|
||||
output: *Output,
|
||||
|
||||
// Bar geometry
|
||||
|
|
@ -34,7 +37,7 @@ pub fn init(context: *Context, output: *Output) !Bar {
|
|||
|
||||
return .{
|
||||
.context = context,
|
||||
.fonts = try getFcftFonts("monospace:size=14"),
|
||||
.fonts = try getFcftFonts("monospace:size=14", 1),
|
||||
.timezone = timezone,
|
||||
.output = output,
|
||||
};
|
||||
|
|
@ -50,8 +53,8 @@ pub fn initSurface(bar: *Bar) !void {
|
|||
const context = bar.context;
|
||||
|
||||
// TODO: Add padding to config
|
||||
const padding = 5;
|
||||
const bar_height: u31 = @intCast(bar.fonts.height + 2 * padding);
|
||||
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();
|
||||
|
|
@ -99,7 +102,11 @@ pub fn layerSurfaceListener(
|
|||
const width: u31 = @intCast(ev.width);
|
||||
const height: u31 = @intCast(ev.height);
|
||||
|
||||
if (bar.configured and bar.width == width and bar.height == height) {
|
||||
if (bar.configured and
|
||||
bar.width == width and
|
||||
bar.height == height and
|
||||
bar.output.scale == bar.font_scale)
|
||||
{
|
||||
if (bar.wl_surface) |wl_surface| {
|
||||
wl_surface.commit();
|
||||
} else {
|
||||
|
|
@ -143,6 +150,13 @@ pub fn render(bar: *Bar) !void {
|
|||
|
||||
const scale = bar.output.scale;
|
||||
|
||||
// Recreate fonts at the output's new scale
|
||||
if (scale != bar.font_scale) {
|
||||
bar.fonts.destroy();
|
||||
bar.fonts = try getFcftFonts("monospace:size=14", scale);
|
||||
bar.font_scale = scale;
|
||||
}
|
||||
|
||||
// Scaled width/height
|
||||
const render_width = bar.width * scale;
|
||||
const render_height = bar.height * scale;
|
||||
|
|
@ -210,8 +224,9 @@ pub fn render(bar: *Bar) !void {
|
|||
|
||||
// Finally, attach the buffer to the surface
|
||||
const wl_surface = bar.wl_surface orelse return;
|
||||
wl_surface.setBufferScale(scale);
|
||||
wl_surface.attach(buffer.wl_buffer, 0, 0);
|
||||
wl_surface.damageBuffer(0, 0, bar.width, bar.height);
|
||||
wl_surface.damageBuffer(0, 0, render_width, render_height);
|
||||
wl_surface.commit();
|
||||
}
|
||||
|
||||
|
|
@ -318,8 +333,8 @@ fn renderGlyphs(
|
|||
}
|
||||
}
|
||||
|
||||
// Borrowed from https://git.sr.ht/~novakane/zig-fcft-example
|
||||
fn getFcftFonts(fonts: []const u8) !*fcft.Font {
|
||||
// Borrowed and modified from https://git.sr.ht/~novakane/zig-fcft-example
|
||||
fn getFcftFonts(fonts: []const u8, scale: u31) !*fcft.Font {
|
||||
// Create an arena to free just for this function;
|
||||
// It makes cleaning up the ArrayList easier.
|
||||
var arena = std.heap.ArenaAllocator.init(utils.gpa);
|
||||
|
|
@ -330,8 +345,17 @@ fn getFcftFonts(fonts: []const u8) !*fcft.Font {
|
|||
|
||||
var it = mem.tokenizeScalar(u8, fonts, ',');
|
||||
while (it.next()) |font| {
|
||||
if (scale > 1) {
|
||||
// If scale >1, we append :dpi so we can scale the font
|
||||
const scaled = try arena_alloc.dupeZ(
|
||||
u8,
|
||||
try std.fmt.allocPrint(arena_alloc, "{s}:dpi={}", .{ font, @as(u32, base_dpi) * scale }),
|
||||
);
|
||||
try list.append(arena_alloc, scaled);
|
||||
} else {
|
||||
try list.append(arena_alloc, try arena_alloc.dupeZ(u8, font));
|
||||
}
|
||||
}
|
||||
|
||||
const fcft_fonts = try fcft.Font.fromName(list.items[0..], null);
|
||||
errdefer fcft_fonts.destroy();
|
||||
|
|
|
|||
|
|
@ -477,7 +477,22 @@ fn loadKeybindsChildBlock(config: *Config, parser: *kdl.Parser, hostname: ?[]con
|
|||
logWarnMissingNodeArg(name, "command");
|
||||
continue;
|
||||
});
|
||||
const split_exec = try utils.tokenizeToOwnedSlices(exec_str, ' ');
|
||||
var split_exec = try utils.tokenizeToOwnedSlices(exec_str, ' ');
|
||||
if (split_exec.len > 0) {
|
||||
// Expand ~ in executable paths
|
||||
const expanded = expandTilde(split_exec[0]) catch |e| {
|
||||
if (e == error.HomeNotSet) {
|
||||
// No ~, just return what we had.
|
||||
break :sw .{ .spawn = split_exec };
|
||||
} else {
|
||||
return e;
|
||||
}
|
||||
};
|
||||
// tokenizeToOwnedSlices dupes each token, so we have to
|
||||
// free the original value before replacing it.
|
||||
utils.gpa.free(split_exec[0]);
|
||||
split_exec[0] = expanded;
|
||||
}
|
||||
break :sw .{ .spawn = split_exec };
|
||||
},
|
||||
.change_ratio => {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ usable_width: u31 = 0,
|
|||
usable_height: u31 = 0,
|
||||
|
||||
// Information for this Output's wallpaper
|
||||
wallpaper_render_scale: u31 = 0,
|
||||
wallpaper_render_width: u31 = 0,
|
||||
wallpaper_render_height: u31 = 0,
|
||||
wl_surface: ?*wl.Surface = null,
|
||||
|
|
@ -265,6 +266,18 @@ fn wlOutputListener(_: *wl.Output, event: wl.Output.Event, output: *Output) void
|
|||
log.err("failed to init bar for {s}: {}", .{ output_name, err });
|
||||
return;
|
||||
};
|
||||
// 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
|
||||
if (output.configured and output.scale != output.wallpaper_render_scale) {
|
||||
output.renderWallpaper() catch |err| {
|
||||
log.err("Wallpaper render failed: {}", .{err});
|
||||
};
|
||||
}
|
||||
},
|
||||
.scale => |ev| {
|
||||
|
|
@ -361,7 +374,11 @@ fn wallpaperLayerSurfaceListener(layer_surface: *zwlr.LayerSurfaceV1, event: zwl
|
|||
const width: u31 = @intCast(ev.width);
|
||||
const height: u31 = @intCast(ev.height);
|
||||
|
||||
if (output.configured and output.wallpaper_render_width == width and output.wallpaper_render_height == height) {
|
||||
if (output.configured and
|
||||
output.wallpaper_render_width == width and
|
||||
output.wallpaper_render_height == height and
|
||||
output.scale == output.wallpaper_render_scale)
|
||||
{
|
||||
if (output.wl_surface) |wl_surface| {
|
||||
wl_surface.commit();
|
||||
} else {
|
||||
|
|
@ -393,7 +410,7 @@ fn calculateScale(image_dimension: c_int, output_dimension: u31, scale: u31) f64
|
|||
return numerator / denominator;
|
||||
}
|
||||
|
||||
/// Calculates (image_dimension / dimension_scale - output_dimension) / 2 / dimension_scale;
|
||||
/// Calculates (image_dimension / dimension_scale - output_dimension) / 2 / dimension_scale
|
||||
fn calculateTransform(image_dimension: c_int, output_dimension: u31, dimension_scale: f64) f64 {
|
||||
const numerator1: f64 = @floatFromInt(image_dimension);
|
||||
const denominator1: f64 = dimension_scale;
|
||||
|
|
@ -441,8 +458,8 @@ pub fn renderWallpaper(output: *Output) !void {
|
|||
|
||||
// Calculate translation offsets to center the image on the output.
|
||||
// If the scaled image is larger than the output, the offset crops equally from both sides.
|
||||
const tx: f64 = calculateTransform(image_width, width, sx);
|
||||
const ty: f64 = calculateTransform(image_height, height, sy);
|
||||
const tx: f64 = calculateTransform(image_width, width * scale, sx);
|
||||
const ty: f64 = calculateTransform(image_height, height * scale, sy);
|
||||
|
||||
// Build a combined source-to-destination transform matrix.
|
||||
// Pixman transforms map destination pixels back to source pixels, so:
|
||||
|
|
@ -473,6 +490,8 @@ pub fn renderWallpaper(output: *Output) !void {
|
|||
wl_surface.attach(buffer.wl_buffer, 0, 0);
|
||||
wl_surface.damageBuffer(0, 0, width * scale, height * scale);
|
||||
wl_surface.commit();
|
||||
|
||||
output.wallpaper_render_scale = scale;
|
||||
}
|
||||
|
||||
pub fn manage(output: *Output) void {
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ pub fn parseModifiers(s: []const u8) !?river.SeatV1.Modifiers {
|
|||
return modifiers;
|
||||
}
|
||||
|
||||
pub fn tokenizeToOwnedSlices(input: []const u8, delimiter: u8) ![]const []const u8 {
|
||||
pub fn tokenizeToOwnedSlices(input: []const u8, delimiter: u8) ![][]const u8 {
|
||||
var list: std.ArrayList([]const u8) = .empty;
|
||||
var it = std.mem.tokenizeScalar(u8, input, delimiter);
|
||||
while (it.next()) |part| {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue