diff --git a/imgui.cpp b/imgui.cpp index 214cfc05..21d4b2a0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -69,12 +69,12 @@ CODE // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) // [SECTION] TOOLTIPS // [SECTION] POPUPS -// [SECTION] VIEWPORTS, PLATFORM WINDOWS // [SECTION] KEYBOARD/GAMEPAD NAVIGATION // [SECTION] COLUMNS // [SECTION] DRAG AND DROP // [SECTION] LOGGING/CAPTURING // [SECTION] SETTINGS +// [SECTION] VIEWPORTS, PLATFORM WINDOWS // [SECTION] DOCKING // [SECTION] PLATFORM DEPENDENT HELPERS // [SECTION] METRICS/DEBUG WINDOW @@ -7786,135 +7786,11 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) return window->Pos; } + //----------------------------------------------------------------------------- // [SECTION] VIEWPORTS, PLATFORM WINDOWS //----------------------------------------------------------------------------- -ImGuiViewport* ImGui::GetMainViewport() -{ - ImGuiContext& g = *GImGui; - return g.Viewports[0]; -} - -ImGuiViewport* ImGui::FindViewportByID(ImGuiID id) -{ - ImGuiContext& g = *GImGui; - for (int n = 0; n < g.Viewports.Size; n++) - if (g.Viewports[n]->ID == id) - return g.Viewports[n]; - return NULL; -} - -ImGuiViewport* ImGui::FindViewportByPlatformHandle(void* platform_handle) -{ - ImGuiContext& g = *GImGui; - for (int i = 0; i != g.Viewports.Size; i++) - if (g.Viewports[i]->PlatformHandle == platform_handle) - return g.Viewports[i]; - return NULL; -} - -void ImGui::SetCurrentViewport(ImGuiWindow* current_window, ImGuiViewportP* viewport) -{ - ImGuiContext& g = *GImGui; - (void)current_window; - - if (viewport) - viewport->LastFrameActive = g.FrameCount; - if (g.CurrentViewport == viewport) - return; - g.CurrentViewport = viewport; - //IMGUI_DEBUG_LOG("SetCurrentViewport changed '%s' 0x%08X\n", current_window ? current_window->Name : NULL, viewport ? viewport->ID : 0); - - // Notify platform layer of viewport changes - // FIXME-DPI: This is only currently used for experimenting with handling of multiple DPI - if (g.CurrentViewport && g.PlatformIO.Platform_OnChangedViewport) - g.PlatformIO.Platform_OnChangedViewport(g.CurrentViewport); -} - -static void SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport) -{ - window->Viewport = viewport; - window->ViewportId = viewport->ID; - window->ViewportOwned = (viewport->Window == window); -} - -static bool ImGui::GetWindowAlwaysWantOwnViewport(ImGuiWindow* window) -{ - // Tooltips and menus are not automatically forced into their own viewport when the NoMerge flag is set, however the multiplication of viewports makes them more likely to protude and create their own. - ImGuiContext& g = *GImGui; - if (g.IO.ConfigViewportsNoAutoMerge && (g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable)) - if (!window->DockIsActive) - if ((window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) == 0) - return true; - return false; -} - -static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* viewport) -{ - ImGuiContext& g = *GImGui; - if (!(viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) || window->Viewport == viewport || viewport->PlatformWindowMinimized) - return false; - if (!viewport->GetRect().Contains(window->Rect())) - return false; - if (GetWindowAlwaysWantOwnViewport(window)) - return false; - - for (int n = 0; n < g.Windows.Size; n++) - { - ImGuiWindow* window_behind = g.Windows[n]; - if (window_behind == window) - break; - if (window_behind->WasActive && window_behind->ViewportOwned && !(window_behind->Flags & ImGuiWindowFlags_ChildWindow)) - if (window_behind->Viewport->GetRect().Overlaps(window->Rect())) - return false; - } - - // Move to the existing viewport, Move child/hosted windows as well (FIXME-OPT: iterate child) - ImGuiViewportP* old_viewport = window->Viewport; - if (window->ViewportOwned) - for (int n = 0; n < g.Windows.Size; n++) - if (g.Windows[n]->Viewport == old_viewport) - SetWindowViewport(g.Windows[n], viewport); - SetWindowViewport(window, viewport); - BringWindowToDisplayFront(window); - - return true; -} - -// Scale all windows (position, size). Use when e.g. changing DPI. (This is a lossy operation!) -void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale) -{ - ImGuiContext& g = *GImGui; - if (viewport->Window) - { - ScaleWindow(viewport->Window, scale); - } - else - { - for (int i = 0; i != g.Windows.Size; i++) - if (g.Windows[i]->Viewport == viewport) - ScaleWindow(g.Windows[i], scale); - } -} - -// If the back-end doesn't set MouseLastHoveredViewport or doesn't honor ImGuiViewportFlags_NoInputs, we do a search ourselves. -// A) It won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window. -// B) It requires Platform_GetWindowFocus to be implemented by back-end. -static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 mouse_platform_pos) -{ - ImGuiContext& g = *GImGui; - ImGuiViewportP* best_candidate = NULL; - for (int n = 0; n < g.Viewports.Size; n++) - { - ImGuiViewportP* viewport = g.Viewports[n]; - if (!(viewport->Flags & ImGuiViewportFlags_NoInputs) && !viewport->PlatformWindowMinimized && viewport->GetRect().Contains(mouse_platform_pos)) - if (best_candidate == NULL || best_candidate->LastFrontMostStampCount < viewport->LastFrontMostStampCount) - best_candidate = viewport; - } - return best_candidate; -} - static void ImGui::UpdateViewportsNewFrame() { ImGuiContext& g = *GImGui; @@ -10611,6 +10487,136 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting } +//----------------------------------------------------------------------------- +// [SECTION] VIEWPORTS, PLATFORM WINDOWS +//----------------------------------------------------------------------------- + +ImGuiViewport* ImGui::GetMainViewport() +{ + ImGuiContext& g = *GImGui; + return g.Viewports[0]; +} + +ImGuiViewport* ImGui::FindViewportByID(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + for (int n = 0; n < g.Viewports.Size; n++) + if (g.Viewports[n]->ID == id) + return g.Viewports[n]; + return NULL; +} + +ImGuiViewport* ImGui::FindViewportByPlatformHandle(void* platform_handle) +{ + ImGuiContext& g = *GImGui; + for (int i = 0; i != g.Viewports.Size; i++) + if (g.Viewports[i]->PlatformHandle == platform_handle) + return g.Viewports[i]; + return NULL; +} + +void ImGui::SetCurrentViewport(ImGuiWindow* current_window, ImGuiViewportP* viewport) +{ + ImGuiContext& g = *GImGui; + (void)current_window; + + if (viewport) + viewport->LastFrameActive = g.FrameCount; + if (g.CurrentViewport == viewport) + return; + g.CurrentViewport = viewport; + //IMGUI_DEBUG_LOG("SetCurrentViewport changed '%s' 0x%08X\n", current_window ? current_window->Name : NULL, viewport ? viewport->ID : 0); + + // Notify platform layer of viewport changes + // FIXME-DPI: This is only currently used for experimenting with handling of multiple DPI + if (g.CurrentViewport && g.PlatformIO.Platform_OnChangedViewport) + g.PlatformIO.Platform_OnChangedViewport(g.CurrentViewport); +} + +static void SetWindowViewport(ImGuiWindow* window, ImGuiViewportP* viewport) +{ + window->Viewport = viewport; + window->ViewportId = viewport->ID; + window->ViewportOwned = (viewport->Window == window); +} + +static bool ImGui::GetWindowAlwaysWantOwnViewport(ImGuiWindow* window) +{ + // Tooltips and menus are not automatically forced into their own viewport when the NoMerge flag is set, however the multiplication of viewports makes them more likely to protude and create their own. + ImGuiContext& g = *GImGui; + if (g.IO.ConfigViewportsNoAutoMerge && (g.ConfigFlagsForFrame & ImGuiConfigFlags_ViewportsEnable)) + if (!window->DockIsActive) + if ((window->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) == 0) + return true; + return false; +} + +static bool ImGui::UpdateTryMergeWindowIntoHostViewport(ImGuiWindow* window, ImGuiViewportP* viewport) +{ + ImGuiContext& g = *GImGui; + if (!(viewport->Flags & ImGuiViewportFlags_CanHostOtherWindows) || window->Viewport == viewport || viewport->PlatformWindowMinimized) + return false; + if (!viewport->GetRect().Contains(window->Rect())) + return false; + if (GetWindowAlwaysWantOwnViewport(window)) + return false; + + for (int n = 0; n < g.Windows.Size; n++) + { + ImGuiWindow* window_behind = g.Windows[n]; + if (window_behind == window) + break; + if (window_behind->WasActive && window_behind->ViewportOwned && !(window_behind->Flags & ImGuiWindowFlags_ChildWindow)) + if (window_behind->Viewport->GetRect().Overlaps(window->Rect())) + return false; + } + + // Move to the existing viewport, Move child/hosted windows as well (FIXME-OPT: iterate child) + ImGuiViewportP* old_viewport = window->Viewport; + if (window->ViewportOwned) + for (int n = 0; n < g.Windows.Size; n++) + if (g.Windows[n]->Viewport == old_viewport) + SetWindowViewport(g.Windows[n], viewport); + SetWindowViewport(window, viewport); + BringWindowToDisplayFront(window); + + return true; +} + +// Scale all windows (position, size). Use when e.g. changing DPI. (This is a lossy operation!) +void ImGui::ScaleWindowsInViewport(ImGuiViewportP* viewport, float scale) +{ + ImGuiContext& g = *GImGui; + if (viewport->Window) + { + ScaleWindow(viewport->Window, scale); + } + else + { + for (int i = 0; i != g.Windows.Size; i++) + if (g.Windows[i]->Viewport == viewport) + ScaleWindow(g.Windows[i], scale); + } +} + +// If the back-end doesn't set MouseLastHoveredViewport or doesn't honor ImGuiViewportFlags_NoInputs, we do a search ourselves. +// A) It won't take account of the possibility that non-imgui windows may be in-between our dragged window and our target window. +// B) It requires Platform_GetWindowFocus to be implemented by back-end. +static ImGuiViewportP* FindViewportHoveredFromPlatformWindowStack(const ImVec2 mouse_platform_pos) +{ + ImGuiContext& g = *GImGui; + ImGuiViewportP* best_candidate = NULL; + for (int n = 0; n < g.Viewports.Size; n++) + { + ImGuiViewportP* viewport = g.Viewports[n]; + if (!(viewport->Flags & ImGuiViewportFlags_NoInputs) && !viewport->PlatformWindowMinimized && viewport->GetRect().Contains(mouse_platform_pos)) + if (best_candidate == NULL || best_candidate->LastFrontMostStampCount < viewport->LastFrontMostStampCount) + best_candidate = viewport; + } + return best_candidate; +} + + //----------------------------------------------------------------------------- // [SECTION] DOCKING //-----------------------------------------------------------------------------