From 54c286407b428db8c0a36b878708ca2b132ec842 Mon Sep 17 00:00:00 2001 From: David Capello Date: Sat, 15 May 2021 14:33:29 -0300 Subject: [PATCH] Close several PopupWindows at the same time w/one click Clicking outside a popup window we can close several popup windows (e.g. tool box tooltip + tool box group popup, or brush pop + brush params popup). Before this change a kMouseDownMessage in a PopupWindow will close the window only if the Manager::getTopWindow() was equal to the PopupWindow. --- src/app/ui/brush_popup.cpp | 14 +++++++++++++- src/app/ui/context_bar.cpp | 11 +++++++---- src/ui/menu.cpp | 7 +++++++ src/ui/menu.h | 3 +++ src/ui/popup_window.cpp | 4 +--- 5 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/app/ui/brush_popup.cpp b/src/app/ui/brush_popup.cpp index 386992c35..3e4824e40 100644 --- a/src/app/ui/brush_popup.cpp +++ b/src/app/ui/brush_popup.cpp @@ -58,7 +58,19 @@ void show_popup_menu(PopupWindow* popupWindow, const gfx::Point& pt, Display* display) { + // Add the menu window region when it popups to the the BrushPopup + // hot region, so when we click inside the popup menu it doesn't + // close the BrushPopup. + obs::scoped_connection c = popupMenu->OpenPopup.connect([popupWindow, popupMenu]{ + gfx::Region rgn(popupWindow->boundsOnScreen()); + rgn |= gfx::Region(popupMenu->boundsOnScreen()); + popupWindow->setHotRegion(rgn); + }); + popupMenu->showPopup(pt, display); + + // Restore hot region of the BrushPopup window + popupWindow->setHotRegion(gfx::Region(popupWindow->boundsOnScreen())); } class SelectBrushItem : public ButtonSet::Item { @@ -322,7 +334,7 @@ private: } // anonymous namespace BrushPopup::BrushPopup() - : PopupWindow("", ClickBehavior::CloseOnClickInOtherWindow) + : PopupWindow("", ClickBehavior::CloseOnClickOutsideHotRegion) , m_standardBrushes(3) , m_customBrushes(nullptr) { diff --git a/src/app/ui/context_bar.cpp b/src/app/ui/context_bar.cpp index 8381b16de..78b68a6a2 100644 --- a/src/app/ui/context_bar.cpp +++ b/src/app/ui/context_bar.cpp @@ -163,6 +163,13 @@ public: SkinPartPtr part(new SkinPart); part->setBitmap(0, BrushPopup::createSurfaceForBrush(BrushRef(nullptr))); addItem(part); + + m_popupWindow.Open.connect( + [this]{ + gfx::Region rgn(m_popupWindow.boundsOnScreen()); + rgn |= gfx::Region(this->boundsOnScreen()); + m_popupWindow.setHotRegion(rgn); + }); } ~BrushTypeField() { @@ -221,10 +228,6 @@ private: m_popupWindow.regenerate(display(), popupPosCandidate()); m_popupWindow.setBrush(brush.get()); - - Region rgn(m_popupWindow.boundsOnScreen().createUnion(boundsOnScreen())); - m_popupWindow.setHotRegion(rgn); - m_popupWindow.openWindow(); } diff --git a/src/ui/menu.cpp b/src/ui/menu.cpp index 364ff2b56..78eceab8d 100644 --- a/src/ui/menu.cpp +++ b/src/ui/menu.cpp @@ -214,6 +214,11 @@ Menu::~Menu() } } +void Menu::onOpenPopup() +{ + OpenPopup(); +} + ////////////////////////////////////////////////////////////////////// // MenuBox @@ -350,6 +355,8 @@ void Menu::showPopup(const gfx::Point& pos, // New window and new menu-box std::unique_ptr window(new Window(Window::WithoutTitleBar)); + window->Open.connect([this]{ this->onOpenPopup(); }); + MenuBox* menubox = new MenuBox(); MenuBaseData* base = menubox->createBase(); base->was_clicked = true; diff --git a/src/ui/menu.h b/src/ui/menu.h index e641d47d9..596c2dc79 100644 --- a/src/ui/menu.h +++ b/src/ui/menu.h @@ -37,10 +37,13 @@ namespace ui { return m_menuitem; } + obs::signal OpenPopup; + protected: virtual void onPaint(PaintEvent& ev) override; virtual void onResize(ResizeEvent& ev) override; virtual void onSizeHint(SizeHintEvent& ev) override; + virtual void onOpenPopup(); private: void setOwnerMenuItem(MenuItem* ownerMenuItem) { diff --git a/src/ui/popup_window.cpp b/src/ui/popup_window.cpp index 68412ea8c..443b931df 100644 --- a/src/ui/popup_window.cpp +++ b/src/ui/popup_window.cpp @@ -134,9 +134,7 @@ bool PopupWindow::onProcessMessage(Message* msg) break; case kMouseDownMessage: - if (m_filtering && - manager()->getTopWindow() == this && - msg->display()) { + if (m_filtering && msg->display()) { gfx::Point mousePos = static_cast(msg)->position(); gfx::Point screenPos = msg->display()->nativeWindow()->pointToScreen(mousePos);