Viewport: extracted code out of Begin() into WindowSyncOwnedViewport() - no other change

This commit is contained in:
ocornut 2021-06-17 16:12:22 +02:00
parent 9b417b26d9
commit afabb2f3d8

173
imgui.cpp
View File

@ -946,7 +946,8 @@ const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbi
static ImGuiViewportP* AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const ImVec2& platform_pos, const ImVec2& size, ImGuiViewportFlags flags);
static void UpdateViewportsNewFrame();
static void UpdateViewportsEndFrame();
static void UpdateSelectWindowViewport(ImGuiWindow* window);
static void WindowSelectViewport(ImGuiWindow* window);
static void WindowSyncOwnedViewport(ImGuiWindow* window, ImGuiWindow* parent_window_in_stack);
static bool UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* host_viewport);
static bool UpdateTryMergeWindowIntoHostViewports(ImGuiWindow* window);
static bool GetWindowAlwaysWantOwnViewport(ImGuiWindow* window);
@ -6315,7 +6316,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// SELECT VIEWPORT
// We need to do this before using any style/font sizes, as viewport with a different DPI may affect font sizes.
UpdateSelectWindowViewport(window);
WindowSelectViewport(window);
SetCurrentViewport(window, window->Viewport);
window->FontDpiScale = (g.IO.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts) ? window->Viewport->DpiScale : 1.0f;
SetCurrentWindow(window);
@ -6447,85 +6448,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
SetCurrentWindow(window);
}
bool viewport_rect_changed = false;
if (window->ViewportOwned)
{
// Synchronize window --> viewport in most situations
// Synchronize viewport -> window in case the platform window has been moved or resized from the OS/WM
if (window->Viewport->PlatformRequestMove)
{
window->Pos = window->Viewport->Pos;
MarkIniSettingsDirty(window);
}
else if (memcmp(&window->Viewport->Pos, &window->Pos, sizeof(window->Pos)) != 0)
{
viewport_rect_changed = true;
window->Viewport->Pos = window->Pos;
}
if (window->Viewport->PlatformRequestResize)
{
window->Size = window->SizeFull = window->Viewport->Size;
MarkIniSettingsDirty(window);
}
else if (memcmp(&window->Viewport->Size, &window->Size, sizeof(window->Size)) != 0)
{
viewport_rect_changed = true;
window->Viewport->Size = window->Size;
}
window->Viewport->UpdateWorkRect();
// The viewport may have changed monitor since the global update in UpdateViewportsNewFrame()
// Either a SetNextWindowPos() call in the current frame or a SetWindowPos() call in the previous frame may have this effect.
if (viewport_rect_changed)
UpdateViewportPlatformMonitor(window->Viewport);
// Update common viewport flags
const ImGuiViewportFlags viewport_flags_to_clear = ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoRendererClear;
ImGuiViewportFlags viewport_flags = window->Viewport->Flags & ~viewport_flags_to_clear;
const bool is_modal = (flags & ImGuiWindowFlags_Modal) != 0;
const bool is_short_lived_floating_window = (flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0;
if (flags & ImGuiWindowFlags_Tooltip)
viewport_flags |= ImGuiViewportFlags_TopMost;
if ((g.IO.ConfigViewportsNoTaskBarIcon || is_short_lived_floating_window) && !is_modal)
viewport_flags |= ImGuiViewportFlags_NoTaskBarIcon;
if (g.IO.ConfigViewportsNoDecoration || is_short_lived_floating_window)
viewport_flags |= ImGuiViewportFlags_NoDecoration;
// Not correct to set modal as topmost because:
// - Because other popups can be stacked above a modal (e.g. combo box in a modal)
// - ImGuiViewportFlags_TopMost is currently handled different in backends: in Win32 it is "appear top most" whereas in GLFW and SDL it is "stay topmost"
//if (flags & ImGuiWindowFlags_Modal)
// viewport_flags |= ImGuiViewportFlags_TopMost;
// For popups and menus that may be protruding out of their parent viewport, we enable _NoFocusOnClick so that clicking on them
// won't steal the OS focus away from their parent window (which may be reflected in OS the title bar decoration).
// Setting _NoFocusOnClick would technically prevent us from bringing back to front in case they are being covered by an OS window from a different app,
// but it shouldn't be much of a problem considering those are already popups that are closed when clicking elsewhere.
if (is_short_lived_floating_window && !is_modal)
viewport_flags |= ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoFocusOnClick;
// We can overwrite viewport flags using ImGuiWindowClass (advanced users)
// We don't default to the main viewport because.
if (window->WindowClass.ParentViewportId)
window->Viewport->ParentViewportId = window->WindowClass.ParentViewportId;
else if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && parent_window_in_stack)
window->Viewport->ParentViewportId = parent_window_in_stack->Viewport->ID;
else
window->Viewport->ParentViewportId = g.IO.ConfigViewportsNoDefaultParent ? 0 : IMGUI_VIEWPORT_DEFAULT_ID;
if (window->WindowClass.ViewportFlagsOverrideSet)
viewport_flags |= window->WindowClass.ViewportFlagsOverrideSet;
if (window->WindowClass.ViewportFlagsOverrideClear)
viewport_flags &= ~window->WindowClass.ViewportFlagsOverrideClear;
// We can also tell the backend that clearing the platform window won't be necessary,
// as our window background is filling the viewport and we have disabled BgAlpha.
// FIXME: Work on support for per-viewport transparency (#2766)
if (!(flags & ImGuiWindowFlags_NoBackground))
viewport_flags |= ImGuiViewportFlags_NoRendererClear;
window->Viewport->Flags = viewport_flags;
}
WindowSyncOwnedViewport(window, parent_window_in_stack);
// Calculate the range of allowed position for that window (to be movable and visible past safe area padding)
// When clamping to stay visible, we will enforce that window->Pos stays inside of visibility_rect.
@ -11409,7 +11333,8 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
// - UpdateViewportsNewFrame() [Internal]
// - UpdateViewportsEndFrame() [Internal]
// - AddUpdateViewport() [Internal]
// - UpdateSelectWindowViewport() [Internal]
// - WindowSelectViewport() [Internal]
// - WindowSyncOwnedViewport() [Internal]
// - UpdatePlatformWindows()
// - RenderPlatformWindowsDefault()
// - FindPlatformMonitorForPos() [Internal]
@ -11425,6 +11350,7 @@ ImGuiViewport* ImGui::GetMainViewport()
return g.Viewports[0];
}
// FIXME: This leaks access to viewports not listed in PlatformIO.Viewports[]. Problematic? (#4236)
ImGuiViewport* ImGui::FindViewportByID(ImGuiID id)
{
ImGuiContext& g = *GImGui;
@ -11856,7 +11782,7 @@ ImGuiViewportP* ImGui::AddUpdateViewport(ImGuiWindow* window, ImGuiID id, const
}
// FIXME-VIEWPORT: This is all super messy and ought to be clarified or rewritten.
static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
static void ImGui::WindowSelectViewport(ImGuiWindow* window)
{
ImGuiContext& g = *GImGui;
ImGuiWindowFlags flags = window->Flags;
@ -11983,6 +11909,89 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
// window->Flags |= ImGuiWindowFlags_NoTitleBar;
}
void ImGui::WindowSyncOwnedViewport(ImGuiWindow* window, ImGuiWindow* parent_window_in_stack)
{
ImGuiContext& g = *GImGui;
bool viewport_rect_changed = false;
// Synchronize window --> viewport in most situations
// Synchronize viewport -> window in case the platform window has been moved or resized from the OS/WM
if (window->Viewport->PlatformRequestMove)
{
window->Pos = window->Viewport->Pos;
MarkIniSettingsDirty(window);
}
else if (memcmp(&window->Viewport->Pos, &window->Pos, sizeof(window->Pos)) != 0)
{
viewport_rect_changed = true;
window->Viewport->Pos = window->Pos;
}
if (window->Viewport->PlatformRequestResize)
{
window->Size = window->SizeFull = window->Viewport->Size;
MarkIniSettingsDirty(window);
}
else if (memcmp(&window->Viewport->Size, &window->Size, sizeof(window->Size)) != 0)
{
viewport_rect_changed = true;
window->Viewport->Size = window->Size;
}
window->Viewport->UpdateWorkRect();
// The viewport may have changed monitor since the global update in UpdateViewportsNewFrame()
// Either a SetNextWindowPos() call in the current frame or a SetWindowPos() call in the previous frame may have this effect.
if (viewport_rect_changed)
UpdateViewportPlatformMonitor(window->Viewport);
// Update common viewport flags
const ImGuiViewportFlags viewport_flags_to_clear = ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration | ImGuiViewportFlags_NoRendererClear;
ImGuiViewportFlags viewport_flags = window->Viewport->Flags & ~viewport_flags_to_clear;
ImGuiWindowFlags window_flags = window->Flags;
const bool is_modal = (window_flags & ImGuiWindowFlags_Modal) != 0;
const bool is_short_lived_floating_window = (window_flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0;
if (window_flags & ImGuiWindowFlags_Tooltip)
viewport_flags |= ImGuiViewportFlags_TopMost;
if ((g.IO.ConfigViewportsNoTaskBarIcon || is_short_lived_floating_window) && !is_modal)
viewport_flags |= ImGuiViewportFlags_NoTaskBarIcon;
if (g.IO.ConfigViewportsNoDecoration || is_short_lived_floating_window)
viewport_flags |= ImGuiViewportFlags_NoDecoration;
// Not correct to set modal as topmost because:
// - Because other popups can be stacked above a modal (e.g. combo box in a modal)
// - ImGuiViewportFlags_TopMost is currently handled different in backends: in Win32 it is "appear top most" whereas in GLFW and SDL it is "stay topmost"
//if (flags & ImGuiWindowFlags_Modal)
// viewport_flags |= ImGuiViewportFlags_TopMost;
// For popups and menus that may be protruding out of their parent viewport, we enable _NoFocusOnClick so that clicking on them
// won't steal the OS focus away from their parent window (which may be reflected in OS the title bar decoration).
// Setting _NoFocusOnClick would technically prevent us from bringing back to front in case they are being covered by an OS window from a different app,
// but it shouldn't be much of a problem considering those are already popups that are closed when clicking elsewhere.
if (is_short_lived_floating_window && !is_modal)
viewport_flags |= ImGuiViewportFlags_NoFocusOnAppearing | ImGuiViewportFlags_NoFocusOnClick;
// We can overwrite viewport flags using ImGuiWindowClass (advanced users)
if (window->WindowClass.ParentViewportId)
window->Viewport->ParentViewportId = window->WindowClass.ParentViewportId;
else if ((window_flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && parent_window_in_stack)
window->Viewport->ParentViewportId = parent_window_in_stack->Viewport->ID;
else
window->Viewport->ParentViewportId = g.IO.ConfigViewportsNoDefaultParent ? 0 : IMGUI_VIEWPORT_DEFAULT_ID;
if (window->WindowClass.ViewportFlagsOverrideSet)
viewport_flags |= window->WindowClass.ViewportFlagsOverrideSet;
if (window->WindowClass.ViewportFlagsOverrideClear)
viewport_flags &= ~window->WindowClass.ViewportFlagsOverrideClear;
// We can also tell the backend that clearing the platform window won't be necessary,
// as our window background is filling the viewport and we have disabled BgAlpha.
// FIXME: Work on support for per-viewport transparency (#2766)
if (!(window_flags & ImGuiWindowFlags_NoBackground))
viewport_flags |= ImGuiViewportFlags_NoRendererClear;
window->Viewport->Flags = viewport_flags;
}
// Called by user at the end of the main loop, after EndFrame()
// This will handle the creation/update of all OS windows via function defined in the ImGuiPlatformIO api.
void ImGui::UpdatePlatformWindows()