mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-22 11:57:00 +00:00
Popups: Fix an edge case where programatically closing a popup while clicking on its empty space would attempt to focus it and close other popups. (#2880)
This commit is contained in:
parent
1dfd0634cb
commit
d31fe97f74
@ -52,6 +52,8 @@ Other Changes:
|
|||||||
Set to 0.0f (default) to always make a close button appear on hover (same as Chrome, VS).
|
Set to 0.0f (default) to always make a close button appear on hover (same as Chrome, VS).
|
||||||
Set to FLT_MAX to only display a close button when selected (merely hovering is not enough).
|
Set to FLT_MAX to only display a close button when selected (merely hovering is not enough).
|
||||||
Set to an intermediary value to toggle behavior based on width (same as Firefox).
|
Set to an intermediary value to toggle behavior based on width (same as Firefox).
|
||||||
|
- Popups: Fix an edge case where programatically closing a popup while clicking on its empty space
|
||||||
|
would attempt to focus it and close other popups. (#2880)
|
||||||
- Fix GetGlyphRangesKorean() end-range to end at 0xD7A3 (instead of 0xD79D). (#348, #3217) [@marukrap]
|
- Fix GetGlyphRangesKorean() end-range to end at 0xD7A3 (instead of 0xD79D). (#348, #3217) [@marukrap]
|
||||||
- Metrics: Added a "Settings" section with some details about persistent ini settings.
|
- Metrics: Added a "Settings" section with some details about persistent ini settings.
|
||||||
- Nav, Menus: Fix vertical wrap-around in menus or popups created with multiple appending calls to
|
- Nav, Menus: Fix vertical wrap-around in menus or popups created with multiple appending calls to
|
||||||
|
36
imgui.cpp
36
imgui.cpp
@ -3449,17 +3449,22 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
|
|||||||
if (g.NavWindow && g.NavWindow->Appearing)
|
if (g.NavWindow && g.NavWindow->Appearing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Click to focus window and start moving (after we're done with all our widgets)
|
// Click on empty space to focus window and start moving (after we're done with all our widgets)
|
||||||
if (g.IO.MouseClicked[0])
|
if (g.IO.MouseClicked[0])
|
||||||
{
|
{
|
||||||
if (g.HoveredRootWindow != NULL)
|
// Handle the edge case of a popup being closed while clicking in its empty space.
|
||||||
|
// If we try to focus it, FocusWindow() > ClosePopupsOverWindow() will accidentally close any parent popups because they are not linked together any more.
|
||||||
|
ImGuiWindow* root_window = g.HoveredRootWindow;
|
||||||
|
const bool is_closed_popup = root_window && (root_window->Flags & ImGuiWindowFlags_Popup) && !IsPopupOpenAtAnyLevel(root_window->PopupId);
|
||||||
|
|
||||||
|
if (root_window != NULL && !is_closed_popup)
|
||||||
{
|
{
|
||||||
StartMouseMovingWindow(g.HoveredWindow);
|
StartMouseMovingWindow(g.HoveredWindow);
|
||||||
if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoTitleBar))
|
if (g.IO.ConfigWindowsMoveFromTitleBarOnly && !(root_window->Flags & ImGuiWindowFlags_NoTitleBar))
|
||||||
if (!g.HoveredRootWindow->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
|
if (!root_window->TitleBarRect().Contains(g.IO.MouseClickedPos[0]))
|
||||||
g.MovingWindow = NULL;
|
g.MovingWindow = NULL;
|
||||||
}
|
}
|
||||||
else if (g.NavWindow != NULL && GetTopMostPopupModal() == NULL)
|
else if (root_window != NULL && g.NavWindow != NULL && GetTopMostPopupModal() == NULL)
|
||||||
{
|
{
|
||||||
// Clicking on void disable focus
|
// Clicking on void disable focus
|
||||||
FocusWindow(NULL);
|
FocusWindow(NULL);
|
||||||
@ -3700,7 +3705,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
|
|||||||
for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
|
for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
|
||||||
{
|
{
|
||||||
if (g.IO.MouseClicked[i])
|
if (g.IO.MouseClicked[i])
|
||||||
g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty());
|
g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (g.OpenPopupStack.Size > 0);
|
||||||
mouse_any_down |= g.IO.MouseDown[i];
|
mouse_any_down |= g.IO.MouseDown[i];
|
||||||
if (g.IO.MouseDown[i])
|
if (g.IO.MouseDown[i])
|
||||||
if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down])
|
if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down])
|
||||||
@ -3718,7 +3723,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
|
|||||||
if (g.WantCaptureMouseNextFrame != -1)
|
if (g.WantCaptureMouseNextFrame != -1)
|
||||||
g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0);
|
g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0);
|
||||||
else
|
else
|
||||||
g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty());
|
g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (g.OpenPopupStack.Size > 0);
|
||||||
|
|
||||||
// Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to Dear ImGui + app)
|
// Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to Dear ImGui + app)
|
||||||
if (g.WantCaptureKeyboardNextFrame != -1)
|
if (g.WantCaptureKeyboardNextFrame != -1)
|
||||||
@ -7610,6 +7615,15 @@ bool ImGui::IsPopupOpen(const char* str_id)
|
|||||||
return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id);
|
return g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ImGui::IsPopupOpenAtAnyLevel(ImGuiID id)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
for (int n = 0; n < g.OpenPopupStack.Size; n++)
|
||||||
|
if (g.OpenPopupStack[n].PopupId == id)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ImGuiWindow* ImGui::GetTopMostPopupModal()
|
ImGuiWindow* ImGui::GetTopMostPopupModal()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
@ -7661,8 +7675,8 @@ void ImGui::OpenPopupEx(ImGuiID id)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Close child popups if any, then flag popup for open/reopen
|
// Close child popups if any, then flag popup for open/reopen
|
||||||
g.OpenPopupStack.resize(current_stack_size + 1);
|
ClosePopupToLevel(current_stack_size, false);
|
||||||
g.OpenPopupStack[current_stack_size] = popup_ref;
|
g.OpenPopupStack.push_back(popup_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow().
|
// When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow().
|
||||||
@ -7675,7 +7689,7 @@ void ImGui::OpenPopupEx(ImGuiID id)
|
|||||||
void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup)
|
void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup)
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (g.OpenPopupStack.empty())
|
if (g.OpenPopupStack.Size == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
|
// When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
|
||||||
@ -7714,6 +7728,8 @@ void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_
|
|||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
IM_ASSERT(remaining >= 0 && remaining < g.OpenPopupStack.Size);
|
IM_ASSERT(remaining >= 0 && remaining < g.OpenPopupStack.Size);
|
||||||
|
|
||||||
|
// Trim open popup stack
|
||||||
ImGuiWindow* focus_window = g.OpenPopupStack[remaining].SourceWindow;
|
ImGuiWindow* focus_window = g.OpenPopupStack[remaining].SourceWindow;
|
||||||
ImGuiWindow* popup_window = g.OpenPopupStack[remaining].Window;
|
ImGuiWindow* popup_window = g.OpenPopupStack[remaining].Window;
|
||||||
g.OpenPopupStack.resize(remaining);
|
g.OpenPopupStack.resize(remaining);
|
||||||
|
@ -1581,7 +1581,7 @@ struct IMGUI_API ImGuiWindow
|
|||||||
bool WantCollapseToggle;
|
bool WantCollapseToggle;
|
||||||
bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed)
|
bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed)
|
||||||
bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
|
bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
|
||||||
bool Hidden; // Do not display (== (HiddenFrames*** > 0))
|
bool Hidden; // Do not display (== HiddenFrames*** > 0)
|
||||||
bool IsFallbackWindow; // Set on the "Debug##Default" window.
|
bool IsFallbackWindow; // Set on the "Debug##Default" window.
|
||||||
bool HasCloseButton; // Set when the window has a close button (p_open != NULL)
|
bool HasCloseButton; // Set when the window has a close button (p_open != NULL)
|
||||||
signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3)
|
signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3)
|
||||||
@ -1853,6 +1853,7 @@ namespace ImGui
|
|||||||
IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup);
|
IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup);
|
||||||
IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup);
|
IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup);
|
||||||
IMGUI_API bool IsPopupOpen(ImGuiID id); // Test for id at current popup stack level (currently begin-ed into); this doesn't scan the whole popup stack!
|
IMGUI_API bool IsPopupOpen(ImGuiID id); // Test for id at current popup stack level (currently begin-ed into); this doesn't scan the whole popup stack!
|
||||||
|
IMGUI_API bool IsPopupOpenAtAnyLevel(ImGuiID id);
|
||||||
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
|
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
|
||||||
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags);
|
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags);
|
||||||
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
|
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
|
||||||
|
Loading…
Reference in New Issue
Block a user