void AwtPopupMenu::Show(JNIEnv *env, jobject event, BOOL isTrayIconPopup) { /* * For not TrayIcon popup. * Convert the event's XY to absolute coordinates. The XY is * relative to the origin component, which is passed by PopupMenu * as the event's target. */ if (env->EnsureLocalCapacity(2) < 0) { return; } jobject origin = (env)->GetObjectField(event, AwtEvent::targetID); jobject peerOrigin = GetPeerForTarget(env, origin); PDATA pData; JNI_CHECK_PEER_GOTO(peerOrigin, done); { AwtComponent* awtOrigin = (AwtComponent*)pData; POINT pt; UINT flags = 0; pt.x = (env)->GetIntField(event, AwtEvent::xID); pt.y = (env)->GetIntField(event, AwtEvent::yID); if (!isTrayIconPopup) { ::MapWindowPoints(awtOrigin->GetHWnd(), 0, (LPPOINT)&pt, 1); // Adjust to account for the Inset values RECT rctInsets; awtOrigin->GetInsets(&rctInsets); pt.x -= rctInsets.left; pt.y -= rctInsets.top; flags = TPM_LEFTALIGN | TPM_RIGHTBUTTON; } else { ::SetForegroundWindow(awtOrigin->GetHWnd()); flags = TPM_NONOTIFY | TPM_RIGHTALIGN | TPM_RIGHTBUTTON | TPM_BOTTOMALIGN; } /* Invoke the popup. */ ::TrackPopupMenu(GetHMenu(), flags, pt.x, pt.y, 0, awtOrigin->GetHWnd(), NULL); if (isTrayIconPopup) { ::PostMessage(awtOrigin->GetHWnd(), WM_NULL, 0, 0); } } done: env->DeleteLocalRef(origin); env->DeleteLocalRef(peerOrigin); }
// get the menu with given handle (recursively) wxMenu* wxMenuBar::MSWGetMenu(WXHMENU hMenu) { wxCHECK_MSG( GetHMenu() != hMenu, NULL, wxT("wxMenuBar::MSWGetMenu(): menu handle is wxMenuBar, not wxMenu") ); // query all menus for ( size_t n = 0 ; n < GetMenuCount(); ++n ) { wxMenu* menu = GetMenu(n)->MSWGetMenu(hMenu); if ( menu ) return menu; } // unknown hMenu return NULL; }
wxMenu* wxMenuBar::MSWGetMenu(WXHMENU hMenu) const { // If we're called with the handle of the menu bar itself, we can return // immediately as it certainly can't be the handle of one of our menus. if ( hMenu == GetHMenu() ) return NULL; // query all menus for ( size_t n = 0 ; n < GetMenuCount(); ++n ) { wxMenu* menu = GetMenu(n)->MSWGetMenu(hMenu); if ( menu ) return menu; } // unknown hMenu return NULL; }
wxMenu* wxMenu::MSWGetMenu(WXHMENU hMenu) { // check self if ( GetHMenu() == hMenu ) return this; // recursively query submenus for ( size_t n = 0 ; n < GetMenuItemCount(); ++n ) { wxMenuItem* item = FindItemByPosition(n); wxMenu* submenu = item->GetSubMenu(); if ( submenu ) { submenu = submenu->MSWGetMenu(hMenu); if (submenu) return submenu; } } // unknown hMenu return NULL; }
// MacOS needs to know about submenus somewhere within this menu // before it can be displayed, also hide special menu items // like preferences that are handled by the OS void wxMenu::MacBeforeDisplay( bool isSubMenu ) { wxMenuItem* previousItem = NULL ; size_t pos ; wxMenuItemList::compatibility_iterator node; wxMenuItem *item; for (pos = 0, node = GetMenuItems().GetFirst(); node; node = node->GetNext(), pos++) { item = (wxMenuItem *)node->GetData(); wxMenu* subMenu = item->GetSubMenu() ; if (subMenu) { subMenu->MacBeforeDisplay( true ) ; } else // normal item { #if TARGET_CARBON // what we do here is to hide the special items which are // shown in the application menu anyhow -- it doesn't make // sense to show them in their normal place as well if ( item->GetId() == wxApp::s_macAboutMenuItemId || ( UMAGetSystemVersion() >= 0x1000 && ( item->GetId() == wxApp::s_macPreferencesMenuItemId || item->GetId() == wxApp::s_macExitMenuItemId ) ) ) { ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ), pos + 1, kMenuItemAttrHidden, 0 ); // also check for a separator which was used just to // separate this item from the others, so don't leave // separator at the menu start or end nor 2 consecutive // separators wxMenuItemList::compatibility_iterator nextNode = node->GetNext(); wxMenuItem *next = nextNode ? nextNode->GetData() : NULL; size_t posSeptoHide; if ( !previousItem && next && next->IsSeparator() ) { // next (i.e. second as we must be first) item is // the separator to hide wxASSERT_MSG( pos == 0, _T("should be the menu start") ); posSeptoHide = 2; } else if ( GetMenuItems().GetCount() == pos + 1 && previousItem != NULL && previousItem->IsSeparator() ) { // prev item is a trailing separator we want to hide posSeptoHide = pos; } else if ( previousItem && previousItem->IsSeparator() && next && next->IsSeparator() ) { // two consecutive separators, this is one too many posSeptoHide = pos; } else // no separators to hide { posSeptoHide = 0; } if ( posSeptoHide ) { // hide the separator as well ChangeMenuItemAttributes( MAC_WXHMENU( GetHMenu() ), posSeptoHide, kMenuItemAttrHidden, 0 ); } } #endif // TARGET_CARBON } previousItem = item ; } if ( isSubMenu ) ::InsertMenu(MAC_WXHMENU( GetHMenu()), -1); }