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

Co-authored-by: Ethan Lee <flibitijibibo@gmail.com>
This commit is contained in:
Weng Xuetian 2022-04-05 19:30:25 -07:00 committed by GitHub
parent 8bae343f25
commit 138d96c8a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 46 additions and 41 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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)) {

View File

@ -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. */

View File

@ -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;
} }

View File

@ -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);

View File

@ -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)) {

View File

@ -996,8 +996,9 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
} }
break; break;
/* Key press? */ /* Key press/release? */
case KeyPress:{ 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,10 +1034,11 @@ 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) {
if (xevent->type == KeyPress) {
/* Don't send the key if it looks like a duplicate of a filtered key sent by an 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) { if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) {
SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]); SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]);
@ -1044,25 +1046,19 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
if(*text) { if(*text) {
SDL_SendKeyboardText(text); SDL_SendKeyboardText(text);
} }
} } else {
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)) { if (X11_KeyRepeat(display, xevent)) {
/* We're about to get a repeated key down, ignore the key up */ /* We're about to get a repeated key down, ignore the key up */
break; break;
} }
SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]); SDL_SendKeyboardKey(SDL_RELEASED, videodata->key_layout[keycode]);
} }
}
if (xevent->type == KeyPress) {
X11_UpdateUserTime(data, xevent->xkey.time);
}
}
break; break;
/* Have we been iconified? */ /* Have we been iconified? */