ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
59.1k stars 10.08k forks source link

On WM with "Focus follow mouse": browsing parent menu can close all submenus #7359

Open m9710797 opened 5 months ago

m9710797 commented 5 months ago

Version/Branch of Dear ImGui:

Version 1.90.5, Branch: docking

Back-ends:

imgui_impl_sdl2.cpp + imgui_impl_opengl3.cpp

Compiler, OS:

Linux + GCC 13

Full config/build information:

Dear ImGui 1.90.5 WIP (19042)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=201103
define: __linux__
define: __GNUC__=13
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_sdl2
io.BackendRendererName: imgui_impl_opengl3
io.ConfigFlags: 0x00000443
 NavEnableKeyboard
 NavEnableGamepad
 DockingEnable
 ViewportsEnable
io.ConfigViewportsNoDecoration
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00001C0E
 HasMouseCursors
 HasSetMousePos
 PlatformHasViewports
 HasMouseHoveredViewport
 RendererHasVtxOffset
 RendererHasViewports
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 854.00,720.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 0.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00

Details:

I tried to search for existing tickets about this issue but I couldn't immediately find anything, I'm sorry if I overlooked something.

I can reproduce the problem with the (unmodified) demo application imgui/examples/example_sdl2_opengl3/example_sdl2_opengl3:

In my application I had a variation on the above:

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

// Here's some code anyone can copy and paste to reproduce your issue
ImGui::Begin("Example Bug");
MoreCodeToExplainMyIssue();
ImGui::End();
ocornut commented 5 months ago

It is probably another side effect of the ongoing #7325 debacle. I don’t think I will be able to check before monday, but if you can maybe see if it happens for you on 1.90.0.

m9710797 commented 5 months ago

I checked (git revision ce0d0ac8298). It also goes wrong there. Though the behavior is slightly different: in this version also the top level menu gets (wrongly) closed.

BTW I (only now) noticed that to trigger the bug (in both versions) it's required to move back to the same menu item in the previous sub-menu.

ocornut commented 5 months ago

I couldn't repro this on Windows so I wonder if it is a Linux specific issue. Could you record a video of the issue, with the Debug Log open and [X] Focus [X] Viewports [X] Popups checked in there?

m9710797 commented 5 months ago

Here's a screen recording (I had to gzip it, otherwise github wouldn't accept the file type). I've also attached the log file in text format.

Let me know if you need any other information, or what I could do to help investigate.

ocornut commented 5 months ago

In UpdateViewportsNewFrame(), could you find that block:

            if (apply_imgui_focus_on_focused_viewport)
            {
                focused_viewport->LastFocusedHadNavWindow |= (g.NavWindow != NULL) && (g.NavWindow->Viewport == focused_viewport); // Update so a window changing viewport won't lose focus.
                ImGuiFocusRequestFlags focus_request_flags = ImGuiFocusRequestFlags_UnlessBelowModal | ImGuiFocusRequestFlags_RestoreFocusedChild;
                if (focused_viewport->Window != NULL)
                    FocusWindow(focused_viewport->Window, focus_request_flags);
                else if (focused_viewport->LastFocusedHadNavWindow)
                    FocusTopMostWindowUnderOne(NULL, NULL, focused_viewport, focus_request_flags); // Focus top most in viewport
                else
                    FocusWindow(NULL, focus_request_flags); // No window had focus last time viewport was focused
            }

and immediately before the opening brace add:

            if (g.IO.KeyShift)
                 printf(""); // <--- ADD A BREAKPOINT HERE
            if (apply_imgui_focus_on_focused_viewport)
            {

This will allow you to easily break in debugger without altering the focus.

Then repeat the maneuver and start holding Shift before you know the issue will happen, and step in debugger.

Then in a debugger:

Could you also confirm when you are holding mouse down and up? (some people browse menu by holding the mouse button down the whole way, some do multiple clicks).

m9710797 commented 5 months ago

After opening the first menu (with a mouse click) I'm not keeping any mouse buttons pressed. I'm only doing mouse movements.

ocornut commented 5 months ago

Does your Linux WM auto focus on hover ?

m9710797 commented 5 months ago

Yes, I have "focus follows mouse" enabled. If I set it to "Click to focus" then I cannot reproduce the issue anymore. But obviously that's not a solution ;-)

I'm very used to "focus follows mouse". I forgot this isn't the (default?) behavior in Windows, so it didn't occur to me to report this.

ocornut commented 5 months ago

I never heard of this possible WM behavior before, I just yesterday guessed it may exists based on your report.

Unfortunately multi-viewports support seems to have many issues with Linux VM (and some with macOS).

It means the // Focused viewport has changed? logic in that function is flawed in particularly the block coming from 3418d509 for #6462 (and see #6299 for previous commits related to same function).

Also linking to #2117 for general Linux support for multi-viewports (generally not well supporting).

ocornut commented 5 months ago

The issue of clamping down the popup stack may be reproduced on most setup by removing the IsAnyMouseDown() check:

const bool apply_imgui_focus_on_focused_viewport = /*!IsAnyMouseDown() &&*/ !prev_focused_has_been_destroyed;

And clicking back on that parent viewport. (And it also breaks #6462.)

m9710797 commented 5 months ago

Hi, thanks for looking into this!

In the past I did use "focus follows mouse" on Windows, but that was over 10 years ago. When I google for it today I found this. Maybe that makes it easier to investigate?

As a side note: I did notice that Dear ImGui windows behave different when they're fully inside the main application window compared to when they're outside. So far I couldn't put my finger on it (I also didn't actively investigate). But now, after your insight, I see that (at least one of) the differences is this "focus follows mouse" behavior.

Would it be an option to always create ImGui windows as native windows? That way they'll always behave like native windows. And maybe it'll simplify testing or expose problems sooner?? (No more separate code paths to handle both cases??). But then I must say I don't know too much about the Dear ImGui internals, and you may have good reasons for the current design. (I can imagine native windows require more resources, so you only want to create them when really needed??)

ocornut commented 5 months ago

They are native windows. I'm not sure what you are saying. If you mean you want them to use WM decoration, you can set io.ConfigViewportsNoDecoration = false in code or Demo->Configuration but I don't think that will solve any problem.

m9710797 commented 5 months ago

Sorry I wasn't clear. I meant when a Dear ImGui window is fully contained inside the main application window. So when no extra viewport is needed.

At least I had the impression that viewports map to native windows. Maybe I'm wrong.

ocornut commented 5 months ago

The NoAutoMerge flag does that but it indeed exposes too many problems.

The current situation is that I don’t have resources to rewrite/redesign this system to accommodate for every eccentric WM features (worst offender being Wayland’s policies), so unfortunately it is unlikely to be fixed in the mid term. But here’s hoping that a redesign of viewports will improve things for Linux users. It’s just currently way off the priority list and too much of a time sink.

m9710797 commented 5 months ago

I understand. No problem. Thanks a lot anyway.

MBilderbeek commented 5 months ago

The issue was originally reported in our project openMSX (hi @m9710797) running on Windows.

grauw commented 2 months ago

I couldn't repro this on Windows so I wonder if it is a Linux specific issue.

Assuming this is the same as I described here, then this also happens on macOS. It seems to specifically happen when a menu item has a tooltip and the menu or the tooltip go outside the window boundaries. (My mouse cursor stays within the window region at all times though.)

ocornut commented 2 months ago

I shall investigate if it happens with stock macOS VM, but barring that we could have some settings to disable focus-imgui-window-on-platform-focus as a workaround for some systems.