refactor(gui): improve hidpi scaling support
This commit is contained in:
parent
f484ea0b57
commit
6faea2ef02
1 changed files with 28 additions and 7 deletions
|
|
@ -42,6 +42,10 @@ var font_name_len: usize = 0;
|
||||||
var font_dirty: std.atomic.Value(bool) = .init(true);
|
var font_dirty: std.atomic.Value(bool) = .init(true);
|
||||||
var stop_requested: std.atomic.Value(bool) = .init(false);
|
var stop_requested: std.atomic.Value(bool) = .init(false);
|
||||||
|
|
||||||
|
// HiDPI scale factor (logical → physical pixels). Updated from wio .scale events.
|
||||||
|
// Only read/written on the wio thread after initialisation.
|
||||||
|
var dpi_scale: f32 = 1.0;
|
||||||
|
|
||||||
// Window title (written from TUI thread, applied by wio thread)
|
// Window title (written from TUI thread, applied by wio thread)
|
||||||
var title_mutex: std.Thread.Mutex = .{};
|
var title_mutex: std.Thread.Mutex = .{};
|
||||||
var title_buf: [512]u8 = undefined;
|
var title_buf: [512]u8 = undefined;
|
||||||
|
|
@ -213,8 +217,11 @@ const CellPos = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
fn pixelToCellPos(pos: wio.Position) CellPos {
|
fn pixelToCellPos(pos: wio.Position) CellPos {
|
||||||
const x: i32 = @intCast(pos.x);
|
// Mouse positions are in logical pixels; cell_size is in physical pixels.
|
||||||
const y: i32 = @intCast(pos.y);
|
// Scale up to physical before dividing so that col/row and sub-cell offsets
|
||||||
|
// are all expressed in physical pixels, matching the GPU coordinate space.
|
||||||
|
const x: i32 = @intFromFloat(@as(f32, @floatFromInt(pos.x)) * dpi_scale);
|
||||||
|
const y: i32 = @intFromFloat(@as(f32, @floatFromInt(pos.y)) * dpi_scale);
|
||||||
const cw: i32 = wio_font.cell_size.x;
|
const cw: i32 = wio_font.cell_size.x;
|
||||||
const ch: i32 = wio_font.cell_size.y;
|
const ch: i32 = wio_font.cell_size.y;
|
||||||
return .{
|
return .{
|
||||||
|
|
@ -228,7 +235,8 @@ fn pixelToCellPos(pos: wio.Position) CellPos {
|
||||||
// Reload wio_font from current settings. Called only from the wio thread.
|
// Reload wio_font from current settings. Called only from the wio thread.
|
||||||
fn reloadFont() void {
|
fn reloadFont() void {
|
||||||
const name = if (font_name_len > 0) font_name_buf[0..font_name_len] else "monospace";
|
const name = if (font_name_len > 0) font_name_buf[0..font_name_len] else "monospace";
|
||||||
wio_font = gpu.loadFont(name, font_size_px) catch return;
|
const size_physical: u16 = @intFromFloat(@round(@as(f32, @floatFromInt(font_size_px)) * dpi_scale));
|
||||||
|
wio_font = gpu.loadFont(name, @max(size_physical, 4)) catch return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check dirty flag and reload if needed.
|
// Check dirty flag and reload if needed.
|
||||||
|
|
@ -298,19 +306,28 @@ fn wioLoop() void {
|
||||||
};
|
};
|
||||||
defer gpu.deinit();
|
defer gpu.deinit();
|
||||||
|
|
||||||
// Load the initial font on the wio thread (gpu.init must be done first).
|
|
||||||
reloadFont();
|
|
||||||
|
|
||||||
var state = gpu.WindowState.init();
|
var state = gpu.WindowState.init();
|
||||||
defer state.deinit();
|
defer state.deinit();
|
||||||
|
|
||||||
// Current window size in pixels (updated by size_physical events)
|
// Current window sizes (updated by size_* events).
|
||||||
var win_size: wio.Size = .{ .width = 1280, .height = 720 };
|
var win_size: wio.Size = .{ .width = 1280, .height = 720 };
|
||||||
// Cell grid dimensions (updated on resize)
|
// Cell grid dimensions (updated on resize)
|
||||||
var cell_width: u16 = 80;
|
var cell_width: u16 = 80;
|
||||||
var cell_height: u16 = 24;
|
var cell_height: u16 = 24;
|
||||||
|
|
||||||
|
// Drain the initial wio events (scale + size_*) that are queued synchronously
|
||||||
|
// during createWindow. This ensures dpi_scale and win_size are correct before
|
||||||
|
// the first reloadFont / sendResize, avoiding a brief render at the wrong scale.
|
||||||
|
while (window.getEvent()) |event| {
|
||||||
|
switch (event) {
|
||||||
|
.scale => |s| dpi_scale = s,
|
||||||
|
.size_physical => |sz| win_size = sz,
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Notify the tui that the window is ready
|
// Notify the tui that the window is ready
|
||||||
|
reloadFont();
|
||||||
sendResize(win_size, &state, &cell_width, &cell_height);
|
sendResize(win_size, &state, &cell_width, &cell_height);
|
||||||
tui_pid.send(.{ "RDR", "WindowCreated", @as(usize, 0) }) catch {};
|
tui_pid.send(.{ "RDR", "WindowCreated", @as(usize, 0) }) catch {};
|
||||||
|
|
||||||
|
|
@ -330,6 +347,10 @@ fn wioLoop() void {
|
||||||
.close => {
|
.close => {
|
||||||
running = false;
|
running = false;
|
||||||
},
|
},
|
||||||
|
.scale => |s| {
|
||||||
|
dpi_scale = s;
|
||||||
|
font_dirty.store(true, .release);
|
||||||
|
},
|
||||||
.size_physical => |sz| {
|
.size_physical => |sz| {
|
||||||
win_size = sz;
|
win_size = sz;
|
||||||
sendResize(sz, &state, &cell_width, &cell_height);
|
sendResize(sz, &state, &cell_width, &cell_height);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue