update dear imgui from 1.92.2b-docking to 1.92.6-docking

This commit is contained in:
Sven Balzer
2026-04-01 18:20:04 +02:00
parent 3b7d593f4e
commit 1daf4d79f1
127 changed files with 10702 additions and 3505 deletions
+51 -17
View File
@@ -22,7 +22,13 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2026-01-28: Inputs: Minor optimization not submitting gamepad input if packet number has not changed (reworked from 2025-09-23 attempt). (#9202, #8556)
// 2026-01-26: [Docking] Fixed an issue from 1.90.5 where newly appearing windows that are not parented to the main viewport don't have task bar icon appear before the windows was explicited refocused. (#7354, #8669)
// 2025-12-03: Inputs: handle WM_IME_CHAR/WM_IME_COMPOSITION messages to support Unicode inputs on MBCS (non-Unicode) Windows. (#9099, #3653, #5961)
// 2025-10-19: Inputs: Revert previous change to allow for io.ClearInputKeys() on focus-out not losing gamepad state.
// 2025-09-23: Inputs: Minor optimization not submitting gamepad input if packet number has not changed.
// 2025-09-18: Call platform_io.ClearPlatformHandlers() on shutdown.
// 2025-06-02: [Docking] WM_DPICHANGED also apply io.ConfigDpiScaleViewports for main viewport instead of letting it be done by application code.
// 2025-04-30: Inputs: Fixed an issue where externally losing mouse capture (due to e.g. focus loss) would fail to claim it again the next subsequent click. (#8594)
// 2025-03-26: [Docking] Viewports: fixed an issue when closing a window from the OS close button (with io.ConfigViewportsNoDecoration = false) while user code was discarding the 'bool* p_open = false' output from Begin(). Because we allowed the Win32 window to close early, Windows destroyed it and our imgui window became not visible even though user code was still submitting it.
@@ -137,6 +143,7 @@ struct ImGui_ImplWin32_Data
HMODULE XInputDLL;
PFN_XInputGetCapabilities XInputGetCapabilities;
PFN_XInputGetState XInputGetState;
DWORD XInputPacketNumber;
#endif
ImGui_ImplWin32_Data() { memset((void*)this, 0, sizeof(*this)); }
@@ -186,6 +193,7 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used)
io.BackendFlags |= ImGuiBackendFlags_PlatformHasViewports; // We can create multi-viewports on the Platform side (optional)
io.BackendFlags |= ImGuiBackendFlags_HasMouseHoveredViewport; // We can call io.AddMouseViewportEvent() with correct data (optional)
io.BackendFlags |= ImGuiBackendFlags_HasParentViewport; // We can honor viewport->ParentViewportId by applying the corresponding parent/child relationship at platform levle (optional)
bd->hWnd = (HWND)hwnd;
bd->TicksPerSecond = perf_frequency;
@@ -216,7 +224,7 @@ static bool ImGui_ImplWin32_InitEx(void* hwnd, bool platform_has_own_dc)
"xinput1_2.dll", // DirectX SDK
"xinput1_1.dll" // DirectX SDK
};
for (int n = 0; n < IM_ARRAYSIZE(xinput_dll_names); n++)
for (int n = 0; n < IM_COUNTOF(xinput_dll_names); n++)
if (HMODULE dll = ::LoadLibraryA(xinput_dll_names[n]))
{
bd->XInputDLL = dll;
@@ -245,6 +253,7 @@ void ImGui_ImplWin32_Shutdown()
ImGui_ImplWin32_Data* bd = ImGui_ImplWin32_GetBackendData();
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO();
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
::SetPropA(bd->hWnd, "IMGUI_CONTEXT", nullptr);
ImGui_ImplWin32_ShutdownMultiViewportSupport();
@@ -257,7 +266,8 @@ void ImGui_ImplWin32_Shutdown()
io.BackendPlatformName = nullptr;
io.BackendPlatformUserData = nullptr;
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport);
io.BackendFlags &= ~(ImGuiBackendFlags_HasMouseCursors | ImGuiBackendFlags_HasSetMousePos | ImGuiBackendFlags_HasGamepad | ImGuiBackendFlags_PlatformHasViewports | ImGuiBackendFlags_HasMouseHoveredViewport | ImGuiBackendFlags_HasParentViewport);
platform_io.ClearPlatformHandlers();
IM_DELETE(bd);
}
@@ -415,6 +425,9 @@ static void ImGui_ImplWin32_UpdateGamepads(ImGuiIO& io)
if (!bd->HasGamepad || bd->XInputGetState == nullptr || bd->XInputGetState(0, &xinput_state) != ERROR_SUCCESS)
return;
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
if (bd->XInputPacketNumber != 0 && bd->XInputPacketNumber == xinput_state.dwPacketNumber)
return;
bd->XInputPacketNumber = xinput_state.dwPacketNumber;
#define IM_SATURATE(V) (V < 0.0f ? 0.0f : V > 1.0f ? 1.0f : V)
#define MAP_BUTTON(KEY_NO, BUTTON_ENUM) { io.AddKeyEvent(KEY_NO, (gamepad.wButtons & BUTTON_ENUM) != 0); }
@@ -869,6 +882,9 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
case WM_SETFOCUS:
case WM_KILLFOCUS:
io.AddFocusEvent(msg == WM_SETFOCUS);
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
bd->XInputPacketNumber = 0; // FIXME: Technically, calling io.ClearInputKeys() directly would require this as well.
#endif
return 0;
case WM_INPUTLANGCHANGE:
ImGui_ImplWin32_UpdateKeyboardCodePage(io);
@@ -883,10 +899,28 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
else
{
wchar_t wch = 0;
::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 1, &wch, 1);
::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 2, &wch, 1);
io.AddInputCharacter(wch);
}
return 0;
case WM_IME_COMPOSITION:
{
// Handling WM_IME_COMPOSITION ensure that WM_IME_CHAR value is correct even for MBCS apps.
// (see #9099, #3653 and https://stackoverflow.com/questions/77450354 topics)
LRESULT result = ::DefWindowProcW(hwnd, msg, wParam, lParam);
return (lParam & GCS_RESULTSTR) ? 1 : result;
}
case WM_IME_CHAR:
if (::IsWindowUnicode(hwnd) == FALSE)
{
if (::IsDBCSLeadByte(HIBYTE(wParam)))
wParam = (WPARAM)MAKEWORD(HIBYTE(wParam), LOBYTE(wParam));
wchar_t wch = 0;
::MultiByteToWideChar(bd->KeyboardCodePage, MB_PRECOMPOSED, (char*)&wParam, 2, &wch, 1);
io.AddInputCharacterUTF16(wch);
return 1;
}
return 0;
case WM_SETCURSOR:
// This is required to restore cursor when transitioning from e.g resize borders to client area.
if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor(io, bd->LastMouseCursor))
@@ -924,7 +958,7 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandlerEx(HWND hwnd, UINT msg, WPA
// - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps.
// - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc.
// but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime,
// neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
// neither of which we want to require the user to have. So we dynamically select and load those functions to avoid dependencies.
//---------------------------------------------------------------------------------------------------------
// This is the scheme successfully used by GLFW (from which we borrowed some of the code) and other apps aiming to be highly portable.
// ImGui_ImplWin32_EnableDpiAwareness() is just a helper called by main.cpp, we don't call it automatically.
@@ -1114,11 +1148,10 @@ static void ImGui_ImplWin32_GetWin32StyleFromViewportFlags(ImGuiViewportFlags fl
*out_ex_style |= WS_EX_TOPMOST;
}
static HWND ImGui_ImplWin32_GetHwndFromViewportID(ImGuiID viewport_id)
static HWND ImGui_ImplWin32_GetHwndFromViewport(ImGuiViewport* viewport)
{
if (viewport_id != 0)
if (ImGuiViewport* viewport = ImGui::FindViewportByID(viewport_id))
return (HWND)viewport->PlatformHandle;
if (viewport != nullptr)
return (HWND)viewport->PlatformHandle;
return nullptr;
}
@@ -1129,7 +1162,7 @@ static void ImGui_ImplWin32_CreateWindow(ImGuiViewport* viewport)
// Select style and parent window
ImGui_ImplWin32_GetWin32StyleFromViewportFlags(viewport->Flags, &vd->DwStyle, &vd->DwExStyle);
vd->HwndParent = ImGui_ImplWin32_GetHwndFromViewportID(viewport->ParentViewportId);
vd->HwndParent = ImGui_ImplWin32_GetHwndFromViewport(viewport->ParentViewport);
// Create window
RECT rect = { (LONG)viewport->Pos.x, (LONG)viewport->Pos.y, (LONG)(viewport->Pos.x + viewport->Size.x), (LONG)(viewport->Pos.y + viewport->Size.y) };
@@ -1170,9 +1203,10 @@ static void ImGui_ImplWin32_ShowWindow(ImGuiViewport* viewport)
ImGui_ImplWin32_ViewportData* vd = (ImGui_ImplWin32_ViewportData*)viewport->PlatformUserData;
IM_ASSERT(vd->Hwnd != 0);
// ShowParent() also brings parent to front, which is not always desirable,
// so we temporarily disable parenting. (#7354)
if (vd->HwndParent != NULL)
// ShowParent() even with SW_SHOWNA also brings parent to front, which is not always desirable,
// so we temporarily disable parenting. (#7354, #8669)
bool avoid_bringing_parent_to_front = vd->HwndParent != NULL && (viewport->Flags & (ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoTaskBarIcon)) != 0;
if (avoid_bringing_parent_to_front)
::SetWindowLongPtr(vd->Hwnd, GWLP_HWNDPARENT, (LONG_PTR)nullptr);
if (viewport->Flags & ImGuiViewportFlags_NoFocusOnAppearing)
@@ -1181,7 +1215,7 @@ static void ImGui_ImplWin32_ShowWindow(ImGuiViewport* viewport)
::ShowWindow(vd->Hwnd, SW_SHOW);
// Restore
if (vd->HwndParent != NULL)
if (avoid_bringing_parent_to_front)
::SetWindowLongPtr(vd->Hwnd, GWLP_HWNDPARENT, (LONG_PTR)vd->HwndParent);
}
@@ -1192,7 +1226,7 @@ static void ImGui_ImplWin32_UpdateWindow(ImGuiViewport* viewport)
// Update Win32 parent if it changed _after_ creation
// Unlike style settings derived from configuration flags, this is more likely to change for advanced apps that are manipulating ParentViewportID manually.
HWND new_parent = ImGui_ImplWin32_GetHwndFromViewportID(viewport->ParentViewportId);
HWND new_parent = ImGui_ImplWin32_GetHwndFromViewport(viewport->ParentViewport);
if (new_parent != vd->HwndParent)
{
// Win32 windows can either have a "Parent" (for WS_CHILD window) or an "Owner" (which among other thing keeps window above its owner).
@@ -1367,7 +1401,7 @@ static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd,
// Allow secondary viewport WndProc to be called regardless of current context
ImGuiContext* ctx = (ImGuiContext*)::GetPropA(hWnd, "IMGUI_CONTEXT");
if (ctx == NULL)
return DefWindowProc(hWnd, msg, wParam, lParam); // unlike ImGui_ImplWin32_WndProcHandler() we are called directly by Windows, we can't just return 0.
return ::DefWindowProcW(hWnd, msg, wParam, lParam); // unlike ImGui_ImplWin32_WndProcHandler() we are called directly by Windows, we can't just return 0.
ImGuiIO& io = ImGui::GetIO(ctx);
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(ctx);
@@ -1402,7 +1436,7 @@ static LRESULT CALLBACK ImGui_ImplWin32_WndProcHandler_PlatformWindow(HWND hWnd,
}
}
if (result == 0)
result = DefWindowProc(hWnd, msg, wParam, lParam);
result = ::DefWindowProcW(hWnd, msg, wParam, lParam);
return result;
}