|
@@ -2929,6 +2929,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
|
|
|
}
|
|
}
|
|
|
g.ActiveId = id;
|
|
g.ActiveId = id;
|
|
|
g.ActiveIdAllowOverlap = false;
|
|
g.ActiveIdAllowOverlap = false;
|
|
|
|
|
+ g.ActiveIdNoClearOnFocusLoss = false;
|
|
|
g.ActiveIdWindow = window;
|
|
g.ActiveIdWindow = window;
|
|
|
g.ActiveIdHasBeenEditedThisFrame = false;
|
|
g.ActiveIdHasBeenEditedThisFrame = false;
|
|
|
if (id)
|
|
if (id)
|
|
@@ -2946,7 +2947,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
|
|
|
|
|
|
|
|
void ImGui::ClearActiveID()
|
|
void ImGui::ClearActiveID()
|
|
|
{
|
|
{
|
|
|
- SetActiveID(0, NULL);
|
|
|
|
|
|
|
+ SetActiveID(0, NULL); // g.ActiveId = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void ImGui::SetHoveredID(ImGuiID id)
|
|
void ImGui::SetHoveredID(ImGuiID id)
|
|
@@ -3102,6 +3103,15 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// This is also inlined in ItemAdd()
|
|
|
|
|
+// Note: if ImGuiItemStatusFlags_HasDisplayRect is set, user needs to set window->DC.LastItemDisplayRect!
|
|
|
|
|
+void ImGui::SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags item_flags, const ImRect& item_rect)
|
|
|
|
|
+{
|
|
|
|
|
+ window->DC.LastItemId = item_id;
|
|
|
|
|
+ window->DC.LastItemStatusFlags = item_flags;
|
|
|
|
|
+ window->DC.LastItemRect = item_rect;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out.
|
|
// Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out.
|
|
|
bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
|
|
bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
|
|
|
{
|
|
{
|
|
@@ -3294,6 +3304,7 @@ void ImGui::StartMouseMovingWindow(ImGuiWindow* window)
|
|
|
FocusWindow(window);
|
|
FocusWindow(window);
|
|
|
SetActiveID(window->MoveId, window);
|
|
SetActiveID(window->MoveId, window);
|
|
|
g.NavDisableHighlight = true;
|
|
g.NavDisableHighlight = true;
|
|
|
|
|
+ g.ActiveIdNoClearOnFocusLoss = true;
|
|
|
g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos;
|
|
g.ActiveIdClickOffset = g.IO.MousePos - window->RootWindow->Pos;
|
|
|
|
|
|
|
|
bool can_move_window = true;
|
|
bool can_move_window = true;
|
|
@@ -5982,9 +5993,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
|
|
|
|
|
// We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin().
|
|
// We fill last item data based on Title Bar/Tab, in order for IsItemHovered() and IsItemActive() to be usable after Begin().
|
|
|
// This is useful to allow creating context menus on title bar only, etc.
|
|
// This is useful to allow creating context menus on title bar only, etc.
|
|
|
- window->DC.LastItemId = window->MoveId;
|
|
|
|
|
- window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0;
|
|
|
|
|
- window->DC.LastItemRect = title_bar_rect;
|
|
|
|
|
|
|
+ SetLastItemData(window, window->MoveId, IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0, title_bar_rect);
|
|
|
|
|
+
|
|
|
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
|
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
|
|
if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
|
|
if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
|
|
|
IMGUI_TEST_ENGINE_ITEM_ADD(window->DC.LastItemRect, window->DC.LastItemId);
|
|
IMGUI_TEST_ENGINE_ITEM_ADD(window->DC.LastItemRect, window->DC.LastItemId);
|
|
@@ -6090,7 +6100,7 @@ void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
|
|
|
{
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
|
ImGuiWindow* current_front_window = g.Windows.back();
|
|
ImGuiWindow* current_front_window = g.Windows.back();
|
|
|
- if (current_front_window == window || current_front_window->RootWindow == window)
|
|
|
|
|
|
|
+ if (current_front_window == window || current_front_window->RootWindow == window) // Cheap early out (could be better)
|
|
|
return;
|
|
return;
|
|
|
for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window
|
|
for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window
|
|
|
if (g.Windows[i] == window)
|
|
if (g.Windows[i] == window)
|
|
@@ -6141,9 +6151,12 @@ void ImGui::FocusWindow(ImGuiWindow* window)
|
|
|
ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL; // NB: In docking branch this is window->RootWindowDockStop
|
|
ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL; // NB: In docking branch this is window->RootWindowDockStop
|
|
|
ImGuiWindow* display_front_window = window ? window->RootWindow : NULL;
|
|
ImGuiWindow* display_front_window = window ? window->RootWindow : NULL;
|
|
|
|
|
|
|
|
- // Steal focus on active widgets
|
|
|
|
|
|
|
+ // Steal active widgets. Some of the cases it triggers includes:
|
|
|
|
|
+ // - Focus a window while an InputText in another window is active, if focus happens before the old InputText can run.
|
|
|
|
|
+ // - When using Nav to activate menu items (due to timing of activating on press->new window appears->losing ActiveId)
|
|
|
if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window)
|
|
if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window)
|
|
|
- ClearActiveID();
|
|
|
|
|
|
|
+ if (!g.ActiveIdNoClearOnFocusLoss)
|
|
|
|
|
+ ClearActiveID();
|
|
|
|
|
|
|
|
// Passing NULL allow to disable keyboard focus
|
|
// Passing NULL allow to disable keyboard focus
|
|
|
if (!window)
|
|
if (!window)
|
|
@@ -6961,6 +6974,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
|
|
|
#endif
|
|
#endif
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Equivalent to calling SetLastItemData()
|
|
|
window->DC.LastItemId = id;
|
|
window->DC.LastItemId = id;
|
|
|
window->DC.LastItemRect = bb;
|
|
window->DC.LastItemRect = bb;
|
|
|
window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None;
|
|
window->DC.LastItemStatusFlags = ImGuiItemStatusFlags_None;
|
|
@@ -7684,13 +7698,14 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
|
|
|
|
|
+// This function closes any popups that are over 'ref_window'.
|
|
|
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.Size == 0)
|
|
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.
|
|
|
|
|
// Don't close our own child popup windows.
|
|
// Don't close our own child popup windows.
|
|
|
int popup_count_to_keep = 0;
|
|
int popup_count_to_keep = 0;
|
|
|
if (ref_window)
|
|
if (ref_window)
|
|
@@ -7705,13 +7720,20 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
|
|
|
if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow)
|
|
if (popup.Window->Flags & ImGuiWindowFlags_ChildWindow)
|
|
|
continue;
|
|
continue;
|
|
|
|
|
|
|
|
- // Trim the stack when popups are not direct descendant of the reference window (the reference window is often the NavWindow)
|
|
|
|
|
- bool popup_or_descendent_is_ref_window = false;
|
|
|
|
|
- for (int m = popup_count_to_keep; m < g.OpenPopupStack.Size && !popup_or_descendent_is_ref_window; m++)
|
|
|
|
|
- if (ImGuiWindow* popup_window = g.OpenPopupStack[m].Window)
|
|
|
|
|
|
|
+ // Trim the stack unless the popup is a direct parent of the reference window (the reference window is often the NavWindow)
|
|
|
|
|
+ // - With this stack of window, clicking/focusing Popup1 will close Popup2 and Popup3:
|
|
|
|
|
+ // Window -> Popup1 -> Popup2 -> Popup3
|
|
|
|
|
+ // - Each popups may contain child windows, which is why we compare ->RootWindow!
|
|
|
|
|
+ // Window -> Popup1 -> Popup1_Child -> Popup2 -> Popup2_Child
|
|
|
|
|
+ bool ref_window_is_descendent_of_popup = false;
|
|
|
|
|
+ for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++)
|
|
|
|
|
+ if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window)
|
|
|
if (popup_window->RootWindow == ref_window->RootWindow)
|
|
if (popup_window->RootWindow == ref_window->RootWindow)
|
|
|
- popup_or_descendent_is_ref_window = true;
|
|
|
|
|
- if (!popup_or_descendent_is_ref_window)
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ ref_window_is_descendent_of_popup = true;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!ref_window_is_descendent_of_popup)
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|