Problem
Two issues found while using JabTerm React component (<JabTerm>) in a dockview grid layout with multiple terminal panes:
1. Missing resize deduplication
handleResize() in JabTerm.js (lines 252-266) calls fitAddon.fit() and sends a resize WebSocket message on every window.resize and ResizeObserver callback without checking if cols/rows actually changed:
// Current behavior — sends resize even if dimensions are identical
const handleResize = () => {
fitAddon.fit();
if (ws.readyState === WebSocket.OPEN) {
const cols = Math.max(term.cols || 80, 80);
const rows = Math.max(term.rows || 24, 24);
ws.send(JSON.stringify({ type: "resize", cols, rows })); // always sends
}
};
In a grid layout with 3 terminal panes, each pane triggers 3-4 redundant resizes during initial layout, causing:
- TUI apps like
htop to flicker/redraw rapidly
mc (Midnight Commander) to show rendering artifacts
- Unnecessary PTY SIGWINCH signals
Suggested fix: Track last sent cols/rows and skip if unchanged:
let lastCols = 0, lastRows = 0;
const handleResize = () => {
fitAddon.fit();
const cols = Math.max(term.cols || 80, 80);
const rows = Math.max(term.rows || 24, 24);
if (cols === lastCols && rows === lastRows) return;
lastCols = cols;
lastRows = rows;
if (ws.readyState === WebSocket.OPEN) {
ws.send(JSON.stringify({ type: "resize", cols, rows }));
}
};
2. No accessibilitySupport option for xterm
JabTerm creates the xterm Terminal without exposing the accessibilitySupport option:
const term = new TerminalCtor({
cursorBlink: true,
fontFamily,
fontSize,
theme: { ... },
// accessibilitySupport not configurable
});
In xterm v6 with the canvas/WebGL renderer, .xterm-rows text content is empty by default (accessibility tree not populated unless accessibilitySupport: "on"). This makes it impossible to read terminal text content via DOM queries like:
document.querySelector("[data-testid=\"my-terminal\"] .xterm-rows").textContent
// Returns empty string in xterm v6 canvas mode
Use case: browser2video uses waitForPrompt() and waitForText() to detect terminal state by reading .xterm-rows text. Without accessibility support, we had to add a workaround using JabTerm's readAll() capture buffer exposed via a DOM attribute.
Suggested fix: Accept accessibilitySupport in JabTerm props and pass it through to xterm:
<JabTerm wsUrl="..." accessibilitySupport="on" />
Reproduction
import { JabTerm } from "jabterm/react";
// In a dockview grid with 3 panes:
<JabTerm wsUrl="ws://localhost:9523/cmd:htop" />
<JabTerm wsUrl="ws://localhost:9523/cmd:mc" />
<JabTerm wsUrl="ws://localhost:9523/shell" />
// Observe: rapid pty_resize messages with identical cols/rows in jabterm server logs
// Observe: document.querySelector(".xterm-rows").textContent returns ""
Environment
- jabterm: latest (commit e4ed68e)
- @xterm/xterm: 6.0.0
- @xterm/addon-fit: 0.11.0
- React: 19.x
- Electron: 40.x
- macOS (Apple Silicon)
Problem
Two issues found while using JabTerm React component (
<JabTerm>) in a dockview grid layout with multiple terminal panes:1. Missing resize deduplication
handleResize()inJabTerm.js(lines 252-266) callsfitAddon.fit()and sends a resize WebSocket message on everywindow.resizeandResizeObservercallback without checking ifcols/rowsactually changed:In a grid layout with 3 terminal panes, each pane triggers 3-4 redundant resizes during initial layout, causing:
htopto flicker/redraw rapidlymc(Midnight Commander) to show rendering artifactsSuggested fix: Track last sent cols/rows and skip if unchanged:
2. No
accessibilitySupportoption for xtermJabTerm creates the xterm Terminal without exposing the
accessibilitySupportoption:In xterm v6 with the canvas/WebGL renderer,
.xterm-rowstext content is empty by default (accessibility tree not populated unlessaccessibilitySupport: "on"). This makes it impossible to read terminal text content via DOM queries like:Use case: browser2video uses
waitForPrompt()andwaitForText()to detect terminal state by reading.xterm-rowstext. Without accessibility support, we had to add a workaround using JabTerm'sreadAll()capture buffer exposed via a DOM attribute.Suggested fix: Accept
accessibilitySupportin JabTerm props and pass it through to xterm:Reproduction
Environment