1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-03-21 10:53:31 +01:00

wmaker: extend default keybinding for multikeys support and add sticky-chain mode

This patch extends the existing keybindings to support multiple keys and
add an optional "sticky chain" mode that lets a prefix remain active until users press
a cancel key so users can enter the continuation key without re-pressing the prefix.

The idea is to bring Emacs shortcuts keybinding to wmaker.

Normal (existing and enhanced) mode:

Prefix behaves like a one-shot release before the next key if any.
For example: Mod1+h -> hide the active application, that is still working as usual.
But if you want for example to have all your window management keys under the same leader key
you can now do something like that:
"Mod4+w h" which is pressing the Super key with w, releasing them and pressing h.
You can assign that key sequence to an action.

Sticky chain mode:

Pressing a configured prefix enters a short-lived sticky state.
Sticky state expires on timeout or when explicitly canceled (with KeychainCancelKey).
For example, you can define:
"Mod4+a x" -> run xterm
"Mod4+a b f" -> run firefox
"Mod4+a b c" -> run google chrome

In sticky mode, "Mod4+a x x b f", then KeychainCancelKey or KeychainTimeoutDelay, will launch 2 xterm and firefox.

New options for WindowMaker conf file:

KeychainTimeoutDelay: timeout in milliseconds (can be set to 0)
Default: 500
Example: KeychainTimeoutDelay = 500;

KeychainCancelKey: explicit keybinding used to cancel an active sticky chain.
If set to None the feature has no dedicated cancel key and the chain only ends by timeout
or naturally if the keybind pressed is not defined.
Default: None
Example: KeychainCancelKey = Escape;
This commit is contained in:
David Maciejak
2026-03-09 20:07:55 -04:00
committed by Carlos R. Mafra
parent ae050ceb40
commit 29177f94ed
14 changed files with 813 additions and 163 deletions

View File

@@ -425,6 +425,10 @@ void StartUp(Bool defaultScreenOnly)
*/
w_global.shortcut.modifiers_mask &= ~(_NumLockMask | _ScrollLockMask);
/* No active key chain at startup */
w_global.shortcut.curpos = NULL;
w_global.shortcut.chain_timeout_handler = NULL;
memset(&wKeyBindings, 0, sizeof(wKeyBindings));
w_global.context.client_win = XUniqueContext();
@@ -704,6 +708,10 @@ void StartUp(Bool defaultScreenOnly)
wSessionRestoreLastWorkspace(wScreen[j]);
}
for (j = 0; j < w_global.screen_count; j++) {
wKeyTreeRebuild(wScreen[j]);
}
if (w_global.screen_count == 0) {
wfatal(_("could not manage any screen"));
Exit(1);