kovidgoyal / kitty

Cross-platform, fast, feature-rich, GPU based terminal
https://sw.kovidgoyal.net/kitty/
GNU General Public License v3.0
24.25k stars 976 forks source link

Ambiguous XCompose sequences do not work #7953

Closed omentic closed 1 week ago

omentic commented 1 week ago

Describe the bug I have a variety of mappings in my XCompose file. Some of them, like <Multi_key> <a> <l> <p> <h> <a> : "α" are unambiguous: there is no way to continue the sequence and to a different mapping. Some of them, like <Multi_key> <a> : "α", are ambiguous: the sequence could be continued to a different keybinding.

Everywhere on my computer, pressing some key that does not lead to a continuation of some sequence - ex. usually space or esc - ends the compose by inserting the character associated with the string up until then, and inserts the remainder of the sequence. For instance, Multi_key a l p x t inserts αlpxt.

This is not the case in Kitty. Multi_key a l p x t only inserts t.

I think this is probably a bug - and if it isn't, this is a feature request to have Kitty behave equivalently to applications using toolkits! It would also be nice if Kitty supported partial rendering (ex. Firefox renders α with an underscore while in the middle of typing out the full sequence) but that is neither here nor there.

To Reproduce Create a .XCompose file with the following lines in it:

<Multi_key> <a> : "α"
<Multi_key> <a> <l> <p> <h> <a> : "α"

Observe that pressing Compose a l p h a inserts α. Observe that pressing Compose a followed by something (other than l) does not insert α.

Environment details I don't have F6 on my keyboard, but I am running kitty 0.36.4 on Arch Linux, under KDE Plasma 6.1 under Wayland.

Additional context Reproducible with kitty --config NONE.

debug input log Keys pressed: `Compose` `a` `l` `p` `h` `a` `` `Compose` `a` `` ``` [apropos@arch ~]$ kitty --config NONE --debug-keyboard [0.079] Loading new XKB keymaps [0.084] Modifier indices alt: 0x3 super: 0x6 hyper: 0xffffffff meta: 0xffffffff numlock: 0x4 shift: 0x0 capslock: 0x1 control: 0x2 [0.132] text-input: updating cursor position: left=3 top=6 width=9 height=20 [0.134] Mouse cursor entered window: 1 at 275.621094x47.300781 [0.134] on_focus_change: window id: 0x1 focused: 1 [0.134] text-input: updating IME focus state, ime_focused: 0 ev->focused: 1 [0.134] text-input: updating IME focus state, ime_focused: 0 ev->focused: 1 [0.134] text-input: enter event [0.134] on_focus_change: window id: 0x1 focused: 1 [0.134] text-input: updating IME focus state, ime_focused: 1 ev->focused: 1 [0.134] Got notification server capabilities: frozenset({'body-images', 'body-hyperlinks', 'x-kde-display-appname', 'inline-reply', 'body', 'icon-static', 'inhibitions', 'persistence', 'x-kde-origin-name', 'x-kde-urls', 'actions', 'body-markup'}) [0.154] text-input: done event: serial: 1 current_commit_serial: 5 [0.154] text-input: done event: serial: 2 current_commit_serial: 5 [0.154] text-input: done event: serial: 3 current_commit_serial: 5 [0.154] text-input: done event: serial: 4 current_commit_serial: 5 [0.154] text-input: done event: serial: 5 current_commit_serial: 5 [3.215] Press xkb_keycode: 0x63 clean_sym: Multi_key compose not complete, ignoring. [3.341] Release xkb_keycode: 0x63 clean_sym: Multi_key mods: none glfw_key: 0 (UNKNOWN) xkb_key: 65312 (Multi_key) alternate_key: 57361 (PRINT_SCREEN) [3.970] Press xkb_keycode: 0x1e clean_sym: a compose not complete, ignoring. [4.056] Release xkb_keycode: 0x1e clean_sym: a mods: none glfw_key: 97 (a) xkb_key: 97 (a) [4.244] Press xkb_keycode: 0x26 clean_sym: l compose not complete, ignoring. [4.322] Release xkb_keycode: 0x26 clean_sym: l mods: none glfw_key: 108 (l) xkb_key: 108 (l) [4.503] Press xkb_keycode: 0x19 clean_sym: p compose not complete, ignoring. [4.573] Release xkb_keycode: 0x19 clean_sym: p mods: none glfw_key: 112 (p) xkb_key: 112 (p) [4.728] Press xkb_keycode: 0x23 clean_sym: h compose not complete, ignoring. [4.814] Release xkb_keycode: 0x23 clean_sym: h mods: none glfw_key: 104 (h) xkb_key: 104 (h) [4.996] Press xkb_keycode: 0x1e clean_sym: a composed_sym: NoSymbol composed_text: α mods: none glfw_key: 0 (UNKNOWN) xkb_key: 0 (NoSymbol) shifted_key: 97 (a) alternate_key: 97 (a) [4.996] on_IME_input: text: α [4.996] text-input: updating cursor position: left=165 top=6 width=9 height=20 sent key as text to child: α [4.996] text-input: done event: serial: 6 current_commit_serial: 6 [5.074] Release xkb_keycode: 0x1e clean_sym: a mods: none glfw_key: 97 (a) xkb_key: 97 (a) [5.074] on_key_input: glfw key: 0x0 native_code: 0x0 action: RELEASE mods: none text: '' state: 0 [5.074] text-input: updating cursor position: left=174 top=6 width=9 height=20 ignoring release event for previous press that was handled as shortcut [5.074] text-input: done event: serial: 7 current_commit_serial: 7 [6.362] Press xkb_keycode: 0x39 clean_sym: space composed_sym: space text: mods: none glfw_key: 32 ( ) xkb_key: 32 (space) [6.362] on_key_input: glfw key: 0x20 native_code: 0x20 action: PRESS mods: none text: ' ' state: 0 sent key as text to child: [6.432] Release xkb_keycode: 0x39 clean_sym: space mods: none glfw_key: 32 ( ) xkb_key: 32 (space) [6.432] on_key_input: glfw key: 0x20 native_code: 0x20 action: RELEASE mods: none text: '' state: 0 [6.432] text-input: updating cursor position: left=183 top=6 width=9 height=20 ignoring as keyboard mode does not support encoding this event [6.433] text-input: done event: serial: 8 current_commit_serial: 8 [9.343] Press xkb_keycode: 0x63 clean_sym: Multi_key compose not complete, ignoring. [9.452] Release xkb_keycode: 0x63 clean_sym: Multi_key mods: none glfw_key: 0 (UNKNOWN) xkb_key: 65312 (Multi_key) alternate_key: 57361 (PRINT_SCREEN) [9.891] Press xkb_keycode: 0x1e clean_sym: a compose not complete, ignoring. [9.993] Release xkb_keycode: 0x1e clean_sym: a mods: none glfw_key: 97 (a) xkb_key: 97 (a) [10.204] Press xkb_keycode: 0x39 clean_sym: space compose not complete, ignoring. [10.290] Release xkb_keycode: 0x39 clean_sym: space mods: none glfw_key: 32 ( ) xkb_key: 32 (space) ```
kovidgoyal commented 1 week ago

I dont know what toolkits other than Microsoft windows have this behavior. Quoting the libxkbcomomn docs:

Cancellation Behavior
What should happen when a sequence is cancelled? For example, consider there are only the above sequences, and the input keysyms are <dead_acute> <b>. There are a few approaches:

1. Swallow the cancelling keysym; that is, no keysym is produced. This is the approach taken by libX11.
2. Let the cancelling keysym through; that is, <b> is produced.
3. Replay the entire sequence; that is, <dead_acute> <b> is produced. This is the approach taken by Microsoft Windows (approximately; instead of <dead_acute>, the underlying key is used. This is difficult to simulate with XKB keymaps).

And indeed there is no API in libxkbcommon to accomplish 3 which is what you are asking for. If you know of such an API, feel free to submit a PR. Or get the libxkbcommon maintainers to create such an API and I will be happy to have kitty use it. One could probably hack together some partially working kludge by recording the key events and then re-interpreting them as key events without composition enabled, but this is fraught with edge cases and needs to be implemented in libxkbcommon, not every application/toolkit independently.

omentic commented 1 week ago

Ah interesting! Upon further investigation, it does look like Qt and GTK have different behavior (and both differ from kitty). Kitty does (1), Qt does (2), GTK does (3).

It looks like there is an open xkbcommon issue for (3): https://github.com/xkbcommon/libxkbcommon/issues/395.