Sfoglia il codice sorgente

SDL_HINT_IME_INTERNAL_EDITING and SDL_HINT_IME_SHOW_UI are replaced with SDL_HINT_IME_NATIVE_UI

Sam Lantinga 9 mesi fa
parent
commit
4c7db129df

+ 2 - 0
docs/README-migration.md

@@ -757,6 +757,8 @@ The following hints have been removed:
 * SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS - gamepad buttons are always positional
 * SDL_HINT_GRAB_KEYBOARD - use SDL_SetWindowKeyboardGrab() instead
 * SDL_HINT_IDLE_TIMER_DISABLED - use SDL_DisableScreenSaver() instead
+* SDL_HINT_IME_INTERNAL_EDITING - replaced with SDL_HINT_IME_NATIVE_UI
+* SDL_HINT_IME_SHOW_UI - replaced with SDL_HINT_IME_NATIVE_UI
 * SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text
 * SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer
 * SDL_HINT_PS2_DYNAMIC_VSYNC - use SDL_SetRenderVSync(renderer, -1) instead

+ 10 - 21
include/SDL3/SDL_hints.h

@@ -943,37 +943,26 @@ extern "C" {
 #define SDL_HINT_HIDAPI_IGNORE_DEVICES "SDL_HIDAPI_IGNORE_DEVICES"
 
 /**
- * A variable to control whether certain IMEs should handle text editing
- * internally instead of sending SDL_EVENT_TEXT_EDITING events.
+ * A variable describing what IME elements the OS should render natively over the game.
  *
- * The variable can be set to the following values:
- *
- * - "0": SDL_EVENT_TEXT_EDITING events are sent, and it is the application's
- *   responsibility to render the text from these events and differentiate it
- *   somehow from committed text. (default)
- * - "1": If supported by the IME then SDL_EVENT_TEXT_EDITING events are not
- *   sent, and text that is being composed will be rendered in its own UI.
+ * By default IME UI is handled using native components by the OS, however this interferes with fullscreen games in some cases.
  *
- * This hint can be set anytime.
+ * The variable can be set to a comma separated list containing the following items:
  *
- * \since This hint is available since SDL 3.0.0.
- */
-#define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING"
-
-/**
- * A variable to control whether certain IMEs should show native UI components
- * (such as the Candidate List) instead of suppressing them.
+ * - "none" or "0": Native UI elements will not be displayed.
+ * - "composition": Native UI elements will be used for the IME composition string.
+ * - "candidates": Native UI elements will be used for the IME candidate list.
+ * - "all" or "1": Native UI elements will be used for all IME UI. (default)
  *
- * The variable can be set to the following values:
+ * If native UI is used for the composition string, then SDL_EVENT_TEXT_EDITING will not be sent.
  *
- * - "0": Native UI components are not display.
- * - "1": Native UI components are displayed. (default)
+ * If native UI is used for the candidates list, then SDL_EVENT_TEXT_EDITING_CANDIDATES will not be sent.
  *
  * This hint should be set before SDL is initialized.
  *
  * \since This hint is available since SDL 3.0.0.
  */
-#define SDL_HINT_IME_SHOW_UI "SDL_IME_SHOW_UI"
+#define SDL_HINT_IME_NATIVE_UI "SDL_IME_NATIVE_UI"
 
 /**
  * A variable controlling whether the home indicator bar on iPhone X should be

+ 12 - 5
src/core/linux/SDL_fcitx.c

@@ -229,7 +229,7 @@ static void FcitxClientICCallMethod(FcitxClient *client, const char *method)
 static void SDLCALL Fcitx_SetCapabilities(void *data,
                                           const char *name,
                                           const char *old_val,
-                                          const char *internal_editing)
+                                          const char *hint)
 {
     FcitxClient *client = (FcitxClient *)data;
     Uint64 caps = 0;
@@ -237,9 +237,16 @@ static void SDLCALL Fcitx_SetCapabilities(void *data,
         return;
     }
 
-    if (!(internal_editing && *internal_editing == '1')) {
-        caps |= (1 << 1); /* Preedit Flag */
-        caps |= (1 << 4); /* Formatted Preedit Flag */
+    if (!hint || !*hint || *hint == '1' || SDL_strstr(hint, "all")) {
+        // Let the OS handle IME UI
+    } else {
+        if (!SDL_strstr(hint, "composition")) {
+            caps |= (1 << 1); /* Preedit Flag */
+            caps |= (1 << 4); /* Formatted Preedit Flag */
+        }
+        if (!SDL_strstr(hint, "candidates")) {
+            // FIXME, turn off native candidate rendering
+        }
     }
 
     SDL_DBus_CallVoidMethod(FCITX_DBUS_SERVICE, client->ic_path, FCITX_IC_DBUS_INTERFACE, "SetCapability", DBUS_TYPE_UINT64, &caps, DBUS_TYPE_INVALID);
@@ -300,7 +307,7 @@ static SDL_bool FcitxClientCreateIC(FcitxClient *client)
                                     NULL);
         dbus->connection_flush(dbus->session_conn);
 
-        SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, Fcitx_SetCapabilities, client);
+        SDL_AddHintCallback(SDL_HINT_IME_NATIVE_UI, Fcitx_SetCapabilities, client);
         return SDL_TRUE;
     }
 

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

@@ -404,14 +404,22 @@ static char *IBus_GetDBusAddressFilename(void)
 static SDL_bool IBus_CheckConnection(SDL_DBusContext *dbus);
 
 static void SDLCALL IBus_SetCapabilities(void *data, const char *name, const char *old_val,
-                                         const char *internal_editing)
+                                         const char *hint)
 {
     SDL_DBusContext *dbus = SDL_DBus_GetContext();
 
     if (IBus_CheckConnection(dbus)) {
         Uint32 caps = IBUS_CAP_FOCUS;
-        if (!(internal_editing && *internal_editing == '1')) {
-            caps |= IBUS_CAP_PREEDIT_TEXT;
+
+        if (!hint || !*hint || *hint == '1' || SDL_strstr(hint, "all")) {
+            // Let the OS handle IME UI
+        } else {
+            if (!SDL_strstr(hint, "composition")) {
+                caps |= IBUS_CAP_PREEDIT_TEXT;
+            }
+            if (!SDL_strstr(hint, "candidates")) {
+                // FIXME, turn off native candidate rendering
+            }
         }
 
         SDL_DBus_CallVoidMethodOnConnection(ibus_conn, ibus_service, input_ctx_path, ibus_input_interface, "SetCapabilities",
@@ -474,7 +482,7 @@ static SDL_bool IBus_SetupConnection(SDL_DBusContext *dbus, const char *addr)
         (void)SDL_snprintf(matchstr, sizeof(matchstr), "type='signal',interface='%s'", ibus_input_interface);
         SDL_free(input_ctx_path);
         input_ctx_path = SDL_strdup(path);
-        SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, IBus_SetCapabilities, NULL);
+        SDL_AddHintCallback(SDL_HINT_IME_NATIVE_UI, IBus_SetCapabilities, NULL);
         dbus->bus_add_match(ibus_conn, matchstr, NULL);
         dbus->connection_try_register_object_path(ibus_conn, input_ctx_path, &ibus_vtable, dbus, NULL);
         dbus->connection_flush(ibus_conn);
@@ -631,7 +639,7 @@ void SDL_IBus_Quit(void)
 
     /* !!! FIXME: should we close(inotify_fd) here? */
 
-    SDL_DelHintCallback(SDL_HINT_IME_INTERNAL_EDITING, IBus_SetCapabilities, NULL);
+    SDL_DelHintCallback(SDL_HINT_IME_NATIVE_UI, IBus_SetCapabilities, NULL);
 
     SDL_memset(&ibus_cursor_rect, 0, sizeof(ibus_cursor_rect));
 }

+ 62 - 39
src/video/windows/SDL_windowskeyboard.c

@@ -306,11 +306,6 @@ static DWORD IME_GetId(SDL_VideoData *videodata, UINT uIndex);
 static void IME_SendEditingEvent(SDL_VideoData *videodata);
 static void IME_SendClearComposition(SDL_VideoData *videodata);
 
-static SDL_bool WIN_ShouldShowNativeUI()
-{
-    return SDL_GetHintBoolean(SDL_HINT_IME_SHOW_UI, SDL_TRUE);
-}
-
 static int IME_Init(SDL_VideoData *videodata, SDL_Window *window)
 {
     HWND hwnd = window->driverdata->hwnd;
@@ -319,6 +314,19 @@ static int IME_Init(SDL_VideoData *videodata, SDL_Window *window)
         return 0;
     }
 
+    const char *hint = SDL_GetHint(SDL_HINT_IME_NATIVE_UI);
+    if (!hint || !*hint || *hint == '1' || SDL_strstr(hint, "all")) {
+        videodata->ime_native_composition = SDL_TRUE;
+        videodata->ime_native_candidates = SDL_TRUE;
+    } else {
+        if (SDL_strstr(hint, "composition")) {
+            videodata->ime_native_composition = SDL_TRUE;
+        }
+        if (SDL_strstr(hint, "candidates")) {
+            videodata->ime_native_candidates = SDL_TRUE;
+        }
+    }
+
     videodata->ime_hwnd_main = hwnd;
     videodata->ime_initialized = SDL_TRUE;
     videodata->ime_himm32 = SDL_LoadObject("imm32.dll");
@@ -345,11 +353,6 @@ static int IME_Init(SDL_VideoData *videodata, SDL_Window *window)
     videodata->ime_available = SDL_TRUE;
     IME_UpdateInputLocale(videodata);
     IME_SetupAPI(videodata);
-    if (WIN_ShouldShowNativeUI()) {
-        videodata->ime_uiless = SDL_FALSE;
-    } else {
-        videodata->ime_uiless = SDL_TRUE;
-    }
     IME_UpdateInputLocale(videodata);
     IME_Disable(videodata, hwnd);
     return 0;
@@ -541,7 +544,8 @@ static DWORD IME_GetId(SDL_VideoData *videodata, UINT uIndex)
 
     SDL_assert(uIndex == 0);
     dwLang = ((DWORD_PTR)hkl & 0xffff);
-    if (videodata->ime_uiless && dwLang == LANG_CHT) {
+    // FIXME: What does this do?
+    if (!videodata->ime_native_candidates && dwLang == LANG_CHT) {
         dwRet[0] = IMEID_CHT_VER_VISTA;
         dwRet[1] = 0;
         return dwRet[0];
@@ -972,9 +976,21 @@ SDL_bool WIN_HandleIMEMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam
 
     if (msg == WM_IME_SETCONTEXT) {
         SDL_DebugIMELog("WM_IME_SETCONTEXT\n");
-        if (videodata->ime_uiless) {
-            *lParam = 0;
+
+        LPARAM element_mask;
+        if (!videodata->ime_native_composition && !videodata->ime_native_candidates) {
+            element_mask = 0;
+        } else {
+            element_mask = ISC_SHOWUIALL;
+            if (!videodata->ime_native_composition) {
+                element_mask &= ~ISC_SHOWUICOMPOSITIONWINDOW;
+            }
+            if (!videodata->ime_native_candidates) {
+                element_mask &= ~ISC_SHOWUIALLCANDIDATEWINDOW;
+            }
         }
+        *lParam &= element_mask;
+
         return SDL_FALSE;
     }
 
@@ -997,34 +1013,41 @@ SDL_bool WIN_HandleIMEMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam
         break;
     case WM_IME_STARTCOMPOSITION:
         SDL_DebugIMELog("WM_IME_STARTCOMPOSITION\n");
-        trap = SDL_TRUE;
+        if (!videodata->ime_native_composition) {
+            trap = SDL_TRUE;
+        }
         break;
     case WM_IME_COMPOSITION:
         SDL_DebugIMELog("WM_IME_COMPOSITION %x\n", lParam);
-        trap = SDL_TRUE;
-        himc = ImmGetContext(hwnd);
-        if (*lParam & GCS_RESULTSTR) {
-            SDL_DebugIMELog("GCS_RESULTSTR\n");
-            IME_GetCompositionString(videodata, himc, GCS_RESULTSTR);
-            IME_SendClearComposition(videodata);
-            IME_SendInputEvent(videodata);
-        }
-        if (*lParam & GCS_COMPSTR) {
-            SDL_DebugIMELog("GCS_COMPSTR\n");
-            videodata->ime_readingstring[0] = 0;
-            IME_GetCompositionString(videodata, himc, GCS_COMPSTR);
-            IME_SendEditingEvent(videodata);
+        if (!videodata->ime_native_composition) {
+            trap = SDL_TRUE;
+            himc = ImmGetContext(hwnd);
+            if (*lParam & GCS_RESULTSTR) {
+                SDL_DebugIMELog("GCS_RESULTSTR\n");
+                IME_GetCompositionString(videodata, himc, GCS_RESULTSTR);
+                IME_SendClearComposition(videodata);
+                IME_SendInputEvent(videodata);
+            }
+            if (*lParam & GCS_COMPSTR) {
+                SDL_DebugIMELog("GCS_COMPSTR\n");
+                videodata->ime_readingstring[0] = 0;
+                IME_GetCompositionString(videodata, himc, GCS_COMPSTR);
+                IME_SendEditingEvent(videodata);
+            }
+            ImmReleaseContext(hwnd, himc);
         }
-        ImmReleaseContext(hwnd, himc);
         break;
     case WM_IME_ENDCOMPOSITION:
         SDL_DebugIMELog("WM_IME_ENDCOMPOSITION\n");
-        videodata->ime_composition[0] = 0;
-        videodata->ime_readingstring[0] = 0;
-        videodata->ime_cursor = 0;
-        videodata->ime_selected_start = 0;
-        videodata->ime_selected_length = 0;
-        IME_SendClearComposition(videodata);
+        if (!videodata->ime_native_composition) {
+            trap = SDL_TRUE;
+            videodata->ime_composition[0] = 0;
+            videodata->ime_readingstring[0] = 0;
+            videodata->ime_cursor = 0;
+            videodata->ime_selected_start = 0;
+            videodata->ime_selected_length = 0;
+            IME_SendClearComposition(videodata);
+        }
         break;
     case WM_IME_NOTIFY:
         SDL_DebugIMELog("WM_IME_NOTIFY %x\n", wParam);
@@ -1043,24 +1066,24 @@ SDL_bool WIN_HandleIMEMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam
         case IMN_OPENCANDIDATE:
         case IMN_CHANGECANDIDATE:
             SDL_DebugIMELog("%s\n", wParam == IMN_OPENCANDIDATE ? "IMN_OPENCANDIDATE" : "IMN_CHANGECANDIDATE");
-            if (videodata->ime_uiless) {
-                videodata->ime_update_candidates = SDL_TRUE;
+            if (!videodata->ime_native_candidates) {
                 trap = SDL_TRUE;
+                videodata->ime_update_candidates = SDL_TRUE;
             }
             break;
         case IMN_CLOSECANDIDATE:
             SDL_DebugIMELog("IMN_CLOSECANDIDATE\n");
-            if (videodata->ime_uiless) {
+            if (!videodata->ime_native_candidates) {
+                trap = SDL_TRUE;
                 videodata->ime_update_candidates = SDL_FALSE;
                 IME_CloseCandidateList(videodata);
-                trap = SDL_TRUE;
             }
             break;
         case IMN_PRIVATE:
         {
             DWORD dwId = IME_GetId(videodata, 0);
-            IME_GetReadingString(videodata, hwnd);
             SDL_DebugIMELog("IMN_PRIVATE %u\n", dwId);
+            IME_GetReadingString(videodata, hwnd);
             switch (dwId) {
             case IMEID_CHT_VER42:
             case IMEID_CHT_VER43:

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

@@ -339,7 +339,6 @@ typedef struct
     void *data;
 } TSFSink;
 
-#ifndef SDL_DISABLE_WINDOWS_IME
 /* Definition from Win98DDK version of IMM.H */
 typedef struct tagINPUTCONTEXT2
 {
@@ -365,7 +364,6 @@ typedef struct tagINPUTCONTEXT2
     DWORD fdwInit;
     DWORD dwReserve[3];
 } INPUTCONTEXT2, *PINPUTCONTEXT2, NEAR *NPINPUTCONTEXT2, FAR *LPINPUTCONTEXT2;
-#endif /* !SDL_DISABLE_WINDOWS_IME */
 
 /* Private display data */
 
@@ -461,7 +459,8 @@ struct SDL_VideoData
     BOOL (WINAPI *ImmUnlockIMCC)(HIMCC himcc);
     /* *INDENT-ON* */ /* clang-format on */
 
-    SDL_bool ime_uiless;
+    SDL_bool ime_native_composition;
+    SDL_bool ime_native_candidates;
 #endif /* !SDL_DISABLE_WINDOWS_IME */
 
     BYTE pre_hook_key_state[256];

+ 18 - 3
test/testime.c

@@ -867,6 +867,8 @@ static void Redraw(void)
 
 int main(int argc, char *argv[])
 {
+    SDL_bool native_composition = SDL_TRUE;
+    SDL_bool native_candidates = SDL_TRUE;
     int i, done;
     SDL_Event event;
     char *fontname = NULL;
@@ -890,12 +892,15 @@ int main(int argc, char *argv[])
                 fontname = argv[i + 1];
                 consumed = 2;
             }
-        } else if (SDL_strcmp(argv[i], "--disable-ui") == 0) {
-            SDL_SetHint(SDL_HINT_IME_SHOW_UI, "0");
+        } else if (SDL_strcmp(argv[i], "--disable-native-composition") == 0) {
+            native_composition = SDL_FALSE;
+            consumed = 1;
+        } else if (SDL_strcmp(argv[i], "--disable-native-candidates") == 0) {
+            native_candidates = SDL_FALSE;
             consumed = 1;
         }
         if (consumed <= 0) {
-            static const char *options[] = { "[--font fontfile] [--disable-ui]", NULL };
+            static const char *options[] = { "[--font fontfile] [--disable-native-composition] [--disable-native-candidates]", NULL };
             SDLTest_CommonLogUsage(state, argv[0], options);
             return 1;
         }
@@ -903,6 +908,16 @@ int main(int argc, char *argv[])
         i += consumed;
     }
 
+    if (native_composition && native_candidates) {
+        SDL_SetHint(SDL_HINT_IME_NATIVE_UI, "1");
+    } else if (native_composition) {
+        SDL_SetHint(SDL_HINT_IME_NATIVE_UI, "composition");
+    } else if (native_candidates) {
+        SDL_SetHint(SDL_HINT_IME_NATIVE_UI, "candidates");
+    } else {
+        SDL_SetHint(SDL_HINT_IME_NATIVE_UI, "0");
+    }
+
     if (!SDLTest_CommonInit(state)) {
         return 2;
     }