sway
sway copied to clipboard
Sticky modifiers
Sticky modifiers is supported on X with xkbset
:
# Enable "sticky keys" for all modifier keys, while also enabling "latchlock"
# (i.e., pressing any modifier key twice in a row locks that key
# on) and disabling "twokey" (i.e., pressing any modifier key and another key
# at the same time permanently disables "sticky keys"). Note that enabling
# "sticky" automatically enables sticky keys for Apple- and Windows-specific
# modifier keys as well, including: <Shift>, <Ctrl>, <Alt>, <Fn>, and <Apple>.
xkbset -bell -feedback sticky -twokey latchlock
# Disable expiration of "sticky keys" after the specified time in seconds. When
# expiration is enabled, sticky keys are permanently disabled after that many
# seconds. This is quite unhelpful.
xkbset exp 64 '=sticky' '=twokey' '=latchlock'
and on GNOME. In dconf, org.gnome.desktop.a11y.keyboard
schema:
- stickykeys-enable: Enable sticky keys
- stickykeys-two-key-off: Disable when two keys are pressed at the same time (revert to non-sticky behavior)
Please fill out the following:
- Description: Press and release modifier key and press another key to behave the same as simultaneously pressing both key together. Disable this behavior if two or more keys are pressed simultaneously.
I tried to set a custom keymap containing this modification but have not been able to do so. It is implemented in libxkbcommon as accessX but activating it seems to do nothing.
Quote from GNOME page:
Historically, AccessX features [including StickyKeys] and key repeat have been implemented in the X server (as part of XKB). Under Wayland, key repeat is currently implemented client-side in GTK+, and other AccessX features are not implemented. ... A client-side implementation of the other AccessX features is doable, but problematic. This should really be implemented in the input event routing layer of the compositor. A slight complication arises for X clients, where we need to disable the XKB implementation in Xwayland, or somehow make it sync state with the compositor.
I might be interested in working on this for selfish reasons, but I need more background as I'm not a sway developer.
One thing I'm not clear on: could this be handled within the XKB configuration? Is this potentially an "option"? XKB is really complex, and I'm only just now really getting into it. But it seems like this feature could be handled at some library level, if not libxkb, then wlroots, for example.
Not every wayland app is a GTK app. Some will interact directly with the compositor, for example. It doesn't make sense for clients to handle this, to my naive understanding.
I've managed to do this locally (for shift, control, start/super, alt) via adding an option in /usr/share/X11/xkb/rules/evdev
.
- Create
/usr/share/X11/xkb/symbols/sticky
File content
partial alphanumeric_keys
xkb_symbols "latch" {
key <RALT> {
symbols = [ ISO_Level3_Shift ],
actions = [ LatchMods(mods=Alt,clearLocks,latchToLock) ]
};
key <LALT> {
symbols = [ ISO_Level3_Shift ],
actions = [ LatchMods(mods=Alt,clearLocks,latchToLock) ]
};
key <LFSH> {
symbols = [ ISO_Level3_Shift ],
actions = [ LatchMods(mods=Shift,clearLocks,latchToLock) ]
};
key <RTSH> {
symbols = [ ISO_Level3_Shift ],
actions = [ LatchMods(mods=Shift,clearLocks,latchToLock) ]
};
key <RWIN> {
symbols = [ ISO_Level3_Shift ],
actions = [ LatchMods(Mods=Super,clearLocks,latchToLock) ]
};
key <LWIN> {
symbols = [ ISO_Level3_Shift ],
actions = [ LatchMods(Mods=Super,clearLocks,latchToLock) ]
};
key <LCTL> {
symbols = [ ISO_Level3_Shift ],
actions = [ LatchMods(Mods=Control,clearLocks,latchToLock) ]
};
key <RCTL> {
symbols = [ ISO_Level3_Shift ],
actions = [ LatchMods(Mods=Control,clearLocks,latchToLock) ]
};
};
- Under
! option = symbols
in/usr/share/X11/xkb/rules/evdev
add a line forsticky:latch = +sticky(latch)
(indention at line start may or may not matter).
You should now be able to enable and disable stickey keys via sway-input
.
Enable: swaymsg -- input '*' xkb_options 'sticky:latch'
Disable: swaymsg -- input '*' xkb_options '-sticky:latch'
(alternatively, you could add something like bindsym $mod+Control+s input * xkb_options sticky:latch
in your sway config)
Note that /usr/share/X11/xkb/rules/evdev
is a generated file. There might be another way to do this that doesn't require editing this generated file but this is suitable for my needs.
You can create user configurations in your home directory. #7326 will be necessary in some cases.
That worked perfectly! As I am already using a custom keyboard layout, all I needed to do was to add the code snippet into my existing keyboard config.
- Create the following directory
mkdir -p ~/.config/xkb/symbols/
- Add keyboard configuration to
~/.config/xkb/symbols/my-xkb-config
- Select keyboard layout in sway config and reload sway
# inside ~/.config/sway/config
input "type:keyboard" {
# xkb_layout config-file-name-without-path(keyboard-layout-name)
xkb_layout my-xkb-config(my-keyboard-layout)
}
I have attached my config below. If my custom keyboard layout is (most likely) not needed, just delete that section to revert to us(basic)
qwerty layout + sticky modifiers.
I encountered some difficulties switching between layouts -- seems that key <CODE> { symbols = []; actions = []; }
conflict with each other.
But I've found an alternate solution for setting sticky modifiers. Namely, obtain a dump of the current keyboard layout with
xkbcomp $DISPLAY keymap.xkb
Then open the resulting plain text file with your favorite editor and replace all instances of the string SetMods
with LatchMods
. Finally, load the keyboard map file with sway:
# inside ~/.config/sway/config
input "type:keyboard" {
xkb_file $HOME/.config/sway/keymap.xkb
}
And there you have it.
This sticky-modifiers keymap has en-US qwerty layout and can be directly used with sway.
- Pressing two or more keys together will revert to non-sticky behavior.
- When a modifier is accidentally pressed, press it once more to cancel it.
This is another sticky-modifiers keymap. It is different from the keymap above in that the option latchToLock
is added to every instance of latchMods()
option.
- Pressing two or more keys together will revert to non-sticky behavior.
- When a modifier is pressed once, sticky for the next key pressed.
- When a modifier is pressed twice, sticky until this modifier is pressed a third time.
en_us-sticky-modifiers-keymap-with-latch-to-lock.xkb.txt
To switch between different keyboard layouts, bind a key to the original, non-sticky keymap.
bindsym $mod+Control+s input type:keyboard xkb_file $HOME/.config/sway/original_keymap.xkb
bindsym $mod+Shift+s input type:keyboard xkb_file $HOME/.config/sway/sticky_keymap.xkb
Thank you so much. I'm not a Sway user, but I was trying to get Ubuntu + Wayland working with sticky keys. The current Ubuntu built-in Sticky Keys has no way to disable "latch to Lock" (XkbAX_LatchToLock
). I do not want this setting. Following these comments, i was able to use XKB directly to turn off this behavior!
Glad it helped you. XKB is indeed quite flexible when you are using it directly, as opposed to whichever option the desktop environment decided to provide.
For example, if you followed my steps, you can even use Caps Lock or Scroll Lock indicator for showing the status of sticky modifiers! You can see that in action here:
https://github.com/ne9z/personal-dotfiles/blob/6a7f7c8fad52e89e037ac63d74d699ba40f0c0a6/modules/per-user/yc/modules/home-manager/not-nix-config-files/sway-yc-sticky-keymap#L1185
Omar Navarro Leija @.***> writes:
Thank you so much. I'm not a Sway user, but I was trying to get Ubuntu + Wayland working with sticky keys. The current Ubuntu built-in Sticky Keys has no way to disable "latch to Lock" (
XkbAX_LatchToLock
). I do not want this setting. Following these comments, i was able to use XKB directly to turn off this behavior!-- Reply to this email directly or view it on GitHub: https://github.com/swaywm/sway/issues/6852#issuecomment-1505986121 You are receiving this because you modified the open/close state.
Message ID: @.***>