mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-10-26 12:27:30 +00:00 
			
		
		
		
	Internals: maintaining focus order inside windows + only storing root windows in WindowsFocusOrder[] array. (toward #2304)
This commit is contained in:
		
							
								
								
									
										50
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -4034,7 +4034,7 @@ void ImGui::NewFrame() | ||||
|     UpdateTabFocus(); | ||||
|  | ||||
|     // Mark all windows as not visible and compact unused memory. | ||||
|     IM_ASSERT(g.WindowsFocusOrder.Size == g.Windows.Size); | ||||
|     IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size); | ||||
|     const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemoryCompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer; | ||||
|     for (int i = 0; i != g.Windows.Size; i++) | ||||
|     { | ||||
| @@ -5143,7 +5143,12 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImGuiWindowFlags flags) | ||||
|         window->AutoFitOnlyGrows = (window->AutoFitFramesX > 0) || (window->AutoFitFramesY > 0); | ||||
|     } | ||||
|  | ||||
|     g.WindowsFocusOrder.push_back(window); | ||||
|     if (!(flags & ImGuiWindowFlags_ChildWindow)) | ||||
|     { | ||||
|         g.WindowsFocusOrder.push_back(window); | ||||
|         window->FocusOrder = (short)(g.WindowsFocusOrder.Size - 1); | ||||
|     } | ||||
|  | ||||
|     if (flags & ImGuiWindowFlags_NoBringToFrontOnFocus) | ||||
|         g.Windows.push_front(window); // Quite slow but rare and only once | ||||
|     else | ||||
| @@ -6378,15 +6383,22 @@ void ImGui::End() | ||||
| void ImGui::BringWindowToFocusFront(ImGuiWindow* window) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     IM_ASSERT(window == window->RootWindow); | ||||
|  | ||||
|     const int cur_order = window->FocusOrder; | ||||
|     IM_ASSERT(g.WindowsFocusOrder[cur_order] == window); | ||||
|     if (g.WindowsFocusOrder.back() == window) | ||||
|         return; | ||||
|     for (int i = g.WindowsFocusOrder.Size - 2; i >= 0; i--) // We can ignore the top-most window | ||||
|         if (g.WindowsFocusOrder[i] == window) | ||||
|         { | ||||
|             memmove(&g.WindowsFocusOrder[i], &g.WindowsFocusOrder[i + 1], (size_t)(g.WindowsFocusOrder.Size - i - 1) * sizeof(ImGuiWindow*)); | ||||
|             g.WindowsFocusOrder[g.WindowsFocusOrder.Size - 1] = window; | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|     const int new_order = g.WindowsFocusOrder.Size - 1; | ||||
|     for (int n = cur_order; n < new_order; n++) | ||||
|     { | ||||
|         g.WindowsFocusOrder[n] = g.WindowsFocusOrder[n + 1]; | ||||
|         g.WindowsFocusOrder[n]->FocusOrder--; | ||||
|         IM_ASSERT(g.WindowsFocusOrder[n]->FocusOrder == n); | ||||
|     } | ||||
|     g.WindowsFocusOrder[new_order] = window; | ||||
|     window->FocusOrder = (short)new_order; | ||||
| } | ||||
|  | ||||
| void ImGui::BringWindowToDisplayFront(ImGuiWindow* window) | ||||
| @@ -6466,18 +6478,13 @@ void ImGui::FocusTopMostWindowUnderOne(ImGuiWindow* under_this_window, ImGuiWind | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|  | ||||
|     int start_idx = g.WindowsFocusOrder.Size - 1; | ||||
|     if (under_this_window != NULL) | ||||
|     { | ||||
|         int under_this_window_idx = FindWindowFocusIndex(under_this_window); | ||||
|         if (under_this_window_idx != -1) | ||||
|             start_idx = under_this_window_idx - 1; | ||||
|     } | ||||
|     const int start_idx = ((under_this_window != NULL) ? FindWindowFocusIndex(under_this_window) : g.WindowsFocusOrder.Size) - 1; | ||||
|     for (int i = start_idx; i >= 0; i--) | ||||
|     { | ||||
|         // We may later decide to test for different NoXXXInputs based on the active navigation input (mouse vs nav) but that may feel more confusing to the user. | ||||
|         ImGuiWindow* window = g.WindowsFocusOrder[i]; | ||||
|         if (window != ignore_window && window->WasActive && !(window->Flags & ImGuiWindowFlags_ChildWindow)) | ||||
|         IM_ASSERT(window == window->RootWindow); | ||||
|         if (window != ignore_window && window->WasActive) | ||||
|             if ((window->Flags & (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) != (ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs)) | ||||
|             { | ||||
|                 ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(window); | ||||
| @@ -9479,13 +9486,12 @@ static void ImGui::NavEndFrame() | ||||
|     } | ||||
| } | ||||
|  | ||||
| static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) // FIXME-OPT O(N) | ||||
| static int ImGui::FindWindowFocusIndex(ImGuiWindow* window) | ||||
| { | ||||
|     ImGuiContext& g = *GImGui; | ||||
|     for (int i = g.WindowsFocusOrder.Size - 1; i >= 0; i--) | ||||
|         if (g.WindowsFocusOrder[i] == window) | ||||
|             return i; | ||||
|     return -1; | ||||
|     int order = window->FocusOrder; | ||||
|     IM_ASSERT(g.WindowsFocusOrder[order] == window); | ||||
|     return order; | ||||
| } | ||||
|  | ||||
| static ImGuiWindow* FindWindowNavFocusable(int i_start, int i_stop, int dir) // FIXME-OPT O(N) | ||||
|   | ||||
| @@ -1322,7 +1322,7 @@ struct ImGuiContext | ||||
|  | ||||
|     // Windows state | ||||
|     ImVector<ImGuiWindow*>  Windows;                            // Windows, sorted in display order, back to front | ||||
|     ImVector<ImGuiWindow*>  WindowsFocusOrder;                  // Windows, sorted in focus order, back to front. (FIXME: We could only store root windows here! Need to sort out the Docking equivalent which is RootWindowDockStop and is unfortunately a little more dynamic) | ||||
|     ImVector<ImGuiWindow*>  WindowsFocusOrder;                  // Root windows, sorted in focus order, back to front. | ||||
|     ImVector<ImGuiWindow*>  WindowsTempSortBuffer;              // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child | ||||
|     ImVector<ImGuiWindow*>  CurrentWindowStack; | ||||
|     ImGuiStorage            WindowsById;                        // Map window's ImGuiID to ImGuiWindow* | ||||
| @@ -1786,8 +1786,9 @@ struct IMGUI_API ImGuiWindow | ||||
|     bool                    HasCloseButton;                     // Set when the window has a close button (p_open != NULL) | ||||
|     signed char             ResizeBorderHeld;                   // Current border being held for resize (-1: none, otherwise 0-3) | ||||
|     short                   BeginCount;                         // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) | ||||
|     short                   BeginOrderWithinParent;             // Order within immediate parent window, if we are a child window. Otherwise 0. | ||||
|     short                   BeginOrderWithinContext;            // Order within entire imgui context. This is mostly used for debugging submission order related issues. | ||||
|     short                   BeginOrderWithinParent;             // Begin() order within immediate parent window, if we are a child window. Otherwise 0. | ||||
|     short                   BeginOrderWithinContext;            // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues. | ||||
|     short                   FocusOrder;                         // Order within WindowsFocusOrder[], altered when windows are focused. | ||||
|     ImGuiID                 PopupId;                            // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) | ||||
|     ImS8                    AutoFitFramesX, AutoFitFramesY; | ||||
|     ImS8                    AutoFitChildAxises; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 ocornut
					ocornut