-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Allow sway to remap key combinations #8937
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
How does this compare to custom XKB maps? https://github.com/swaywm/sway/wiki#load-a-modified-custom-xkb-keymap-xmodmap-equivalent |
As I understand it xkb is designed to handle individual key mappings like changing specific keys in your keyboard layout. What this PR achieves would allow users to quite simply map certain keybinds that will work either globally or tailored for specific apps. One such case would be cmd+c for copy mapping to ctrl+c in most apps but then also allowing the mapping to be adjusted to ctrl+shift+c on the terminal, hence achieving a single keybind across multiple apps. This is similar to what is supported by Hyprland, xremap and others. |
ba566a3 to
6e983f6
Compare
kennylevinsen
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I do see that this would be practical, I don't see a way to make a feature like this work well. The reason xkb does not support a way to remap key combos is because it is not reconcilable with an interface working on individual key events. Attempts to do so involve unstable hacks like sending storms of synthetic keyboard events to try to coerce a certain application xkb state and revert it afterwards.
A solution that is compatible with how keyboards work is using dedicated keysyms for various actions. For example, there's XF86Cut, XF86Copy and XF86Paste - normally used for dedicated cut/copy/paste multimedia keys - which can be arbitrarily assigned in your keyboard layout. There's also a large number of unused F keys available if you need spares. Given your examples, there are probably already keyboard events available for what you need/want.
Alternatively we'd be looking at a way to abstract "actions" from keyboard events in a separate protocol to give sway control, something similar to global hotkey protocol proposals.
| wlr_seat_set_keyboard(wlr_seat, keyboard->wlr); | ||
| wlr_seat_keyboard_notify_modifiers(wlr_seat, &new_mods); | ||
| wlr_seat_keyboard_notify_key(wlr_seat, time_msec, target_keycode, state); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not correct. For an application to register, say, "ctrl+c" correctly, it needs to see something like:
- Left ctrl press
- Modifiers |= ctrl
- "C" press
- "C" release
- Left ctrl release
- Modifiers &= ~ctrl
This, however, is just faking the modifiers and key, which means:
- The keys held and the active modifiers are not consistent (say, left super pressed leading to ctrl modifier, no ctrl key held).
- The faked modifier and key sticks, so the following keypresses will be on a weird and inconsistent keyboard state, and e.g. the modifier may end up being immediately reset even though the remapped combo has not been released. Modifiers affect other things, such as drag-and-drop, so this is not great.
Could you help me understand it can't work well? Detection seems to work well enough right now, all I'm doing is transforming the keys being delivered to the surface when an "expected" key combination is detected. I made a small adjustment because beforehand I wasn't taking into consideration the already translated keys froms xkb so it doesn't add any complexity to the current detection of combinations and it does work well so far I've been running this version backported to v1.11 and so far the only issues were the key translations that I had missed. I am, however, new to this project and wayland in general so I might be missing something here. |
Sure. An application does not see you click "ctrl + alt + del", it sees a series of keypresses the gradually change the keyboard state until finally ctrl, alt and del are all held at the same time. As a random example, imagine you try to map "ctrl + alt + del" to "super + shift + 5". To make this happen, a lot of keyboard events would need to be sent. First, ctrl and alt get sent because the final part of the keycombo hasn't happened yet:
Then, "del" is pressed and whatever is doing the mapping must start to roll back the real button presses and apply the fake ones:
Then the actual "del" press is sent, translated to "5"
Then we roll back to the real held buttons:
Finally, you let go of the remaining buttons:
Throughout this, keyboard state is really weird and inconsistent (what would happen if you pressed "ctrl + alt + del + 1"? would it become "super + shift + 5 + 1" or "ctrl + alt + del + 1"?), and the app sees it as if you are pressing and letting go of keys a lot. Some apps do things when you press and hold modifiers (like highlighting menus, changing cursors, affecting current drag-n-drop/select operation), or even use modifier keys as general keys (e.g. a game using "shift" as a regular button for running/jumping/scope aiming/whatever). Things probably get even hairier if we involve IMEs. The above would be what something like xremap does. What your PR does is simpler because it "just" sends a fake modifier list before the fake symbol, but I don't think it's valid to have modifiers be completely disconnected from key events like that - at the very least it would be quite surprising for an application. It would be interesting to establish for sure whether that's allowed or not though, as I don't think anyone thought of it, but even if it is allowed it is not guaranteed to work for this usecase. The main reason we have separate modifier event as opposed to having apps always listen to key events to deduce the modifiers is because we sometimes need to notify a client without keyboard focus of what the current modifiers are, for example during drag-and-drop operations. On the other hand, if you instead of key combos use keysyms, such as XF86Cut, then you already have full arbitrary remapping capability through your keymap. The issue is that client-side keycombos basically sidestep the keymap to some extent. |
|
is there an architectural difference between what we're discussing and what is done on xremap or hyprland? If I understand what you are saying, you think this is the wrogn approach because it will send "fake" modifiers. If instead we were to just send an additional even, that would be ok? Effectively monitoring the stream of keys and when a trigger is detected just send an additional fake "key combination" event ? |
The goal of this PR is adding support for remapping key combinations in a global way, avoiding the need for setting up other applications that normally require full access to a device or sudo.
Since all the processing already happens on sway, I only introduced a new configuration and we replace the keys for keyboards that belong to a group.
I'm quite new to the sway codebase so please let me know if there's a better way of achieving this or any modifications so that you'd be willing to accept the PR.
I have tested by starting a nested compositor and trying all the keybinds in either terminals or a text editor, from my testing everything seemed to be working.