[prev in list] [next in list] [prev in thread] [next in thread]
List: haiku-commits
Subject: [haiku-commits] Change in haiku[master]: BPopUpMenu: Call MenusBeginning() and MenusEnded() hook met
From: Gerrit <review () review ! haiku-os ! org>
Date: 2020-02-27 23:25:00
Message-ID: gerrit.1582845898000.I0161272f968db419e4b2887ddebbef90810183c4 () review ! haiku-os ! org
[Download RAW message or body]
From John Scipione <jscipione@gmail.com>:
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@gmail.com>
Gerrit-MessageType: newchange
[Attachment #3 (text/html)]
<p>John Scipione has uploaded this change for <strong>review</strong>.</p><p><a \
href="https://review.haiku-os.org/c/haiku/+/2289">View Change</a></p><pre \
style="font-family: monospace,monospace; white-space: pre-wrap;">BPopUpMenu: Call \
MenusBeginning() and MenusEnded() hook methods<br><br>... when opening and closing a \
BPopUpMenu that isn't attached to a BMenuBar<br>asynchronously. Check to see if \
we are attached to a BMenuBar first because<br>if we are attached to a BMenuBar (as \
is the case for example in a BMenuField)<br>the BMenuBar will call MenusBeginning() \
and MenuEnding() for us. Create<br>private static class method _HasMenuBar() for this \
purpose.<br><br>Update documentation for BWindow::MenusBeginning() and \
BWindow::MenusEnded().<br>---<br>M docs/user/interface/Window.dox<br>M \
headers/os/interface/PopUpMenu.h<br>M src/kits/interface/PopUpMenu.cpp<br>3 files \
changed, 48 insertions(+), 10 deletions(-)<br><br></pre><pre style="font-family: \
monospace,monospace; white-space: pre-wrap;">git pull ssh://git.haiku-os.org:22/haiku \
refs/changes/89/2289/1</pre><pre style="font-family: monospace,monospace; \
white-space: pre-wrap;"><span>diff --git a/docs/user/interface/Window.dox \
b/docs/user/interface/Window.dox</span><br><span>index 89f0960..8886305 \
100644</span><br><span>--- a/docs/user/interface/Window.dox</span><br><span>+++ \
b/docs/user/interface/Window.dox</span><br><span>@@ -1046,11 +1046,12 \
@@</span><br><span> </span><br><span> /*!</span><br><span> \fn void \
BWindow::MenusBeginning()</span><br><span style="color: hsl(0, 100%, 40%);">- \brief \
Hook method that gets called just before a menu owned by the window \
is</span><br><span style="color: hsl(0, 100%, 40%);">- shown.</span><br><span \
style="color: hsl(120, 100%, 40%);">+ \brief Hook method that gets called just before \
an asynchronous pop-up</span><br><span style="color: hsl(120, 100%, 40%);">+ \
menu or a menu attached to a menu bar owned by the window is</span><br><span \
style="color: hsl(120, 100%, 40%);">+ opened.</span><br><span> \
</span><br><span> \note This method is not invoked by a message, there is \
no</span><br><span style="color: hsl(0, 100%, 40%);">- \c B_MENUS_BEGINNING \
flag.</span><br><span style="color: hsl(120, 100%, 40%);">+ \c \
B_MENUS_BEGINNING or \c _MENUS_BEGUN_ command.</span><br><span> </span><br><span> \
\since BeOS R3</span><br><span> */</span><br><span>@@ -1058,11 +1059,12 \
@@</span><br><span> </span><br><span> /*!</span><br><span> \fn void \
BWindow::MenusEnded()</span><br><span style="color: hsl(0, 100%, 40%);">- \brief Hook \
method that gets called just before a menu owned by the window is</span><br><span \
style="color: hsl(0, 100%, 40%);">- hidden.</span><br><span style="color: \
hsl(120, 100%, 40%);">+ \brief Hook method that gets called just after an \
asynchronous pop-up</span><br><span style="color: hsl(120, 100%, 40%);">+ menu \
or a menu attached to a menu bar owned by the window is</span><br><span style="color: \
hsl(120, 100%, 40%);">+ closed.</span><br><span> </span><br><span \
style="color: hsl(0, 100%, 40%);">- \note This method is not invoked by a message, \
there is no</span><br><span style="color: hsl(0, 100%, 40%);">- \c \
B_MENUS_ENDED flag.</span><br><span style="color: hsl(120, 100%, 40%);">+ You may \
invoke this method from another thread by sending a message</span><br><span \
style="color: hsl(120, 100%, 40%);">+ to the window with the \c _MENUS_DONE_ command \
(defined in AppDefs.h).</span><br><span> </span><br><span> \since BeOS \
R3</span><br><span> */</span><br><span>diff --git a/headers/os/interface/PopUpMenu.h \
b/headers/os/interface/PopUpMenu.h</span><br><span>index 2ecf6dd..36d82bd \
100644</span><br><span>--- a/headers/os/interface/PopUpMenu.h</span><br><span>+++ \
b/headers/os/interface/PopUpMenu.h</span><br><span>@@ -74,6 +74,8 @@</span><br><span> \
</span><br><span> static int32 _thread_entry(void* menuData);</span><br><span> \
</span><br><span style="color: hsl(120, 100%, \
40%);">+ static bool _HasMenuBar(BPopUpMenu* popUpMenu);</span><br><span \
style="color: hsl(120, 100%, 40%);">+</span><br><span> private:</span><br><span> \
BPoint fWhere;</span><br><span> bool fUseWhere;</span><br><span>diff --git \
a/src/kits/interface/PopUpMenu.cpp \
b/src/kits/interface/PopUpMenu.cpp</span><br><span>index 7b94b38..c608b92 \
100644</span><br><span>--- a/src/kits/interface/PopUpMenu.cpp</span><br><span>+++ \
b/src/kits/interface/PopUpMenu.cpp</span><br><span>@@ -10,6 +10,7 @@</span><br><span> \
</span><br><span> #include <Application.h></span><br><span> #include \
<Looper.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include \
<MenuBar.h></span><br><span> #include <MenuItem.h></span><br><span> \
#include <PopUpMenu.h></span><br><span> #include \
<Window.h></span><br><span>@@ -347,14 +348,17 @@</span><br><span> // Get a \
pointer to the window from which Go() was called</span><br><span> BWindow* \
window</span><br><span> = \
dynamic_cast<BWindow*>(BLooper::LooperForThread(find_thread(NULL)));</span><br><span \
style="color: hsl(0, 100%, 40%);">- data->window = window;</span><br><span> \
</span><br><span> // Asynchronous menu: we set the BWindow menu's \
semaphore</span><br><span> // and let BWindow block when needed</span><br><span \
style="color: hsl(0, 100%, 40%);">- if (async && window != \
NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (async && \
window != NULL) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if \
(!_HasMenuBar(this))</span><br><span style="color: hsl(120, 100%, \
40%);">+ window->MenusBeginning();</span><br><span> _set_menu_sem_(window, \
sem);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> \
</span><br><span> data->object = this;</span><br><span style="color: hsl(120, \
100%, 40%);">+ data->window = window;</span><br><span> data->autoInvoke = \
autoInvoke;</span><br><span> data->useRect = _specialRect != \
NULL;</span><br><span> if (_specialRect != NULL)</span><br><span>@@ -400,9 +404,13 \
@@</span><br><span> data->selected = menu->_StartTrack(data->where, \
data->autoInvoke,</span><br><span> data->startOpened, rect);</span><br><span> \
</span><br><span style="color: hsl(120, 100%, 40%);">+ // We aren't the BWindow \
thread, so don't call MenusEnded() directly.</span><br><span> // Reset the \
window menu semaphore</span><br><span style="color: hsl(0, 100%, 40%);">- if \
(data->async && data->window)</span><br><span style="color: hsl(120, \
100%, 40%);">+ if (data->async && data->window) {</span><br><span \
style="color: hsl(120, 100%, 40%);">+ if \
(!_HasMenuBar(data->object))</span><br><span style="color: hsl(120, 100%, \
40%);">+ data->window->PostMessage(_MENUS_DONE_);</span><br><span> \
_set_menu_sem_(data->window, B_BAD_SEM_ID);</span><br><span style="color: hsl(120, \
100%, 40%);">+ }</span><br><span> </span><br><span> \
delete_sem(data->lock);</span><br><span> </span><br><span>@@ -479,3 +487,29 \
@@</span><br><span> </span><br><span> return selected;</span><br><span> \
}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: \
hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* \
static */</span><br><span style="color: hsl(120, 100%, 40%);">+bool</span><br><span \
style="color: hsl(120, 100%, 40%);">+BPopUpMenu::_HasMenuBar(BPopUpMenu* \
popUpMenu)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span \
style="color: hsl(120, 100%, 40%);">+ if (popUpMenu == NULL)</span><br><span \
style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: \
hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // we \
have a pop up menu;</span><br><span style="color: hsl(120, 100%, \
40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ BMenu* menu = \
static_cast<BMenu*>(popUpMenu);</span><br><span style="color: hsl(120, 100%, \
40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // we have a menu, \
static_cast to an inherited class is guaranteed to pass</span><br><span style="color: \
hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ BMenu* \
_menu;</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((_menu = \
menu->Supermenu()) != NULL)</span><br><span style="color: hsl(120, 100%, \
40%);">+ menu = _menu;</span><br><span style="color: hsl(120, 100%, \
40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // went up the \
hierarchy and found the topmost menu ancestor</span><br><span style="color: hsl(120, \
100%, 40%);">+ // (possibly ourself)</span><br><span style="color: hsl(120, 100%, \
40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return \
dynamic_cast<BMenuBar*>(menu) != NULL;</span><br><span style="color: hsl(120, \
100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ // our topmost \
menu ancestor has been determined to be a BMenuBar or not</span><br><span \
style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, \
visit <a href="https://review.haiku-os.org/c/haiku/+/2289">change 2289</a>. To \
unsubscribe, or for help writing mail filters, visit <a \
href="https://review.haiku-os.org/settings">settings</a>.</p><div itemscope \
itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" \
itemtype="http://schema.org/ViewAction"><link itemprop="url" \
href="https://review.haiku-os.org/c/haiku/+/2289"/><meta itemprop="name" \
content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: haiku </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: \
I0161272f968db419e4b2887ddebbef90810183c4 </div> <div style="display:none"> \
Gerrit-Change-Number: 2289 </div> <div style="display:none"> Gerrit-PatchSet: 1 \
</div> <div style="display:none"> Gerrit-Owner: John Scipione \
<jscipione@gmail.com> </div> <div style="display:none"> Gerrit-MessageType: \
newchange </div>
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic