From fa236f169baa1faa2a8dad4ce4e0b2d11cc589f5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 25 Mar 2024 12:49:09 -0700 Subject: [PATCH] Only do work to process text events if text input is active Fixes https://github.com/libsdl-org/SDL/issues/9353 --- src/events/SDL_keyboard.c | 8 +++ src/video/emscripten/SDL_emscriptenevents.c | 11 +-- src/video/wayland/SDL_waylandevents.c | 4 +- src/video/windows/SDL_windowsevents.c | 43 ++++++----- src/video/winrt/SDL_winrtkeyboard.cpp | 38 +++++----- src/video/x11/SDL_x11events.c | 80 +++++++++++---------- 6 files changed, 105 insertions(+), 79 deletions(-) diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 871d45a73..2f1ea4f1d 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -1180,6 +1180,10 @@ int SDL_SendKeyboardText(const char *text) SDL_Keyboard *keyboard = &SDL_keyboard; int posted; + if (!SDL_TextInputActive()) { + return 0; + } + /* Don't post text events for unprintable characters */ if (SDL_iscntrl((unsigned char)*text)) { return 0; @@ -1210,6 +1214,10 @@ int SDL_SendEditingText(const char *text, int start, int length) SDL_Keyboard *keyboard = &SDL_keyboard; int posted; + if (!SDL_TextInputActive()) { + return 0; + } + /* Post the event, if desired */ posted = 0; if (SDL_EventEnabled(SDL_EVENT_TEXT_EDITING)) { diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index c67a8f3c5..5eef44851 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -837,11 +837,14 @@ static EM_BOOL Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent static EM_BOOL Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) { - char text[5]; - if (Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text)) { - SDL_SendKeyboardText(text); + if (SDL_TextInputActive()) { + char text[5]; + if (Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text)) { + SDL_SendKeyboardText(text); + } + return EM_TRUE; } - return SDL_EventEnabled(SDL_EVENT_TEXT_INPUT); + return EM_FALSE; } static EM_BOOL Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData) diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 3b284f5ef..c73197bd8 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -1605,7 +1605,9 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, Wayland_UpdateImplicitGrabSerial(input, serial); if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime); + if (SDL_TextInputActive()) { + has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime); + } } else { if (keyboard_repeat_key_is_set(&input->keyboard_repeat, key)) { /* Send any due key repeat events before stopping the repeat and generating the key up event. diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 96dfcb07c..b7c8af674 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1164,33 +1164,40 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara if (wParam == UNICODE_NOCHAR) { returnCode = 1; } else { - char text[5]; - if (SDL_UCS4ToUTF8((Uint32)wParam, text) != text) { - SDL_SendKeyboardText(text); + if (SDL_TextInputActive()) { + char text[5]; + if (SDL_UCS4ToUTF8((Uint32)wParam, text) != text) { + SDL_SendKeyboardText(text); + } } returnCode = 0; } break; case WM_CHAR: - /* Characters outside Unicode Basic Multilingual Plane (BMP) - * are coded as so called "surrogate pair" in two separate UTF-16 character events. - * Cache high surrogate until next character event. */ - if (IS_HIGH_SURROGATE(wParam)) { - data->high_surrogate = (WCHAR)wParam; - } else { - WCHAR utf16[3]; + if (SDL_TextInputActive()) { + /* Characters outside Unicode Basic Multilingual Plane (BMP) + * are coded as so called "surrogate pair" in two separate UTF-16 character events. + * Cache high surrogate until next character event. */ + if (IS_HIGH_SURROGATE(wParam)) { + data->high_surrogate = (WCHAR)wParam; + } else { + if (SDL_TextInputActive()) { + WCHAR utf16[3]; - utf16[0] = data->high_surrogate ? data->high_surrogate : (WCHAR)wParam; - utf16[1] = data->high_surrogate ? (WCHAR)wParam : L'\0'; - utf16[2] = L'\0'; + utf16[0] = data->high_surrogate ? data->high_surrogate : (WCHAR)wParam; + utf16[1] = data->high_surrogate ? (WCHAR)wParam : L'\0'; + utf16[2] = L'\0'; - char utf8[5]; - int result = WIN_WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16, -1, utf8, sizeof(utf8), NULL, NULL); - if (result > 0) { - SDL_SendKeyboardText(utf8); + char utf8[5]; + int result = WIN_WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16, -1, utf8, sizeof(utf8), NULL, NULL); + if (result > 0) { + SDL_SendKeyboardText(utf8); + } + } + data->high_surrogate = L'\0'; } - + } else { data->high_surrogate = L'\0'; } diff --git a/src/video/winrt/SDL_winrtkeyboard.cpp b/src/video/winrt/SDL_winrtkeyboard.cpp index 6f088ec17..28013413a 100644 --- a/src/video/winrt/SDL_winrtkeyboard.cpp +++ b/src/video/winrt/SDL_winrtkeyboard.cpp @@ -88,25 +88,29 @@ void WINRT_ProcessCharacterReceivedEvent(SDL_Window *window, Windows::UI::Core:: SDL_WindowData *data = window->driverdata; - /* Characters outside Unicode Basic Multilingual Plane (BMP) - * are coded as so called "surrogate pair" in two separate UTF-16 character events. - * Cache high surrogate until next character event. */ - if (IS_HIGH_SURROGATE(args->KeyCode)) { - data->high_surrogate = (WCHAR)args->KeyCode; - } else { - WCHAR utf16[] = { - data->high_surrogate ? data->high_surrogate : (WCHAR)args->KeyCode, - data->high_surrogate ? (WCHAR)args->KeyCode : L'\0', - L'\0' - }; + if (SDL_TextInputActive()) { + /* Characters outside Unicode Basic Multilingual Plane (BMP) + * are coded as so called "surrogate pair" in two separate UTF-16 character events. + * Cache high surrogate until next character event. */ + if (IS_HIGH_SURROGATE(args->KeyCode)) { + data->high_surrogate = (WCHAR)args->KeyCode; + } else { + WCHAR utf16[] = { + data->high_surrogate ? data->high_surrogate : (WCHAR)args->KeyCode, + data->high_surrogate ? (WCHAR)args->KeyCode : L'\0', + L'\0' + }; - char utf8[5]; - // doesn't need to be WIN_WideCharToMultiByte, since we don't care about WinXP support in WinRT. - int result = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16, -1, utf8, sizeof(utf8), NULL, NULL); - if (result > 0) { - SDL_SendKeyboardText(utf8); + char utf8[5]; + // doesn't need to be WIN_WideCharToMultiByte, since we don't care about WinXP support in WinRT. + int result = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, utf16, -1, utf8, sizeof(utf8), NULL, NULL); + if (result > 0) { + SDL_SendKeyboardText(utf8); + } + + data->high_surrogate = L'\0'; } - + } else { data->high_surrogate = L'\0'; } } diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 6d568a90d..2d24a2d9e 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -842,35 +842,6 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_ Status status = 0; SDL_bool handled_by_ime = SDL_FALSE; - /* Save the original keycode for dead keys, which are filtered out by - the XFilterEvent() call below. - */ - int orig_event_type = xevent->type; - KeyCode orig_keycode = xevent->xkey.keycode; - - /* filter events catches XIM events and sends them to the correct handler */ - if (X11_XFilterEvent(xevent, None)) { -#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 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(0, keyboardID, SDL_PRESSED, scancode); - } else { - SDL_SendKeyboardKey(0, keyboardID, SDL_RELEASED, scancode); - } -#endif - return; - } - #ifdef DEBUG_XEVENTS printf("window %p: %s (X11 keycode = 0x%X)\n", data, (xevent->type == KeyPress ? "KeyPress" : "KeyRelease"), xevent->xkey.keycode); #endif @@ -885,23 +856,54 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_ } #endif /* DEBUG SCANCODES */ - SDL_zeroa(text); + text[0] = '\0'; + + if (SDL_TextInputActive()) { + /* Save the original keycode for dead keys, which are filtered out by + the XFilterEvent() call below. + */ + int orig_event_type = xevent->type; + KeyCode orig_keycode = xevent->xkey.keycode; + + /* filter events catches XIM events and sends them to the correct handler */ + if (X11_XFilterEvent(xevent, None)) { +#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 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(0, keyboardID, SDL_PRESSED, scancode); + } else { + SDL_SendKeyboardKey(0, keyboardID, SDL_RELEASED, scancode); + } +#endif + return; + } + #ifdef X_HAVE_UTF8_STRING - if (windowdata->ic && xevent->type == KeyPress) { - X11_Xutf8LookupString(windowdata->ic, &xevent->xkey, text, sizeof(text), - &keysym, &status); - } else { - XLookupStringAsUTF8(&xevent->xkey, text, sizeof(text), &keysym, NULL); - } + if (windowdata->ic && xevent->type == KeyPress) { + X11_Xutf8LookupString(windowdata->ic, &xevent->xkey, text, sizeof(text), + &keysym, &status); + } else { + XLookupStringAsUTF8(&xevent->xkey, text, sizeof(text), &keysym, NULL); + } #else - XLookupStringAsUTF8(&xevent->xkey, text, sizeof(text), &keysym, NULL); + XLookupStringAsUTF8(&xevent->xkey, text, sizeof(text), &keysym, NULL); #endif #ifdef SDL_USE_IME - if (SDL_TextInputActive()) { handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode, (xevent->type == KeyPress ? SDL_PRESSED : SDL_RELEASED)); - } #endif + } + 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 */