From 83cee9e091c38b9e5ce37eb09540319581d417ec Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 16 Nov 2022 15:55:10 +0100 Subject: [PATCH] InputText: replaced some uses of SetKeyOwner() + IsKeyPressed() with Shortcut() Which makes it easier to hook/disable those keys from outside if needed. --- imgui.cpp | 8 ++++---- imgui.h | 2 +- imgui_internal.h | 4 ++-- imgui_widgets.cpp | 27 ++++++++++++--------------- 4 files changed, 19 insertions(+), 22 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 190fd0511..9ce5a2880 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8035,13 +8035,13 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord) return routing_data; } - // Add - ImGuiKeyRoutingIndex idx = (ImGuiKeyRoutingIndex)rt->Entries.Size; + // Add to linked-list + ImGuiKeyRoutingIndex routing_data_idx = (ImGuiKeyRoutingIndex)rt->Entries.Size; rt->Entries.push_back(ImGuiKeyRoutingData()); - routing_data = &rt->Entries[idx]; + routing_data = &rt->Entries[routing_data_idx]; routing_data->Mods = (ImU16)mods; routing_data->NextEntryIndex = rt->Index[key - ImGuiKey_NamedKey_BEGIN]; // Setup linked list - rt->Index[key - ImGuiKey_NamedKey_BEGIN] = idx; + rt->Index[key - ImGuiKey_NamedKey_BEGIN] = routing_data_idx; return routing_data; } diff --git a/imgui.h b/imgui.h index 3cf1d20c6..273de146d 100644 --- a/imgui.h +++ b/imgui.h @@ -23,7 +23,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM > 12345') #define IMGUI_VERSION "1.89" -#define IMGUI_VERSION_NUM 18900 +#define IMGUI_VERSION_NUM 18901 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 62727c5b0..4c25c45ff 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1283,8 +1283,8 @@ typedef ImS16 ImGuiKeyRoutingIndex; struct ImGuiKeyRoutingData { ImGuiKeyRoutingIndex NextEntryIndex; - ImU16 Mods; - ImU8 RoutingNextScore; // Lower is better (0: perfect score) + ImU16 Mods; // Technically we'd only need 4 bits but for simplify we store ImGuiMod_ values which need 16 bits. + ImU8 RoutingNextScore; // Lower is better (0: perfect score) ImGuiID RoutingCurr; ImGuiID RoutingNext; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 953de9a7a..93e655745 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4099,14 +4099,12 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } if (g.ActiveId == id) { - // Declare our inputs + // Declare some inputs, the other are registered and polled via Shortcut() routing system. if (user_clicked) SetKeyOwner(ImGuiKey_MouseLeft, id); g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); if (is_multiline || (flags & ImGuiInputTextFlags_CallbackHistory)) g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); - SetKeyOwner(ImGuiKey_Escape, id); - SetKeyOwner(ImGuiKey_NavGamepadCancel, id); SetKeyOwner(ImGuiKey_Home, id); SetKeyOwner(ImGuiKey_End, id); if (is_multiline) @@ -4115,9 +4113,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ SetKeyOwner(ImGuiKey_PageDown, id); } if (flags & (ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_AllowTabInput)) // Disable keyboard tabbing out as we will use the \t character. - { SetKeyOwner(ImGuiKey_Tab, id); - } } // We have an edge case if ActiveId was set through another widget (e.g. widget being swapped), clear id immediately (don't wait until the end of the function) @@ -4290,22 +4286,23 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const bool is_wordmove_key_down = is_osx ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl const bool is_startend_key_down = is_osx && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End - // Using Shortcut() with ImGuiInputFlags_RouteFocused flag to allow routing operations for other code (e.g. calling window trying to use CTRL+A and CTRL+B: formet would be handled by InputText) + // Using Shortcut() with ImGuiInputFlags_RouteFocused (default policy) to allow routing operations for other code (e.g. calling window trying to use CTRL+A and CTRL+B: formet would be handled by InputText) // Otherwise we could simply assume that we own the keys as we are active. - const ImGuiInputFlags shortcut_flags = ImGuiInputFlags_RouteFocused | ImGuiInputFlags_Repeat; - const bool is_cut = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_X, id, shortcut_flags) || Shortcut(ImGuiMod_Shift | ImGuiKey_Delete, id, shortcut_flags)) && !is_readonly && !is_password && (!is_multiline || state->HasSelection()); - const bool is_copy = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_C, id, shortcut_flags & ~ImGuiInputFlags_Repeat) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_Insert, id, shortcut_flags & ~ImGuiInputFlags_Repeat)) && !is_password && (!is_multiline || state->HasSelection()); - const bool is_paste = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_V, id, shortcut_flags) || Shortcut(ImGuiMod_Shift | ImGuiKey_Insert, id, shortcut_flags)) && !is_readonly; - const bool is_undo = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_Z, id, shortcut_flags)) && !is_readonly && is_undoable; - const bool is_redo = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_Y, id, shortcut_flags) || (is_osx && Shortcut(ImGuiMod_Shortcut | ImGuiMod_Shift | ImGuiKey_Z, id, shortcut_flags))) && !is_readonly && is_undoable; - const bool is_select_all = Shortcut(ImGuiMod_Shortcut | ImGuiKey_A, id, shortcut_flags & ~ImGuiInputFlags_Repeat); + const ImGuiInputFlags f_repeat = ImGuiInputFlags_Repeat; + const bool is_cut = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_X, id, f_repeat) || Shortcut(ImGuiMod_Shift | ImGuiKey_Delete, id, f_repeat)) && !is_readonly && !is_password && (!is_multiline || state->HasSelection()); + const bool is_copy = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_C, id) || Shortcut(ImGuiMod_Ctrl | ImGuiKey_Insert, id)) && !is_password && (!is_multiline || state->HasSelection()); + const bool is_paste = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_V, id, f_repeat) || Shortcut(ImGuiMod_Shift | ImGuiKey_Insert, id, f_repeat)) && !is_readonly; + const bool is_undo = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_Z, id, f_repeat)) && !is_readonly && is_undoable; + const bool is_redo = (Shortcut(ImGuiMod_Shortcut | ImGuiKey_Y, id, f_repeat) || (is_osx && Shortcut(ImGuiMod_Shortcut | ImGuiMod_Shift | ImGuiKey_Z, id, f_repeat))) && !is_readonly && is_undoable; + const bool is_select_all = Shortcut(ImGuiMod_Shortcut | ImGuiKey_A, id); // We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful. const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; const bool is_enter_pressed = IsKeyPressed(ImGuiKey_Enter, true) || IsKeyPressed(ImGuiKey_KeypadEnter, true); const bool is_gamepad_validate = nav_gamepad_active && (IsKeyPressed(ImGuiKey_NavGamepadActivate, false) || IsKeyPressed(ImGuiKey_NavGamepadInput, false)); - const bool is_cancel = Shortcut(ImGuiKey_Escape, id, shortcut_flags) || (nav_gamepad_active && IsKeyPressed(ImGuiKey_NavGamepadCancel, false)); + const bool is_cancel = Shortcut(ImGuiKey_Escape, id, f_repeat) || (nav_gamepad_active && Shortcut(ImGuiKey_NavGamepadCancel, id, f_repeat)); + // FIXME: Should use more Shortcut() and reduce IsKeyPressed()+SetKeyOwner(), but requires modifiers combination to be taken account of. if (IsKeyPressed(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } else if (IsKeyPressed(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } else if (IsKeyPressed(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } @@ -6326,7 +6323,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries ImGuiButtonFlags button_flags = 0; if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; } - if (flags & ImGuiSelectableFlags_NoSetKeyOwner) { button_flags |= ImGuiButtonFlags_NoSetKeyOwner; } + if (flags & ImGuiSelectableFlags_NoSetKeyOwner) { button_flags |= ImGuiButtonFlags_NoSetKeyOwner; } if (flags & ImGuiSelectableFlags_SelectOnClick) { button_flags |= ImGuiButtonFlags_PressedOnClick; } if (flags & ImGuiSelectableFlags_SelectOnRelease) { button_flags |= ImGuiButtonFlags_PressedOnRelease; } if (flags & ImGuiSelectableFlags_AllowDoubleClick) { button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; }