Skip to content
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

IsWindowAppearing + SetKeyboardFocusHere not focusing keyboard on first open #4079

Closed
invrainbow opened this issue Apr 26, 2021 · 6 comments
Closed
Labels
focus nav keyboard/gamepad navigation scrolling
Milestone

Comments

@invrainbow
Copy link

invrainbow commented Apr 26, 2021

I'm showing a window with a text input that I'd like to autofocus when the window is opened. Here's a simplified version of what I'm doing:

bool show;
char query[256];

if (show) {
    ImGui::Begin("Open File", &show, ImGuiWindowFlags_AlwaysAutoResize);
    ImGui::Text("Search for file:");
    if (ImGui::IsWindowAppearing())
        ImGui::SetKeyboardFocusHere();
    ImGui::InputText("##search_for_file", query, _countof(query));
    ImGui::End();
}

This mostly works. The only problem is, the first time the window is opened, the keyboard focus is not set. It works on the second and all subsequent opens.

I set a breakpoint on the ImGui::SetKeyboardFocusHere() call, and it is being called on the first window open. The text input is just not focused.

I'm not entirely sure how to productively ask this question, since this is part of a much larger application & I'm not sure what confounding factors might be causing this. Anyone have any hunches? I can share more of my code where helpful.

Also, I was previously using a copy of dear imgui from about August 2020, and I wasn't getting this bug then. I upgraded to master HEAD yesterday, and this bug appeared.

@ocornut
Copy link
Owner

ocornut commented Apr 27, 2021

Please specify which exact version because we made changes to those functions recently.

@invrainbow
Copy link
Author

Old version was v1.77, upgraded to v1.83.

@ocornut ocornut added the focus label Apr 27, 2021
@ocornut
Copy link
Owner

ocornut commented Apr 30, 2021

Thank you for confirming this. I think this is the same as #343. I'm going to look at this now.

ocornut added a commit that referenced this issue Apr 30, 2021
…le it prior to clipping (not yet the case) (#343, #4079)

Now performed in ItemAdd(). It can't be trivially moved above clipping effectively because it would require us to scroll to be useful, meaning we'd be better off locking the bounding box a frame earlier. Still wip.
As-is this commit has no value for end-user, but it's a reengineering that moves us closer to the solution. + Internals: moved internal flags.
@ocornut
Copy link
Owner

ocornut commented Apr 30, 2021

Also, I was previously using a copy of dear imgui from about August 2020, and I wasn't getting this bug then. I upgraded to master HEAD yesterday, and this bug appeared.

Having investigated I believe this statement may be incorrect, I also know understand how subtle factors can invalidate some tests you could have done. Since this is a clipping issue, last known window size would affect it, and e.g not using ImGuiWindowFlags_AlwaysAutoResize would in most cases reduce the issue to the first session (before .ini file is created) as on next sessions the window would have a stored size, leading the widget to not be clipped.
If you are firmly convinced it worked in the August 2020 I would be interested in you double-checking that with a clean state (including same or cleared .ini data), but I suspect the different may be due to different window size or .ini data.

Actually spent a while digging on this but it is a rather nasty problem to fully solve (had a bunch of related work done a while ago, almost spent a week on this but didn't finish). I would want to solve it.

I just committed some partial refactor (393941c) which is getting us closer to being able to move the focusable registration before clipping, as it is now performed in ItemAdd() literally clipping and focus registration are now next to each others...

...However they can't be trivially swapped yet because it would require us to scroll to keep target item visible in order to be useful (if you Tab out of sight it would be wrong). So while doing that simple swap would fix #4079 and #343 it would currently come with a bigger regression in term of user experience.

Given the current code we have access to the positional data too late in the frame since scroll needs to be locked in Begin(). So with current code structure the dumb solution would requires us to first focus/tab the next widget on frame N and then scroll on frame N+1, which is the kind of horrible scrolling experience you'd expect from an Android TV.

So right now I don't have a nice answer for it but

Repro

ImGui::Begin("Another Window", &show_another_window, ImGuiWindowFlags_AlwaysAutoResize);   // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)

static char query[256] = "";

ImGui::Text("Search for file:");
if (ImGui::IsWindowAppearing())
    ImGui::SetKeyboardFocusHere();
ImGui::InputText("##search_for_file", query, 256);

ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
    show_another_window = false;
ImGui::End();

@invrainbow
Copy link
Author

Also, I was previously using a copy of dear imgui from about August 2020, and I wasn't getting this bug then. I upgraded to master HEAD yesterday, and this bug appeared.

Having investigated I believe this statement may be incorrect, I also know understand how subtle factors can invalidate some tests you could have done. Since this is a clipping issue, last known window size would affect it, and e.g not using ImGuiWindowFlags_AlwaysAutoResize would in most cases reduce the issue to the first session (before .ini file is created) as on next sessions the window would have a stored size, leading the widget to not be clipped.

You're probably right. I don't remember it from before, but I might have just never noticed, or there could be some other reason.

Anyway, I don't really understand how the internals of ImGui work, but I am getting the gist that it's the first call to SetKeyboardFocusHere() that fails. So I fixed this by calling it twice:

// global variable
bool first_open = true;

// later, in window
if (ImGui::IsWindowAppearing()) {
  ImGui::SetKeyboardFocusHere();
} else if (first_open) {
  ImGui::SetKeyboardFocusHere();
  first_open = false;
}

I'll leave the issue open as it looks like there's still some genuine fix that needs to happen.

@ocornut ocornut added the nav keyboard/gamepad navigation label Aug 20, 2021
@ocornut ocornut added this to the v1.85 milestone Sep 7, 2021
ocornut added a commit that referenced this issue Oct 6, 2021
…for clipped items. (#343, #4079, #2352, #432)

+ Removed references to counter used by previous implementation of SetKeyboardFocus functions (the TabStop ones will be removed after)
@ocornut
Copy link
Owner

ocornut commented Oct 6, 2021

Better late than never.... using SetKeyboardFocusHere() on non-visible item is finally fixed by 31d033c + 8f495e5.
It was particularly trickier than meet-the-eyes but satisfied with current version.

(I'm not done with the refactor as Tabbing currently doesn't scroll, I still have a few things I don't yet know how to solve for the tabbing but we are nearly there).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
focus nav keyboard/gamepad navigation scrolling
Projects
None yet
Development

No branches or pull requests

2 participants