I'm using ImGui to display a popup menu. Normally, Escape closes my application, i. e. if !ImGui::GetIO().WantCaptureKeyboard.
I have enabled keyboard navigation with io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard in order to make Escape close the menu. That works, but unfortunately WantCaptureKeyboard is still true afterwards. So if I hit Escape again, my application won't close.
This is not the case when I click next to the menu. In this case, the menu closes and WantCaptureKeyboard becomes false.
Another problem is that WantCaptureKeyboard is true when my application starts.
So maybe I misunderstand something. I would think that navigation only requests the keyboard if any ImGui window or popup is active. As far as I know, that is not the case when the application starts, or after the popup menu is closed.
I've tried to also set ImGuiConfigFlags_NavNoCaptureKeyboard, but then the application would always close, even if I intend to close the popup.
Tested with 1.69 on Windows.
So maybe I misunderstand something. I would think that navigation only requests the keyboard if any ImGui window or popup is active. As far as I know, that is not the case when the application starts, or after the popup menu is closed.
I am not sure what you mean by "Active", in dear imgui terminology a Window is "Active" when it has been submitted during the current frame, leading to it being visible.
Navigation requests the keyboard when any window is _Focused_. This is the case when starting the application and when closing a popup. If you click on the void area not handled by dear imgui, all windows will be unfocused.
I understand your problem but I am not sure what the solution is yet. We may need more granularity as to how Navigation capture keyboard but I don't yet know what design would be satisfactory. When navigation is enabled you can always use the arrow keys/space/etc. to manipulate imgui so it seems to make sense to request Keyboard Capture then.
Thanks for the clarification. After digging a bit deeper, I discovered ShowMetricsWindow to display the current NavWindow. When my application has focus (NavWindow is 0), and I then trigger the popup and press Escape, ImGui switches the focus to Debug#Default. I would expect the focus to go back to my application.
I was able to hack it by changing ClosePopupToLevel.
if (focus_window->ParentWindow == NULL) {
focus_window = NULL;
}
FocusWindow(focus_window);
What is the purpose of the Debug#Default window? Is it necessary that this window ever has focus?
and I then trigger the popup and press Escape, ImGui switches the focus to Debug#Default. I would expect the focus to go back to my application.
Correct, this is a bug then and should be fixed.
I will look into it.
I assume that your popup is called outside of a Begin/End call ?
The Debug##Default window sits a the bottom of the window stack and is automatically hidden when unused. In this situation it appears there is an incorrect relationship between the popup and the window on the top of the stack at the time of opening the popup, and focus is restored to it when closing the popup.
Fixing that bug will fix that scenario you mentioned in the last message.
(As a separate thing, we could possibly also want to decide that pressing Escape when there's no widget active would unfocus the current window.)
It would be useful if you provided a repro as requested by the issue template.
My current assumption is that you are doing something like this:
ImGui::NewFrame();
if (ImGui::BeginPopupContextVoid())
{
ImGui::MenuItem("This is a popup");
ImGui::EndPopup();
}
After testing it some more I think this is a deeper issue.
My application basically consists of one GL viewport, similar to Maya with a maximized viewport. I interact with it with the mouse and the keyboard. Most of the time, no other window is visible. But sometimes I do want windows, e. g. the popup I described earlier. If I enable ImGuiConfigFlags_NavEnableKeyboard, it is an all or nothing kind of deal. From my perspective, ImGui now blocks user interaction, even in cases when it doesn't do anything with the keys.
What I would prefer is events like in Qt. For example normally I use keys like W or E as hotkeys. But if a line edit has focus, e. g. when I enter a file name, I want that line edit to consume these keys. In Qt, the line edit would be the widget with the focus, receive an event, and mark it as accepted. But if it doesn't care about those keys, the event is propagated to the parent. The top-most parent would then handle the global shortcuts.
ImGui already has something like this for text edits, but there is no global solution.
Another aspect: We have Ctrl+Tab now. But there's no way for me to add my viewport to the list of Ctrl+Tab targets, right?
So I think the two open questions are: How can ImGui share focus with the application? And how can ImGui pass the focus back to the application?
It would be useful if you provided a repro as requested by the issue template.
Sure, sorry.
static bool MainMenu = false;
if (App.TriggerMainMenu) {
ImGui::OpenPopup("mainmenu");
App.TriggerMainMenu = false;
ProcessImGuiEvent = true;
}
if (ImGui::BeginPopup("mainmenu")) {
MainMenu = true;
ImGui::MenuItem("Hi there");
ImGui::EndPopup();
} else if (MainMenu) {
MainMenu = false;
// Draw an additional frame if the menu is hidden so that ImGui will realize that it
// no longer wants the mouse.
ProcessImGuiEvent = true;
}
From my perspective, ImGui now blocks user interaction,
It does if an imgui window is focused and keyboard navigation is enabled, unless you set ImGuiConfigFlags_NavNoCaptureKeyboard.
Right now you reported a bug where an imgui window is erroneously marked as focused, requesting inputs. This should be fixed and i'll be looking into it.
What I would prefer is events like in Qt.
I think there's case for something like you describe, and as we transition to storing events instead of levels for all aspect of the input system, we could imagine that a consumer would mark one as consumed and leave it to the caller to process it on return. That would be acceptable if you are ready to poll keyboard from the same events/structure you submitted to imgui and after submitting all your imgui contents, but that's a constraint more than anything if your input is the application and not actual UI code. This technique would probably be ideal for global shortcuts, but probaby not the ideal solution if your consumer is the game and not actual UI stuff. In all likehood from a gamey application point of view you want to be able to access your inputs early in the frame?
Enabling keyboard navigation means you can control the entirely of dear imgui with the keyboard (using arrows, space, etc.) and in the future we could imagine interactions to be tied to local shortcuts (e.g. in a menu you would press E to trigger an item caled `Execute'). So having inputs selectively be dispatched to the UI or your game based on what the UI is showing up at a certain point in time is going to be very confusing and dangerous. Someone needs to be owning the focus and inputs. Right now keyboard navigation means that focused imgui window are consuming inputs.
A stateful toggle generally work, you'll need the bug fix mentioned above, and then let the user click back on background/game, or maybe use global hotkey if we want to stop using imgui.
So I think the two open questions are: How can ImGui share focus with the application? And how can ImGui pass the focus back to the application?
It's a perfectly fine topic for discussion but as presented the questions are too vague and wide reaching, we ought to be working on specific problem to solve.
Another aspect: We have Ctrl+Tab now. But there's no way for me to add my viewport to the list of Ctrl+Tab targets, right?
Please open a separate issue for that. I don't know what you mean by "viewport" here. Do you mean ImGuiViewport ? Or do you mean you would like Ctrl+Tab to be able to target a state where no imgui window is focused, relinquishing full inputs to your underlying app? If so that's an interesting idea we could design and implement (in a separate thread).
// Draw an additional frame if the menu is hidden so that ImGui will realize that it no longer wants the mouse.
I think you should use a counter, that would make your code simpler.
MarkUiAsAlive() { frame_counter = 3; } // Will keep processing events for 3 frames.
Even so I am not sure why you are doing this at all unless you want whole app to go idle and only resume on inputs (in which case your wakeup triggers would be tied to inputs rather than display of actual ui). If you have a 3D viewport of some sort presumably you are already running a main loop at interactive refresh rate?
Yea. Sorry that this got so confusing. All I wanted in my life was for Escape to close that popup menu. Then I enabled ImGuiConfigFlags_NavEnableKeyboard, which did that, but also introduced other issues so that I've since disabled it again.
I've implemented a solution that calls CloseCurrentPopup() on Escape. I wouldn't mind if you closed this issue.
I've implemented a solution that calls CloseCurrentPopup() on Escape. I wouldn't mind if you closed this issue.
If you don't need any other keyboard control that would work as a workaround, yes.
I'll look into fixing the bug either way. Unsurprisingly the code in ClosePopupToLevel() has a large comment that state that the focus restoring code is currently completely wrong and I'd like to tackle that.
As for Ctrl+Tab toward giving back full inputs to your underlying game. It didn't come up before because many people just render their game content in an imgui window. But then I realize you can just do that as well:
ImGui::SetNextWindowPos(ImVec2(0, 0));
ImGui::SetNextWindowSize(io.DisplaySize);
ImGui::Begin("My Game", NULL, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoBringToFrontOnFocus);
ImGui::End();
Then you can CTRL+Tab into the background and because that window has the ImGuiWindowFlags_NoNavInputs flag it won't request keyboard at all.
FYI I have pushed the fix for NavWindow not being restored to NULL in the situation you described.
Closing this as afaik
I understand this is a wider topic and I'm happy to get back to any discussion/features regarding different ways to share inputs between imgui side and app side, so feel free to comment it (and I can reopen this) or create new issue if something arise.
@ocornut Thanks, Omar!