Send key release event to input method. (#5281) Co-authored-by: Ethan Lee <flibitijibibo@gmail.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c
index 3f07947..bab5e88 100644
--- a/src/core/linux/SDL_fcitx.c
+++ b/src/core/linux/SDL_fcitx.c
@@ -339,11 +339,11 @@ SDL_Fcitx_Reset(void)
}
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 is_release = SDL_FALSE;
+ Uint32 is_release = (state == SDL_RELEASED);
Uint32 event_time = 0;
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",
- 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)) {
if (handled) {
SDL_Fcitx_UpdateTextRect(NULL);
diff --git a/src/core/linux/SDL_fcitx.h b/src/core/linux/SDL_fcitx.h
index f7884ea..c3cea52 100644
--- a/src/core/linux/SDL_fcitx.h
+++ b/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_SetFocus(SDL_bool focused);
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_PumpEvents(void);
diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c
index 20236e7..60af0ba 100644
--- a/src/core/linux/SDL_ibus.c
+++ b/src/core/linux/SDL_ibus.c
@@ -503,14 +503,18 @@ SDL_IBus_Reset(void)
}
SDL_bool
-SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
{
Uint32 result = 0;
SDL_DBusContext *dbus = SDL_DBus_GetContext();
-
+
+
if (IBus_CheckConnection(dbus)) {
Uint32 mods = IBus_ModState();
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",
DBUS_TYPE_UINT32, &keysym, DBUS_TYPE_UINT32, &ibus_keycode, DBUS_TYPE_UINT32, &mods, DBUS_TYPE_INVALID,
DBUS_TYPE_BOOLEAN, &result, DBUS_TYPE_INVALID)) {
diff --git a/src/core/linux/SDL_ibus.h b/src/core/linux/SDL_ibus.h
index 73a9f1b..71d1f2d 100644
--- a/src/core/linux/SDL_ibus.h
+++ b/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
update its candidate list or change input methods. PumpEvents should be
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
just reposition it relative to the focused window's new position. */
diff --git a/src/core/linux/SDL_ime.c b/src/core/linux/SDL_ime.c
index 84c461f..9c0cb80 100644
--- a/src/core/linux/SDL_ime.c
+++ b/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_SetFocus)(SDL_bool);
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_PumpEvents)(void);
@@ -127,10 +127,10 @@ SDL_IME_Reset(void)
}
SDL_bool
-SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
{
if (SDL_IME_ProcessKeyEvent_Real)
- return SDL_IME_ProcessKeyEvent_Real(keysym, keycode);
+ return SDL_IME_ProcessKeyEvent_Real(keysym, keycode, state);
return SDL_FALSE;
}
diff --git a/src/core/linux/SDL_ime.h b/src/core/linux/SDL_ime.h
index a28a4b4..cc5b105 100644
--- a/src/core/linux/SDL_ime.h
+++ b/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_SetFocus(SDL_bool focused);
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_PumpEvents(void);
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index f4d6ade..b81c9db 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -921,7 +921,7 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
}
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;
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];
#ifdef SDL_USE_IME
- if (SDL_IME_ProcessKeyEvent(sym, key + 8)) {
+ if (SDL_IME_ProcessKeyEvent(sym, key + 8, state)) {
*handled_by_ime = SDL_TRUE;
return SDL_TRUE;
}
#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) {
switch(WAYLAND_xkb_compose_state_get_status(input->xkb.compose_state)) {
case XKB_COMPOSE_COMPOSING:
@@ -977,7 +981,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
SDL_bool handled_by_ime = SDL_FALSE;
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 {
if (keyboard_repeat_is_set(&input->keyboard_repeat)) {
// 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_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)) {
diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 186f37b..31e739c 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -996,8 +996,9 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
}
break;
- /* Key press? */
- case KeyPress:{
+ /* Key press/release? */
+ case KeyPress:
+ case KeyRelease: {
KeyCode keycode = xevent->xkey.keycode;
KeySym keysym = NoSymbol;
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
@@ -1005,7 +1006,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
SDL_bool handled_by_ime = SDL_FALSE;
#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
#if 1
if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
@@ -1021,7 +1022,7 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
/* */
SDL_zeroa(text);
#ifdef X_HAVE_UTF8_STRING
- if (data->ic) {
+ if (data->ic && xevent->type == KeyPress) {
X11_Xutf8LookupString(data->ic, &xevent->xkey, text, sizeof(text),
&keysym, &status);
} else {
@@ -1033,35 +1034,30 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
#ifdef SDL_USE_IME
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
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;