From 0edad6d097bed1706515faf2ba4762a70fcffec8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 1 Jul 2026 14:42:23 +0200 Subject: [PATCH] Internals: track WasSelected/WasSoleSelected data for ActiveId. (#8337) --- imgui.cpp | 7 +++++++ imgui_internal.h | 5 +++++ imgui_widgets.cpp | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index addbe5e9a..b237f956f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4234,6 +4234,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas) ActiveIdIsAlive = 0; ActiveIdTimer = 0.0f; ActiveIdIsJustActivated = false; + ActiveIdWasSelected = ActiveIdWasSoleSelected = false; ActiveIdAllowOverlap = false; ActiveIdNoClearOnFocusLoss = false; ActiveIdHasBeenPressedBefore = false; @@ -4250,6 +4251,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas) memset(&ActiveIdValueOnActivation, 0, sizeof(ActiveIdValueOnActivation)); LastActiveId = 0; LastActiveIdTimer = 0.0f; + LastActiveIdWasSelected = LastActiveIdWasSoleSelected = false; LastKeyboardKeyPressTime = LastKeyModsChangeTime = LastKeyModsChangeFromNoneTime = -1.0; @@ -5629,6 +5631,11 @@ void ImGui::NewFrame() // Update ActiveId data (clear reference to active widget if the widget isn't alive anymore) if (g.ActiveId) g.ActiveIdTimer += g.IO.DeltaTime; + if (g.ActiveId && g.ActiveId == g.LastActiveId) + { + g.LastActiveIdWasSelected = g.ActiveIdWasSelected; + g.LastActiveIdWasSoleSelected = g.ActiveIdWasSoleSelected; + } g.LastActiveIdTimer += g.IO.DeltaTime; g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdIsAlive = 0; diff --git a/imgui_internal.h b/imgui_internal.h index 7f07a5439..299287e65 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1940,6 +1940,7 @@ struct IMGUI_API ImGuiMultiSelectTempData bool NavIdPassedBy; bool RangeSrcPassedBy; // Set by the item that matches RangeSrcItem. bool RangeDstPassedBy; // Set by the item that matches NavJustMovedToId when IsSetRange is set. + bool IsSoleOrUnknownSelectionSize; ImGuiMultiSelectTempData() { Clear(); } void Clear() { size_t io_sz = sizeof(IO); ClearIO(); memset((void*)(&IO + 1), 0, sizeof(*this) - io_sz); } // Zero-clear except IO as we preserve IO.Requests[] buffer allocation. @@ -2281,6 +2282,8 @@ struct ImGuiContext ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame) float ActiveIdTimer; bool ActiveIdIsJustActivated; // Set at the time of activation for one frame + bool ActiveIdWasSelected; // Active ID was selected at the time of activating + bool ActiveIdWasSoleSelected; // Active ID was sole selection at the time of activating bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) bool ActiveIdNoClearOnFocusLoss; // Disable losing active id if the active id window gets unfocused. bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch. @@ -2297,6 +2300,8 @@ struct ImGuiContext ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX. ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation. float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation. + bool LastActiveIdWasSelected; + bool LastActiveIdWasSoleSelected; // Key/Input Ownership + Shortcut Routing system // - The idea is that instead of "eating" a given key, we can link to an owner. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7b770b433..ace655d4d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7489,6 +7489,11 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (selected != was_selected) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection; + if (g.ActiveId == id && g.ActiveIdIsJustActivated) + { + g.ActiveIdWasSelected = was_selected; + g.ActiveIdWasSoleSelected = was_selected && (!is_multi_select || g.CurrentMultiSelect->IsSoleOrUnknownSelectionSize); + } // Render if (is_visible) @@ -8116,6 +8121,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel storage->LastSelectionSize = 0; } ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1; + ms->IsSoleOrUnknownSelectionSize = (storage->LastSelectionSize == 1) || (storage->LastSelectionSize == -1); //ms->PrevSubmittedItem = ImGuiSelectionUserData_Invalid; if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)