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:
omar 2019-03-07 18:35:14 +01:00
parent bbb543fc16
commit bdf60dac6a

485
imgui.cpp
View File

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