From 3a90dc3893444bc0811c2181f61fe0673b270a05 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 5 Jan 2022 13:03:48 +0100 Subject: [PATCH] Platform IME: changed io.ImeSetInputScreenPosFn() to io.SetPlatformImeDataFn() API. Ref #2589, #2598, #3108, #3113, #3653, #4642 --- backends/imgui_impl_glfw.cpp | 4 +++- backends/imgui_impl_sdl.cpp | 3 ++- backends/imgui_impl_win32.cpp | 3 ++- docs/CHANGELOG.txt | 11 +++++++++ docs/FAQ.md | 4 ++-- imgui.cpp | 44 +++++++++++++++++++++-------------- imgui.h | 25 +++++++++++++++++--- 7 files changed, 68 insertions(+), 26 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 2c5a6cd86..2504ca877 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -246,8 +246,10 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText; io.ClipboardUserData = bd->Window; + + // Set platform dependent data in viewport #if defined(_WIN32) - io.ImeWindowHandle = (void*)glfwGetWin32Window(bd->Window); + ImGui::GetMainViewport()->PlatformHandleRaw = (void*)glfwGetWin32Window(bd->Window); #endif // Create mouse cursors diff --git a/backends/imgui_impl_sdl.cpp b/backends/imgui_impl_sdl.cpp index b725e0ac2..82561bea1 100644 --- a/backends/imgui_impl_sdl.cpp +++ b/backends/imgui_impl_sdl.cpp @@ -230,11 +230,12 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window) bd->MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); + // Set platform dependent data in viewport #ifdef _WIN32 SDL_SysWMinfo info; SDL_VERSION(&info.version); if (SDL_GetWindowWMInfo(window, &info)) - io.ImeWindowHandle = info.info.win.window; + ImGui::GetMainViewport()->PlatformHandleRaw = (void*)info.info.win.window; #else (void)window; #endif diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index ce8f9d55c..e1444efc2 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -122,7 +122,8 @@ bool ImGui_ImplWin32_Init(void* hwnd) bd->Time = perf_counter; bd->LastMouseCursor = ImGuiMouseCursor_COUNT; - io.ImeWindowHandle = hwnd; + // Set platform dependent data in viewport + ImGui::GetMainViewport()->PlatformHandleRaw = (void*)hwnd; // Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array that we will update during the application lifetime. io.KeyMap[ImGuiKey_Tab] = VK_TAB; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 38b71a1ec..305864e8c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,14 @@ Breaking Changes: - ImGui::TreeAdvanceToLabelPos() -> use ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetTreeNodeToLabelSpacing()); - ImFontAtlas::CustomRect -> use ImFontAtlasCustomRect - ImGuiColorEditFlags_RGB/HSV/HEX -> use ImGuiColorEditFlags_DisplayRGB/HSV/Hex +- Removed io.ImeSetInputScreenPosFn() in favor of more flexible io.SetPlatformImeDataFn() for IME support. + Because this field was mostly only ever used by Dear ImGui internally, not by backends nor the vast majority + of user code, this should only affect a very small fraction for users who are already very IME-aware. +- Obsoleted 'void* io.ImeWindowHandle' in favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. + This removes an incompatibility between 'master' and 'multi-viewports' backends and toward enabling + better support for IME. Updated backends accordingly. Because the old field is set by existing backends, + we are keeping it (marked as obsolete). + Other Changes: @@ -50,6 +58,9 @@ Other Changes: which would makes the draw operation of some backends assert (e.g. Metal with debugging). (#4857) - Tables, ImDrawListSplitter: Fixed erroneously stripping trailing ImDrawList::AddCallback() when submitted in last column or last channel and when there are no other drawing operation. (#4843, #4844) [@hoffstadt] +- Platform IME: changed io.ImeSetInputScreenPosFn() to io.SetPlatformImeDataFn() API, + now taking a ImGuiPlatformImeData structure which we can more easily extend in the future. +- Platform IME: moved io.ImeWindowHandle to GetMainViewport()->PlatformHandleRaw. - Backends: OpenGL3: Fixed a buffer overflow in imgui_impl_opengl3_loader.h init (added in 1.86). (#4468, #4830) [@dymk] It would generally not have noticeable side-effect at runtime but would be detected by runtime checkers. - Backends: Metal: Added Apple Metal C++ API support. (#4824, #4746) [@luigifcruz] diff --git a/docs/FAQ.md b/docs/FAQ.md index 009027c11..f6fc96c49 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -607,8 +607,8 @@ Text input: it is up to your application to pass the right character code by cal The applications in examples/ are doing that. Windows: you can use the WM_CHAR or WM_UNICHAR or WM_IME_CHAR message (depending if your app is built using Unicode or MultiByte mode). You may also use MultiByteToWideChar() or ToUnicode() to retrieve Unicode codepoints from MultiByte characters or keyboard state. -Windows: if your language is relying on an Input Method Editor (IME), you copy the HWND of your window to io.ImeWindowHandle in order for -the default implementation of io.ImeSetInputScreenPosFn() to set your Microsoft IME position correctly. +Windows: if your language is relying on an Input Method Editor (IME), you can write your HWND to ImGui::GetMainViewport()->PlatformHandleRaw +in order for the default the default implementation of io.SetPlatformImeDataFn() to set your Microsoft IME position correctly. ##### [Return to Index](#index) diff --git a/imgui.cpp b/imgui.cpp index 453e6a72e..349a5654d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -386,6 +386,7 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2022/03/05 (1.87) - removed io.ImeSetInputScreenPosFn() in favor of more flexible io.SetPlatformImeDataFn(). Removed 'void* io.ImeWindowHandle' in favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. - 2022/03/01 (1.87) - commented out redirecting functions/enums names that were marked obsolete in 1.69, 1.70, 1.71, 1.72 (March-July 2019) - ImGui::SetNextTreeNodeOpen() -> use ImGui::SetNextItemOpen() - ImGui::GetContentRegionAvailWidth() -> use ImGui::GetContentRegionAvail().x @@ -919,7 +920,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSetti // Platform Dependents default implementation for IO functions static const char* GetClipboardTextFn_DefaultImpl(void* user_data); static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text); -static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); +static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data); namespace ImGui { @@ -1136,8 +1137,7 @@ ImGuiIO::ImGuiIO() GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; ClipboardUserData = NULL; - ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; - ImeWindowHandle = NULL; + SetPlatformImeDataFn = SetPlatformImeDataFn_DefaultImpl; // Input (NB: we already have memset zero the entire structure!) MousePos = ImVec2(-FLT_MAX, -FLT_MAX); @@ -4553,9 +4553,11 @@ void ImGui::EndFrame() ErrorCheckEndFrameSanityChecks(); // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME) - if (g.IO.ImeSetInputScreenPosFn && (g.PlatformImeLastPos.x == FLT_MAX || ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f)) + if (g.IO.SetPlatformImeDataFn && (g.PlatformImeLastPos.x == FLT_MAX || ImLengthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f)) { - g.IO.ImeSetInputScreenPosFn((int)g.PlatformImePos.x, (int)g.PlatformImePos.y); + ImGuiPlatformImeData data; + data.InputPos = g.PlatformImePos; + g.IO.SetPlatformImeDataFn(GetMainViewport(), &data); g.PlatformImeLastPos = g.PlatformImePos; } @@ -11500,25 +11502,31 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text) #pragma comment(lib, "imm32") #endif -static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y) +static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data) { // Notify OS Input Method Editor of text input position - ImGuiIO& io = ImGui::GetIO(); - if (HWND hwnd = (HWND)io.ImeWindowHandle) - if (HIMC himc = ::ImmGetContext(hwnd)) - { - COMPOSITIONFORM cf; - cf.ptCurrentPos.x = x; - cf.ptCurrentPos.y = y; - cf.dwStyle = CFS_FORCE_POSITION; - ::ImmSetCompositionWindow(himc, &cf); - ::ImmReleaseContext(hwnd, himc); - } + HWND hwnd = (HWND)viewport->PlatformHandleRaw; +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + if (hwnd == 0) + hwnd = (HWND)ImGui::GetIO().ImeWindowHandle; +#endif + if (hwnd == 0) + return; + + if (HIMC himc = ::ImmGetContext(hwnd)) + { + COMPOSITIONFORM cf; + cf.ptCurrentPos.x = (LONG)data->InputPos.x; + cf.ptCurrentPos.y = (LONG)data->InputPos.y; + cf.dwStyle = CFS_FORCE_POSITION; + ::ImmSetCompositionWindow(himc, &cf); + ::ImmReleaseContext(hwnd, himc); + } } #else -static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} +static void SetPlatformImeDataFn_De(int, int) {} #endif diff --git a/imgui.h b/imgui.h index 552137c32..4f7a5333b 100644 --- a/imgui.h +++ b/imgui.h @@ -35,6 +35,7 @@ Index of this file: // [SECTION] Drawing API (ImDrawCallback, ImDrawCmd, ImDrawIdx, ImDrawVert, ImDrawChannel, ImDrawListSplitter, ImDrawFlags, ImDrawListFlags, ImDrawList, ImDrawData) // [SECTION] Font API (ImFontConfig, ImFontGlyph, ImFontGlyphRangesBuilder, ImFontAtlasFlags, ImFontAtlas, ImFont) // [SECTION] Viewports (ImGuiViewportFlags, ImGuiViewport) +// [SECTION] Platform Dependent Interfaces (ImGuiPlatformImeData) // [SECTION] Obsolete functions and types */ @@ -64,7 +65,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.87 WIP" -#define IMGUI_VERSION_NUM 18602 +#define IMGUI_VERSION_NUM 18603 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE @@ -154,6 +155,7 @@ struct ImGuiInputTextCallbackData; // Shared state of InputText() when using cu struct ImGuiListClipper; // Helper to manually clip large list of items struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame struct ImGuiPayload; // User data payload for drag and drop operations +struct ImGuiPlatformImeData; // Platform IME data for io.SetPlatformImeDataFn() function. struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use) struct ImGuiStorage; // Helper for key->value storage struct ImGuiStyle; // Runtime data for styling/colors @@ -1868,8 +1870,12 @@ struct ImGuiIO // Optional: Notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME on Windows) // (default to use native imm32 api on Windows) - void (*ImeSetInputScreenPosFn)(int x, int y); - void* ImeWindowHandle; // = NULL // (Windows) Set this to your HWND to get automatic IME cursor positioning. + void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data); +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + void* ImeWindowHandle; // = NULL // [Obsolete] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning. +#else + void* _UnusedPadding; // Unused field to keep data structure the same size. +#endif //------------------------------------------------------------------ // Input - Fill before calling NewFrame() @@ -2809,6 +2815,9 @@ struct ImGuiViewport ImVec2 WorkPos; // Work Area: Position of the viewport minus task bars, menus bars, status bars (>= Pos) ImVec2 WorkSize; // Work Area: Size of the viewport minus task bars, menu bars, status bars (<= Size) + // Platform/Backend Dependent Data + void* PlatformHandleRaw; // void* to hold lower-level, platform-native window handle (under Win32 this is expected to be a HWND, unused for other platforms) + ImGuiViewport() { memset(this, 0, sizeof(*this)); } // Helpers @@ -2816,6 +2825,16 @@ struct ImGuiViewport ImVec2 GetWorkCenter() const { return ImVec2(WorkPos.x + WorkSize.x * 0.5f, WorkPos.y + WorkSize.y * 0.5f); } }; +//----------------------------------------------------------------------------- +// [SECTION] Platform Dependent Interfaces +//----------------------------------------------------------------------------- + +// (Optional) Support for IME (Input Method Editor) via the io.SetPlatformImeDataFn() function. +struct ImGuiPlatformImeData +{ + ImVec2 InputPos; // Position of the input cursor +}; + //----------------------------------------------------------------------------- // [SECTION] Obsolete functions and types // (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details)