diff --git a/imgui.cpp b/imgui.cpp index f5949408..562b5f93 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3347,13 +3347,13 @@ static void ImGui::UpdateViewports() const ImVec2 mouse_os_pos = ConvertViewportPosToOsDesktopPos(g.IO.MousePos, viewport_ref); g.CurrentViewport = NULL; - for (int n = 1; n < g.Viewports.Size; n++) + for (int n = 0; n < g.Viewports.Size; n++) { // Erase unused viewports ImGuiViewport* viewport = g.Viewports[n]; IM_ASSERT(viewport->Idx == n); - IM_ASSERT(!(viewport->Flags & ImGuiViewportFlags_MainViewport)); - if (viewport->LastFrameActive < g.FrameCount - 2) + + if (n > 0 && viewport->LastFrameActive < g.FrameCount - 2) { // Translate windows like if we were resizing the viewport to be zero-width ResizeViewportTranslateWindows(n + 1, g.Viewports.Size, viewport->Pos.x - viewport->GetNextX(), -1, viewport); @@ -3380,6 +3380,19 @@ static void ImGui::UpdateViewports() if (dx != 0.0f) ResizeViewportTranslateWindows(viewport->Idx + 1, g.Viewports.Size, dx, 0, NULL); } + + // Update DPI Scale + float new_dpi_scale; + if (g.IO.PlatformInterface.GetWindowDpiScale) + new_dpi_scale = g.IO.PlatformInterface.GetWindowDpiScale(viewport); + else + new_dpi_scale = (viewport->PlatformDpiScale != 0.0f) ? viewport->PlatformDpiScale : 1.0f; + if (viewport->PlatformDpiScale != 0.0f && new_dpi_scale != viewport->PlatformDpiScale) + { + float scale_factor = new_dpi_scale / viewport->PlatformDpiScale; + ScaleWindowsInViewport(viewport, scale_factor); + } + viewport->PlatformDpiScale = new_dpi_scale; } // Update main viewport with current size (and OS window position, if known) @@ -13769,6 +13782,31 @@ static void RenderViewportThumbnail(ImDrawList* draw_list, const ImRect& bb, con draw_list->AddRect(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_Border)); } +static void ScaleWindow(ImGuiWindow* window, float scale) +{ + ImVec2 origin = window->Viewport->Pos; + window->Pos = window->PosFloat = ImFloor((window->PosFloat - origin) * scale + origin); + window->Size = ImFloor(window->Size * scale); + window->SizeFull = ImFloor(window->SizeFull * scale); + window->SizeContents = ImFloor(window->SizeContents * scale); +} + +// Scale all windows (position, size). Use when e.g. changing DPI. (This is a lossy operation!) +void ImGui::ScaleWindowsInViewport(ImGuiViewport* viewport, float scale) +{ + if (viewport->Window) + { + ScaleWindow(viewport->Window, scale); + } + else + { + ImGuiContext& g = *GImGui; + for (int i = 0; i != g.Windows.Size; i++) + if (g.Windows[i]->Viewport == viewport) + ScaleWindow(g.Windows[i], scale); + } +} + void ImGui::ShowViewportThumbnails() { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index cff33252..529c1a0f 100644 --- a/imgui.h +++ b/imgui.h @@ -964,6 +964,7 @@ struct ImGuiPlatformInterface void (*SwapBuffers)(ImGuiViewport* viewport); // FIXME-DPI + float (*GetWindowDpiScale)(ImGuiViewport* viewport); // (Optional) void (*BeginViewport)(ImGuiViewport* viewport); // (Optional) Called during Begin() every time the viewport we are outputting into changes (viewport = next viewport) void (*EndViewport)(ImGuiViewport* viewport); // (Optional) Called during Begin() every time the viewport we are outputting into changes (viewport = previous viewport) }; diff --git a/imgui_internal.h b/imgui_internal.h index 3dc1b434..17f7c7ef 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -546,7 +546,7 @@ struct ImGuiViewport bool PlatformRequestResize; // Platform window requested resize void* RendererUserData; // void* to hold custom data structure for the renderer (e.g. framebuffer) - ImGuiViewport(ImGuiID id, int idx) { ID = id; Idx = idx; Flags = 0; LastFrameActive = LastFrameAsRefViewport = -1; LastNameHash = 0; Window = NULL; PlatformDpiScale = 1.0f; PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestResize = false; RendererUserData = NULL; } + ImGuiViewport(ImGuiID id, int idx) { ID = id; Idx = idx; Flags = 0; LastFrameActive = LastFrameAsRefViewport = -1; LastNameHash = 0; Window = NULL; PlatformDpiScale = 0.0f; PlatformUserData = PlatformHandle = NULL; PlatformRequestClose = PlatformRequestResize = false; RendererUserData = NULL; } ~ImGuiViewport() { IM_ASSERT(PlatformUserData == NULL && RendererUserData == NULL); } ImRect GetRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); } float GetNextX() const { const float SPACING = 4.0f; return Pos.x + Size.x + SPACING; } @@ -1092,6 +1092,7 @@ namespace ImGui IMGUI_API ImGuiViewport* FindViewportByID(ImGuiID id); IMGUI_API ImGuiViewport* FindViewportByPlatformHandle(void* platform_handle); IMGUI_API void SetNextWindowViewport(ImGuiID id); + IMGUI_API void ScaleWindowsInViewport(ImGuiViewport* viewport, float scale); IMGUI_API void ShowViewportThumbnails(); IMGUI_API void DestroyViewportsPlaformData(ImGuiContext* context); IMGUI_API void DestroyViewportsRendererData(ImGuiContext* context);