-
-
Notifications
You must be signed in to change notification settings - Fork 10.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to avoid a pressed button stealing the input from an InputText #1418
Comments
…ctly setting ActiveIdClickOffset, which probably have no known effect, but it is more correct this way. (#1418)
Hello Stefano, At the moment there's no way to avoid that with the default button behavior.
The demo code does the awkward:
Current Nav branch uses an explicit flag that you could set when pressing a keyboard key:
Also linking to #622 and #727 which relate to similar things. |
Hello Omar, Thanks for the response, just incredibly fast as always.
I have also tried (hacking in the internal api) to save and restore the entire ActiveID* state variables and it works, but I have found another problem that prevents me from getting the behavior I like. The relevant code in InputTextEx is: // Edit in progress
const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f));
const bool osx_double_click_selects_words = io.OSXBehaviors; // OS X style: Double click selects by word instead of selecting whole text
if (select_all || (hovered && !osx_double_click_selects_words && io.MouseDoubleClicked[0]))
{
edit_state.SelectAll();
edit_state.SelectedAllMouseLock = true;
}
else if (hovered && osx_double_click_selects_words && io.MouseDoubleClicked[0])
{
// Select a word only, OS X style (by simulating keystrokes)
edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
}
else if (io.MouseClicked[0] && !edit_state.SelectedAllMouseLock)
{
stb_textedit_click(&edit_state, &edit_state.StbState, mouse_x, mouse_y);
edit_state.CursorAnimReset();
}
else if (io.MouseDown[0] && !edit_state.SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f))
{
stb_textedit_drag(&edit_state, &edit_state.StbState, mouse_x, mouse_y);
edit_state.CursorAnimReset();
edit_state.CursorFollow = true;
}
if (edit_state.SelectedAllMouseLock && !io.MouseDown[0])
edit_state.SelectedAllMouseLock = false;
I was trying to get this done without modifying imgui core, but I am thinking that is not possible. Thanks again for your inputs. |
That's correct. Removing the
I cannot reproduce that. The code is normally programmed to restore cursor/selection of an InputText (it works as tested in I see the problem with testing for In the meanwhile it may be worth investigating why |
You are right, I cannot reproduce the issue with the text being selected automatically with SetKeyboardFocusHere, I was probably doing something wrong during the many tests I've been doing. It's not ideal but works for what I need. I am thinking that I could "reserve" the space for the text box without drawing it, draw the keyboard and then roll-back the Cursor position to draw the inputtext...or force another window or a child/popup window to be drawn before the input text. |
A true hack would be to use a second imgui context just for the keyboard... It's output then gets sent to the primary context that hold the textbox. |
This is an excellent idea! |
Part of the issue here and #1554 (but that's not all there is to it), is that the code path when programmatically focusing an InputText() automatically select all the text. This was an arbitrary decision but I think it came mostly to mimic the behavior of Tabbing through widgets (which auto select the text). When I rework the focus/activation API (it's currently a big big mess) I imagine there could be different flags to specify more detailed behavior (positioning the Nav focus/selection vs activating the widget vs activating + selecting all). If this is specified on the calling function the flags have to be designed in an InputText-agnostic way (focus vs activate vs xxx?). This is a perfect use case to design that focus/activation API. Short term I could either: I think (B) is best though it is technically breaking the existing select-all behavior. |
Btw I think this is the bug I fixed in 7ccbb76 |
Thanks for the bugfix, I will try at some point. I have solved also by reserving space for the input box, draw the keyboard first and the input box later, rolling back the cursor position appropriately. It's a little bit of a hack but it works. Regarding the behaviour I prefer option B, that is not to select on programmatic focus. |
Thanks! Yes I intend to move those flag to the focus functions it makes a lot more sense. My short term plan will be to try to merge the Navigation branch (what's done of it) because it add extra emphasis on focus concepts, and then I can work on the focus functions over the upcoming weeks/months. |
Ok, in other words you will be able to focus more on focus related things ;) |
Hi @Pagghiu, any chance you can post the code for your keyboard? It's looks really good! |
I'm going to work on this a little bit and provided updated code or workaround soon. |
The most common workaround mentioned in #1418 (comment) would today be likely written as: ImGui::InputText("Input", ....);
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy))
if (!ImGui::IsAnyItemActive() && !ImGui::IsAnyMouseDown())
ImGui::SetKeyboardFocusHere(-1); But that will essentially break keyboard navigation. if (ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy))
if (!ImGui::IsAnyItemActive() && !ImGui::IsAnyMouseDown())
if (!ImGui::GetIO().NavVisible)
ImGui::SetKeyboardFocusHere(-1); But it also means that the auto-focus will not work while using keyboard navigation, but currently if you press Escape to disable it (which itself is a feature that desktop apps are hoping to disable, another story) it'll clear NavVisible and therefore resurrect the focus. experimental idea ImGui::Begin(...);
// Make move requests in this window not steal active id:
ImGuiContext& g = *GImGui;
if (ImGui::NavMoveRequestButNoResultYet() && g.NavWindow == g.CurrentWindow)
g.NavMoveFlags |= ImGuiNavMoveFlags_NoClearActiveId; It "appears" to work but then |
…'s currently no satisfying way to take advantage of it. (#1418)
…'s currently no satisfying way to take advantage of it. (ocornut#1418)
Has that flag to not select text ever been implemented? I'm struggling with this right now for an autocomplete textbox. The issue is that I'm using the return key as a completion key and that deselects the textbox. Upon refocusing with edit: ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue;
static std::string text = "something";
if(ImGui::InputText("input", &text, flags)) {
ImGui::SetKeyboardFocusHere(-1);
text = "else";
} edit 2: I've just switched it over to a char array and it behaves the same, so it's not related to std::string. |
I am trying to create an on screen keyboard to edit text on systems without a keyboard.
Something like that.
The problem is that pressing any button "steals" the keyboard focus from the input text widget.
What's the most intelligent way of handling this scenario?
I have seen a few similar topics in the issues but nothing 100% equal to this case.
The text was updated successfully, but these errors were encountered: