From c90ea1315a532e8442df71ce904e0e374cf310c8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 15 May 2025 14:31:26 +0200 Subject: [PATCH] Viewports: added per-viewport FramebufferScale, Platform_GetWindowFramebufferScale() + Backends: GLFW, SDL2, SDL3, Apple: added support. (#1065, #1542, #1676, #1786, #2826, #3757, #5081, #5580, #5592, #6465, #7273, #7779 etc.) ) Metal backend is not in charge of writing to DpiScale/FramebufferScale (tho it was a neat workaround). --- backends/imgui_impl_glfw.cpp | 34 ++++++++++++----- backends/imgui_impl_metal.mm | 9 ++--- backends/imgui_impl_osx.mm | 10 +++++ backends/imgui_impl_sdl2.cpp | 51 +++++++++++++++++--------- backends/imgui_impl_sdl3.cpp | 36 +++++++++++++----- docs/CHANGELOG.txt | 10 ++++- examples/example_apple_opengl2/main.mm | 2 + imgui.cpp | 7 +++- imgui.h | 6 ++- 9 files changed, 119 insertions(+), 46 deletions(-) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index f2c67ff1e..06e22336f 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -31,7 +31,8 @@ // 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. -// 2025-04-26: Disable multi-viewports under Wayland. (#8587) +// 2025-05-15: [Docking] Add Platform_GetWindowFramebufferScale() handler, to allow varying Retina display density on multiple monitors. +// 2025-04-26: [Docking] Disable multi-viewports under Wayland. (#8587) // 2025-03-10: Map GLFW_KEY_WORLD_1 and GLFW_KEY_WORLD_2 into ImGuiKey_Oem102. // 2025-03-03: Fixed clipboard handler assertion when using GLFW <= 3.2.1 compiled with asserts enabled. // 2025-02-21: [Docking] Update monitors and work areas information every frame, as the later may change regardless of monitor changes. (#8415) @@ -970,20 +971,26 @@ static void ImGui_ImplGlfw_UpdateMonitors() } } +static void ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(GLFWwindow* window, ImVec2* out_size, ImVec2* out_framebuffer_scale) +{ + int w, h; + int display_w, display_h; + glfwGetWindowSize(window, &w, &h); + glfwGetFramebufferSize(window, &display_w, &display_h); + if (out_size != nullptr) + *out_size = ImVec2((float)w, (float)h); + if (out_framebuffer_scale != nullptr) + *out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / (float)w, (float)display_h / (float)h) : ImVec2(1.0f, 1.0f); +} + void ImGui_ImplGlfw_NewFrame() { ImGuiIO& io = ImGui::GetIO(); ImGui_ImplGlfw_Data* bd = ImGui_ImplGlfw_GetBackendData(); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplGlfw_InitForXXX()?"); - // Setup display size (every frame to accommodate for window resizing) - int w, h; - int display_w, display_h; - glfwGetWindowSize(bd->Window, &w, &h); - glfwGetFramebufferSize(bd->Window, &display_w, &display_h); - io.DisplaySize = ImVec2((float)w, (float)h); - if (w > 0 && h > 0) - io.DisplayFramebufferScale = ImVec2((float)display_w / (float)w, (float)display_h / (float)h); + // Setup main viewport size (every frame to accommodate for window resizing) + ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(bd->Window, &io.DisplaySize, &io.DisplayFramebufferScale); ImGui_ImplGlfw_UpdateMonitors(); // Setup time step @@ -1283,6 +1290,14 @@ static void ImGui_ImplGlfw_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) glfwSetWindowSize(vd->Window, (int)size.x, (int)size.y); } +static ImVec2 ImGui_ImplGlfw_GetWindowFramebufferScale(ImGuiViewport* viewport) +{ + ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData; + ImVec2 framebuffer_scale; + ImGui_ImplGlfw_GetWindowSizeAndFramebufferScale(vd->Window, nullptr, &framebuffer_scale); + return framebuffer_scale; +} + static void ImGui_ImplGlfw_SetWindowTitle(ImGuiViewport* viewport, const char* title) { ImGui_ImplGlfw_ViewportData* vd = (ImGui_ImplGlfw_ViewportData*)viewport->PlatformUserData; @@ -1381,6 +1396,7 @@ static void ImGui_ImplGlfw_InitMultiViewportSupport() platform_io.Platform_GetWindowPos = ImGui_ImplGlfw_GetWindowPos; platform_io.Platform_SetWindowSize = ImGui_ImplGlfw_SetWindowSize; platform_io.Platform_GetWindowSize = ImGui_ImplGlfw_GetWindowSize; + platform_io.Platform_GetWindowFramebufferScale = ImGui_ImplGlfw_GetWindowFramebufferScale; platform_io.Platform_SetWindowFocus = ImGui_ImplGlfw_SetWindowFocus; platform_io.Platform_GetWindowFocus = ImGui_ImplGlfw_GetWindowFocus; platform_io.Platform_GetWindowMinimized = ImGui_ImplGlfw_GetWindowMinimized; diff --git a/backends/imgui_impl_metal.mm b/backends/imgui_impl_metal.mm index 9ab4a342a..a953bcaf3 100644 --- a/backends/imgui_impl_metal.mm +++ b/backends/imgui_impl_metal.mm @@ -485,13 +485,12 @@ static void ImGui_ImplMetal_RenderWindow(ImGuiViewport* viewport, void*) } data->FirstFrame = false; - viewport->DpiScale = (float)window.backingScaleFactor; - if (data->MetalLayer.contentsScale != viewport->DpiScale) + float fb_scale = (float)window.backingScaleFactor; + if (data->MetalLayer.contentsScale != fb_scale) { - data->MetalLayer.contentsScale = viewport->DpiScale; - data->MetalLayer.drawableSize = MakeScaledSize(window.frame.size, viewport->DpiScale); + data->MetalLayer.contentsScale = fb_scale; + data->MetalLayer.drawableSize = MakeScaledSize(window.frame.size, fb_scale); } - viewport->DrawData->FramebufferScale = ImVec2(viewport->DpiScale, viewport->DpiScale); #endif id drawable = [data->MetalLayer nextDrawable]; diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index ca69fb0e8..3543177fb 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -35,6 +35,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) // 2025-XX-XX: Added support for multiple windows via the ImGuiPlatformIO interface. +// 2025-05-15: [Docking] Add Platform_GetWindowFramebufferScale() handler, to allow varying Retina display density on multiple monitors. // 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set. // 2025-01-20: Removed notification observer when shutting down. (#8331) // 2024-08-22: moved some OS/backend related function pointers from ImGuiIO to ImGuiPlatformIO: @@ -1021,6 +1022,14 @@ static void ImGui_ImplOSX_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) [window setFrame:rect display:YES]; } +static ImVec2 ImGui_ImplOSX_GetWindowFramebufferScale(ImGuiViewport* viewport) +{ + ImGui_ImplOSX_ViewportData* vd = (ImGui_ImplOSX_ViewportData*)viewport->PlatformUserData; + NSWindow* window = vd->Window; + const float fb_scale = (float)[window backingScaleFactor]; + return ImVec2(fb_scale, fb_scale); +} + static void ImGui_ImplOSX_SetWindowFocus(ImGuiViewport* viewport) { ImGui_ImplOSX_Data* bd = ImGui_ImplOSX_GetBackendData(); @@ -1110,6 +1119,7 @@ static void ImGui_ImplOSX_InitMultiViewportSupport() platform_io.Platform_GetWindowPos = ImGui_ImplOSX_GetWindowPos; platform_io.Platform_SetWindowSize = ImGui_ImplOSX_SetWindowSize; platform_io.Platform_GetWindowSize = ImGui_ImplOSX_GetWindowSize; + platform_io.Platform_GetWindowFramebufferScale = ImGui_ImplOSX_GetWindowFramebufferScale; platform_io.Platform_SetWindowFocus = ImGui_ImplOSX_SetWindowFocus; platform_io.Platform_GetWindowFocus = ImGui_ImplOSX_GetWindowFocus; platform_io.Platform_GetWindowMinimized = ImGui_ImplOSX_GetWindowMinimized; diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index a2fc05e4f..3c44a5801 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -26,6 +26,7 @@ // 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. +// 2025-05-15: [Docking] Add Platform_GetWindowFramebufferScale() handler, to allow varying Retina display density on multiple monitors. // 2025-04-09: [Docking] Revert update monitors and work areas information every frame. Only do it on Windows. (#8415, #8558) // 2025-04-09: Don't attempt to call SDL_CaptureMouse() on drivers where we don't call SDL_GetGlobalMouseState(). (#8561) // 2025-03-21: Fill gamepad inputs and set ImGuiBackendFlags_HasGamepad regardless of ImGuiConfigFlags_NavEnableGamepad being set. @@ -939,29 +940,35 @@ static void ImGui_ImplSDL2_UpdateMonitors() } } +static void ImGui_ImplSDL2_GetWindowSizeAndFramebufferScale(SDL_Window* window, SDL_Renderer* renderer, ImVec2* out_size, ImVec2* out_framebuffer_scale) +{ + int w, h; + int display_w, display_h; + SDL_GetWindowSize(window, &w, &h); + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + w = h = 0; + if (renderer != nullptr) + SDL_GetRendererOutputSize(renderer, &display_w, &display_h); +#if SDL_HAS_VULKAN + else if (SDL_GetWindowFlags(window) & SDL_WINDOW_VULKAN) + SDL_Vulkan_GetDrawableSize(window, &display_w, &display_h); +#endif + else + SDL_GL_GetDrawableSize(window, &display_w, &display_h); + if (out_size != nullptr) + *out_size = ImVec2((float)w, (float)h); + if (out_framebuffer_scale != nullptr) + *out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / w, (float)display_h / h) : ImVec2(1.0f, 1.0f); +} + void ImGui_ImplSDL2_NewFrame() { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL2_Init()?"); ImGuiIO& io = ImGui::GetIO(); - // Setup display size (every frame to accommodate for window resizing) - int w, h; - int display_w, display_h; - SDL_GetWindowSize(bd->Window, &w, &h); - if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED) - w = h = 0; - if (bd->Renderer != nullptr) - SDL_GetRendererOutputSize(bd->Renderer, &display_w, &display_h); -#if SDL_HAS_VULKAN - else if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_VULKAN) - SDL_Vulkan_GetDrawableSize(bd->Window, &display_w, &display_h); -#endif - else - SDL_GL_GetDrawableSize(bd->Window, &display_w, &display_h); - io.DisplaySize = ImVec2((float)w, (float)h); - if (w > 0 && h > 0) - io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); + // Setup main viewport size (every frame to accommodate for window resizing) + ImGui_ImplSDL2_GetWindowSizeAndFramebufferScale(bd->Window, bd->Renderer, &io.DisplaySize, &io.DisplayFramebufferScale); // Update monitors #ifdef WIN32 @@ -1147,6 +1154,15 @@ static void ImGui_ImplSDL2_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) SDL_SetWindowSize(vd->Window, (int)size.x, (int)size.y); } +static ImVec2 ImGui_ImplSDL2_GetWindowFramebufferScale(ImGuiViewport* viewport) +{ + // FIXME: SDL_Renderer does not support multi-viewport. + ImGui_ImplSDL2_ViewportData* vd = (ImGui_ImplSDL2_ViewportData*)viewport->PlatformUserData; + ImVec2 framebuffer_scale; + ImGui_ImplSDL2_GetWindowSizeAndFramebufferScale(vd->Window, nullptr, nullptr, &framebuffer_scale); + return framebuffer_scale; +} + static void ImGui_ImplSDL2_SetWindowTitle(ImGuiViewport* viewport, const char* title) { ImGui_ImplSDL2_ViewportData* vd = (ImGui_ImplSDL2_ViewportData*)viewport->PlatformUserData; @@ -1220,6 +1236,7 @@ static void ImGui_ImplSDL2_InitMultiViewportSupport(SDL_Window* window, void* sd platform_io.Platform_GetWindowPos = ImGui_ImplSDL2_GetWindowPos; platform_io.Platform_SetWindowSize = ImGui_ImplSDL2_SetWindowSize; platform_io.Platform_GetWindowSize = ImGui_ImplSDL2_GetWindowSize; + platform_io.Platform_GetWindowFramebufferScale = ImGui_ImplSDL2_GetWindowFramebufferScale; platform_io.Platform_SetWindowFocus = ImGui_ImplSDL2_SetWindowFocus; platform_io.Platform_GetWindowFocus = ImGui_ImplSDL2_GetWindowFocus; platform_io.Platform_GetWindowMinimized = ImGui_ImplSDL2_GetWindowMinimized; diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 7773b95f6..7c55b4c97 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -24,6 +24,7 @@ // 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. +// 2025-05-15: [Docking] Add Platform_GetWindowFramebufferScale() handler, to allow varying Retina display density on multiple monitors. // 2025-05-06: [Docking] macOS: fixed secondary viewports not appearing on other monitors before of parenting. // 2025-04-09: [Docking] Revert update monitors and work areas information every frame. Only do it on Windows. (#8415, #8558) // 2025-04-22: IME: honor ImGuiPlatformImeData->WantTextInput as an alternative way to call SDL_StartTextInput(), without IME being necessarily visible. @@ -901,22 +902,28 @@ static void ImGui_ImplSDL3_UpdateMonitors() SDL_free(displays); } +static void ImGui_ImplSDL3_GetWindowSizeAndFramebufferScale(SDL_Window* window, ImVec2* out_size, ImVec2* out_framebuffer_scale) +{ + int w, h; + int display_w, display_h; + SDL_GetWindowSize(window, &w, &h); + if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) + w = h = 0; + SDL_GetWindowSizeInPixels(window, &display_w, &display_h); + if (out_size != nullptr) + *out_size = ImVec2((float)w, (float)h); + if (out_framebuffer_scale != nullptr) + *out_framebuffer_scale = (w > 0 && h > 0) ? ImVec2((float)display_w / w, (float)display_h / h) : ImVec2(1.0f, 1.0f); +} + void ImGui_ImplSDL3_NewFrame() { ImGui_ImplSDL3_Data* bd = ImGui_ImplSDL3_GetBackendData(); IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplSDL3_Init()?"); ImGuiIO& io = ImGui::GetIO(); - // Setup display size (every frame to accommodate for window resizing) - int w, h; - int display_w, display_h; - SDL_GetWindowSize(bd->Window, &w, &h); - if (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_MINIMIZED) - w = h = 0; - SDL_GetWindowSizeInPixels(bd->Window, &display_w, &display_h); - io.DisplaySize = ImVec2((float)w, (float)h); - if (w > 0 && h > 0) - io.DisplayFramebufferScale = ImVec2((float)display_w / w, (float)display_h / h); + // Setup main viewport size (every frame to accommodate for window resizing) + ImGui_ImplSDL3_GetWindowSizeAndFramebufferScale(bd->Window, &io.DisplaySize, &io.DisplayFramebufferScale); // Update monitors #ifdef WIN32 @@ -1117,6 +1124,14 @@ static void ImGui_ImplSDL3_SetWindowSize(ImGuiViewport* viewport, ImVec2 size) SDL_SetWindowSize(vd->Window, (int)size.x, (int)size.y); } +static ImVec2 ImGui_ImplSDL3_GetWindowFramebufferScale(ImGuiViewport* viewport) +{ + ImGui_ImplSDL3_ViewportData* vd = (ImGui_ImplSDL3_ViewportData*)viewport->PlatformUserData; + ImVec2 framebuffer_scale; + ImGui_ImplSDL3_GetWindowSizeAndFramebufferScale(vd->Window, nullptr, &framebuffer_scale); + return framebuffer_scale; +} + static void ImGui_ImplSDL3_SetWindowTitle(ImGuiViewport* viewport, const char* title) { ImGui_ImplSDL3_ViewportData* vd = (ImGui_ImplSDL3_ViewportData*)viewport->PlatformUserData; @@ -1187,6 +1202,7 @@ static void ImGui_ImplSDL3_InitMultiViewportSupport(SDL_Window* window, void* sd platform_io.Platform_GetWindowPos = ImGui_ImplSDL3_GetWindowPos; platform_io.Platform_SetWindowSize = ImGui_ImplSDL3_SetWindowSize; platform_io.Platform_GetWindowSize = ImGui_ImplSDL3_GetWindowSize; + platform_io.Platform_GetWindowFramebufferScale = ImGui_ImplSDL3_GetWindowFramebufferScale; platform_io.Platform_SetWindowFocus = ImGui_ImplSDL3_SetWindowFocus; platform_io.Platform_GetWindowFocus = ImGui_ImplSDL3_GetWindowFocus; platform_io.Platform_GetWindowMinimized = ImGui_ImplSDL3_GetWindowMinimized; diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9e60b0a36..1ed832251 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -129,12 +129,20 @@ Other changes: Docking+Viewports Branch: -- Backends: Win32: Viewports: fixed an issue when closing a window from +- Viewports: added per-viewport FramebufferScale for Retina display multi-monitor support. + Backend must provide platform_io.platform_io.Platform_GetWindowFramebufferScale handler. + This effectively fixes clipping/rendering on multi-monitors with varying Retina scale. + (this per-se doesn't fix the font quality which requires setting RasterizerDensity + separately. More on this later as it should soon become automatic). + (#1065, #1542, #1676, #1786, #2826, #3757, #5081, #5580, #5592, #6465, #7273, #7779 etc.) +- Backends: Win32: Viewports: fixed an issue when closing a window from the OS close button (with io.ConfigViewportsNoDecoration=false) while user code is 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. +- Backends: GLFW, SDL2, SDL3, Apple: provide Platform_GetWindowFramebufferScale handler, + (#1065, #1542, #1676, #1786, #2826, #3757, #5081, #5580, #5592, #6465, #7273, #7779 etc.) - Backends: SDLGPU3 for SDL3: added multi-viewport support. (#8573) [@Lekoopapaul] - Backends: SDL2, SDL3: revert updating monitors and work areas info every frame. Only do it on Windows to detect task-bar resize until we get an diff --git a/examples/example_apple_opengl2/main.mm b/examples/example_apple_opengl2/main.mm index 11829a820..40d007dfb 100644 --- a/examples/example_apple_opengl2/main.mm +++ b/examples/example_apple_opengl2/main.mm @@ -6,6 +6,8 @@ // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). // - Introduction, links and more at the top of imgui.cpp +// FIXME: Multi-viewports is not yet functional in this example. May need backend rework/coordination. + #import #import #import diff --git a/imgui.cpp b/imgui.cpp index b868d93be..a7f05df1f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5719,7 +5719,7 @@ static void InitViewportDrawData(ImGuiViewportP* viewport) draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0; draw_data->DisplayPos = viewport->Pos; draw_data->DisplaySize = is_minimized ? ImVec2(0.0f, 0.0f) : viewport->Size; - draw_data->FramebufferScale = io.DisplayFramebufferScale; // FIXME-VIEWPORT: This may vary on a per-monitor/viewport basis? + draw_data->FramebufferScale = (viewport->FramebufferScale.x != 0.0f) ? viewport->FramebufferScale : io.DisplayFramebufferScale; draw_data->OwnerViewport = viewport; } @@ -16015,6 +16015,8 @@ static void ImGui::UpdateViewportsNewFrame() viewport->Pos = viewport->LastPlatformPos = g.PlatformIO.Platform_GetWindowPos(viewport); if (viewport->PlatformRequestResize) viewport->Size = viewport->LastPlatformSize = g.PlatformIO.Platform_GetWindowSize(viewport); + if (g.PlatformIO.Platform_GetWindowFramebufferScale != NULL) + viewport->FramebufferScale = g.PlatformIO.Platform_GetWindowFramebufferScale(viewport); } } @@ -22313,8 +22315,9 @@ void ImGui::DebugNodeViewport(ImGuiViewportP* viewport) if (open) { ImGuiWindowFlags flags = viewport->Flags; - BulletText("Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nWorkArea Inset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f\nMonitor: %d, DpiScale: %.0f%%", + BulletText("Main Pos: (%.0f,%.0f), Size: (%.0f,%.0f)\nFrameBufferScale: (%.2f,%.2f)\nWorkArea Inset Left: %.0f Top: %.0f, Right: %.0f, Bottom: %.0f\nMonitor: %d, DpiScale: %.0f%%", viewport->Pos.x, viewport->Pos.y, viewport->Size.x, viewport->Size.y, + viewport->FramebufferScale.x, viewport->FramebufferScale.y, viewport->WorkInsetMin.x, viewport->WorkInsetMin.y, viewport->WorkInsetMax.x, viewport->WorkInsetMax.y, viewport->PlatformMonitor, viewport->DpiScale * 100.0f); if (viewport->Idx > 0) { SameLine(); if (SmallButton("Reset Pos")) { viewport->Pos = ImVec2(200, 200); viewport->UpdateWorkRect(); if (viewport->Window) viewport->Window->Pos = viewport->Pos; } } diff --git a/imgui.h b/imgui.h index 0a0e6fa6d..e1688b966 100644 --- a/imgui.h +++ b/imgui.h @@ -2336,7 +2336,8 @@ struct ImGuiIO ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Keyboard/Gamepad navigation options, etc. ImGuiBackendFlags BackendFlags; // = 0 // See ImGuiBackendFlags_ enum. Set by backend (imgui_impl_xxx files or custom backend) to communicate features supported by the backend. - ImVec2 DisplaySize; // // Main display size, in pixels (generally == GetMainViewport()->Size). May change every frame. + ImVec2 DisplaySize; // // Main display size, in pixels (== GetMainViewport()->Size). May change every frame. + ImVec2 DisplayFramebufferScale; // = (1, 1) // Main display density. For retina display where window coordinates are different from framebuffer coordinates. This generally ends up in ImDrawData::FramebufferScale. float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. May change every frame. float IniSavingRate; // = 5.0f // Minimum time between saving positions/sizes to .ini file, in seconds. const char* IniFilename; // = "imgui.ini" // Path to .ini file (important: default "imgui.ini" is relative to current working dir!). Set NULL to disable automatic .ini loading/saving or if you want to manually call LoadIniSettingsXXX() / SaveIniSettingsXXX() functions. @@ -2348,7 +2349,6 @@ struct ImGuiIO float FontGlobalScale; // = 1.0f // Global scale all fonts bool FontAllowUserScaling; // = false // [OBSOLETE] Allow user scaling text of individual window with CTRL+Wheel. ImFont* FontDefault; // = NULL // Font to use on NewFrame(). Use NULL to uses Fonts->Fonts[0]. - ImVec2 DisplayFramebufferScale; // = (1, 1) // For retina display or other situations where window coordinates are different from framebuffer coordinates. This generally ends up in ImDrawData::FramebufferScale. // Keyboard/Gamepad Navigation options bool ConfigNavSwapGamepadButtons; // = false // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout. @@ -3698,6 +3698,7 @@ struct ImGuiViewport ImGuiViewportFlags Flags; // See ImGuiViewportFlags_ ImVec2 Pos; // Main Area: Position of the viewport (Dear ImGui coordinates are the same as OS desktop/native coordinates) ImVec2 Size; // Main Area: Size of the viewport. + ImVec2 FramebufferScale; // Density of the viewport for Retina display (always 1,1 on Windows, may be 2,2 etc on macOS/iOS). 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) float DpiScale; // 1.0f = 96 DPI = No extra scale. @@ -3837,6 +3838,7 @@ struct ImGuiPlatformIO ImVec2 (*Platform_GetWindowPos)(ImGuiViewport* vp); // N . . . . // void (*Platform_SetWindowSize)(ImGuiViewport* vp, ImVec2 size); // . . U . . // Set platform window client area size (ignoring OS decorations such as OS title bar etc.) ImVec2 (*Platform_GetWindowSize)(ImGuiViewport* vp); // N . . . . // Get platform window client area size + ImVec2 (*Platform_GetWindowFramebufferScale)(ImGuiViewport* vp); // N . . . . // Return viewport density. Always 1,1 on Windows, often 2,2 on Retina display on macOS/iOS. MUST BE INTEGER VALUES. void (*Platform_SetWindowFocus)(ImGuiViewport* vp); // N . . . . // Move window to front and set input focus bool (*Platform_GetWindowFocus)(ImGuiViewport* vp); // . . U . . // bool (*Platform_GetWindowMinimized)(ImGuiViewport* vp); // N . . . . // Get platform window minimized state. When minimized, we generally won't attempt to get/set size and contents will be culled more easily