55 lines
1.9 KiB
TypeScript
55 lines
1.9 KiB
TypeScript
import { logForDebugging } from '../debug.js'
|
|
import { releasePump, retainPump } from './drainRunLoop.js'
|
|
import { requireComputerUseSwift } from './swiftLoader.js'
|
|
|
|
/**
|
|
* Global Escape → abort. Mirrors Cowork's `escAbort.ts` but without Electron:
|
|
* CGEventTap via `@ant/computer-use-swift`. While registered, Escape is
|
|
* consumed system-wide (PI defense — a prompt-injected action can't dismiss
|
|
* a dialog with Escape).
|
|
*
|
|
* Lifecycle: register on fresh lock acquire (`wrapper.tsx` `acquireCuLock`),
|
|
* unregister on lock release (`cleanup.ts`). The tap's CFRunLoopSource sits
|
|
* in .defaultMode on CFRunLoopGetMain(), so we hold a drainRunLoop pump
|
|
* retain for the registration's lifetime — same refcounted setInterval as
|
|
* the `@MainActor` methods.
|
|
*
|
|
* `notifyExpectedEscape()` punches a hole for model-synthesized Escapes: the
|
|
* executor's `key("escape")` calls it before posting the CGEvent. Swift
|
|
* schedules a 100ms decay so a CGEvent that never reaches the tap callback
|
|
* doesn't eat the next user ESC.
|
|
*/
|
|
|
|
let registered = false
|
|
|
|
export function registerEscHotkey(onEscape: () => void): boolean {
|
|
if (registered) return true
|
|
const cu = requireComputerUseSwift()
|
|
if (!cu.hotkey.registerEscape(onEscape)) {
|
|
// CGEvent.tapCreate failed — typically missing Accessibility permission.
|
|
// CU still works, just without ESC abort. Mirrors Cowork's escAbort.ts:81.
|
|
logForDebugging('[cu-esc] registerEscape returned false', { level: 'warn' })
|
|
return false
|
|
}
|
|
retainPump()
|
|
registered = true
|
|
logForDebugging('[cu-esc] registered')
|
|
return true
|
|
}
|
|
|
|
export function unregisterEscHotkey(): void {
|
|
if (!registered) return
|
|
try {
|
|
requireComputerUseSwift().hotkey.unregister()
|
|
} finally {
|
|
releasePump()
|
|
registered = false
|
|
logForDebugging('[cu-esc] unregistered')
|
|
}
|
|
}
|
|
|
|
export function notifyExpectedEscape(): void {
|
|
if (!registered) return
|
|
requireComputerUseSwift().hotkey.notifyExpectedEscape()
|
|
}
|