mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-15 19:43:28 +01: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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user