-
Notifications
You must be signed in to change notification settings - Fork 26
Description
(Sorry if this is a bit messy, I'm just dumping from Discord post of 6 months ago so the issue is not forgotten)
My app has two layers, a sidebar and a content area.
Basically like the Sample 3 Resizable App.
But the problem is, unlike Resizable App, my content area is not full height. Its floating in the middle of the window.
So I create basically a "background" overlay/view.
And then I place a semi-transparent overlay "overlaying" over top.
But there comes the fun part. I can choose between correct rendering, or correct input handling, but not both.
If I create the background first, and the foreground second.
The foreground renders infront of the background, but I cannot click/interact with the foreground element.
If I swap the order, the foreground renders behind the background, BUT I can click/interact with the foreground element, which I now cannot see.
The problem seems to be here:
AppCore/src/common/OverlayManager.cpp
Line 39 in 5f88113
| for (auto& overlay : overlays_) { |
Overlays are rendered in order they are added, so the second overlay is rendered ontop of the first. That is how I would expect it to work.
But the hit test, for which overlay you're mousing/clicking over
AppCore/src/common/OverlayManager.cpp
Line 149 in 5f88113
| for (auto& i : overlays_) { |
Is also in order they are added, and it chooses the first overlay that is under the cursor.
But in my case, there are two overlays under the cursor.
The second one is the topmost one that I expect to interact with. But the first one it finds in the HitTest, is the background one, behind the overlay I'm trying to click on.
I can think of two solutions, give Overlays a Z order and sort them by it.
Or keep the "later created one is on top" and instead do the HitTest in reverse.
In my project I applied this hackfix, which works.
I asked 6 months ago if you wanted a PR and that I would create one, but I never got a reply to that question.
template<typename T> struct reversion_wrapper {
T& iterable;
};
template<typename T> auto begin(reversion_wrapper<T> w) { return std::rbegin(w.iterable); }
template<typename T> auto end(reversion_wrapper<T> w) { return std::rend(w.iterable); }
template<typename T> reversion_wrapper<T> reverse(T&& iterable) { return { iterable }; }
Overlay* OverlayManager::HitTest(int x, int y)
{
for (auto& i : reverse(overlays_)) {
if (!i->is_hidden() && x >= i->x() && y >= i->y() && x < i->x() + (int)i->width() && y < i->y() + (int)i->height())
return i;
}
return nullptr;
}The reverse wrapper code definitely belongs into some better place in some header file. But it fixes the issue.