mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 13:11:05 +01:00 
			
		
		
		
	Popups: Fix popups being closed by newly appearing windows. (#4317)
* Popups/modals now remain open when new windows are created from within popup/modal begin stack. * Modals are not closed when new window appears behind active modal. Tested by "window_popup_interruptions"
This commit is contained in:
		| @@ -45,6 +45,10 @@ Other Changes: | |||||||
|   (so IsMouseDoubleClicked(ImGuiMouseButton_Left) is same as GetMouseClickedCount(ImGuiMouseButton_Left) == 2, |   (so IsMouseDoubleClicked(ImGuiMouseButton_Left) is same as GetMouseClickedCount(ImGuiMouseButton_Left) == 2, | ||||||
|   but it allows testing for triple clicks and more). |   but it allows testing for triple clicks and more). | ||||||
| - Modals: fixed issue hovering popups inside a child inside a modal. (#4676, #4527) | - Modals: fixed issue hovering popups inside a child inside a modal. (#4676, #4527) | ||||||
|  | - Modals, Popups, Windows: changes how appearing windows are interrupting popups and modals. (#4317) [@rokups] | ||||||
|  |   - appearing windows created from within the begin stack of a popup/modal will no longer close it. | ||||||
|  |   - appearing windows created not within the begin stack of a modal will no longer close the modal, | ||||||
|  |     and automatically appear behind it. | ||||||
| - Fixed IsWindowFocused()/IsWindowHovered() issues with childs inside popups. (#4676) | - Fixed IsWindowFocused()/IsWindowHovered() issues with childs inside popups. (#4676) | ||||||
| - Nav: Ctrl+tabbing to cycle through windows is now enabled regardless of using the _NavEnableKeyboard | - Nav: Ctrl+tabbing to cycle through windows is now enabled regardless of using the _NavEnableKeyboard | ||||||
|   configuration flag. This is part of an effort to generalize the use of keyboard inputs. (#4023, #787). |   configuration flag. This is part of an effort to generalize the use of keyboard inputs. (#4023, #787). | ||||||
|   | |||||||
							
								
								
									
										114
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -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 && !IsWindowChildOf(g.HoveredWindow->RootWindow, modal_window, true)) |     if (modal_window && g.HoveredWindow && !IsWindowWithinBeginStackOf(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; | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								imgui.h
									
									
									
									
									
								
							| @@ -64,7 +64,7 @@ Index of this file: | |||||||
| // Version | // Version | ||||||
| // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) | // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) | ||||||
| #define IMGUI_VERSION               "1.86 WIP" | #define IMGUI_VERSION               "1.86 WIP" | ||||||
| #define IMGUI_VERSION_NUM           18516 | #define IMGUI_VERSION_NUM           18517 | ||||||
| #define IMGUI_CHECKVERSION()        ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) | #define IMGUI_CHECKVERSION()        ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) | ||||||
| #define IMGUI_HAS_TABLE | #define IMGUI_HAS_TABLE | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2418,6 +2418,7 @@ namespace ImGui | |||||||
|     IMGUI_API void          UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); |     IMGUI_API void          UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); | ||||||
|     IMGUI_API ImVec2        CalcWindowNextAutoFitSize(ImGuiWindow* window); |     IMGUI_API ImVec2        CalcWindowNextAutoFitSize(ImGuiWindow* window); | ||||||
|     IMGUI_API bool          IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy); |     IMGUI_API bool          IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy); | ||||||
|  |     IMGUI_API bool          IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent); | ||||||
|     IMGUI_API bool          IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below); |     IMGUI_API bool          IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below); | ||||||
|     IMGUI_API bool          IsWindowNavFocusable(ImGuiWindow* window); |     IMGUI_API bool          IsWindowNavFocusable(ImGuiWindow* window); | ||||||
|     IMGUI_API void          SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); |     IMGUI_API void          SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0); | ||||||
| @@ -2433,6 +2434,9 @@ namespace ImGui | |||||||
|     IMGUI_API void          BringWindowToFocusFront(ImGuiWindow* window); |     IMGUI_API void          BringWindowToFocusFront(ImGuiWindow* window); | ||||||
|     IMGUI_API void          BringWindowToDisplayFront(ImGuiWindow* window); |     IMGUI_API void          BringWindowToDisplayFront(ImGuiWindow* window); | ||||||
|     IMGUI_API void          BringWindowToDisplayBack(ImGuiWindow* window); |     IMGUI_API void          BringWindowToDisplayBack(ImGuiWindow* window); | ||||||
|  |     IMGUI_API void          BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* above_window); | ||||||
|  |     IMGUI_API int           FindWindowDisplayIndex(ImGuiWindow* window); | ||||||
|  |     IMGUI_API ImGuiWindow*  FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* window); | ||||||
|  |  | ||||||
|     // Fonts, drawing |     // Fonts, drawing | ||||||
|     IMGUI_API void          SetCurrentFont(ImFont* font); |     IMGUI_API void          SetCurrentFont(ImFont* font); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user