xkbcommon / libxkbcommon

keymap handling library for toolkits and window systems
https://xkbcommon.org
Other
269 stars 122 forks source link

Compose key does not always work #467

Open jerome-pouiller opened 4 months ago

jerome-pouiller commented 4 months ago

Summary

I have mapped Compose key to CapsLock physical key. Then, I have noticed the behavior of the Compose key is ignored half of the time.

Steps to reproduce

Map CapsLock to Compose using KDE System Settings > Input Devices > Keyboard > Advanced > Position of Compose Key > Caps Lock.

Open a KDE application (tested with konsole and kontact). Keep Compose pressed, then type '=', then 'c', then release Compose. Repeat several times. Euro symbol (€) should be typed, but sometime you get "=c".

Useful observations

The behavior is correct if user release Compose before typing '=' and 'c'.

If you install ibus, ibus feedback show that maintaining Compose press quickly start/abort the compose sequence. So, the issue is somewhere in the repetition code of the Compose key.

I know this behavior happens in KDE applications, GIMP and LibreOffice. However, Chrome has a different behavior (it works very well with ibus).

I have first reported this bug to libinput, however they say the issue is rather related to libxkbcommon.

Required information

$ dpkg -l libinput* libxkbcommon*
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                     Version      Architecture Description
+++-========================-============-============-=======================================================================
ii  libinput-bin             1.22.1-1     amd64        input device management and event handling library - udev quirks
ii  libinput-tools           1.22.1-1     amd64        input device management and event handling library - command line tools
ii  libinput10:amd64         1.22.1-1     amd64        input device management and event handling library - shared library
ii  libxkbcommon-tools       1.5.0-1      amd64        library interface to the XKB compiler - tools
ii  libxkbcommon-x11-0:amd64 1.5.0-1      amd64        library to create keymaps with the XKB X11 protocol
ii  libxkbcommon0:amd64      1.5.0-1      amd64        library interface to the XKB compiler - shared library
ii  libxkbcommon0:i386       1.5.0-1      i386         library interface to the XKB compiler - shared library
$ cat .config/kxkbrc
[$Version]
update_info=kxkb_variants.upd:split-variants,kxkb.upd:remove-empty-lists,kxkb.upd:add-back-resetoptions

[Layout]
DisplayNames=us,
LayoutList=us,fr
LayoutLoopCount=-1
Model=pc101
Options=compose:caps
ResetOldOptions=true
ShowFlag=false
ShowLabel=true
ShowLayoutIndicator=true
ShowSingle=false
SwitchMode=Global
Use=true
VariantList=mac,
$ cat .config/kcminputrc
[$Version]
update_info=delete_cursor_old_default_size.upd:DeleteCursorOldDefaultSize,kcminputrc_fix_botched_5_21_0.upd:kcminputrc_fix_botched_5_21_0_pre,kcminputrc_fix_botched_5_21_0.upd:kcminputrc_fix_botched_5_21_0,kcminputrc_repeat.upd:kcminputrc_migrate_key_repeat

[Keyboard]
KeyboardRepeating=0
NumLock=2
RepeatDelay=140
RepeatRate=50

[Libinput][1160][4122][DELL0A36:00 0488:101A Touchpad]
ClickMethod=2
LmrTapButtonMap=true
TapToClick=true

[Libinput][1267][1842][ELAN25B6:00 04F3:0732]
OutputName=eDP-1

[Libinput][8146][45061][MELF0410:00 1FD2:B005]
Enabled=false

[Mouse]
X11LibInputXAccelProfileFlat=false
XLbInptPointerAcceleration=-0.4
cursorTheme=oxy-whitewater

[Tmp]
update_info=delete_cursor_old_default_size.upd:DeleteCursorOldDefaultSize

Note RepeatDelay=140 is a rather low value.

wismill commented 4 months ago

Just to be clear: are you using a specific Input Method (i.e. IBus), or is it just for debugging and you rely on default settings?

jerome-pouiller commented 4 months ago

I have made my tests again with (note libibus is installed):

$ dpkg -l *ibus*
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                    Version                     Architecture Description
+++-=======================-===========================-============-==========================================================================
un  ibus-data               <none>                      <none>       (no description available)
ii  libhidapi-libusb0:amd64 0.13.1-1                    amd64        Multi-Platform library for communication with HID devices (libusb backend)
ii  libibus-1.0-5:amd64     1.5.27-5                    amd64        Intelligent Input Bus - shared library
un  libusb-0.1-4            <none>                      <none>       (no description available)
ii  libusb-1.0-0:amd64      2:1.0.26-1                  amd64        userspace USB programming library
ii  libusb-1.0-0:i386       2:1.0.26-1                  i386         userspace USB programming library
ii  libusb-1.0-0-dev:amd64  2:1.0.26-1                  amd64        userspace USB programming library development files
ii  libusb-1.0-doc          2:1.0.26-1                  all          documentation for userspace USB programming
ii  libusb3380-0:amd64      0.0.1+git20190125.c83d1e9-2 amd64        USB3380 abstraction layer for libusb
un  libusbmuxd-tools        <none>                      <none>       (no description available)
ii  libusbmuxd6:amd64       2.0.2-3                     amd64        USB multiplexor daemon for iPhone and iPod Touch devices - library
un  libusbredirparser1      <none>                      <none>       (no description available)
ii  libuser-identity-perl   1.01-1                      all          module to manage a person's identities/roles

It seems I made a few error during my first tests:

wismill commented 4 months ago

Having ibus installed does not mean it is active. Do you have the IM env variables set? This is very important to know, as ibus does not use xkbcommon.

wismill commented 4 months ago

It seems Gtk handles Compose very differently than xkbcommon (and thus Qt and KDE apps):

So I do not think this is a bug: Compose is not a modifier key, it is not expected to be held down.

jerome-pouiller commented 4 months ago

Thank you for your feedback.

No, I don't export any IM variables (I did when I tested with ibus, but I reset my environment meanwhile).

On X11, the behavior of Multi_key was the one you describe in GTK (which I believe is the expected one):

So, you're right this key is really specific. It is neither a modifier neither a normal key.

jerome-pouiller commented 4 months ago

In fact on GTK/X11, Multi_key acts as a normal key, but repetition is ignored.

wismill commented 4 months ago

Do you to have the same issue when using Menu as Compose?

jerome-pouiller commented 4 months ago

I don't have Menu on my keyboard. I tested with Left Win. The behavior is identical to CapsLock.

wismill commented 3 months ago

Thank you for your feedback.

No, I don't export any IM variables (I did when I tested with ibus, but I reset my environment meanwhile).

On X11, the behavior of Multi_key was the one you describe in GTK (which I believe is the expected one):

* press `<Multi_key>`, `<e>`, `<e>`, release `<Multi_key>` → `ə`

* press `<Multi_key>`, release `<Multi_key>`, `<e>`, `<e>` → `ə`

* press `<Multi_key>`, release `<Multi_key>`, press `<Multi_key>`, release `<Multi_key>`, `<e>`, `<e>` → `ee`

* press `<Multi_key>`, release `<Multi_key>`, press `<Multi_key>`, `<e>`, `<e>`, release `<Multi_key>` → `ee`

So, you're right this key is really specific. It is neither a modifier neither a normal key.

It is the expected behavior for Gtk. The last two “do not work” because the sequence <Multi_key> <Multi_key> <e> <e> is not defined. If you add <Multi_key> <Multi_key> <e> <e> : "ə" U0259 you should have the same result than the first two examples. Could you confirm it?

So what we have here are implementation differences (Gtk/xkbcommon-Qt). As Compose key and Multi_key keysym are not modifiers, I do not think there is something to fix.

But I will try to have a look at the Gtk implementation, to check if this is a feature or an unintended side effect. If this is a feature, I would like to known the motivation.

jerome-pouiller commented 3 months ago

In fact the only difference between GTK and xkbcommon is: press <Multi_key>, <e>, <e>, release <Multi_key>. On GTK and X11, you always get ə, while on xkbcommon-Qt, you sometime get ee (depending of the repeat delay/rate).

wismill commented 3 months ago

I did not dive into Gtk code, but the behavior seems simple enough to understand: when no valid sequence is found, Gtk does not reset its state machine. You can use <Multi_key> <Multi_key> : "!" exclam to get similar behavior than e.g. dead_acute.

If you want the same behavior in non-Gtk apps, you should open a ticket in e.g. Qt repository and point to this issue.

@whot @bluetech I think we would still need a new API for that though: something like:

// Option 1: new function with configurable behavior, using an additional argument
enum xkb_compose_feed_result
xkb_compose_state_feed2(struct xkb_compose_state *state, xkb_keysym_t keysym, bool reset)
// Option 2: new function that keep previous state in case of failure
enum xkb_compose_feed_result
xkb_compose_state_feed_no_reset(struct xkb_compose_state *state, xkb_keysym_t keysym)