Fix terminal resize after splitting panes (#1249)
This commit is contained in:
@@ -214,6 +214,7 @@ export function TerminalPane({
|
||||
const pendingTerminalInputRef = useRef<PendingTerminalInput[]>([]);
|
||||
const keyboardRefitTimeoutsRef = useRef<Array<ReturnType<typeof setTimeout>>>([]);
|
||||
const lastAutoFocusKeyRef = useRef<string | null>(null);
|
||||
const lastPaneFocusResizeKeyRef = useRef<string | null>(null);
|
||||
const initialSnapshot = workspaceTerminalSession.snapshots.get({ terminalId });
|
||||
|
||||
useEffect(() => {
|
||||
@@ -252,7 +253,7 @@ export function TerminalPane({
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isMobile || !isWorkspaceFocused || !isPaneFocused || !terminalId) {
|
||||
if (isMobile || !isPaneFocused || !terminalId) {
|
||||
lastAutoFocusKeyRef.current = null;
|
||||
return;
|
||||
}
|
||||
@@ -263,15 +264,36 @@ export function TerminalPane({
|
||||
}
|
||||
|
||||
lastAutoFocusKeyRef.current = nextFocusKey;
|
||||
if (!isWorkspaceFocused) {
|
||||
return;
|
||||
}
|
||||
|
||||
requestTerminalFocus();
|
||||
}, [isMobile, isPaneFocused, isWorkspaceFocused, requestTerminalFocus, scopeKey, terminalId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isPaneFocused && isWorkspaceFocused && isAppVisible && terminalId) {
|
||||
lastSentTerminalSizeRef.current = null;
|
||||
requestTerminalReflow();
|
||||
if (!isPaneFocused || !terminalId) {
|
||||
lastPaneFocusResizeKeyRef.current = null;
|
||||
return;
|
||||
}
|
||||
}, [isAppVisible, isPaneFocused, isWorkspaceFocused, requestTerminalReflow, terminalId]);
|
||||
|
||||
const focusResizeKey = `${scopeKey}:${terminalId}`;
|
||||
if (lastPaneFocusResizeKeyRef.current === focusResizeKey) {
|
||||
return;
|
||||
}
|
||||
lastPaneFocusResizeKeyRef.current = focusResizeKey;
|
||||
if (!isWorkspaceFocused) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastSentTerminalSizeRef.current = null;
|
||||
requestTerminalReflow();
|
||||
}, [isPaneFocused, isWorkspaceFocused, requestTerminalReflow, scopeKey, terminalId]);
|
||||
|
||||
const handleTerminalFocus = useCallback(() => {
|
||||
lastSentTerminalSizeRef.current = null;
|
||||
requestTerminalReflow();
|
||||
}, [requestTerminalReflow]);
|
||||
|
||||
const clearKeyboardRefitTimeouts = useCallback(() => {
|
||||
if (keyboardRefitTimeoutsRef.current.length === 0) {
|
||||
@@ -308,25 +330,6 @@ export function TerminalPane({
|
||||
[pulseKeyboardRefits],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isWorkspaceFocused || !terminalId) {
|
||||
return;
|
||||
}
|
||||
// Focus transitions can temporarily report stale dimensions.
|
||||
// Pulse forced refits so xterm fills the pane when returning to a terminal.
|
||||
const timeoutHandles = TERMINAL_REFIT_DELAYS_MS.map((delayMs) =>
|
||||
setTimeout(() => {
|
||||
requestTerminalReflow();
|
||||
}, delayMs),
|
||||
);
|
||||
|
||||
return () => {
|
||||
for (const handle of timeoutHandles) {
|
||||
clearTimeout(handle);
|
||||
}
|
||||
};
|
||||
}, [isWorkspaceFocused, requestTerminalReflow, terminalId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!client || !isConnected || !isWorkspaceFocused) {
|
||||
return;
|
||||
@@ -375,7 +378,7 @@ export function TerminalPane({
|
||||
|
||||
const controller = new TerminalStreamController({
|
||||
client,
|
||||
getPreferredSize: () => measuredTerminalSizeRef.current,
|
||||
getPreferredSize: () => lastSentTerminalSizeRef.current,
|
||||
onOutput: ({ terminalId: outputTerminalId, data }) => {
|
||||
if (!isWorkspaceFocused || terminalIdRef.current !== outputTerminalId) {
|
||||
return;
|
||||
@@ -605,33 +608,35 @@ export function TerminalPane({
|
||||
],
|
||||
);
|
||||
|
||||
const handleTerminalResize = useStableEvent((input: { rows: number; cols: number }) => {
|
||||
const { rows, cols } = input;
|
||||
if (rows <= 0 || cols <= 0) {
|
||||
return;
|
||||
}
|
||||
const normalizedRows = Math.floor(rows);
|
||||
const normalizedCols = Math.floor(cols);
|
||||
const nextSize = { rows: normalizedRows, cols: normalizedCols };
|
||||
measuredTerminalSizeRef.current = nextSize;
|
||||
if (!client || !terminalId || !isPaneFocused || !isWorkspaceFocused || !isAppVisible) {
|
||||
return;
|
||||
}
|
||||
const previousSent = lastSentTerminalSizeRef.current;
|
||||
if (
|
||||
previousSent &&
|
||||
previousSent.rows === normalizedRows &&
|
||||
previousSent.cols === normalizedCols
|
||||
) {
|
||||
return;
|
||||
}
|
||||
lastSentTerminalSizeRef.current = nextSize;
|
||||
client.sendTerminalInput(terminalId, {
|
||||
type: "resize",
|
||||
rows: normalizedRows,
|
||||
cols: normalizedCols,
|
||||
});
|
||||
});
|
||||
const handleTerminalResize = useStableEvent(
|
||||
(input: { rows: number; cols: number; shouldClaim: boolean }) => {
|
||||
const { rows, cols } = input;
|
||||
if (rows <= 0 || cols <= 0) {
|
||||
return;
|
||||
}
|
||||
const normalizedRows = Math.floor(rows);
|
||||
const normalizedCols = Math.floor(cols);
|
||||
const nextSize = { rows: normalizedRows, cols: normalizedCols };
|
||||
measuredTerminalSizeRef.current = nextSize;
|
||||
if (!input.shouldClaim || !client || !terminalId || !isWorkspaceFocused || !isAppVisible) {
|
||||
return;
|
||||
}
|
||||
const previousSent = lastSentTerminalSizeRef.current;
|
||||
if (
|
||||
previousSent &&
|
||||
previousSent.rows === normalizedRows &&
|
||||
previousSent.cols === normalizedCols
|
||||
) {
|
||||
return;
|
||||
}
|
||||
lastSentTerminalSizeRef.current = nextSize;
|
||||
client.sendTerminalInput(terminalId, {
|
||||
type: "resize",
|
||||
rows: normalizedRows,
|
||||
cols: normalizedCols,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
const handleTerminalKey = useCallback(
|
||||
async (input: { key: string; ctrl: boolean; shift: boolean; alt: boolean; meta: boolean }) => {
|
||||
@@ -764,6 +769,7 @@ export function TerminalPane({
|
||||
onSwipeRight={handleSwipeRight}
|
||||
onSwipeLeft={handleSwipeLeft}
|
||||
onInput={handleTerminalData}
|
||||
onFocus={handleTerminalFocus}
|
||||
onResize={handleTerminalResize}
|
||||
onTerminalKey={handleTerminalKey}
|
||||
onInputModeChange={handleInputModeChange}
|
||||
|
||||
Reference in New Issue
Block a user