Summary
Several layout and input handling details in the default renderer cause problems when embedding the terminal in a resizable LiveView container (especially with tmux, full-screen TUIs, or when the browser devtools/refresh keys need to work).
Current pain points observed vs. the upstream priv/static/ghostty.js:
createScreen() does not set height: 100% → the screen is content-sized, causing fitToContainer to over/under-count rows and tmux status bars to drift below the grid.
<pre> is not absolutely positioned to fill its parent → same measurement feedback loop.
- Missing explicit
letterSpacing: 0, fontVariantLigatures: none, textRendering: geometricPrecision, and a pinned lineHeight (e.g. 17px) → sub-pixel drift in cursor position and row alignment, especially noticeable by column 80 or after resize.
- No
isBrowserDevShortcut handling → Ctrl/Cmd+Shift+R (hard refresh), F5, F12, Shift+I/J/C (devtools/inspect) are swallowed by the terminal key handler, which is very annoying during development of LiveView apps.
Proposed changes
- Adopt the layout fixes from
createScreen / createPre / measureCellMetrics (height 100%, absolute inset fill on pre, the font metric locking styles).
- Add (and call)
isBrowserDevShortcut(e) early in the keydown handler so legitimate browser shortcuts pass through even when the terminal has focus.
- These changes should be safe defaults or easily configurable.
Why upstream
These are not DevIDE-specific. Any web app embedding Ghostty terminals via the LiveView component will hit the fit accuracy and dev shortcut problems. The fixes have been battle-tested in a real multi-pane IDE.
Related
- Works especially well together with the
onRenderCells hook (separate issue) because custom renderers also need correct metrics.
- Complements the row-diff protocol proposal.
Would be happy to provide the precise patches from our current extension layer.
Summary
Several layout and input handling details in the default renderer cause problems when embedding the terminal in a resizable LiveView container (especially with tmux, full-screen TUIs, or when the browser devtools/refresh keys need to work).
Current pain points observed vs. the upstream
priv/static/ghostty.js:createScreen()does not setheight: 100%→ the screen is content-sized, causingfitToContainerto over/under-count rows and tmux status bars to drift below the grid.<pre>is not absolutely positioned to fill its parent → same measurement feedback loop.letterSpacing: 0,fontVariantLigatures: none,textRendering: geometricPrecision, and a pinnedlineHeight(e.g. 17px) → sub-pixel drift in cursor position and row alignment, especially noticeable by column 80 or after resize.isBrowserDevShortcuthandling → Ctrl/Cmd+Shift+R (hard refresh), F5, F12, Shift+I/J/C (devtools/inspect) are swallowed by the terminal key handler, which is very annoying during development of LiveView apps.Proposed changes
createScreen/createPre/measureCellMetrics(height 100%, absolute inset fill on pre, the font metric locking styles).isBrowserDevShortcut(e)early in the keydown handler so legitimate browser shortcuts pass through even when the terminal has focus.Why upstream
These are not DevIDE-specific. Any web app embedding Ghostty terminals via the LiveView component will hit the fit accuracy and dev shortcut problems. The fixes have been battle-tested in a real multi-pane IDE.
Related
onRenderCellshook (separate issue) because custom renderers also need correct metrics.Would be happy to provide the precise patches from our current extension layer.