fix: report correct screen pixel size

Mode 2048 and CSI 14 t are size report control sequences which contain
the text area size in pixels. The text area is defined to be the extents
of the grid (rows and columns). Ghostty calculates the available size
for the text area by setting the available padding, and then filling as
much of the remaining space as possible. However, if there are remainder
pixels these are still reported as part of the text area size.

Pass the cell_size geometry through so that we can always report the
correct value: columns * cell width and rows * cell height.
This commit is contained in:
Tim Culverhouse
2024-10-18 22:29:52 -05:00
parent 0084103ff1
commit 4f1cee8eb9
5 changed files with 26 additions and 11 deletions

View File

@ -500,6 +500,7 @@ pub fn init(
try termio.Termio.init(&self.io, alloc, .{ try termio.Termio.init(&self.io, alloc, .{
.grid_size = grid_size, .grid_size = grid_size,
.cell_size = cell_size,
.screen_size = screen_size, .screen_size = screen_size,
.padding = padding, .padding = padding,
.full_config = config, .full_config = config,
@ -1331,6 +1332,7 @@ fn setCellSize(self: *Surface, size: renderer.CellSize) !void {
self.io.queueMessage(.{ self.io.queueMessage(.{
.resize = .{ .resize = .{
.grid_size = self.grid_size, .grid_size = self.grid_size,
.cell_size = self.cell_size,
.screen_size = self.screen_size, .screen_size = self.screen_size,
.padding = self.padding, .padding = self.padding,
}, },
@ -1435,6 +1437,7 @@ fn resize(self: *Surface, size: renderer.ScreenSize) !void {
self.io.queueMessage(.{ self.io.queueMessage(.{
.resize = .{ .resize = .{
.grid_size = self.grid_size, .grid_size = self.grid_size,
.cell_size = self.cell_size,
.screen_size = self.screen_size, .screen_size = self.screen_size,
.padding = self.padding, .padding = self.padding,
}, },

View File

@ -11,6 +11,9 @@ const termio = @import("../termio.zig");
/// The size of the terminal grid. /// The size of the terminal grid.
grid_size: renderer.GridSize, grid_size: renderer.GridSize,
/// The size of a single cell, in pixels.
cell_size: renderer.CellSize,
/// The size of the viewport in pixels. /// The size of the viewport in pixels.
screen_size: renderer.ScreenSize, screen_size: renderer.ScreenSize,

View File

@ -60,6 +60,9 @@ surface_mailbox: apprt.surface.Mailbox,
/// The cached grid size whenever a resize is called. /// The cached grid size whenever a resize is called.
grid_size: renderer.GridSize, grid_size: renderer.GridSize,
/// The size of a single cell. Used for size reports.
cell_size: renderer.CellSize,
/// The mailbox implementation to use. /// The mailbox implementation to use.
mailbox: termio.Mailbox, mailbox: termio.Mailbox,
@ -171,9 +174,8 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
backend.initTerminal(&term); backend.initTerminal(&term);
// Setup our terminal size in pixels for certain requests. // Setup our terminal size in pixels for certain requests.
const screen_size = opts.screen_size.subPadding(opts.padding); term.width_px = opts.grid_size.columns * opts.cell_size.width;
term.width_px = screen_size.width; term.height_px = opts.grid_size.rows * opts.cell_size.height;
term.height_px = screen_size.height;
// Create our stream handler. This points to memory in self so it // Create our stream handler. This points to memory in self so it
// isn't safe to use until self.* is set. // isn't safe to use until self.* is set.
@ -214,6 +216,7 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
.renderer_mailbox = opts.renderer_mailbox, .renderer_mailbox = opts.renderer_mailbox,
.surface_mailbox = opts.surface_mailbox, .surface_mailbox = opts.surface_mailbox,
.grid_size = opts.grid_size, .grid_size = opts.grid_size,
.cell_size = opts.cell_size,
.backend = opts.backend, .backend = opts.backend,
.mailbox = opts.mailbox, .mailbox = opts.mailbox,
.terminal_stream = .{ .terminal_stream = .{
@ -348,6 +351,7 @@ pub fn resize(
self: *Termio, self: *Termio,
td: *ThreadData, td: *ThreadData,
grid_size: renderer.GridSize, grid_size: renderer.GridSize,
cell_size: renderer.CellSize,
screen_size: renderer.ScreenSize, screen_size: renderer.ScreenSize,
padding: renderer.Padding, padding: renderer.Padding,
) !void { ) !void {
@ -357,6 +361,7 @@ pub fn resize(
// Update our cached grid size // Update our cached grid size
self.grid_size = grid_size; self.grid_size = grid_size;
self.cell_size = cell_size;
// Enter the critical area that we want to keep small // Enter the critical area that we want to keep small
{ {
@ -371,8 +376,8 @@ pub fn resize(
); );
// Update our pixel sizes // Update our pixel sizes
self.terminal.width_px = padded_size.width; self.terminal.width_px = self.grid_size.columns * self.cell_size.width;
self.terminal.height_px = padded_size.height; self.terminal.height_px = self.grid_size.rows * self.cell_size.height;
// Disable synchronized output mode so that we show changes // Disable synchronized output mode so that we show changes
// immediately for a resize. This is allowed by the spec. // immediately for a resize. This is allowed by the spec.
@ -412,24 +417,24 @@ fn sizeReportLocked(self: *Termio, td: *ThreadData, style: termio.Message.SizeRe
.{ .{
self.grid_size.rows, self.grid_size.rows,
self.grid_size.columns, self.grid_size.columns,
self.terminal.height_px, self.grid_size.rows * self.cell_size.height,
self.terminal.width_px, self.grid_size.columns * self.cell_size.width,
}, },
), ),
.csi_14_t => try std.fmt.bufPrint( .csi_14_t => try std.fmt.bufPrint(
&buf, &buf,
"\x1b[4;{};{}t", "\x1b[4;{};{}t",
.{ .{
self.terminal.height_px, self.grid_size.rows * self.cell_size.height,
self.terminal.width_px, self.grid_size.columns * self.cell_size.width,
}, },
), ),
.csi_16_t => try std.fmt.bufPrint( .csi_16_t => try std.fmt.bufPrint(
&buf, &buf,
"\x1b[6;{};{}t", "\x1b[6;{};{}t",
.{ .{
self.terminal.height_px / self.grid_size.rows, self.cell_size.height,
self.terminal.width_px / self.grid_size.columns, self.cell_size.width,
}, },
), ),
.csi_18_t => try std.fmt.bufPrint( .csi_18_t => try std.fmt.bufPrint(

View File

@ -383,6 +383,7 @@ fn coalesceCallback(
cb.io.resize( cb.io.resize(
&cb.data, &cb.data,
v.grid_size, v.grid_size,
v.cell_size,
v.screen_size, v.screen_size,
v.padding, v.padding,
) catch |err| { ) catch |err| {

View File

@ -20,6 +20,9 @@ pub const Message = union(enum) {
/// The grid size for the given screen size with padding applied. /// The grid size for the given screen size with padding applied.
grid_size: renderer.GridSize, grid_size: renderer.GridSize,
/// The updated cell size.
cell_size: renderer.CellSize,
/// The full screen (drawable) size. This does NOT include padding. /// The full screen (drawable) size. This does NOT include padding.
/// This should be sent on to the renderer. /// This should be sent on to the renderer.
screen_size: renderer.ScreenSize, screen_size: renderer.ScreenSize,