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

Trigger widgets (per default) with the click that closes a popup #7681

Open
alektron opened this issue Jun 10, 2024 · 4 comments
Open

Trigger widgets (per default) with the click that closes a popup #7681

alektron opened this issue Jun 10, 2024 · 4 comments

Comments

@alektron
Copy link
Contributor

alektron commented Jun 10, 2024

Version/Branch of Dear ImGui:

Version 1.90.5, Branch: docking

Back-ends:

Tested with win32_opengl3 and custom

Compiler, OS:

MSVC 2022

Full config/build information:

No response

Details:

Related to #3154 , however in my case, I would like it not just for IsWindowHovered calls (where it can be done with a flag) but as a default behavior for all (or most) widgets.

Current behavior:
When a non-modal popup is open, clicking out of that popup closes it.
While the popup is open, the windows behind it do not receive hover 'events', e.g. buttons do not get highlighted on mouse over.
This is to be expected and in fact the same behavior as in most applications I have tested (Visual Studio, Chrome).

Expected/Wanted behavior:
The difference to other applications is, that despite the hover effect not showing, the click will still close the popup AND trigger the widget that is below the mouse cursor. For example, in Chrome if I open a context menu via right click on a web page and then click on a different tab, that single click will close the context menu and switch to that tab.

Is there already some configuration flag or similar that would replicate this behavior?
As far as I can tell, the fact that the background widgets can not go into the hovered state causes them to also not go into the active state on click. So this might be a problem because they can not be in a state where they are hovered but do not look like they are. Is that a correct assumption?

At first I did not think, this behavior would cause any problems but I have now repeatedly encountered "less experienced" users of our software, that do not realize that a click did not work because there was still a popup on screen that got closed first.
Ok, so this is just a bit of a bad user experience ("why did that click not work? Weird, guess I'll click again"). But in a recent extreme case, a user was trying to switch to another tab, whose content looked quite similar to the one that was currently open. That tab switch did not work because of an open popup and the user did not notice that and continued to erroneously work in the same tab he was already in.
The active tab is distinctly colored different to the other tabs (light blue vs. dark gray/black) and I also made the popup background color brighter than other windows but some users are just resistant to visual cues.

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

No response

@ocornut
Copy link
Owner

ocornut commented Jun 10, 2024

Expected/Wanted behavior:
The difference to other applications is, that despite the hover effect not showing, the click will still close the popup AND trigger the widget that is below the mouse cursor. For example, in Chrome if I open a context menu via right click on a web page and then click on a different tab, that single click will close the context menu and switch to that tab.

For right-click reopening of context-menu, this tends to be handled by dear imgui because the right-mouse down event is closing popup and the right-mouse up event opens one. Therefore a right-click does both. This is why BeginPopupContextItem() and other similar functions are using IsMouseReleased().

However you are right that many systems behave in the way you described, do not display highlight but react on click.
I don't yet know how easy or difficult it would be to implement this.

I know that it would be simple to make the whole feature an opt-out in BeginPopup(), e..g ImGuiPopupFlags_NoBlockHoveringBehind, which might solve/help in some situation but not exactly provide the discussed behavior.

@ocornut
Copy link
Owner

ocornut commented Jun 10, 2024

The way this is implemented:

Actual filter is in IsWindowContentHoverable().

  • This is where it would be easy to make the whole thing opt-out using a popup flag.
  • We'd need to refactor that interface to extract the info we need, maybe return a tri-state enum (Hoverable, HoverableBehindPopup, HoverableBehindModal).

That function is roughly called from three spots: IsItemHovered(), ItemHoverable() and IsWindowHovered()
ItemHoverable() is roughly in-widget-code specialized version of what would be needed for IsItemHovered(), so they have similar stuff.

Very broadly, making ItemHoverable() return false while still calling SetHoveredId() would be the direction to go, and we already have systems doing this, and it would probably get us 80% of the way. But the remaining 80% would require checking/considering every possible path, also the feature match and extra flags for IsItemHovered().

@alektron
Copy link
Contributor Author

I'm still looking into the code trying to get a bit of an overview over all the hovering internals. However I have some trouble understanding and got some follow up questions.

I know that it would be simple to make the whole feature an opt-out in BeginPopup(), e..g ImGuiPopupFlags_NoBlockHoveringBehind, which might solve/help in some situation but not exactly provide the discussed behavior.

Would that not be an opt-IN? By passing that flag I would get the "new" behavior of not blocking the hover of windows behind the popup. Or are you saying if the new behavior were the default, one could opt back out into the old behavior via that flag.
But then it seems to me it would be called ImGuiPopupFlags_BlockHoveringBehind without the "No".

Would that really be ImGuiPopupFlags_NoBlockHoveringBehind or ImGuiWindowFlags_NoBlockHoveringBehind? Since BeginPopup takes WindowFlags. Also contrary to OpenPopup (which would take PopupFlags), only BeginPopup seems to store the flags, which would be necessary for other windows to even check for that. Correct?


I've also been playing around a bit and while this is of course not the solution, I hardcoded an ImGuiHoveredFlags_AllowWhenBlockedByPopup into the call of IsWindowContentHoverable in ItemHoverable, just to see what happens.
Like this I can already use widgets in the back. However when clicking on one, the popup stays open. The reason seems to be that UpdateMouseMovingWindowEndFrame, which would focus the window and close the popup down the line exits early because ActiveId and/or HoveredId is now set.

Also, we do of course get the normal hover effect. I am wondering however if this is even that bad. Why should one not want the hover effect when I can in fact click the widget? Tbh I feel like the no-hover-but-clickable convention in other applications could just as well be unintended and an artifact of default Windows window behavior. Something that we are just stuck with now due to historical reasons. Just something to think about.

@ocornut
Copy link
Owner

ocornut commented Jun 11, 2024

know that it would be simple to make the whole feature an opt-out in BeginPopup(), e..g
Would that not be an opt-IN?

I meant the BLOCKING which is the current default, could be opted-out on a per popup basis.

Would that really be ImGuiPopupFlags_NoBlockHoveringBehind or ImGuiWindowFlags_NoBlockHoveringBehind? Since BeginPopup takes WindowFlags.

I'd rather move popup specific stuff to PopupFlags. But, dang, I forgot that some of those entry points don't have PopupFlags already exposed :( it's a little annoying because it means we would need to use BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0, ImGuiPopupFlags = 0) which is inconsistent with e.g. BeginChild().

, only BeginPopup seems to store the flags, which would be necessary for other windows to even check for that. Correct?

We would likely store a ImGuiPopupFlags in ImGuiWindow just like we now store ImGuiChildFlags.

Tbh I feel like the no-hover-but-clickable convention in other applications could just as well be unintended and an artifact of default Windows window behavior. Something that we are just stuck with now due to historical reasons. Just something to think about.

Yes, to be honest I was actually surprised yesterday to find how many things allowed that click even though there's no hover feedback. I wonder if things evolved over the last decade or so tending toward the current state, because it my mind it wasn't even possible most of the time. I don't know where I got this idea from.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants