mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-15 09:27:00 +00:00
Refactor: Move viewport code under other subsystem to simplify merging (2) (moving in multiple commits to make diff/patch behave nicely)
This commit is contained in:
parent
bbb543fc16
commit
bdf60dac6a
485
imgui.cpp
485
imgui.cpp
@ -7791,246 +7791,6 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
|
|||||||
// [SECTION] VIEWPORTS, PLATFORM WINDOWS
|
// [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.
|
// FIXME-VIEWPORT: This is all super messy and ought to be clarified or rewritten.
|
||||||
static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
|
static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
|
||||||
{
|
{
|
||||||
@ -8045,7 +7805,6 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
|
|||||||
SetWindowViewport(window, main_viewport);
|
SetWindowViewport(window, main_viewport);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window->ViewportOwned = false;
|
window->ViewportOwned = false;
|
||||||
|
|
||||||
// Appearing popups reset their viewport so they can inherit again
|
// 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);
|
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
|
// Regular (non-child, non-popup) windows by default are also allowed to protrude
|
||||||
// Child windows are kept contained within their parent.
|
// Child windows are kept contained within their parent.
|
||||||
else if (window->ViewportAllowPlatformMonitorExtend < 0 && (flags & ImGuiWindowFlags_ChildWindow) == 0)
|
else if (window->ViewportAllowPlatformMonitorExtend < 0 && (flags & ImGuiWindowFlags_ChildWindow) == 0)
|
||||||
@ -8146,12 +7904,11 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
|
|||||||
|
|
||||||
// Update flags
|
// Update flags
|
||||||
window->ViewportOwned = (window == window->Viewport->Window);
|
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 the OS window has a title bar, hide our imgui title bar
|
||||||
//if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration))
|
//if (window->ViewportOwned && !(window->Viewport->Flags & ImGuiViewportFlags_NoDecoration))
|
||||||
// window->Flags |= ImGuiWindowFlags_NoTitleBar;
|
// window->Flags |= ImGuiWindowFlags_NoTitleBar;
|
||||||
|
|
||||||
window->ViewportId = window->Viewport->ID;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by user at the end of the main loop, after EndFrame()
|
// 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;
|
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
|
// [SECTION] DOCKING
|
||||||
|
Loading…
Reference in New Issue
Block a user