Skip to content
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

Added keyboard-mapping based on symbol (use "mapsym" in config) #665

Closed
wants to merge 3 commits into from
Closed

Added keyboard-mapping based on symbol (use "mapsym" in config) #665

wants to merge 3 commits into from

Conversation

Ma-Shell
Copy link
Contributor

This pull-request adds the option to add keyboard shortcuts based on symbols instead of GLFW-keys.
The necessity of using GLFW-keys is quite annoying to any user of non-English keyboards, since some keys can simply not be mapped (see #643).
In order to not break with the current mappings, it adds a new identifier to the config: mapsym.
e.g.: mapsym kitty_mod+* change_font_size all +2.0
can be used on a german keyboard to map the "+"-key (which becomes a "*", when pressed together with shift). It is important to always specify the symbol with modifiers applied, (i.e. mapping shift+x will not work, since there is usually no way to get a lower-case x at the same time as shift -> use shift+X) when mapping.

Technical details:
Keybindings are stored and processed in python, just like ordinary key-presses.
In C, there is the array needs_special_sym_handling, which takes the utf-8-encoded symbol as the index mangled with the mod-keys for early decisions whether a mapping should be sent to python (much like the needs_special_handling-array). Note that this is only an early detection, whether the pressed keys might need special treatment, since the actual decision, whether to treat it in a special manner is taken in Python. For that reason, it is not necessary for the needs_special_sym_handling-table to uniquely map each symbol to a different entry and thus, it does not have to be big enough to store every symbol/mod-combination.

The symbols that are used are are given by xkb_state_key_get_utf8. There is one downside to that function: When using Ctrl+Shift, it does not generate any symbols. My proposal here is to simply ignore the Ctrl while resolving the symbol, if Shift is pressed, as well.
The current implementation otherwise explicitly does not generate the symbol-text, if either Ctrl, Alt, or Super are pressed. For this purpose, however, I changed that behaviour, which is not really necessary in my opinion. (i.e. formerly pressing Ctrl+Shift+Z would simply enter nothing, if that was not bound to any combination while with the change it enters a capital Z.)

- Keys mapped with "mapsym" are handled before keys mapped with just "map".
  This is convenient, since default keys are mapped with "map" and thus would
  need to be set to "no_op" using the GLFW-name before being able to map them
  via sym
- Added option of using "+" by escaping it as "plus"
@kovidgoyal
Copy link
Owner

Some comments:

  1. Meta comment: The glfw files in kitty are auto-generated from my glfw fork. So changes to those should come as a PR to my glfw fork

  2. Your proposed patch would break keyboard handling for people using layouts such as a russian layout. By always adding text it breaks the fallback logic at line 448

  3. Using text to match keystrokes means you can only match keys that have a textual representation and there is no easy way to figure out what that textual representation is for end users. They'd basically have to use --debug-keys to figure it out. And then there's the whole can of worms of shift keys, which modify text. So you have to figure out what shift+x and shift+X match.

  4. Adding new config directives is not acceptable for this. Instead the correct way to do this would be to have parse_shortcut handle the case of a key that does not map to glfw key and return something to represent it. Either a negative integer or an object or something, depending on what the actual technique for matching keys is.

Now if you really want to do this, here are some thoughts:

  1. This feature is linux only, since as far as I know, apple does not have dedicated non-english keys, instead you type non-english characters by pressing the option key so there is no question of shortcuts with non-english keys.

  2. Since this is linux only, it makes more sense to me to use xkb key names for keys not representable in glfw.

  3. In order to support (2) you would need to make the following changes:

  • Add a native (C) function that takes a key name as a lowercase ascii string and maps it to an xkb symbolic name (which is just an integer, see keysymdef.h on your system)
    Implementing this function is going to be a major pain, which is why I dont want to implement this feature in the first place. Essentially to make it performant you would need to write code in python to parse keysymdef.h and from it generate a perfect hash function using gperf and use that to implement the function.

  • In keys.c in on_key_input the xkb symbolic key is availabel as scancode, soif the glfw key is UNKNOWN then you match on the scancode instead.

  • In order to not need a separate config directive, you simply store xkb symbolic names in keymap in parse_shortcuts shifted by 16bits so they can never conflict with glfw key codes.

  • We obviously cannot store all keys to check for special handling, so instead store all the actual mappings and iterate over them with scancode to see if they map. Since the typicaluser will not have more than a few dozen mappings, this should be fast enough.

  • Add some documentation to the map config directive saying that X11 platforms you can also use XKB symbolic key names.

@kovidgoyal
Copy link
Owner

Turns out libxkb has a function we can use to get sym codes from names, https://xkbcommon.org/doc/current/group__keysyms.html#gad6b3273c0a82876bba5bd59958358fbe

that should make this significantly easier to implement. Now you just need to wrap this as an API in glfw3native.h for the X11 and wayland backends

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants