Bladeren bron

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.
Sam Lantinga 10 maanden geleden
bovenliggende
commit
76631a0978
48 gewijzigde bestanden met toevoegingen van 350 en 328 verwijderingen
  1. 2 0
      docs/README-migration.md
  2. 28 14
      include/SDL3/SDL_keyboard.h
  3. 2 2
      src/core/android/SDL_android.c
  4. 5 1
      src/core/haiku/SDL_BApp.h
  5. 9 13
      src/core/linux/SDL_fcitx.c
  6. 1 1
      src/core/linux/SDL_fcitx.h
  7. 15 15
      src/core/linux/SDL_ibus.c
  8. 1 1
      src/core/linux/SDL_ibus.h
  9. 3 3
      src/core/linux/SDL_ime.c
  10. 1 1
      src/core/linux/SDL_ime.h
  11. 5 5
      src/dynapi/SDL_dynapi_procs.h
  12. 6 6
      src/events/SDL_keyboard.c
  13. 7 5
      src/video/SDL_sysvideo.h
  14. 41 30
      src/video/SDL_video.c
  15. 1 9
      src/video/android/SDL_androidkeyboard.c
  16. 0 1
      src/video/android/SDL_androidkeyboard.h
  17. 0 3
      src/video/android/SDL_androidvideo.c
  18. 0 1
      src/video/android/SDL_androidvideo.h
  19. 3 3
      src/video/cocoa/SDL_cocoakeyboard.h
  20. 12 13
      src/video/cocoa/SDL_cocoakeyboard.m
  21. 1 1
      src/video/cocoa/SDL_cocoavideo.m
  22. 5 2
      src/video/emscripten/SDL_emscriptenevents.c
  23. 7 4
      src/video/gdk/SDL_gdktextinput.cpp
  24. 4 4
      src/video/gdk/SDL_gdktextinput.h
  25. 0 14
      src/video/haiku/SDL_bvideo.cc
  26. 4 3
      src/video/n3ds/SDL_n3dsswkb.c
  27. 2 2
      src/video/n3ds/SDL_n3dsswkb.h
  28. 1 1
      src/video/uikit/SDL_uikitvideo.m
  29. 4 4
      src/video/uikit/SDL_uikitview.m
  30. 1 1
      src/video/uikit/SDL_uikitviewcontroller.h
  31. 8 8
      src/video/uikit/SDL_uikitviewcontroller.m
  32. 3 3
      src/video/wayland/SDL_waylandevents.c
  33. 13 10
      src/video/wayland/SDL_waylandkeyboard.c
  34. 3 3
      src/video/wayland/SDL_waylandkeyboard.h
  35. 1 1
      src/video/wayland/SDL_waylandvideo.c
  36. 10 12
      src/video/windows/SDL_windowsevents.c
  37. 62 59
      src/video/windows/SDL_windowskeyboard.c
  38. 4 4
      src/video/windows/SDL_windowskeyboard.h
  39. 1 1
      src/video/windows/SDL_windowsvideo.c
  40. 1 1
      src/video/winrt/SDL_winrtkeyboard.cpp
  41. 4 4
      src/video/x11/SDL_x11events.c
  42. 16 19
      src/video/x11/SDL_x11keyboard.c
  43. 3 3
      src/video/x11/SDL_x11keyboard.h
  44. 1 1
      src/video/x11/SDL_x11video.c
  45. 14 8
      test/checkkeys.c
  46. 8 4
      test/checkkeysthreads.c
  47. 22 19
      test/testautomation_keyboard.c
  48. 5 5
      test/testime.c

+ 2 - 0
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:

+ 28 - 14
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.

+ 2 - 2
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 */

+ 5 - 1
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) {

+ 9 - 13
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;
     }

+ 1 - 1
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_ */

+ 15 - 15
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);

+ 1 - 1
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 */

+ 3 - 3
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);
     }
 }
 

+ 1 - 1
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_ */

+ 5 - 5
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),)

+ 6 - 6
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;
     }
 

+ 7 - 5
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 */

+ 41 - 30
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);
 
-SDL_bool SDL_TextInputActive(void)
-{
-    return _this && _this->text_input_active;
+    return window->text_input_active;
 }
 
-void SDL_StopTextInput(void)
+int SDL_StopTextInput(SDL_Window *window)
 {
-    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)

+ 1 - 9
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 */

+ 0 - 1
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);

+ 0 - 3
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;

+ 0 - 1
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;

+ 3 - 3
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);
 

+ 12 - 13
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 <https://discourse.libsdl.org/> or to Christian Walther <cwalther@gmx.ch>. 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

+ 1 - 1
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;

+ 5 - 2
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);

+ 7 - 4
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)

+ 4 - 4
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);

+ 0 - 14
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;

+ 4 - 3
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 */

+ 2 - 2
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_ */

+ 1 - 1
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;

+ 4 - 4
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<UIPress *> *)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];
     }
 }

+ 1 - 1
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

+ 8 - 8
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];

+ 3 - 3
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 {

+ 13 - 10
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;

+ 3 - 3
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_ */

+ 1 - 1
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;

+ 10 - 12
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';
             }

+ 62 - 59
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);
-    }
+    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);
+
+    WIN_UpdateTextInputRect(_this, window);
 #endif /* !SDL_DISABLE_WINDOWS_IME */
+
+    return 0;
 }
 
-void WIN_StopTextInput(SDL_VideoDevice *_this)
+int WIN_StopTextInput(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;
-        IME_Init(videodata, hwnd);
-        IME_Disable(videodata, hwnd);
-    }
+    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_SetTextInputRect(SDL_VideoDevice *_this, const SDL_Rect *rect)
+int WIN_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window)
 {
-    SDL_VideoData *videodata = _this->driverdata;
-    HIMC himc = 0;
-
 #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);
+    SDL_VideoData *data = _this->driverdata;
 
-        ImmReleaseContext(videodata->ime_hwnd_current, himc);
-    }
+    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 */

+ 4 - 4
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);
 

+ 1 - 1
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;

+ 1 - 1
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. */

+ 4 - 4
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

+ 16 - 19
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;
 }

+ 3 - 3
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);

+ 1 - 1
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;

+ 14 - 8
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();

+ 8 - 4
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();

+ 22 - 19
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 */

+ 5 - 5
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);
     }
 }