Browse Source

Send key release event to input method. (#5281)

Co-authored-by: Ethan Lee <[email protected]>
Weng Xuetian 3 years ago
parent
commit
138d96c8a6

+ 4 - 4
src/core/linux/SDL_fcitx.c

@@ -339,11 +339,11 @@ SDL_Fcitx_Reset(void)
 }
 }
 
 
 SDL_bool
 SDL_bool
-SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
 {
 {
-    Uint32 state = Fcitx_ModState();
+    Uint32 mod_state = Fcitx_ModState();
     Uint32 handled = SDL_FALSE;
     Uint32 handled = SDL_FALSE;
-    Uint32 is_release = SDL_FALSE;
+    Uint32 is_release = (state == SDL_RELEASED);
     Uint32 event_time = 0;
     Uint32 event_time = 0;
 
 
     if (!fcitx_client.ic_path) {
     if (!fcitx_client.ic_path) {
@@ -351,7 +351,7 @@ SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
     }
     }
 
 
     if (SDL_DBus_CallMethod(FCITX_DBUS_SERVICE, fcitx_client.ic_path, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
     if (SDL_DBus_CallMethod(FCITX_DBUS_SERVICE, fcitx_client.ic_path, FCITX_IC_DBUS_INTERFACE, "ProcessKeyEvent",
-            DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &state, DBUS_TYPE_BOOLEAN, &is_release, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
+            DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &keycode, DBUS_TYPE_UINT32, &mod_state, DBUS_TYPE_BOOLEAN, &is_release, DBUS_TYPE_UINT32, &event_time, DBUS_TYPE_INVALID,
             DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID)) {
             DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID)) {
         if (handled) {
         if (handled) {
             SDL_Fcitx_UpdateTextRect(NULL);
             SDL_Fcitx_UpdateTextRect(NULL);

+ 1 - 1
src/core/linux/SDL_fcitx.h

@@ -31,7 +31,7 @@ extern SDL_bool SDL_Fcitx_Init(void);
 extern void SDL_Fcitx_Quit(void);
 extern void SDL_Fcitx_Quit(void);
 extern void SDL_Fcitx_SetFocus(SDL_bool focused);
 extern void SDL_Fcitx_SetFocus(SDL_bool focused);
 extern void SDL_Fcitx_Reset(void);
 extern void SDL_Fcitx_Reset(void);
-extern SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
+extern SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
 extern void SDL_Fcitx_UpdateTextRect(SDL_Rect *rect);
 extern void SDL_Fcitx_UpdateTextRect(SDL_Rect *rect);
 extern void SDL_Fcitx_PumpEvents(void);
 extern void SDL_Fcitx_PumpEvents(void);
 
 

+ 6 - 2
src/core/linux/SDL_ibus.c

@@ -503,14 +503,18 @@ SDL_IBus_Reset(void)
 }
 }
 
 
 SDL_bool
 SDL_bool
-SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
 { 
 { 
     Uint32 result = 0;
     Uint32 result = 0;
     SDL_DBusContext *dbus = SDL_DBus_GetContext();
     SDL_DBusContext *dbus = SDL_DBus_GetContext();
-    
+
+
     if (IBus_CheckConnection(dbus)) {
     if (IBus_CheckConnection(dbus)) {
         Uint32 mods = IBus_ModState();
         Uint32 mods = IBus_ModState();
         Uint32 ibus_keycode = keycode - 8;
         Uint32 ibus_keycode = keycode - 8;
+        if (state == SDL_RELEASED) {
+            mods |= (1 << 30); // IBUS_RELEASE_MASK
+        }
         if (!SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
         if (!SDL_DBus_CallMethodOnConnection(ibus_conn, IBUS_SERVICE, input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
                 DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &ibus_keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
                 DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &ibus_keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
                 DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) {
                 DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) {

+ 1 - 1
src/core/linux/SDL_ibus.h

@@ -41,7 +41,7 @@ extern void SDL_IBus_Reset(void);
 /* Sends a keypress event to IBus, returns SDL_TRUE if IBus used this event to
 /* Sends a keypress event to IBus, returns SDL_TRUE if IBus used this event to
    update its candidate list or change input methods. PumpEvents should be
    update its candidate list or change input methods. PumpEvents should be
    called some time after this, to recieve the TextInput / TextEditing event back. */
    called some time after this, to recieve the TextInput / TextEditing event back. */
-extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
+extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
 
 
 /* Update the position of IBus' candidate list. If rect is NULL then this will 
 /* Update the position of IBus' candidate list. If rect is NULL then this will 
    just reposition it relative to the focused window's new position. */
    just reposition it relative to the focused window's new position. */

+ 3 - 3
src/core/linux/SDL_ime.c

@@ -27,7 +27,7 @@ typedef SDL_bool (*_SDL_IME_Init)(void);
 typedef void (*_SDL_IME_Quit)(void);
 typedef void (*_SDL_IME_Quit)(void);
 typedef void (*_SDL_IME_SetFocus)(SDL_bool);
 typedef void (*_SDL_IME_SetFocus)(SDL_bool);
 typedef void (*_SDL_IME_Reset)(void);
 typedef void (*_SDL_IME_Reset)(void);
-typedef SDL_bool (*_SDL_IME_ProcessKeyEvent)(Uint32, Uint32);
+typedef SDL_bool (*_SDL_IME_ProcessKeyEvent)(Uint32, Uint32, Uint8 state);
 typedef void (*_SDL_IME_UpdateTextRect)(SDL_Rect *);
 typedef void (*_SDL_IME_UpdateTextRect)(SDL_Rect *);
 typedef void (*_SDL_IME_PumpEvents)(void);
 typedef void (*_SDL_IME_PumpEvents)(void);
 
 
@@ -127,10 +127,10 @@ SDL_IME_Reset(void)
 }
 }
 
 
 SDL_bool
 SDL_bool
-SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
 {
 {
     if (SDL_IME_ProcessKeyEvent_Real)
     if (SDL_IME_ProcessKeyEvent_Real)
-        return SDL_IME_ProcessKeyEvent_Real(keysym, keycode);
+        return SDL_IME_ProcessKeyEvent_Real(keysym, keycode, state);
 
 
     return SDL_FALSE;
     return SDL_FALSE;
 }
 }

+ 1 - 1
src/core/linux/SDL_ime.h

@@ -31,7 +31,7 @@ extern SDL_bool SDL_IME_Init(void);
 extern void SDL_IME_Quit(void);
 extern void SDL_IME_Quit(void);
 extern void SDL_IME_SetFocus(SDL_bool focused);
 extern void SDL_IME_SetFocus(SDL_bool focused);
 extern void SDL_IME_Reset(void);
 extern void SDL_IME_Reset(void);
-extern SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
+extern SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state);
 extern void SDL_IME_UpdateTextRect(SDL_Rect *rect);
 extern void SDL_IME_UpdateTextRect(SDL_Rect *rect);
 extern void SDL_IME_PumpEvents(void);
 extern void SDL_IME_PumpEvents(void);
 
 

+ 8 - 3
src/video/wayland/SDL_waylandevents.c

@@ -921,7 +921,7 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
 }
 }
 
 
 static SDL_bool
 static SDL_bool
-keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, SDL_bool *handled_by_ime)
+keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint32_t key, Uint8 state, SDL_bool *handled_by_ime)
 {
 {
     SDL_WindowData *window = input->keyboard_focus;
     SDL_WindowData *window = input->keyboard_focus;
     const xkb_keysym_t *syms;
     const xkb_keysym_t *syms;
@@ -938,12 +938,16 @@ keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint
     sym = syms[0];
     sym = syms[0];
 
 
 #ifdef SDL_USE_IME
 #ifdef SDL_USE_IME
-    if (SDL_IME_ProcessKeyEvent(sym, key + 8)) {
+    if (SDL_IME_ProcessKeyEvent(sym, key + 8, state)) {
         *handled_by_ime = SDL_TRUE;
         *handled_by_ime = SDL_TRUE;
         return SDL_TRUE;
         return SDL_TRUE;
     }
     }
 #endif
 #endif
 
 
+    if (state == SDL_RELEASED) {
+        return SDL_FALSE;
+    }
+
     if (input->xkb.compose_state && WAYLAND_xkb_compose_state_feed(input->xkb.compose_state, sym) == XKB_COMPOSE_FEED_ACCEPTED) {
     if (input->xkb.compose_state && WAYLAND_xkb_compose_state_feed(input->xkb.compose_state, sym) == XKB_COMPOSE_FEED_ACCEPTED) {
         switch(WAYLAND_xkb_compose_state_get_status(input->xkb.compose_state)) {
         switch(WAYLAND_xkb_compose_state_get_status(input->xkb.compose_state)) {
             case XKB_COMPOSE_COMPOSING:
             case XKB_COMPOSE_COMPOSING:
@@ -977,7 +981,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
     SDL_bool handled_by_ime = SDL_FALSE;
     SDL_bool handled_by_ime = SDL_FALSE;
 
 
     if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
     if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
-        has_text = keyboard_input_get_text(text, input, key, &handled_by_ime);
+        has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime);
     } else {
     } else {
         if (keyboard_repeat_is_set(&input->keyboard_repeat)) {
         if (keyboard_repeat_is_set(&input->keyboard_repeat)) {
             // Send any due key repeat events before stopping the repeat and generating the key up event
             // Send any due key repeat events before stopping the repeat and generating the key up event
@@ -987,6 +991,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
             keyboard_repeat_handle(&input->keyboard_repeat, time - input->keyboard_repeat.wl_press_time);
             keyboard_repeat_handle(&input->keyboard_repeat, time - input->keyboard_repeat.wl_press_time);
             keyboard_repeat_clear(&input->keyboard_repeat);
             keyboard_repeat_clear(&input->keyboard_repeat);
         }
         }
+        keyboard_input_get_text(text, input, key, SDL_RELEASED, &handled_by_ime);
     }
     }
 
 
     if (!handled_by_ime && key < SDL_arraysize(xfree86_scancode_table2)) {
     if (!handled_by_ime && key < SDL_arraysize(xfree86_scancode_table2)) {

+ 22 - 26
src/video/x11/SDL_x11events.c

@@ -996,8 +996,9 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
         }
         }
         break;
         break;
 
 
-        /* Key press? */
-    case KeyPress:{
+        /* Key press/release? */
+    case KeyPress:
+    case KeyRelease: {
             KeyCode keycode = xevent->xkey.keycode;
             KeyCode keycode = xevent->xkey.keycode;
             KeySym keysym = NoSymbol;
             KeySym keysym = NoSymbol;
             char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
             char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
@@ -1005,7 +1006,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
             SDL_bool handled_by_ime = SDL_FALSE;
             SDL_bool handled_by_ime = SDL_FALSE;
 
 
 #ifdef DEBUG_XEVENTS
 #ifdef DEBUG_XEVENTS
-            printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode);
+            printf("window %p: %s (X11 keycode = 0x%X)\n" data, (xevent->type == KeyPress ? "KeyPress" : "KeyRelease"),  xevent->xkey.keycode);
 #endif
 #endif
 #if 1
 #if 1
             if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
             if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
@@ -1021,7 +1022,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
             /* */
             /* */
             SDL_zeroa(text);
             SDL_zeroa(text);
 #ifdef X_HAVE_UTF8_STRING
 #ifdef X_HAVE_UTF8_STRING
-            if (data->ic) {
+            if (data->ic && xevent->type == KeyPress) {
                 X11_Xutf8LookupString(data->ic, &xevent->xkey, text, sizeof(text),
                 X11_Xutf8LookupString(data->ic, &xevent->xkey, text, sizeof(text),
                                   &keysym, &status);
                                   &keysym, &status);
             } else {
             } else {
@@ -1033,35 +1034,30 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
 
 
 #ifdef SDL_USE_IME
 #ifdef SDL_USE_IME
             if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
             if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
-                handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode);
+                handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode, (xevent->type == KeyPress ? SDL_PRESSED : SDL_RELEASED));
             }
             }
 #endif
 #endif
             if (!handled_by_ime) {
             if (!handled_by_ime) {
-                /* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
-                if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) {
-                    SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
-                }
-                if(*text) {
-                    SDL_SendKeyboardText(text);
+                if (xevent->type == KeyPress) {
+                    /* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */
+                    if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) {
+                        SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
+                    }
+                    if(*text) {
+                        SDL_SendKeyboardText(text);
+                    }
+                } else {
+                    if (X11_KeyRepeat(display, xevent)) {
+                        /* We're about to get a repeated key down, ignore the key up */
+                        break;
+                    }
+                    SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
                 }
                 }
             }
             }
 
 
-            X11_UpdateUserTime(data, xevent->xkey.time);
-        }
-        break;
-
-        /* Key release? */
-    case KeyRelease:{
-            KeyCode keycode = xevent->xkey.keycode;
-
-#ifdef DEBUG_XEVENTS
-            printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode);
-#endif
-            if (X11_KeyRepeat(display, xevent)) {
-                /* We're about to get a repeated key down, ignore the key up */
-                break;
+            if (xevent->type == KeyPress) {
+                X11_UpdateUserTime(data, xevent->xkey.time);
             }
             }
-            SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
         }
         }
         break;
         break;