Fix bug where we were able to click a non-foreground window

With multiple windows on, if a modal/foreground window like Canvas
Size (which has a special onBroadcastMouseMessage()) were running, and
there was a script dialog also opened on the background, the
non-foreground dialog could receive clicks. This patch fixes this
particular scenario (no other window than the actual foreground window
can receive mouse clicks).
This commit is contained in:
David Capello 2023-05-05 20:08:39 -03:00
parent b5f262f423
commit 8cdb4edcac
2 changed files with 28 additions and 20 deletions

View File

@ -639,7 +639,10 @@ void Manager::handleMouseDown(Display* display,
PointerType pointerType,
const float pressure)
{
handleWindowZOrder();
// Returns false in case that we click another Display (os::Window)
// that is not the current running top-most foreground window.
if (!handleWindowZOrder())
return;
enqueueMessage(
newMouseMessage(
@ -730,45 +733,49 @@ void Manager::handleTouchMagnify(Display* display,
// window that aren't the desktop).
//
// TODO code similar to Display::handleWindowZOrder()
void Manager::handleWindowZOrder()
bool Manager::handleWindowZOrder()
{
if (capture_widget || !mouse_widget)
return;
return true;
// The clicked window
Window* window = mouse_widget->window();
Manager* win_manager = (window ? window->manager(): nullptr);
Window* topWindow = getTopWindow();
if ((window) &&
// We cannot change Z-order of desktop windows
(!window->isDesktop()) &&
// We cannot change Z order of foreground windows because a
// foreground window can launch other background windows
// which should be kept on top of the foreground one.
(!window->isForeground()) &&
// If the window is not already the top window of the manager.
(window != win_manager->getTopWindow())) {
// We cannot change Z-order of desktop windows
(!window->isDesktop()) &&
// We cannot change Z order of foreground windows because a
// foreground window can launch other background windows
// which should be kept on top of the foreground one.
(!window->isForeground()) &&
// If the window is not already the top window of the manager.
(window != topWindow)) {
// If there is already a top foreground window, cancel the z-order change
if (topWindow && topWindow->isForeground())
return false;
base::ScopedValue<Widget*> scoped(m_lockedWindow, window);
window->display()->handleWindowZOrder(window);
// Put it in the top of the list
win_manager->removeChild(window);
removeChild(window);
if (window->isOnTop())
win_manager->insertChild(0, window);
insertChild(0, window);
else {
int pos = (int)win_manager->children().size();
int pos = (int)children().size();
for (auto it=win_manager->children().rbegin(),
end=win_manager->children().rend();
for (auto it=children().rbegin(),
end=children().rend();
it != end; ++it) {
if (static_cast<Window*>(*it)->isOnTop())
break;
--pos;
}
win_manager->insertChild(pos, window);
insertChild(pos, window);
}
if (!window->ownDisplay())
@ -777,6 +784,7 @@ void Manager::handleWindowZOrder()
// Put the focus
setFocus(mouse_widget);
return true;
}
// If display is nullptr, mousePos is in screen coordinates, if not,

View File

@ -1,5 +1,5 @@
// Aseprite UI Library
// Copyright (C) 2018-2022 Igara Studio S.A.
// Copyright (C) 2018-2023 Igara Studio S.A.
// Copyright (C) 2001-2017 David Capello
//
// This file is released under the terms of the MIT license.
@ -152,7 +152,7 @@ namespace ui {
const gfx::Point& mousePos,
const KeyModifiers modifiers,
const double magnification);
void handleWindowZOrder();
bool handleWindowZOrder();
void updateMouseWidgets(const gfx::Point& mousePos,
Display* display);