@ -6439,13 +6439,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
}
// Add to focus scope stack
if ( ( flags & ImGuiWindowFlags_NavFlattened ) = = 0 )
PushFocusScope ( window - > ID ) ;
PushFocusScope ( ( flags & ImGuiWindowFlags_NavFlattened ) ? g . CurrentFocusScopeId : window - > ID ) ;
window - > NavRootFocusScopeId = g . CurrentFocusScopeId ;
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
g . CurrentWindow = NULL ;
// Add to popup stack
if ( flags & ImGuiWindowFlags_Popup )
{
@ -6510,6 +6506,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
if ( window - > Appearing )
SetWindowConditionAllowFlags ( window , ImGuiCond_Appearing , false ) ;
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
g . CurrentWindow = NULL ;
// When reusing window again multiple times a frame, just append content (don't need to setup again)
if ( first_begin_of_the_frame )
{
@ -7083,8 +7082,7 @@ void ImGui::End()
if ( window - > DC . CurrentColumns )
EndColumns ( ) ;
PopClipRect ( ) ; // Inner window clip rectangle
if ( ( window - > Flags & ImGuiWindowFlags_NavFlattened ) = = 0 )
PopFocusScope ( ) ;
PopFocusScope ( ) ;
// Stop logging
if ( ! ( window - > Flags & ImGuiWindowFlags_ChildWindow ) ) // FIXME: add more options for scope of logging
@ -7209,7 +7207,7 @@ void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags)
g . NavMousePosDirty = true ;
g . NavId = window ? window - > NavLastIds [ 0 ] : 0 ; // Restore NavId
g . NavLayer = ImGuiNavLayer_Main ;
g . NavFocusScopeId = window ? window - > NavRootFocusScopeId : 0 ;
SetNavFocusScope ( window ? window - > NavRootFocusScopeId : 0 ) ;
g . NavIdIsAlive = false ;
g . NavLastValidSelectionUserData = ImGuiSelectionUserData_Invalid ;
@ -7822,6 +7820,33 @@ void ImGui::PopFocusScope()
g . CurrentFocusScopeId = g . FocusScopeStack . Size ? g . FocusScopeStack . back ( ) . ID : 0 ;
}
void ImGui : : SetNavFocusScope ( ImGuiID focus_scope_id )
{
ImGuiContext & g = * GImGui ;
g . NavFocusScopeId = focus_scope_id ;
g . NavFocusScopePath . resize ( 0 ) ; // Invalidate
if ( focus_scope_id = = 0 )
return ;
IM_ASSERT ( g . NavWindow ! = NULL ) ;
// Store current path (in reverse order)
if ( focus_scope_id = = g . CurrentFocusScopeId )
{
// Top of focus stack contains local focus scopes inside current window
for ( int n = g . FocusScopeStack . Size - 1 ; n > = 0 & & g . FocusScopeStack . Data [ n ] . WindowID = = g . CurrentWindow - > ID ; n - - )
g . NavFocusScopePath . push_back ( g . FocusScopeStack . Data [ n ] ) ;
}
else if ( focus_scope_id = = g . NavWindow - > NavRootFocusScopeId )
g . NavFocusScopePath . push_back ( { focus_scope_id , g . NavWindow - > ID } ) ;
else
return ;
// Then follow on manually set ParentWindowForFocusRoute field (#6798)
for ( ImGuiWindow * window = g . NavWindow - > ParentWindowForFocusRoute ; window ! = NULL ; window = window - > ParentWindowForFocusRoute )
g . NavFocusScopePath . push_back ( { window - > NavRootFocusScopeId , window - > ID } ) ;
IM_ASSERT ( g . NavFocusScopePath . Size < 100 ) ; // Maximum depth is technically 251 as per CalcRoutingScore(): 254 - 3
}
// Focus = move navigation cursor, set scrolling, set focus window.
void ImGui : : FocusItem ( )
{
@ -8318,12 +8343,11 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
// - 254: ImGuiInputFlags_RouteGlobalLow
// - 255: never route
// 'flags' should include an explicit routing policy
static int CalcRoutingScore ( ImGuiWindow * location , ImGuiID owner_id , ImGuiInputFlags flags )
static int CalcRoutingScore ( ImGuiID focus_scope_id , ImGuiID owner_id , ImGuiInputFlags flags )
{
if ( flags & ImGuiInputFlags_RouteFocused )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * focused = g . NavWindow ;
// ActiveID gets top priority
// (we don't check g.ActiveIdUsingAllKeys here. Routing is applied but if input ownership is tested later it may discard it)
@ -8336,13 +8360,12 @@ static int CalcRoutingScore(ImGuiWindow* location, ImGuiID owner_id, ImGuiInputF
// - When Window/ChildB is focused -> Window scores 4, Window/ChildB scores 3 (best)
// Assuming only WindowA is submitting a routing request,
// - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score.
// FIXME: This could be later abstracted as a focus path
for ( int next_score = 3 ; focused ! = NULL ; next_score + + , focused = focused - > ParentWindowForFocusRoute )
if ( focused = = location )
{
IM_ASSERT ( next_score < 255 ) ;
return next_score ;
}
if ( focus_scope_id = = 0 )
return 255 ;
for ( int index_in_focus_path = 0 ; index_in_focus_path < g . NavFocusScopePath . Size ; index_in_focus_path + + )
if ( g . NavFocusScopePath . Data [ index_in_focus_path ] . ID = = focus_scope_id )
return 3 + index_in_focus_path ;
return 255 ;
}
@ -8383,7 +8406,7 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiID owner_id, ImGuiI
return true ;
}
const int score = CalcRoutingScore ( g . CurrentWindow , owner_id , flags ) ;
const int score = CalcRoutingScore ( g . CurrentFocusScopeId , owner_id , flags ) ;
IMGUI_DEBUG_LOG_INPUTROUTING ( " SetShortcutRouting(%s, owner_id=0x%08X, flags=%04X) -> score %d \n " , GetKeyChordName ( key_chord ) , owner_id , flags , score ) ;
if ( score = = 255 )
return false ;
@ -11095,7 +11118,7 @@ void ImGui::SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id
IM_ASSERT ( nav_layer = = ImGuiNavLayer_Main | | nav_layer = = ImGuiNavLayer_Menu ) ;
g . NavId = id ;
g . NavLayer = nav_layer ;
g . NavFocusScopeId = focus_scope_id ;
SetNavFocusScope ( focus_scope_id ) ;
g . NavWindow - > NavLastIds [ nav_layer ] = id ;
g . NavWindow - > NavRectRel [ nav_layer ] = rect_rel ;
@ -11117,7 +11140,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window)
const ImGuiNavLayer nav_layer = window - > DC . NavLayerCurrent ;
g . NavId = id ;
g . NavLayer = nav_layer ;
g . NavFocusScopeId = g . CurrentFocusScopeId ;
SetNavFocusScope ( g . CurrentFocusScopeId ) ;
window - > NavLastIds [ nav_layer ] = id ;
if ( g . LastItemData . ID = = id )
window - > NavRectRel [ nav_layer ] = WindowRectAbsToRel ( window , g . LastItemData . NavRect ) ;
@ -11375,6 +11398,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 ;
SetNavFocusScope ( g . CurrentFocusScopeId ) ; // Will set g.NavFocusScopeId AND store g.NavFocusScopePath
g . NavFocusScopeId = g . CurrentFocusScopeId ;
g . NavIdIsAlive = true ;
if ( g . LastItemData . InFlags & ImGuiItemFlags_HasSelectionUserData )
@ -11604,7 +11628,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
if ( window - > Flags & ImGuiWindowFlags_NoNavInputs )
{
g . NavId = 0 ;
g . NavFocusScopeId = window - > NavRootFocusScopeId ;
SetNavFocusScope ( window - > NavRootFocusScopeId ) ;
return ;
}
@ -11623,7 +11647,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
else
{
g . NavId = window - > NavLastIds [ 0 ] ;
g . NavFocusScopeId = window - > NavRootFocusScopeId ;
SetNavFocusScope ( window - > NavRootFocusScopeId ) ;
}
}
@ -14507,6 +14531,14 @@ void ImGui::ShowMetricsWindow(bool* p_open)
Text ( " NavActivateFlags: %04X " , g . NavActivateFlags ) ;
Text ( " NavDisableHighlight: %d, NavDisableMouseHover: %d " , g . NavDisableHighlight , g . NavDisableMouseHover ) ;
Text ( " NavFocusScopeId = 0x%08X " , g . NavFocusScopeId ) ;
Text ( " NavFocusScopePath[] = " ) ;
for ( int path_n = g . NavFocusScopePath . Size - 1 ; path_n > = 0 ; path_n - - )
{
const ImGuiFocusScopeData & focus_scope = g . NavFocusScopePath [ path_n ] ;
SameLine ( 0.0f , 0.0f ) ;
Text ( " 0x%08X/ " , focus_scope . ID ) ;
SetItemTooltip ( " In window \" %s \" " , FindWindowByID ( focus_scope . WindowID ) - > Name ) ;
}
Text ( " NavWindowingTarget: '%s' " , g . NavWindowingTarget ? g . NavWindowingTarget - > Name : " NULL " ) ;
Unindent ( ) ;