mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-06 04:58:47 +02:00
Internals: rework FocusScope system, current scope doesn't need to be in window + child doesn't inherit.
Intended as part of work for input routing + blind menu processing shortcuts. Some of this commit will be stripped by next commit. Intent was to sort windows along with focus scope to build a hierarchy, but for our needs we'd need a persistant one, so scrapping the idea. Not squashing this with next commit to keep a bit of history for future references.
This commit is contained in:
66
imgui.cpp
66
imgui.cpp
@ -6319,10 +6319,23 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
window_stack_data.ParentLastItemDataBackup = g.LastItemData;
|
||||
window_stack_data.StackSizesOnBegin.SetToCurrentState();
|
||||
g.CurrentWindowStack.push_back(window_stack_data);
|
||||
g.CurrentWindow = NULL;
|
||||
if (flags & ImGuiWindowFlags_ChildMenu)
|
||||
g.BeginMenuCount++;
|
||||
|
||||
// Update ->RootWindow and others pointers (before any possible call to FocusWindow)
|
||||
if (first_begin_of_the_frame)
|
||||
{
|
||||
UpdateWindowParentAndRootLinks(window, flags, parent_window);
|
||||
window->ParentWindowInBeginStack = parent_window_in_stack;
|
||||
}
|
||||
|
||||
// Add to focus scope stack - inherited by default by child windows from parent, reset by regular window
|
||||
//if (window == window->RootWindow && (window->Flags & ImGuiWindowFlags_ChildMenu) == 0)
|
||||
PushFocusScope(window->ID);
|
||||
window->NavRootFocusScopeId = g.CurrentFocusScopeId;
|
||||
g.CurrentWindow = NULL;
|
||||
|
||||
// Add to popup stack
|
||||
if (flags & ImGuiWindowFlags_Popup)
|
||||
{
|
||||
ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
|
||||
@ -6332,13 +6345,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
window->PopupId = popup_ref.PopupId;
|
||||
}
|
||||
|
||||
// Update ->RootWindow and others pointers (before any possible call to FocusWindow)
|
||||
if (first_begin_of_the_frame)
|
||||
{
|
||||
UpdateWindowParentAndRootLinks(window, flags, parent_window);
|
||||
window->ParentWindowInBeginStack = parent_window_in_stack;
|
||||
}
|
||||
|
||||
// Process SetNextWindow***() calls
|
||||
// (FIXME: Consider splitting the HasXXX flags into X/Y components
|
||||
bool window_pos_set_by_api = false;
|
||||
@ -6859,9 +6865,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
SetCurrentWindow(window);
|
||||
}
|
||||
|
||||
// Pull/inherit current state
|
||||
window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : window->GetID("#FOCUSSCOPE"); // Inherit from parent only // -V595
|
||||
|
||||
PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true);
|
||||
|
||||
// Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused)
|
||||
@ -6939,6 +6942,8 @@ void ImGui::End()
|
||||
if (window->DC.CurrentColumns)
|
||||
EndColumns();
|
||||
PopClipRect(); // Inner window clip rectangle
|
||||
//if (window == window->RootWindow && (window->Flags & ImGuiWindowFlags_ChildMenu) == 0)
|
||||
PopFocusScope();
|
||||
|
||||
// Stop logging
|
||||
if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging
|
||||
@ -7048,7 +7053,7 @@ void ImGui::FocusWindow(ImGuiWindow* window)
|
||||
g.NavMousePosDirty = true;
|
||||
g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId
|
||||
g.NavLayer = ImGuiNavLayer_Main;
|
||||
g.NavFocusScopeId = 0;
|
||||
g.NavFocusScopeId = window ? window->NavRootFocusScopeId : 0;
|
||||
g.NavIdIsAlive = false;
|
||||
|
||||
// Close popups if any
|
||||
@ -7619,18 +7624,24 @@ void ImGui::ActivateItem(ImGuiID id)
|
||||
void ImGui::PushFocusScope(ImGuiID id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
g.FocusScopeStack.push_back(window->DC.NavFocusScopeIdCurrent);
|
||||
window->DC.NavFocusScopeIdCurrent = id;
|
||||
if (g.FocusScopeStackLocked > 0)
|
||||
return;
|
||||
ImGuiFocusScope scope;
|
||||
scope.FocusScopeId = id;
|
||||
scope.Window = g.CurrentWindow;
|
||||
g.FocusScopeStack.push_back(scope);
|
||||
g.CurrentFocusScopeId = scope.FocusScopeId;
|
||||
}
|
||||
|
||||
void ImGui::PopFocusScope()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if (g.FocusScopeStackLocked > 0)
|
||||
return;
|
||||
IM_ASSERT(g.FocusScopeStack.Size > 0); // Too many PopFocusScope() ?
|
||||
window->DC.NavFocusScopeIdCurrent = g.FocusScopeStack.back();
|
||||
IM_ASSERT(g.FocusScopeStack.back().Window == g.CurrentWindow); // Mismatched pop location?
|
||||
g.FocusScopeStack.pop_back();
|
||||
g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().FocusScopeId : 0;
|
||||
}
|
||||
|
||||
// Note: this will likely be called ActivateItem() once we rework our Focus/Activation system!
|
||||
@ -8509,7 +8520,7 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name);
|
||||
PopStyleVar();
|
||||
}
|
||||
while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack) //-V1044
|
||||
while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack + 1) //-V1044
|
||||
{
|
||||
if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name);
|
||||
PopFocusScope();
|
||||
@ -9953,12 +9964,12 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
|
||||
if (g.NavWindow != window)
|
||||
SetNavWindow(window);
|
||||
|
||||
// Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and window->DC.NavFocusScopeIdCurrent are valid.
|
||||
// Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and g.CurrentFocusScopeId are valid.
|
||||
// Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text)
|
||||
const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent;
|
||||
g.NavId = id;
|
||||
g.NavLayer = nav_layer;
|
||||
g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||
g.NavFocusScopeId = g.CurrentFocusScopeId;
|
||||
window->NavLastIds[nav_layer] = id;
|
||||
if (g.LastItemData.ID == id)
|
||||
window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
||||
@ -10139,7 +10150,7 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result)
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
result->Window = window;
|
||||
result->ID = g.LastItemData.ID;
|
||||
result->FocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||
result->FocusScopeId = g.CurrentFocusScopeId;
|
||||
result->InFlags = g.LastItemData.InFlags;
|
||||
result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect);
|
||||
}
|
||||
@ -10206,7 +10217,7 @@ static void ImGui::NavProcessItem()
|
||||
if (g.NavWindow != window)
|
||||
SetNavWindow(window); // Always refresh g.NavWindow, because some operations such as FocusItem() may not have a window.
|
||||
g.NavLayer = window->DC.NavLayerCurrent;
|
||||
g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent;
|
||||
g.NavFocusScopeId = g.CurrentFocusScopeId;
|
||||
g.NavIdIsAlive = true;
|
||||
window->NavRectRel[window->DC.NavLayerCurrent] = WindowRectAbsToRel(window, nav_bb); // Store item bounding box (relative to window position)
|
||||
}
|
||||
@ -10394,7 +10405,8 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
|
||||
|
||||
if (window->Flags & ImGuiWindowFlags_NoNavInputs)
|
||||
{
|
||||
g.NavId = g.NavFocusScopeId = 0;
|
||||
g.NavId = 0;
|
||||
g.NavFocusScopeId = window->NavRootFocusScopeId;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -10404,7 +10416,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
|
||||
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer);
|
||||
if (init_for_nav)
|
||||
{
|
||||
SetNavID(0, g.NavLayer, 0, ImRect());
|
||||
SetNavID(0, g.NavLayer, window->NavRootFocusScopeId, ImRect());
|
||||
g.NavInitRequest = true;
|
||||
g.NavInitRequestFromMove = false;
|
||||
g.NavInitResultId = 0;
|
||||
@ -10414,7 +10426,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
|
||||
else
|
||||
{
|
||||
g.NavId = window->NavLastIds[0];
|
||||
g.NavFocusScopeId = 0;
|
||||
g.NavFocusScopeId = window->NavRootFocusScopeId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10738,7 +10750,7 @@ void ImGui::NavUpdateCreateMoveRequest()
|
||||
inner_rect_rel.Min.y = clamp_y ? (inner_rect_rel.Min.y + pad_y) : -FLT_MAX;
|
||||
inner_rect_rel.Max.y = clamp_y ? (inner_rect_rel.Max.y - pad_y) : +FLT_MAX;
|
||||
window->NavRectRel[g.NavLayer].ClipWithFull(inner_rect_rel);
|
||||
g.NavId = g.NavFocusScopeId = 0;
|
||||
g.NavId = /*g.NavFocusScopeId =*/ 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10921,7 +10933,7 @@ static void ImGui::NavUpdateCancelRequest()
|
||||
// Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were
|
||||
if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow)))
|
||||
g.NavWindow->NavLastIds[0] = 0;
|
||||
g.NavId = g.NavFocusScopeId = 0;
|
||||
g.NavId = /*g.NavFocusScopeId =*/ 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user