Giter Club home page Giter Club logo

Comments (17)

bluetech avatar bluetech commented on August 26, 2024

xev uses the XLookupString() function from Xlib. The keysym and string it displays are the one returned by XLookupString().

The behavior you describe is implemented in Xlib by a hidden library control called XkbLC_ControlFallback (enabled by default).

xkbcommon implements this behavior, but not for keysyms, only the strings, i.e. xkb_state_key_get_one_sym is not affected, xkb_state_key_get_utf8() is affected. Adding it for strings was necessary for backward compatibility. No one asked for it to be added for keysyms as well.

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 Ctrl-a but it won't fix it for Alt-a. So I think the application can handle this on its own, if it wants to.

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.

from libxkbcommon.

maximbaz avatar maximbaz commented on August 26, 2024

Thanks for the answer, @kovidgoyal what do you think about this argument for implementing the fix in the kitty application itself?

from libxkbcommon.

kovidgoyal avatar kovidgoyal commented on August 26, 2024

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 libxkbcommon.

felselva avatar felselva commented on August 26, 2024

From the link that you provided:

# Ctrl+C in English layout
scancode: 0x25 release: 0 clean_sym: Control_L composed_sym: Control_L mods: numlock glfw_key: LEFT CONTROL
scancode: 0x36 release: 0 clean_sym: c composed_sym: c mods: ctrl+numlock glfw_key: C
scancode: 0x36 release: 1 clean_sym: c mods: ctrl+numlock glfw_key: C
scancode: 0x25 release: 1 clean_sym: Control_L mods: ctrl+numlock glfw_key: LEFT CONTROL

# Ctrl+C in Russian layout
scancode: 0x25 release: 0 clean_sym: Control_L composed_sym: Control_L mods: numlock glfw_key: LEFT CONTROL
scancode: 0x36 release: 0 clean_sym: Cyrillic_es composed_sym: Cyrillic_es mods: ctrl+numlock glfw_key: UNKNOWN
scancode: 0x36 release: 1 clean_sym: Cyrillic_es mods: ctrl+numlock glfw_key: UNKNOWN
scancode: 0x25 release: 1 clean_sym: Control_L mods: ctrl+numlock glfw_key: LEFT CONTROL

Shouldn't the application be using the key code scancode to test shortcuts, instead?

from libxkbcommon.

maximbaz avatar maximbaz commented on August 26, 2024

For me as a user this would be ideal, e.g. I already use such approach in my i3wm key bindings and I'm happy that my shortcuts consistently work regardless of currently active layout (in other words, I configure Ctrl+36 instead of Ctrl+C). However @kovidgoyal said this would make it impossible to use compose keys to enter non-english text — I confess I still don't understand the reason 100%, so I'll let him describe the details if necessary.

from libxkbcommon.

felselva avatar felselva commented on August 26, 2024

For me as a user this would be ideal, e.g. I already use such approach in my i3wm key bindings and I'm happy that my shortcuts consistently work regardless of currently active layout (in other words, I configure Ctrl+36 instead of Ctrl+C)

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.

from libxkbcommon.

bluetech avatar bluetech commented on August 26, 2024

This really doesn't seem like something that every application should have to workaround.

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

Yes, that's what every other application does. GTK and SDL applications for example.

I don't know about SDL, but GTK and Qt use keysyms.

Keysyms or the composed string shouldn't be used for testing shortcuts.

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).

from libxkbcommon.

kovidgoyal avatar kovidgoyal commented on August 26, 2024

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.

from libxkbcommon.

felselva avatar felselva commented on August 26, 2024

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).

Sorry, I meant scancode there.

from libxkbcommon.

maximbaz avatar maximbaz commented on August 26, 2024

Scancodes are different according to kitty's debug mode:

# QWERTY, pressing "c" (bottom row, third key from the left)
scancode: 0x36 release: 0 clean_sym: c composed_sym: c text: c mods: numlock glfw_key: C
scancode: 0x36 release: 1 clean_sym: c mods: numlock glfw_key: C

# Dvorak, pressing "c" (top row, the key right under "8" and "9")
scancode: 0x1f release: 0 clean_sym: c composed_sym: c text: c mods: numlock glfw_key: C
scancode: 0x1f release: 1 clean_sym: c mods: numlock glfw_key: C

Maybe the solution is to make application support both bindings with keysym and scancode? That's what i3wm does for example, it has commands bindsym and bindcode. In other words, if I could have configured Ctrl+40 to do what Ctrl+D does, I would be happy.

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 ~/.XCompose:

include "%L"

! Ctrl <Cyrillic_ve>: "\033D" d
! Ctrl <Cyrillic_es>: "\033C" c

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?

from libxkbcommon.

kovidgoyal avatar kovidgoyal commented on August 26, 2024

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 <modifier>+key -> modifier+another_key in it (at least as far as I can tell from reading it's absolutely pathetic documentation). Which makes it useless for your purpose.

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.

from libxkbcommon.

maximbaz avatar maximbaz commented on August 26, 2024

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.

from libxkbcommon.

bluetech avatar bluetech commented on August 26, 2024

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.

from libxkbcommon.

kovidgoyal avatar kovidgoyal commented on August 26, 2024

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?

from libxkbcommon.

bluetech avatar bluetech commented on August 26, 2024

You can use a "scratch" xkb_state (like qt does), or you can query the keymap directly if you don't need some info like consumed modifiers. Here is some old code I dug up which shows the idea:

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;
}

from libxkbcommon.

kovidgoyal avatar kovidgoyal commented on August 26, 2024

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?

from libxkbcommon.

bluetech avatar bluetech commented on August 26, 2024

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.

Incidentally how would the desktop environment know what the physical layout of the keyboard is, to insert such an ascii layout?

I don't know how they do it, but I'm willing to bet what's added is always the simple us layout.

from libxkbcommon.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.