From 76631a09787a7f43d2151b496e7e23d03de9f3d7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 22 Jun 2024 06:16:19 -0700 Subject: [PATCH] The text input state has been changed to be window-specific. SDL_StartTextInput(), SDL_StopTextInput(), SDL_TextInputActive(), SDL_ClearComposition(), and SDL_SetTextInputRect() all now take a window parameter. This change also fixes IME candidate positioning when SDL_SetTextInputRect() is called before SDL_StartTextInput(), as is recommended in the documentation. --- docs/README-migration.md | 2 + include/SDL3/SDL_keyboard.h | 42 ++++-- src/core/android/SDL_android.c | 4 +- src/core/haiku/SDL_BApp.h | 6 +- src/core/linux/SDL_fcitx.c | 22 ++- src/core/linux/SDL_fcitx.h | 2 +- src/core/linux/SDL_ibus.c | 30 ++--- src/core/linux/SDL_ibus.h | 2 +- src/core/linux/SDL_ime.c | 6 +- src/core/linux/SDL_ime.h | 2 +- src/dynapi/SDL_dynapi_procs.h | 10 +- src/events/SDL_keyboard.c | 12 +- src/video/SDL_sysvideo.h | 12 +- src/video/SDL_video.c | 73 +++++----- src/video/android/SDL_androidkeyboard.c | 10 +- src/video/android/SDL_androidkeyboard.h | 1 - src/video/android/SDL_androidvideo.c | 3 - src/video/android/SDL_androidvideo.h | 1 - src/video/cocoa/SDL_cocoakeyboard.h | 6 +- src/video/cocoa/SDL_cocoakeyboard.m | 25 ++-- src/video/cocoa/SDL_cocoavideo.m | 2 +- src/video/emscripten/SDL_emscriptenevents.c | 7 +- src/video/gdk/SDL_gdktextinput.cpp | 11 +- src/video/gdk/SDL_gdktextinput.h | 8 +- src/video/haiku/SDL_bvideo.cc | 14 -- src/video/n3ds/SDL_n3dsswkb.c | 7 +- src/video/n3ds/SDL_n3dsswkb.h | 4 +- src/video/uikit/SDL_uikitvideo.m | 2 +- src/video/uikit/SDL_uikitview.m | 8 +- src/video/uikit/SDL_uikitviewcontroller.h | 2 +- src/video/uikit/SDL_uikitviewcontroller.m | 16 +-- src/video/wayland/SDL_waylandevents.c | 6 +- src/video/wayland/SDL_waylandkeyboard.c | 23 ++-- src/video/wayland/SDL_waylandkeyboard.h | 6 +- src/video/wayland/SDL_waylandvideo.c | 2 +- src/video/windows/SDL_windowsevents.c | 22 ++- src/video/windows/SDL_windowskeyboard.c | 141 ++++++++++---------- src/video/windows/SDL_windowskeyboard.h | 8 +- src/video/windows/SDL_windowsvideo.c | 2 +- src/video/winrt/SDL_winrtkeyboard.cpp | 2 +- src/video/x11/SDL_x11events.c | 8 +- src/video/x11/SDL_x11keyboard.c | 35 +++-- src/video/x11/SDL_x11keyboard.h | 6 +- src/video/x11/SDL_x11video.c | 2 +- test/checkkeys.c | 22 +-- test/checkkeysthreads.c | 12 +- test/testautomation_keyboard.c | 41 +++--- test/testime.c | 10 +- 48 files changed, 361 insertions(+), 339 deletions(-) diff --git a/docs/README-migration.md b/docs/README-migration.md index 496feceee1..3790bc49b5 100644 --- a/docs/README-migration.md +++ b/docs/README-migration.md @@ -907,6 +907,8 @@ The following symbols have been removed: 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 text input state hase been changed to be window-specific. SDL_StartTextInput(), SDL_StopTextInput(), SDL_TextInputActive(), and SDL_ClearComposition() all now take a window parameter. + SDL_GetDefaultKeyFromScancode(), SDL_GetKeyFromScancode(), and SDL_GetScancodeFromKey() take an SDL_Keymod parameter and use that to provide the correct result based on keyboard modifier state. The following functions have been renamed: diff --git a/include/SDL3/SDL_keyboard.h b/include/SDL3/SDL_keyboard.h index 83576e208f..7452461344 100644 --- a/include/SDL3/SDL_keyboard.h +++ b/include/SDL3/SDL_keyboard.h @@ -353,59 +353,72 @@ extern SDL_DECLSPEC const char *SDLCALL SDL_GetKeyName(SDL_Keycode key); extern SDL_DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromName(const char *name); /** - * Start accepting Unicode text input events. + * Start accepting Unicode text input events in a window. * - * This function will start accepting Unicode text input events in the focused - * SDL window, and start emitting SDL_TextInputEvent (SDL_EVENT_TEXT_INPUT) - * and SDL_TextEditingEvent (SDL_EVENT_TEXT_EDITING) events. Please use this - * function in pair with SDL_StopTextInput(). + * This function will enable text input (SDL_EVENT_TEXT_INPUT and SDL_EVENT_TEXT_EDITING events) in the specified window. Please use this function paired with SDL_StopTextInput(). * * Text input events are not received by default. * - * On some platforms using this function activates the screen keyboard. + * On some platforms using this function shows the screen keyboard. + * + * \param window the window to enable text input. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_SetTextInputRect * \sa SDL_StopTextInput + * \sa SDL_TextInputActive */ -extern SDL_DECLSPEC void SDLCALL SDL_StartTextInput(void); +extern SDL_DECLSPEC int SDLCALL SDL_StartTextInput(SDL_Window *window); /** - * Check whether or not Unicode text input events are enabled. + * Check whether or not Unicode text input events are enabled for a window. * + * \param window the window to check. * \returns SDL_TRUE if text input events are enabled else SDL_FALSE. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StartTextInput */ -extern SDL_DECLSPEC SDL_bool SDLCALL SDL_TextInputActive(void); +extern SDL_DECLSPEC SDL_bool SDLCALL SDL_TextInputActive(SDL_Window *window); /** - * Stop receiving any text input events. + * Stop receiving any text input events in a window. * - * Text input events are not received by default. + * If SDL_StartTextInput() showed the screen keyboard, this function will hide it. + * + * \param window the window to disable text input. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. * * \since This function is available since SDL 3.0.0. * * \sa SDL_StartTextInput */ -extern SDL_DECLSPEC void SDLCALL SDL_StopTextInput(void); +extern SDL_DECLSPEC int SDLCALL SDL_StopTextInput(SDL_Window *window); /** * Dismiss the composition window/IME without disabling the subsystem. * + * \param window the window to affect. + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * * \since This function is available since SDL 3.0.0. * * \sa SDL_StartTextInput * \sa SDL_StopTextInput */ -extern SDL_DECLSPEC void SDLCALL SDL_ClearComposition(void); +extern SDL_DECLSPEC int SDLCALL SDL_ClearComposition(SDL_Window *window); /** * Set the rectangle used to type Unicode text inputs. * + * This is often set to the extents of a text field within the window. + * * Native input methods will place a window with word suggestions near it, * without covering the text being inputted. * @@ -417,6 +430,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ClearComposition(void); * **SDL_HINT_IME_SHOW_UI** to **1**, otherwise this function won't give you * any feedback. * + * \param window the window for which to set the text input rectangle. * \param rect the SDL_Rect structure representing the rectangle to receive * text (ignored if NULL). * \returns 0 on success or a negative error code on failure; call @@ -426,7 +440,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_ClearComposition(void); * * \sa SDL_StartTextInput */ -extern SDL_DECLSPEC int SDLCALL SDL_SetTextInputRect(const SDL_Rect *rect); +extern SDL_DECLSPEC int SDLCALL SDL_SetTextInputRect(SDL_Window *window, const SDL_Rect *rect); /** * Check whether the platform has screen keyboard support. diff --git a/src/core/android/SDL_android.c b/src/core/android/SDL_android.c index b33d420a1e..a426506010 100644 --- a/src/core/android/SDL_android.c +++ b/src/core/android/SDL_android.c @@ -1252,7 +1252,7 @@ JNIEXPORT jboolean JNICALL SDL_JAVA_INTERFACE(onNativeSoftReturnKey)( JNIEnv *env, jclass jcls) { if (SDL_GetHintBoolean(SDL_HINT_RETURN_KEY_HIDES_IME, SDL_FALSE)) { - SDL_StopTextInput(); + SDL_StopTextInput(Android_Window); return JNI_TRUE; } return JNI_FALSE; @@ -1263,7 +1263,7 @@ JNIEXPORT void JNICALL SDL_JAVA_INTERFACE(onNativeKeyboardFocusLost)( JNIEnv *env, jclass jcls) { /* Calling SDL_StopTextInput will take care of hiding the keyboard and cleaning up the DummyText widget */ - SDL_StopTextInput(); + SDL_StopTextInput(Android_Window); } /* Touch */ diff --git a/src/core/haiku/SDL_BApp.h b/src/core/haiku/SDL_BApp.h index 37384fdb69..e4f3b8dcce 100644 --- a/src/core/haiku/SDL_BApp.h +++ b/src/core/haiku/SDL_BApp.h @@ -292,8 +292,11 @@ class SDL_BLooper : public BLooper void _HandleKey(BMessage *msg) { + SDL_Window *win; + int32 winID; int32 scancode, state; /* scancode, pressed/released */ if ( + !_GetWinID(msg, &winID) || msg->FindInt32("key-state", &state) != B_OK || msg->FindInt32("key-scancode", &scancode) != B_OK) { return; @@ -306,7 +309,8 @@ class SDL_BLooper : public BLooper HAIKU_SetKeyState(scancode, state); SDL_SendKeyboardKey(0, SDL_DEFAULT_KEYBOARD_ID, scancode, HAIKU_GetScancodeFromBeKey(scancode), state); - if (state == SDL_PRESSED && SDL_TextInputActive()) { + win = GetSDLWindow(winID); + if (state == SDL_PRESSED && SDL_TextInputActive(win)) { const int8 *keyUtf8; ssize_t count; if (msg->FindData("key-utf8", B_INT8_TYPE, (const void **)&keyUtf8, &count) == B_OK) { diff --git a/src/core/linux/SDL_fcitx.c b/src/core/linux/SDL_fcitx.c index 808054a05b..bd0a8fb7b2 100644 --- a/src/core/linux/SDL_fcitx.c +++ b/src/core/linux/SDL_fcitx.c @@ -211,7 +211,7 @@ static DBusHandlerResult DBus_MessageFilter(DBusConnection *conn, DBusMessage *m SDL_SendEditingText("", 0, 0); } - SDL_Fcitx_UpdateTextRect(NULL); + SDL_Fcitx_UpdateTextRect(SDL_GetKeyboardFocus()); return DBUS_HANDLER_RESULT_HANDLED; } @@ -390,7 +390,7 @@ SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) 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); + SDL_Fcitx_UpdateTextRect(SDL_GetKeyboardFocus()); return SDL_TRUE; } } @@ -398,26 +398,22 @@ SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) return SDL_FALSE; } -void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect) +void SDL_Fcitx_UpdateTextRect(SDL_Window *window) { - SDL_Window *focused_win = NULL; int x = 0, y = 0; SDL_Rect *cursor = &fcitx_client.cursor_rect; - if (rect) { - SDL_copyp(cursor, rect); - } - - focused_win = SDL_GetKeyboardFocus(); - if (!focused_win) { + if (!window) { return; } - SDL_GetWindowPosition(focused_win, &x, &y); + SDL_copyp(cursor, &window->text_input_rect); + + SDL_GetWindowPosition(window, &x, &y); #ifdef SDL_VIDEO_DRIVER_X11 { - SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); + SDL_PropertiesID props = SDL_GetWindowProperties(window); Display *x_disp = (Display *)SDL_GetProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); int x_screen = SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_SCREEN_NUMBER, 0); Window x_win = SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); @@ -431,7 +427,7 @@ void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect) if (cursor->x == -1 && cursor->y == -1 && cursor->w == 0 && cursor->h == 0) { /* move to bottom left */ int w = 0, h = 0; - SDL_GetWindowSize(focused_win, &w, &h); + SDL_GetWindowSize(window, &w, &h); cursor->x = 0; cursor->y = h; } diff --git a/src/core/linux/SDL_fcitx.h b/src/core/linux/SDL_fcitx.h index 44ee053309..daddf8fd4e 100644 --- a/src/core/linux/SDL_fcitx.h +++ b/src/core/linux/SDL_fcitx.h @@ -29,7 +29,7 @@ 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, Uint8 state); -extern void SDL_Fcitx_UpdateTextRect(const SDL_Rect *rect); +extern void SDL_Fcitx_UpdateTextRect(SDL_Window *window); extern void SDL_Fcitx_PumpEvents(void); #endif /* SDL_fcitx_h_ */ diff --git a/src/core/linux/SDL_ibus.c b/src/core/linux/SDL_ibus.c index 9e514c3022..370dff7d4b 100644 --- a/src/core/linux/SDL_ibus.c +++ b/src/core/linux/SDL_ibus.c @@ -261,7 +261,7 @@ static DBusHandlerResult IBus_MessageHandler(DBusConnection *conn, DBusMessage * } } - SDL_IBus_UpdateTextRect(NULL); + SDL_IBus_UpdateTextRect(SDL_GetKeyboardFocus()); return DBUS_HANDLER_RESULT_HANDLED; } @@ -480,9 +480,13 @@ static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr) dbus->connection_flush(ibus_conn); } - SDL_IBus_SetFocus(SDL_GetKeyboardFocus() != NULL); - SDL_IBus_UpdateTextRect(NULL); - + SDL_Window *window = SDL_GetKeyboardFocus(); + if (SDL_TextInputActive(window)) { + SDL_IBus_SetFocus(SDL_TRUE); + SDL_IBus_UpdateTextRect(window); + } else { + SDL_IBus_SetFocus(SDL_FALSE); + } return result; } @@ -670,31 +674,27 @@ SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) } } - SDL_IBus_UpdateTextRect(NULL); + SDL_IBus_UpdateTextRect(SDL_GetKeyboardFocus()); return (result != 0); } -void SDL_IBus_UpdateTextRect(const SDL_Rect *rect) +void SDL_IBus_UpdateTextRect(SDL_Window *window) { - SDL_Window *focused_win; int x = 0, y = 0; SDL_DBusContext *dbus; - if (rect) { - SDL_memcpy(&ibus_cursor_rect, rect, sizeof(ibus_cursor_rect)); - } - - focused_win = SDL_GetKeyboardFocus(); - if (!focused_win) { + if (!window) { return; } - SDL_GetWindowPosition(focused_win, &x, &y); + SDL_copyp(&ibus_cursor_rect, &window->text_input_rect); + + SDL_GetWindowPosition(window, &x, &y); #ifdef SDL_VIDEO_DRIVER_X11 { - SDL_PropertiesID props = SDL_GetWindowProperties(focused_win); + SDL_PropertiesID props = SDL_GetWindowProperties(window); Display *x_disp = (Display *)SDL_GetProperty(props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL); int x_screen = SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_SCREEN_NUMBER, 0); Window x_win = SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0); diff --git a/src/core/linux/SDL_ibus.h b/src/core/linux/SDL_ibus.h index 377a9fc2bd..5ff90cb82d 100644 --- a/src/core/linux/SDL_ibus.h +++ b/src/core/linux/SDL_ibus.h @@ -44,7 +44,7 @@ extern SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 st /* 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. */ -extern void SDL_IBus_UpdateTextRect(const SDL_Rect *window_relative_rect); +extern void SDL_IBus_UpdateTextRect(SDL_Window *window); /* Checks DBus for new IBus events, and calls SDL_SendKeyboardText / SDL_SendEditingText for each event it finds */ diff --git a/src/core/linux/SDL_ime.c b/src/core/linux/SDL_ime.c index 752c3ab9b8..7f2ba82392 100644 --- a/src/core/linux/SDL_ime.c +++ b/src/core/linux/SDL_ime.c @@ -29,7 +29,7 @@ typedef void (*SDL_IME_Quit_t)(void); typedef void (*SDL_IME_SetFocus_t)(SDL_bool); typedef void (*SDL_IME_Reset_t)(void); typedef SDL_bool (*SDL_IME_ProcessKeyEvent_t)(Uint32, Uint32, Uint8 state); -typedef void (*SDL_IME_UpdateTextRect_t)(const SDL_Rect *); +typedef void (*SDL_IME_UpdateTextRect_t)(SDL_Window *window); typedef void (*SDL_IME_PumpEvents_t)(void); static SDL_IME_Init_t SDL_IME_Init_Real = NULL; @@ -135,10 +135,10 @@ SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state) return SDL_FALSE; } -void SDL_IME_UpdateTextRect(const SDL_Rect *rect) +void SDL_IME_UpdateTextRect(SDL_Window *window) { if (SDL_IME_UpdateTextRect_Real) { - SDL_IME_UpdateTextRect_Real(rect); + SDL_IME_UpdateTextRect_Real(window); } } diff --git a/src/core/linux/SDL_ime.h b/src/core/linux/SDL_ime.h index f0ac778259..088ac53397 100644 --- a/src/core/linux/SDL_ime.h +++ b/src/core/linux/SDL_ime.h @@ -29,7 +29,7 @@ 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, Uint8 state); -extern void SDL_IME_UpdateTextRect(const SDL_Rect *rect); +extern void SDL_IME_UpdateTextRect(SDL_Window *window); extern void SDL_IME_PumpEvents(void); #endif /* SDL_ime_h_ */ diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 09cc85694a..bc9b6bfe7a 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -86,7 +86,7 @@ SDL_DYNAPI_PROC(int,SDL_CaptureMouse,(SDL_bool a),(a),return) SDL_DYNAPI_PROC(void,SDL_CleanupTLS,(void),(),) SDL_DYNAPI_PROC(int,SDL_ClearAudioStream,(SDL_AudioStream *a),(a),return) SDL_DYNAPI_PROC(int,SDL_ClearClipboardData,(void),(),return) -SDL_DYNAPI_PROC(void,SDL_ClearComposition,(void),(),) +SDL_DYNAPI_PROC(int,SDL_ClearComposition,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_ClearError,(void),(),return) SDL_DYNAPI_PROC(int,SDL_ClearProperty,(SDL_PropertiesID a, const char *b),(a,b),return) SDL_DYNAPI_PROC(void,SDL_CloseAudioDevice,(SDL_AudioDeviceID a),(a),) @@ -779,7 +779,7 @@ SDL_DYNAPI_PROC(int,SDL_SetSurfaceColorspace,(SDL_Surface *a, SDL_Colorspace b), SDL_DYNAPI_PROC(int,SDL_SetSurfacePalette,(SDL_Surface *a, SDL_Palette *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetSurfaceRLE,(SDL_Surface *a, int b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetTLS,(SDL_TLSID a, const void *b, SDL_TLSDestructorCallback c),(a,b,c),return) -SDL_DYNAPI_PROC(int,SDL_SetTextInputRect,(const SDL_Rect *a),(a),return) +SDL_DYNAPI_PROC(int,SDL_SetTextInputRect,(SDL_Window *a, const SDL_Rect *b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetTextureAlphaMod,(SDL_Texture *a, Uint8 b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetTextureAlphaModFloat,(SDL_Texture *a, float b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_SetTextureBlendMode,(SDL_Texture *a, SDL_BlendMode b),(a,b),return) @@ -821,17 +821,17 @@ SDL_DYNAPI_PROC(int,SDL_ShowWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_ShowWindowSystemMenu,(SDL_Window *a, int b, int c),(a,b,c),return) SDL_DYNAPI_PROC(int,SDL_SignalCondition,(SDL_Condition *a),(a),return) SDL_DYNAPI_PROC(int,SDL_SoftStretch,(SDL_Surface *a, const SDL_Rect *b, SDL_Surface *c, const SDL_Rect *d, SDL_ScaleMode e),(a,b,c,d,e),return) -SDL_DYNAPI_PROC(void,SDL_StartTextInput,(void),(),) +SDL_DYNAPI_PROC(int,SDL_StartTextInput,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(int,SDL_StopHapticEffect,(SDL_Haptic *a, int b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_StopHapticEffects,(SDL_Haptic *a),(a),return) SDL_DYNAPI_PROC(int,SDL_StopHapticRumble,(SDL_Haptic *a),(a),return) -SDL_DYNAPI_PROC(void,SDL_StopTextInput,(void),(),) +SDL_DYNAPI_PROC(int,SDL_StopTextInput,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_StorageReady,(SDL_Storage *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_SurfaceHasColorKey,(SDL_Surface *a),(a),return) SDL_DYNAPI_PROC(SDL_bool,SDL_SurfaceHasRLE,(SDL_Surface *a),(a),return) SDL_DYNAPI_PROC(int,SDL_SyncWindow,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(Sint64,SDL_TellIO,(SDL_IOStream *a),(a),return) -SDL_DYNAPI_PROC(SDL_bool,SDL_TextInputActive,(void),(),return) +SDL_DYNAPI_PROC(SDL_bool,SDL_TextInputActive,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_Time,SDL_TimeFromWindows,(Uint32 a, Uint32 b),(a,b),return) SDL_DYNAPI_PROC(int,SDL_TimeToDateTime,(SDL_Time a, SDL_DateTime *b, SDL_bool c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_TimeToWindows,(SDL_Time a, Uint32 *b, Uint32 *c),(a,b,c),) diff --git a/src/events/SDL_keyboard.c b/src/events/SDL_keyboard.c index d490facae4..21e581dcfd 100644 --- a/src/events/SDL_keyboard.c +++ b/src/events/SDL_keyboard.c @@ -303,9 +303,9 @@ int SDL_SetKeyboardFocus(SDL_Window *window) SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_LOST, 0, 0); /* Ensures IME compositions are committed */ - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(keyboard->focus)) { if (video && video->StopTextInput) { - video->StopTextInput(video); + video->StopTextInput(video, keyboard->focus); } } } @@ -315,9 +315,9 @@ int SDL_SetKeyboardFocus(SDL_Window *window) if (keyboard->focus) { SDL_SendWindowEvent(keyboard->focus, SDL_EVENT_WINDOW_FOCUS_GAINED, 0, 0); - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(keyboard->focus)) { if (video && video->StartTextInput) { - video->StartTextInput(video); + video->StartTextInput(video, keyboard->focus); } } } @@ -598,7 +598,7 @@ int SDL_SendKeyboardText(const char *text) SDL_Keyboard *keyboard = &SDL_keyboard; int posted; - if (!SDL_TextInputActive()) { + if (!SDL_TextInputActive(keyboard->focus)) { return 0; } @@ -632,7 +632,7 @@ int SDL_SendEditingText(const char *text, int start, int length) SDL_Keyboard *keyboard = &SDL_keyboard; int posted; - if (!SDL_TextInputActive()) { + if (!SDL_TextInputActive(keyboard->focus)) { return 0; } diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 9add48fcac..b49a1501ce 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -101,6 +101,9 @@ struct SDL_Window SDL_bool is_destroying; SDL_bool is_dropping; /* drag/drop in progress, expecting SDL_SendDropComplete(). */ + SDL_bool text_input_active; + SDL_Rect text_input_rect; + SDL_Rect mouse_rect; SDL_HitTest hit_test; @@ -322,10 +325,10 @@ struct SDL_VideoDevice int (*SuspendScreenSaver)(SDL_VideoDevice *_this); /* Text input */ - void (*StartTextInput)(SDL_VideoDevice *_this); - void (*StopTextInput)(SDL_VideoDevice *_this); - int (*SetTextInputRect)(SDL_VideoDevice *_this, const SDL_Rect *rect); - void (*ClearComposition)(SDL_VideoDevice *_this); + int (*StartTextInput)(SDL_VideoDevice *_this, SDL_Window *window); + int (*StopTextInput)(SDL_VideoDevice *_this, SDL_Window *window); + int (*UpdateTextInputRect)(SDL_VideoDevice *_this, SDL_Window *window); + int (*ClearComposition)(SDL_VideoDevice *_this, SDL_Window *window); /* Screen keyboard */ SDL_bool (*HasScreenKeyboardSupport)(SDL_VideoDevice *_this); @@ -382,7 +385,6 @@ 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 2cfbfb96da..2ffb28ff45 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -4981,74 +4981,85 @@ void SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask) } #endif -void SDL_StartTextInput(void) +int SDL_StartTextInput(SDL_Window *window) { - if (!_this) { - return; - } + CHECK_WINDOW_MAGIC(window, -1); /* Show the on-screen keyboard, if desired */ const char *hint = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD); if (((!hint || SDL_strcasecmp(hint, "auto") == 0) && !SDL_HasKeyboard()) || SDL_GetStringBoolean(hint, SDL_FALSE)) { - SDL_Window *window = SDL_GetKeyboardFocus(); - if (window && _this->ShowScreenKeyboard) { + if (_this->ShowScreenKeyboard) { _this->ShowScreenKeyboard(_this, window); } } /* Finally start the text input system */ if (_this->StartTextInput) { - _this->StartTextInput(_this); + if (_this->StartTextInput(_this, window) < 0) { + return -1; + } } - _this->text_input_active = SDL_TRUE; + window->text_input_active = SDL_TRUE; + return 0; } -void SDL_ClearComposition(void) +SDL_bool SDL_TextInputActive(SDL_Window *window) { - if (_this && _this->ClearComposition) { - _this->ClearComposition(_this); - } + CHECK_WINDOW_MAGIC(window, SDL_FALSE); + + return window->text_input_active; } -SDL_bool SDL_TextInputActive(void) +int SDL_StopTextInput(SDL_Window *window) { - return _this && _this->text_input_active; -} - -void SDL_StopTextInput(void) -{ - if (!_this) { - return; - } + CHECK_WINDOW_MAGIC(window, -1); /* Stop the text input system */ if (_this->StopTextInput) { - _this->StopTextInput(_this); + _this->StopTextInput(_this, window); } - _this->text_input_active = SDL_FALSE; + window->text_input_active = SDL_FALSE; /* Hide the on-screen keyboard, if desired */ const char *hint = SDL_GetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD); if (((!hint || SDL_strcasecmp(hint, "auto") == 0) && !SDL_HasKeyboard()) || SDL_GetStringBoolean(hint, SDL_FALSE)) { - SDL_Window *window = SDL_GetKeyboardFocus(); - if (window && _this->HideScreenKeyboard) { + if (_this->HideScreenKeyboard) { _this->HideScreenKeyboard(_this, window); } } + return 0; } -int SDL_SetTextInputRect(const SDL_Rect *rect) +int SDL_SetTextInputRect(SDL_Window *window, const SDL_Rect *rect) { - if (!rect) { - return SDL_InvalidParamError("rect"); + CHECK_WINDOW_MAGIC(window, -1); + + if (rect) { + SDL_copyp(&window->text_input_rect, rect); + } else { + SDL_zero(window->text_input_rect); } - if (_this && _this->SetTextInputRect) { - return _this->SetTextInputRect(_this, rect); + if (_this && _this->UpdateTextInputRect) { + if (_this->UpdateTextInputRect(_this, window) < 0) { + return -1; + } } - return SDL_Unsupported(); + return 0; +} + +int SDL_ClearComposition(SDL_Window *window) +{ + CHECK_WINDOW_MAGIC(window, -1); + + if (_this->ClearComposition) { + if (_this->ClearComposition(_this, window) < 0) { + return -1; + } + } + return 0; } SDL_bool SDL_HasScreenKeyboardSupport(void) diff --git a/src/video/android/SDL_androidkeyboard.c b/src/video/android/SDL_androidkeyboard.c index 45bf4021aa..85a124725c 100644 --- a/src/video/android/SDL_androidkeyboard.c +++ b/src/video/android/SDL_androidkeyboard.c @@ -345,8 +345,7 @@ SDL_bool Android_HasScreenKeyboardSupport(SDL_VideoDevice *_this) void Android_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window) { - SDL_VideoData *videodata = _this->driverdata; - Android_JNI_ShowScreenKeyboard(&videodata->textRect); + Android_JNI_ShowScreenKeyboard(&window->text_input_rect); SDL_screen_keyboard_shown = SDL_TRUE; } @@ -368,11 +367,4 @@ SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *windo return Android_JNI_IsScreenKeyboardShown(); } -int Android_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) -{ - SDL_VideoData *videodata = _this->driverdata; - videodata->textRect = *rect; - return 0; -} - #endif /* SDL_VIDEO_DRIVER_ANDROID */ diff --git a/src/video/android/SDL_androidkeyboard.h b/src/video/android/SDL_androidkeyboard.h index 48de9d481f..bcbd948e1c 100644 --- a/src/video/android/SDL_androidkeyboard.h +++ b/src/video/android/SDL_androidkeyboard.h @@ -30,4 +30,3 @@ extern void Android_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *windo extern void Android_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window); extern void Android_RestoreScreenKeyboardOnResume(SDL_VideoDevice *_this, SDL_Window *window); extern SDL_bool Android_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window); -extern int Android_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect); diff --git a/src/video/android/SDL_androidvideo.c b/src/video/android/SDL_androidvideo.c index 5924a027ec..8e2cae7c00 100644 --- a/src/video/android/SDL_androidvideo.c +++ b/src/video/android/SDL_androidvideo.c @@ -143,9 +143,6 @@ static SDL_VideoDevice *Android_CreateDevice(void) /* Screensaver */ device->SuspendScreenSaver = Android_SuspendScreenSaver; - /* Text input */ - device->SetTextInputRect = Android_SetTextInputRect; - /* Screen keyboard */ device->HasScreenKeyboardSupport = Android_HasScreenKeyboardSupport; device->ShowScreenKeyboard = Android_ShowScreenKeyboard; diff --git a/src/video/android/SDL_androidvideo.h b/src/video/android/SDL_androidvideo.h index f6dd54eb56..b7043ffa8d 100644 --- a/src/video/android/SDL_androidvideo.h +++ b/src/video/android/SDL_androidvideo.h @@ -35,7 +35,6 @@ extern void Android_SetDarkMode(SDL_bool enabled); struct SDL_VideoData { - SDL_Rect textRect; int isPaused; int isPausing; int pauseAudio; diff --git a/src/video/cocoa/SDL_cocoakeyboard.h b/src/video/cocoa/SDL_cocoakeyboard.h index 1314ec67d8..ccbc057b44 100644 --- a/src/video/cocoa/SDL_cocoakeyboard.h +++ b/src/video/cocoa/SDL_cocoakeyboard.h @@ -27,9 +27,9 @@ extern void Cocoa_InitKeyboard(SDL_VideoDevice *_this); extern void Cocoa_HandleKeyEvent(SDL_VideoDevice *_this, NSEvent *event); extern void Cocoa_QuitKeyboard(SDL_VideoDevice *_this); -extern void Cocoa_StartTextInput(SDL_VideoDevice *_this); -extern void Cocoa_StopTextInput(SDL_VideoDevice *_this); -extern int Cocoa_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect); +extern int Cocoa_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window); +extern int Cocoa_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window); +extern int Cocoa_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window); extern int Cocoa_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed); diff --git a/src/video/cocoa/SDL_cocoakeyboard.m b/src/video/cocoa/SDL_cocoakeyboard.m index f6ef52bf3a..b003d6910b 100644 --- a/src/video/cocoa/SDL_cocoakeyboard.m +++ b/src/video/cocoa/SDL_cocoakeyboard.m @@ -48,7 +48,7 @@ - (void)setInputRect:(const SDL_Rect *)rect { - _inputRect = *rect; + SDL_copyp(&_inputRect, rect); } - (void)insertText:(id)aString replacementRange:(NSRange)replacementRange @@ -343,16 +343,12 @@ void Cocoa_InitKeyboard(SDL_VideoDevice *_this) SDL_ToggleModState(SDL_KMOD_CAPS, (data.modifierFlags & NSEventModifierFlagCapsLock) ? SDL_TRUE : SDL_FALSE); } -void Cocoa_StartTextInput(SDL_VideoDevice *_this) +int Cocoa_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window) { @autoreleasepool { NSView *parentView; SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata; - SDL_Window *window = SDL_GetKeyboardFocus(); - NSWindow *nswindow = nil; - if (window) { - nswindow = ((__bridge SDL_CocoaWindowData *)window->driverdata).nswindow; - } + NSWindow *nswindow = ((__bridge SDL_CocoaWindowData *)window->driverdata).nswindow; parentView = [nswindow contentView]; @@ -362,8 +358,7 @@ void Cocoa_StartTextInput(SDL_VideoDevice *_this) * text input, simply remove the field editor from its superview then add * it to the front most window's content view */ if (!data.fieldEdit) { - data.fieldEdit = - [[SDLTranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)]; + data.fieldEdit = [[SDLTranslatorResponder alloc] initWithFrame:NSMakeRect(0.0, 0.0, 0.0, 0.0)]; } if (![[data.fieldEdit superview] isEqual:parentView]) { @@ -373,9 +368,10 @@ void Cocoa_StartTextInput(SDL_VideoDevice *_this) [nswindow makeFirstResponder:data.fieldEdit]; } } + return Cocoa_UpdateTextInputRect(_this, window); } -void Cocoa_StopTextInput(SDL_VideoDevice *_this) +int Cocoa_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window) { @autoreleasepool { SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata; @@ -385,12 +381,15 @@ void Cocoa_StopTextInput(SDL_VideoDevice *_this) data.fieldEdit = nil; } } + return 0; } -int Cocoa_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) +int Cocoa_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window) { SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata; - [data.fieldEdit setInputRect:rect]; + if (data.fieldEdit) { + [data.fieldEdit setInputRect:&window->text_input_rect]; + } return 0; } @@ -433,7 +432,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_TextInputActive()) { + if (SDL_TextInputActive(SDL_GetKeyboardFocus())) { /* 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/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index 5e796c73f4..0b63c248cc 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -172,7 +172,7 @@ static SDL_VideoDevice *Cocoa_CreateDevice(void) device->StartTextInput = Cocoa_StartTextInput; device->StopTextInput = Cocoa_StopTextInput; - device->SetTextInputRect = Cocoa_SetTextInputRect; + device->UpdateTextInputRect = Cocoa_UpdateTextInputRect; device->SetClipboardData = Cocoa_SetClipboardData; device->GetClipboardData = Cocoa_GetClipboardData; diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index 99ed3efbb7..fa6a0d1c98 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -790,6 +790,7 @@ static EM_BOOL Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent static EM_BOOL Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) { + SDL_WindowData *window_data = (SDL_WindowData *)userData; const SDL_Keycode keycode = Emscripten_MapKeyCode(keyEvent); SDL_Scancode scancode = Emscripten_MapScanCode(keyEvent->code); SDL_bool prevent_default = SDL_TRUE; @@ -852,7 +853,7 @@ static EM_BOOL Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent is_nav_key = SDL_TRUE; } - if ((eventType == EMSCRIPTEN_EVENT_KEYDOWN) && SDL_TextInputActive() && !is_nav_key) { + if ((eventType == EMSCRIPTEN_EVENT_KEYDOWN) && SDL_TextInputActive(window_data->window) && !is_nav_key) { prevent_default = SDL_FALSE; } @@ -861,7 +862,9 @@ static EM_BOOL Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent static EM_BOOL Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) { - if (SDL_TextInputActive()) { + SDL_WindowData *window_data = (SDL_WindowData *)userData; + + if (SDL_TextInputActive(window_data->window)) { char text[5]; if (Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text)) { SDL_SendKeyboardText(text); diff --git a/src/video/gdk/SDL_gdktextinput.cpp b/src/video/gdk/SDL_gdktextinput.cpp index b54b1ab774..de82500ded 100644 --- a/src/video/gdk/SDL_gdktextinput.cpp +++ b/src/video/gdk/SDL_gdktextinput.cpp @@ -178,7 +178,7 @@ void GDK_EnsureHints(void) } } -void GDK_StartTextInput(SDL_VideoDevice *_this) +int GDK_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window) { /* * Currently a stub, since all input is handled by the virtual keyboard, @@ -191,14 +191,16 @@ void GDK_StartTextInput(SDL_VideoDevice *_this) * Right now this function isn't implemented on Desktop * and seems to be present only in the docs? So I didn't bother. */ + return 0; } -void GDK_StopTextInput(SDL_VideoDevice *_this) +int GDK_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window) { /* See notice in GDK_StartTextInput */ + return 0; } -int GDK_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) +int GDK_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window) { /* * XGameUiShowTextEntryAsync does not allow you to set @@ -212,9 +214,10 @@ int GDK_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) return 0; } -void GDK_ClearComposition(SDL_VideoDevice *_this) +int GDK_ClearComposition(SDL_VideoDevice *_this, SDL_Window *window) { /* See notice in GDK_StartTextInput */ + return 0; } SDL_bool GDK_HasScreenKeyboardSupport(SDL_VideoDevice *_this) diff --git a/src/video/gdk/SDL_gdktextinput.h b/src/video/gdk/SDL_gdktextinput.h index 5272703143..78c506cbf2 100644 --- a/src/video/gdk/SDL_gdktextinput.h +++ b/src/video/gdk/SDL_gdktextinput.h @@ -32,10 +32,10 @@ extern "C" { void GDK_EnsureHints(void); -void GDK_StartTextInput(SDL_VideoDevice *_this); -void GDK_StopTextInput(SDL_VideoDevice *_this); -int GDK_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect); -void GDK_ClearComposition(SDL_VideoDevice *_this); +int GDK_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window); +int GDK_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window); +int GDK_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window); +int GDK_ClearComposition(SDL_VideoDevice *_this, SDL_Window *window); SDL_bool GDK_HasScreenKeyboardSupport(SDL_VideoDevice *_this); void GDK_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/haiku/SDL_bvideo.cc b/src/video/haiku/SDL_bvideo.cc index 2b5b170963..f4ed4c8ba9 100644 --- a/src/video/haiku/SDL_bvideo.cc +++ b/src/video/haiku/SDL_bvideo.cc @@ -47,16 +47,6 @@ static SDL_INLINE SDL_BWin *_ToBeWin(SDL_Window *window) { return (SDL_BWin *)(window->driverdata); } -/* FIXME: Undefined functions */ -// #define HAIKU_PumpEvents NULL - #define HAIKU_StartTextInput NULL - #define HAIKU_StopTextInput NULL - #define HAIKU_SetTextInputRect NULL - -// #define HAIKU_DeleteDevice NULL - -/* End undefined functions */ - static SDL_VideoDevice * HAIKU_CreateDevice(void) { SDL_VideoDevice *device; @@ -109,10 +99,6 @@ static SDL_VideoDevice * HAIKU_CreateDevice(void) device->GL_DeleteContext = HAIKU_GL_DeleteContext; #endif - device->StartTextInput = HAIKU_StartTextInput; - device->StopTextInput = HAIKU_StopTextInput; - device->SetTextInputRect = HAIKU_SetTextInputRect; - device->SetClipboardText = HAIKU_SetClipboardText; device->GetClipboardText = HAIKU_GetClipboardText; device->HasClipboardText = HAIKU_HasClipboardText; diff --git a/src/video/n3ds/SDL_n3dsswkb.c b/src/video/n3ds/SDL_n3dsswkb.c index 0948fff095..1140aae087 100644 --- a/src/video/n3ds/SDL_n3dsswkb.c +++ b/src/video/n3ds/SDL_n3dsswkb.c @@ -50,7 +50,7 @@ SDL_bool N3DS_HasScreenKeyboardSupport(SDL_VideoDevice *_this) return SDL_TRUE; } -void N3DS_StartTextInput(SDL_VideoDevice *_this) +int N3DS_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window) { char buffer[BUFFER_SIZE]; SwkbdButton button_pressed; @@ -58,11 +58,12 @@ void N3DS_StartTextInput(SDL_VideoDevice *_this) if (button_pressed == SWKBD_BUTTON_CONFIRM) { SDL_SendKeyboardText(buffer); } + return 0; } -void N3DS_StopTextInput(SDL_VideoDevice *_this) +int N3DS_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window) { - return; + return 0; } #endif /* SDL_VIDEO_DRIVER_N3DS */ diff --git a/src/video/n3ds/SDL_n3dsswkb.h b/src/video/n3ds/SDL_n3dsswkb.h index da86f0b5bb..0f505ebe89 100644 --- a/src/video/n3ds/SDL_n3dsswkb.h +++ b/src/video/n3ds/SDL_n3dsswkb.h @@ -30,7 +30,7 @@ void N3DS_SwkbQuit(); SDL_bool N3DS_HasScreenKeyboardSupport(SDL_VideoDevice *_this); -void N3DS_StartTextInput(SDL_VideoDevice *_this); -void N3DS_StopTextInput(SDL_VideoDevice *_this); +int N3DS_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window); +int N3DS_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window); #endif /* SDL_n3dskeyboard_h_ */ diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index c4f1eb0460..dea57315cf 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -100,7 +100,7 @@ static SDL_VideoDevice *UIKit_CreateDevice(void) device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard; device->HideScreenKeyboard = UIKit_HideScreenKeyboard; device->IsScreenKeyboardShown = UIKit_IsScreenKeyboardShown; - device->SetTextInputRect = UIKit_SetTextInputRect; + device->UpdateTextInputRect = UIKit_UpdateTextInputRect; #endif device->SetClipboardText = UIKit_SetClipboardText; diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 92d3dd3461..ebae602fc3 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -417,7 +417,7 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick; SDL_SendKeyboardKey(UIKit_GetEventTimestamp([event timestamp]), SDL_GLOBAL_KEYBOARD_ID, 0, scancode, SDL_PRESSED); } } - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(sdlwindow)) { [super pressesBegan:presses withEvent:event]; } } @@ -430,7 +430,7 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick; SDL_SendKeyboardKey(UIKit_GetEventTimestamp([event timestamp]), SDL_GLOBAL_KEYBOARD_ID, 0, scancode, SDL_RELEASED); } } - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(sdlwindow)) { [super pressesEnded:presses withEvent:event]; } } @@ -443,7 +443,7 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick; SDL_SendKeyboardKey(UIKit_GetEventTimestamp([event timestamp]), SDL_GLOBAL_KEYBOARD_ID, 0, scancode, SDL_RELEASED); } } - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(sdlwindow)) { [super pressesCancelled:presses withEvent:event]; } } @@ -451,7 +451,7 @@ extern int SDL_AppleTVRemoteOpenedAsJoystick; - (void)pressesChanged:(NSSet *)presses withEvent:(UIPressesEvent *)event { /* This is only called when the force of a press changes. */ - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(sdlwindow)) { [super pressesChanged:presses withEvent:event]; } } diff --git a/src/video/uikit/SDL_uikitviewcontroller.h b/src/video/uikit/SDL_uikitviewcontroller.h index 23d93f876f..670c174fef 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.h +++ b/src/video/uikit/SDL_uikitviewcontroller.h @@ -91,5 +91,5 @@ SDL_bool UIKit_HasScreenKeyboardSupport(SDL_VideoDevice *_this); void UIKit_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window); void UIKit_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window); SDL_bool UIKit_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window); -int UIKit_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect); +int UIKit_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window); #endif diff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m index f6de072e85..1027b8d883 100644 --- a/src/video/uikit/SDL_uikitviewcontroller.m +++ b/src/video/uikit/SDL_uikitviewcontroller.m @@ -425,7 +425,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char { BOOL shouldStartTextInput = NO; - if (!SDL_TextInputActive() && !hidingKeyboard && !rotatingOrientation) { + if (!SDL_TextInputActive(window) && !hidingKeyboard && !rotatingOrientation) { shouldStartTextInput = YES; } @@ -441,7 +441,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char #endif if (shouldStartTextInput) { - SDL_StartTextInput(); + SDL_StartTextInput(window); } } @@ -454,7 +454,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char { BOOL shouldStopTextInput = NO; - if (SDL_TextInputActive() && !showingKeyboard && !rotatingOrientation) { + if (SDL_TextInputActive(window) && !showingKeyboard && !rotatingOrientation) { shouldStopTextInput = YES; } @@ -462,7 +462,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char [self setKeyboardHeight:0]; if (shouldStopTextInput) { - SDL_StopTextInput(); + SDL_StopTextInput(window); } } @@ -567,7 +567,7 @@ static void SDLCALL SDL_HideHomeIndicatorHintChanged(void *userdata, const char SDL_SendKeyboardKeyAutoRelease(0, SDL_SCANCODE_RETURN); if (keyboardVisible && SDL_GetHintBoolean(SDL_HINT_RETURN_KEY_HIDES_IME, SDL_FALSE)) { - SDL_StopTextInput(); + SDL_StopTextInput(window); } return YES; } @@ -623,12 +623,12 @@ SDL_bool UIKit_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window) } } -int UIKit_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) +int UIKit_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window) { @autoreleasepool { - SDL_uikitviewcontroller *vc = GetWindowViewController(SDL_GetKeyboardFocus()); + SDL_uikitviewcontroller *vc = GetWindowViewController(window); if (vc != nil) { - vc.textInputRect = *rect; + vc.textInputRect = window->text_input_rect; if (vc.keyboardVisible) { [vc updateKeyboard]; diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index 309f3e4130..05e4017dcb 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -381,7 +381,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_TextInputActive()) { + if (!d->text_input_manager && SDL_TextInputActive(SDL_GetKeyboardFocus())) { SDL_IME_PumpEvents(); } #endif @@ -454,7 +454,7 @@ void Wayland_PumpEvents(SDL_VideoDevice *_this) int err; #ifdef SDL_USE_IME - if (!d->text_input_manager && SDL_TextInputActive()) { + if (!d->text_input_manager && SDL_TextInputActive(SDL_GetKeyboardFocus())) { SDL_IME_PumpEvents(); } #endif @@ -1649,7 +1649,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, Wayland_UpdateImplicitGrabSerial(input, serial); if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(SDL_GetKeyboardFocus())) { has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime); } } else { diff --git a/src/video/wayland/SDL_waylandkeyboard.c b/src/video/wayland/SDL_waylandkeyboard.c index eac7e8219a..481e706cb2 100644 --- a/src/video/wayland/SDL_waylandkeyboard.c +++ b/src/video/wayland/SDL_waylandkeyboard.c @@ -51,7 +51,7 @@ void Wayland_QuitKeyboard(SDL_VideoDevice *_this) #endif } -void Wayland_StartTextInput(SDL_VideoDevice *_this) +int Wayland_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window) { SDL_VideoData *driverdata = _this->driverdata; struct SDL_WaylandInput *input = driverdata->input; @@ -82,9 +82,11 @@ void Wayland_StartTextInput(SDL_VideoDevice *_this) /* Reset compose state so composite and dead keys don't carry over */ WAYLAND_xkb_compose_state_reset(input->xkb.compose_state); } + + return Wayland_UpdateTextInputRect(_this, window); } -void Wayland_StopTextInput(SDL_VideoDevice *_this) +int Wayland_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window) { SDL_VideoData *driverdata = _this->driverdata; struct SDL_WaylandInput *input = driverdata->input; @@ -105,21 +107,22 @@ void Wayland_StopTextInput(SDL_VideoDevice *_this) /* Reset compose state so composite and dead keys don't carry over */ WAYLAND_xkb_compose_state_reset(input->xkb.compose_state); } + return 0; } -int Wayland_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) +int Wayland_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window) { SDL_VideoData *driverdata = _this->driverdata; if (driverdata->text_input_manager) { struct SDL_WaylandInput *input = driverdata->input; if (input && input->text_input) { - if (!SDL_RectsEqual(rect, &input->text_input->cursor_rect)) { - SDL_copyp(&input->text_input->cursor_rect, rect); + if (!SDL_RectsEqual(&window->text_input_rect, &input->text_input->cursor_rect)) { + SDL_copyp(&input->text_input->cursor_rect, &window->text_input_rect); zwp_text_input_v3_set_cursor_rectangle(input->text_input->text_input, - rect->x, - rect->y, - rect->w, - rect->h); + window->text_input_rect.x, + window->text_input_rect.y, + window->text_input_rect.w, + window->text_input_rect.h); zwp_text_input_v3_commit(input->text_input->text_input); } } @@ -127,7 +130,7 @@ int Wayland_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) #ifdef SDL_USE_IME else { - SDL_IME_UpdateTextRect(rect); + SDL_IME_UpdateTextRect(window); } #endif return 0; diff --git a/src/video/wayland/SDL_waylandkeyboard.h b/src/video/wayland/SDL_waylandkeyboard.h index 62613cffff..b42bb11b91 100644 --- a/src/video/wayland/SDL_waylandkeyboard.h +++ b/src/video/wayland/SDL_waylandkeyboard.h @@ -32,9 +32,9 @@ typedef struct SDL_WaylandTextInput extern int Wayland_InitKeyboard(SDL_VideoDevice *_this); extern void Wayland_QuitKeyboard(SDL_VideoDevice *_this); -extern void Wayland_StartTextInput(SDL_VideoDevice *_this); -extern void Wayland_StopTextInput(SDL_VideoDevice *_this); -extern int Wayland_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect); +extern int Wayland_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window); +extern int Wayland_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window); +extern int Wayland_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window); extern SDL_bool Wayland_HasScreenKeyboardSupport(SDL_VideoDevice *_this); #endif /* SDL_waylandkeyboard_h_ */ diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index aedc1b2393..893fd1bd9a 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -511,7 +511,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(void) device->HasClipboardData = Wayland_HasClipboardData; device->StartTextInput = Wayland_StartTextInput; device->StopTextInput = Wayland_StopTextInput; - device->SetTextInputRect = Wayland_SetTextInputRect; + device->UpdateTextInputRect = Wayland_UpdateTextInputRect; #ifdef SDL_VIDEO_VULKAN device->Vulkan_LoadLibrary = Wayland_Vulkan_LoadLibrary; diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 9cc060ac7c..4e4f29f16e 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -1280,7 +1280,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara if (wParam == UNICODE_NOCHAR) { returnCode = 1; } else { - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(data->window)) { char text[5]; if (SDL_UCS4ToUTF8((Uint32)wParam, text) != text) { SDL_SendKeyboardText(text); @@ -1291,25 +1291,23 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara break; case WM_CHAR: - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(data->window)) { /* 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]; + 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'; } diff --git a/src/video/windows/SDL_windowskeyboard.c b/src/video/windows/SDL_windowskeyboard.c index a2206ea5a8..61dfe9da39 100644 --- a/src/video/windows/SDL_windowskeyboard.c +++ b/src/video/windows/SDL_windowskeyboard.c @@ -34,6 +34,7 @@ static int IME_Init(SDL_VideoData *videodata, HWND hwnd); static void IME_Enable(SDL_VideoData *videodata, HWND hwnd); static void IME_Disable(SDL_VideoData *videodata, HWND hwnd); +static void IME_SetTextInputRect(SDL_VideoData *videodata, const SDL_Rect *rect); static void IME_Quit(SDL_VideoData *videodata); #endif /* !SDL_DISABLE_WINDOWS_IME */ @@ -190,9 +191,9 @@ void WIN_UpdateKeymap(SDL_bool send_event) void WIN_QuitKeyboard(SDL_VideoDevice *_this) { +#ifndef SDL_DISABLE_WINDOWS_IME SDL_VideoData *data = _this->driverdata; -#ifndef SDL_DISABLE_WINDOWS_IME IME_Quit(data); if (data->ime_composition) { @@ -233,87 +234,53 @@ void WIN_ResetDeadKeys() } } -void WIN_StartTextInput(SDL_VideoDevice *_this) +int WIN_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window) { -#ifndef SDL_DISABLE_WINDOWS_IME - SDL_Window *window; -#endif - WIN_ResetDeadKeys(); #ifndef SDL_DISABLE_WINDOWS_IME - window = SDL_GetKeyboardFocus(); - if (window) { - HWND hwnd = window->driverdata->hwnd; - SDL_VideoData *videodata = _this->driverdata; - SDL_GetWindowSize(window, &videodata->ime_winwidth, &videodata->ime_winheight); - IME_Init(videodata, hwnd); - IME_Enable(videodata, hwnd); - } -#endif /* !SDL_DISABLE_WINDOWS_IME */ -} - -void WIN_StopTextInput(SDL_VideoDevice *_this) -{ -#ifndef SDL_DISABLE_WINDOWS_IME - SDL_Window *window; -#endif - - WIN_ResetDeadKeys(); - -#ifndef SDL_DISABLE_WINDOWS_IME - window = SDL_GetKeyboardFocus(); - if (window) { - HWND hwnd = window->driverdata->hwnd; - SDL_VideoData *videodata = _this->driverdata; - IME_Init(videodata, hwnd); - IME_Disable(videodata, hwnd); - } -#endif /* !SDL_DISABLE_WINDOWS_IME */ -} - -int WIN_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) -{ + HWND hwnd = window->driverdata->hwnd; SDL_VideoData *videodata = _this->driverdata; - HIMC himc = 0; + SDL_GetWindowSize(window, &videodata->ime_winwidth, &videodata->ime_winheight); + IME_Init(videodata, hwnd); + IME_Enable(videodata, hwnd); + + WIN_UpdateTextInputRect(_this, window); +#endif /* !SDL_DISABLE_WINDOWS_IME */ + + return 0; +} + +int WIN_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window) +{ + WIN_ResetDeadKeys(); #ifndef SDL_DISABLE_WINDOWS_IME - videodata->ime_rect = *rect; - - himc = ImmGetContext(videodata->ime_hwnd_current); - if (himc) { - COMPOSITIONFORM cof; - CANDIDATEFORM caf; - - cof.dwStyle = CFS_RECT; - cof.ptCurrentPos.x = videodata->ime_rect.x; - cof.ptCurrentPos.y = videodata->ime_rect.y; - cof.rcArea.left = videodata->ime_rect.x; - cof.rcArea.right = (LONG)videodata->ime_rect.x + videodata->ime_rect.w; - cof.rcArea.top = videodata->ime_rect.y; - cof.rcArea.bottom = (LONG)videodata->ime_rect.y + videodata->ime_rect.h; - ImmSetCompositionWindow(himc, &cof); - - caf.dwIndex = 0; - caf.dwStyle = CFS_EXCLUDE; - caf.ptCurrentPos.x = videodata->ime_rect.x; - caf.ptCurrentPos.y = videodata->ime_rect.y; - caf.rcArea.left = videodata->ime_rect.x; - caf.rcArea.right = (LONG)videodata->ime_rect.x + videodata->ime_rect.w; - caf.rcArea.top = videodata->ime_rect.y; - caf.rcArea.bottom = (LONG)videodata->ime_rect.y + videodata->ime_rect.h; - ImmSetCandidateWindow(himc, &caf); - - ImmReleaseContext(videodata->ime_hwnd_current, himc); - } + HWND hwnd = window->driverdata->hwnd; + SDL_VideoData *videodata = _this->driverdata; + IME_Init(videodata, hwnd); + IME_Disable(videodata, hwnd); #endif /* !SDL_DISABLE_WINDOWS_IME */ + + return 0; +} + +int WIN_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window) +{ +#ifndef SDL_DISABLE_WINDOWS_IME + SDL_VideoData *data = _this->driverdata; + + IME_SetTextInputRect(data, &window->text_input_rect); +#endif /* !SDL_DISABLE_WINDOWS_IME */ + return 0; } #ifdef SDL_DISABLE_WINDOWS_IME -void WIN_ClearComposition(SDL_VideoDevice *_this) +int WIN_ClearComposition(SDL_VideoDevice *_this, SDL_Window *window) { + return 0; } SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata) @@ -758,6 +725,41 @@ static void IME_SetWindow(SDL_VideoData *videodata, HWND hwnd) } } } + IME_SetTextInputRect(videodata, &videodata->ime_rect); +} + +static void IME_SetTextInputRect(SDL_VideoData *videodata, const SDL_Rect *rect) +{ + HIMC himc = 0; + + videodata->ime_rect = *rect; + + himc = ImmGetContext(videodata->ime_hwnd_current); + if (himc) { + COMPOSITIONFORM cof; + CANDIDATEFORM caf; + + cof.dwStyle = CFS_RECT; + cof.ptCurrentPos.x = videodata->ime_rect.x; + cof.ptCurrentPos.y = videodata->ime_rect.y; + cof.rcArea.left = videodata->ime_rect.x; + cof.rcArea.right = (LONG)videodata->ime_rect.x + videodata->ime_rect.w; + cof.rcArea.top = videodata->ime_rect.y; + cof.rcArea.bottom = (LONG)videodata->ime_rect.y + videodata->ime_rect.h; + ImmSetCompositionWindow(himc, &cof); + + caf.dwIndex = 0; + caf.dwStyle = CFS_EXCLUDE; + caf.ptCurrentPos.x = videodata->ime_rect.x; + caf.ptCurrentPos.y = videodata->ime_rect.y; + caf.rcArea.left = videodata->ime_rect.x; + caf.rcArea.right = (LONG)videodata->ime_rect.x + videodata->ime_rect.w; + caf.rcArea.top = videodata->ime_rect.y; + caf.rcArea.bottom = (LONG)videodata->ime_rect.y + videodata->ime_rect.h; + ImmSetCandidateWindow(himc, &caf); + + ImmReleaseContext(videodata->ime_hwnd_current, himc); + } } static void IME_UpdateInputLocale(SDL_VideoData *videodata) @@ -1742,10 +1744,11 @@ void IME_Present(SDL_VideoData *videodata) /* FIXME: Need to show the IME bitmap */ } -void WIN_ClearComposition(SDL_VideoDevice *_this) +int WIN_ClearComposition(SDL_VideoDevice *_this, SDL_Window *window) { SDL_VideoData *videodata = _this->driverdata; IME_ClearComposition(videodata); + return 0; } #endif /* SDL_DISABLE_WINDOWS_IME */ diff --git a/src/video/windows/SDL_windowskeyboard.h b/src/video/windows/SDL_windowskeyboard.h index 41ce58eb5d..0c614b5488 100644 --- a/src/video/windows/SDL_windowskeyboard.h +++ b/src/video/windows/SDL_windowskeyboard.h @@ -29,10 +29,10 @@ extern void WIN_QuitKeyboard(SDL_VideoDevice *_this); extern void WIN_ResetDeadKeys(void); -extern void WIN_StartTextInput(SDL_VideoDevice *_this); -extern void WIN_StopTextInput(SDL_VideoDevice *_this); -extern int WIN_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect); -extern void WIN_ClearComposition(SDL_VideoDevice *_this); +extern int WIN_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window); +extern int WIN_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window); +extern int WIN_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window); +extern int WIN_ClearComposition(SDL_VideoDevice *_this, SDL_Window *window); extern SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata); diff --git a/src/video/windows/SDL_windowsvideo.c b/src/video/windows/SDL_windowsvideo.c index 3130ecfbf6..889f5e58ab 100644 --- a/src/video/windows/SDL_windowsvideo.c +++ b/src/video/windows/SDL_windowsvideo.c @@ -268,7 +268,7 @@ static SDL_VideoDevice *WIN_CreateDevice(void) #if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) device->StartTextInput = WIN_StartTextInput; device->StopTextInput = WIN_StopTextInput; - device->SetTextInputRect = WIN_SetTextInputRect; + device->UpdateTextInputRect = WIN_UpdateTextInputRect; device->ClearComposition = WIN_ClearComposition; device->SetClipboardData = WIN_SetClipboardData; diff --git a/src/video/winrt/SDL_winrtkeyboard.cpp b/src/video/winrt/SDL_winrtkeyboard.cpp index d5f9a6e832..eece32c6e7 100644 --- a/src/video/winrt/SDL_winrtkeyboard.cpp +++ b/src/video/winrt/SDL_winrtkeyboard.cpp @@ -90,7 +90,7 @@ void WINRT_ProcessCharacterReceivedEvent(SDL_Window *window, Windows::UI::Core:: SDL_WindowData *data = window->driverdata; - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(window)) { /* 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. */ diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 043db8de53..abb75622bc 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -883,7 +883,7 @@ void X11_HandleKeyEvent(SDL_VideoDevice *_this, SDL_WindowData *windowdata, SDL_ text[0] = '\0'; - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(windowdata->window)) { #if defined(HAVE_IBUS_IBUS_H) || defined(HAVE_FCITX) /* Save the original keycode for dead keys, which are filtered out by the XFilterEvent() call below. @@ -1397,7 +1397,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_TextInputActive()) { + if (SDL_TextInputActive(data->window)) { /* Update IME candidate list position */ SDL_IME_UpdateTextRect(NULL); } @@ -2014,7 +2014,7 @@ int X11_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS) X11_DispatchEvent(_this, &xevent); #ifdef SDL_USE_IME - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(SDL_GetKeyboardFocus())) { SDL_IME_PumpEvents(); } #endif @@ -2074,7 +2074,7 @@ void X11_PumpEvents(SDL_VideoDevice *_this) } #ifdef SDL_USE_IME - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(SDL_GetKeyboardFocus())) { SDL_IME_PumpEvents(); } #endif diff --git a/src/video/x11/SDL_x11keyboard.c b/src/video/x11/SDL_x11keyboard.c index 543c36e4a8..2d772449c2 100644 --- a/src/video/x11/SDL_x11keyboard.c +++ b/src/video/x11/SDL_x11keyboard.c @@ -430,44 +430,41 @@ void X11_QuitKeyboard(SDL_VideoDevice *_this) #endif } -static void X11_ResetXIM(SDL_VideoDevice *_this) +static void X11_ResetXIM(SDL_VideoDevice *_this, SDL_Window *window) { #ifdef X_HAVE_UTF8_STRING - SDL_VideoData *videodata = _this->driverdata; - int i; + SDL_WindowData *data = window->driverdata; - if (videodata && videodata->windowlist) { - for (i = 0; i < videodata->numwindows; ++i) { - SDL_WindowData *data = videodata->windowlist[i]; - if (data && data->ic) { - /* Clear any partially entered dead keys */ - char *contents = X11_Xutf8ResetIC(data->ic); - if (contents) { - X11_XFree(contents); - } - } + if (data && data->ic) { + /* Clear any partially entered dead keys */ + char *contents = X11_Xutf8ResetIC(data->ic); + if (contents) { + X11_XFree(contents); } } #endif } -void X11_StartTextInput(SDL_VideoDevice *_this) +int X11_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window) { - X11_ResetXIM(_this); + X11_ResetXIM(_this, window); + + return X11_UpdateTextInputRect(_this, window); } -void X11_StopTextInput(SDL_VideoDevice *_this) +int X11_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window) { - X11_ResetXIM(_this); + X11_ResetXIM(_this, window); #ifdef SDL_USE_IME SDL_IME_Reset(); #endif + return 0; } -int X11_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect) +int X11_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window) { #ifdef SDL_USE_IME - SDL_IME_UpdateTextRect(rect); + SDL_IME_UpdateTextRect(window); #endif return 0; } diff --git a/src/video/x11/SDL_x11keyboard.h b/src/video/x11/SDL_x11keyboard.h index 5e0ed2803e..7fe7384496 100644 --- a/src/video/x11/SDL_x11keyboard.h +++ b/src/video/x11/SDL_x11keyboard.h @@ -26,9 +26,9 @@ extern int X11_InitKeyboard(SDL_VideoDevice *_this); extern void X11_UpdateKeymap(SDL_VideoDevice *_this, SDL_bool send_event); extern void X11_QuitKeyboard(SDL_VideoDevice *_this); -extern void X11_StartTextInput(SDL_VideoDevice *_this); -extern void X11_StopTextInput(SDL_VideoDevice *_this); -extern int X11_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect); +extern int X11_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window); +extern int X11_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window); +extern int X11_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window); extern SDL_bool X11_HasScreenKeyboardSupport(SDL_VideoDevice *_this); extern void X11_ShowScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window); extern void X11_HideScreenKeyboard(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index d417ce9223..aba3cfc728 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -267,7 +267,7 @@ static SDL_VideoDevice *X11_CreateDevice(void) device->HasPrimarySelectionText = X11_HasPrimarySelectionText; device->StartTextInput = X11_StartTextInput; device->StopTextInput = X11_StopTextInput; - device->SetTextInputRect = X11_SetTextInputRect; + device->UpdateTextInputRect = X11_UpdateTextInputRect; device->HasScreenKeyboardSupport = X11_HasScreenKeyboardSupport; device->ShowScreenKeyboard = X11_ShowScreenKeyboard; device->HideScreenKeyboard = X11_HideScreenKeyboard; diff --git a/test/checkkeys.c b/test/checkkeys.c index 4dae90ae43..f9f03f3e8f 100644 --- a/test/checkkeys.c +++ b/test/checkkeys.c @@ -252,28 +252,34 @@ static void loop(void) SDLTest_TextWindowAddText(textwin, "%s", event.text.text); break; case SDL_EVENT_FINGER_DOWN: - if (SDL_TextInputActive()) { + { + SDL_Window *window = SDL_GetWindowFromID(event.tfinger.windowID); + if (SDL_TextInputActive(window)) { SDL_Log("Stopping text input\n"); - SDL_StopTextInput(); + SDL_StopTextInput(window); } else { SDL_Log("Starting text input\n"); - SDL_StartTextInput(); + SDL_StartTextInput(window); } break; + } case SDL_EVENT_MOUSE_BUTTON_DOWN: + { + SDL_Window *window = SDL_GetWindowFromID(event.button.windowID); /* Left button quits the app, other buttons toggles text input */ if (event.button.button == SDL_BUTTON_LEFT) { done = 1; } else { - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(window)) { SDL_Log("Stopping text input\n"); - SDL_StopTextInput(); + SDL_StopTextInput(window); } else { SDL_Log("Starting text input\n"); - SDL_StartTextInput(); + SDL_StartTextInput(window); } } break; + } case SDL_EVENT_KEYMAP_CHANGED: SDL_Log("Keymap changed!\n"); PrintKeymap(); @@ -356,9 +362,9 @@ int main(int argc, char *argv[]) input_rect.y = h / 4; input_rect.w = w / 2; input_rect.h = h / 2; - SDL_SetTextInputRect(&input_rect); + SDL_SetTextInputRect(state->windows[0], &input_rect); - SDL_StartTextInput(); + SDL_StartTextInput(state->windows[0]); /* Print initial state */ SDL_PumpEvents(); diff --git a/test/checkkeysthreads.c b/test/checkkeysthreads.c index a596bdd0bb..881de8f94f 100644 --- a/test/checkkeysthreads.c +++ b/test/checkkeysthreads.c @@ -186,20 +186,24 @@ static void loop(void) PrintText("INPUT", event.text.text); break; case SDL_EVENT_MOUSE_BUTTON_DOWN: + { + SDL_Window *window = SDL_GetWindowFromID(event.button.windowID); + /* Left button quits the app, other buttons toggles text input */ SDL_Log("mouse button down button: %d (LEFT=%d)\n", event.button.button, SDL_BUTTON_LEFT); if (event.button.button == SDL_BUTTON_LEFT) { done = 1; } else { - if (SDL_TextInputActive()) { + if (SDL_TextInputActive(window)) { SDL_Log("Stopping text input\n"); - SDL_StopTextInput(); + SDL_StopTextInput(window); } else { SDL_Log("Starting text input\n"); - SDL_StartTextInput(); + SDL_StartTextInput(window); } } break; + } case SDL_EVENT_QUIT: done = 1; break; @@ -278,7 +282,7 @@ int main(int argc, char *argv[]) SDL_GL_CreateContext(window); #endif - SDL_StartTextInput(); + SDL_StartTextInput(window); /* Print initial modifier state */ SDL_PumpEvents(); diff --git a/test/testautomation_keyboard.c b/test/testautomation_keyboard.c index d825db4075..d15d170520 100644 --- a/test/testautomation_keyboard.c +++ b/test/testautomation_keyboard.c @@ -336,36 +336,38 @@ static int keyboard_getSetModState(void *arg) */ static int keyboard_startStopTextInput(void *arg) { + SDL_Window *window = SDL_GetKeyboardFocus(); + /* Start-Stop */ - SDL_StartTextInput(); + SDL_StartTextInput(window); SDLTest_AssertPass("Call to SDL_StartTextInput()"); - SDL_StopTextInput(); + SDL_StopTextInput(window); SDLTest_AssertPass("Call to SDL_StopTextInput()"); /* Stop-Start */ - SDL_StartTextInput(); + SDL_StartTextInput(window); SDLTest_AssertPass("Call to SDL_StartTextInput()"); /* Start-Start */ - SDL_StartTextInput(); + SDL_StartTextInput(window); SDLTest_AssertPass("Call to SDL_StartTextInput()"); /* Stop-Stop */ - SDL_StopTextInput(); + SDL_StopTextInput(window); SDLTest_AssertPass("Call to SDL_StopTextInput()"); - SDL_StopTextInput(); + SDL_StopTextInput(window); SDLTest_AssertPass("Call to SDL_StopTextInput()"); return TEST_COMPLETED; } /* Internal function to test SDL_SetTextInputRect */ -static void testSetTextInputRect(SDL_Rect refRect) +static void testSetTextInputRect(SDL_Window *window, SDL_Rect refRect) { SDL_Rect testRect; testRect = refRect; - SDL_SetTextInputRect(&testRect); + SDL_SetTextInputRect(window, &testRect); SDLTest_AssertPass("Call to SDL_SetTextInputRect with refRect(x:%d,y:%d,w:%d,h:%d)", refRect.x, refRect.y, refRect.w, refRect.h); SDLTest_AssertCheck( (refRect.x == testRect.x) && (refRect.y == testRect.y) && (refRect.w == testRect.w) && (refRect.h == testRect.h), @@ -381,6 +383,7 @@ static void testSetTextInputRect(SDL_Rect refRect) */ static int keyboard_setTextInputRect(void *arg) { + SDL_Window *window = SDL_GetKeyboardFocus(); SDL_Rect refRect; /* Normal visible refRect, origin inside */ @@ -388,66 +391,66 @@ static int keyboard_setTextInputRect(void *arg) refRect.y = SDLTest_RandomIntegerInRange(1, 50); refRect.w = SDLTest_RandomIntegerInRange(10, 50); refRect.h = SDLTest_RandomIntegerInRange(10, 50); - testSetTextInputRect(refRect); + testSetTextInputRect(window, refRect); /* Normal visible refRect, origin 0,0 */ refRect.x = 0; refRect.y = 0; refRect.w = SDLTest_RandomIntegerInRange(10, 50); refRect.h = SDLTest_RandomIntegerInRange(10, 50); - testSetTextInputRect(refRect); + testSetTextInputRect(window, refRect); /* 1Pixel refRect */ refRect.x = SDLTest_RandomIntegerInRange(10, 50); refRect.y = SDLTest_RandomIntegerInRange(10, 50); refRect.w = 1; refRect.h = 1; - testSetTextInputRect(refRect); + testSetTextInputRect(window, refRect); /* 0pixel refRect */ refRect.x = 1; refRect.y = 1; refRect.w = 1; refRect.h = 0; - testSetTextInputRect(refRect); + testSetTextInputRect(window, refRect); /* 0pixel refRect */ refRect.x = 1; refRect.y = 1; refRect.w = 0; refRect.h = 1; - testSetTextInputRect(refRect); + testSetTextInputRect(window, refRect); /* 0pixel refRect */ refRect.x = 1; refRect.y = 1; refRect.w = 0; refRect.h = 0; - testSetTextInputRect(refRect); + testSetTextInputRect(window, refRect); /* 0pixel refRect */ refRect.x = 0; refRect.y = 0; refRect.w = 0; refRect.h = 0; - testSetTextInputRect(refRect); + testSetTextInputRect(window, refRect); /* negative refRect */ refRect.x = SDLTest_RandomIntegerInRange(-200, -100); refRect.y = SDLTest_RandomIntegerInRange(-200, -100); refRect.w = 50; refRect.h = 50; - testSetTextInputRect(refRect); + testSetTextInputRect(window, refRect); /* oversized refRect */ refRect.x = SDLTest_RandomIntegerInRange(1, 50); refRect.y = SDLTest_RandomIntegerInRange(1, 50); refRect.w = 5000; refRect.h = 5000; - testSetTextInputRect(refRect); + testSetTextInputRect(window, refRect); /* NULL refRect */ - SDL_SetTextInputRect(NULL); + SDL_SetTextInputRect(window, NULL); SDLTest_AssertPass("Call to SDL_SetTextInputRect(NULL)"); return TEST_COMPLETED; @@ -470,7 +473,7 @@ static int keyboard_setTextInputRectNegative(void *arg) #endif /* NULL refRect */ - SDL_SetTextInputRect(NULL); + SDL_SetTextInputRect(SDL_GetKeyboardFocus(), NULL); SDLTest_AssertPass("Call to SDL_SetTextInputRect(NULL)"); /* Some platforms set also an error message; so check it */ diff --git a/test/testime.c b/test/testime.c index dcf38ba00d..9e7a9a3802 100644 --- a/test/testime.c +++ b/test/testime.c @@ -440,12 +440,12 @@ static void InitInput(void) markedRect = textRect; markedText[0] = 0; - SDL_StartTextInput(); + SDL_StartTextInput(state->windows[0]); } static void CleanupVideo(void) { - SDL_StopTextInput(); + SDL_StopTextInput(state->windows[0]); #ifdef HAVE_SDL_TTF TTF_CloseFont(font); TTF_Quit(); @@ -507,10 +507,10 @@ static void _Redraw(int rendererID) markedRect.w = textRect.w - drawnTextRect.w; if (markedRect.w < 0) { /* Stop text input because we cannot hold any more characters */ - SDL_StopTextInput(); + SDL_StopTextInput(state->windows[0]); return; } else { - SDL_StartTextInput(); + SDL_StartTextInput(state->windows[0]); } cursorRect = drawnTextRect; @@ -602,7 +602,7 @@ static void _Redraw(int rendererID) inputrect.y = (int)markedRect.y; inputrect.w = (int)markedRect.w; inputrect.h = (int)markedRect.h; - SDL_SetTextInputRect(&inputrect); + SDL_SetTextInputRect(state->windows[0], &inputrect); } }