|
@@ -85,6 +85,7 @@ CODE
|
|
|
// [SECTION] SCROLLING
|
|
|
// [SECTION] TOOLTIPS
|
|
|
// [SECTION] POPUPS
|
|
|
+// [SECTION] WINDOW FOCUS
|
|
|
// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
|
|
|
// [SECTION] DRAG AND DROP
|
|
|
// [SECTION] LOGGING/CAPTURING
|
|
@@ -1202,6 +1203,10 @@ namespace ImGui
|
|
|
// Item
|
|
|
static void ItemHandleShortcut(ImGuiID id);
|
|
|
|
|
|
+// Window Focus
|
|
|
+static int FindWindowFocusIndex(ImGuiWindow* window);
|
|
|
+static void UpdateWindowInFocusOrderList(ImGuiWindow* window, bool just_created, ImGuiWindowFlags new_flags);
|
|
|
+
|
|
|
// Navigation
|
|
|
static void NavUpdate();
|
|
|
static void NavUpdateWindowing();
|
|
@@ -1222,7 +1227,6 @@ static ImVec2 NavCalcPreferredRefPos();
|
|
|
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
|
|
|
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
|
|
|
static void NavRestoreLayer(ImGuiNavLayer layer);
|
|
|
-static int FindWindowFocusIndex(ImGuiWindow* window);
|
|
|
|
|
|
// Error Checking and Debug Tools
|
|
|
static void ErrorCheckNewFrameSanityChecks();
|
|
@@ -6171,29 +6175,6 @@ static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settin
|
|
|
window->Collapsed = settings->Collapsed;
|
|
|
}
|
|
|
|
|
|
-static void UpdateWindowInFocusOrderList(ImGuiWindow* window, bool just_created, ImGuiWindowFlags new_flags)
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
-
|
|
|
- const bool new_is_explicit_child = (new_flags & ImGuiWindowFlags_ChildWindow) != 0 && ((new_flags & ImGuiWindowFlags_Popup) == 0 || (new_flags & ImGuiWindowFlags_ChildMenu) != 0);
|
|
|
- const bool child_flag_changed = new_is_explicit_child != window->IsExplicitChild;
|
|
|
- if ((just_created || child_flag_changed) && !new_is_explicit_child)
|
|
|
- {
|
|
|
- IM_ASSERT(!g.WindowsFocusOrder.contains(window));
|
|
|
- g.WindowsFocusOrder.push_back(window);
|
|
|
- window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1);
|
|
|
- }
|
|
|
- else if (!just_created && child_flag_changed && new_is_explicit_child)
|
|
|
- {
|
|
|
- IM_ASSERT(g.WindowsFocusOrder[window->FocusOrder] == window);
|
|
|
- for (int n = window->FocusOrder + 1; n < g.WindowsFocusOrder.Size; n++)
|
|
|
- g.WindowsFocusOrder[n]->FocusOrder--;
|
|
|
- g.WindowsFocusOrder.erase(g.WindowsFocusOrder.Data + window->FocusOrder);
|
|
|
- window->FocusOrder = -1;
|
|
|
- }
|
|
|
- window->IsExplicitChild = new_is_explicit_child;
|
|
|
-}
|
|
|
-
|
|
|
static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
|
|
|
{
|
|
|
// Initial window state with e.g. default/arbitrary window position
|
|
@@ -7777,176 +7758,6 @@ void ImGui::End()
|
|
|
SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
|
|
|
}
|
|
|
|
|
|
-void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- IM_ASSERT(window == window->RootWindow);
|
|
|
-
|
|
|
- const int cur_order = window->FocusOrder;
|
|
|
- IM_ASSERT(g.WindowsFocusOrder[cur_order] == window);
|
|
|
- if (g.WindowsFocusOrder.back() == window)
|
|
|
- return;
|
|
|
-
|
|
|
- const int new_order = g.WindowsFocusOrder.Size - 1;
|
|
|
- for (int n = cur_order; n < new_order; n++)
|
|
|
- {
|
|
|
- g.WindowsFocusOrder[n] = g.WindowsFocusOrder[n + 1];
|
|
|
- g.WindowsFocusOrder[n]->FocusOrder--;
|
|
|
- IM_ASSERT(g.WindowsFocusOrder[n]->FocusOrder == n);
|
|
|
- }
|
|
|
- g.WindowsFocusOrder[new_order] = window;
|
|
|
- window->FocusOrder = (short)new_order;
|
|
|
-}
|
|
|
-
|
|
|
-void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- ImGuiWindow* current_front_window = g.Windows.back();
|
|
|
- if (current_front_window == window || current_front_window->RootWindow == window) // Cheap early out (could be better)
|
|
|
- return;
|
|
|
- for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window
|
|
|
- if (g.Windows[i] == window)
|
|
|
- {
|
|
|
- memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*));
|
|
|
- g.Windows[g.Windows.Size - 1] = window;
|
|
|
- break;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- if (g.Windows[0] == window)
|
|
|
- return;
|
|
|
- for (int i = 0; i < g.Windows.Size; i++)
|
|
|
- if (g.Windows[i] == window)
|
|
|
- {
|
|
|
- memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*));
|
|
|
- g.Windows[0] = window;
|
|
|
- break;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-void ImGui::BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* behind_window)
|
|
|
-{
|
|
|
- IM_ASSERT(window != NULL && behind_window != NULL);
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- window = window->RootWindow;
|
|
|
- behind_window = behind_window->RootWindow;
|
|
|
- int pos_wnd = FindWindowDisplayIndex(window);
|
|
|
- int pos_beh = FindWindowDisplayIndex(behind_window);
|
|
|
- if (pos_wnd < pos_beh)
|
|
|
- {
|
|
|
- size_t copy_bytes = (pos_beh - pos_wnd - 1) * sizeof(ImGuiWindow*);
|
|
|
- memmove(&g.Windows.Data[pos_wnd], &g.Windows.Data[pos_wnd + 1], copy_bytes);
|
|
|
- g.Windows[pos_beh - 1] = window;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- size_t copy_bytes = (pos_wnd - pos_beh) * sizeof(ImGuiWindow*);
|
|
|
- memmove(&g.Windows.Data[pos_beh + 1], &g.Windows.Data[pos_beh], copy_bytes);
|
|
|
- g.Windows[pos_beh] = window;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-int ImGui::FindWindowDisplayIndex(ImGuiWindow* window)
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- return g.Windows.index_from_ptr(g.Windows.find(window));
|
|
|
-}
|
|
|
-
|
|
|
-// Moving window to front of display and set focus (which happens to be back of our sorted list)
|
|
|
-void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
-
|
|
|
- // Modal check?
|
|
|
- if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window)) // Early out in common case.
|
|
|
- if (ImGuiWindow* blocking_modal = FindBlockingModal(window))
|
|
|
- {
|
|
|
- // This block would typically be reached in two situations:
|
|
|
- // - API call to FocusWindow() with a window under a modal and ImGuiFocusRequestFlags_UnlessBelowModal flag.
|
|
|
- // - User clicking on void or anything behind a modal while a modal is open (window == NULL)
|
|
|
- IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "<NULL>", blocking_modal->Name);
|
|
|
- if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
|
|
|
- BringWindowToDisplayBehind(window, blocking_modal); // Still bring right under modal. (FIXME: Could move in focus list too?)
|
|
|
- ClosePopupsOverWindow(GetTopMostPopupModal(), false); // Note how we need to use GetTopMostPopupModal() aad NOT blocking_modal, to handle nested modals
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // Find last focused child (if any) and focus it instead.
|
|
|
- if ((flags & ImGuiFocusRequestFlags_RestoreFocusedChild) && window != NULL)
|
|
|
- window = NavRestoreLastChildNavWindow(window);
|
|
|
-
|
|
|
- // Apply focus
|
|
|
- if (g.NavWindow != window)
|
|
|
- {
|
|
|
- SetNavWindow(window);
|
|
|
- if (window && g.NavHighlightItemUnderNav)
|
|
|
- g.NavMousePosDirty = true;
|
|
|
- g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
|
|
|
- g.NavLayer = ImGuiNavLayer_Main;
|
|
|
- SetNavFocusScope(window ? window->NavRootFocusScopeId : 0);
|
|
|
- g.NavIdIsAlive = false;
|
|
|
- g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
|
|
|
-
|
|
|
- // Close popups if any
|
|
|
- ClosePopupsOverWindow(window, false);
|
|
|
- }
|
|
|
-
|
|
|
- // Move the root window to the top of the pile
|
|
|
- IM_ASSERT(window == NULL || window->RootWindow != NULL);
|
|
|
- ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL; // NB: In docking branch this is window->RootWindowDockStop
|
|
|
- ImGuiWindow* display_front_window = window ? window->RootWindow : NULL;
|
|
|
-
|
|
|
- // 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.ActiveIdNoClearOnFocusLoss)
|
|
|
- ClearActiveID();
|
|
|
-
|
|
|
- // Passing NULL allow to disable keyboard focus
|
|
|
- if (!window)
|
|
|
- return;
|
|
|
-
|
|
|
- // Bring to front
|
|
|
- BringWindowToFocusFront(focus_front_window);
|
|
|
- if (((window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
|
|
|
- BringWindowToDisplayFront(display_front_window);
|
|
|
-}
|
|
|
-
|
|
|
-void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags)
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- IM_UNUSED(filter_viewport); // Unused in master branch.
|
|
|
- int start_idx = g.WindowsFocusOrder.Size - 1;
|
|
|
- if (under_this_window != NULL)
|
|
|
- {
|
|
|
- // Aim at root window behind us, if we are in a child window that's our own root (see #4640)
|
|
|
- int offset = -1;
|
|
|
- while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow)
|
|
|
- {
|
|
|
- under_this_window = under_this_window->ParentWindow;
|
|
|
- offset = 0;
|
|
|
- }
|
|
|
- start_idx = FindWindowFocusIndex(under_this_window) + offset;
|
|
|
- }
|
|
|
- for (int i = start_idx; i >= 0; i--)
|
|
|
- {
|
|
|
- // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user.
|
|
|
- ImGuiWindow* window = g.WindowsFocusOrder[i];
|
|
|
- if (window == ignore_window || !window->WasActive)
|
|
|
- continue;
|
|
|
- if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
|
|
|
- {
|
|
|
- FocusWindow(window, flags);
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- FocusWindow(NULL, flags);
|
|
|
-}
|
|
|
-
|
|
|
// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only.
|
|
|
void ImGui::SetCurrentFont(ImFont* font)
|
|
|
{
|
|
@@ -8216,28 +8027,6 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- ImGuiWindow* ref_window = g.NavWindow;
|
|
|
- ImGuiWindow* cur_window = g.CurrentWindow;
|
|
|
-
|
|
|
- if (ref_window == NULL)
|
|
|
- return false;
|
|
|
- if (flags & ImGuiFocusedFlags_AnyWindow)
|
|
|
- return true;
|
|
|
-
|
|
|
- IM_ASSERT(cur_window); // Not inside a Begin()/End()
|
|
|
- const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0;
|
|
|
- if (flags & ImGuiHoveredFlags_RootWindow)
|
|
|
- cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy);
|
|
|
-
|
|
|
- if (flags & ImGuiHoveredFlags_ChildWindows)
|
|
|
- return IsWindowChildOf(ref_window, cur_window, popup_hierarchy);
|
|
|
- else
|
|
|
- return (ref_window == cur_window);
|
|
|
-}
|
|
|
-
|
|
|
float ImGui::GetWindowWidth()
|
|
|
{
|
|
|
ImGuiWindow* window = GImGui->CurrentWindow;
|
|
@@ -8385,24 +8174,6 @@ void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond)
|
|
|
SetWindowCollapsed(window, collapsed, cond);
|
|
|
}
|
|
|
|
|
|
-void ImGui::SetWindowFocus()
|
|
|
-{
|
|
|
- FocusWindow(GImGui->CurrentWindow);
|
|
|
-}
|
|
|
-
|
|
|
-void ImGui::SetWindowFocus(const char* name)
|
|
|
-{
|
|
|
- if (name)
|
|
|
- {
|
|
|
- if (ImGuiWindow* window = FindWindowByName(name))
|
|
|
- FocusWindow(window);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- FocusWindow(NULL);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -8460,12 +8231,6 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
|
|
|
g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
|
|
|
}
|
|
|
|
|
|
-void ImGui::SetNextWindowFocus()
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus;
|
|
|
-}
|
|
|
-
|
|
|
void ImGui::SetNextWindowBgAlpha(float alpha)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -12148,6 +11913,273 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
|
|
|
return window->Pos;
|
|
|
}
|
|
|
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+// [SECTION] WINDOW FOCUS
|
|
|
+//----------------------------------------------------------------------------
|
|
|
+// - SetWindowFocus()
|
|
|
+// - SetNextWindowFocus()
|
|
|
+// - IsWindowFocused()
|
|
|
+// - UpdateWindowInFocusOrderList() [Internal]
|
|
|
+// - BringWindowToFocusFront() [Internal]
|
|
|
+// - BringWindowToDisplayFront() [Internal]
|
|
|
+// - BringWindowToDisplayBack() [Internal]
|
|
|
+// - BringWindowToDisplayBehind() [Internal]
|
|
|
+// - FindWindowDisplayIndex() [Internal]
|
|
|
+// - FocusWindow() [Internal]
|
|
|
+// - FocusTopMostWindowUnderOne() [Internal]
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+
|
|
|
+void ImGui::SetWindowFocus()
|
|
|
+{
|
|
|
+ FocusWindow(GImGui->CurrentWindow);
|
|
|
+}
|
|
|
+
|
|
|
+void ImGui::SetWindowFocus(const char* name)
|
|
|
+{
|
|
|
+ if (name)
|
|
|
+ {
|
|
|
+ if (ImGuiWindow* window = FindWindowByName(name))
|
|
|
+ FocusWindow(window);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ FocusWindow(NULL);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void ImGui::SetNextWindowFocus()
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus;
|
|
|
+}
|
|
|
+
|
|
|
+// Similar to IsWindowHovered()
|
|
|
+bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ ImGuiWindow* ref_window = g.NavWindow;
|
|
|
+ ImGuiWindow* cur_window = g.CurrentWindow;
|
|
|
+
|
|
|
+ if (ref_window == NULL)
|
|
|
+ return false;
|
|
|
+ if (flags & ImGuiFocusedFlags_AnyWindow)
|
|
|
+ return true;
|
|
|
+
|
|
|
+ IM_ASSERT(cur_window); // Not inside a Begin()/End()
|
|
|
+ const bool popup_hierarchy = (flags & ImGuiFocusedFlags_NoPopupHierarchy) == 0;
|
|
|
+ if (flags & ImGuiHoveredFlags_RootWindow)
|
|
|
+ cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy);
|
|
|
+
|
|
|
+ if (flags & ImGuiHoveredFlags_ChildWindows)
|
|
|
+ return IsWindowChildOf(ref_window, cur_window, popup_hierarchy);
|
|
|
+ else
|
|
|
+ return (ref_window == cur_window);
|
|
|
+}
|
|
|
+
|
|
|
+static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ IM_UNUSED(g);
|
|
|
+ int order = window->FocusOrder;
|
|
|
+ IM_ASSERT(window->RootWindow == window); // No child window (not testing _ChildWindow because of docking)
|
|
|
+ IM_ASSERT(g.WindowsFocusOrder[order] == window);
|
|
|
+ return order;
|
|
|
+}
|
|
|
+
|
|
|
+static void ImGui::UpdateWindowInFocusOrderList(ImGuiWindow* window, bool just_created, ImGuiWindowFlags new_flags)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+
|
|
|
+ const bool new_is_explicit_child = (new_flags & ImGuiWindowFlags_ChildWindow) != 0 && ((new_flags & ImGuiWindowFlags_Popup) == 0 || (new_flags & ImGuiWindowFlags_ChildMenu) != 0);
|
|
|
+ const bool child_flag_changed = new_is_explicit_child != window->IsExplicitChild;
|
|
|
+ if ((just_created || child_flag_changed) && !new_is_explicit_child)
|
|
|
+ {
|
|
|
+ IM_ASSERT(!g.WindowsFocusOrder.contains(window));
|
|
|
+ g.WindowsFocusOrder.push_back(window);
|
|
|
+ window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1);
|
|
|
+ }
|
|
|
+ else if (!just_created && child_flag_changed && new_is_explicit_child)
|
|
|
+ {
|
|
|
+ IM_ASSERT(g.WindowsFocusOrder[window->FocusOrder] == window);
|
|
|
+ for (int n = window->FocusOrder + 1; n < g.WindowsFocusOrder.Size; n++)
|
|
|
+ g.WindowsFocusOrder[n]->FocusOrder--;
|
|
|
+ g.WindowsFocusOrder.erase(g.WindowsFocusOrder.Data + window->FocusOrder);
|
|
|
+ window->FocusOrder = -1;
|
|
|
+ }
|
|
|
+ window->IsExplicitChild = new_is_explicit_child;
|
|
|
+}
|
|
|
+
|
|
|
+void ImGui::BringWindowToFocusFront(ImGuiWindow* window)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ IM_ASSERT(window == window->RootWindow);
|
|
|
+
|
|
|
+ const int cur_order = window->FocusOrder;
|
|
|
+ IM_ASSERT(g.WindowsFocusOrder[cur_order] == window);
|
|
|
+ if (g.WindowsFocusOrder.back() == window)
|
|
|
+ return;
|
|
|
+
|
|
|
+ const int new_order = g.WindowsFocusOrder.Size - 1;
|
|
|
+ for (int n = cur_order; n < new_order; n++)
|
|
|
+ {
|
|
|
+ g.WindowsFocusOrder[n] = g.WindowsFocusOrder[n + 1];
|
|
|
+ g.WindowsFocusOrder[n]->FocusOrder--;
|
|
|
+ IM_ASSERT(g.WindowsFocusOrder[n]->FocusOrder == n);
|
|
|
+ }
|
|
|
+ g.WindowsFocusOrder[new_order] = window;
|
|
|
+ window->FocusOrder = (short)new_order;
|
|
|
+}
|
|
|
+
|
|
|
+// Note technically focus related but rather adjacent and close to BringWindowToFocusFront()
|
|
|
+void ImGui::BringWindowToDisplayFront(ImGuiWindow* window)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ ImGuiWindow* current_front_window = g.Windows.back();
|
|
|
+ if (current_front_window == window || current_front_window->RootWindow == window) // Cheap early out (could be better)
|
|
|
+ return;
|
|
|
+ for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the top-most window
|
|
|
+ if (g.Windows[i] == window)
|
|
|
+ {
|
|
|
+ memmove(&g.Windows[i], &g.Windows[i + 1], (size_t)(g.Windows.Size - i - 1) * sizeof(ImGuiWindow*));
|
|
|
+ g.Windows[g.Windows.Size - 1] = window;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ if (g.Windows[0] == window)
|
|
|
+ return;
|
|
|
+ for (int i = 0; i < g.Windows.Size; i++)
|
|
|
+ if (g.Windows[i] == window)
|
|
|
+ {
|
|
|
+ memmove(&g.Windows[1], &g.Windows[0], (size_t)i * sizeof(ImGuiWindow*));
|
|
|
+ g.Windows[0] = window;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void ImGui::BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* behind_window)
|
|
|
+{
|
|
|
+ IM_ASSERT(window != NULL && behind_window != NULL);
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ window = window->RootWindow;
|
|
|
+ behind_window = behind_window->RootWindow;
|
|
|
+ int pos_wnd = FindWindowDisplayIndex(window);
|
|
|
+ int pos_beh = FindWindowDisplayIndex(behind_window);
|
|
|
+ if (pos_wnd < pos_beh)
|
|
|
+ {
|
|
|
+ size_t copy_bytes = (pos_beh - pos_wnd - 1) * sizeof(ImGuiWindow*);
|
|
|
+ memmove(&g.Windows.Data[pos_wnd], &g.Windows.Data[pos_wnd + 1], copy_bytes);
|
|
|
+ g.Windows[pos_beh - 1] = window;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ size_t copy_bytes = (pos_wnd - pos_beh) * sizeof(ImGuiWindow*);
|
|
|
+ memmove(&g.Windows.Data[pos_beh + 1], &g.Windows.Data[pos_beh], copy_bytes);
|
|
|
+ g.Windows[pos_beh] = window;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int ImGui::FindWindowDisplayIndex(ImGuiWindow* window)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ return g.Windows.index_from_ptr(g.Windows.find(window));
|
|
|
+}
|
|
|
+
|
|
|
+// Moving window to front of display and set focus (which happens to be back of our sorted list)
|
|
|
+void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+
|
|
|
+ // Modal check?
|
|
|
+ if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window)) // Early out in common case.
|
|
|
+ if (ImGuiWindow* blocking_modal = FindBlockingModal(window))
|
|
|
+ {
|
|
|
+ // This block would typically be reached in two situations:
|
|
|
+ // - API call to FocusWindow() with a window under a modal and ImGuiFocusRequestFlags_UnlessBelowModal flag.
|
|
|
+ // - User clicking on void or anything behind a modal while a modal is open (window == NULL)
|
|
|
+ IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "<NULL>", blocking_modal->Name);
|
|
|
+ if (window && window == window->RootWindow && (window->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
|
|
|
+ BringWindowToDisplayBehind(window, blocking_modal); // Still bring right under modal. (FIXME: Could move in focus list too?)
|
|
|
+ ClosePopupsOverWindow(GetTopMostPopupModal(), false); // Note how we need to use GetTopMostPopupModal() aad NOT blocking_modal, to handle nested modals
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Find last focused child (if any) and focus it instead.
|
|
|
+ if ((flags & ImGuiFocusRequestFlags_RestoreFocusedChild) && window != NULL)
|
|
|
+ window = NavRestoreLastChildNavWindow(window);
|
|
|
+
|
|
|
+ // Apply focus
|
|
|
+ if (g.NavWindow != window)
|
|
|
+ {
|
|
|
+ SetNavWindow(window);
|
|
|
+ if (window && g.NavHighlightItemUnderNav)
|
|
|
+ g.NavMousePosDirty = true;
|
|
|
+ g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
|
|
|
+ g.NavLayer = ImGuiNavLayer_Main;
|
|
|
+ SetNavFocusScope(window ? window->NavRootFocusScopeId : 0);
|
|
|
+ g.NavIdIsAlive = false;
|
|
|
+ g.NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid;
|
|
|
+
|
|
|
+ // Close popups if any
|
|
|
+ ClosePopupsOverWindow(window, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ // Move the root window to the top of the pile
|
|
|
+ IM_ASSERT(window == NULL || window->RootWindow != NULL);
|
|
|
+ ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL; // NB: In docking branch this is window->RootWindowDockStop
|
|
|
+ ImGuiWindow* display_front_window = window ? window->RootWindow : NULL;
|
|
|
+
|
|
|
+ // 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.ActiveIdNoClearOnFocusLoss)
|
|
|
+ ClearActiveID();
|
|
|
+
|
|
|
+ // Passing NULL allow to disable keyboard focus
|
|
|
+ if (!window)
|
|
|
+ return;
|
|
|
+
|
|
|
+ // Bring to front
|
|
|
+ BringWindowToFocusFront(focus_front_window);
|
|
|
+ if (((window->Flags | display_front_window->Flags) & ImGuiWindowFlags_NoBringToFrontOnFocus) == 0)
|
|
|
+ BringWindowToDisplayFront(display_front_window);
|
|
|
+}
|
|
|
+
|
|
|
+void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWindow* ignore_window, ImGuiViewport* filter_viewport, ImGuiFocusRequestFlags flags)
|
|
|
+{
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
+ IM_UNUSED(filter_viewport); // Unused in master branch.
|
|
|
+ int start_idx = g.WindowsFocusOrder.Size - 1;
|
|
|
+ if (under_this_window != NULL)
|
|
|
+ {
|
|
|
+ // Aim at root window behind us, if we are in a child window that's our own root (see #4640)
|
|
|
+ int offset = -1;
|
|
|
+ while (under_this_window->Flags & ImGuiWindowFlags_ChildWindow)
|
|
|
+ {
|
|
|
+ under_this_window = under_this_window->ParentWindow;
|
|
|
+ offset = 0;
|
|
|
+ }
|
|
|
+ start_idx = FindWindowFocusIndex(under_this_window) + offset;
|
|
|
+ }
|
|
|
+ for (int i = start_idx; i >= 0; i--)
|
|
|
+ {
|
|
|
+ // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user.
|
|
|
+ ImGuiWindow* window = g.WindowsFocusOrder[i];
|
|
|
+ if (window == ignore_window || !window->WasActive)
|
|
|
+ continue;
|
|
|
+ if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
|
|
|
+ {
|
|
|
+ FocusWindow(window, flags);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ FocusWindow(NULL, flags);
|
|
|
+}
|
|
|
+
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
|
|
|
//-----------------------------------------------------------------------------
|
|
@@ -13504,16 +13536,6 @@ static void ImGui::NavUpdateCreateWrappingRequest()
|
|
|
NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags);
|
|
|
}
|
|
|
|
|
|
-static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
|
|
|
-{
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
- IM_UNUSED(g);
|
|
|
- int order = window->FocusOrder;
|
|
|
- IM_ASSERT(window->RootWindow == window); // No child window (not testing _ChildWindow because of docking)
|
|
|
- IM_ASSERT(g.WindowsFocusOrder[order] == window);
|
|
|
- return order;
|
|
|
-}
|
|
|
-
|
|
|
// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext)
|
|
|
// Note that NoNavFocus makes the window not reachable with CTRL+TAB but it can still be focused with mouse or programmatically.
|
|
|
// If you want a window to never be focused, you may use the e.g. NoInputs flag.
|