From c59aa14a6c1f23ddcd34822443483332a5ee81c3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 26 Apr 2010 14:19:17 +0000 Subject: [PATCH] Set popup menu invoking window in wxWindowBase and not in all ports. Don't duplicate the code for setting (and unsetting, which was forgotten by at least wxGTK) the popup menu invoking window in all ports but do it in the base class PopupMenu() itself. Also add a helper wxMenuInvokingWindowSetter class which ensures that the invoking window will be unset in any case. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64143 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/menu.h | 35 +++++++++++++++++++++++++++++++++-- src/cocoa/taskbar.mm | 6 +++--- src/common/wincmn.cpp | 3 +++ src/gtk/window.cpp | 6 ------ src/gtk1/menu.cpp | 19 ------------------- src/motif/window.cpp | 1 - src/msw/window.cpp | 3 --- src/os2/window.cpp | 2 -- src/osx/window_osx.cpp | 36 +++++++++++++++++------------------- src/univ/menu.cpp | 6 ------ 10 files changed, 56 insertions(+), 61 deletions(-) diff --git a/include/wx/menu.h b/include/wx/menu.h index 5e318ef..accb6f1 100644 --- a/include/wx/menu.h +++ b/include/wx/menu.h @@ -259,6 +259,9 @@ public: // popup menu and reset after it's hidden. Notice that you probably want to // use GetWindow() below instead of GetInvokingWindow() as the latter only // returns non-NULL for the top level menus + // + // NB: avoid calling SetInvokingWindow() directly if possible, use + // wxMenuInvokingWindowSetter class below instead void SetInvokingWindow(wxWindow *win); wxWindow *GetInvokingWindow() const { return m_invokingWindow; } @@ -551,7 +554,35 @@ protected: #endif #endif // wxUSE_BASE_CLASSES_ONLY/!wxUSE_BASE_CLASSES_ONLY +// ---------------------------------------------------------------------------- +// Helper class used in the implementation only: sets the invoking window of +// the given menu in its ctor and resets it in dtor. +// ---------------------------------------------------------------------------- + +class wxMenuInvokingWindowSetter +{ +public: + // Ctor sets the invoking window for the given menu. + // + // The menu lifetime must be greater than that of this class. + wxMenuInvokingWindowSetter(wxMenu& menu, wxWindow *win) + : m_menu(menu) + { + menu.SetInvokingWindow(win); + } + + // Dtor resets the invoking window. + ~wxMenuInvokingWindowSetter() + { + m_menu.SetInvokingWindow(NULL); + } + +private: + wxMenu& m_menu; + + wxDECLARE_NO_COPY_CLASS(wxMenuInvokingWindowSetter); +}; + #endif // wxUSE_MENUS -#endif - // _WX_MENU_H_BASE_ +#endif // _WX_MENU_H_BASE_ diff --git a/src/cocoa/taskbar.mm b/src/cocoa/taskbar.mm index 78bc7c5..05ceafc 100644 --- a/src/cocoa/taskbar.mm +++ b/src/cocoa/taskbar.mm @@ -311,8 +311,9 @@ bool wxTaskBarIconCustomStatusItemImpl::RemoveIcon() bool wxTaskBarIconCustomStatusItemImpl::PopupMenu(wxMenu *menu) { - wxASSERT(menu); - menu->SetInvokingWindow(m_iconWindow); + wxCHECK_MSG(menu, false, "can't popup a NULL menu"); + + wxMenuInvokingWindowSetter setInvokingWin(*menu, m_iconWindow); menu->UpdateUI(); if([m_cocoaNSStatusItem respondsToSelector:@selector(popUpStatusItemMenu:)]) @@ -328,7 +329,6 @@ bool wxTaskBarIconCustomStatusItemImpl::PopupMenu(wxMenu *menu) eventNumber:0 clickCount:1 pressure:0.0]; [NSMenu popUpContextMenu:menu->GetNSMenu() withEvent:nsevent forView:m_iconWindow->GetNSView()]; } - menu->SetInvokingWindow(NULL); return true; } diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index fdeecde..dda9325 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -2567,6 +2567,9 @@ bool wxWindowBase::PopupMenu(wxMenu *menu, int x, int y) { wxCHECK_MSG( menu, false, "can't popup NULL menu" ); + wxMenuInvokingWindowSetter + setInvokingWin(*menu, static_cast(this)); + wxCurrentPopupMenu = menu; const bool rc = DoPopupMenu(menu, x, y); wxCurrentPopupMenu = NULL; diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 3bd97fb..e1b0b87 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -3996,10 +3996,6 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y ) { wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") ); - wxCHECK_MSG( menu != NULL, false, wxT("invalid popup-menu") ); - - menu->SetInvokingWindow( this ); - menu->UpdateUI(); wxPoint pos; @@ -4034,8 +4030,6 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y ) gtk_main_iteration(); } - menu->SetInvokingWindow( NULL ); - return true; } diff --git a/src/gtk1/menu.cpp b/src/gtk1/menu.cpp index a14e6b0..5e3e83d 100644 --- a/src/gtk1/menu.cpp +++ b/src/gtk1/menu.cpp @@ -1457,23 +1457,6 @@ void gtk_pop_hide_callback( GtkWidget *WXUNUSED(widget), bool* is_waiting ) *is_waiting = false; } -WXDLLIMPEXP_CORE void SetInvokingWindow( wxMenu *menu, wxWindow* win ) -{ - menu->SetInvokingWindow( win ); - - wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst(); - while (node) - { - wxMenuItem *menuitem = node->GetData(); - if (menuitem->IsSubMenu()) - { - SetInvokingWindow( menuitem->GetSubMenu(), win ); - } - - node = node->GetNext(); - } -} - extern "C" WXDLLIMPEXP_CORE void wxPopupMenuPositionCallback( GtkMenu *menu, gint *x, gint *y, @@ -1503,8 +1486,6 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y ) // the same code in taskbar.cpp as well. This // is ugly code duplication, I know. - SetInvokingWindow( menu, this ); - menu->UpdateUI(); bool is_waiting = true; diff --git a/src/motif/window.cpp b/src/motif/window.cpp index 0d3e0b5..aca5e60 100644 --- a/src/motif/window.cpp +++ b/src/motif/window.cpp @@ -1083,7 +1083,6 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y) menu->SetId(1); /* Mark as popped-up */ menu->CreateMenu(NULL, widget, menu, 0); - menu->SetInvokingWindow(this); menu->UpdateUI(); diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 3b8ced6..baf0318 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -2267,7 +2267,6 @@ static void wxYieldForCommandsOnly() bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) { - menu->SetInvokingWindow(this); menu->UpdateUI(); if ( x == wxDefaultCoord && y == wxDefaultCoord ) @@ -2310,8 +2309,6 @@ bool wxWindowMSW::DoPopupMenu(wxMenu *menu, int x, int y) // for example) and so we do need to process the event immediately wxYieldForCommandsOnly(); - menu->SetInvokingWindow(NULL); - return true; } diff --git a/src/os2/window.cpp b/src/os2/window.cpp index 7a44b19..33862da 100644 --- a/src/os2/window.cpp +++ b/src/os2/window.cpp @@ -1788,7 +1788,6 @@ bool wxWindowOS2::DoPopupMenu( wxMenu* pMenu, int nX, int nY ) bool bIsWaiting = true; int nHeight; - pMenu->SetInvokingWindow(this); pMenu->UpdateUI(); if ( nX == -1 && nY == -1 ) @@ -1824,7 +1823,6 @@ bool wxWindowOS2::DoPopupMenu( wxMenu* pMenu, int nX, int nY ) ::WinDispatchMsg(vHabmain, (PQMSG)&vMsg); } - pMenu->SetInvokingWindow(NULL); return true; } // end of wxWindowOS2::DoPopupMenu #endif // wxUSE_MENUS_NATIVE diff --git a/src/osx/window_osx.cpp b/src/osx/window_osx.cpp index 53fb99f..cd8aecd 100644 --- a/src/osx/window_osx.cpp +++ b/src/osx/window_osx.cpp @@ -100,7 +100,7 @@ class WXDLLIMPEXP_CORE wxBlindPlateWindow : public wxWindow { public: wxBlindPlateWindow() { Init(); } - + // Old-style constructor (no default values for coordinates to avoid // ambiguity with the new one) wxBlindPlateWindow(wxWindow *parent, @@ -109,10 +109,10 @@ public: const wxString& name = wxPanelNameStr) { Init(); - + Create(parent, wxID_ANY, wxPoint(x, y), wxSize(width, height), style, name); } - + // Constructor wxBlindPlateWindow(wxWindow *parent, wxWindowID winid = wxID_ANY, @@ -122,10 +122,10 @@ public: const wxString& name = wxPanelNameStr) { Init(); - + Create(parent, winid, pos, size, style, name); } - + // Pseudo ctor bool Create(wxWindow *parent, wxWindowID winid = wxID_ANY, @@ -136,25 +136,25 @@ public: { if ( !wxWindow::Create(parent, winid, pos, size, style, name) ) return false; - + // so that non-solid background renders correctly under GTK+: SetThemeEnabled(true); return true; } - + virtual ~wxBlindPlateWindow(); - + virtual bool AcceptsFocus() const { return false; } - + protected: // common part of all ctors void Init() { } - + DECLARE_DYNAMIC_CLASS_NO_COPY(wxBlindPlateWindow) DECLARE_EVENT_TABLE() }; @@ -415,7 +415,7 @@ void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant ) m_peer->SetData(kControlEntireControl, kControlSizeTag, &size ) ; #endif - + switch ( variant ) { case wxWINDOW_VARIANT_NORMAL : @@ -477,7 +477,7 @@ bool wxWindowMac::SetBackgroundStyle(wxBackgroundStyle style) { if ( !wxWindowBase::SetBackgroundStyle(style) ) return false; - + if ( m_peer ) m_peer->SetBackgroundStyle(style); return true; @@ -809,7 +809,6 @@ bool wxWindowMac::SetCursor(const wxCursor& cursor) bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y) { #ifndef __WXUNIVERSAL__ - menu->SetInvokingWindow((wxWindow*)this); menu->UpdateUI(); if ( x == wxDefaultCoord && y == wxDefaultCoord ) @@ -823,7 +822,6 @@ bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y) ClientToScreen( &x , &y ) ; } menu->GetPeer()->PopUp(this, x, y); - menu->SetInvokingWindow( NULL ); return true; #else // actually this shouldn't be called, because universal is having its own implementation @@ -844,7 +842,7 @@ void wxWindowMac::DoSetToolTip(wxToolTip *tooltip) if ( m_tooltip ) m_tooltip->SetWindow(this); - + if (m_peer) m_peer->SetToolTip(tooltip); } @@ -1154,16 +1152,16 @@ bool wxWindowMac::Show(bool show) m_peer->SetVisibility( show ) ; #ifdef __WXOSX_IPHONE__ - // only when there's no native event support + // only when there's no native event support if ( !IsTopLevel() ) #endif { wxShowEvent eventShow(GetId(), show); eventShow.SetEventObject(this); - + HandleWindowEvent(eventShow); } - + return true; } @@ -1629,7 +1627,7 @@ void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect) if (child->IsTopLevel()) continue; - + if ( !IsClientAreaChild(child) ) continue; diff --git a/src/univ/menu.cpp b/src/univ/menu.cpp index 4714ba7..571761f 100644 --- a/src/univ/menu.cpp +++ b/src/univ/menu.cpp @@ -2497,10 +2497,6 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y) Update(); #endif // 0 - menu->SetInvokingWindow(this); - - // wxLogDebug( "Name of invoking window %s", menu->GetInvokingWindow()->GetName().c_str() ); - menu->Popup(ClientToScreen(wxPoint(x, y)), wxSize(0,0)); // this is not very useful if the menu was popped up because of the mouse @@ -2523,8 +2519,6 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y) // remove the handler PopEventHandler(true /* delete it */); - menu->SetInvokingWindow(NULL); - #ifdef __WXMSW__ SetCursor(cursorOld); #endif // __WXMSW__ -- 2.7.4