mirror of
https://github.com/ocornut/imgui.git
synced 2025-02-02 20:47:23 +01:00
Refactor: moved Window Focus related functions to a dedicated section.
This commit is contained in:
parent
bbbdc70f26
commit
2b8545684c
522
imgui.cpp
522
imgui.cpp
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user