diff --git a/include/wx/menu.h b/include/wx/menu.h index 5e318efac6..accb6f1d7e 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 78bc7c5747..05ceafc5ca 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 fdeecde222..dda9325346 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 3bd97fb96f..e1b0b87036 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 a14e6b063a..5e3e83d92f 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 0d3e0b548e..aca5e608d3 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 3b8ced6092..baf0318950 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 7a44b19018..33862da5f0 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 53fb99f7f1..cd8aecdc4d 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 4714ba73f3..571761f561 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__