@ -948,6 +948,7 @@ static void RenderWindowDecorations(ImGuiWindow* window, const ImRec
static void RenderWindowTitleBarContents ( ImGuiWindow * window , const ImRect & title_bar_rect , const char * name , bool * p_open ) ;
static void RenderWindowTitleBarContents ( ImGuiWindow * window , const ImRect & title_bar_rect , const char * name , bool * p_open ) ;
static void RenderDimmedBackgroundBehindWindow ( ImGuiWindow * window , ImU32 col ) ;
static void RenderDimmedBackgroundBehindWindow ( ImGuiWindow * window , ImU32 col ) ;
static void RenderDimmedBackgrounds ( ) ;
static void RenderDimmedBackgrounds ( ) ;
static ImGuiWindow * FindBlockingModal ( ImGuiWindow * window ) ;
// Viewports
// Viewports
static void UpdateViewportsNewFrame ( ) ;
static void UpdateViewportsNewFrame ( ) ;
@ -3910,7 +3911,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
// Modal windows prevents mouse from hovering behind them.
// Modal windows prevents mouse from hovering behind them.
ImGuiWindow * modal_window = GetTopMostPopupModal ( ) ;
ImGuiWindow * modal_window = GetTopMostPopupModal ( ) ;
if ( modal_window & & g . HoveredWindow & & ! IsWindow Child Of( g . HoveredWindow - > RootWindow , modal_window , true ) )
if ( modal_window & & g . HoveredWindow & & ! IsWindow WithinBeginStack Of( g . HoveredWindow - > RootWindow , modal_window ) )
clear_hovered_windows = true ;
clear_hovered_windows = true ;
// Disabled mouse?
// Disabled mouse?
@ -4466,6 +4467,23 @@ static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32
}
}
}
}
ImGuiWindow * ImGui : : FindBottomMostVisibleWindowWithinBeginStack ( ImGuiWindow * parent_window )
{
ImGuiContext & g = * GImGui ;
ImGuiWindow * bottom_most_visible_window = parent_window ;
for ( int i = FindWindowDisplayIndex ( parent_window ) ; i > = 0 ; i - - )
{
ImGuiWindow * window = g . Windows [ i ] ;
if ( window - > Flags & ImGuiWindowFlags_ChildWindow )
continue ;
if ( ! IsWindowWithinBeginStackOf ( window , parent_window ) )
break ;
if ( IsWindowActiveAndVisible ( window ) )
bottom_most_visible_window = window ;
}
return bottom_most_visible_window ;
}
static void ImGui : : RenderDimmedBackgrounds ( )
static void ImGui : : RenderDimmedBackgrounds ( )
{
{
ImGuiContext & g = * GImGui ;
ImGuiContext & g = * GImGui ;
@ -4477,8 +4495,9 @@ static void ImGui::RenderDimmedBackgrounds()
if ( dim_bg_for_modal )
if ( dim_bg_for_modal )
{
{
// Draw dimming behind modal
// Draw dimming behind modal or a begin stack child, whichever comes first in draw order.
RenderDimmedBackgroundBehindWindow ( modal_window , GetColorU32 ( ImGuiCol_ModalWindowDimBg , g . DimBgRatio ) ) ;
ImGuiWindow * dim_behind_window = FindBottomMostVisibleWindowWithinBeginStack ( modal_window ) ;
RenderDimmedBackgroundBehindWindow ( dim_behind_window , GetColorU32 ( ImGuiCol_ModalWindowDimBg , g . DimBgRatio ) ) ;
}
}
else if ( dim_bg_for_window_list )
else if ( dim_bg_for_window_list )
{
{
@ -5859,6 +5878,36 @@ void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags
}
}
}
}
// 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.
// - Window // FindBlockingModal() returns Modal1
// - Window // .. returns Modal1
// - Modal1 // .. returns Modal2
// - Window // .. returns Modal2
// - Window // .. returns Modal2
// - Modal2 // .. returns Modal2
static 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 ( int i = g . OpenPopupStack . Size - 1 ; i > = 0 ; i - - )
{
ImGuiWindow * popup_window = g . OpenPopupStack . Data [ i ] . Window ;
if ( popup_window = = NULL | | ! popup_window - > WasActive | | ! ( popup_window - > Flags & ImGuiWindowFlags_Modal ) ) // Check WasActive, because this code may run before popup renders on current frame.
continue ;
if ( IsWindowWithinBeginStackOf ( window , popup_window ) ) // Window is rendered over last modal, no render order change needed.
break ;
for ( ImGuiWindow * parent = popup_window - > ParentWindowInBeginStack - > RootWindow ; parent ! = NULL ; parent = parent - > ParentWindowInBeginStack - > RootWindow )
if ( IsWindowWithinBeginStackOf ( window , parent ) )
return popup_window ; // Place window above its begin stack parent.
}
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.
@ -6204,6 +6253,22 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
want_focus = true ;
want_focus = true ;
else if ( ( flags & ( ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip ) ) = = 0 )
else if ( ( flags & ( ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip ) ) = = 0 )
want_focus = true ;
want_focus = true ;
ImGuiWindow * modal = GetTopMostPopupModal ( ) ;
if ( modal ! = NULL & & ! IsWindowWithinBeginStackOf ( window , modal ) )
{
// Avoid focusing a window that is created outside of active modal. This will prevent active modal from being closed.
// Since window is not focused it would reappear at the same display position like the last time it was visible.
// In case of completely new windows it would go to the top (over current modal), but input to such window would still be blocked by modal.
// Position window behind a modal that is not a begin-parent of this window.
want_focus = false ;
if ( window = = window - > RootWindow )
{
ImGuiWindow * blocking_modal = FindBlockingModal ( window ) ;
IM_ASSERT ( blocking_modal ! = NULL ) ;
BringWindowToDisplayBehind ( window , blocking_modal ) ;
}
}
}
}
// Handle manual resize: Resize Grips, Borders, Gamepad
// Handle manual resize: Resize Grips, Borders, Gamepad
@ -6581,6 +6646,34 @@ void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
}
}
}
}
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)
// Moving window to front of display and set focus (which happens to be back of our sorted list)
void ImGui : : FocusWindow ( ImGuiWindow * window )
void ImGui : : FocusWindow ( ImGuiWindow * window )
{
{
@ -6810,6 +6903,19 @@ bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent,
return false ;
return false ;
}
}
bool ImGui : : IsWindowWithinBeginStackOf ( ImGuiWindow * window , ImGuiWindow * potential_parent )
{
if ( window - > RootWindow = = potential_parent )
return true ;
while ( window ! = NULL )
{
if ( window = = potential_parent )
return true ;
window = window - > ParentWindowInBeginStack ;
}
return false ;
}
bool ImGui : : IsWindowAbove ( ImGuiWindow * potential_above , ImGuiWindow * potential_below )
bool ImGui : : IsWindowAbove ( ImGuiWindow * potential_above , ImGuiWindow * potential_below )
{
{
ImGuiContext & g = * GImGui ;
ImGuiContext & g = * GImGui ;
@ -8492,7 +8598,7 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
bool ref_window_is_descendent_of_popup = false ;
bool ref_window_is_descendent_of_popup = false ;
for ( int n = popup_count_to_keep ; n < g . OpenPopupStack . Size ; n + + )
for ( int n = popup_count_to_keep ; n < g . OpenPopupStack . Size ; n + + )
if ( ImGuiWindow * popup_window = g . OpenPopupStack [ n ] . Window )
if ( ImGuiWindow * popup_window = g . OpenPopupStack [ n ] . Window )
if ( popup_window- > RootWindow = = ref_window - > RootWindow )
if ( IsWindowWithinBeginStackOf( ref_window , popup_window ) )
{
{
ref_window_is_descendent_of_popup = true ;
ref_window_is_descendent_of_popup = true ;
break ;
break ;