diff --git a/src/app/layout.zig b/src/app/layout.zig index 118e85b..41cd53e 100644 --- a/src/app/layout.zig +++ b/src/app/layout.zig @@ -4,6 +4,7 @@ const c = @import("../c.zig"); const font_mod = @import("../font.zig"); const pty_mod = @import("../pty.zig"); const renderer_mod = @import("../render/renderer.zig"); +const dpi = @import("../dpi.zig"); const session_state = @import("../session/state.zig"); const vt_stream = @import("../vt_stream.zig"); @@ -91,8 +92,8 @@ pub fn calculateHoveredSession( }; } -pub fn calculateTerminalSize(font: *const font_mod.Font, window_width: c_int, window_height: c_int, grid_font_scale: f32) TerminalSize { - const padding = renderer_mod.terminal_padding * 2; +pub fn calculateTerminalSize(font: *const font_mod.Font, window_width: c_int, window_height: c_int, grid_font_scale: f32, ui_scale: f32) TerminalSize { + const padding = dpi.scale(renderer_mod.terminal_padding, ui_scale) * 2; const usable_w = @max(0, window_width - padding); const usable_h = @max(0, window_height - padding); const scaled_cell_w = @max(1, @as(c_int, @intFromFloat(@as(f32, @floatFromInt(font.cell_width)) * grid_font_scale))); @@ -105,21 +106,21 @@ pub fn calculateTerminalSize(font: *const font_mod.Font, window_width: c_int, wi }; } -pub fn calculateGridCellTerminalSize(font: *const font_mod.Font, window_width: c_int, window_height: c_int, grid_font_scale: f32, grid_cols: usize, grid_rows: usize) TerminalSize { +pub fn calculateGridCellTerminalSize(font: *const font_mod.Font, window_width: c_int, window_height: c_int, grid_font_scale: f32, grid_cols: usize, grid_rows: usize, ui_scale: f32) TerminalSize { const cell_width = @divFloor(window_width, @as(c_int, @intCast(grid_cols))); const cell_height = @divFloor(window_height, @as(c_int, @intCast(grid_rows))); - return calculateTerminalSize(font, cell_width, cell_height, grid_font_scale); + return calculateTerminalSize(font, cell_width, cell_height, grid_font_scale, ui_scale); } -pub fn calculateTerminalSizeForMode(font: *const font_mod.Font, window_width: c_int, window_height: c_int, mode: app_state.ViewMode, grid_font_scale: f32, grid_cols: usize, grid_rows: usize) TerminalSize { +pub fn calculateTerminalSizeForMode(font: *const font_mod.Font, window_width: c_int, window_height: c_int, mode: app_state.ViewMode, grid_font_scale: f32, grid_cols: usize, grid_rows: usize, ui_scale: f32) TerminalSize { return switch (mode) { .Grid, .Expanding, .Collapsing, .GridResizing => { const grid_dim = @max(grid_cols, grid_rows); const base_grid_scale: f32 = 1.0 / @as(f32, @floatFromInt(grid_dim)); const effective_scale: f32 = base_grid_scale * grid_font_scale; - return calculateGridCellTerminalSize(font, window_width, window_height, effective_scale, grid_cols, grid_rows); + return calculateGridCellTerminalSize(font, window_width, window_height, effective_scale, grid_cols, grid_rows, ui_scale); }, - else => calculateTerminalSize(font, window_width, window_height, 1.0), + else => calculateTerminalSize(font, window_width, window_height, 1.0, ui_scale), }; } @@ -142,9 +143,10 @@ pub fn applyTerminalResize( rows: u16, render_width: c_int, render_height: c_int, + ui_scale: f32, ) void { - const usable_width = @max(0, render_width - renderer_mod.terminal_padding * 2); - const usable_height = @max(0, render_height - renderer_mod.terminal_padding * 2); + const usable_width = @max(0, render_width - dpi.scale(renderer_mod.terminal_padding, ui_scale) * 2); + const usable_height = @max(0, render_height - dpi.scale(renderer_mod.terminal_padding, ui_scale) * 2); const new_size = pty_mod.winsize{ .ws_row = rows, diff --git a/src/app/runtime.zig b/src/app/runtime.zig index e69a9e3..7221a0e 100644 --- a/src/app/runtime.zig +++ b/src/app/runtime.zig @@ -134,10 +134,10 @@ fn applyTerminalLayout( full_rows: *u16, ) void { const term_render_height = adjustedRenderHeightForMode(mode, render_height, ui_scale, grid_rows); - const term_size = layout.calculateTerminalSizeForMode(font, render_width, term_render_height, mode, grid_font_scale, grid_cols, grid_rows); + const term_size = layout.calculateTerminalSizeForMode(font, render_width, term_render_height, mode, grid_font_scale, grid_cols, grid_rows, ui_scale); full_cols.* = term_size.cols; full_rows.* = term_size.rows; - layout.applyTerminalResize(sessions, allocator, full_cols.*, full_rows.*, render_width, term_render_height); + layout.applyTerminalResize(sessions, allocator, full_cols.*, full_rows.*, render_width, term_render_height, ui_scale); } const SessionIndexSnapshot = struct { @@ -654,7 +654,7 @@ pub fn run() !void { var window_y: c_int = persistence.window.y; const initial_term_render_height = adjustedRenderHeightForMode(.Grid, render_height, ui_scale, grid.rows); - const initial_term_size = layout.calculateTerminalSizeForMode(&font, render_width, initial_term_render_height, .Grid, config.grid.font_scale, grid.cols, grid.rows); + const initial_term_size = layout.calculateTerminalSizeForMode(&font, render_width, initial_term_render_height, .Grid, config.grid.font_scale, grid.cols, grid.rows, ui_scale); var full_cols: u16 = initial_term_size.cols; var full_rows: u16 = initial_term_size.rows; @@ -946,16 +946,16 @@ pub fn run() !void { ui_font = try initSharedFont(allocator, renderer, &shared_font_cache, layout.scaledFontSize(ui_font_size, ui_scale)); ui.assets.ui_font = &ui_font; const term_render_height = adjustedRenderHeightForMode(anim_state.mode, render_height, ui_scale, grid.rows); - const new_term_size = layout.calculateTerminalSizeForMode(&font, render_width, term_render_height, anim_state.mode, config.grid.font_scale, grid.cols, grid.rows); + const new_term_size = layout.calculateTerminalSizeForMode(&font, render_width, term_render_height, anim_state.mode, config.grid.font_scale, grid.cols, grid.rows, ui_scale); full_cols = new_term_size.cols; full_rows = new_term_size.rows; - layout.applyTerminalResize(sessions, allocator, full_cols, full_rows, render_width, term_render_height); + layout.applyTerminalResize(sessions, allocator, full_cols, full_rows, render_width, term_render_height, ui_scale); } else { const term_render_height = adjustedRenderHeightForMode(anim_state.mode, render_height, ui_scale, grid.rows); - const new_term_size = layout.calculateTerminalSizeForMode(&font, render_width, term_render_height, anim_state.mode, config.grid.font_scale, grid.cols, grid.rows); + const new_term_size = layout.calculateTerminalSizeForMode(&font, render_width, term_render_height, anim_state.mode, config.grid.font_scale, grid.cols, grid.rows, ui_scale); full_cols = new_term_size.cols; full_rows = new_term_size.rows; - layout.applyTerminalResize(sessions, allocator, full_cols, full_rows, render_width, term_render_height); + layout.applyTerminalResize(sessions, allocator, full_cols, full_rows, render_width, term_render_height, ui_scale); } cell_width_pixels = @divFloor(render_width, @as(c_int, @intCast(grid.cols))); cell_height_pixels = @divFloor(render_height, @as(c_int, @intCast(grid.rows))); @@ -1306,10 +1306,10 @@ pub fn run() !void { font_size = target_size; const term_render_height = adjustedRenderHeightForMode(anim_state.mode, render_height, ui_scale, grid.rows); - const term_size = layout.calculateTerminalSizeForMode(&font, render_width, term_render_height, anim_state.mode, config.grid.font_scale, grid.cols, grid.rows); + const term_size = layout.calculateTerminalSizeForMode(&font, render_width, term_render_height, anim_state.mode, config.grid.font_scale, grid.cols, grid.rows, ui_scale); full_cols = term_size.cols; full_rows = term_size.rows; - layout.applyTerminalResize(sessions, allocator, full_cols, full_rows, render_width, term_render_height); + layout.applyTerminalResize(sessions, allocator, full_cols, full_rows, render_width, term_render_height, ui_scale); std.debug.print("Font size -> {d}px, terminal size: {d}x{d}\n", .{ font_size, full_cols, full_rows }); persistence.font_size = font_size; @@ -2187,10 +2187,10 @@ pub fn run() !void { const desired_font_scale = layout.gridFontScaleForMode(anim_state.mode, config.grid.font_scale); if (desired_font_scale != current_grid_font_scale) { const term_render_height = adjustedRenderHeightForMode(anim_state.mode, render_height, ui_scale, grid.rows); - const term_size = layout.calculateTerminalSizeForMode(&font, render_width, term_render_height, anim_state.mode, config.grid.font_scale, grid.cols, grid.rows); + const term_size = layout.calculateTerminalSizeForMode(&font, render_width, term_render_height, anim_state.mode, config.grid.font_scale, grid.cols, grid.rows, ui_scale); full_cols = term_size.cols; full_rows = term_size.rows; - layout.applyTerminalResize(sessions, allocator, full_cols, full_rows, render_width, term_render_height); + layout.applyTerminalResize(sessions, allocator, full_cols, full_rows, render_width, term_render_height, ui_scale); current_grid_font_scale = desired_font_scale; std.debug.print("Adjusted terminal size for view mode {s}: scale={d:.2} size={d}x{d}\n", .{ @tagName(anim_state.mode), diff --git a/src/render/renderer.zig b/src/render/renderer.zig index 181d968..0c35aec 100644 --- a/src/render/renderer.zig +++ b/src/render/renderer.zig @@ -309,7 +309,7 @@ fn renderSession( theme: *const colors.Theme, ui_scale: f32, ) RenderError!void { - try renderSessionContent(renderer, session, view, rect, scale, is_focused, font, term_cols, term_rows, current_time_ms, theme); + try renderSessionContent(renderer, session, view, rect, scale, is_focused, font, term_cols, term_rows, current_time_ms, theme, ui_scale); renderSessionOverlays(renderer, session, view, rect, is_focused, apply_effects, current_time_ms, is_grid_view, theme, ui_scale); cache_entry.presented_epoch = session.render_epoch; } @@ -326,6 +326,7 @@ fn renderSessionContent( term_rows: u16, _: i64, theme: *const colors.Theme, + ui_scale: f32, ) RenderError!void { if (!session.spawned) return; @@ -362,7 +363,7 @@ fn renderSessionContent( const cell_width_actual: c_int = @max(1, @as(c_int, @intFromFloat(@as(f32, @floatFromInt(base_cell_width)) * scale))); const cell_height_actual: c_int = @max(1, @as(c_int, @intFromFloat(@as(f32, @floatFromInt(base_cell_height)) * scale))); - const padding: c_int = terminal_padding; + const padding: c_int = dpi.scale(terminal_padding, ui_scale); const drawable_w: c_int = rect.w - padding * 2; const drawable_h: c_int = rect.h - padding * 2; if (drawable_w <= 0 or drawable_h <= 0) return; @@ -715,7 +716,7 @@ fn renderTerminalScrollbar( view.terminal_scrollbar.hideNow(); return; }; - const content_rect = terminalContentRect(rect) orelse { + const content_rect = terminalContentRect(rect, ui_scale) orelse { view.terminal_scrollbar.hideNow(); return; }; @@ -733,13 +734,14 @@ fn renderTerminalScrollbar( view.terminal_scrollbar.markDrawn(); } -fn terminalContentRect(rect: Rect) ?Rect { - const padded_w = rect.w - terminal_padding * 2; - const padded_h = rect.h - terminal_padding * 2; +fn terminalContentRect(rect: Rect, ui_scale: f32) ?Rect { + const padding = dpi.scale(terminal_padding, ui_scale); + const padded_w = rect.w - padding * 2; + const padded_h = rect.h - padding * 2; if (padded_w <= 0 or padded_h <= 0) return null; return .{ - .x = rect.x + terminal_padding, - .y = rect.y + terminal_padding, + .x = rect.x + padding, + .y = rect.y + padding, .w = padded_w, .h = padded_h, }; @@ -820,7 +822,7 @@ fn renderGridSessionCached( _ = c.SDL_SetRenderDrawColor(renderer, theme.background.r, theme.background.g, theme.background.b, 255); _ = c.SDL_RenderClear(renderer); const local_rect = Rect{ .x = 0, .y = 0, .w = rect.w, .h = rect.h }; - try renderSessionContent(renderer, session, view, local_rect, scale, is_focused, font, term_cols, term_rows, current_time_ms, theme); + try renderSessionContent(renderer, session, view, local_rect, scale, is_focused, font, term_cols, term_rows, current_time_ms, theme, ui_scale); if (any_waving and render_overlays) { renderSessionOverlays(renderer, session, view, local_rect, is_focused, apply_effects, current_time_ms, true, theme, ui_scale); } @@ -852,7 +854,7 @@ fn renderGridSessionCached( return; } - try renderSessionContent(renderer, session, view, rect, scale, is_focused, font, term_cols, term_rows, current_time_ms, theme); + try renderSessionContent(renderer, session, view, rect, scale, is_focused, font, term_cols, term_rows, current_time_ms, theme, ui_scale); cache_entry.presented_epoch = session.render_epoch; } diff --git a/src/ui/components/cwd_bar.zig b/src/ui/components/cwd_bar.zig index 9ef7086..00df323 100644 --- a/src/ui/components/cwd_bar.zig +++ b/src/ui/components/cwd_bar.zig @@ -20,7 +20,7 @@ const marquee_speed: f32 = 30.0; const fade_fade_width: c_int = 20; pub fn reservedHeight(ui_scale: f32) c_int { - return dpi.scale(cwd_bar_height, ui_scale) + renderer_mod.grid_border_thickness; + return dpi.scale(cwd_bar_height, ui_scale) + dpi.scale(renderer_mod.grid_border_thickness, ui_scale); } pub fn minCellHeight(ui_scale: f32) c_int { @@ -173,7 +173,7 @@ pub const CwdBarComponent = struct { const cwd_basename = info.cwd_basename orelse return; const bar_height = dpi.scale(cwd_bar_height, host.ui_scale); - const border_thickness = renderer_mod.grid_border_thickness; + const border_thickness = dpi.scale(renderer_mod.grid_border_thickness, host.ui_scale); const padding = dpi.scale(cwd_padding, host.ui_scale); const fade_width = dpi.scale(fade_fade_width, host.ui_scale); diff --git a/src/ui/components/session_interaction.zig b/src/ui/components/session_interaction.zig index 0407deb..c204cce 100644 --- a/src/ui/components/session_interaction.zig +++ b/src/ui/components/session_interaction.zig @@ -5,6 +5,7 @@ const input = @import("../../input/mapper.zig"); const open_url = @import("../../os/open.zig"); const geom = @import("../../geom.zig"); const renderer_mod = @import("../../render/renderer.zig"); +const dpi = @import("../../dpi.zig"); const session_state = @import("../../session/state.zig"); const url_matcher = @import("../../url_matcher.zig"); const font_mod = @import("../../font.zig"); @@ -192,7 +193,7 @@ pub const SessionInteractionComponent = struct { const view = &self.views[focused_idx]; if (focused.spawned and focused.terminal != null) { - if (fullViewPinFromMouse(focused, view, mouse_x, mouse_y, host.window_w, host.window_h, self.font, host.term_cols, host.term_rows)) |pin| { + if (fullViewPinFromMouse(focused, view, mouse_x, mouse_y, host.window_w, host.window_h, self.font, host.term_cols, host.term_rows, host.ui_scale)) |pin| { const clicks = event.button.clicks; if (clicks >= 3) { selectLine(focused, view, pin); @@ -243,7 +244,7 @@ pub const SessionInteractionComponent = struct { if (focused_idx < self.sessions.len) { var focused = self.sessions[focused_idx]; const view = &self.views[focused_idx]; - const pin = fullViewPinFromMouse(focused, view, mouse_x, mouse_y, host.window_w, host.window_h, self.font, host.term_cols, host.term_rows); + const pin = fullViewPinFromMouse(focused, view, mouse_x, mouse_y, host.window_w, host.window_h, self.font, host.term_cols, host.term_rows, host.ui_scale); if (view.selection_dragging) { if (pin) |p| { @@ -344,7 +345,7 @@ pub const SessionInteractionComponent = struct { var forwarded = false; if (should_forward) { if (terminal_opt) |terminal| { - if (fullViewCellFromMouse(mouse_x, mouse_y, host.window_w, host.window_h, self.font, host.term_cols, host.term_rows)) |cell| { + if (fullViewCellFromMouse(mouse_x, mouse_y, host.window_w, host.window_h, self.font, host.term_cols, host.term_rows, host.ui_scale)) |cell| { forwarded = true; const sgr_format = terminal.modes.get(.mouse_format_sgr); const direction: input.MouseScrollDirection = if (scroll_delta < 0) .up else .down; @@ -513,7 +514,7 @@ pub const SessionInteractionComponent = struct { if (!session.spawned) return null; const terminal = session.terminal orelse return null; const session_rect = sessionRectForIndex(host, session_idx) orelse return null; - const content_rect = terminalContentRect(session_rect) orelse return null; + const content_rect = terminalContentRect(session_rect, host.ui_scale) orelse return null; const bar = terminal.screens.active.pages.scrollbar(); const metrics = scrollbar.Metrics.init( @as(f32, @floatFromInt(bar.total)), @@ -583,8 +584,9 @@ fn fullViewCellFromMouse( font: *const font_mod.Font, term_cols: u16, term_rows: u16, + ui_scale: f32, ) ?CellPosition { - const padding = renderer_mod.terminal_padding; + const padding = dpi.scale(renderer_mod.terminal_padding, ui_scale); const origin_x: c_int = padding; const origin_y: c_int = padding; const drawable_w: c_int = render_width - padding * 2; @@ -615,10 +617,11 @@ fn fullViewPinFromMouse( font: *const font_mod.Font, term_cols: u16, term_rows: u16, + ui_scale: f32, ) ?ghostty_vt.Pin { if (!session.spawned or session.terminal == null) return null; - const padding = renderer_mod.terminal_padding; + const padding = dpi.scale(renderer_mod.terminal_padding, ui_scale); const origin_x: c_int = padding; const origin_y: c_int = padding; const drawable_w: c_int = render_width - padding * 2; @@ -1080,8 +1083,8 @@ fn sessionRectForIndex(host: *const types.UiHost, idx: usize) ?geom.Rect { }; } -fn terminalContentRect(session_rect: geom.Rect) ?geom.Rect { - const padding = renderer_mod.terminal_padding; +fn terminalContentRect(session_rect: geom.Rect, ui_scale: f32) ?geom.Rect { + const padding = dpi.scale(renderer_mod.terminal_padding, ui_scale); const w = session_rect.w - padding * 2; const h = session_rect.h - padding * 2; if (w <= 0 or h <= 0) return null;