Bladeren bron

SDL_SetTextInputRect() has been renamed to SDL_SetTextInputArea()

The new function includes the cursor position so IME UI elements can be placed relative to the cursor, as well as having the whole text area available so on-screen keyboards can avoid it.
Sam Lantinga 9 maanden geleden
bovenliggende
commit
bdd531986b

+ 1 - 0
docs/README-migration.md

@@ -917,6 +917,7 @@ The following functions have been renamed:
 
 The following functions have been removed:
 * SDL_IsTextInputShown()
+* SDL_SetTextInputRect() - replaced with SDL_SetTextInputArea()
 
 The following structures have been removed:
 * SDL_Keysym

+ 23 - 16
include/SDL3/SDL_keyboard.h

@@ -369,7 +369,7 @@ extern SDL_DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromName(const char *name);
  *
  * \since This function is available since SDL 3.0.0.
  *
- * \sa SDL_SetTextInputRect
+ * \sa SDL_SetTextInputArea
  * \sa SDL_StopTextInput
  * \sa SDL_TextInputActive
  */
@@ -418,32 +418,39 @@ extern SDL_DECLSPEC int SDLCALL SDL_StopTextInput(SDL_Window *window);
 extern SDL_DECLSPEC int SDLCALL SDL_ClearComposition(SDL_Window *window);
 
 /**
- * Set the rectangle used to type Unicode text inputs.
+ * Set the area used to type Unicode text input.
  *
- * This is often set to the extents of a text field within the window.
+ * Native input methods may place a window with word suggestions near the cursor, without covering the text being entered.
  *
- * Native input methods will place a window with word suggestions near it,
- * without covering the text being inputted.
+ * \param window the window for which to set the text input area.
+ * \param rect the SDL_Rect representing the text input area, in window coordinates, or NULL to clear it.
+ * \param cursor the offset of the current cursor location relative to `rect->x`, in window coordinates.
+ * \returns 0 on success or a negative error code on failure; call
+ *          SDL_GetError() for more information.
  *
- * To start text input in a given location, this function is intended to be
- * called before SDL_StartTextInput, although some platforms support moving
- * the rectangle even while text input (and a composition) is active.
+ * \since This function is available since SDL 3.0.0.
  *
- * Note: If you want to use the system native IME window, try setting hint
- * **SDL_HINT_IME_SHOW_UI** to **1**, otherwise this function won't give you
- * any feedback.
+ * \sa SDL_GetTextInputArea
+ * \sa SDL_StartTextInput
+ */
+extern SDL_DECLSPEC int SDLCALL SDL_SetTextInputArea(SDL_Window *window, const SDL_Rect *rect, int cursor);
+
+/**
+ * Get the area used to type Unicode text input.
  *
- * \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).
+ * This returns the values previously set by SDL_SetTextInputArea().
+ *
+ * \param window the window for which to query the text input area.
+ * \param rect a pointer to an SDL_Rect filled in with the text input area, may be NULL.
+ * \param cursor a pointer to the offset of the current cursor location relative to `rect->x`, may be NULL.
  * \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_SetTextInputArea
  */
-extern SDL_DECLSPEC int SDLCALL SDL_SetTextInputRect(SDL_Window *window, const SDL_Rect *rect);
+extern SDL_DECLSPEC int SDLCALL SDL_GetTextInputArea(SDL_Window *window, SDL_Rect *rect, int *cursor);
 
 /**
  * Check whether the platform has screen keyboard support.

+ 8 - 4
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(SDL_GetKeyboardFocus());
+        SDL_Fcitx_UpdateTextInputArea(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(SDL_GetKeyboardFocus());
+            SDL_Fcitx_UpdateTextInputArea(SDL_GetKeyboardFocus());
             return SDL_TRUE;
         }
     }
@@ -398,7 +398,7 @@ SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
     return SDL_FALSE;
 }
 
-void SDL_Fcitx_UpdateTextRect(SDL_Window *window)
+void SDL_Fcitx_UpdateTextInputArea(SDL_Window *window)
 {
     int x = 0, y = 0;
     SDL_Rect *cursor = &fcitx_client.cursor_rect;
@@ -407,7 +407,11 @@ void SDL_Fcitx_UpdateTextRect(SDL_Window *window)
         return;
     }
 
-    SDL_copyp(cursor, &window->text_input_rect);
+    // We'll use a square at the text input cursor location for the cursor_rect
+    cursor->x = window->text_input_rect.x + window->text_input_cursor;
+    cursor->y = window->text_input_rect.x;
+    cursor->w = window->text_input_rect.h;
+    cursor->h = window->text_input_rect.h;
 
     SDL_GetWindowPosition(window, &x, &y);
 

+ 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(SDL_Window *window);
+extern void SDL_Fcitx_UpdateTextInputArea(SDL_Window *window);
 extern void SDL_Fcitx_PumpEvents(void);
 
 #endif /* SDL_fcitx_h_ */

+ 9 - 5
src/core/linux/SDL_ibus.c

@@ -261,7 +261,7 @@ static DBusHandlerResult IBus_MessageHandler(DBusConnection *conn, DBusMessage *
             }
         }
 
-        SDL_IBus_UpdateTextRect(SDL_GetKeyboardFocus());
+        SDL_IBus_UpdateTextInputArea(SDL_GetKeyboardFocus());
 
         return DBUS_HANDLER_RESULT_HANDLED;
     }
@@ -483,7 +483,7 @@ static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr)
     SDL_Window *window = SDL_GetKeyboardFocus();
     if (SDL_TextInputActive(window)) {
         SDL_IBus_SetFocus(SDL_TRUE);
-        SDL_IBus_UpdateTextRect(window);
+        SDL_IBus_UpdateTextInputArea(window);
     } else {
         SDL_IBus_SetFocus(SDL_FALSE);
     }
@@ -674,12 +674,12 @@ SDL_bool SDL_IBus_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
         }
     }
 
-    SDL_IBus_UpdateTextRect(SDL_GetKeyboardFocus());
+    SDL_IBus_UpdateTextInputArea(SDL_GetKeyboardFocus());
 
     return (result != 0);
 }
 
-void SDL_IBus_UpdateTextRect(SDL_Window *window)
+void SDL_IBus_UpdateTextInputArea(SDL_Window *window)
 {
     int x = 0, y = 0;
     SDL_DBusContext *dbus;
@@ -688,7 +688,11 @@ void SDL_IBus_UpdateTextRect(SDL_Window *window)
         return;
     }
 
-    SDL_copyp(&ibus_cursor_rect, &window->text_input_rect);
+    // We'll use a square at the text input cursor location for the ibus_cursor
+    ibus_cursor_rect.x = window->text_input_rect.x + window->text_input_cursor;
+    ibus_cursor_rect.y = window->text_input_rect.x;
+    ibus_cursor_rect.w = window->text_input_rect.h;
+    ibus_cursor_rect.h = window->text_input_rect.h;
 
     SDL_GetWindowPosition(window, &x, &y);
 

+ 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(SDL_Window *window);
+extern void SDL_IBus_UpdateTextInputArea(SDL_Window *window);
 
 /* Checks DBus for new IBus events, and calls SDL_SendKeyboardText /
    SDL_SendEditingText for each event it finds */

+ 8 - 8
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)(SDL_Window *window);
+typedef void (*SDL_IME_UpdateTextInputArea_t)(SDL_Window *window);
 typedef void (*SDL_IME_PumpEvents_t)(void);
 
 static SDL_IME_Init_t SDL_IME_Init_Real = NULL;
@@ -37,7 +37,7 @@ static SDL_IME_Quit_t SDL_IME_Quit_Real = NULL;
 static SDL_IME_SetFocus_t SDL_IME_SetFocus_Real = NULL;
 static SDL_IME_Reset_t SDL_IME_Reset_Real = NULL;
 static SDL_IME_ProcessKeyEvent_t SDL_IME_ProcessKeyEvent_Real = NULL;
-static SDL_IME_UpdateTextRect_t SDL_IME_UpdateTextRect_Real = NULL;
+static SDL_IME_UpdateTextInputArea_t SDL_IME_UpdateTextInputArea_Real = NULL;
 static SDL_IME_PumpEvents_t SDL_IME_PumpEvents_Real = NULL;
 
 static void InitIME(void)
@@ -64,7 +64,7 @@ static void InitIME(void)
         SDL_IME_SetFocus_Real = SDL_Fcitx_SetFocus;
         SDL_IME_Reset_Real = SDL_Fcitx_Reset;
         SDL_IME_ProcessKeyEvent_Real = SDL_Fcitx_ProcessKeyEvent;
-        SDL_IME_UpdateTextRect_Real = SDL_Fcitx_UpdateTextRect;
+        SDL_IME_UpdateTextInputArea_Real = SDL_Fcitx_UpdateTextInputArea;
         SDL_IME_PumpEvents_Real = SDL_Fcitx_PumpEvents;
     }
 #endif /* HAVE_FCITX */
@@ -77,7 +77,7 @@ static void InitIME(void)
         SDL_IME_SetFocus_Real = SDL_IBus_SetFocus;
         SDL_IME_Reset_Real = SDL_IBus_Reset;
         SDL_IME_ProcessKeyEvent_Real = SDL_IBus_ProcessKeyEvent;
-        SDL_IME_UpdateTextRect_Real = SDL_IBus_UpdateTextRect;
+        SDL_IME_UpdateTextInputArea_Real = SDL_IBus_UpdateTextInputArea;
         SDL_IME_PumpEvents_Real = SDL_IBus_PumpEvents;
     }
 #endif /* HAVE_IBUS_IBUS_H */
@@ -98,7 +98,7 @@ SDL_bool SDL_IME_Init(void)
         SDL_IME_SetFocus_Real = NULL;
         SDL_IME_Reset_Real = NULL;
         SDL_IME_ProcessKeyEvent_Real = NULL;
-        SDL_IME_UpdateTextRect_Real = NULL;
+        SDL_IME_UpdateTextInputArea_Real = NULL;
         SDL_IME_PumpEvents_Real = NULL;
     }
 
@@ -135,10 +135,10 @@ SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode, Uint8 state)
     return SDL_FALSE;
 }
 
-void SDL_IME_UpdateTextRect(SDL_Window *window)
+void SDL_IME_UpdateTextInputArea(SDL_Window *window)
 {
-    if (SDL_IME_UpdateTextRect_Real) {
-        SDL_IME_UpdateTextRect_Real(window);
+    if (SDL_IME_UpdateTextInputArea_Real) {
+        SDL_IME_UpdateTextInputArea_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(SDL_Window *window);
+extern void SDL_IME_UpdateTextInputArea(SDL_Window *window);
 extern void SDL_IME_PumpEvents(void);
 
 #endif /* SDL_ime_h_ */

+ 2 - 1
src/dynapi/SDL_dynapi.sym

@@ -437,6 +437,7 @@ SDL3_0.0.0 {
     SDL_GetSystemRAM;
     SDL_GetSystemTheme;
     SDL_GetTLS;
+    SDL_GetTextInputArea;
     SDL_GetTextureAlphaMod;
     SDL_GetTextureAlphaModFloat;
     SDL_GetTextureBlendMode;
@@ -745,7 +746,7 @@ SDL3_0.0.0 {
     SDL_SetSurfacePalette;
     SDL_SetSurfaceRLE;
     SDL_SetTLS;
-    SDL_SetTextInputRect;
+    SDL_SetTextInputArea;
     SDL_SetTextureAlphaMod;
     SDL_SetTextureAlphaModFloat;
     SDL_SetTextureBlendMode;

+ 2 - 1
src/dynapi/SDL_dynapi_overrides.h

@@ -462,6 +462,7 @@
 #define SDL_GetSystemRAM SDL_GetSystemRAM_REAL
 #define SDL_GetSystemTheme SDL_GetSystemTheme_REAL
 #define SDL_GetTLS SDL_GetTLS_REAL
+#define SDL_GetTextInputArea SDL_GetTextInputArea_REAL
 #define SDL_GetTextureAlphaMod SDL_GetTextureAlphaMod_REAL
 #define SDL_GetTextureAlphaModFloat SDL_GetTextureAlphaModFloat_REAL
 #define SDL_GetTextureBlendMode SDL_GetTextureBlendMode_REAL
@@ -770,7 +771,7 @@
 #define SDL_SetSurfacePalette SDL_SetSurfacePalette_REAL
 #define SDL_SetSurfaceRLE SDL_SetSurfaceRLE_REAL
 #define SDL_SetTLS SDL_SetTLS_REAL
-#define SDL_SetTextInputRect SDL_SetTextInputRect_REAL
+#define SDL_SetTextInputArea SDL_SetTextInputArea_REAL
 #define SDL_SetTextureAlphaMod SDL_SetTextureAlphaMod_REAL
 #define SDL_SetTextureAlphaModFloat SDL_SetTextureAlphaModFloat_REAL
 #define SDL_SetTextureBlendMode SDL_SetTextureBlendMode_REAL

+ 2 - 1
src/dynapi/SDL_dynapi_procs.h

@@ -482,6 +482,7 @@ SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetSurfaceProperties,(SDL_Surface *a),(a),r
 SDL_DYNAPI_PROC(int,SDL_GetSystemRAM,(void),(),return)
 SDL_DYNAPI_PROC(SDL_SystemTheme,SDL_GetSystemTheme,(void),(),return)
 SDL_DYNAPI_PROC(void*,SDL_GetTLS,(SDL_TLSID a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_GetTextInputArea,(SDL_Window *a, SDL_Rect *b, int *c),(a,b,c),return)
 SDL_DYNAPI_PROC(int,SDL_GetTextureAlphaMod,(SDL_Texture *a, Uint8 *b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_GetTextureAlphaModFloat,(SDL_Texture *a, float *b),(a,b),return)
 SDL_DYNAPI_PROC(int,SDL_GetTextureBlendMode,(SDL_Texture *a, SDL_BlendMode *b),(a,b),return)
@@ -780,7 +781,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,(SDL_Window *a, const SDL_Rect *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_SetTextInputArea,(SDL_Window *a, const SDL_Rect *b, int c),(a,b,c),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)

+ 2 - 1
src/video/SDL_sysvideo.h

@@ -103,6 +103,7 @@ struct SDL_Window
 
     SDL_bool text_input_active;
     SDL_Rect text_input_rect;
+    int text_input_cursor;
 
     SDL_Rect mouse_rect;
 
@@ -327,7 +328,7 @@ struct SDL_VideoDevice
     /* Text input */
     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 (*UpdateTextInputArea)(SDL_VideoDevice *_this, SDL_Window *window);
     int (*ClearComposition)(SDL_VideoDevice *_this, SDL_Window *window);
 
     /* Screen keyboard */

+ 18 - 3
src/video/SDL_video.c

@@ -5074,24 +5074,39 @@ int SDL_StopTextInput(SDL_Window *window)
     return 0;
 }
 
-int SDL_SetTextInputRect(SDL_Window *window, const SDL_Rect *rect)
+int SDL_SetTextInputArea(SDL_Window *window, const SDL_Rect *rect, int cursor)
 {
     CHECK_WINDOW_MAGIC(window, -1);
 
     if (rect) {
         SDL_copyp(&window->text_input_rect, rect);
+        window->text_input_cursor = cursor;
     } else {
         SDL_zero(window->text_input_rect);
+        window->text_input_cursor = 0;
     }
 
-    if (_this && _this->UpdateTextInputRect) {
-        if (_this->UpdateTextInputRect(_this, window) < 0) {
+    if (_this && _this->UpdateTextInputArea) {
+        if (_this->UpdateTextInputArea(_this, window) < 0) {
             return -1;
         }
     }
     return 0;
 }
 
+int SDL_GetTextInputArea(SDL_Window *window, SDL_Rect *rect, int *cursor)
+{
+    CHECK_WINDOW_MAGIC(window, -1);
+
+    if (rect) {
+        SDL_copyp(rect, &window->text_input_rect);
+    }
+    if (cursor) {
+        *cursor = window->text_input_cursor;
+    }
+    return 0;
+}
+
 int SDL_ClearComposition(SDL_Window *window)
 {
     CHECK_WINDOW_MAGIC(window, -1);

+ 1 - 1
src/video/cocoa/SDL_cocoakeyboard.h

@@ -29,7 +29,7 @@ extern void Cocoa_QuitKeyboard(SDL_VideoDevice *_this);
 
 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_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window);
 
 extern int Cocoa_SetWindowKeyboardGrab(SDL_VideoDevice *_this, SDL_Window *window, SDL_bool grabbed);
 

+ 2 - 2
src/video/cocoa/SDL_cocoakeyboard.m

@@ -368,7 +368,7 @@ int Cocoa_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window)
             [nswindow makeFirstResponder:data.fieldEdit];
         }
     }
-    return Cocoa_UpdateTextInputRect(_this, window);
+    return Cocoa_UpdateTextInputArea(_this, window);
 }
 
 int Cocoa_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window)
@@ -384,7 +384,7 @@ int Cocoa_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window)
     return 0;
 }
 
-int Cocoa_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window)
+int Cocoa_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window)
 {
     SDL_CocoaVideoData *data = (__bridge SDL_CocoaVideoData *)_this->driverdata;
     if (data.fieldEdit) {

+ 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->UpdateTextInputRect = Cocoa_UpdateTextInputRect;
+        device->UpdateTextInputArea = Cocoa_UpdateTextInputArea;
 
         device->SetClipboardData = Cocoa_SetClipboardData;
         device->GetClipboardData = Cocoa_GetClipboardData;

+ 1 - 1
src/video/gdk/SDL_gdktextinput.cpp

@@ -200,7 +200,7 @@ int GDK_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window)
     return 0;
 }
 
-int GDK_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window)
+int GDK_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window)
 {
     /*
      * XGameUiShowTextEntryAsync does not allow you to set

+ 1 - 1
src/video/gdk/SDL_gdktextinput.h

@@ -34,7 +34,7 @@ void GDK_EnsureHints(void);
 
 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_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window);
 int GDK_ClearComposition(SDL_VideoDevice *_this, SDL_Window *window);
 
 SDL_bool GDK_HasScreenKeyboardSupport(SDL_VideoDevice *_this);

+ 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->UpdateTextInputRect = UIKit_UpdateTextInputRect;
+        device->UpdateTextInputArea = UIKit_UpdateTextInputArea;
 #endif
 
         device->SetClipboardText = UIKit_SetClipboardText;

+ 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_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window);
+int UIKit_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window);
 #endif

+ 1 - 1
src/video/uikit/SDL_uikitviewcontroller.m

@@ -623,7 +623,7 @@ SDL_bool UIKit_IsScreenKeyboardShown(SDL_VideoDevice *_this, SDL_Window *window)
     }
 }
 
-int UIKit_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window)
+int UIKit_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window)
 {
     @autoreleasepool {
         SDL_uikitviewcontroller *vc = GetWindowViewController(window);

+ 3 - 3
src/video/wayland/SDL_waylandkeyboard.c

@@ -83,7 +83,7 @@ int Wayland_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window)
         WAYLAND_xkb_compose_state_reset(input->xkb.compose_state);
     }
 
-    return Wayland_UpdateTextInputRect(_this, window);
+    return Wayland_UpdateTextInputArea(_this, window);
 }
 
 int Wayland_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window)
@@ -110,7 +110,7 @@ int Wayland_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window)
     return 0;
 }
 
-int Wayland_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window)
+int Wayland_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window)
 {
     SDL_VideoData *driverdata = _this->driverdata;
     if (driverdata->text_input_manager) {
@@ -130,7 +130,7 @@ int Wayland_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window)
 
 #ifdef SDL_USE_IME
     else {
-        SDL_IME_UpdateTextRect(window);
+        SDL_IME_UpdateTextInputArea(window);
     }
 #endif
     return 0;

+ 1 - 1
src/video/wayland/SDL_waylandkeyboard.h

@@ -34,7 +34,7 @@ extern int Wayland_InitKeyboard(SDL_VideoDevice *_this);
 extern void Wayland_QuitKeyboard(SDL_VideoDevice *_this);
 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 int Wayland_UpdateTextInputArea(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->UpdateTextInputRect = Wayland_UpdateTextInputRect;
+    device->UpdateTextInputArea = Wayland_UpdateTextInputArea;
 
 #ifdef SDL_VIDEO_VULKAN
     device->Vulkan_LoadLibrary = Wayland_Vulkan_LoadLibrary;

+ 46 - 35
src/video/windows/SDL_windowskeyboard.c

@@ -36,10 +36,10 @@
 #else
 #define SDL_DebugIMELog(...)
 #endif
-static int IME_Init(SDL_VideoData *videodata, HWND hwnd);
+static int IME_Init(SDL_VideoData *videodata, SDL_Window *window);
 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_SetTextInputArea(SDL_VideoData *videodata, const SDL_Rect *rect, int cursor);
 static void IME_Quit(SDL_VideoData *videodata);
 #endif /* !SDL_DISABLE_WINDOWS_IME */
 
@@ -208,10 +208,10 @@ int WIN_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window)
 #ifndef SDL_DISABLE_WINDOWS_IME
     HWND hwnd = window->driverdata->hwnd;
     SDL_VideoData *videodata = _this->driverdata;
-    IME_Init(videodata, hwnd);
+    IME_Init(videodata, window);
     IME_Enable(videodata, hwnd);
 
-    WIN_UpdateTextInputRect(_this, window);
+    WIN_UpdateTextInputArea(_this, window);
 #endif /* !SDL_DISABLE_WINDOWS_IME */
 
     return 0;
@@ -224,19 +224,19 @@ int WIN_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window)
 #ifndef SDL_DISABLE_WINDOWS_IME
     HWND hwnd = window->driverdata->hwnd;
     SDL_VideoData *videodata = _this->driverdata;
-    IME_Init(videodata, hwnd);
+    IME_Init(videodata, window);
     IME_Disable(videodata, hwnd);
 #endif /* !SDL_DISABLE_WINDOWS_IME */
 
     return 0;
 }
 
-int WIN_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window)
+int WIN_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window)
 {
 #ifndef SDL_DISABLE_WINDOWS_IME
     SDL_VideoData *data = _this->driverdata;
 
-    IME_SetTextInputRect(data, &window->text_input_rect);
+    IME_SetTextInputArea(data, &window->text_input_rect, window->text_input_cursor);
 #endif /* !SDL_DISABLE_WINDOWS_IME */
 
     return 0;
@@ -313,7 +313,7 @@ DEFINE_GUID(IID_ITfThreadMgrEx, 0x3E90ADE3, 0x7594, 0x4CB0, 0xBB, 0x58, 0x69, 0x
 
 static void IME_UpdateInputLocale(SDL_VideoData *videodata);
 static void IME_ClearComposition(SDL_VideoData *videodata);
-static void IME_SetWindow(SDL_VideoData *videodata, HWND hwnd);
+static void IME_SetWindow(SDL_VideoData *videodata, SDL_Window *window);
 static void IME_SetupAPI(SDL_VideoData *videodata);
 static DWORD IME_GetId(SDL_VideoData *videodata, UINT uIndex);
 static void IME_SendEditingEvent(SDL_VideoData *videodata);
@@ -329,8 +329,9 @@ static SDL_bool WIN_ShouldShowNativeUI()
     return SDL_GetHintBoolean(SDL_HINT_IME_SHOW_UI, SDL_TRUE);
 }
 
-static int IME_Init(SDL_VideoData *videodata, HWND hwnd)
+static int IME_Init(SDL_VideoData *videodata, SDL_Window *window)
 {
+    HWND hwnd = window->driverdata->hwnd;
     HRESULT hResult = S_OK;
 
     if (videodata->ime_initialized) {
@@ -360,7 +361,7 @@ static int IME_Init(SDL_VideoData *videodata, HWND hwnd)
     videodata->ImmUnlockIMCC = (BOOL (WINAPI *)(HIMCC))SDL_LoadFunction(videodata->ime_himm32, "ImmUnlockIMCC");
     /* *INDENT-ON* */ /* clang-format on */
 
-    IME_SetWindow(videodata, hwnd);
+    IME_SetWindow(videodata, window);
     videodata->ime_himc = ImmGetContext(hwnd);
     ImmReleaseContext(hwnd, videodata->ime_himc);
     if (!videodata->ime_himc) {
@@ -678,9 +679,16 @@ static void IME_SetupAPI(SDL_VideoData *videodata)
     }
 }
 
-static void IME_SetWindow(SDL_VideoData *videodata, HWND hwnd)
+static void IME_SetWindow(SDL_VideoData *videodata, SDL_Window *window)
 {
-    videodata->ime_hwnd_current = hwnd;
+    HWND hwnd = window->driverdata->hwnd;
+
+    if (hwnd != videodata->ime_hwnd_current) {
+        videodata->ime_hwnd_current = hwnd;
+        SDL_zero(videodata->ime_composition_area);
+        SDL_zero(videodata->ime_candidate_area);
+    }
+
     if (videodata->ime_threadmgr) {
         struct ITfDocumentMgr *document_mgr = 0;
         if (SUCCEEDED(videodata->ime_threadmgr->lpVtbl->AssociateFocus(videodata->ime_threadmgr, hwnd, NULL, &document_mgr))) {
@@ -689,42 +697,45 @@ static void IME_SetWindow(SDL_VideoData *videodata, HWND hwnd)
             }
         }
     }
-    IME_SetTextInputRect(videodata, &videodata->ime_rect);
+
+    IME_SetTextInputArea(videodata, &window->text_input_rect, window->text_input_cursor);
 }
 
-static void IME_SetTextInputRect(SDL_VideoData *videodata, const SDL_Rect *rect)
+static void IME_SetTextInputArea(SDL_VideoData *videodata, const SDL_Rect *rect, int cursor)
 {
-    HIMC himc = 0;
-
-    if (SDL_memcmp(rect, &videodata->ime_rect, sizeof(*rect)) == 0) {
-        return;
-    }
-
-    videodata->ime_rect = *rect;
+    HIMC himc;
 
     himc = ImmGetContext(videodata->ime_hwnd_current);
     if (himc) {
         COMPOSITIONFORM cof;
         CANDIDATEFORM caf;
 
+        SDL_zero(cof);
         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);
+        cof.ptCurrentPos.x = rect->x + cursor;
+        cof.ptCurrentPos.y = rect->y;
+        cof.rcArea.left = rect->x;
+        cof.rcArea.right = (LONG)rect->x + rect->w;
+        cof.rcArea.top = rect->y;
+        cof.rcArea.bottom = (LONG)rect->y + rect->h;
+        if (SDL_memcmp(&cof, &videodata->ime_composition_area, sizeof(cof)) != 0) {
+            SDL_copyp(&videodata->ime_composition_area, &cof);
+            ImmSetCompositionWindow(himc, &cof);
+        }
 
+        SDL_zero(caf);
         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);
+        caf.ptCurrentPos.x = rect->x + cursor;
+        caf.ptCurrentPos.y = rect->y;
+        caf.rcArea.left = rect->x;
+        caf.rcArea.right = (LONG)rect->x + rect->w;
+        caf.rcArea.top = rect->y;
+        caf.rcArea.bottom = (LONG)rect->y + rect->h;
+        if (SDL_memcmp(&caf, &videodata->ime_candidate_area, sizeof(caf)) != 0) {
+            SDL_copyp(&videodata->ime_candidate_area, &caf);
+            ImmSetCandidateWindow(himc, &caf);
+        }
 
         ImmReleaseContext(videodata->ime_hwnd_current, himc);
     }

+ 1 - 1
src/video/windows/SDL_windowskeyboard.h

@@ -31,7 +31,7 @@ extern void WIN_ResetDeadKeys(void);
 
 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_UpdateTextInputArea(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);

+ 2 - 2
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->UpdateTextInputRect = WIN_UpdateTextInputRect;
+    device->UpdateTextInputArea = WIN_UpdateTextInputArea;
     device->ClearComposition = WIN_ClearComposition;
 
     device->SetClipboardData = WIN_SetClipboardData;
@@ -281,7 +281,7 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
 
     device->StartTextInput = GDK_StartTextInput;
     device->StopTextInput = GDK_StopTextInput;
-    device->SetTextInputRect = GDK_SetTextInputRect;
+    device->SetTextInputArea = GDK_SetTextInputArea;
     device->ClearComposition = GDK_ClearComposition;
 
     device->HasScreenKeyboardSupport = GDK_HasScreenKeyboardSupport;

+ 2 - 1
src/video/windows/SDL_windowsvideo.h

@@ -447,7 +447,8 @@ struct SDL_VideoData
     int ime_candlistindexbase;
     SDL_bool ime_horizontal_candidates;
 
-    SDL_Rect ime_rect;
+    COMPOSITIONFORM ime_composition_area;
+    CANDIDATEFORM ime_candidate_area;
 
     HKL ime_hkl;
     void *ime_himm32;

+ 1 - 1
src/video/x11/SDL_x11events.c

@@ -1293,7 +1293,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
 #ifdef SDL_USE_IME
                 if (SDL_TextInputActive(data->window)) {
                     /* Update IME candidate list position */
-                    SDL_IME_UpdateTextRect(NULL);
+                    SDL_IME_UpdateTextInputArea(NULL);
                 }
 #endif
                 for (w = data->window->first_child; w; w = w->next_sibling) {

+ 3 - 3
src/video/x11/SDL_x11keyboard.c

@@ -448,7 +448,7 @@ int X11_StartTextInput(SDL_VideoDevice *_this, SDL_Window *window)
 {
     X11_ResetXIM(_this, window);
 
-    return X11_UpdateTextInputRect(_this, window);
+    return X11_UpdateTextInputArea(_this, window);
 }
 
 int X11_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window)
@@ -460,10 +460,10 @@ int X11_StopTextInput(SDL_VideoDevice *_this, SDL_Window *window)
     return 0;
 }
 
-int X11_UpdateTextInputRect(SDL_VideoDevice *_this, SDL_Window *window)
+int X11_UpdateTextInputArea(SDL_VideoDevice *_this, SDL_Window *window)
 {
 #ifdef SDL_USE_IME
-    SDL_IME_UpdateTextRect(window);
+    SDL_IME_UpdateTextInputArea(window);
 #endif
     return 0;
 }

+ 1 - 1
src/video/x11/SDL_x11keyboard.h

@@ -28,7 +28,7 @@ extern void X11_UpdateKeymap(SDL_VideoDevice *_this, SDL_bool send_event);
 extern void X11_QuitKeyboard(SDL_VideoDevice *_this);
 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 int X11_UpdateTextInputArea(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->UpdateTextInputRect = X11_UpdateTextInputRect;
+    device->UpdateTextInputArea = X11_UpdateTextInputArea;
     device->HasScreenKeyboardSupport = X11_HasScreenKeyboardSupport;
     device->ShowScreenKeyboard = X11_ShowScreenKeyboard;
     device->HideScreenKeyboard = X11_HideScreenKeyboard;

+ 6 - 8
test/checkkeys.c

@@ -73,23 +73,21 @@ static void UpdateTextWindowInputRect(SDL_WindowID id)
             SDLTest_TextWindow *textwindow = windowstates[i].textwindow;
             int w, h;
             SDL_Rect rect;
+            int cursor = 0;
             int current = textwindow->current;
             const char *current_line = textwindow->lines[current];
 
             SDL_GetWindowSize(state->windows[i], &w, &h);
 
-            rect.x = (int)TEXT_WINDOW_OFFSET_X;
             if (current_line) {
-                rect.x += (int)SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE;
+                cursor = (int)SDL_utf8strlen(current_line) * FONT_CHARACTER_SIZE;
             }
+
+            rect.x = (int)TEXT_WINDOW_OFFSET_X;
             rect.y = (int)TEXT_WINDOW_OFFSET_Y + current * FONT_LINE_HEIGHT;
-#if 1
-            rect.w = FONT_CHARACTER_SIZE;
-#else
             rect.w = (int)(w - (2 * TEXT_WINDOW_OFFSET_X));
-#endif
-            rect.h = FONT_LINE_HEIGHT;
-            SDL_SetTextInputRect(state->windows[i], &rect);
+            rect.h = FONT_CHARACTER_SIZE;
+            SDL_SetTextInputArea(state->windows[i], &rect, cursor);
             return;
         }
     }

+ 25 - 25
test/testautomation_keyboard.c

@@ -361,14 +361,14 @@ static int keyboard_startStopTextInput(void *arg)
     return TEST_COMPLETED;
 }
 
-/* Internal function to test SDL_SetTextInputRect */
-static void testSetTextInputRect(SDL_Window *window, SDL_Rect refRect)
+/* Internal function to test SDL_SetTextInputArea */
+static void testSetTextInputArea(SDL_Window *window, SDL_Rect refRect)
 {
     SDL_Rect testRect;
 
     testRect = refRect;
-    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);
+    SDL_SetTextInputArea(window, &testRect, 0);
+    SDLTest_AssertPass("Call to SDL_SetTextInputArea 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),
         "Check that input data was not modified, expected: x:%d,y:%d,w:%d,h:%d, got: x:%d,y:%d,w:%d,h:%d",
@@ -377,11 +377,11 @@ static void testSetTextInputRect(SDL_Window *window, SDL_Rect refRect)
 }
 
 /**
- * Check call to SDL_SetTextInputRect
+ * Check call to SDL_SetTextInputArea
  *
- * \sa SDL_SetTextInputRect
+ * \sa SDL_SetTextInputArea
  */
-static int keyboard_setTextInputRect(void *arg)
+static int keyboard_setTextInputArea(void *arg)
 {
     SDL_Window *window = SDL_GetKeyboardFocus();
     SDL_Rect refRect;
@@ -391,77 +391,77 @@ 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(window, refRect);
+    testSetTextInputArea(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(window, refRect);
+    testSetTextInputArea(window, refRect);
 
     /* 1Pixel refRect */
     refRect.x = SDLTest_RandomIntegerInRange(10, 50);
     refRect.y = SDLTest_RandomIntegerInRange(10, 50);
     refRect.w = 1;
     refRect.h = 1;
-    testSetTextInputRect(window, refRect);
+    testSetTextInputArea(window, refRect);
 
     /* 0pixel refRect */
     refRect.x = 1;
     refRect.y = 1;
     refRect.w = 1;
     refRect.h = 0;
-    testSetTextInputRect(window, refRect);
+    testSetTextInputArea(window, refRect);
 
     /* 0pixel refRect */
     refRect.x = 1;
     refRect.y = 1;
     refRect.w = 0;
     refRect.h = 1;
-    testSetTextInputRect(window, refRect);
+    testSetTextInputArea(window, refRect);
 
     /* 0pixel refRect */
     refRect.x = 1;
     refRect.y = 1;
     refRect.w = 0;
     refRect.h = 0;
-    testSetTextInputRect(window, refRect);
+    testSetTextInputArea(window, refRect);
 
     /* 0pixel refRect */
     refRect.x = 0;
     refRect.y = 0;
     refRect.w = 0;
     refRect.h = 0;
-    testSetTextInputRect(window, refRect);
+    testSetTextInputArea(window, refRect);
 
     /* negative refRect */
     refRect.x = SDLTest_RandomIntegerInRange(-200, -100);
     refRect.y = SDLTest_RandomIntegerInRange(-200, -100);
     refRect.w = 50;
     refRect.h = 50;
-    testSetTextInputRect(window, refRect);
+    testSetTextInputArea(window, refRect);
 
     /* oversized refRect */
     refRect.x = SDLTest_RandomIntegerInRange(1, 50);
     refRect.y = SDLTest_RandomIntegerInRange(1, 50);
     refRect.w = 5000;
     refRect.h = 5000;
-    testSetTextInputRect(window, refRect);
+    testSetTextInputArea(window, refRect);
 
     /* NULL refRect */
-    SDL_SetTextInputRect(window, NULL);
-    SDLTest_AssertPass("Call to SDL_SetTextInputRect(NULL)");
+    SDL_SetTextInputArea(window, NULL, 0);
+    SDLTest_AssertPass("Call to SDL_SetTextInputArea(NULL)");
 
     return TEST_COMPLETED;
 }
 
 /**
- * Check call to SDL_SetTextInputRect with invalid data
+ * Check call to SDL_SetTextInputArea with invalid data
  *
- * \sa SDL_SetTextInputRect
+ * \sa SDL_SetTextInputArea
  */
-static int keyboard_setTextInputRectNegative(void *arg)
+static int keyboard_setTextInputAreaNegative(void *arg)
 {
     /* Some platforms set also an error message; prepare for checking it */
 #if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_ANDROID) || defined(SDL_VIDEO_DRIVER_COCOA)
@@ -473,8 +473,8 @@ static int keyboard_setTextInputRectNegative(void *arg)
 #endif
 
     /* NULL refRect */
-    SDL_SetTextInputRect(SDL_GetKeyboardFocus(), NULL);
-    SDLTest_AssertPass("Call to SDL_SetTextInputRect(NULL)");
+    SDL_SetTextInputArea(SDL_GetKeyboardFocus(), NULL, 0);
+    SDLTest_AssertPass("Call to SDL_SetTextInputArea(NULL)");
 
     /* Some platforms set also an error message; so check it */
 #if defined(SDL_VIDEO_DRIVER_WINDOWS) || defined(SDL_VIDEO_DRIVER_ANDROID) || defined(SDL_VIDEO_DRIVER_COCOA)
@@ -666,11 +666,11 @@ static const SDLTest_TestCaseReference keyboardTest7 = {
 };
 
 static const SDLTest_TestCaseReference keyboardTest8 = {
-    (SDLTest_TestCaseFp)keyboard_setTextInputRect, "keyboard_setTextInputRect", "Check call to SDL_SetTextInputRect", TEST_ENABLED
+    (SDLTest_TestCaseFp)keyboard_setTextInputArea, "keyboard_setTextInputArea", "Check call to SDL_SetTextInputArea", TEST_ENABLED
 };
 
 static const SDLTest_TestCaseReference keyboardTest9 = {
-    (SDLTest_TestCaseFp)keyboard_setTextInputRectNegative, "keyboard_setTextInputRectNegative", "Check call to SDL_SetTextInputRect with invalid data", TEST_ENABLED
+    (SDLTest_TestCaseFp)keyboard_setTextInputAreaNegative, "keyboard_setTextInputAreaNegative", "Check call to SDL_SetTextInputArea with invalid data", TEST_ENABLED
 };
 
 static const SDLTest_TestCaseReference keyboardTest10 = {

+ 19 - 11
test/testime.c

@@ -457,6 +457,8 @@ static Uint32 utf8_decode(char *p, size_t len)
 
 static void InitInput(void)
 {
+    int i;
+
     /* Prepare a rect for text input */
     textRect.x = textRect.y = 100.0f;
     textRect.w = DEFAULT_WINDOW_WIDTH - 2 * textRect.x;
@@ -466,7 +468,9 @@ static void InitInput(void)
     markedRect = textRect;
     markedText[0] = 0;
 
-    SDL_StartTextInput(state->windows[0]);
+    for (i = 0; i < state->num_windows; ++i) {
+        SDL_StartTextInput(state->windows[i]);
+    }
 }
 
 
@@ -649,6 +653,18 @@ static void DrawCandidates(int rendererID, SDL_FRect *cursorRect)
     }
 }
 
+static void UpdateTextInputArea(SDL_Window *window, const SDL_FRect *cursorRect)
+{
+    SDL_Rect rect;
+    int cursor_offset = (int)(cursorRect->x - textRect.x);
+
+    rect.x = (int)textRect.x;
+    rect.y = (int)textRect.y;
+    rect.w = (int)textRect.w;
+    rect.h = (int)textRect.h;
+    SDL_SetTextInputArea(window, &rect, cursor_offset);
+}
+
 static void CleanupVideo(void)
 {
     SDL_StopTextInput(state->windows[0]);
@@ -827,16 +843,8 @@ static void RedrawWindow(int rendererID)
     /* Draw the candidates */
     DrawCandidates(rendererID, &cursorRect);
 
-    {
-        SDL_Rect inputrect;
-
-        /* The input rect is a square at the cursor insertion point */
-        inputrect.x = (int)cursorRect.x;
-        inputrect.y = (int)cursorRect.y;
-        inputrect.w = (int)cursorRect.h;
-        inputrect.h = (int)cursorRect.h;
-        SDL_SetTextInputRect(state->windows[0], &inputrect);
-    }
+    /* Update the area used to draw composition UI */
+    UpdateTextInputArea(state->windows[0], &cursorRect);
 }
 
 static void Redraw(void)