-
Notifications
You must be signed in to change notification settings - Fork 124
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
Generate layout-agnostic events when holding Ctrl #61
Comments
xev uses the The behavior you describe is implemented in Xlib by a hidden library control called xkbcommon implements this behavior, but not for keysyms, only the strings, i.e. I am inclined to not support this. In general, adding these special cases just makes it harder for an application to get things working in the hand, since it has to handle a bunch of obscure edge-cases. This solution is not general; for example, in the terminal example it might (arguably) fix the problem with BTW, the switching-language-breaks-shortcuts problem is well known, and is handled by both big toolkits (GTK and Qt) at least. A terminal has its own input pipeline though. |
Thanks for the answer, @kovidgoyal what do you think about this argument for implementing the fix in the kitty application itself? |
This really doesn't seem like something that every application should have to workaround. And there really is no good way to workaround it. You want ctrl+X in the russian layout to generate Ctrl+. Somebody else might want it to generate Arabic Aleph. This kind of thing belongs in the layout definition,or if that is not possible, then via XCompose rules. Applications should not be second guessing what keys the OS wants them to generate, that way lies chaos. It means that it is not possible for users to configure their keyboards in one cetral place, instead they have to somehow get every different application to do what they want, that is insanity. |
From the link that you provided:
Shouldn't the application be using the |
For me as a user this would be ideal, e.g. I already use such approach in my |
Yes, that's what every other application does. GTK and SDL applications for example. Keysyms or the composed string shouldn't be used for testing shortcuts. |
Shortcuts are not a concept in XKB. Shortcuts are an application-level concept. Different applications want different things (for the same user). To use your example, Application A wants ctrl+X in the russian layout to generate Ctrl+. Application B might want it to generate Arabic Aleph
I don't know about SDL, but GTK and Qt use keysyms.
Using keycodes for shortcuts does not work well in general. For example, "Ctrl-S" is the universally accepted shortcut for "Save"; if you configure your qwerty keyboard with a dvorak layout, it should still be "Ctrl-S" (here I mean the key that generates "S" in the dvorak layout). |
Indeed, it is to support people with layouts like dvorak that kitty uses keysyms not keycodes. To me it is logical that if you press the key X and get S output as text, you should be able to press the key Ctrl+X and get the shortcut Ctrl+S not Ctrl+X As I said before, it is not possible for an application to figure out what the user wants. It is up to the user to configure their keyboard layout to generate the logical keypresses they intend, with and without modifiers. No other approach can possibly hope to be consistent or logical. |
Sorry, I meant scancode there. |
Scancodes are different according to kitty's debug mode:
Maybe the solution is to make application support both bindings with keysym and scancode? That's what I also tried to make use of XCompose as suggested, it's very difficult to find how to properly configure it, but trial and error helped achieve the following
It does send Ctrl+C and Ctrl+D to the application when active layout is Russian, but (1) I can't figure out how to make a binding for Ctrl+Shift+C, i.e. what escape code corresponds to Shift, and (2) this magic with escape code "\033" feels a bit specific to terminal apps only, isn't it? |
I suspect I was wrong about xcompose, the fundamental problem is that xcompose is designed to output text, not key presses, so there is no way to represent a mapping from That means you have to rely on the XKB layout, and that is, as far as I can tell an undocumented rat's nest. I dont see in principle why XKB is not able to map modifier+key to modifier+another key but I cannot find out how to do it, without spending indecent amounts of time on it, at least. Maybe somebody with more experience with XKB can point you in the right direction. As for binding via keycode instead of keysym -- it is an ugly hack to a problem that is correctly solved at the system level. And it means that in order to bind the shortcuts, users have to now figure out what the scancode for their keys is. That is really unacceptable. Not to mention fragile. As far as I know there is no guarantee that scancodes are portable across systems, so tomorrow if you change your computer/kernel version/graphics stack/keyboard model all your shortcuts will stop working, and I will have to deal with the bug reports. |
This was solved on application level without introducing the initially suggested hack, the application now makes use of xkb fallback keyboard layout. Thank you for your input, closing the ticket. |
That's not a bad way to do it. Another way to do it is, instead of looking at a fallback keymap, look at a fallback "ascii layout" in the same keymap. By "ascii layout" I mean a layout which generates English-like Latin keysyms. I believe that for this purpose, modern desktop environments ensure that there is always at least one "ascii layout", i.e. they add a hidden one if not present. |
How would I I do that? It's not clear to me form the libxkb API docs. And would doing it modify the xkb_state or xkb_compose_state? |
You can use a "scratch" static xkb_keysym_t
get_ascii(struct xkb_state *state, xkb_keycode_t keycode)
{
struct xkb_keymap *keymap;
xkb_layout_index_t num_layouts;
xkb_layout_index_t layout;
xkb_level_index_t level;
const xkb_keysym_t *syms;
int num_syms;
keymap = xkb_state_get_keymap(state);
num_layouts = xkb_keymap_num_layouts_for_key(keymap, keycode);
for (layout = 0; layout < num_layouts; layout++) {
level = xkb_state_key_get_level(state, keycode, layout);
num_syms = xkb_keymap_key_get_syms_by_level(keymap, keycode,
layout, level, &syms);
if (num_syms != 1)
continue;
if (syms[0] > 0 && xkb_keysym_to_utf32(syms[0]) < 128)
return syms[0];
}
return XKB_KEY_NoSymbol;
} |
Interesting, thanks. However, I'm not sure how reliable that would be. A lot of my users use alternative desktop environments, such as i3 or other window managers/lightweight desktops. If as you say, it is the responsibility of the desktop environment to ensure there is always an ascii layout, it might not be the case that all of them do that. On the other hand, I dont know how often the default keyboard layout would match the keyboard the user has connected either. I wish there was some "official" way to do this. The advantage with using the default keyboard layout is that it can be easily configured by the user. Hidden layouts automagically inserted by desktop environments, not so much. Incidentally how would the desktop environment know what the physical layout of the keyboard is, to insert such an ascii layout? |
I agree you can't be completely sure that an ascii layout is present. In my experience (which might be biased), most users do have one. And for terminal users, not having one would be very hard. But again, I agree.
I don't know how they do it, but I'm willing to bet what's added is always the simple |
xev
shows a very interesting behavior, when holding Ctrl it always generates latin key events even if the currently active layout is Russian (which only has cyrillic letters).Click to see the output
English layout, press "d", xev sees it as "d":Russian layout, press "d", xev sees it as cyrillic "в":
English layout, press "Ctrl+d", xev sees it as "Ctrl+d":
Russian layout, press "Ctrl+d", xev sees it as latin "Ctrl+d" and not cyrillic "Ctrl+в":
I know this might sound like an xkcd comic, but please bear with me, this is truly very useful, because applications can have keyboard shortcuts and they work regardless of the currently active layout. For example, in terminal
Ctrl+C
,Ctrl+D
,Ctrl+Shift+C
do not work unless you configure an English keyboard layout on your computer.I was told
xev
usesxlib
to get this behavior, and it looks likelibxkbcommon
doesn't follow this behavior.Here's what
libxkbcommon
emits when I pressCtrl+d
in Russian layout:This was originally reported for
kitty
terminal, the author suggested this to be fixed inlibxkbcommon
instead.The text was updated successfully, but these errors were encountered: