From 72fc6f86e5d605a3787222bc7dc18c5379047f4a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 23 Mar 2024 09:21:28 -0700 Subject: [PATCH] Text input is no longer automatically enabled when initializing video. Fixes https://github.com/libsdl-org/SDL/issues/9309 Fixes https://github.com/libsdl-org/SDL/issues/9268 --- docs/README-migration.md | 2 + include/SDL3/SDL_hints.h | 5 +- src/core/haiku/SDL_BApp.h | 2 +- src/events/SDL_events.c | 8 --- src/events/SDL_keyboard.c | 10 ++-- src/video/SDL_sysvideo.h | 1 + src/video/SDL_video.c | 59 ++++++++------------- src/video/cocoa/SDL_cocoakeyboard.m | 2 +- src/video/emscripten/SDL_emscriptenevents.c | 2 +- src/video/wayland/SDL_waylandevents.c | 4 +- src/video/x11/SDL_x11events.c | 8 +-- 11 files changed, 41 insertions(+), 62 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 394c29c1c..145ac536e 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -855,6 +855,8 @@ The following symbols have been removed: ## SDL_keyboard.h +Text input is no longer automatically enabled when initializing video, you should call SDL_StartTextInput() when you want to receive text input and call SDL_StopTextInput() when you are done. Starting text input may shown an input method editor (IME) and cause key up/down events to be skipped, so should only be enabled when the application wants text input. + The following functions have been renamed: * SDL_IsScreenKeyboardShown() => SDL_ScreenKeyboardShown() * SDL_IsTextInputActive() => SDL_TextInputActive() diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index a1ae55d4d..2939d75e7 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -439,10 +439,11 @@ extern "C" { * A variable that controls whether the on-screen keyboard should be shown when text input is active * * The variable can be set to the following values: + * "auto" - The on-screen keyboard will be shown if there is no physical keyboard attached. (default) * "0" - Do not show the on-screen keyboard. - * "1" - Show the on-screen keyboard. (default) + * "1" - Show the on-screen keyboard, if available. * - * This hint must be set before text input is activated. + * This hint must be set before SDL_StartTextInput() is called */ #define SDL_HINT_ENABLE_SCREEN_KEYBOARD "SDL_ENABLE_SCREEN_KEYBOARD" diff --git a/src/core/haiku/SDL_BApp.h b/src/core/haiku/SDL_BApp.h index 484b0f3c8..66d88d1dd 100644 --- a/src/core/haiku/SDL_BApp.h +++ b/src/core/haiku/SDL_BApp.h @@ -306,7 +306,7 @@ class SDL_BLooper : public BLooper HAIKU_SetKeyState(scancode, state); SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, state, HAIKU_GetScancodeFromBeKey(scancode)); - if (state == SDL_PRESSED && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (state == SDL_PRESSED && SDL_TextInputActive()) { const int8 *keyUtf8; ssize_t count; if (msg->FindData("key-utf8", B_INT8_TYPE, (const void **)&keyUtf8, &count) == B_OK) { diff --git a/src/events/SDL_events.c b/src/events/SDL_events.c index d1b277641..968f53c5d 100644 --- a/src/events/SDL_events.c +++ b/src/events/SDL_events.c @@ -729,14 +729,6 @@ int SDL_StartEventLoop(void) } #endif /* !SDL_THREADS_DISABLED */ - /* Process most event types */ - SDL_SetEventEnabled(SDL_EVENT_TEXT_INPUT, SDL_FALSE); - SDL_SetEventEnabled(SDL_EVENT_TEXT_EDITING, SDL_FALSE); -#if 0 /* Leave these events enabled so apps can respond to items being dragged onto them at startup */ - SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, SDL_FALSE); - SDL_SetEventEnabled(SDL_EVENT_DROP_TEXT, SDL_FALSE); -#endif - SDL_EventQ.active = SDL_TRUE; SDL_UnlockMutex(SDL_EventQ.lock); return 0; diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index 3ef19e650..871d45a73 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -912,11 +912,10 @@ int SDL_SetKeyboardFocus(SDL_Window *window) SDL_assert(!(keyboard->focus->flags & SDL_WINDOW_MOUSE_CAPTURE)); } - SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_LOST, - 0, 0); + SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_LOST, 0, 0); /* Ensures IME compositions are committed */ - if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (SDL_TextInputActive()) { if (video && video->StopTextInput) { video->StopTextInput(video); } @@ -926,10 +925,9 @@ int SDL_SetKeyboardFocus(SDL_Window *window) keyboard->focus = window; if (keyboard->focus) { - SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_GAINED, - 0, 0); + SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_GAINED, 0, 0); - if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (SDL_TextInputActive()) { if (video && video->StartTextInput) { video->StartTextInput(video); } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index f96b42837..61e1c8cea 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -365,6 +365,7 @@ struct SDL_VideoDevice SDL_bool setting_display_mode; Uint32 device_caps; SDL_SystemTheme system_theme; + SDL_bool text_input_active; /* * * */ /* Data used by the GL drivers */ diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index eff8e398e..d3c336990 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -562,22 +562,6 @@ int SDL_VideoInit(const char *driver_name) SDL_DisableScreenSaver(); } -#if !defined(SDL_VIDEO_DRIVER_N3DS) - { - /* In the initial state we don't want to pop up an on-screen keyboard, - * but we do want to allow text input from other mechanisms. - */ - const char *hint = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD); - if (!hint) { - SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, "0"); - } - SDL_StartTextInput(); - if (!hint) { - SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, NULL); - } - } -#endif /* !SDL_VIDEO_DRIVER_N3DS */ - SDL_PostInitMouse(); /* We're ready to go! */ @@ -4808,24 +4792,25 @@ void SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask) void SDL_StartTextInput(void) { - SDL_Window *window; + if (!_this) { + return; + } - /* First, enable text events */ - SDL_SetEventEnabled(SDL_EVENT_TEXT_INPUT, SDL_TRUE); - SDL_SetEventEnabled(SDL_EVENT_TEXT_EDITING, SDL_TRUE); - - /* Then show the on-screen keyboard, if any */ - if (SDL_GetHintBoolean(SDL_HINT_ENABLE_SCREEN_KEYBOARD, SDL_TRUE)) { - window = SDL_GetKeyboardFocus(); - if (window && _this && _this->ShowScreenKeyboard) { + /* Show the on-screen keyboard, if desired */ + const char *hint = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD); + if (((!hint || SDL_strcasecmp(hint, "auto")) && !SDL_HasKeyboard()) || + SDL_GetStringBoolean(hint, SDL_FALSE)) { + SDL_Window *window = SDL_GetKeyboardFocus(); + if (window && _this->ShowScreenKeyboard) { _this->ShowScreenKeyboard(_this, window); } } /* Finally start the text input system */ - if (_this && _this->StartTextInput) { + if (_this->StartTextInput) { _this->StartTextInput(_this); } + _this->text_input_active = SDL_TRUE; } void SDL_ClearComposition(void) @@ -4846,29 +4831,29 @@ SDL_bool SDL_TextInputShown(void) SDL_bool SDL_TextInputActive(void) { - return SDL_EventEnabled(SDL_EVENT_TEXT_INPUT); + return _this && _this->text_input_active; } void SDL_StopTextInput(void) { - SDL_Window *window; + if (!_this) { + return; + } /* Stop the text input system */ - if (_this && _this->StopTextInput) { + if (_this->StopTextInput) { _this->StopTextInput(_this); } - /* Hide the on-screen keyboard, if any */ - if (SDL_GetHintBoolean(SDL_HINT_ENABLE_SCREEN_KEYBOARD, SDL_TRUE)) { - window = SDL_GetKeyboardFocus(); - if (window && _this && _this->HideScreenKeyboard) { + /* Hide the on-screen keyboard, if desired */ + const char *hint = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD); + if (((!hint || SDL_strcasecmp(hint, "auto")) && !SDL_HasKeyboard()) || + SDL_GetStringBoolean(hint, SDL_FALSE)) { + SDL_Window *window = SDL_GetKeyboardFocus(); + if (window && _this->HideScreenKeyboard) { _this->HideScreenKeyboard(_this, window); } } - - /* Finally disable text events */ - SDL_SetEventEnabled(SDL_EVENT_TEXT_INPUT, SDL_FALSE); - SDL_SetEventEnabled(SDL_EVENT_TEXT_EDITING, SDL_FALSE); } int SDL_SetTextInputRect(const SDL_Rect *rect) diff --git a/src/video/cocoa/SDL_cocoakeyboard.m b/src/video/cocoa/SDL_cocoakeyboard.m index fc12196c8..61866a413 100644 --- a/src/video/cocoa/SDL_cocoakeyboard.m +++ b/src/video/cocoa/SDL_cocoakeyboard.m @@ -420,7 +420,7 @@ void Cocoa_HandleKeyEvent(SDL_VideoDevice *_this, NSEvent *event) SDL_Log("The key you just pressed is not recognized by SDL. To help get this fixed, report this to the SDL forums/mailing list or to Christian Walther . Mac virtual key code is %d.\n", scancode); } #endif - if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (SDL_TextInputActive()) { /* FIXME CW 2007-08-16: only send those events to the field editor for which we actually want text events, not e.g. esc or function keys. Arrow keys in particular seem to produce crashes sometimes. */ [data.fieldEdit interpretKeyEvents:[NSArray arrayWithObject:event]]; #if 0 diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index 7bf4e76ca..c67a8f3c5 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -828,7 +828,7 @@ static EM_BOOL Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent is_nav_key = SDL_TRUE; } - if ((eventType == EMSCRIPTEN_EVENT_KEYDOWN) && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT) && !is_nav_key) { + if ((eventType == EMSCRIPTEN_EVENT_KEYDOWN) && SDL_TextInputActive() && !is_nav_key) { prevent_default = SDL_FALSE; } diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 1d72eaeb4..75fbbc3eb 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -377,7 +377,7 @@ int Wayland_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS) WAYLAND_wl_display_flush(d->display); #ifdef SDL_USE_IME - if (!d->text_input_manager && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (!d->text_input_manager && SDL_TextInputActive()) { SDL_IME_PumpEvents(); } #endif @@ -450,7 +450,7 @@ void Wayland_PumpEvents(SDL_VideoDevice *_this) int err; #ifdef SDL_USE_IME - if (!d->text_input_manager && SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (!d->text_input_manager && SDL_TextInputActive()) { SDL_IME_PumpEvents(); } #endif diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index c170a59f5..72ad194c6 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -1254,7 +1254,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) #endif #ifdef SDL_USE_IME - if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (SDL_TextInputActive()) { handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode, (xevent->type == KeyPress ? SDL_PRESSED : SDL_RELEASED)); } #endif @@ -1355,7 +1355,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent) SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y); #ifdef SDL_USE_IME - if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (SDL_TextInputActive()) { /* Update IME candidate list position */ SDL_IME_UpdateTextRect(NULL); } @@ -1937,7 +1937,7 @@ int X11_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS) X11_DispatchEvent(_this, &xevent); #ifdef SDL_USE_IME - if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (SDL_TextInputActive()) { SDL_IME_PumpEvents(); } #endif @@ -1998,7 +1998,7 @@ void X11_PumpEvents(SDL_VideoDevice *_this) } #ifdef SDL_USE_IME - if (SDL_EventEnabled(SDL_EVENT_TEXT_INPUT)) { + if (SDL_TextInputActive()) { SDL_IME_PumpEvents(); } #endif