pascal OSStatus wxDockEventHandler( EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void* pData) { wxTaskBarIcon*& pTB = (wxTaskBarIcon*&) pData; const UInt32 eventClass = GetEventClass(inEvent); const UInt32 eventKind = GetEventKind(inEvent); if (eventClass == kEventClassCommand && eventKind == kEventCommandProcess) { //TODO: This is a complete copy of //static pascal OSStatus wxMacAppCommandEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) if (! pTB->GetCurrentMenu() ) { return eventNotHandledErr; } MenuRef hMenu = MAC_WXHMENU(pTB->GetCurrentMenu()->GetHMenu()); OSStatus result = eventNotHandledErr ; HICommand command ; OSErr err; err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command); wxASSERT(err == noErr); MenuItemIndex menuItemIndex; err = GetIndMenuItemWithCommandID(hMenu, command.commandID, 1, NULL, &menuItemIndex); wxASSERT(err == noErr); MenuCommand id = command.commandID ; wxMenuItem* item = NULL; // for items we don't really control if ( id == kHICommandPreferences ) { id = wxApp::s_macPreferencesMenuItemId ; wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ; if ( mbar ) { wxMenu* menu = NULL ; item = mbar->FindItem( id , &menu ) ; } } else if (id != 0) GetMenuItemRefCon( hMenu , menuItemIndex , (UInt32*) &item ) ; if ( item ) { if (item->IsCheckable()) { item->Check( !item->IsChecked() ) ; } item->GetMenu()->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ; result = noErr ; } return result ; } wxASSERT(eventClass == kEventClassApplication && eventKind == kEventAppGetDockTileMenu); //process the right click events wxTaskBarIconEvent downevt(wxEVT_TASKBAR_RIGHT_DOWN,NULL); pTB->ProcessEvent(downevt); wxTaskBarIconEvent upevt(wxEVT_TASKBAR_RIGHT_UP,NULL); pTB->ProcessEvent(upevt); //create popup menu wxMenu* menu = pTB->DoCreatePopupMenu(); OSStatus err = noErr; if(menu) { //note to self - a MenuRef IS A MenuHandle MenuRef hMenu = MAC_WXHMENU(menu->GetHMenu()); //When we call SetEventParameter it will decrement //the reference count of the menu - we need to make //sure it stays around in the wxMenu class here RetainMenu(hMenu); //set the actual dock menu err = SetEventParameter((EventRef) inEvent, kEventParamMenuRef, typeMenuRef, sizeof(MenuRef), &hMenu); wxASSERT(err == 0); return err; } else return eventNotHandledErr; }
//----------------------------------------------------------------------------- // wxDockEventHandler // // This is the global Mac/Carbon event handler for the dock. // We need this for two reasons: // 1) To handle wxTaskBarIcon menu events (see below for why) // 2) To handle events from the dock when it requests a menu //----------------------------------------------------------------------------- pascal OSStatus wxDockEventHandler(EventHandlerCallRef WXUNUSED(inHandlerCallRef), EventRef inEvent, void *pData) { // Get the parameters we want from the event wxDockTaskBarIcon* pTB = (wxDockTaskBarIcon*) pData; const UInt32 eventClass = GetEventClass(inEvent); const UInt32 eventKind = GetEventKind(inEvent); OSStatus err = eventNotHandledErr; // Handle wxTaskBar menu events (note that this is a global event handler // so it will actually get called by all commands/menus) if ((eventClass == kEventClassCommand) && (eventKind == kEventCommandProcess || eventKind == kEventCommandUpdateStatus )) { // if we have no taskbar menu quickly pass it back to wxApp if (pTB->m_pMenu != NULL) { // This is the real reason why we need this. Normally menus // get handled in wxMacAppEventHandler // However, in the case of a taskbar menu call // command.menu.menuRef IS NULL! // Which causes the wxApp handler just to skip it. // get the HICommand from the event HICommand command; if (GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL,sizeof(HICommand), NULL, &command ) == noErr) { // Obtain the REAL menuRef and the menuItemIndex in the real menuRef // // NOTE: menuRef is generally used here for submenus, as // GetMenuItemRefCon could give an incorrect wxMenuItem if we pass // just the top level wxTaskBar menu MenuItemIndex menuItemIndex; MenuRef menuRef; MenuRef taskbarMenuRef = MAC_WXHMENU(pTB->m_pMenu->GetHMenu()); // the next command is only successful if it was a command from the taskbar menu // otherwise we pass it on if (GetIndMenuItemWithCommandID(taskbarMenuRef,command.commandID, 1, &menuRef, &menuItemIndex ) == noErr) { wxMenu* itemMenu = wxFindMenuFromMacMenu( menuRef ) ; int id = wxMacCommandToId( command.commandID ) ; wxMenuItem *item = NULL; if (id != 0) // get the wxMenuItem reference from the MenuRef GetMenuItemRefCon( menuRef, menuItemIndex, (URefCon*) &item ); if (item && itemMenu ) { if ( eventKind == kEventCommandProcess ) { if ( itemMenu->HandleCommandProcess( item ) ) err = noErr; } else if ( eventKind == kEventCommandUpdateStatus ) { if ( itemMenu->HandleCommandUpdateStatus( item ) ) err = noErr; } } } } } //end if noErr on getting HICommand from event } else if ((eventClass == kEventClassApplication) && (eventKind == kEventAppGetDockTileMenu )) { // process the right click events // NB: This may result in double or even triple-creation of the menus // We need to do this for 2.4 compat, however wxTaskBarIconEvent downevt(wxEVT_TASKBAR_RIGHT_DOWN, NULL); pTB->m_parent->ProcessEvent(downevt); wxTaskBarIconEvent upevt(wxEVT_TASKBAR_RIGHT_UP, NULL); pTB->m_parent->ProcessEvent(upevt); // create popup menu wxMenu* menu = pTB->DoCreatePopupMenu(); if (menu != NULL) { // note to self - a MenuRef *is* a MenuHandle MenuRef hMenu = MAC_WXHMENU(menu->GetHMenu()); // When SetEventParameter is called it will decrement // the reference count of the menu - we need to make // sure it stays around in the wxMenu class here CFRetain(hMenu); // set the actual dock menu err = SetEventParameter( inEvent, kEventParamMenuRef, typeMenuRef, sizeof(MenuRef), &hMenu ); verify_noerr( err ); } } return err; }
//----------------------------------------------------------------------------- // wxDockEventHandler // // This is the global Mac/Carbon event handler for the dock. // We need this for two reasons: // 1) To handle wxTaskBarIcon menu events (see below for why) // 2) To handle events from the dock when it requests a menu //----------------------------------------------------------------------------- pascal OSStatus wxDockEventHandler( EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *pData ) { // Get the parameters we want from the event wxDockTaskBarIcon* pTB = (wxDockTaskBarIcon*) pData; const UInt32 eventClass = GetEventClass(inEvent); const UInt32 eventKind = GetEventKind(inEvent); // Handle wxTaskBar menu events (note that this is a global event handler // so it will actually get called by all commands/menus) if ((eventClass == kEventClassCommand) && (eventKind == kEventCommandProcess)) { // if we have no taskbar menu quickly pass it back to wxApp if (pTB->m_pMenu == NULL) return eventNotHandledErr; // This is the real reason why we need this. Normally menus // get handled in wxMacAppEventHandler // // pascal OSStatus wxMacAppEventHandler(EventHandlerCallRef handler, // EventRef event, void *data) // // However, in the case of a taskbar menu call // command.menu.menuRef IS NULL! // Which causes the wxApp handler just to skip it. MenuRef taskbarMenuRef = MAC_WXHMENU(pTB->m_pMenu->GetHMenu()); OSStatus err; // get the HICommand from the event HICommand command; err = GetEventParameter( inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &command ); if (err == noErr) { // Obtain the REAL menuRef and the menuItemIndex in the real menuRef // // NOTE: menuRef is generally used here for submenus, as // GetMenuItemRefCon could give an incorrect wxMenuItem if we pass // just the top level wxTaskBar menu MenuItemIndex menuItemIndex; MenuRef menuRef; err = GetIndMenuItemWithCommandID( taskbarMenuRef, command.commandID, 1, &menuRef, &menuItemIndex ); if (err == noErr) { MenuCommand id = command.commandID; wxMenuItem *item = NULL; if (id != 0) // get the wxMenuItem reference from the MenuRef GetMenuItemRefCon( menuRef, menuItemIndex, (URefCon*) &item ); if (item) { // Handle items that are checkable // FIXME: Doesn't work (at least on 10.2)! if (item->IsCheckable()) item->Check( !item->IsChecked() ); // send the wxEvent to the wxMenu item->GetMenu()->SendEvent( id, item->IsCheckable() ? item->IsChecked() : -1 ); // successfully handled the event err = noErr; } } } //end if noErr on getting HICommand from event // return whether we handled the event or not return err; } // We better have a kEventClassApplication/kEventAppGetDockTileMenu combo here, // otherwise something is truly funky wxASSERT(eventClass == kEventClassApplication && eventKind == kEventAppGetDockTileMenu); // process the right click events // NB: This may result in double or even triple-creation of the menus // We need to do this for 2.4 compat, however wxTaskBarIconEvent downevt(wxEVT_TASKBAR_RIGHT_DOWN, NULL); pTB->m_parent->ProcessEvent(downevt); wxTaskBarIconEvent upevt(wxEVT_TASKBAR_RIGHT_UP, NULL); pTB->m_parent->ProcessEvent(upevt); // create popup menu wxMenu* menu = pTB->DoCreatePopupMenu(); OSStatus err = eventNotHandledErr; if (menu != NULL) { // note to self - a MenuRef *is* a MenuHandle MenuRef hMenu = MAC_WXHMENU(menu->GetHMenu()); // When SetEventParameter is called it will decrement // the reference count of the menu - we need to make // sure it stays around in the wxMenu class here CFRetain(hMenu); // set the actual dock menu err = SetEventParameter( inEvent, kEventParamMenuRef, typeMenuRef, sizeof(MenuRef), &hMenu ); verify_noerr( err ); } return err; }