have it work the old way with PopupMenu(), and have it restore the old menu on destruction (and hopefully when RemoveIcon() is called
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@29558 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -53,6 +53,7 @@ protected:
|
|||||||
wxTaskBarIconType m_nType;
|
wxTaskBarIconType m_nType;
|
||||||
void* m_pEventHandlerRef;
|
void* m_pEventHandlerRef;
|
||||||
wxMenu* m_pMenu;
|
wxMenu* m_pMenu;
|
||||||
|
WXHMENU m_theLastMenu;
|
||||||
bool m_iconAdded;
|
bool m_iconAdded;
|
||||||
|
|
||||||
DECLARE_DYNAMIC_CLASS(wxTaskBarIcon)
|
DECLARE_DYNAMIC_CLASS(wxTaskBarIcon)
|
||||||
|
@@ -20,13 +20,8 @@
|
|||||||
#include "wx/taskbar.h"
|
#include "wx/taskbar.h"
|
||||||
#include "wx/menu.h"
|
#include "wx/menu.h"
|
||||||
#include "wx/icon.h"
|
#include "wx/icon.h"
|
||||||
|
#include "wx/dcmemory.h"
|
||||||
|
|
||||||
//
|
|
||||||
//TODO: Implement Apple Software Guidelines - show the top window it it's not shown,
|
|
||||||
//and force it to be unminimized - and all unminimized windows should be brought to
|
|
||||||
//the front
|
|
||||||
//
|
|
||||||
//TODO:
|
|
||||||
IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
|
IMPLEMENT_DYNAMIC_CLASS(wxTaskBarIcon, wxEvtHandler)
|
||||||
|
|
||||||
pascal OSStatus wxDockEventHandler( EventHandlerCallRef inHandlerCallRef,
|
pascal OSStatus wxDockEventHandler( EventHandlerCallRef inHandlerCallRef,
|
||||||
@@ -39,61 +34,65 @@ pascal OSStatus wxDockEventHandler( EventHandlerCallRef inHandlerCallRef,
|
|||||||
|
|
||||||
if (eventClass == kEventClassCommand && eventKind == kEventCommandProcess)
|
if (eventClass == kEventClassCommand && eventKind == kEventCommandProcess)
|
||||||
{
|
{
|
||||||
//TODO:
|
//TODO: This is a complete copy of
|
||||||
//TODO: This is a complete copy of
|
//static pascal OSStatus wxMacAppCommandEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
|
||||||
//static pascal OSStatus wxMacAppCommandEventHandler( EventHandlerCallRef handler , EventRef event , void *data )
|
|
||||||
//FIND A WAY TO EXTERN THIS AND USE THAT HERE INSTEAD!!
|
|
||||||
//TODO:
|
|
||||||
MenuRef hMenu = MAC_WXHMENU(pTB->GetCurrentMenu()->GetHMenu());
|
|
||||||
OSStatus result = eventNotHandledErr ;
|
|
||||||
|
|
||||||
HICommand command ;
|
MenuRef hMenu = MAC_WXHMENU(pTB->GetCurrentMenu()->GetHMenu());
|
||||||
OSErr err;
|
OSStatus result = eventNotHandledErr ;
|
||||||
|
|
||||||
err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand,
|
HICommand command ;
|
||||||
|
OSErr err;
|
||||||
|
|
||||||
|
err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand,
|
||||||
NULL, sizeof(HICommand), NULL, &command);
|
NULL, sizeof(HICommand), NULL, &command);
|
||||||
wxASSERT(err == noErr);
|
wxASSERT(err == noErr);
|
||||||
|
|
||||||
MenuItemIndex menuItemIndex;
|
MenuItemIndex menuItemIndex;
|
||||||
err = GetIndMenuItemWithCommandID(hMenu, command.commandID, 1, NULL, &menuItemIndex);
|
err = GetIndMenuItemWithCommandID(hMenu, command.commandID, 1, NULL, &menuItemIndex);
|
||||||
wxASSERT(err == noErr);
|
wxASSERT(err == noErr);
|
||||||
|
|
||||||
|
|
||||||
MenuCommand id = command.commandID ;
|
MenuCommand id = command.commandID ;
|
||||||
wxMenuItem* item = NULL;
|
wxMenuItem* item = NULL;
|
||||||
// for items we don't really control
|
|
||||||
if ( id == kHICommandPreferences )
|
|
||||||
{
|
|
||||||
id = wxApp::s_macPreferencesMenuItemId ;
|
|
||||||
|
|
||||||
wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
|
// for items we don't really control
|
||||||
if ( mbar )
|
if ( id == kHICommandPreferences )
|
||||||
{
|
{
|
||||||
wxMenu* menu = NULL ;
|
id = wxApp::s_macPreferencesMenuItemId ;
|
||||||
item = mbar->FindItem( id , &menu ) ;
|
|
||||||
|
wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ;
|
||||||
|
|
||||||
|
if ( mbar )
|
||||||
|
{
|
||||||
|
wxMenu* menu = NULL ;
|
||||||
|
item = mbar->FindItem( id , &menu ) ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (id != 0)
|
||||||
else if (id != 0)
|
GetMenuItemRefCon( hMenu , menuItemIndex , (UInt32*) &item ) ;
|
||||||
GetMenuItemRefCon( hMenu , menuItemIndex , (UInt32*) &item ) ;
|
|
||||||
|
|
||||||
if ( item )
|
if ( item )
|
||||||
{
|
|
||||||
if (item->IsCheckable())
|
|
||||||
{
|
{
|
||||||
item->Check( !item->IsChecked() ) ;
|
if (item->IsCheckable())
|
||||||
|
{
|
||||||
|
item->Check( !item->IsChecked() ) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
item->GetMenu()->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
|
||||||
|
result = noErr ;
|
||||||
}
|
}
|
||||||
|
|
||||||
item->GetMenu()->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ;
|
return result ;
|
||||||
result = noErr ;
|
|
||||||
}
|
|
||||||
return result ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wxASSERT(eventClass == kEventClassApplication && eventKind == kEventAppGetDockTileMenu);
|
wxASSERT(eventClass == kEventClassApplication && eventKind == kEventAppGetDockTileMenu);
|
||||||
|
|
||||||
//process the right click event
|
//process the right click events
|
||||||
wxTaskBarIconEvent evt(wxEVT_TASKBAR_RIGHT_UP,NULL);
|
wxTaskBarIconEvent downevt(wxEVT_TASKBAR_RIGHT_DOWN,NULL);
|
||||||
pTB->ProcessEvent(evt);
|
pTB->ProcessEvent(downevt);
|
||||||
|
|
||||||
|
wxTaskBarIconEvent upevt(wxEVT_TASKBAR_RIGHT_UP,NULL);
|
||||||
|
pTB->ProcessEvent(upevt);
|
||||||
|
|
||||||
//create popup menu
|
//create popup menu
|
||||||
wxMenu* menu = pTB->DoCreatePopupMenu();
|
wxMenu* menu = pTB->DoCreatePopupMenu();
|
||||||
@@ -115,15 +114,18 @@ pascal OSStatus wxDockEventHandler( EventHandlerCallRef inHandlerCallRef,
|
|||||||
typeMenuRef, sizeof(MenuRef),
|
typeMenuRef, sizeof(MenuRef),
|
||||||
&hMenu);
|
&hMenu);
|
||||||
wxASSERT(err == 0);
|
wxASSERT(err == 0);
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return eventNotHandledErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_ONE_SHOT_HANDLER_GETTER( wxDockEventHandler );
|
DEFINE_ONE_SHOT_HANDLER_GETTER( wxDockEventHandler );
|
||||||
|
|
||||||
wxTaskBarIcon::wxTaskBarIcon(const wxTaskBarIconType& nType)
|
wxTaskBarIcon::wxTaskBarIcon(const wxTaskBarIconType& nType)
|
||||||
: m_nType(nType), m_pEventHandlerRef(NULL), m_pMenu(NULL), m_iconAdded(false)
|
: m_nType(nType), m_pEventHandlerRef(NULL), m_pMenu(NULL),
|
||||||
|
m_theLastMenu((WXHMENU)GetApplicationDockTileMenu()), m_iconAdded(false)
|
||||||
{
|
{
|
||||||
//Register the events that will return the dock menu
|
//Register the events that will return the dock menu
|
||||||
EventTypeSpec tbEventList[] = { { kEventClassCommand, kEventProcessCommand },
|
EventTypeSpec tbEventList[] = { { kEventClassCommand, kEventProcessCommand },
|
||||||
@@ -142,7 +144,11 @@ wxTaskBarIcon::wxTaskBarIcon(const wxTaskBarIconType& nType)
|
|||||||
|
|
||||||
wxTaskBarIcon::~wxTaskBarIcon()
|
wxTaskBarIcon::~wxTaskBarIcon()
|
||||||
{
|
{
|
||||||
|
//clean up event handler
|
||||||
RemoveEventHandler((EventHandlerRef&)m_pEventHandlerRef);
|
RemoveEventHandler((EventHandlerRef&)m_pEventHandlerRef);
|
||||||
|
|
||||||
|
//restore old icon and menu to the dock
|
||||||
|
RemoveIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMenu* wxTaskBarIcon::GetCurrentMenu()
|
wxMenu* wxTaskBarIcon::GetCurrentMenu()
|
||||||
@@ -152,13 +158,14 @@ wxMenu* wxTaskBarIcon::GetCurrentMenu()
|
|||||||
|
|
||||||
wxMenu* wxTaskBarIcon::DoCreatePopupMenu()
|
wxMenu* wxTaskBarIcon::DoCreatePopupMenu()
|
||||||
{
|
{
|
||||||
if (m_pMenu)
|
wxMenu* theNewMenu = CreatePopupMenu();
|
||||||
|
|
||||||
|
if (theNewMenu)
|
||||||
|
{
|
||||||
delete m_pMenu;
|
delete m_pMenu;
|
||||||
|
m_pMenu = theNewMenu;
|
||||||
m_pMenu = CreatePopupMenu();
|
|
||||||
|
|
||||||
if (m_pMenu)
|
|
||||||
m_pMenu->SetEventHandler(this);
|
m_pMenu->SetEventHandler(this);
|
||||||
|
}
|
||||||
|
|
||||||
return m_pMenu;
|
return m_pMenu;
|
||||||
}
|
}
|
||||||
@@ -205,23 +212,71 @@ bool wxTaskBarIcon::SetIcon(const wxIcon& icon, const wxString& tooltip)
|
|||||||
|
|
||||||
bool wxTaskBarIcon::RemoveIcon()
|
bool wxTaskBarIcon::RemoveIcon()
|
||||||
{
|
{
|
||||||
OSStatus err = RestoreApplicationDockTileImage();
|
if(m_pMenu)
|
||||||
wxASSERT(err == 0);
|
{
|
||||||
|
delete m_pMenu;
|
||||||
|
m_pMenu = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
//restore old icon to the dock
|
||||||
|
OSStatus err = RestoreApplicationDockTileImage();
|
||||||
|
wxASSERT(err == 0);
|
||||||
|
|
||||||
|
//restore the old menu to the dock
|
||||||
|
SetApplicationDockTileMenu(MAC_WXHMENU(m_theLastMenu));
|
||||||
|
|
||||||
return !(m_iconAdded = !(err == noErr));
|
return !(m_iconAdded = !(err == noErr));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
|
bool wxTaskBarIcon::PopupMenu(wxMenu *menu)
|
||||||
{
|
{
|
||||||
|
wxASSERT(menu != NULL);
|
||||||
|
|
||||||
if (m_pMenu)
|
if (m_pMenu)
|
||||||
|
{
|
||||||
delete m_pMenu;
|
delete m_pMenu;
|
||||||
|
m_pMenu = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
m_pMenu = menu;
|
//
|
||||||
|
// NB: Here we have to perform a deep copy of the menu,
|
||||||
|
// copying each and every menu item from menu to m_pMenu.
|
||||||
|
// Other implementations use wxWindow::PopupMenu here,
|
||||||
|
// which idle execution until the user selects something,
|
||||||
|
// but since the mac handles this internally, we can't -
|
||||||
|
// and have no way at all to idle it while the dock menu
|
||||||
|
// is being shown before menu goes out of scope (it may
|
||||||
|
// not be on the heap, and may expire right after this function
|
||||||
|
// is done - we need it to last until the carbon event is triggered -
|
||||||
|
// that's when the user right clicks).
|
||||||
|
//
|
||||||
|
// Also, since there is no equal (assignment) operator
|
||||||
|
// on either wxMenu or wxMenuItem, we have to do all the
|
||||||
|
// dirty work ourselves.
|
||||||
|
//
|
||||||
|
|
||||||
|
//Perform a deep copy of the menu
|
||||||
|
wxMenuItemList& theList = menu->GetMenuItems();
|
||||||
|
wxMenuItemList::compatibility_iterator theNode = theList.GetFirst();
|
||||||
|
|
||||||
|
//create the main menu
|
||||||
|
m_pMenu = new wxMenu(menu->GetTitle());
|
||||||
|
|
||||||
|
while(theNode != NULL)
|
||||||
|
{
|
||||||
|
wxMenuItem* theItem = theNode->GetData();
|
||||||
|
m_pMenu->Append(new wxMenuItem( m_pMenu, //parent menu
|
||||||
|
theItem->GetId(), //id
|
||||||
|
theItem->GetText(), //text label
|
||||||
|
theItem->GetHelp(), //status bar help string
|
||||||
|
theItem->GetKind(), //menu flags - checkable, seperator, etc.
|
||||||
|
theItem->GetSubMenu() //submenu
|
||||||
|
));
|
||||||
|
theNode = theNode->GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
wxASSERT(menu);
|
|
||||||
m_pMenu->SetEventHandler(this);
|
m_pMenu->SetEventHandler(this);
|
||||||
|
return true;
|
||||||
return SetApplicationDockTileMenu(MAC_WXHMENU(menu->GetHMenu()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //wxHAS_TASK_BAR_ICON
|
#endif //wxHAS_TASK_BAR_ICON
|
||||||
|
Reference in New Issue
Block a user