-
Notifications
You must be signed in to change notification settings - Fork 0
crates capto hooks
Active contributors: elwina
crates/capto-hooks covers two related concerns. First, it is the hotkey model: the actions, bindings, defaults, and the migration that keeps old keyboard settings current. Second, it provides the low-level OS input hooks that feed click and keystroke overlays while a recording runs. On Windows it installs WH_MOUSE_LL and WH_KEYBOARD_LL hooks on a dedicated thread; on other platforms it is a NullInputHook that does nothing, so the rest of Capto still compiles and runs.
| File | Role |
|---|---|
crates/capto-hooks/src/lib.rs |
Shared hotkey model, InputEvent / InputHook trait, channel, create_input_hook, and the Windows LL-hook implementation in a nested windows_impl module |
| Abstraction | Where | What it does |
|---|---|---|
HotkeyAction |
crates/capto-hooks/src/lib.rs |
StartRecording, PauseRecording, StopRecording, TakeScreenshot
|
HotkeyBinding |
crates/capto-hooks/src/lib.rs |
action + shortcut (Tauri string, e.g. CommandOrControl+Shift+R) + enabled
|
InputHook |
crates/capto-hooks/src/lib.rs |
Trait with start(Sender<InputEvent>) and stop() that overlay consumers treat as opaque |
InputEvent |
crates/capto-hooks/src/lib.rs |
MouseButton { button, x, y, down } or Key { label, down }
|
WindowsInputHook |
crates/capto-hooks/src/lib.rs |
LL mouse/keyboard hooks on a named capto-input-hooks thread |
NullInputHook |
crates/capto-hooks/src/lib.rs |
No-op on non-Windows; start returns Ok and stop does nothing |
default_hotkeys |
crates/capto-hooks/src/lib.rs |
Alt+F5..Alt+F8 for the four actions (Alt+F4 is reserved by Windows) |
normalize_hotkeys |
crates/capto-hooks/src/lib.rs |
Migrates legacy Ctrl+Shift defaults and reorders to exactly the four supported actions |
create_input_hook |
crates/capto-hooks/src/lib.rs |
Factory returning WindowsInputHook on Windows, NullInputHook elsewhere |
channel |
crates/capto-hooks/src/lib.rs |
Convenience mpsc::channel() for InputEvent
|
graph TD
S[settings.rs load/save] --> N[normalize_hotkeys]
N --> D[exactly four actions Alt+F5..F8]
SET[desktop register_hotkeys] --> G[global_shortcut on_shortcut]
REC[recording overlay pipeline] --> F[create_input_hook]
F --> W[WindowsInputHook thread]
W --> M[WH_MOUSE_LL + WH_KEYBOARD_LL]
M -->|"InputEvent"| CH[mpsc channel]
CH --> V[consumers: click + keystroke events]
normalize_hotkeys runs on settings load/save. It first migrates values that still equal the pre-1.0 defaults (Ctrl+Shift+R/P/E/S) to the current Alt+F5..Alt+F8 cluster, then rebuilds the vector from default_hotkeys() so settings always expose exactly the four supported actions in order, filling in any missing binding from the defaults. The desktop's register_hotkeys (see apps/desktop/src-tauri/src/lib.rs) clones settings.hotkeys, calls normalize_hotkeys, unregisters all global shortcuts, and re-registers an on_shortcut handler per enabled binding that dispatches to the matching start/pause/stop/screenshot command.
WindowsInputHook::start stores the sender in a shared TX, initializes the KEYS_DOWN set, and spawns a thread. That thread sets per-monitor DPI awareness, installs WH_MOUSE_LL and WH_KEYBOARD_LL via SetWindowsHookExW (recording each handle in a mutex for later UnhookWindowsHookEx), and runs a standard GetMessageW/TranslateMessage/DispatchMessageW loop; after the loop it unhooks both.
-
Mouse proc: emits
InputEvent::MouseButtonforWM_LBUTTONDOWN,WM_RBUTTONDOWN,WM_MBUTTONDOWNwith the cursor point,down: true. -
Keyboard proc: for
WM_(SYS)KEYDOWN/WM_(SYS)KEYUP, modifier virtual keys are skipped (they only matter as chord prefixes), and a key down is only emitted if it is the first of a hold. TheKEYS_DOWNset tracks held virtual keys so OS auto-repeatKEYDOWNs are deduped; akeyupremoves the key.format_key_labelbuilds a chord likeCtrl+Afrom the currently-heldCtrl/Alt/Shift/Winkeys (GetAsyncKeyState) plus the key name (MapVirtualKeyWto scan code, thenGetKeyNameTextW), skipsCtrl+Control-style duplicates, and falls back to a hex code when a name cannot be resolved.
stop() posts WM_QUIT to the thread, joins it, clears the sender and KEYS_DOWN, and unhooks. Because stop and the running loop are all behind Send-safe mutexes, the overlay pipeline can start and stop hooks per take without a leak.
-
register_hotkeysinapps/desktop/src-tauri/src/lib.rsrunsnormalize_hotkeysand wires the four global shortcuts to their recording commands; settings persistence is inapps/desktop/src-tauri/src/settings.rs. - Recordings create the input hook through
create_input_hook()and routeInputEvents into the click and keystroke overlay renderers, which appear in the video (see overlays and recording). - Hotkey defaults and conflict rules are documented for users in hotkeys; the settings model that stores bindings lives in
crates/capto-core(see capto-core).
-
Add or reorder a hotkey action:
HotkeyAction,default_hotkeys, andnormalize_hotkeys(including theLEGACYmigration table) incrates/capto-hooks/src/lib.rs. -
New input event or extra metadata: extend
InputEventand the corresponding reactor in the consumer. -
Hook mechanics:
mouse_proc,keyboard_proc,format_key_label, and the thread setup incrates/capto-hooks/src/lib.rs. -
Non-Windows path: implement a real
InputHookbehind#[cfg(not(windows))]incrates/capto-hooks/src/lib.rs(currentlyNullInputHook).
| File | What to look for |
|---|---|
crates/capto-hooks/src/lib.rs |
HotkeyAction/HotkeyBinding, default_hotkeys, normalize_hotkeys, InputEvent/InputHook, WindowsInputHook LL hooks and key-label formatting, NullInputHook, create_input_hook
|
apps/desktop/src-tauri/src/lib.rs |
register_hotkeys, global-shortcut wiring |
apps/desktop/src-tauri/src/settings.rs |
Hotkey bindings in AppSettings, load/save through normalize_hotkeys
|