|
@@ -7791,246 +7791,6 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
|
|
|
// [SECTION] VIEWPORTS, PLATFORM WINDOWS
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
-static void ImGui::UpdateViewportsNewFrame()
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- IM_ASSERT(g.PlatformIO.Viewports.Size <= g.Viewports.Size);
|
|
|
-
|
|
|
- // Update Minimized status (we need it first in order to decide if we'll apply Pos/Size of the main viewport)
|
|
|
- for (int n = 0; n < g.Viewports.Size; n++)
|
|
|
- {
|
|
|
- ImGuiViewportP* viewport = g.Viewports[n];
|
|
|
- const bool platform_funcs_available = (n == 0 || viewport->PlatformWindowCreated);
|
|
|
- if ((g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable))
|
|
|
- if (g.PlatformIO.Platform_GetWindowMinimized && platform_funcs_available)
|
|
|
- viewport->PlatformWindowMinimized = g.PlatformIO.Platform_GetWindowMinimized(viewport);
|
|
|
- }
|
|
|
-
|
|
|
- // Create/update main viewport with current platform position and size
|
|
|
- ImGuiViewportP* main_viewport = g.Viewports[0];
|
|
|
- IM_ASSERT(main_viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID);
|
|
|
- IM_ASSERT(main_viewport->Window == NULL);
|
|
|
- ImVec2 main_viewport_platform_pos = ImVec2(0.0f, 0.0f);
|
|
|
- ImVec2 main_viewport_platform_size = g.IO.DisplaySize;
|
|
|
- if (g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable)
|
|
|
- main_viewport_platform_pos = main_viewport->PlatformWindowMinimized ? main_viewport->Pos : g.PlatformIO.Platform_GetWindowPos(main_viewport);
|
|
|
- AddUpdateViewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, main_viewport_platform_pos, main_viewport_platform_size, ImGuiViewportFlags_CanHostOtherWindows);
|
|
|
-
|
|
|
- g.CurrentViewport = NULL;
|
|
|
- g.MouseViewport = NULL;
|
|
|
- for (int n = 0; n < g.Viewports.Size; n++)
|
|
|
- {
|
|
|
- // Erase unused viewports
|
|
|
- ImGuiViewportP* viewport = g.Viewports[n];
|
|
|
- viewport->Idx = n;
|
|
|
-
|
|
|
- if (n > 0 && viewport->LastFrameActive < g.FrameCount - 2)
|
|
|
- {
|
|
|
- // Clear references to this viewport in windows (window->ViewportId becomes the master data)
|
|
|
- for (int window_n = 0; window_n < g.Windows.Size; window_n++)
|
|
|
- if (g.Windows[window_n]->Viewport == viewport)
|
|
|
- {
|
|
|
- g.Windows[window_n]->Viewport = NULL;
|
|
|
- g.Windows[window_n]->ViewportOwned = false;
|
|
|
- }
|
|
|
- if (viewport == g.MouseLastHoveredViewport)
|
|
|
- g.MouseLastHoveredViewport = NULL;
|
|
|
- g.Viewports.erase(g.Viewports.Data + n);
|
|
|
-
|
|
|
- // Destroy
|
|
|
- //IMGUI_DEBUG_LOG("Delete Viewport %08X (%s)\n", viewport->ID, viewport->Window ? viewport->Window->Name : "n/a");
|
|
|
- DestroyPlatformWindow(viewport); // In most circumstances the platform window will already be destroyed here.
|
|
|
- IM_ASSERT(g.PlatformIO.Viewports.contains(viewport) == false);
|
|
|
- IM_DELETE(viewport);
|
|
|
- n--;
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- const bool platform_funcs_available = (n == 0 || viewport->PlatformWindowCreated);
|
|
|
- if ((g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable))
|
|
|
- {
|
|
|
- // Update Position and Size (from Platform Window to ImGui) if requested.
|
|
|
- // We do it early in the frame instead of waiting for UpdatePlatformWindows() to avoid a frame of lag when moving/resizing using OS facilities.
|
|
|
- if (!viewport->PlatformWindowMinimized && platform_funcs_available)
|
|
|
- {
|
|
|
- if (viewport->PlatformRequestMove)
|
|
|
- viewport->Pos = viewport->LastPlatformPos = g.PlatformIO.Platform_GetWindowPos(viewport);
|
|
|
- if (viewport->PlatformRequestResize)
|
|
|
- viewport->Size = viewport->LastPlatformSize = g.PlatformIO.Platform_GetWindowSize(viewport);
|
|
|
- }
|
|
|
-
|
|
|
- // Update monitor (we'll use this info to clamp windows and save windows lost in a removed monitor)
|
|
|
- viewport->PlatformMonitor = (short)FindPlatformMonitorForRect(viewport->GetRect());
|
|
|
- }
|
|
|
-
|
|
|
- // Reset alpha every frame. Users of transparency (docking) needs to request a lower alpha back.
|
|
|
- viewport->Alpha = 1.0f;
|
|
|
-
|
|
|
- // Translate imgui windows when a Host Viewport has been moved
|
|
|
- // (This additionally keeps windows at the same place when ImGuiConfigFlags_ViewportsEnable is toggled!)
|
|
|
- ImVec2 viewport_delta = viewport->Pos - viewport->LastPos;
|
|
|
- if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) && (viewport_delta.x != 0.0f || viewport_delta.y != 0.0f))
|
|
|
- for (int window_n = 0; window_n < g.Windows.Size; window_n++)
|
|
|
- if (g.Windows[window_n]->Viewport == viewport || (g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable) == 0)
|
|
|
- TranslateWindow(g.Windows[window_n], viewport_delta);
|
|
|
-
|
|
|
- // Update DPI scale
|
|
|
- float new_dpi_scale;
|
|
|
- if (g.PlatformIO.Platform_GetWindowDpiScale && platform_funcs_available)
|
|
|
- new_dpi_scale = g.PlatformIO.Platform_GetWindowDpiScale(viewport);
|
|
|
- else if (viewport->PlatformMonitor != -1)
|
|
|
- new_dpi_scale = g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
|
|
|
- else
|
|
|
- new_dpi_scale = (viewport->DpiScale != 0.0f) ? viewport->DpiScale : 1.0f;
|
|
|
- if (viewport->DpiScale != 0.0f && new_dpi_scale != viewport->DpiScale)
|
|
|
- {
|
|
|
- float scale_factor = new_dpi_scale / viewport->DpiScale;
|
|
|
- if (g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
|
|
|
- ScaleWindowsInViewport(viewport, scale_factor);
|
|
|
- //if (viewport == GetMainViewport())
|
|
|
- // g.PlatformInterface.SetWindowSize(viewport, viewport->Size * scale_factor);
|
|
|
-
|
|
|
- // Scale our window moving pivot so that the window will rescale roughly around the mouse position.
|
|
|
- // FIXME-VIEWPORT: This currently creates a resizing feedback loop when a window is straddling a DPI transition border.
|
|
|
- // (Minor: since our sizes do not perfectly linearly scale, deferring the click offset scale until we know the actual window scale ratio may get us slightly more precise mouse positioning.)
|
|
|
- //if (g.MovingWindow != NULL && g.MovingWindow->Viewport == viewport)
|
|
|
- // g.ActiveIdClickOffset = ImFloor(g.ActiveIdClickOffset * scale_factor);
|
|
|
- }
|
|
|
- viewport->DpiScale = new_dpi_scale;
|
|
|
- }
|
|
|
-
|
|
|
- if (!(g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable))
|
|
|
- {
|
|
|
- g.MouseViewport = main_viewport;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Mouse handling: decide on the actual mouse viewport for this frame between the active/focused viewport and the hovered viewport.
|
|
|
- // Note that 'viewport_hovered' should skip over any viewport that has the ImGuiViewportFlags_NoInputs flags set.
|
|
|
- ImGuiViewportP* viewport_hovered = NULL;
|
|
|
- if (g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport)
|
|
|
- {
|
|
|
- viewport_hovered = g.IO.MouseHoveredViewport ? (ImGuiViewportP*)FindViewportByID(g.IO.MouseHoveredViewport) : NULL;
|
|
|
- if (viewport_hovered && (viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
|
|
|
- {
|
|
|
- // Back-end failed at honoring its contract if it returned a viewport with the _NoInputs flag.
|
|
|
- IM_ASSERT(0);
|
|
|
- viewport_hovered = FindViewportHoveredFromPlatformWindowStack(g.IO.MousePos);
|
|
|
- }
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // If the back-end doesn't know how to honor ImGuiViewportFlags_NoInputs, we do a search ourselves. Note that this search:
|
|
|
- // A) won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
|
|
|
- // B) uses LastFrameAsRefViewport as a flawed replacement for the last time a window was focused (we could/should fix that by introducing Focus functions in PlatformIO)
|
|
|
- viewport_hovered = FindViewportHoveredFromPlatformWindowStack(g.IO.MousePos);
|
|
|
- }
|
|
|
- if (viewport_hovered != NULL)
|
|
|
- g.MouseLastHoveredViewport = viewport_hovered;
|
|
|
- else if (g.MouseLastHoveredViewport == NULL)
|
|
|
- g.MouseLastHoveredViewport = g.Viewports[0];
|
|
|
-
|
|
|
- // Update mouse reference viewport
|
|
|
- // (when moving a window we aim at its viewport, but this will be overwritten below if we go in drag and drop mode)
|
|
|
- if (g.MovingWindow)
|
|
|
- g.MouseViewport = g.MovingWindow->Viewport;
|
|
|
- else
|
|
|
- g.MouseViewport = g.MouseLastHoveredViewport;
|
|
|
-
|
|
|
- // When dragging something, always refer to the last hovered viewport.
|
|
|
- // - when releasing a moving window we will revert to aiming behind (at viewport_hovered)
|
|
|
- // - when we are between viewports, our dragged preview will tend to show in the last viewport _even_ if we don't have tooltips in their viewports (when lacking monitor info)
|
|
|
- // - consider the case of holding on a menu item to browse child menus: even thou a mouse button is held, there's no active id because menu items only react on mouse release.
|
|
|
- const bool is_mouse_dragging_with_an_expected_destination = g.DragDropActive;
|
|
|
- if (is_mouse_dragging_with_an_expected_destination && viewport_hovered == NULL)
|
|
|
- viewport_hovered = g.MouseLastHoveredViewport;
|
|
|
- if (is_mouse_dragging_with_an_expected_destination || g.ActiveId == 0 || !IsAnyMouseDown())
|
|
|
- if (viewport_hovered != NULL && viewport_hovered != g.MouseViewport && !(viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
|
|
|
- g.MouseViewport = viewport_hovered;
|
|
|
-
|
|
|
- IM_ASSERT(g.MouseViewport != NULL);
|
|
|
-}
|
|
|
-
|
|
|
-// Update user-facing viewport list (g.Viewports -> g.PlatformIO.Viewports after filtering out some)
|
|
|
-static void ImGui::UpdateViewportsEndFrame()
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- g.PlatformIO.MainViewport = g.Viewports[0];
|
|
|
- g.PlatformIO.Viewports.resize(0);
|
|
|
- for (int i = 0; i < g.Viewports.Size; i++)
|
|
|
- {
|
|
|
- ImGuiViewportP* viewport = g.Viewports[i];
|
|
|
- viewport->LastPos = viewport->Pos;
|
|
|
- if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f)
|
|
|
- if (i > 0) // Always include main viewport in the list
|
|
|
- continue;
|
|
|
- if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window))
|
|
|
- continue;
|
|
|
- if (i > 0)
|
|
|
- IM_ASSERT(viewport->Window != NULL);
|
|
|
- g.PlatformIO.Viewports.push_back(viewport);
|
|
|
- }
|
|
|
- g.Viewports[0]->ClearRequestFlags(); // Clear main viewport flags because UpdatePlatformWindows() won't do it and may not even be called
|
|
|
-}
|
|
|
-
|
|
|
-// FIXME: We should ideally refactor the system to call this every frame (we currently don't)
|
|
|
-ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& pos, const ImVec2& size, ImGuiViewportFlags flags)
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- IM_ASSERT(id != 0);
|
|
|
-
|
|
|
- if (window != NULL)
|
|
|
- {
|
|
|
- if (g.MovingWindow && g.MovingWindow->RootWindow == window)
|
|
|
- flags |= ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_NoFocusOnAppearing;
|
|
|
- if ((window->Flags & ImGuiWindowFlags_NoMouseInputs) && (window->Flags & ImGuiWindowFlags_NoNavInputs))
|
|
|
- flags |= ImGuiViewportFlags_NoInputs;
|
|
|
- if (window->Flags & ImGuiWindowFlags_NoFocusOnAppearing)
|
|
|
- flags |= ImGuiViewportFlags_NoFocusOnAppearing;
|
|
|
- }
|
|
|
-
|
|
|
- ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(id);
|
|
|
- if (viewport)
|
|
|
- {
|
|
|
- if (!viewport->PlatformRequestMove)
|
|
|
- viewport->Pos = pos;
|
|
|
- if (!viewport->PlatformRequestResize)
|
|
|
- viewport->Size = size;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- // New viewport
|
|
|
- viewport = IM_NEW(ImGuiViewportP)();
|
|
|
- viewport->ID = id;
|
|
|
- viewport->Idx = g.Viewports.Size;
|
|
|
- viewport->Pos = viewport->LastPos = pos;
|
|
|
- viewport->Size = size;
|
|
|
- viewport->PlatformMonitor = (short)FindPlatformMonitorForRect(viewport->GetRect());
|
|
|
- g.Viewports.push_back(viewport);
|
|
|
- //IMGUI_DEBUG_LOG("Add Viewport %08X (%s)\n", id, window->Name);
|
|
|
-
|
|
|
- // We normally setup for all viewports in NewFrame() but here need to handle the mid-frame creation of a new viewport.
|
|
|
- // We need to extend the fullscreen clip rect so the OverlayDrawList clip is correct for that the first frame
|
|
|
- g.DrawListSharedData.ClipRectFullscreen.z = ImMax(g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x);
|
|
|
- g.DrawListSharedData.ClipRectFullscreen.w = ImMax(g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y);
|
|
|
-
|
|
|
- // Store initial DpiScale before the OS platform window creation, based on expected monitor data.
|
|
|
- // This is so we can select an appropriate font size on the first frame of our window lifetime
|
|
|
- if (viewport->PlatformMonitor != -1)
|
|
|
- viewport->DpiScale = g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
|
|
|
- }
|
|
|
-
|
|
|
- viewport->Window = window;
|
|
|
- viewport->Flags = flags;
|
|
|
- viewport->LastFrameActive = g.FrameCount;
|
|
|
- IM_ASSERT(window == NULL || viewport->ID == window->ID);
|
|
|
-
|
|
|
- if (window != NULL)
|
|
|
- window->ViewportOwned = true;
|
|
|
-
|
|
|
- return viewport;
|
|
|
-}
|
|
|
-
|
|
|
// FIXME-VIEWPORT: This is all super messy and ought to be clarified or rewritten.
|
|
|
static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
|
|
|
{
|
|
@@ -8045,7 +7805,6 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
|
|
|
SetWindowViewport(window, main_viewport);
|
|
|
return;
|
|
|
}
|
|
|
-
|
|
|
window->ViewportOwned = false;
|
|
|
|
|
|
// Appearing popups reset their viewport so they can inherit again
|
|
@@ -8138,7 +7897,6 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
|
|
|
window->Viewport = AddUpdateViewport(window, window->ID, window->Pos, window->Size, ImGuiViewportFlags_NoFocusOnAppearing);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
// Regular (non-child, non-popup) windows by default are also allowed to protrude
|
|
|
// Child windows are kept contained within their parent.
|
|
|
else if (window->ViewportAllowPlatformMonitorExtend < 0 && (flags & ImGuiWindowFlags_ChildWindow) == 0)
|
|
@@ -8146,12 +7904,11 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
|
|
|
|
|
|
// Update flags
|
|
|
window->ViewportOwned = (window == window->Viewport->Window);
|
|
|
+ window->ViewportId = window->Viewport->ID;
|
|
|
|
|
|
// If the OS window has a title bar, hide our imgui title bar
|
|
|
//if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration))
|
|
|
// window->Flags |= ImGuiWindowFlags_NoTitleBar;
|
|
|
-
|
|
|
- window->ViewportId = window->Viewport->ID;
|
|
|
}
|
|
|
|
|
|
// Called by user at the end of the main loop, after EndFrame()
|
|
@@ -10616,6 +10373,246 @@ static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 m
|
|
|
return best_candidate;
|
|
|
}
|
|
|
|
|
|
+static void ImGui::UpdateViewportsNewFrame()
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ IM_ASSERT(g.PlatformIO.Viewports.Size <= g.Viewports.Size);
|
|
|
+
|
|
|
+ // Update Minimized status (we need it first in order to decide if we'll apply Pos/Size of the main viewport)
|
|
|
+ for (int n = 0; n < g.Viewports.Size; n++)
|
|
|
+ {
|
|
|
+ ImGuiViewportP* viewport = g.Viewports[n];
|
|
|
+ const bool platform_funcs_available = (n == 0 || viewport->PlatformWindowCreated);
|
|
|
+ if ((g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable))
|
|
|
+ if (g.PlatformIO.Platform_GetWindowMinimized && platform_funcs_available)
|
|
|
+ viewport->PlatformWindowMinimized = g.PlatformIO.Platform_GetWindowMinimized(viewport);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create/update main viewport with current platform position and size
|
|
|
+ ImGuiViewportP* main_viewport = g.Viewports[0];
|
|
|
+ IM_ASSERT(main_viewport->ID == IMGUI_VIEWPORT_DEFAULT_ID);
|
|
|
+ IM_ASSERT(main_viewport->Window == NULL);
|
|
|
+ ImVec2 main_viewport_platform_pos = ImVec2(0.0f, 0.0f);
|
|
|
+ ImVec2 main_viewport_platform_size = g.IO.DisplaySize;
|
|
|
+ if (g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable)
|
|
|
+ main_viewport_platform_pos = main_viewport->PlatformWindowMinimized ? main_viewport->Pos : g.PlatformIO.Platform_GetWindowPos(main_viewport);
|
|
|
+ AddUpdateViewport(NULL, IMGUI_VIEWPORT_DEFAULT_ID, main_viewport_platform_pos, main_viewport_platform_size, ImGuiViewportFlags_CanHostOtherWindows);
|
|
|
+
|
|
|
+ g.CurrentViewport = NULL;
|
|
|
+ g.MouseViewport = NULL;
|
|
|
+ for (int n = 0; n < g.Viewports.Size; n++)
|
|
|
+ {
|
|
|
+ // Erase unused viewports
|
|
|
+ ImGuiViewportP* viewport = g.Viewports[n];
|
|
|
+ viewport->Idx = n;
|
|
|
+
|
|
|
+ if (n > 0 && viewport->LastFrameActive < g.FrameCount - 2)
|
|
|
+ {
|
|
|
+ // Clear references to this viewport in windows (window->ViewportId becomes the master data)
|
|
|
+ for (int window_n = 0; window_n < g.Windows.Size; window_n++)
|
|
|
+ if (g.Windows[window_n]->Viewport == viewport)
|
|
|
+ {
|
|
|
+ g.Windows[window_n]->Viewport = NULL;
|
|
|
+ g.Windows[window_n]->ViewportOwned = false;
|
|
|
+ }
|
|
|
+ if (viewport == g.MouseLastHoveredViewport)
|
|
|
+ g.MouseLastHoveredViewport = NULL;
|
|
|
+ g.Viewports.erase(g.Viewports.Data + n);
|
|
|
+
|
|
|
+ // Destroy
|
|
|
+ //IMGUI_DEBUG_LOG("Delete Viewport %08X (%s)\n", viewport->ID, viewport->Window ? viewport->Window->Name : "n/a");
|
|
|
+ DestroyPlatformWindow(viewport); // In most circumstances the platform window will already be destroyed here.
|
|
|
+ IM_ASSERT(g.PlatformIO.Viewports.contains(viewport) == false);
|
|
|
+ IM_DELETE(viewport);
|
|
|
+ n--;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ const bool platform_funcs_available = (n == 0 || viewport->PlatformWindowCreated);
|
|
|
+ if ((g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable))
|
|
|
+ {
|
|
|
+ // Update Position and Size (from Platform Window to ImGui) if requested.
|
|
|
+ // We do it early in the frame instead of waiting for UpdatePlatformWindows() to avoid a frame of lag when moving/resizing using OS facilities.
|
|
|
+ if (!viewport->PlatformWindowMinimized && platform_funcs_available)
|
|
|
+ {
|
|
|
+ if (viewport->PlatformRequestMove)
|
|
|
+ viewport->Pos = viewport->LastPlatformPos = g.PlatformIO.Platform_GetWindowPos(viewport);
|
|
|
+ if (viewport->PlatformRequestResize)
|
|
|
+ viewport->Size = viewport->LastPlatformSize = g.PlatformIO.Platform_GetWindowSize(viewport);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Update monitor (we'll use this info to clamp windows and save windows lost in a removed monitor)
|
|
|
+ viewport->PlatformMonitor = (short)FindPlatformMonitorForRect(viewport->GetRect());
|
|
|
+ }
|
|
|
+
|
|
|
+ // Reset alpha every frame. Users of transparency (docking) needs to request a lower alpha back.
|
|
|
+ viewport->Alpha = 1.0f;
|
|
|
+
|
|
|
+ // Translate imgui windows when a Host Viewport has been moved
|
|
|
+ // (This additionally keeps windows at the same place when ImGuiConfigFlags_ViewportsEnable is toggled!)
|
|
|
+ ImVec2 viewport_delta = viewport->Pos - viewport->LastPos;
|
|
|
+ if ((viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) && (viewport_delta.x != 0.0f || viewport_delta.y != 0.0f))
|
|
|
+ for (int window_n = 0; window_n < g.Windows.Size; window_n++)
|
|
|
+ if (g.Windows[window_n]->Viewport == viewport || (g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable) == 0)
|
|
|
+ TranslateWindow(g.Windows[window_n], viewport_delta);
|
|
|
+
|
|
|
+ // Update DPI scale
|
|
|
+ float new_dpi_scale;
|
|
|
+ if (g.PlatformIO.Platform_GetWindowDpiScale && platform_funcs_available)
|
|
|
+ new_dpi_scale = g.PlatformIO.Platform_GetWindowDpiScale(viewport);
|
|
|
+ else if (viewport->PlatformMonitor != -1)
|
|
|
+ new_dpi_scale = g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
|
|
|
+ else
|
|
|
+ new_dpi_scale = (viewport->DpiScale != 0.0f) ? viewport->DpiScale : 1.0f;
|
|
|
+ if (viewport->DpiScale != 0.0f && new_dpi_scale != viewport->DpiScale)
|
|
|
+ {
|
|
|
+ float scale_factor = new_dpi_scale / viewport->DpiScale;
|
|
|
+ if (g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)
|
|
|
+ ScaleWindowsInViewport(viewport, scale_factor);
|
|
|
+ //if (viewport == GetMainViewport())
|
|
|
+ // g.PlatformInterface.SetWindowSize(viewport, viewport->Size * scale_factor);
|
|
|
+
|
|
|
+ // Scale our window moving pivot so that the window will rescale roughly around the mouse position.
|
|
|
+ // FIXME-VIEWPORT: This currently creates a resizing feedback loop when a window is straddling a DPI transition border.
|
|
|
+ // (Minor: since our sizes do not perfectly linearly scale, deferring the click offset scale until we know the actual window scale ratio may get us slightly more precise mouse positioning.)
|
|
|
+ //if (g.MovingWindow != NULL && g.MovingWindow->Viewport == viewport)
|
|
|
+ // g.ActiveIdClickOffset = ImFloor(g.ActiveIdClickOffset * scale_factor);
|
|
|
+ }
|
|
|
+ viewport->DpiScale = new_dpi_scale;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!(g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable))
|
|
|
+ {
|
|
|
+ g.MouseViewport = main_viewport;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Mouse handling: decide on the actual mouse viewport for this frame between the active/focused viewport and the hovered viewport.
|
|
|
+ // Note that 'viewport_hovered' should skip over any viewport that has the ImGuiViewportFlags_NoInputs flags set.
|
|
|
+ ImGuiViewportP* viewport_hovered = NULL;
|
|
|
+ if (g.IO.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport)
|
|
|
+ {
|
|
|
+ viewport_hovered = g.IO.MouseHoveredViewport ? (ImGuiViewportP*)FindViewportByID(g.IO.MouseHoveredViewport) : NULL;
|
|
|
+ if (viewport_hovered && (viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
|
|
|
+ {
|
|
|
+ // Back-end failed at honoring its contract if it returned a viewport with the _NoInputs flag.
|
|
|
+ IM_ASSERT(0);
|
|
|
+ viewport_hovered = FindViewportHoveredFromPlatformWindowStack(g.IO.MousePos);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // If the back-end doesn't know how to honor ImGuiViewportFlags_NoInputs, we do a search ourselves. Note that this search:
|
|
|
+ // A) won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window.
|
|
|
+ // B) uses LastFrameAsRefViewport as a flawed replacement for the last time a window was focused (we could/should fix that by introducing Focus functions in PlatformIO)
|
|
|
+ viewport_hovered = FindViewportHoveredFromPlatformWindowStack(g.IO.MousePos);
|
|
|
+ }
|
|
|
+ if (viewport_hovered != NULL)
|
|
|
+ g.MouseLastHoveredViewport = viewport_hovered;
|
|
|
+ else if (g.MouseLastHoveredViewport == NULL)
|
|
|
+ g.MouseLastHoveredViewport = g.Viewports[0];
|
|
|
+
|
|
|
+ // Update mouse reference viewport
|
|
|
+ // (when moving a window we aim at its viewport, but this will be overwritten below if we go in drag and drop mode)
|
|
|
+ if (g.MovingWindow)
|
|
|
+ g.MouseViewport = g.MovingWindow->Viewport;
|
|
|
+ else
|
|
|
+ g.MouseViewport = g.MouseLastHoveredViewport;
|
|
|
+
|
|
|
+ // When dragging something, always refer to the last hovered viewport.
|
|
|
+ // - when releasing a moving window we will revert to aiming behind (at viewport_hovered)
|
|
|
+ // - when we are between viewports, our dragged preview will tend to show in the last viewport _even_ if we don't have tooltips in their viewports (when lacking monitor info)
|
|
|
+ // - consider the case of holding on a menu item to browse child menus: even thou a mouse button is held, there's no active id because menu items only react on mouse release.
|
|
|
+ const bool is_mouse_dragging_with_an_expected_destination = g.DragDropActive;
|
|
|
+ if (is_mouse_dragging_with_an_expected_destination && viewport_hovered == NULL)
|
|
|
+ viewport_hovered = g.MouseLastHoveredViewport;
|
|
|
+ if (is_mouse_dragging_with_an_expected_destination || g.ActiveId == 0 || !IsAnyMouseDown())
|
|
|
+ if (viewport_hovered != NULL && viewport_hovered != g.MouseViewport && !(viewport_hovered->Flags & ImGuiViewportFlags_NoInputs))
|
|
|
+ g.MouseViewport = viewport_hovered;
|
|
|
+
|
|
|
+ IM_ASSERT(g.MouseViewport != NULL);
|
|
|
+}
|
|
|
+
|
|
|
+// Update user-facing viewport list (g.Viewports -> g.PlatformIO.Viewports after filtering out some)
|
|
|
+static void ImGui::UpdateViewportsEndFrame()
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ g.PlatformIO.MainViewport = g.Viewports[0];
|
|
|
+ g.PlatformIO.Viewports.resize(0);
|
|
|
+ for (int i = 0; i < g.Viewports.Size; i++)
|
|
|
+ {
|
|
|
+ ImGuiViewportP* viewport = g.Viewports[i];
|
|
|
+ viewport->LastPos = viewport->Pos;
|
|
|
+ if (viewport->LastFrameActive < g.FrameCount || viewport->Size.x <= 0.0f || viewport->Size.y <= 0.0f)
|
|
|
+ if (i > 0) // Always include main viewport in the list
|
|
|
+ continue;
|
|
|
+ if (viewport->Window && !IsWindowActiveAndVisible(viewport->Window))
|
|
|
+ continue;
|
|
|
+ if (i > 0)
|
|
|
+ IM_ASSERT(viewport->Window != NULL);
|
|
|
+ g.PlatformIO.Viewports.push_back(viewport);
|
|
|
+ }
|
|
|
+ g.Viewports[0]->ClearRequestFlags(); // Clear main viewport flags because UpdatePlatformWindows() won't do it and may not even be called
|
|
|
+}
|
|
|
+
|
|
|
+// FIXME: We should ideally refactor the system to call this every frame (we currently don't)
|
|
|
+ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& pos, const ImVec2& size, ImGuiViewportFlags flags)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ IM_ASSERT(id != 0);
|
|
|
+
|
|
|
+ if (window != NULL)
|
|
|
+ {
|
|
|
+ if (g.MovingWindow && g.MovingWindow->RootWindow == window)
|
|
|
+ flags |= ImGuiViewportFlags_NoInputs | ImGuiViewportFlags_NoFocusOnAppearing;
|
|
|
+ if ((window->Flags & ImGuiWindowFlags_NoMouseInputs) && (window->Flags & ImGuiWindowFlags_NoNavInputs))
|
|
|
+ flags |= ImGuiViewportFlags_NoInputs;
|
|
|
+ if (window->Flags & ImGuiWindowFlags_NoFocusOnAppearing)
|
|
|
+ flags |= ImGuiViewportFlags_NoFocusOnAppearing;
|
|
|
+ }
|
|
|
+
|
|
|
+ ImGuiViewportP* viewport = (ImGuiViewportP*)FindViewportByID(id);
|
|
|
+ if (viewport)
|
|
|
+ {
|
|
|
+ if (!viewport->PlatformRequestMove)
|
|
|
+ viewport->Pos = pos;
|
|
|
+ if (!viewport->PlatformRequestResize)
|
|
|
+ viewport->Size = size;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ // New viewport
|
|
|
+ viewport = IM_NEW(ImGuiViewportP)();
|
|
|
+ viewport->ID = id;
|
|
|
+ viewport->Idx = g.Viewports.Size;
|
|
|
+ viewport->Pos = viewport->LastPos = pos;
|
|
|
+ viewport->Size = size;
|
|
|
+ viewport->PlatformMonitor = (short)FindPlatformMonitorForRect(viewport->GetRect());
|
|
|
+ g.Viewports.push_back(viewport);
|
|
|
+ //IMGUI_DEBUG_LOG("Add Viewport %08X (%s)\n", id, window->Name);
|
|
|
+
|
|
|
+ // We normally setup for all viewports in NewFrame() but here need to handle the mid-frame creation of a new viewport.
|
|
|
+ // We need to extend the fullscreen clip rect so the OverlayDrawList clip is correct for that the first frame
|
|
|
+ g.DrawListSharedData.ClipRectFullscreen.z = ImMax(g.DrawListSharedData.ClipRectFullscreen.z, viewport->Pos.x + viewport->Size.x);
|
|
|
+ g.DrawListSharedData.ClipRectFullscreen.w = ImMax(g.DrawListSharedData.ClipRectFullscreen.w, viewport->Pos.y + viewport->Size.y);
|
|
|
+
|
|
|
+ // Store initial DpiScale before the OS platform window creation, based on expected monitor data.
|
|
|
+ // This is so we can select an appropriate font size on the first frame of our window lifetime
|
|
|
+ if (viewport->PlatformMonitor != -1)
|
|
|
+ viewport->DpiScale = g.PlatformIO.Monitors[viewport->PlatformMonitor].DpiScale;
|
|
|
+ }
|
|
|
+
|
|
|
+ viewport->Window = window;
|
|
|
+ viewport->Flags = flags;
|
|
|
+ viewport->LastFrameActive = g.FrameCount;
|
|
|
+ IM_ASSERT(window == NULL || viewport->ID == window->ID);
|
|
|
+
|
|
|
+ if (window != NULL)
|
|
|
+ window->ViewportOwned = true;
|
|
|
+
|
|
|
+ return viewport;
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// [SECTION] DOCKING
|