[haiku-commits] Change in haiku[master]: BPopUpMenu: Call MenusBeginning() and MenusEnded() hook methods

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 27 Feb 2020 23:25:00 +0000

From John Scipione <jscipione@xxxxxxxxx>:

John Scipione has uploaded this change for review. ( 
https://review.haiku-os.org/c/haiku/+/2289 ;)


Change subject: BPopUpMenu: Call MenusBeginning() and MenusEnded() hook methods
......................................................................

BPopUpMenu: Call MenusBeginning() and MenusEnded() hook methods

... when opening and closing a BPopUpMenu that isn't attached to a BMenuBar
asynchronously. Check to see if we are attached to a BMenuBar first because
if we are attached to a BMenuBar (as is the case for example in a BMenuField)
the BMenuBar will call MenusBeginning() and MenuEnding() for us. Create
private static class method _HasMenuBar() for this purpose.

Update documentation for BWindow::MenusBeginning() and BWindow::MenusEnded().
---
M docs/user/interface/Window.dox
M headers/os/interface/PopUpMenu.h
M src/kits/interface/PopUpMenu.cpp
3 files changed, 48 insertions(+), 10 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/89/2289/1

diff --git a/docs/user/interface/Window.dox b/docs/user/interface/Window.dox
index 89f0960..8886305 100644
--- a/docs/user/interface/Window.dox
+++ b/docs/user/interface/Window.dox
@@ -1046,11 +1046,12 @@

 /*!
        \fn void BWindow::MenusBeginning()
-       \brief Hook method that gets called just before a menu owned by the 
window is
-              shown.
+       \brief Hook method that gets called just before an asynchronous pop-up
+              menu or a menu attached to a menu bar owned by the window is
+              opened.
 
        \note This method is not invoked by a message, there is no
-             \c B_MENUS_BEGINNING flag.
+             \c B_MENUS_BEGINNING or \c _MENUS_BEGUN_ command.

        \since BeOS R3
 */
@@ -1058,11 +1059,12 @@

 /*!
        \fn void BWindow::MenusEnded()
-       \brief Hook method that gets called just before a menu owned by the 
window is
-              hidden.
+       \brief Hook method that gets called just after an asynchronous pop-up
+              menu or a menu attached to a menu bar owned by the window is
+              closed.

-       \note This method is not invoked by a message, there is no
-             \c B_MENUS_ENDED flag.
+       You may invoke this method from another thread by sending a message
+       to the window with the \c _MENUS_DONE_ command (defined in AppDefs.h).

        \since BeOS R3
 */
diff --git a/headers/os/interface/PopUpMenu.h b/headers/os/interface/PopUpMenu.h
index 2ecf6dd..36d82bd 100644
--- a/headers/os/interface/PopUpMenu.h
+++ b/headers/os/interface/PopUpMenu.h
@@ -74,6 +74,8 @@

        static  int32                           _thread_entry(void* menuData);

+       static  bool                            _HasMenuBar(BPopUpMenu* 
popUpMenu);
+
 private:
                        BPoint                          fWhere;
                        bool                            fUseWhere;
diff --git a/src/kits/interface/PopUpMenu.cpp b/src/kits/interface/PopUpMenu.cpp
index 7b94b38..c608b92 100644
--- a/src/kits/interface/PopUpMenu.cpp
+++ b/src/kits/interface/PopUpMenu.cpp
@@ -10,6 +10,7 @@

 #include <Application.h>
 #include <Looper.h>
+#include <MenuBar.h>
 #include <MenuItem.h>
 #include <PopUpMenu.h>
 #include <Window.h>
@@ -347,14 +348,17 @@
        // Get a pointer to the window from which Go() was called
        BWindow* window
                = 
dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));
-       data->window = window;

        // Asynchronous menu: we set the BWindow menu's semaphore
        // and let BWindow block when needed
-       if (async && window != NULL)
+       if (async && window != NULL) {
+               if (!_HasMenuBar(this))
+                       window->MenusBeginning();
                _set_menu_sem_(window, sem);
+       }

        data->object = this;
+       data->window = window;
        data->autoInvoke = autoInvoke;
        data->useRect = _specialRect != NULL;
        if (_specialRect != NULL)
@@ -400,9 +404,13 @@
        data->selected = menu->_StartTrack(data->where, data->autoInvoke,
                data->startOpened, rect);

+       // We aren't the BWindow thread, so don't call MenusEnded() directly.
        // Reset the window menu semaphore
-       if (data->async && data->window)
+       if (data->async && data->window) {
+               if (!_HasMenuBar(data->object))
+                       data->window->PostMessage(_MENUS_DONE_);
                _set_menu_sem_(data->window, B_BAD_SEM_ID);
+       }

        delete_sem(data->lock);

@@ -479,3 +487,29 @@

        return selected;
 }
+
+
+/* static */
+bool
+BPopUpMenu::_HasMenuBar(BPopUpMenu* popUpMenu)
+{
+       if (popUpMenu == NULL)
+               return false;
+
+       // we have a pop up menu;
+
+       BMenu* menu = static_cast<BMenu*>(popUpMenu);
+
+       // we have a menu, static_cast to an inherited class is guaranteed to 
pass
+
+       BMenu* _menu;
+       while ((_menu = menu->Supermenu()) != NULL)
+               menu = _menu;
+
+       // went up the hierarchy and found the topmost menu ancestor
+       // (possibly ourself)
+
+       return dynamic_cast<BMenuBar*>(menu) != NULL;
+
+       // our topmost menu ancestor has been determined to be a BMenuBar or not
+}

--
To view, visit https://review.haiku-os.org/c/haiku/+/2289
To unsubscribe, or for help writing mail filters, visit 
https://review.haiku-os.org/settings

Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I0161272f968db419e4b2887ddebbef90810183c4
Gerrit-Change-Number: 2289
Gerrit-PatchSet: 1
Gerrit-Owner: John Scipione <jscipione@xxxxxxxxx>
Gerrit-MessageType: newchange

Other related posts:

  • » [haiku-commits] Change in haiku[master]: BPopUpMenu: Call MenusBeginning() and MenusEnded() hook methods - Gerrit