imgui
imgui copied to clipboard
InputText: Implement double/triple-click + drag word/line selection
Select word/line on double/triple click was already implemented but
holding down the last click and dragging the mouse to incrementally
select was not.
To do this, `ImGuiInputTextState` keeps track of the current selection
mode (based on the number of mouse clicks) and the originating cursor
position over which the clicks happened. Later, on mouse moves, the
appropriate selection for mouse position and origin gets constructed.
Logic based on https://github.com/rxi/lite/commit/53d555b362f10044b473d452220d85c943f3dfd2.
Before:
https://github.com/user-attachments/assets/fe373069-676c-4feb-996c-b56a796d0cef
After:
https://github.com/user-attachments/assets/219b3e72-4969-4ee3-b363-d100750fd3c6
Some issues in double click selection:
Even if the cursor is already at a word boundary double-click will jump left. This patch fixes it. But I don't know why selection gets checked here. In my testing, the selection is never there and this assertion never fails.
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index ad1c1ea9a..282a35ae3 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -4638,7 +4638,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant:
// FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS)
const bool is_bol = (state->Stb->cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb->cursor - 1) == '\n';
- if (STB_TEXT_HAS_SELECTION(state->Stb) || !is_bol)
+ const bool move_left = !ImStb::is_word_boundary_from_right(state, state->Stb->cursor);
+ IM_ASSERT(!STB_TEXT_HAS_SELECTION(state->Stb));
+ if (move_left && (STB_TEXT_HAS_SELECTION(state->Stb) || !is_bol))
state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
//state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
if (!STB_TEXT_HAS_SELECTION(state->Stb))
See the difference it makes:
Before:
https://github.com/user-attachments/assets/bbf2a9ea-6b42-47b8-8990-0eae49765893
After:
https://github.com/user-attachments/assets/e36f63ed-59ab-4889-8bfd-97c783fd35ec
Also, the is_bol
check prevents selection if the clicks happen at the very last character. It should fallback to select the last word of the text instead.