mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-11-14 12:53:43 +01:00
A static shortcut can only be one combo, pressed, the same in every application. Modes, chord chains, release bindings and per-application bindings need komorebi to hold the keys and decide what each press does: the engine of komorebi-hotkeys, a state machine with no I/O. This commit runs it against KWin's global shortcut daemon, which KWin 6.8 runs inside itself on the session bus. kwin::hotkeys owns the component komorebi in kglobalaccel, with one action per combo, named after the combo (Alt+H). An activation of the engine is setShortcutKeys(id, [[combo]], 6), with a doRegister the first time; a deactivation is setInactive, after which the key reaches the focused window again. The calls of one event are sent without waiting for each other's answers, which Phase 0 measured at 60 calls in 2.4 ms. globalShortcutPressed and globalShortcutReleased of /component/komorebi feed the engine; globalShortcutRepeated is ignored, so a held key runs its binding once. A komorebic command runs the komorebic next to the daemon with its words when they need no shell, anything else runs through sh -c. The calls are computed by Registry, which is pure and tested; the D-Bus part is proved by the VM test. The engine hears the presses at the path /component/komorebi and does not ask kglobalaccel for the object with getComponent. kglobalaccel makes the object when the component gets its first action, so a start with no key to grab (every binding is for an application other than the one with the focus) has none to ask for: getComponent fails with NoSuchComponent, and an engine that asked would never start. A signal is matched by the path it comes from, so the presses are heard as soon as there is an object. PLATFORM.md says so. kglobalaccel keeps the actions and the grabs of a client that was killed, so a start is an idempotent reconcile: the actions of the component that the keymap names are taken over and released unless the default mode wants them, the others are unregistered. A stop releases and unregisters everything, from KWinBackend::shutdown, which SIGINT, SIGTERM and the Stop message all go through. The daemon takes --keybindings FILE, --keybindings-format skhd|whkd|sxhkd (by default from the file's name) and --keybindings-mode (the mode komorebic hotkeys compile wrote the static shortcuts in, so that the daemon leaves those to KDE); without --keybindings it reads the first of skhdrc, whkdrc and sxhkdrc in the config directory (HOME_DIR, KOMOREBI_CONFIG_HOME). It logs one line about the file and the diagnostics at debug level. An engine that cannot start is logged and the window manager runs without keys; the fake backend runs none. The VM test vm-keys-engine starts the daemon in a Plasma session with an skhdrc in the config directory, presses its keys (a command, one through a shell, komorebic retile reaching the daemon), kills the daemon and sees its keys stay registered, starts it with another file and sees the old keys unregistered and the new ones work, and stops it with komorebic stop, after which no key is registered and none runs. The library gains spawn_komorebi, kill_spawned_komorebi and shortcut_actions, and Checks.finish names the checks that failed, since nix build shows only the last lines of a failed run. The suite's node turns the module's unit off: the test runs daemons of its own.