IPopupMenu* IGraphicsCarbon::CreateIPopupMenu(IPopupMenu* pMenu, IRECT* pAreaRect) { // Get the plugin gui frame rect within the host's window HIRect rct; HIViewGetFrame(this->mView, &rct); // Get the host's window rect within the screen Rect wrct; GetWindowBounds(this->mWindow, kWindowContentRgn, &wrct); #ifdef RTAS_API int xpos = wrct.left + this->GetLeftOffset() + pAreaRect->L; int ypos = wrct.top + this->GetTopOffset() + pAreaRect->B + 5; #else HIViewRef contentView; HIViewFindByID(HIViewGetRoot(this->mWindow), kHIViewWindowContentID, &contentView); HIViewConvertRect(&rct, HIViewGetSuperview((HIViewRef)this->mView), contentView); int xpos = wrct.left + rct.origin.x + pAreaRect->L; int ypos = wrct.top + rct.origin.y + pAreaRect->B + 5; #endif MenuRef menuRef = CreateMenu(pMenu); if (menuRef) { int32_t popUpItem = 1; int32_t PopUpMenuItem = PopUpMenuSelect(menuRef, ypos, xpos, popUpItem); short result = LoWord(PopUpMenuItem) - 1; short menuIDResult = HiWord(PopUpMenuItem); IPopupMenu* resultMenu = 0; if (menuIDResult != 0) { MenuRef usedMenuRef = GetMenuHandle(menuIDResult); if (usedMenuRef) { if (GetMenuItemRefCon(usedMenuRef, 0, (URefCon*)&resultMenu) == noErr) { resultMenu->SetChosenItemIdx(result); } } } CFRelease(menuRef); return resultMenu; } else { return 0; } }
static pascal OSStatus wxMacAppCommandEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) { OSStatus result = eventNotHandledErr ; HICommand command ; wxMacCarbonEvent cEvent( event ) ; cEvent.GetParameter<HICommand>(kEventParamDirectObject,typeHICommand,&command) ; wxMenuItem* item = NULL ; MenuCommand id = command.commandID ; // 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 && command.menu.menuRef != 0 && command.menu.menuItemIndex != 0 ) { GetMenuItemRefCon( command.menu.menuRef , command.menu.menuItemIndex , (UInt32*) &item ) ; } if ( item ) { switch( cEvent.GetKind() ) { case kEventProcessCommand : { if (item->IsCheckable()) { item->Check( !item->IsChecked() ) ; } item->GetMenu()->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ; result = noErr ; } break ; case kEventCommandUpdateStatus: // eventually trigger an updateui round result = noErr ; break ; default : break ; } } return result ; }
wxMenu* wxFindMenuFromMacCommand( const HICommand &command , wxMenuItem* &item ) { wxMenu* itemMenu = NULL ; #ifndef __WXUNIVERSAL__ int id = 0 ; // for 'standard' commands which don't have a wx-menu if ( command.commandID == kHICommandPreferences || command.commandID == kHICommandQuit || command.commandID == kHICommandAbout ) { id = wxMacCommandToId( command.commandID ) ; wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ; if ( mbar ) item = mbar->FindItem( id , &itemMenu ) ; } else if ( command.commandID != 0 && command.menu.menuRef != 0 && command.menu.menuItemIndex != 0 ) { id = wxMacCommandToId( command.commandID ) ; // make sure it is one of our own menus, or of the 'synthetic' apple and help menus , otherwise don't touch MenuItemIndex firstUserHelpMenuItem ; static MenuHandle helpMenuHandle = NULL ; if ( helpMenuHandle == NULL ) { if ( UMAGetHelpMenuDontCreate( &helpMenuHandle , &firstUserHelpMenuItem) != noErr ) helpMenuHandle = NULL ; } // is it part of the application or the Help menu, then look for the id directly if ( ( GetMenuHandle( kwxMacAppleMenuId ) != NULL && command.menu.menuRef == GetMenuHandle( kwxMacAppleMenuId ) ) || ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) || wxMenuBar::MacGetWindowMenuHMenu() != NULL && command.menu.menuRef == wxMenuBar::MacGetWindowMenuHMenu() ) { wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ; if ( mbar ) item = mbar->FindItem( id , &itemMenu ) ; } else { URefCon refCon = 0 ; GetMenuItemRefCon( command.menu.menuRef , command.menu.menuItemIndex , &refCon ) ; itemMenu = wxFindMenuFromMacMenu( command.menu.menuRef ) ; if ( itemMenu != NULL && refCon != 0) item = (wxMenuItem*) refCon; } } #endif return itemMenu ; }
bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */) { // [tom, 8/20/2006] Pass off to a sub menu if it's for them for(S32 i = 0;i < mSubmenus->size();i++) { PopupMenu *subM = dynamic_cast<PopupMenu *>((*mSubmenus)[i]); if(subM == NULL) continue; if(subM->canHandleID(command)) { return subM->handleSelect(command, text); } } // ensure that this menu actually has an item with the specificed command / refcon. // this is not strictly necessary, we're just doing it here to keep the behavior // in line with the windows implementation. UInt32 refcon; U32 nItems = CountMenuItems(mData->mMenu); S32 pos = -1; for(int i = 1; i <= nItems; i++) { GetMenuItemRefCon(mData->mMenu, i, &refcon); if(refcon == command) pos = i; } if(pos == -1) { Con::errorf("PopupMenu::handleSelect - Could not find menu item position for ID %d ... this shouldn't happen!", command); return false; } char textbuf[1024]; if(!text) { CFStringRef cfstr; CopyMenuItemTextAsCFString(mData->mMenu, pos, &cfstr); CFStringGetCString(cfstr,textbuf,sizeof(textbuf) - 1,kCFStringEncodingUTF8); CFRelease( cfstr ); text = textbuf; } // [tom, 8/20/2006] Wasn't handled by a submenu, pass off to script return dAtob(Con::executef(this, "onSelectItem", Con::getIntArg(pos - 1), text ? text : "")); }
MenuItemIndex FindMenuItemIndex() { MenuItemIndex hit = 0 ; if ( m_parentMenuRef ) { for ( MenuItemIndex i = 1 ; i <= CountMenuItems(m_parentMenuRef) ; ++i ) { URefCon storedRef = 0; GetMenuItemRefCon(m_parentMenuRef, i, &storedRef ); if ( storedRef == (URefCon) m_peer ) { hit = i; break; } } } return hit; }
// this method really isn't necessary for the mac implementation bool PopupMenu::canHandleID(U32 iD) { for(S32 i = 0;i < mSubmenus->size();i++) { PopupMenu *subM = dynamic_cast<PopupMenu *>((*mSubmenus)[i]); if(subM == NULL) continue; if(subM->canHandleID(iD)) return true; } UInt32 refcon; U32 nItems = CountMenuItems(mData->mMenu); for(int i = 1; i <= nItems; i++) { GetMenuItemRefCon(mData->mMenu, i, &refcon); if(refcon == iD) return true; } return false; }
//----------------------------------------------------------------------------- // 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; }
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 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; }