/ ink / terminal-focus-state.ts
terminal-focus-state.ts
 1  // Terminal focus state signal — non-React access to DECSET 1004 focus events.
 2  // 'unknown' is the default for terminals that don't support focus reporting;
 3  // consumers treat 'unknown' identically to 'focused' (no throttling).
 4  // Subscribers are notified synchronously when focus changes, used by
 5  // TerminalFocusProvider to avoid polling.
 6  export type TerminalFocusState = 'focused' | 'blurred' | 'unknown'
 7  
 8  let focusState: TerminalFocusState = 'unknown'
 9  const resolvers: Set<() => void> = new Set()
10  const subscribers: Set<() => void> = new Set()
11  
12  export function setTerminalFocused(v: boolean): void {
13    focusState = v ? 'focused' : 'blurred'
14    // Notify useSyncExternalStore subscribers
15    for (const cb of subscribers) {
16      cb()
17    }
18    if (!v) {
19      for (const resolve of resolvers) {
20        resolve()
21      }
22      resolvers.clear()
23    }
24  }
25  
26  export function getTerminalFocused(): boolean {
27    return focusState !== 'blurred'
28  }
29  
30  export function getTerminalFocusState(): TerminalFocusState {
31    return focusState
32  }
33  
34  // For useSyncExternalStore
35  export function subscribeTerminalFocus(cb: () => void): () => void {
36    subscribers.add(cb)
37    return () => {
38      subscribers.delete(cb)
39    }
40  }
41  
42  export function resetTerminalFocusState(): void {
43    focusState = 'unknown'
44    for (const cb of subscribers) {
45      cb()
46    }
47  }