Skip to content

fix(terminal): pass physical pixels to ghostty_surface_set_size on HiDPI#100

Open
PavloGrubyi wants to merge 1 commit into
am-will:mainfrom
PavloGrubyi:fix/hidpi-physical-pixel-size
Open

fix(terminal): pass physical pixels to ghostty_surface_set_size on HiDPI#100
PavloGrubyi wants to merge 1 commit into
am-will:mainfrom
PavloGrubyi:fix/hidpi-physical-pixel-size

Conversation

@PavloGrubyi

Copy link
Copy Markdown

Problem

On any GTK scale_factor != 1 (e.g. 200% HiDPI, or fractional scaling), the embedded Ghostty terminal pane renders solid black while the GTK chrome (sidebar, tabs, toolbar) renders fine. The shell underneath is alive the whole time (limux read-screen shows content, surface-health reports healthy) — only the on-screen GL paint is missing. At 100% scale it renders correctly.

This reproduces independent of GPU/driver/renderer/session: verified black with NVIDIA, with pure Mesa llvmpipe software rendering, under GSK_RENDERER=gl/ngl/software, and on both native Wayland and XWayland. It matches #99 (reported on non-NVIDIA Mint/Cinnamon) and #82 (Wayland fractional scaling clip).

Root cause

refresh_surface_display() in rust/limux-host-linux/src/terminal.rs passes gl_area.allocation()logical/CSS pixels — to ghostty_surface_set_size. But that API expects physical pixels (the GL framebuffer size): the OpenGL renderer reads the real size from GL_VIEWPORT and, on a mismatch between the set size and the viewport, presents the previous (empty) frame and returns early — a black pane. The GtkGLArea framebuffer is physical-sized (logical * scale_factor), so at scale 1 logical == physical and it works, while at scale 2 the renderer is told 800×600 but the viewport is 1600×1200 → permanent mismatch → black.

Fix

Multiply the allocation by scale_factor() so Ghostty receives the true framebuffer dimensions. content_scale is unchanged (it drives font DPI). One call site; grep-confirmed there are no others.

let scale = gl_area.scale_factor();
let w = (alloc.width() * scale) as u32;
let h = (alloc.height() * scale) as u32;

Testing

Built and verified on Ubuntu 24.04 / GNOME 46 Wayland / NVIDIA / 4K @ 200%: terminal pane now renders correctly at 200% (and still at 100%). Live-switching the display scale 100%↔200% repaints correctly via the existing connect_resize path.

Fixes #99. Related: #82.

The GtkGLArea framebuffer is sized in physical pixels (logical * scale_factor),
and ghostty_surface_set_size expects physical pixels — the OpenGL renderer
compares the value against GL_VIEWPORT and presents an empty (black) frame on
mismatch. refresh_surface_display() was passing logical CSS pixels, so at any
scale_factor != 1 (e.g. 200% HiDPI / fractional scaling) the terminal pane
rendered solid black while chrome rendered fine.

Multiply the allocation by scale_factor() so ghostty receives the true
framebuffer size. content_scale is unchanged (it drives font DPI).

Fixes am-will#99. Related: am-will#82.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Limux Terminal shows no readable content (just black)

1 participant