mirror of
https://github.com/ocornut/imgui.git
synced 2025-09-06 03:18:21 +00:00
Windows, Viewport: fixed an issue where interrupting a viewport move with e.g. a ClearActiveID() call would leave the dragged viewport with the ImGuiViewportFlags_NoInputs flag.
Amend6b7766817
,36055213c5
, #5324. Next would be good to amend the ImGuiViewportFlags_NoInputs clear to match the set logic.
This commit is contained in:
@@ -62,6 +62,13 @@ Other Changes:
|
|||||||
- Backends: Vulkan: Fixed texture update corruption introduced in 1.92.0,
|
- Backends: Vulkan: Fixed texture update corruption introduced in 1.92.0,
|
||||||
affecting some drivers/setups. (#8801, #8755, #8840) [@Retro52, @Miolith]
|
affecting some drivers/setups. (#8801, #8755, #8840) [@Retro52, @Miolith]
|
||||||
|
|
||||||
|
Docking+Viewports Branch:
|
||||||
|
|
||||||
|
- Windows, Viewport: fixed an issue where interrupting a viewport move with
|
||||||
|
e.g. a ClearActiveID() call would leave the dragged viewport with the
|
||||||
|
normally temporary ImGuiViewportFlags_NoInputs flag, preventing further
|
||||||
|
interactions with the viewport. (#5324) (thanks @mdelaharpe)
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
VERSION 1.92.1 (Released 2025-07-09)
|
VERSION 1.92.1 (Released 2025-07-09)
|
||||||
|
71
imgui.cpp
71
imgui.cpp
@@ -4606,15 +4606,6 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
|
|||||||
// Clear previous active id
|
// Clear previous active id
|
||||||
if (g.ActiveId != 0)
|
if (g.ActiveId != 0)
|
||||||
{
|
{
|
||||||
// While most behaved code would make an effort to not steal active id during window move/drag operations,
|
|
||||||
// we at least need to be resilient to it. Canceling the move is rather aggressive and users of 'master' branch
|
|
||||||
// may prefer the weird ill-defined half working situation ('docking' did assert), so may need to rework that.
|
|
||||||
if (g.MovingWindow != NULL && g.ActiveId == g.MovingWindow->MoveId)
|
|
||||||
{
|
|
||||||
IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() cancel MovingWindow\n");
|
|
||||||
g.MovingWindow = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store deactivate data
|
// Store deactivate data
|
||||||
ImGuiDeactivatedItemData* deactivated_data = &g.DeactivatedItemData;
|
ImGuiDeactivatedItemData* deactivated_data = &g.DeactivatedItemData;
|
||||||
deactivated_data->ID = g.ActiveId;
|
deactivated_data->ID = g.ActiveId;
|
||||||
@@ -4627,6 +4618,15 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
|
|||||||
// One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveID()
|
// One common scenario leading to this is: pressing Key ->NavMoveRequestApplyResult() -> ClearActiveID()
|
||||||
if (g.InputTextState.ID == g.ActiveId)
|
if (g.InputTextState.ID == g.ActiveId)
|
||||||
InputTextDeactivateHook(g.ActiveId);
|
InputTextDeactivateHook(g.ActiveId);
|
||||||
|
|
||||||
|
// While most behaved code would make an effort to not steal active id during window move/drag operations,
|
||||||
|
// we at least need to be resilient to it. Canceling the move is rather aggressive and users of 'master' branch
|
||||||
|
// may prefer the weird ill-defined half working situation ('docking' did assert), so may need to rework that.
|
||||||
|
if (g.MovingWindow != NULL && g.ActiveId == g.MovingWindow->MoveId)
|
||||||
|
{
|
||||||
|
IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() cancel MovingWindow\n");
|
||||||
|
StopMouseMovingWindow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set active id
|
// Set active id
|
||||||
@@ -5207,6 +5207,34 @@ void ImGui::StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* nod
|
|||||||
StartMouseMovingWindow(window);
|
StartMouseMovingWindow(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is not 100% symetric with StartMouseMovingWindow().
|
||||||
|
// We do NOT clear ActiveID, because:
|
||||||
|
// - It would lead to rather confusing recursive code paths. Caller can call ClearActiveID() if desired.
|
||||||
|
// - Some code intentionally cancel moving but keep the ActiveID to lock inputs (e.g. code path taken when clicking a disabled item).
|
||||||
|
void ImGui::StopMouseMovingWindow()
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiWindow* window = g.MovingWindow;
|
||||||
|
|
||||||
|
// Ref commits 6b7766817, 36055213c for some partial history on checking if viewport != NULL.
|
||||||
|
if (window && window->Viewport)
|
||||||
|
{
|
||||||
|
// 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(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 = window->Viewport;
|
||||||
|
|
||||||
|
// Clear the NoInputs window flag set by the Viewport system in AddUpdateViewport()
|
||||||
|
window->Viewport->Flags &= ~ImGuiViewportFlags_NoInputs;
|
||||||
|
}
|
||||||
|
|
||||||
|
g.MovingWindow = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle mouse moving window
|
// Handle mouse moving window
|
||||||
// Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
|
// Note: moving window with the navigation keys (Square + d-pad / CTRL+TAB + Arrows) are processed in NavUpdateWindowing()
|
||||||
// FIXME: We don't have strong guarantee that g.MovingWindow stay synced with g.ActiveId == g.MovingWindow->MoveId.
|
// FIXME: We don't have strong guarantee that g.MovingWindow stay synced with g.ActiveId == g.MovingWindow->MoveId.
|
||||||
@@ -5224,8 +5252,8 @@ void ImGui::UpdateMouseMovingWindowNewFrame()
|
|||||||
ImGuiWindow* moving_window = g.MovingWindow->RootWindowDockTree;
|
ImGuiWindow* moving_window = g.MovingWindow->RootWindowDockTree;
|
||||||
|
|
||||||
// When a window stop being submitted while being dragged, it may will its viewport until next Begin()
|
// 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->Active);
|
const bool window_disappeared = (!moving_window->WasActive && !moving_window->Active);
|
||||||
if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos) && !window_disappared)
|
if (g.IO.MouseDown[0] && IsMousePosValid(&g.IO.MousePos) && !window_disappeared)
|
||||||
{
|
{
|
||||||
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)
|
||||||
@@ -5241,23 +5269,7 @@ void ImGui::UpdateMouseMovingWindowNewFrame()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!window_disappared)
|
StopMouseMovingWindow();
|
||||||
{
|
|
||||||
// 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 (moving_window->Viewport && !IsDragDropPayloadBeingAccepted())
|
|
||||||
g.MouseViewport = moving_window->Viewport;
|
|
||||||
|
|
||||||
// Clear the NoInput window flag set by the Viewport system
|
|
||||||
if (moving_window->Viewport)
|
|
||||||
moving_window->Viewport->Flags &= ~ImGuiViewportFlags_NoInputs;
|
|
||||||
}
|
|
||||||
|
|
||||||
g.MovingWindow = NULL;
|
|
||||||
ClearActiveID();
|
ClearActiveID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5299,6 +5311,9 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
|
|||||||
{
|
{
|
||||||
StartMouseMovingWindow(g.HoveredWindow); //-V595
|
StartMouseMovingWindow(g.HoveredWindow); //-V595
|
||||||
|
|
||||||
|
// FIXME: In principal we might be able to call StopMouseMovingWindow() below.
|
||||||
|
// Please note how StartMouseMovingWindow() and StopMouseMovingWindow() and not entirely symetrical, at the later doesn't clear ActiveId.
|
||||||
|
|
||||||
// Cancel moving if clicked outside of title bar
|
// Cancel moving if clicked outside of title bar
|
||||||
if (g.IO.ConfigWindowsMoveFromTitleBarOnly)
|
if (g.IO.ConfigWindowsMoveFromTitleBarOnly)
|
||||||
if (!(root_window->Flags & ImGuiWindowFlags_NoTitleBar) || root_window->DockIsActive)
|
if (!(root_window->Flags & ImGuiWindowFlags_NoTitleBar) || root_window->DockIsActive)
|
||||||
|
@@ -3382,6 +3382,7 @@ namespace ImGui
|
|||||||
IMGUI_API void FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_viewport, ImGuiWindow** out_hovered_window, ImGuiWindow** out_hovered_window_under_moving_window);
|
IMGUI_API void FindHoveredWindowEx(const ImVec2& pos, bool find_first_and_in_any_viewport, ImGuiWindow** out_hovered_window, ImGuiWindow** out_hovered_window_under_moving_window);
|
||||||
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
|
IMGUI_API void StartMouseMovingWindow(ImGuiWindow* window);
|
||||||
IMGUI_API void StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock);
|
IMGUI_API void StartMouseMovingWindowOrNode(ImGuiWindow* window, ImGuiDockNode* node, bool undock);
|
||||||
|
IMGUI_API void StopMouseMovingWindow();
|
||||||
IMGUI_API void UpdateMouseMovingWindowNewFrame();
|
IMGUI_API void UpdateMouseMovingWindowNewFrame();
|
||||||
IMGUI_API void UpdateMouseMovingWindowEndFrame();
|
IMGUI_API void UpdateMouseMovingWindowEndFrame();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user