Decision Records
ADR-0005: Cross-platform global hotkey & paste
Architecture Decision Record
- Status: accepted
- Date: 2026-06-15
- Deciders: project owner
Context
The picker reaches parity on Windows (global hotkey + paste-into-the-source-app), but the same behavior is needed on macOS and Linux. There is no portable API for either a process-wide hotkey or for synthesizing a paste keystroke — each OS has its own mechanism, and some (Wayland) deliberately have none. The development machine is Windows, so the non-Windows paths cannot be GUI-tested locally.
Decision
- Keep the existing seams.
IGlobalHotkey(registers a system-wide chord, raisesPressed) andIPasteService(capture source window + paste into it) already isolate the OS-specific bits. Add one implementation of each per OS, selected inAppbyOperatingSystem.Is*. - Linux —
LinuxGlobalHotkeyuses X11XGrabKeyon the root window (Alt+Shift+V) with anXNextEventthread;LinuxPasteServiceshells out toxdotool(X11) orwtype(Wayland). X11 only: a pure Wayland session has no global-grab API, so the hotkey returnsfalseand the app runs tray-only. - macOS —
MacGlobalHotkeyuses CarbonRegisterEventHotKey(Option+Shift+V), dispatched on the NSApplication run loop Avalonia already drives;MacPasteServiceposts a Cmd+V via CoreGraphics events (CGEventPost), which needs Accessibility permission. - Focus model differs by OS. On Windows we capture the foreground
HWNDat hotkey time and restore it before pasting. On macOS/Linux, hiding our window returns focus to the previous app automatically, so the paste service ignores the target and just synthesizes the shortcut. - Degrade, never crash. Every native call is guarded; a failed
Register()(missing libX11, Wayland, no permission) leaves the app fully usable from the tray. The AvaloniaTrayIconis already cross-platform, so the tray needs no per-OS code.
Consequences
- The mac/Linux implementations are compile-checked in CI (the cross-platform
dotnet buildon macOS + Linux runners) but their GUI behavior is not yet verified on real hardware — this is called out in the install docs and code comments rather than claimed as done. - Wayland users get tray-only hotkey behavior until a portal-based path is added.
- macOS paste is gated on a one-time Accessibility grant; without it the item is copied and the user pastes manually.
- Verification is the next step once a real Mac/Linux box (or a suitable VM) is available; the daemon and Unix clipboard watcher are already covered by CI.