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).
This commit is contained in:
ocornut
2025-05-15 14:31:26 +02:00
parent 63554bcee5
commit c90ea1315a
9 changed files with 119 additions and 46 deletions

View File

@@ -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;

View File

@@ -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 <CAMetalDrawable> drawable = [data->MetalLayer nextDrawable];

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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 <Cocoa/Cocoa.h>
#import <OpenGL/gl.h>
#import <OpenGL/glu.h>

View File

@@ -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; } }

View File

@@ -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; // <unset> // Main display size, in pixels (generally == GetMainViewport()->Size). May change every frame.
ImVec2 DisplaySize; // <unset> // 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