From 0eae77f783beb2debfad701d5f9c77a0c1b44661 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 7 May 2026 20:51:32 +0200 Subject: [PATCH] Inputs: SetItemKeyOwner(): return true if ownership has been requested, which can to be checked to accurately gate further input test. (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641) --- docs/CHANGELOG.txt | 4 ++++ imgui.cpp | 13 ++++++++----- imgui.h | 5 +++-- imgui_demo.cpp | 6 +++--- imgui_internal.h | 2 +- 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e492452db..e8f4776b7 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -152,6 +152,10 @@ Other Changes: items straying out of columns boundaries. (#7994, #2221) - Box-Select + Tables: fixed an issue when calling `BeginMultiSelect()` in a table before layout has been locked (first row or headers row submitted). (#8250) +- Inputs: + - SetItemKeyOwner(): return true if ownership has been requested, which typically + needs to to checked for gating further tests. This is important as the function + may fail. (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641) - Style: - Fixed vertical scrollbar top coordinates when using thick borders on windows with no title bar and no menu bar. (#9366) diff --git a/imgui.cpp b/imgui.cpp index 1e752cdd2..cd21c2735 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10682,6 +10682,7 @@ bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id) // - SetKeyOwner(..., None) : clears owner // - SetKeyOwner(..., Any, !Lock) : illegal (assert) // - SetKeyOwner(..., Any or None, Lock) : set lock +// Ownership is automatically released on the frame after a release, see code in UpdateKeyboardInputs(). void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; @@ -10708,30 +10709,32 @@ void ImGui::SetKeyOwnersForKeyChord(ImGuiKeyChord key_chord, ImGuiID owner_id, I if (key_chord & ~ImGuiMod_Mask_) { SetKeyOwner((ImGuiKey)(key_chord & ~ImGuiMod_Mask_), owner_id, flags); } } -// This is more or less equivalent to: +// This is more or less equivalent to a fancier version of: // if (IsItemHovered() || IsItemActive()) // SetKeyOwner(key, GetItemID()); // Extensive uses of that (e.g. many calls for a single item) may want to manually perform the tests once and then call SetKeyOwner() multiple times. // More advanced usage scenarios may want to call SetKeyOwner() manually based on different condition. // Worth noting is that only one item can be hovered and only one item can be active, therefore this usage pattern doesn't need to bother with routing and priority. -void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags) +bool ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags) { ImGuiContext& g = *GImGui; ImGuiID id = g.LastItemData.ID; if (id == 0 || (g.HoveredId != id && g.ActiveId != id)) - return; + return false; if ((flags & ImGuiInputFlags_CondMask_) == 0) flags |= ImGuiInputFlags_CondDefault_; if ((g.HoveredId == id && (flags & ImGuiInputFlags_CondHovered)) || (g.ActiveId == id && (flags & ImGuiInputFlags_CondActive))) { IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetItemKeyOwner) == 0); // Passing flags not supported by this function! SetKeyOwner(key, id, flags & ~ImGuiInputFlags_CondMask_); + return true; } + return false; } -void ImGui::SetItemKeyOwner(ImGuiKey key) +bool ImGui::SetItemKeyOwner(ImGuiKey key) { - SetItemKeyOwner(key, ImGuiInputFlags_None); + return SetItemKeyOwner(key, ImGuiInputFlags_None); } // This is the only public API until we expose owner_id versions of the API as replacements. diff --git a/imgui.h b/imgui.h index 376a008d5..68e5a578a 100644 --- a/imgui.h +++ b/imgui.h @@ -1092,10 +1092,11 @@ namespace ImGui // Inputs Utilities: Key/Input Ownership [BETA] // - One common use case would be to allow your items to disable standard inputs behaviors such // as Tab or Alt key handling, Mouse Wheel scrolling, etc. - // e.g. Button(...); SetItemKeyOwner(ImGuiKey_MouseWheelY); to make hovering/activating a button disable wheel for scrolling. + // e.g. `Button(...); if (SetItemKeyOwner(ImGuiKey_MouseWheelY)) { ... }` to make hovering/activating a button disable wheel for scrolling. // - Reminder ImGuiKey enum include access to mouse buttons and gamepad, so key ownership can apply to them. + // - The return value of SetItemKeyOwner() says if ownership has been requested for the item, which is a shortcut to calling yet non-public TestKeyOwner() function. // - Many related features are still in imgui_internal.h. For instance, most IsKeyXXX()/IsMouseXXX() functions have an owner-id-aware version. - IMGUI_API void SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'. + IMGUI_API bool SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Return true when ownership has been set. Roughly equivalent to 'if (TestKeyOwner(key, GetItemID()) && (IsItemHovered() || IsItemActive())) { SetKeyOwner(key, GetItemID());'. // Inputs Utilities: Mouse // - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d43d3495f..39d9e1f07 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -875,9 +875,9 @@ static void ExampleImageViewer_DrawCanvas(ExampleImageViewerData* data, ImVec2 c data->ViewReset = false; // Handle inputs - ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY); // FIXME: Not while scrolling? - if (ImGui::IsItemHovered() && io.MouseWheel != 0.0f) - data->Zoom = IM_CLAMP(data->Zoom * (1.0f + io.MouseWheel * 0.10f), data->ZoomMin, data->ZoomMax); + if (ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY)) // FIXME: Not while scrolling? + if (io.MouseWheel != 0.0f) + data->Zoom = IM_CLAMP(data->Zoom * (1.0f + io.MouseWheel * 0.10f), data->ZoomMin, data->ZoomMax); float zoom = data->Zoom; // (float)(int)ViewZoom; if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) { diff --git a/imgui_internal.h b/imgui_internal.h index 918b6277d..32fea290b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3436,7 +3436,7 @@ namespace ImGui IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key); IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0); IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0); - IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'. + IMGUI_API bool SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags); IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id' inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; }