Skip to content

Let buffer-face-mode rescale ghostel terminals - #589

Merged
dakra merged 1 commit into
mainfrom
fix/buffer-face-mode
Jul 31, 2026
Merged

dakra merged 1 commit into
mainfrom
fix/buffer-face-mode

Conversation

@dakra

@dakra dakra commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Fixes #588 — buffer-face-mode had no effect in ghostel buffers, for two independent reasons.

The face remapping was masked

ghostel-mode remaps default to ghostel-default, which was defined as :inherit default. face-remap-add-relative orders the default remappings by how many attributes they leave unspecified, giving the most relative one the highest precedence — and :inherit default pins every attribute of default. So ghostel-default outranked and silently masked any face-name remapping added afterwards: plain M-x buffer-face-mode (variable-pitch) was a complete no-op. Plists such as (:height 240) tied on the sort key and applied only by virtue of sort being stable.

Dropping the inherit is safe: face-remap-add-relative already keeps the real default face as the base of the remapping entry, and ghostel--face-hex-color passes default as its INHERIT fallback, so the OSC 10/11 color replies are unchanged (verified live — an OSC 11 ? query still answers rgb:ffff/ffff/ffff against a White-background default).

The terminal never resized

Even where the remapping did apply, buffer-face-mode rescales the font without changing the window's pixel geometry, so window-size-change-functions never fires and the PTY kept its old dimensions: at (:height 240) the window fit 16x50 while the shell still saw 33 100. It is now advised with ghostel--around-local-font-scale, the same wrapper text-scale-mode already uses; buffer-face-set, buffer-face-toggle and variable-pitch-mode all reach the remapping through buffer-face-mode, so one advice covers every entry point. ghostel--windows filters on derived-mode-p 'ghostel-mode, so it is a no-op in other buffers.

Verification

make -j8 all clean from scratch, 0 unexpected. Two regression tests added in test/ghostel-modes-test.el.

Live GUI Emacs 31 driving a real bash, window 100x35:

action font terminal grid window fits shell stty size
baseline Menlo 12 33x100 33x100 33 100
M-x buffer-face-mode Tahoma 12 33x116 33x116 33 116
buffer-face-set '(:height 240) Menlo 24 16x50 16x50 16 50
buffer-face-mode -1 Menlo 12 33x100 33x100 33 100
text-scale-set 6 Menlo 36 11x31 11x31 11 31
text-scale-set 0 Menlo 12 33x100 33x100 33 100

Grid and window agree in every row now, and text-scale-mode is unregressed.

Note

M-x buffer-face-mode with its default variable-pitch now genuinely applies a proportional font. Ghostel resizes correctly for it (100 → 116 columns from the narrower average glyph), but a proportional font in a character grid still renders ragged — that is now the user's choice rather than a silent no-op.

Not addressed here: ghostel--reported-cell-width/-height still derive from frame-char-width/frame-char-height, which are frame-level and blind to any buffer-local remap, so the cell pixel size reported to libghostty (CSI 14 t/CSI 16 t, ws_xpixel/ws_ypixel, kitty/sixel scaling) is stale under buffer-face and under the already-supported text-scale-mode. Pre-existing and separate.

ghostel-mode remaps `default' to `ghostel-default', which was defined
as `:inherit default'.  `face-remap-add-relative' orders the `default'
remappings by how many attributes they leave unspecified, giving the
most relative one the highest precedence, and `:inherit default' pins
every attribute of `default'.  `ghostel-default' therefore outranked
and silently masked any face-name remapping added afterwards: plain
`M-x buffer-face-mode' (variable-pitch) had no effect at all.  Plists
such as (:height 240) tied on the sort key and applied only by virtue
of `sort' being stable.

Drop the inherit.  `face-remap-add-relative' already keeps the real
`default' face as the base of the remapping entry, and
`ghostel--face-hex-color' passes `default' as its INHERIT fallback, so
the OSC 10/11 color replies are unchanged.

Even where the remapping did apply, the terminal kept its old
dimensions: `buffer-face-mode' rescales the font without changing the
window's pixel geometry, so `window-size-change-functions' never fires.
At (:height 240) the window fit 16x50 while the shell still saw 33x100.
Advise it with `ghostel--around-local-font-scale', the wrapper
`text-scale-mode' already uses; `buffer-face-set', `buffer-face-toggle'
and `variable-pitch-mode' all reach the remapping through it.

Verified in a GUI Emacs driving a live bash: `M-x buffer-face-mode'
now yields 33x116 (proportional font, narrower average glyph),
(:height 240) yields 16x50 and (buffer-face-mode -1) restores 33x100,
with `stty size' agreeing in each case; text-scale-set 6/0 still
yields 11x31 / 33x100.

Closes #588
@dakra
dakra merged commit ebd6466 into main Jul 31, 2026
29 checks passed
@dakra
dakra deleted the fix/buffer-face-mode branch July 31, 2026 22:19
@dakra
dakra temporarily deployed to github-pages July 31, 2026 22:19 — with GitHub Actions Inactive

This branch was previously deployed

1 inactive deployment
github-pages — ebd6466f Deployed Jul 31, 2026 by dakra via deploy #138
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.

buffer-face-mode has no effect

1 participant