libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.98k stars 1.84k forks source link

Compose key keypress events aren't sent to IME under X11 #6437

Open Guldoman opened 2 years ago

Guldoman commented 2 years ago

Key presses of the compose key get eaten by https://github.com/libsdl-org/SDL/blob/f4d1f5ed54aecbbccf20e4967b14f965196b7694/src/video/x11/SDL_x11events.c#L773-L796 and are not sent to https://github.com/libsdl-org/SDL/blob/f4d1f5ed54aecbbccf20e4967b14f965196b7694/src/video/x11/SDL_x11events.c#L1072-L1076

Key releases are handled as expected.

Because of this, TEXTEDITING events aren't generated while using the compose key.

slouken commented 1 month ago

Do you have minimal repro steps for this? Maybe desktop environment setup and repro with checkkeys?

Guldoman commented 1 month ago

I'm testing on GNOME 47 Wayland. Under Settings->Keyboard->Compose key I have Right ctrl.

When running Lite XL with Xwayland, pressing the compose key doesn't make the IME functionality show up (the center dot thing). Continuing with the compose action (for example pressing a twice) makes the correct character show up (å).

If I use SDL_VIDEODRIVER=wayland, it shows up as expected.

Here I'm pressing right ctrl -> a -> a in both cases:

https://github.com/user-attachments/assets/26c9dcfc-7555-4020-8870-1df24a4e0a47

EDIT: This is checkkeys, doing the same thing as above:

$ SDL_VIDEODRIVER=wayland ./checkkeys
INFO: Initial state: modifiers: (none)
INFO: EDIT Text (): ""
INFO: EDIT Text (\xc2\xb7): "·"
INFO: EDIT Text (\x61): "a"
INFO: EDIT Text (): ""
INFO: INPUT Text (\xc3\xa5): "å"
INFO: EDIT Text (): ""
$ ./checkkeys
INFO: Initial state: modifiers: (none)
INFO: EDIT Text (): ""
INFO: Key pressed :  scancode 228 = Right Ctrl, keycode 0x40000000 =   modifiers: (none)
INFO: Key released:  scancode 228 = Right Ctrl, keycode 0x40000000 =   modifiers: (none)
INFO: Key pressed :  scancode 4 = A, keycode 0x00000061 = A  modifiers: (none)
INFO: Key released:  scancode 4 = A, keycode 0x00000061 = A  modifiers: (none)
INFO: Key pressed :  scancode 4 = A, keycode 0x00000061 = A  modifiers: (none)
INFO: INPUT Text (\xc3\xa5): "å"
INFO: Key released:  scancode 4 = A, keycode 0x00000061 = A  modifiers: (none)

EDIT2: And this is the output with the code highlighted in the initial post removed:

$ ./checkkeys
INFO: Initial state: modifiers: (none)
INFO: EDIT Text (): ""
INFO: EDIT Text (\xc2\xb7): "·"
INFO: EDIT Text (\x61): "a"
INFO: INPUT Text (\xc3\xa5): "å"
INFO: EDIT Text (): ""
slouken commented 1 month ago

Thanks for the great repro steps and explanation. It's interesting that you don't get key press/release events under Wayland or in the case where it works for you. These are intended to happen in addition to the IME composition.

I'll see if I can repro here.

slouken commented 1 month ago

I can repro the issue, but I am not seeing the fixed behavior if I comment out the return after the filter events call. Do you have a patch that fixes this for you?

Kontrabant commented 1 month ago

Thanks for the great repro steps and explanation. It's interesting that you don't get key press/release events under Wayland or in the case where it works for you. These are intended to happen in addition to the IME composition.

On Wayland, Gnome doesn't send key down events for keys that are part of a compose sequence when text input is active. SDL isn't dropping or ignoring them, they are just never sent.

slouken commented 1 month ago

Oh, that makes sense. I was thinking about when text input is enabled, but we shouldn't get keys that are actively part of composition.

Guldoman commented 1 month ago

Do you have a patch that fixes this for you?

Just a very brutal, likely incorrect, deletion:

diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 21b66ff77..7f56a531f 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -816,31 +816,6 @@ static void X11_DispatchEvent(_THIS, XEvent *xevent)
         orig_keycode = 0;
     }

-    /* filter events catchs XIM events and sends them to the correct handler */
-    if (X11_XFilterEvent(xevent, None) == True) {
-#if 0
-        printf("Filtered event type = %d display = %d window = %d\n",
-               xevent->type, xevent->xany.display, xevent->xany.window);
-#endif
-        /* Make sure dead key press/release events are sent */
-        /* But only if we're using one of the DBus IMEs, otherwise
-           some XIM IMEs will generate duplicate events */
-        if (orig_keycode) {
-#if defined(HAVE_IBUS_IBUS_H) || defined(HAVE_FCITX)
-            SDL_Scancode scancode = videodata->key_layout[orig_keycode];
-            videodata->filter_code = orig_keycode;
-            videodata->filter_time = xevent->xkey.time;
-
-            if (orig_event_type == KeyPress) {
-                SDL_SendKeyboardKey(SDL_PRESSED, scancode);
-            } else {
-                SDL_SendKeyboardKey(SDL_RELEASED, scancode);
-            }
-#endif
-        }
-        return;
-    }
-
 #ifdef SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
     if (xevent->type == GenericEvent) {
         X11_HandleGenericEvent(videodata, xevent);
slouken commented 1 month ago

Interesting. It sounds like there are two different IMEs in play here. One which is in the X server, which doesn't provide composition events, and one which is D-Bus based, which does.