|
@@ -85,6 +85,7 @@ CODE
|
|
// [SECTION] SCROLLING
|
|
// [SECTION] SCROLLING
|
|
// [SECTION] TOOLTIPS
|
|
// [SECTION] TOOLTIPS
|
|
// [SECTION] POPUPS
|
|
// [SECTION] POPUPS
|
|
|
|
+// [SECTION] WINDOW FOCUS
|
|
// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
|
|
// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
|
|
// [SECTION] DRAG AND DROP
|
|
// [SECTION] DRAG AND DROP
|
|
// [SECTION] LOGGING/CAPTURING
|
|
// [SECTION] LOGGING/CAPTURING
|
|
@@ -1216,6 +1217,10 @@ namespace ImGui
|
|
// Item
|
|
// Item
|
|
static void ItemHandleShortcut(ImGuiID id);
|
|
static void ItemHandleShortcut(ImGuiID id);
|
|
|
|
|
|
|
|
+// Window Focus
|
|
|
|
+static int FindWindowFocusIndex(ImGuiWindow* window);
|
|
|
|
+static void UpdateWindowInFocusOrderList(ImGuiWindow* window, bool just_created, ImGuiWindowFlags new_flags);
|
|
|
|
+
|
|
// Navigation
|
|
// Navigation
|
|
static void NavUpdate();
|
|
static void NavUpdate();
|
|
static void NavUpdateWindowing();
|
|
static void NavUpdateWindowing();
|
|
@@ -1236,7 +1241,6 @@ static ImVec2 NavCalcPreferredRefPos();
|
|
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
|
|
static void NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window);
|
|
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
|
|
static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window);
|
|
static void NavRestoreLayer(ImGuiNavLayer layer);
|
|
static void NavRestoreLayer(ImGuiNavLayer layer);
|
|
-static int FindWindowFocusIndex(ImGuiWindow* window);
|
|
|
|
|
|
|
|
// Error Checking and Debug Tools
|
|
// Error Checking and Debug Tools
|
|
static void ErrorCheckNewFrameSanityChecks();
|
|
static void ErrorCheckNewFrameSanityChecks();
|
|
@@ -3610,7 +3614,6 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
|
|
return "Unknown";
|
|
return "Unknown";
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
// [SECTION] RENDER HELPERS
|
|
// [SECTION] RENDER HELPERS
|
|
// Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change,
|
|
// Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change,
|
|
@@ -4348,7 +4351,6 @@ void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type)
|
|
hook.Callback(&g, &hook);
|
|
hook.Callback(&g, &hook);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
|
|
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
@@ -6460,29 +6462,6 @@ static void ApplyWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settin
|
|
window->DockOrder = settings->DockOrder;
|
|
window->DockOrder = settings->DockOrder;
|
|
}
|
|
}
|
|
|
|
|
|
-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)
|
|
static void InitOrLoadWindowSettings(ImGuiWindow* window, ImGuiWindowSettings* settings)
|
|
{
|
|
{
|
|
// Initial window state with e.g. default/arbitrary window position
|
|
// Initial window state with e.g. default/arbitrary window position
|
|
@@ -7341,42 +7320,6 @@ static void SetWindowActiveForSkipRefresh(ImGuiWindow* window)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-// When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing)
|
|
|
|
-// should be positioned behind that modal window, unless the window was created inside the modal begin-stack.
|
|
|
|
-// In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent.
|
|
|
|
-// - WindowA // FindBlockingModal() returns Modal1
|
|
|
|
-// - WindowB // .. returns Modal1
|
|
|
|
-// - Modal1 // .. returns Modal2
|
|
|
|
-// - WindowC // .. returns Modal2
|
|
|
|
-// - WindowD // .. returns Modal2
|
|
|
|
-// - Modal2 // .. returns Modal2
|
|
|
|
-// - WindowE // .. returns NULL
|
|
|
|
-// Notes:
|
|
|
|
-// - FindBlockingModal(NULL) == NULL is generally equivalent to GetTopMostPopupModal() == NULL.
|
|
|
|
-// Only difference is here we check for ->Active/WasActive but it may be unnecessary.
|
|
|
|
-ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
|
|
|
|
-{
|
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
|
- if (g.OpenPopupStack.Size <= 0)
|
|
|
|
- return NULL;
|
|
|
|
-
|
|
|
|
- // Find a modal that has common parent with specified window. Specified window should be positioned behind that modal.
|
|
|
|
- for (ImGuiPopupData& popup_data : g.OpenPopupStack)
|
|
|
|
- {
|
|
|
|
- ImGuiWindow* popup_window = popup_data.Window;
|
|
|
|
- if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal))
|
|
|
|
- continue;
|
|
|
|
- if (!popup_window->Active && !popup_window->WasActive) // Check WasActive, because this code may run before popup renders on current frame, also check Active to handle newly created windows.
|
|
|
|
- continue;
|
|
|
|
- if (window == NULL) // FindBlockingModal(NULL) test for if FocusWindow(NULL) is naturally possible via a mouse click.
|
|
|
|
- return popup_window;
|
|
|
|
- if (IsWindowWithinBeginStackOf(window, popup_window)) // Window may be over modal
|
|
|
|
- continue;
|
|
|
|
- return popup_window; // Place window right below first block modal
|
|
|
|
- }
|
|
|
|
- return NULL;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
// Push a new Dear ImGui window to add widgets to.
|
|
// Push a new Dear ImGui window to add widgets to.
|
|
// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
|
|
// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
|
|
// - Begin/End can be called multiple times during the frame with the same window name to append content.
|
|
// - Begin/End can be called multiple times during the frame with the same window name to append content.
|
|
@@ -8385,191 +8328,6 @@ void ImGui::End()
|
|
SetCurrentViewport(g.CurrentWindow, g.CurrentWindow->Viewport);
|
|
SetCurrentViewport(g.CurrentWindow, g.CurrentWindow->Viewport);
|
|
}
|
|
}
|
|
|
|
|
|
-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->RootWindowDockTree == 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->RootWindowDockTree != NULL);
|
|
|
|
- ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL;
|
|
|
|
- ImGuiWindow* display_front_window = window ? window->RootWindowDockTree : NULL;
|
|
|
|
- ImGuiDockNode* dock_node = window ? window->DockNode : NULL;
|
|
|
|
- bool active_id_window_is_dock_node_host = (g.ActiveIdWindow && dock_node && dock_node->HostWindow == g.ActiveIdWindow);
|
|
|
|
-
|
|
|
|
- // 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)
|
|
|
|
- // - Using dock host items (tab, collapse button) can trigger this before we redirect the ActiveIdWindow toward the child window.
|
|
|
|
- if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window)
|
|
|
|
- if (!g.ActiveIdNoClearOnFocusLoss && !active_id_window_is_dock_node_host)
|
|
|
|
- ClearActiveID();
|
|
|
|
-
|
|
|
|
- // Passing NULL allow to disable keyboard focus
|
|
|
|
- if (!window)
|
|
|
|
- return;
|
|
|
|
- window->LastFrameJustFocused = g.FrameCount;
|
|
|
|
-
|
|
|
|
- // Select in dock node
|
|
|
|
- // For #2304 we avoid applying focus immediately before the tabbar is visible.
|
|
|
|
- //if (dock_node && dock_node->TabBar)
|
|
|
|
- // dock_node->TabBar->SelectedTabId = dock_node->TabBar->NextSelectedTabId = window->TabId;
|
|
|
|
-
|
|
|
|
- // Bring to front
|
|
|
|
- BringWindowToFocusFront(focus_front_window);
|
|
|
|
- if (((window->Flags | focus_front_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;
|
|
|
|
- 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 (filter_viewport != NULL && window->Viewport != filter_viewport)
|
|
|
|
- continue;
|
|
|
|
- if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
|
|
|
|
- {
|
|
|
|
- // FIXME-DOCK: When ImGuiFocusRequestFlags_RestoreFocusedChild is set...
|
|
|
|
- // This is failing (lagging by one frame) for docked windows.
|
|
|
|
- // If A and B are docked into window and B disappear, at the NewFrame() call site window->NavLastChildNavWindow will still point to B.
|
|
|
|
- // We might leverage the tab order implicitly stored in window->DockNodeAsHost->TabBar (essentially the 'most_recently_selected_tab' code in tab bar will do that but on next update)
|
|
|
|
- // to tell which is the "previous" window. Or we may leverage 'LastFrameFocused/LastFrameJustFocused' and have this function handle child window itself?
|
|
|
|
- FocusWindow(window, flags);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- FocusWindow(NULL, flags);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only.
|
|
// Important: this alone doesn't alter current ImDrawList state. This is called by PushFont/PopFont only.
|
|
void ImGui::SetCurrentFont(ImFont* font)
|
|
void ImGui::SetCurrentFont(ImFont* font)
|
|
{
|
|
{
|
|
@@ -8842,34 +8600,11 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags)
|
|
|
|
|
|
+ImGuiID ImGui::GetWindowDockID()
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
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;
|
|
|
|
- const bool dock_hierarchy = (flags & ImGuiFocusedFlags_DockHierarchy) != 0;
|
|
|
|
- if (flags & ImGuiHoveredFlags_RootWindow)
|
|
|
|
- cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
|
|
|
|
-
|
|
|
|
- if (flags & ImGuiHoveredFlags_ChildWindows)
|
|
|
|
- return IsWindowChildOf(ref_window, cur_window, popup_hierarchy, dock_hierarchy);
|
|
|
|
- else
|
|
|
|
- return (ref_window == cur_window);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-ImGuiID ImGui::GetWindowDockID()
|
|
|
|
-{
|
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
|
- return g.CurrentWindow->DockId;
|
|
|
|
-}
|
|
|
|
|
|
+ return g.CurrentWindow->DockId;
|
|
|
|
+}
|
|
|
|
|
|
bool ImGui::IsWindowDocked()
|
|
bool ImGui::IsWindowDocked()
|
|
{
|
|
{
|
|
@@ -8877,14 +8612,6 @@ bool ImGui::IsWindowDocked()
|
|
return g.CurrentWindow->DockIsActive;
|
|
return g.CurrentWindow->DockIsActive;
|
|
}
|
|
}
|
|
|
|
|
|
-// 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.
|
|
|
|
-bool ImGui::IsWindowNavFocusable(ImGuiWindow* window)
|
|
|
|
-{
|
|
|
|
- return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
float ImGui::GetWindowWidth()
|
|
float ImGui::GetWindowWidth()
|
|
{
|
|
{
|
|
ImGuiWindow* window = GImGui->CurrentWindow;
|
|
ImGuiWindow* window = GImGui->CurrentWindow;
|
|
@@ -9033,24 +8760,6 @@ void ImGui::SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond)
|
|
SetWindowCollapsed(window, collapsed, 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)
|
|
void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -9109,12 +8818,6 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond)
|
|
g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
|
|
g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always;
|
|
}
|
|
}
|
|
|
|
|
|
-void ImGui::SetNextWindowFocus()
|
|
|
|
-{
|
|
|
|
- ImGuiContext& g = *GImGui;
|
|
|
|
- g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasFocus;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
void ImGui::SetNextWindowBgAlpha(float alpha)
|
|
void ImGui::SetNextWindowBgAlpha(float alpha)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -10957,7 +10660,6 @@ bool ImGui::Shortcut(ImGuiKeyChord key_chord, ImGuiInputFlags flags, ImGuiID own
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
// [SECTION] ERROR CHECKING, STATE RECOVERY
|
|
// [SECTION] ERROR CHECKING, STATE RECOVERY
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
@@ -12344,6 +12046,43 @@ ImGuiWindow* ImGui::GetTopMostAndVisiblePopupModal()
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+// When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing)
|
|
|
|
+// should be positioned behind that modal window, unless the window was created inside the modal begin-stack.
|
|
|
|
+// In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent.
|
|
|
|
+// - WindowA // FindBlockingModal() returns Modal1
|
|
|
|
+// - WindowB // .. returns Modal1
|
|
|
|
+// - Modal1 // .. returns Modal2
|
|
|
|
+// - WindowC // .. returns Modal2
|
|
|
|
+// - WindowD // .. returns Modal2
|
|
|
|
+// - Modal2 // .. returns Modal2
|
|
|
|
+// - WindowE // .. returns NULL
|
|
|
|
+// Notes:
|
|
|
|
+// - FindBlockingModal(NULL) == NULL is generally equivalent to GetTopMostPopupModal() == NULL.
|
|
|
|
+// Only difference is here we check for ->Active/WasActive but it may be unnecessary.
|
|
|
|
+ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ if (g.OpenPopupStack.Size <= 0)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ // Find a modal that has common parent with specified window. Specified window should be positioned behind that modal.
|
|
|
|
+ for (ImGuiPopupData& popup_data : g.OpenPopupStack)
|
|
|
|
+ {
|
|
|
|
+ ImGuiWindow* popup_window = popup_data.Window;
|
|
|
|
+ if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Modal))
|
|
|
|
+ continue;
|
|
|
|
+ if (!popup_window->Active && !popup_window->WasActive) // Check WasActive, because this code may run before popup renders on current frame, also check Active to handle newly created windows.
|
|
|
|
+ continue;
|
|
|
|
+ if (window == NULL) // FindBlockingModal(NULL) test for if FocusWindow(NULL) is naturally possible via a mouse click.
|
|
|
|
+ return popup_window;
|
|
|
|
+ if (IsWindowWithinBeginStackOf(window, popup_window)) // Window may be over modal
|
|
|
|
+ continue;
|
|
|
|
+ return popup_window; // Place window right below first block modal
|
|
|
|
+ }
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
void ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags)
|
|
void ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -12858,6 +12597,289 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window)
|
|
return window->Pos;
|
|
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;
|
|
|
|
+ const bool dock_hierarchy = (flags & ImGuiFocusedFlags_DockHierarchy) != 0;
|
|
|
|
+ if (flags & ImGuiHoveredFlags_RootWindow)
|
|
|
|
+ cur_window = GetCombinedRootWindow(cur_window, popup_hierarchy, dock_hierarchy);
|
|
|
|
+
|
|
|
|
+ if (flags & ImGuiHoveredFlags_ChildWindows)
|
|
|
|
+ return IsWindowChildOf(ref_window, cur_window, popup_hierarchy, dock_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->RootWindowDockTree == 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->RootWindowDockTree != NULL);
|
|
|
|
+ ImGuiWindow* focus_front_window = window ? window->RootWindow : NULL;
|
|
|
|
+ ImGuiWindow* display_front_window = window ? window->RootWindowDockTree : NULL;
|
|
|
|
+ ImGuiDockNode* dock_node = window ? window->DockNode : NULL;
|
|
|
|
+ bool active_id_window_is_dock_node_host = (g.ActiveIdWindow && dock_node && dock_node->HostWindow == g.ActiveIdWindow);
|
|
|
|
+
|
|
|
|
+ // 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)
|
|
|
|
+ // - Using dock host items (tab, collapse button) can trigger this before we redirect the ActiveIdWindow toward the child window.
|
|
|
|
+ if (g.ActiveId != 0 && g.ActiveIdWindow && g.ActiveIdWindow->RootWindow != focus_front_window)
|
|
|
|
+ if (!g.ActiveIdNoClearOnFocusLoss && !active_id_window_is_dock_node_host)
|
|
|
|
+ ClearActiveID();
|
|
|
|
+
|
|
|
|
+ // Passing NULL allow to disable keyboard focus
|
|
|
|
+ if (!window)
|
|
|
|
+ return;
|
|
|
|
+ window->LastFrameJustFocused = g.FrameCount;
|
|
|
|
+
|
|
|
|
+ // Select in dock node
|
|
|
|
+ // For #2304 we avoid applying focus immediately before the tabbar is visible.
|
|
|
|
+ //if (dock_node && dock_node->TabBar)
|
|
|
|
+ // dock_node->TabBar->SelectedTabId = dock_node->TabBar->NextSelectedTabId = window->TabId;
|
|
|
|
+
|
|
|
|
+ // Bring to front
|
|
|
|
+ BringWindowToFocusFront(focus_front_window);
|
|
|
|
+ if (((window->Flags | focus_front_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;
|
|
|
|
+ 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 (filter_viewport != NULL && window->Viewport != filter_viewport)
|
|
|
|
+ continue;
|
|
|
|
+ if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs))
|
|
|
|
+ {
|
|
|
|
+ // FIXME-DOCK: When ImGuiFocusRequestFlags_RestoreFocusedChild is set...
|
|
|
|
+ // This is failing (lagging by one frame) for docked windows.
|
|
|
|
+ // If A and B are docked into window and B disappear, at the NewFrame() call site window->NavLastChildNavWindow will still point to B.
|
|
|
|
+ // We might leverage the tab order implicitly stored in window->DockNodeAsHost->TabBar (essentially the 'most_recently_selected_tab' code in tab bar will do that but on next update)
|
|
|
|
+ // to tell which is the "previous" window. Or we may leverage 'LastFrameFocused/LastFrameJustFocused' and have this function handle child window itself?
|
|
|
|
+ FocusWindow(window, flags);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ FocusWindow(NULL, flags);
|
|
|
|
+}
|
|
|
|
+
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
|
|
// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
@@ -14218,14 +14240,12 @@ static void ImGui::NavUpdateCreateWrappingRequest()
|
|
NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags);
|
|
NavMoveRequestForward(g.NavMoveDir, clip_dir, move_flags, g.NavMoveScrollFlags);
|
|
}
|
|
}
|
|
|
|
|
|
-static int ImGui::FindWindowFocusIndex(ImGuiWindow* window)
|
|
|
|
|
|
+// 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.
|
|
|
|
+bool ImGui::IsWindowNavFocusable(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;
|
|
|
|
|
|
+ return window->WasActive && window == window->RootWindow && !(window->Flags & ImGuiWindowFlags_NoNavFocus);
|
|
}
|
|
}
|
|
|
|
|
|
static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N)
|
|
static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N)
|
|
@@ -14515,7 +14535,6 @@ void ImGui::NavUpdateWindowingOverlay()
|
|
PopStyleVar();
|
|
PopStyleVar();
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
// [SECTION] DRAG AND DROP
|
|
// [SECTION] DRAG AND DROP
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
@@ -15124,7 +15143,6 @@ void ImGui::LogButtons()
|
|
LogToClipboard();
|
|
LogToClipboard();
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
// [SECTION] SETTINGS
|
|
// [SECTION] SETTINGS
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
@@ -15515,7 +15533,6 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandl
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
// [SECTION] LOCALIZATION
|
|
// [SECTION] LOCALIZATION
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
@@ -15527,7 +15544,6 @@ void ImGui::LocalizeRegisterEntries(const ImGuiLocEntry* entries, int count)
|
|
g.LocalizationTable[entries[n].Key] = entries[n].Text;
|
|
g.LocalizationTable[entries[n].Key] = entries[n].Text;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
// [SECTION] VIEWPORTS, PLATFORM WINDOWS
|
|
// [SECTION] VIEWPORTS, PLATFORM WINDOWS
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|