kglobalaccel keeps the actions of a client that died, and their keys: a daemon
that is killed leaves its keys swallowed and running nothing until they are
unregistered. And kglobalaccel runs inside KWin, so a KWin that restarts forgets
every key komorebi registered. Neither should leave a user without keys.
kwin::hotkeys::release unregisters every action of the component, whatever
registered it, and komorebic hotkeys release runs it, with or without a daemon.
The NixOS module's unit runs it after the daemon stops (ExecStopPost), however
it stops, and a start already takes over what is left. The KWin backend's
NameOwnerChanged watch now also follows org.kde.kglobalaccel: when it has an
owner again, kwin::hotkeys::rebind loads the key bindings into the new one,
trying for 15 seconds.
Loading moves from the daemon's main into kwin::hotkeys::load, which keeps its
settings (Keybindings: file, format, plan mode, engine options), so that reload
can read the file again: the message ReloadHotkeys, komorebic hotkeys reload. A
new engine replaces the running one without unregistering its keys, and takes
them over as a start does, so the keys both files have stay grabbed. The message
HotkeysState answers with the engine's mode, the combos it holds and whether a
chain is pending (null without an engine); komorebic hotkeys state prints it
with the actions kglobalaccel has for the component. komorebic now depends on
komorebi for the two calls to kglobalaccel, and on serde_json for the state.
Tests: the socket messages without key bindings, state and release without a
session bus, reload without a daemon, and a nixos-module-eval check of
ExecStopPost. The VM test vm-restart-survival runs the module's unit in a Plasma
session: a key works, hotkeys state shows it; with the daemon stopped by SIGSTOP
the key runs nothing until hotkeys release gives it back; after SIGKILL the
unit's journal shows the release and the restarted daemon has the key; after the
KWin process is killed, the daemon registers the key with the new KWin; and a
reload of a changed file swaps the key.
vm-keys-engine asks the engine and does not sleep. A key that is not grabbed yet
reaches the focused window, which showed as a binding that does not run, so the
suite presses one once komorebic hotkeys state answers, which it does when the
engine has made the calls of its last event: for a mode, for a chord chain
beginning and ending, and for the keys of the application that takes the focus.
It waits for the old daemon to exit before it starts the next (a daemon started
meanwhile failed to load its KWin script), and activates a window until KWin has
it (KWin lists a window before it can have the focus). The last check reloads
the key bindings with komorebic hotkeys reload while wev has the focus and every
binding is for the terminal, a start with no key to grab.
komorebi users keep their bindings to komorebic in a file of skhd, whkd or
sxhkd. On Plasma under Wayland no client sees the keys of another, and the
program that runs a command on a key is KDE's global shortcut daemon, which runs
inside KWin. A binding that is one combo, pressed, the same in every
application, in a file without modes, can be a static shortcut: a .desktop file
that KWin reads by itself, that shows in System Settings and that works with no
komorebi process at all.
komorebic hotkeys compile reads a file of any of the three formats, plans it
with komorebi-hotkeys in the mode it is given (auto, engine or static; the
default is the crate's), prints the diagnostics of reading and planning, and
writes the static shortcuts to $XDG_DATA_HOME/kglobalaccel or --output,
replacing the files it wrote before and no other. --strict refuses a file with a
warning or an error before writing anything, --dry-run says what a write would
change, and --reload hands each new file to the running KWin. komorebic
export-kde-shortcuts keeps the spike's interface for an skhdrc, in the static
mode. Both are thin: the reading, the plan and the files are the crate's. The
bindings that need the engine are counted; the daemon does not run them yet.
docgen gives a subcommand of a subcommand a page of its own
(hotkeys-compile.md). KOMOREBI_CONFIG_HOME, or ~/.config/komorebi, is where
komorebic looks for a file it is not given.
komorebic check gains a section for the key bindings, between the configuration
and the desktop: the first key binding file of the config home, how many
bindings it has and where they go, the lines that cannot be read (a warning, and
the first five) and the bindings not realized as their own daemon would (a
note), and whether the generated files in the shortcut directory are the ones
hotkeys compile would write now (a warning with how many to add, to change and
to remove). --configuration-only keeps it, as it looks at files.
The VM test vm-keys-static boots a Plasma session with shortcut files that
hotkeys compile wrote into the system profile at build time, presses their keys
through QEMU's keyboard, and sees each command run, a % in one of them included;
then it writes a binding in the middle of the session with export-kde-shortcuts
--reload and presses it. The library gains Keys, which sends a combo as KDE
writes it through QEMU's sendkey.