Viewport, Platform: Fixed IME positioning for multi-viewport. Moved API from ImGuiIO to ImGuiPlatformIO. Because it is extremely unlikely to people redefined this API manually the moving-forward-breakage is ok. (#1542)

SDL2 ime support under Win32 never worked properly because of SDL interferences.
docking
omar 7 years ago
parent 376f2aec54
commit cb78e62df9

@ -261,7 +261,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
- viewport: popup/tooltip glitches when appearing near the monitor limits (e.g. opening a menu).
- viewport: platform: introduce getfocus/setfocus api, so e.g. focus flags can be honored, imgui-side ctrl-tab can focus os window, OS alt-tab can focus imgui window etc.
- viewport: store per-viewport/monitor DPI in .ini file so an application reload or main window changing DPI on reload can be properly patched for.
- viewport: IME positioning are wrong.
- viewport: vulkan renderer implementation.
- viewport: need to clarify how to use GetMousePos() from a user point of view.

@ -199,10 +199,6 @@ bool ImGui_ImplAllegro5_Init(ALLEGRO_DISPLAY* display)
io.KeyMap[ImGuiKey_Y] = ALLEGRO_KEY_Y;
io.KeyMap[ImGuiKey_Z] = ALLEGRO_KEY_Z;
#ifdef _WIN32
io.ImeWindowHandle = al_get_win_window_handle(g_Display);
#endif
return true;
}

@ -150,9 +150,6 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
io.SetClipboardTextFn = ImGui_ImplGlfw_SetClipboardText;
io.GetClipboardTextFn = ImGui_ImplGlfw_GetClipboardText;
io.ClipboardUserData = g_Window;
#ifdef _WIN32
io.ImeWindowHandle = glfwGetWin32Window(g_Window);
#endif
g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
@ -500,7 +497,33 @@ static void ImGui_ImplGlfw_SwapBuffers(ImGuiViewport* viewport, void*)
glfwSwapBuffers(data->Window);
}
//--------------------------------------------------------------------------------------------------------
// IME (Input Method Editor) basic support for e.g. Asian language users
//--------------------------------------------------------------------------------------------------------
// We provide a Win32 implementation because this is such a common issue for IME users
#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(__GNUC__)
#define HAS_WIN32_IME 1
#include <imm.h>
#ifdef _MSC_VER
#pragma comment(lib, "imm32")
#endif
static void ImGui_ImplWin32_SetImeInputPos(ImGuiViewport* viewport, ImVec2 pos)
{
COMPOSITIONFORM cf = { CFS_FORCE_POSITION, { (LONG)(pos.x - viewport->Pos.x), (LONG)(pos.y - viewport->Pos.y) }, { 0, 0, 0, 0 } };
if (ImGuiViewportDataGlfw* data = (ImGuiViewportDataGlfw*)viewport->PlatformUserData)
if (HWND hwnd = glfwGetWin32Window(data->Window))
if (HIMC himc = ImmGetContext(hwnd))
ImmSetCompositionWindow(himc, &cf);
}
#else
#define HAS_WIN32_IME 0
#endif
//--------------------------------------------------------------------------------------------------------
// Vulkan support (the Vulkan renderer needs to call a platform-side support function to create the surface)
//--------------------------------------------------------------------------------------------------------
// Avoid including <vulkan.h> so we can build without it
#if GLFW_HAS_VULKAN
#ifndef VULKAN_H_
@ -571,6 +594,9 @@ static void ImGui_ImplGlfw_InitPlatformInterface()
#if GLFW_HAS_VULKAN
platform_io.Platform_CreateVkSurface = ImGui_ImplGlfw_CreateVkSurface;
#endif
#if HAS_WIN32_IME
platform_io.Platform_SetImeInputPos = ImGui_ImplWin32_SetImeInputPos;
#endif
ImGui_ImplGlfw_UpdateMonitors();

@ -170,13 +170,6 @@ bool ImGui_ImplSDL2_Init(SDL_Window* window, void* sdl_gl_context)
g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW);
g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE);
#ifdef _WIN32
SDL_SysWMinfo wmInfo;
SDL_VERSION(&wmInfo.version);
SDL_GetWindowWMInfo(window, &wmInfo);
io.ImeWindowHandle = wmInfo.info.win.window;
#endif
// Our mouse update function expect PlatformHandle to be filled for the main viewport
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
main_viewport->PlatformHandle = (void*)window;

@ -76,8 +76,6 @@ bool ImGui_ImplWin32_Init(void* hwnd)
io.KeyMap[ImGuiKey_Y] = 'Y';
io.KeyMap[ImGuiKey_Z] = 'Z';
io.ImeWindowHandle = g_hWnd;
return true;
}
@ -279,7 +277,7 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa
return 0;
}
// --------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
// DPI handling
// Those in theory should be simple calls but Windows has multiple ways to handle DPI, and most of them
// require recent Windows versions at runtime or recent Windows SDK at compile-time. Neither we want to depend on.
@ -370,9 +368,30 @@ float ImGui_ImplWin32_GetDpiScaleForRect(int x1, int y1, int x2, int y2)
return ImGui_ImplWin32_GetDpiScaleForMonitor(monitor);
}
// --------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
// IME (Input Method Editor) basic support for e.g. Asian language users
//--------------------------------------------------------------------------------------------------------
#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(__GNUC__)
#define HAS_WIN32_IME 1
#include <imm.h>
#ifdef _MSC_VER
#pragma comment(lib, "imm32")
#endif
static void ImGui_ImplWin32_SetImeInputPos(ImGuiViewport* viewport, ImVec2 pos)
{
COMPOSITIONFORM cf = { CFS_FORCE_POSITION,{ (LONG)(pos.x - viewport->Pos.x), (LONG)(pos.y - viewport->Pos.y) },{ 0, 0, 0, 0 } };
if (HWND hwnd = (HWND)viewport->PlatformHandle)
if (HIMC himc = ImmGetContext(hwnd))
ImmSetCompositionWindow(himc, &cf);
}
#else
#define HAS_WIN32_IME 0
#endif
//--------------------------------------------------------------------------------------------------------
// Platform Windows
// --------------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------------
struct ImGuiViewportDataWin32
{
@ -625,6 +644,9 @@ static void ImGui_ImplWin32_InitPlatformInterface()
platform_io.Platform_SetWindowAlpha = ImGui_ImplWin32_SetWindowAlpha;
platform_io.Platform_GetWindowDpiScale = ImGui_ImplWin32_GetWindowDpiScale;
platform_io.Platform_OnChangedViewport = ImGui_ImplWin32_OnChangedViewport; // FIXME-DPI
#if HAS_WIN32_IME
platform_io.Platform_SetImeInputPos = ImGui_ImplWin32_SetImeInputPos;
#endif
// Register main window handle (which is owned by the main application, not by us)
ImGuiViewport* main_viewport = ImGui::GetMainViewport();

@ -262,6 +262,8 @@
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
Also read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2018/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
- 2018/04/09 (1.61) - IM_DELETE() helper function added in 1.60 doesn't clear the input _pointer_ reference, more consistent with expectation and allows passing r-value.
- 2018/03/20 (1.60) - Renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core and only honored by some binding ahead of merging the Nav branch).
- 2018/03/12 (1.60) - Removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now.
@ -617,10 +619,7 @@
Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8.
Text input: it is up to your application to pass the right character code by calling
io.AddInputCharacter(). The applications in examples/ are doing that. For languages relying
on an Input Method Editor (IME), on Windows you can copy the Hwnd of your application in the
io.ImeWindowHandle field. The default implementation of io.ImeSetInputScreenPosFn() will set
your Microsoft IME position correctly.
io.AddInputCharacter(). The applications in examples/ are doing that.
Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
A: - You can create a dummy window. Call SetNextWindowBgAlpha(0.0f), call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flags.
@ -771,7 +770,6 @@ static void SetCurrentViewport(ImGuiViewportP* viewport);
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);
//-----------------------------------------------------------------------------
// Context
@ -907,8 +905,6 @@ ImGuiIO::ImGuiIO()
GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
ClipboardUserData = NULL;
ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
ImeWindowHandle = NULL;
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
RenderDrawListsFn = NULL;
@ -3924,7 +3920,8 @@ void ImGui::NewFrame()
g.MouseCursor = ImGuiMouseCursor_Arrow;
g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1;
g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
g.PlatformImePos = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
g.PlatformImePosViewport = NULL;
// Mouse wheel scrolling, scale
if (g.HoveredWindow && !g.HoveredWindow->Collapsed && (g.IO.MouseWheel != 0.0f || g.IO.MouseWheelH != 0.0f))
@ -4464,10 +4461,11 @@ void ImGui::EndFrame()
return;
// Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
if (g.IO.ImeSetInputScreenPosFn && ImLengthSqr(g.OsImePosRequest - g.OsImePosSet) > 0.0001f)
if (g.PlatformIO.Platform_SetImeInputPos && g.PlatformImePosViewport != NULL && ImLengthSqr(g.PlatformImePos - g.PlatformImeLastPos) > 0.0001f)
{
g.IO.ImeSetInputScreenPosFn((int)g.OsImePosRequest.x, (int)g.OsImePosRequest.y);
g.OsImePosSet = g.OsImePosRequest;
g.PlatformIO.Platform_SetImeInputPos(g.PlatformImePosViewport, g.PlatformImePos);
g.PlatformImeLastPos = g.PlatformImePos;
g.PlatformImePosViewport = NULL;
}
// Hide implicit "Debug" window if it hasn't been used
@ -11316,7 +11314,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
if (is_editable)
g.OsImePosRequest = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize);
{
g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1, cursor_screen_pos.y - g.FontSize);
g.PlatformImePosViewport = window->Viewport;
}
}
else
{
@ -14027,34 +14028,6 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
#endif
// Win32 API IME support (for Asian languages, etc.)
#if defined(_WIN32) && !defined(__GNUC__) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
#include <imm.h>
#ifdef _MSC_VER
#pragma comment(lib, "imm32")
#endif
static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y)
{
// Notify OS Input Method Editor of text input position
if (HWND hwnd = (HWND)GImGui->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);
}
}
#else
static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {}
#endif
//-----------------------------------------------------------------------------
// HELP
//-----------------------------------------------------------------------------

@ -1059,11 +1059,6 @@ struct ImGuiIO
void (*SetClipboardTextFn)(void* user_data, const char* text);
void* ClipboardUserData;
// Optional: notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME in Windows)
// (default to use native imm32 api on Windows)
void (*ImeSetInputScreenPosFn)(int x, int y);
void* ImeWindowHandle; // (Windows) Set this to your HWND to get automatic IME cursor positioning.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// [OBSOLETE] Rendering function, will be automatically called in Render(). Please call your rendering function yourself now! You can obtain the ImDrawData* by calling ImGui::GetDrawData() after Render().
// See example applications if you are unsure of how to implement this.
@ -1896,7 +1891,7 @@ struct ImGuiPlatformIO
// Input - Back-end interface/functions + Monitor List
//------------------------------------------------------------------
// Platform functions (e.g. Win32, GLFW, SDL2)
// (Optional) Platform functions (e.g. Win32, GLFW, SDL2)
void (*Platform_CreateWindow)(ImGuiViewport* vp); // Create a new platform window for the given viewport
void (*Platform_DestroyWindow)(ImGuiViewport* vp);
void (*Platform_ShowWindow)(ImGuiViewport* vp); // Newly created windows are initially hidden so SetWindowPos/Size/Title can be called on them first
@ -1910,16 +1905,17 @@ struct ImGuiPlatformIO
void (*Platform_SwapBuffers)(ImGuiViewport* vp, void* render_arg); // (Optional) Call Present/SwapBuffers (platform side)
float (*Platform_GetWindowDpiScale)(ImGuiViewport* vp); // (Optional) DPI handling: Return DPI scale for this viewport. 1.0f = 96 DPI. (FIXME-DPI)
void (*Platform_OnChangedViewport)(ImGuiViewport* vp); // (Optional) DPI handling: Called during Begin() every time the viewport we are outputting into changes, so back-end has a chance to swap fonts to adjust style.
void (*Platform_SetImeInputPos)(ImGuiViewport* vp, ImVec2 pos); // (Optional) Set IME (Input Method Editor, e.g. for Asian languages) input position, so text preview appears over the imgui input box.
int (*Platform_CreateVkSurface)(ImGuiViewport* vp, ImU64 vk_inst, const void* vk_allocators, ImU64* out_vk_surface); // (Optional) For Renderer to call into Platform code
// Renderer functions (e.g. DirectX, OpenGL3, Vulkan)
// (Optional) Renderer functions (e.g. DirectX, OpenGL3, Vulkan)
void (*Renderer_CreateWindow)(ImGuiViewport* vp); // Create swap chains, frame buffers etc.
void (*Renderer_DestroyWindow)(ImGuiViewport* vp);
void (*Renderer_SetWindowSize)(ImGuiViewport* vp, ImVec2 size); // Resize swap chain, frame buffers etc.
void (*Renderer_RenderWindow)(ImGuiViewport* vp, void* render_arg); // (Optional) Clear targets, Render viewport->DrawData
void (*Renderer_SwapBuffers)(ImGuiViewport* vp, void* render_arg); // (Optional) Call Present/SwapBuffers (renderer side)
// List of monitors (updated by: app/back-end, used by: imgui to clamp popups/tooltips within same monitor and not have them straddle monitors)
// (Optional) List of monitors (updated by: app/back-end, used by: imgui to clamp popups/tooltips within same monitor and not have them straddle monitors)
ImVector<ImGuiPlatformMonitor> Monitors;
//------------------------------------------------------------------

@ -715,7 +715,10 @@ struct ImGuiContext
ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
int TooltipOverrideCount;
ImVector<char> PrivateClipboard; // If no custom clipboard handler is defined
ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor
// Platform support
ImVec2 PlatformImePos, PlatformImeLastPos; // Cursor position request & last passed to the OS Input Method Editor
ImGuiViewport* PlatformImePosViewport;
// Settings
bool SettingsLoaded;
@ -822,7 +825,8 @@ struct ImGuiContext
DragSpeedScaleFast = 10.0f;
ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f);
TooltipOverrideCount = 0;
OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f);
PlatformImePos = PlatformImeLastPos = ImVec2(FLT_MAX, FLT_MAX);
PlatformImePosViewport = 0;
SettingsLoaded = false;
SettingsDirtyTimer = 0.0f;

Loading…
Cancel
Save