mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 13:11:05 +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:
		
							
								
								
									
										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 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user