diff --git a/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts b/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts index 701482d16bb..26b19453f64 100644 --- a/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts +++ b/src/renderer/src/lib/pane-manager/pane-lifecycle.test.ts @@ -527,6 +527,12 @@ describe('openTerminal — addon and provider wiring', () => { deregisterCharacterJoiner: vi.fn((joinerId: number) => { events.push(`deregisterCharacterJoiner:${joinerId}`) }), + clearSelection: vi.fn(() => { + events.push('clearSelection') + }), + dispose: vi.fn(() => { + events.push('dispose') + }), unicode: unicodeProxy, buffer: { active: { cursorX: 0, cursorY: 0 } } } as unknown as ManagedPaneInternal['terminal'] @@ -607,6 +613,15 @@ describe('openTerminal — addon and provider wiring', () => { expect(pane.arabicShapingJoinerCleanup).toBeNull() }) + it('clears selection before disposing a remounted pane', () => { + const { pane, events } = createOpenTerminalHarness() + openTerminal(pane) + + disposePane(pane, new Map([[pane.id, pane]])) + + expect(events.indexOf('clearSelection')).toBeLessThan(events.indexOf('dispose')) + }) + // Why: a link streamed under a stationary pointer must re-linkify on the next // move; openTerminal wires the hover-cache reset and disposePane must detach it. it('installs the streamed-output linkifier hover reset and disposes it', () => { diff --git a/src/renderer/src/lib/pane-manager/pane-lifecycle.ts b/src/renderer/src/lib/pane-manager/pane-lifecycle.ts index e5695207a57..131a947312e 100644 --- a/src/renderer/src/lib/pane-manager/pane-lifecycle.ts +++ b/src/renderer/src/lib/pane-manager/pane-lifecycle.ts @@ -254,6 +254,12 @@ export function disposePane( } catch { /* ignore */ } + try { + // Drop renderer selection state before a recovery remount replaces the surface. + pane.terminal.clearSelection() + } catch { + /* ignore */ + } try { pane.terminal.dispose() } catch {