Skip to content

Commit 5117be7

Browse files
committed
Replace xterm.js with ghostty-web
Switch terminal emulator from @xterm/xterm to ghostty-web (WASM-based Ghostty port) loaded via ES module importmap from jsDelivr CDN. Include a workaround for coder/ghostty-web#136: forward wheel events with cell coordinates when mouse tracking is active, so scrolling in tmux panes and other multi-region TUIs works correctly. Assisted-By: docker-agent
1 parent 61e1687 commit 5117be7

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

pkg/board/static/app.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import { init, Terminal as GhosttyTerminal, FitAddon } from 'ghostty-web';
2+
3+
// Initialize ghostty-web WASM (must complete before creating terminals)
4+
const ghosttyReady = init();
5+
16
// --- Theme ---
27

38
function getPreferredTheme() {
@@ -263,15 +268,17 @@ async function handleCardAction(e) {
263268
let activeTerm = null;
264269
let activeSocket = null;
265270

266-
function openTerminal(sessionName, title) {
271+
async function openTerminal(sessionName, title) {
267272
const dialog = document.getElementById("terminal-dialog");
268273
const container = document.getElementById("terminal-container");
269274
document.getElementById("terminal-title").textContent = title;
270275

271276
closeTerminal();
272277
dialog.showModal();
273278

274-
const term = new Terminal({
279+
await ghosttyReady;
280+
281+
const term = new GhosttyTerminal({
275282
cursorBlink: true,
276283
fontSize: 13,
277284
fontFamily: "'JetBrains Mono', 'Fira Code', 'Cascadia Code', Menlo, monospace",
@@ -306,11 +313,21 @@ function openTerminal(sessionName, title) {
306313
},
307314
});
308315

309-
const fitAddon = new FitAddon.FitAddon();
316+
const fitAddon = new FitAddon();
310317
term.loadAddon(fitAddon);
311318
term.open(container);
312319
activeTerm = term;
313320

321+
// PR #136 fix: forward wheel events with coordinates when mouse tracking
322+
// is active, so tmux panes and other TUI split views scroll correctly.
323+
term.attachCustomWheelEventHandler((e) => {
324+
if (term.hasMouseTracking()) {
325+
term.inputHandler?.handleWheel(e);
326+
return true;
327+
}
328+
return false;
329+
});
330+
314331
requestAnimationFrame(() => {
315332
fitAddon.fit();
316333

pkg/board/static/index.html

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>Docker Agent Board</title>
77
<link rel="stylesheet" href="style.css">
8-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/css/xterm.min.css">
9-
<script src="https://cdn.jsdelivr.net/npm/@xterm/xterm@5.5.0/lib/xterm.min.js"></script>
10-
<script src="https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0.10.0/lib/addon-fit.min.js"></script>
8+
<script type="importmap">
9+
{
10+
"imports": {
11+
"ghostty-web": "https://cdn.jsdelivr.net/npm/ghostty-web@next/dist/ghostty-web.js"
12+
}
13+
}
14+
</script>
1115
</head>
1216
<body>
1317
<header class="app-header">

pkg/board/static/style.css

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,8 +530,10 @@ dialog.dialog-terminal[open] {
530530
overflow: hidden;
531531
padding: 4px;
532532

533-
& .xterm {
533+
& canvas {
534+
display: block;
534535
height: 100%;
536+
width: 100%;
535537
}
536538
}
537539

0 commit comments

Comments
 (0)