diff --git a/include/wx/taskbar.h b/include/wx/taskbar.h index c209a1027b..1911e65cf8 100644 --- a/include/wx/taskbar.h +++ b/include/wx/taskbar.h @@ -62,6 +62,9 @@ protected: // creates menu to be displayed when user clicks on the icon virtual wxMenu *CreatePopupMenu() { return NULL; } + // same as CreatePopupMenu but won't destroy the menu + virtual wxMenu *GetPopupMenu() { return NULL; } + private: // default events handling, calls CreatePopupMenu: void OnRightButtonDown(wxTaskBarIconEvent& event); diff --git a/interface/wx/taskbar.h b/interface/wx/taskbar.h index a7ad602dd9..b0c2ce300c 100644 --- a/interface/wx/taskbar.h +++ b/interface/wx/taskbar.h @@ -62,8 +62,9 @@ public: @beginEventEmissionTable{wxTaskBarIconEvent} Note that not all ports are required to send these events and so it's better - to override wxTaskBarIcon::CreatePopupMenu() if all that the application does - is that it shows a popup menu in reaction to mouse click. + to override wxTaskBarIcon::CreatePopupMenu() or wxTaskBarIcon::GetPopupMenu() + if all that the application does is that it shows a popup menu in reaction to + mouse click. @event{EVT_TASKBAR_MOVE(func)} Process a @c wxEVT_TASKBAR_MOVE event. @event{EVT_TASKBAR_LEFT_DOWN(func)} @@ -123,9 +124,10 @@ public: The events can be handled by a class derived from wxTaskBarIcon. @note - It is recommended to override CreatePopupMenu() callback instead of - calling this method from event handler, because some ports (e.g. wxCocoa) - may not implement PopupMenu() and mouse click events at all. + It is recommended to override the CreatePopupMenu() or GetPopupMenu() + callback instead of calling this method from event handler, because some + ports (e.g. wxCocoa) may not implement PopupMenu() and mouse click events + at all. */ virtual bool PopupMenu(wxMenu* menu); @@ -172,11 +174,25 @@ protected: Override this function in order to provide popup menu associated with the icon. If CreatePopupMenu() returns @NULL (this happens by default), no menu is shown, otherwise the menu is displayed and then deleted by the library as soon as the - user dismisses it. + user dismisses it. If you don't want the menu to get destroyed when it is dismissed, + override GetPopupMenu() instead. The events can be handled by a class derived from wxTaskBarIcon. */ virtual wxMenu* CreatePopupMenu(); + + /** + This method is called by the library when the user requests popup menu + (on Windows and Unix platforms, this is when the user right-clicks the icon). + + Override this function in order to provide popup menu associated with the icon. + If GetPopupMenu() returns @NULL (this happens by default), no menu is shown, + otherwise the menu is displayed. In contrast to CreatePopupMenu(), GetPopupMenu() + won't destroy the menu once the user dismisses it. + + The events can be handled by a class derived from wxTaskBarIcon. + */ + virtual wxMenu* GetPopupMenu(); }; diff --git a/src/common/taskbarcmn.cpp b/src/common/taskbarcmn.cpp index cc5908ad06..7bf7c6a58e 100644 --- a/src/common/taskbarcmn.cpp +++ b/src/common/taskbarcmn.cpp @@ -53,6 +53,13 @@ void wxTaskBarIconBase::OnRightButtonDown(wxTaskBarIconEvent& WXUNUSED(event)) PopupMenu(menu); delete menu; } + else + { + menu = GetPopupMenu(); + + if (menu) + PopupMenu(menu); + } } void wxTaskBarIconBase::Destroy() diff --git a/src/osx/cocoa/taskbar.mm b/src/osx/cocoa/taskbar.mm index df66491361..fb263e5565 100644 --- a/src/osx/cocoa/taskbar.mm +++ b/src/osx/cocoa/taskbar.mm @@ -68,6 +68,8 @@ public: inline wxTaskBarIcon* GetTaskBarIcon() { return m_taskBarIcon; } wxMenu * CreatePopupMenu() { return m_taskBarIcon->CreatePopupMenu(); } + wxMenu * GetPopupMenu() + { return m_taskBarIcon->GetPopupMenu(); } wxDECLARE_NO_COPY_CLASS(wxTaskBarIconImpl); @@ -100,6 +102,7 @@ protected: private: wxTaskBarIconDockImpl(); wxMenu *m_pMenu; + bool m_keepMenu; }; class wxTaskBarIconCustomStatusItemImpl; @@ -228,6 +231,7 @@ wxTaskBarIconDockImpl::wxTaskBarIconDockImpl(wxTaskBarIcon *taskBarIcon) wxASSERT_MSG(!sm_dockIcon, wxT("You should never have more than one dock icon!")); sm_dockIcon = this; m_pMenu = NULL; + m_keepMenu = false; } wxTaskBarIconDockImpl::~wxTaskBarIconDockImpl() @@ -247,13 +251,27 @@ WX_NSMenu wxTaskBarIconDockImpl::OSXGetDockHMenu() WX_NSMenu wxTaskBarIconDockImpl::OSXDoGetDockHMenu() { wxMenu *dockMenu = CreatePopupMenu(); + bool keepMenu; if(!dockMenu) - return nil; + { + dockMenu = GetPopupMenu(); + + if(!dockMenu) + return nil; - wxDELETE(m_pMenu); + keepMenu = true; + } + else + { + keepMenu = false; + } + + if(!m_keepMenu) + wxDELETE(m_pMenu); m_pMenu = dockMenu; + m_keepMenu = keepMenu; m_pMenu->SetInvokingWindow(m_eventWindow); @@ -271,7 +289,9 @@ bool wxTaskBarIconDockImpl::SetIcon(const wxIcon& icon, const wxString& WXUNUSED bool wxTaskBarIconDockImpl::RemoveIcon() { - wxDELETE(m_pMenu); + if(!m_keepMenu) + wxDELETE(m_pMenu); + m_icon = wxBitmap(); [[NSApplication sharedApplication] setApplicationIconImage:nil]; return true;