Pārlūkot izejas kodu

Viewports: Fixed a crash while a window owning its viewport disappear while being dragged.

t would manifest when e.g. reconfiguring dock nodes while dragging.
ocornut 4 gadi atpakaļ
vecāks
revīzija
6b77668171
2 mainītis faili ar 21 papildinājumiem un 12 dzēšanām
  1. 3 1
      docs/CHANGELOG.txt
  2. 18 11
      imgui.cpp

+ 3 - 1
docs/CHANGELOG.txt

@@ -148,7 +148,9 @@ Docking+Viewports Branch:
 - Docking: fixed settings load issue when mouse wheeling. (#4310)
 - Docking: fixed settings load issue when mouse wheeling. (#4310)
 - Docking + Drag and Drop: Fixed using BeginDragDropSource() or BeginDragDropTarget() inside a Begin()
 - Docking + Drag and Drop: Fixed using BeginDragDropSource() or BeginDragDropTarget() inside a Begin()
   that returned false because the window is docked. (#4515)
   that returned false because the window is docked. (#4515)
-- Viewports: Viewports: fixed unnecessary creation of temporary viewports when multiple docked windows
+- Viewports: Fixed a crash while a window owning its viewport disappear while being dragged.
+  It would manifest when e.g. reconfiguring dock nodes while dragging.
+- Viewports: Fixed unnecessary creation of temporary viewports when multiple docked windows
   got reassigned to a new node (created mid-frame) which already has a HostWindow.
   got reassigned to a new node (created mid-frame) which already has a HostWindow.
 
 
 
 

+ 18 - 11
imgui.cpp

@@ -3690,7 +3690,10 @@ void ImGui::UpdateMouseMovingWindowNewFrame()
         KeepAliveID(g.ActiveId);
         KeepAliveID(g.ActiveId);
         IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindowDockTree);
         IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindowDockTree);
         ImGuiWindow* moving_window = g.MovingWindow->RootWindowDockTree;
         ImGuiWindow* moving_window = g.MovingWindow->RootWindowDockTree;
-        if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos))
+
+        // When a window stop being submitted while being dragged, it may will its viewport until next Begin()
+        const bool window_disappared = (!moving_window->WasActive || moving_window->Viewport == NULL);
+        if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos) && !window_disappared)
         {
         {
             ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset;
             ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset;
             if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
             if (moving_window->Pos.x != pos.x || moving_window->Pos.y != pos.y)
@@ -3707,17 +3710,20 @@ void ImGui::UpdateMouseMovingWindowNewFrame()
         }
         }
         else
         else
         {
         {
-            // Try to merge the window back into the main viewport.
-            // This works because MouseViewport should be != MovingWindow->Viewport on release (as per code in UpdateViewports)
-            if (g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
-                UpdateTryMergeWindowIntoHostViewport(moving_window, g.MouseViewport);
+            if (!window_disappared)
+            {
+                // Try to merge the window back into the main viewport.
+                // This works because MouseViewport should be != MovingWindow->Viewport on release (as per code in UpdateViewports)
+                if (g.ConfigFlagsCurrFrame & ImGuiConfigFlags_ViewportsEnable)
+                    UpdateTryMergeWindowIntoHostViewport(moving_window, g.MouseViewport);
 
 
-            // Restore the mouse viewport so that we don't hover the viewport _under_ the moved window during the frame we released the mouse button.
-            if (!IsDragDropPayloadBeingAccepted())
-                g.MouseViewport = moving_window->Viewport;
+                // Restore the mouse viewport so that we don't hover the viewport _under_ the moved window during the frame we released the mouse button.
+                if (!IsDragDropPayloadBeingAccepted())
+                    g.MouseViewport = moving_window->Viewport;
 
 
-            // Clear the NoInput window flag set by the Viewport system
-            moving_window->Viewport->Flags &= ~ImGuiViewportFlags_NoInputs; // FIXME-VIEWPORT: Test engine managed to crash here because Viewport was NULL.
+                // Clear the NoInput window flag set by the Viewport system
+                moving_window->Viewport->Flags &= ~ImGuiViewportFlags_NoInputs; // FIXME-VIEWPORT: Test engine managed to crash here because Viewport was NULL.
+            }
 
 
             g.MovingWindow = NULL;
             g.MovingWindow = NULL;
             ClearActiveID();
             ClearActiveID();
@@ -11855,7 +11861,8 @@ static void ImGui::UpdateViewportsNewFrame()
 
 
     // Update mouse reference viewport
     // 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)
     // (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)
+    // (MovingViewport->Viewport will be NULL in the rare situation where the window disappared while moving, set UpdateMouseMovingWindowNewFrame() for details)
+    if (g.MovingWindow && g.MovingWindow->Viewport)
         g.MouseViewport = g.MovingWindow->Viewport;
         g.MouseViewport = g.MovingWindow->Viewport;
     else
     else
         g.MouseViewport = g.MouseLastHoveredViewport;
         g.MouseViewport = g.MouseLastHoveredViewport;