fix(terminal): restore clickable link hover after returning to the Orca window (#9659)
xterm's Linkifier only re-runs providers when the hovered cell changes; window blur fires mouseleave which clears the current link but leaves the cell cache, so on refocus with a stationary pointer the link stays dead until a scroll. Adds the same guarded hover-cache reset the reveal/on-write paths already use, to the window-wake path. Closes #9116
This commit is contained in:
parent
a6f54acd0f
commit
8847f615ac
|
|
@ -28,9 +28,11 @@ vi.mock('./terminal-webgl-atlas-recovery', () => ({
|
|||
scheduleTabRevealWebglAtlasRecovery: () => scheduleTabRevealWebglAtlasRecovery()
|
||||
}))
|
||||
const resetTerminalLinkifierHoverState = vi.fn()
|
||||
const isTerminalLinkifierHoverActive = vi.fn((_terminal: unknown) => false)
|
||||
vi.mock('@/lib/pane-manager/terminal-linkifier-hover-reset', () => ({
|
||||
resetTerminalLinkifierHoverState: (terminal: unknown) =>
|
||||
resetTerminalLinkifierHoverState(terminal)
|
||||
resetTerminalLinkifierHoverState(terminal),
|
||||
isTerminalLinkifierHoverActive: (terminal: unknown) => isTerminalLinkifierHoverActive(terminal)
|
||||
}))
|
||||
|
||||
type FakeManager = {
|
||||
|
|
@ -115,6 +117,37 @@ describe('resumeTerminalVisibility reveal repaint', () => {
|
|||
expect(order).toEqual(['resume-rendering', 'reveal-repaint'])
|
||||
})
|
||||
|
||||
it('resets each pane linkifier hover cache on window wake recovery so links recover without a scroll', () => {
|
||||
const first = { name: 'pane-a' }
|
||||
const second = { name: 'pane-b' }
|
||||
const manager = createManager()
|
||||
manager.getPanes.mockReturnValue([{ terminal: first }, { terminal: second }])
|
||||
|
||||
recoverVisibleTerminalWindowWake({
|
||||
manager: manager as never as PaneManager,
|
||||
isActive: true,
|
||||
clearGlyphAtlases: false
|
||||
})
|
||||
|
||||
expect(resetTerminalLinkifierHoverState).toHaveBeenCalledWith(first)
|
||||
expect(resetTerminalLinkifierHoverState).toHaveBeenCalledWith(second)
|
||||
})
|
||||
|
||||
it('keeps a genuinely-hovered link intact on window wake recovery', () => {
|
||||
const hovered = { name: 'hovered-pane' }
|
||||
const manager = createManager()
|
||||
manager.getPanes.mockReturnValue([{ terminal: hovered }])
|
||||
isTerminalLinkifierHoverActive.mockReturnValueOnce(true)
|
||||
|
||||
recoverVisibleTerminalWindowWake({
|
||||
manager: manager as never as PaneManager,
|
||||
isActive: true,
|
||||
clearGlyphAtlases: false
|
||||
})
|
||||
|
||||
expect(resetTerminalLinkifierHoverState).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('schedules the atlas-clearing repaint on genuine wake recovery', () => {
|
||||
const manager = createManager()
|
||||
recoverVisibleTerminalWindowWake({
|
||||
|
|
|
|||
|
|
@ -9,7 +9,10 @@ import {
|
|||
enforceTerminalCurrentScrollIntent,
|
||||
syncTerminalScrollIntentFromViewport
|
||||
} from '@/lib/pane-manager/terminal-scroll-intent'
|
||||
import { resetTerminalLinkifierHoverState } from '@/lib/pane-manager/terminal-linkifier-hover-reset'
|
||||
import {
|
||||
isTerminalLinkifierHoverActive,
|
||||
resetTerminalLinkifierHoverState
|
||||
} from '@/lib/pane-manager/terminal-linkifier-hover-reset'
|
||||
import { fitAndFocusPanes, fitPanes, focusActivePane } from './pane-helpers'
|
||||
import { scheduleTabRevealWebglAtlasRecovery } from './terminal-webgl-atlas-recovery'
|
||||
|
||||
|
|
@ -143,6 +146,13 @@ export function recoverVisibleTerminalWindowWake({
|
|||
for (const pane of manager.getPanes()) {
|
||||
requestTerminalBacklogRecovery(pane.terminal)
|
||||
flushTerminalOutput(pane.terminal, { maxChars: WINDOW_WAKE_FLUSH_CHARS })
|
||||
// Why: window blur fires mouseleave, clearing xterm's current link but not
|
||||
// its hover cell cache; on refocus the stationary pointer sits on the same
|
||||
// cell, so the link stays dead until a scroll. Skip while a link is hovered
|
||||
// to avoid flickering its underline (same guard as the on-write reset).
|
||||
if (!isTerminalLinkifierHoverActive(pane.terminal)) {
|
||||
resetTerminalLinkifierHoverState(pane.terminal)
|
||||
}
|
||||
}
|
||||
syncTerminalViewportIntents(manager)
|
||||
manager.resumeRendering()
|
||||
|
|
|
|||
Loading…
Reference in New Issue