@ -3449,17 +3449,22 @@ void ImGui::UpdateMouseMovingWindowEndFrame()
if ( g . NavWindow & & g . NavWindow - > Appearing )
if ( g . NavWindow & & g . NavWindow - > Appearing )
return ;
return ;
// Click to focus window and start moving (after we're done with all our widgets)
// Click on empty space to focus window and start moving (after we're done with all our widgets)
if ( g . IO . MouseClicked [ 0 ] )
if ( g . IO . MouseClicked [ 0 ] )
{
{
if ( g . HoveredRootWindow ! = NULL )
// Handle the edge case of a popup being closed while clicking in its empty space.
// If we try to focus it, FocusWindow() > ClosePopupsOverWindow() will accidentally close any parent popups because they are not linked together any more.
ImGuiWindow * root_window = g . HoveredRootWindow ;
const bool is_closed_popup = root_window & & ( root_window - > Flags & ImGuiWindowFlags_Popup ) & & ! IsPopupOpenAtAnyLevel ( root_window - > PopupId ) ;
if ( root_window ! = NULL & & ! is_closed_popup )
{
{
StartMouseMovingWindow ( g . HoveredWindow ) ;
StartMouseMovingWindow ( g . HoveredWindow ) ;
if ( g . IO . ConfigWindowsMoveFromTitleBarOnly & & ! ( g . HoveredRootWindow - > Flags & ImGuiWindowFlags_NoTitleBar ) )
if ( g . IO . ConfigWindowsMoveFromTitleBarOnly & & ! ( root_w indow- > Flags & ImGuiWindowFlags_NoTitleBar ) )
if ( ! g . HoveredRootWindow - > TitleBarRect ( ) . Contains ( g . IO . MouseClickedPos [ 0 ] ) )
if ( ! root_w indow- > TitleBarRect ( ) . Contains ( g . IO . MouseClickedPos [ 0 ] ) )
g . MovingWindow = NULL ;
g . MovingWindow = NULL ;
}
}
else if ( g . NavWindow ! = NULL & & GetTopMostPopupModal ( ) = = NULL )
else if ( root_window ! = NULL & & g . NavWindow ! = NULL & & GetTopMostPopupModal ( ) = = NULL )
{
{
// Clicking on void disable focus
// Clicking on void disable focus
FocusWindow ( NULL ) ;
FocusWindow ( NULL ) ;
@ -3700,7 +3705,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
for ( int i = 0 ; i < IM_ARRAYSIZE ( g . IO . MouseDown ) ; i + + )
for ( int i = 0 ; i < IM_ARRAYSIZE ( g . IO . MouseDown ) ; i + + )
{
{
if ( g . IO . MouseClicked [ i ] )
if ( g . IO . MouseClicked [ i ] )
g . IO . MouseDownOwned [ i ] = ( g . HoveredWindow ! = NULL ) | | ( ! g . OpenPopupStack . empty ( ) ) ;
g . IO . MouseDownOwned [ i ] = ( g . HoveredWindow ! = NULL ) | | ( g . OpenPopupStack . Size > 0 ) ;
mouse_any_down | = g . IO . MouseDown [ i ] ;
mouse_any_down | = g . IO . MouseDown [ i ] ;
if ( g . IO . MouseDown [ i ] )
if ( g . IO . MouseDown [ i ] )
if ( mouse_earliest_button_down = = - 1 | | g . IO . MouseClickedTime [ i ] < g . IO . MouseClickedTime [ mouse_earliest_button_down ] )
if ( mouse_earliest_button_down = = - 1 | | g . IO . MouseClickedTime [ i ] < g . IO . MouseClickedTime [ mouse_earliest_button_down ] )
@ -3718,7 +3723,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
if ( g . WantCaptureMouseNextFrame ! = - 1 )
if ( g . WantCaptureMouseNextFrame ! = - 1 )
g . IO . WantCaptureMouse = ( g . WantCaptureMouseNextFrame ! = 0 ) ;
g . IO . WantCaptureMouse = ( g . WantCaptureMouseNextFrame ! = 0 ) ;
else
else
g . IO . WantCaptureMouse = ( mouse_avail_to_imgui & & ( g . HoveredWindow ! = NULL | | mouse_any_down ) ) | | ( ! g . OpenPopupStack . empty ( ) ) ;
g . IO . WantCaptureMouse = ( mouse_avail_to_imgui & & ( g . HoveredWindow ! = NULL | | mouse_any_down ) ) | | ( g . OpenPopupStack . Size > 0 ) ;
// Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to Dear ImGui + app)
// Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to Dear ImGui + app)
if ( g . WantCaptureKeyboardNextFrame ! = - 1 )
if ( g . WantCaptureKeyboardNextFrame ! = - 1 )
@ -7610,6 +7615,15 @@ bool ImGui::IsPopupOpen(const char* str_id)
return g . OpenPopupStack . Size > g . BeginPopupStack . Size & & g . OpenPopupStack [ g . BeginPopupStack . Size ] . PopupId = = g . CurrentWindow - > GetID ( str_id ) ;
return g . OpenPopupStack . Size > g . BeginPopupStack . Size & & g . OpenPopupStack [ g . BeginPopupStack . Size ] . PopupId = = g . CurrentWindow - > GetID ( str_id ) ;
}
}
bool ImGui : : IsPopupOpenAtAnyLevel ( ImGuiID id )
{
ImGuiContext & g = * GImGui ;
for ( int n = 0 ; n < g . OpenPopupStack . Size ; n + + )
if ( g . OpenPopupStack [ n ] . PopupId = = id )
return true ;
return false ;
}
ImGuiWindow * ImGui : : GetTopMostPopupModal ( )
ImGuiWindow * ImGui : : GetTopMostPopupModal ( )
{
{
ImGuiContext & g = * GImGui ;
ImGuiContext & g = * GImGui ;
@ -7661,8 +7675,8 @@ void ImGui::OpenPopupEx(ImGuiID id)
else
else
{
{
// Close child popups if any, then flag popup for open/reopen
// Close child popups if any, then flag popup for open/reopen
g . OpenPopupStack . resize ( current_stack_size + 1 ) ;
ClosePopupToLevel ( current_stack_size , false ) ;
g . OpenPopupStack [ current_stack_size ] = popup_ref ;
g . OpenPopupStack . push_back ( popup_ref ) ;
}
}
// When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow().
// When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow().
@ -7675,7 +7689,7 @@ void ImGui::OpenPopupEx(ImGuiID id)
void ImGui : : ClosePopupsOverWindow ( ImGuiWindow * ref_window , bool restore_focus_to_window_under_popup )
void ImGui : : ClosePopupsOverWindow ( ImGuiWindow * ref_window , bool restore_focus_to_window_under_popup )
{
{
ImGuiContext & g = * GImGui ;
ImGuiContext & g = * GImGui ;
if ( g . OpenPopupStack . empty ( ) )
if ( g . OpenPopupStack . Size = = 0 )
return ;
return ;
// When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
// When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it.
@ -7714,6 +7728,8 @@ void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_
{
{
ImGuiContext & g = * GImGui ;
ImGuiContext & g = * GImGui ;
IM_ASSERT ( remaining > = 0 & & remaining < g . OpenPopupStack . Size ) ;
IM_ASSERT ( remaining > = 0 & & remaining < g . OpenPopupStack . Size ) ;
// Trim open popup stack
ImGuiWindow * focus_window = g . OpenPopupStack [ remaining ] . SourceWindow ;
ImGuiWindow * focus_window = g . OpenPopupStack [ remaining ] . SourceWindow ;
ImGuiWindow * popup_window = g . OpenPopupStack [ remaining ] . Window ;
ImGuiWindow * popup_window = g . OpenPopupStack [ remaining ] . Window ;
g . OpenPopupStack . resize ( remaining ) ;
g . OpenPopupStack . resize ( remaining ) ;