mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-11-04 09:44:29 +00:00 
			
		
		
		
	Internals: Added FocusItem(). Made activation explicit/opt-in via ImGuiNavMoveFlags_Activate. Rename ActivateItem() to ActivateItemByID().
This commit is contained in:
		
							
								
								
									
										59
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								imgui.cpp
									
									
									
									
									
								
							@@ -7530,13 +7530,6 @@ void ImGui::SetWindowFontScale(float scale)
 | 
				
			|||||||
    g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
 | 
					    g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ImGui::ActivateItem(ImGuiID id)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    ImGuiContext& g = *GImGui;
 | 
					 | 
				
			||||||
    g.NavNextActivateId = id;
 | 
					 | 
				
			||||||
    g.NavNextActivateFlags = ImGuiActivateFlags_None;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void ImGui::PushFocusScope(ImGuiID id)
 | 
					void ImGui::PushFocusScope(ImGuiID id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ImGuiContext& g = *GImGui;
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
@@ -7552,13 +7545,40 @@ void ImGui::PopFocusScope()
 | 
				
			|||||||
    g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back() : 0;
 | 
					    g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back() : 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Focus = move navigation cursor, set scrolling, set focus window.
 | 
				
			||||||
 | 
					void ImGui::FocusItem()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
 | 
					    ImGuiWindow* window = g.CurrentWindow;
 | 
				
			||||||
 | 
					    IMGUI_DEBUG_LOG_FOCUS("FocusItem(0x%08x) in window \"%s\"\n", g.LastItemData.ID, window->Name);
 | 
				
			||||||
 | 
					    if (g.DragDropActive || g.MovingWindow != NULL) // FIXME: Opt-in flags for this?
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        IMGUI_DEBUG_LOG_FOCUS("FocusItem() ignored while DragDropActive!\n");
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_Tabbing | ImGuiNavMoveFlags_FocusApi; // No activation/selection
 | 
				
			||||||
 | 
					    ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
 | 
				
			||||||
 | 
					    SetNavWindow(window);
 | 
				
			||||||
 | 
					    NavMoveRequestSubmit(ImGuiDir_None, ImGuiDir_Up, move_flags, scroll_flags);
 | 
				
			||||||
 | 
					    NavMoveRequestResolveWithLastItem(&g.NavMoveResultLocal);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ImGui::ActivateItemByID(ImGuiID id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
 | 
					    g.NavNextActivateId = id;
 | 
				
			||||||
 | 
					    g.NavNextActivateFlags = ImGuiActivateFlags_None;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Note: this will likely be called ActivateItem() once we rework our Focus/Activation system!
 | 
					// Note: this will likely be called ActivateItem() once we rework our Focus/Activation system!
 | 
				
			||||||
 | 
					// But ActivateItem() should function without altering scroll/focus?
 | 
				
			||||||
void ImGui::SetKeyboardFocusHere(int offset)
 | 
					void ImGui::SetKeyboardFocusHere(int offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ImGuiContext& g = *GImGui;
 | 
					    ImGuiContext& g = *GImGui;
 | 
				
			||||||
    ImGuiWindow* window = g.CurrentWindow;
 | 
					    ImGuiWindow* window = g.CurrentWindow;
 | 
				
			||||||
    IM_ASSERT(offset >= -1);    // -1 is allowed but not below
 | 
					    IM_ASSERT(offset >= -1);    // -1 is allowed but not below
 | 
				
			||||||
    IMGUI_DEBUG_LOG_ACTIVEID("SetKeyboardFocusHere(%d) in window \"%s\"\n", offset, window->Name);
 | 
					    IMGUI_DEBUG_LOG_FOCUS("SetKeyboardFocusHere(%d) in window \"%s\"\n", offset, window->Name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // It makes sense in the vast majority of cases to never interrupt a drag and drop.
 | 
					    // It makes sense in the vast majority of cases to never interrupt a drag and drop.
 | 
				
			||||||
    // When we refactor this function into ActivateItem() we may want to make this an option.
 | 
					    // When we refactor this function into ActivateItem() we may want to make this an option.
 | 
				
			||||||
@@ -7566,14 +7586,15 @@ void ImGui::SetKeyboardFocusHere(int offset)
 | 
				
			|||||||
    // is also automatically dropped in the event g.ActiveId is stolen.
 | 
					    // is also automatically dropped in the event g.ActiveId is stolen.
 | 
				
			||||||
    if (g.DragDropActive || g.MovingWindow != NULL)
 | 
					    if (g.DragDropActive || g.MovingWindow != NULL)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        IMGUI_DEBUG_LOG_ACTIVEID("SetKeyboardFocusHere() ignored while DragDropActive!\n");
 | 
					        IMGUI_DEBUG_LOG_FOCUS("SetKeyboardFocusHere() ignored while DragDropActive!\n");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SetNavWindow(window);
 | 
					    SetNavWindow(window);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_Tabbing | ImGuiNavMoveFlags_Activate | ImGuiNavMoveFlags_FocusApi;
 | 
				
			||||||
    ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
 | 
					    ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
 | 
				
			||||||
    NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, ImGuiNavMoveFlags_Tabbing | ImGuiNavMoveFlags_FocusApi, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
 | 
					    NavMoveRequestSubmit(ImGuiDir_None, offset < 0 ? ImGuiDir_Up : ImGuiDir_Down, move_flags, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
 | 
				
			||||||
    if (offset == -1)
 | 
					    if (offset == -1)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        NavMoveRequestResolveWithLastItem(&g.NavMoveResultLocal);
 | 
					        NavMoveRequestResolveWithLastItem(&g.NavMoveResultLocal);
 | 
				
			||||||
@@ -11555,9 +11576,10 @@ void ImGui::NavUpdateCreateTabbingRequest()
 | 
				
			|||||||
        g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.NavDisableHighlight == true && g.ActiveId == 0) ? 0 : +1;
 | 
					        g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.NavDisableHighlight == true && g.ActiveId == 0) ? 0 : +1;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.ActiveId == 0) ? 0 : +1;
 | 
					        g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.ActiveId == 0) ? 0 : +1;
 | 
				
			||||||
 | 
					    ImGuiNavMoveFlags move_flags = ImGuiNavMoveFlags_Tabbing | ImGuiNavMoveFlags_Activate;
 | 
				
			||||||
    ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
 | 
					    ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY;
 | 
				
			||||||
    ImGuiDir clip_dir = (g.NavTabbingDir < 0) ? ImGuiDir_Up : ImGuiDir_Down;
 | 
					    ImGuiDir clip_dir = (g.NavTabbingDir < 0) ? ImGuiDir_Up : ImGuiDir_Down;
 | 
				
			||||||
    NavMoveRequestSubmit(ImGuiDir_None, clip_dir, ImGuiNavMoveFlags_Tabbing, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
 | 
					    NavMoveRequestSubmit(ImGuiDir_None, clip_dir, move_flags, scroll_flags); // FIXME-NAV: Once we refactor tabbing, add LegacyApi flag to not activate non-inputable.
 | 
				
			||||||
    g.NavTabbingCounter = -1;
 | 
					    g.NavTabbingCounter = -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11623,7 +11645,7 @@ void ImGui::NavMoveRequestApplyResult()
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    if (g.ActiveId != result->ID)
 | 
					    if (g.ActiveId != result->ID)
 | 
				
			||||||
        ClearActiveID();
 | 
					        ClearActiveID();
 | 
				
			||||||
    if (g.NavId != result->ID)
 | 
					    if (g.NavId != result->ID && (g.NavMoveFlags & ImGuiNavMoveFlags_Activate) != 0)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        // Don't set NavJustMovedToId if just landed on the same spot (which may happen with ImGuiNavMoveFlags_AllowCurrentNavId)
 | 
					        // Don't set NavJustMovedToId if just landed on the same spot (which may happen with ImGuiNavMoveFlags_AllowCurrentNavId)
 | 
				
			||||||
        g.NavJustMovedToId = result->ID;
 | 
					        g.NavJustMovedToId = result->ID;
 | 
				
			||||||
@@ -11644,19 +11666,18 @@ void ImGui::NavMoveRequestApplyResult()
 | 
				
			|||||||
        g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer] = preferred_scoring_pos_rel;
 | 
					        g.NavWindow->RootWindowForNav->NavPreferredScoringPosRel[g.NavLayer] = preferred_scoring_pos_rel;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Tabbing: Activates Inputable or Focus non-Inputable
 | 
					    // Tabbing: Activates Inputable, otherwise only Focus
 | 
				
			||||||
    if ((g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) && (result->InFlags & ImGuiItemFlags_Inputable))
 | 
					    if ((g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing) && (result->InFlags & ImGuiItemFlags_Inputable) == 0)
 | 
				
			||||||
    {
 | 
					        g.NavMoveFlags &= ~ImGuiNavMoveFlags_Activate;
 | 
				
			||||||
        g.NavNextActivateId = result->ID;
 | 
					 | 
				
			||||||
        g.NavNextActivateFlags = ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState;
 | 
					 | 
				
			||||||
        g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Activate
 | 
					    // Activate
 | 
				
			||||||
    if (g.NavMoveFlags & ImGuiNavMoveFlags_Activate)
 | 
					    if (g.NavMoveFlags & ImGuiNavMoveFlags_Activate)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        g.NavNextActivateId = result->ID;
 | 
					        g.NavNextActivateId = result->ID;
 | 
				
			||||||
        g.NavNextActivateFlags = ImGuiActivateFlags_None;
 | 
					        g.NavNextActivateFlags = ImGuiActivateFlags_None;
 | 
				
			||||||
 | 
					        g.NavMoveFlags |= ImGuiNavMoveFlags_DontSetNavHighlight;
 | 
				
			||||||
 | 
					        if (g.NavMoveFlags & ImGuiNavMoveFlags_Tabbing)
 | 
				
			||||||
 | 
					            g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Enable nav highlight
 | 
					    // Enable nav highlight
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1479,9 +1479,9 @@ enum ImGuiNavMoveFlags_
 | 
				
			|||||||
    ImGuiNavMoveFlags_ScrollToEdgeY         = 1 << 6,   // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary
 | 
					    ImGuiNavMoveFlags_ScrollToEdgeY         = 1 << 6,   // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary
 | 
				
			||||||
    ImGuiNavMoveFlags_Forwarded             = 1 << 7,
 | 
					    ImGuiNavMoveFlags_Forwarded             = 1 << 7,
 | 
				
			||||||
    ImGuiNavMoveFlags_DebugNoResult         = 1 << 8,   // Dummy scoring for debug purpose, don't apply result
 | 
					    ImGuiNavMoveFlags_DebugNoResult         = 1 << 8,   // Dummy scoring for debug purpose, don't apply result
 | 
				
			||||||
    ImGuiNavMoveFlags_FocusApi              = 1 << 9,
 | 
					    ImGuiNavMoveFlags_FocusApi              = 1 << 9,   // Requests from focus API can land/focus/activate items even if they are marked with _NoTabStop (see NavProcessItemForTabbingRequest() for details)
 | 
				
			||||||
    ImGuiNavMoveFlags_Tabbing               = 1 << 10,  // == Focus + Activate if item is Inputable + DontChangeNavHighlight
 | 
					    ImGuiNavMoveFlags_Tabbing               = 1 << 10,  // == Focus + Activate if item is Inputable + DontChangeNavHighlight
 | 
				
			||||||
    ImGuiNavMoveFlags_Activate              = 1 << 11,
 | 
					    ImGuiNavMoveFlags_Activate              = 1 << 11,  // Activate/select target item.
 | 
				
			||||||
    ImGuiNavMoveFlags_DontSetNavHighlight   = 1 << 12,  // Do not alter the visible state of keyboard vs mouse nav highlight
 | 
					    ImGuiNavMoveFlags_DontSetNavHighlight   = 1 << 12,  // Do not alter the visible state of keyboard vs mouse nav highlight
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2912,10 +2912,15 @@ namespace ImGui
 | 
				
			|||||||
    IMGUI_API void          NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
 | 
					    IMGUI_API void          NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
 | 
				
			||||||
    IMGUI_API void          NavClearPreferredPosForAxis(ImGuiAxis axis);
 | 
					    IMGUI_API void          NavClearPreferredPosForAxis(ImGuiAxis axis);
 | 
				
			||||||
    IMGUI_API void          NavUpdateCurrentWindowIsScrollPushableX();
 | 
					    IMGUI_API void          NavUpdateCurrentWindowIsScrollPushableX();
 | 
				
			||||||
    IMGUI_API void          ActivateItem(ImGuiID id);   // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again.
 | 
					 | 
				
			||||||
    IMGUI_API void          SetNavWindow(ImGuiWindow* window);
 | 
					    IMGUI_API void          SetNavWindow(ImGuiWindow* window);
 | 
				
			||||||
    IMGUI_API void          SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
 | 
					    IMGUI_API void          SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Focus/Activation
 | 
				
			||||||
 | 
					    // This should be part of a larger set of API: FocusItem(offset = -1), FocusItemByID(id), ActivateItem(offset = -1), ActivateItemByID(id) etc. which are
 | 
				
			||||||
 | 
					    // much harder to design and implement than expected. I have a couple of private branches on this matter but it's not simple. For now implementing the easy ones.
 | 
				
			||||||
 | 
					    IMGUI_API void          FocusItem();                    // Focus last item (no selection/activation).
 | 
				
			||||||
 | 
					    IMGUI_API void          ActivateItemByID(ImGuiID id);   // Activate an item by ID (button, checkbox, tree node etc.). Activation is queued and processed on the next frame when the item is encountered again.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Inputs
 | 
					    // Inputs
 | 
				
			||||||
    // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
 | 
					    // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
 | 
				
			||||||
    inline bool             IsNamedKey(ImGuiKey key)                                    { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; }
 | 
					    inline bool             IsNamedKey(ImGuiKey key)                                    { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user