PRBool nsMenuFrame::ShouldBlink() { PRInt32 shouldBlink = 0; nsCOMPtr<nsILookAndFeel> lookAndFeel(do_GetService(kLookAndFeelCID)); if (lookAndFeel) { lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ChosenMenuItemsShouldBlink, shouldBlink); } if (!shouldBlink) return PR_FALSE; // Don't blink in editable menulists. if (mMenuParent && mMenuParent->IsMenu()) { nsMenuPopupFrame* popupFrame = static_cast<nsMenuPopupFrame*>(mMenuParent); nsIFrame* parentMenu = popupFrame->GetParent(); if (parentMenu) { nsCOMPtr<nsIDOMXULMenuListElement> menulist = do_QueryInterface(parentMenu->GetContent()); if (menulist) { PRBool isEditable = PR_FALSE; menulist->GetEditable(&isEditable); return !isEditable; } } } return PR_TRUE; }
NS_IMETHODIMP nsBoxObject::GetLookAndFeelMetric(const PRUnichar* aPropertyName, PRUnichar** aResult) { nsCOMPtr<nsILookAndFeel> lookAndFeel(do_GetService(kLookAndFeelCID)); if (!lookAndFeel) return NS_ERROR_FAILURE; nsAutoString property(aPropertyName); if (property.LowerCaseEqualsLiteral("scrollbarstyle")) { PRInt32 metricResult; lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ScrollArrowStyle, metricResult); switch (metricResult) { case nsILookAndFeel::eMetric_ScrollArrowStyleBothAtBottom: *aResult = ToNewUnicode(NS_LITERAL_STRING("doublebottom")); break; case nsILookAndFeel::eMetric_ScrollArrowStyleBothAtEachEnd: *aResult = ToNewUnicode(NS_LITERAL_STRING("double")); break; case nsILookAndFeel::eMetric_ScrollArrowStyleBothAtTop: *aResult = ToNewUnicode(NS_LITERAL_STRING("doubletop")); break; default: *aResult = ToNewUnicode(NS_LITERAL_STRING("single")); break; } } else if (property.LowerCaseEqualsLiteral("thumbstyle")) { PRInt32 metricResult; lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ScrollSliderStyle, metricResult); if ( metricResult == nsILookAndFeel::eMetric_ScrollThumbStyleNormal ) *aResult = ToNewUnicode(NS_LITERAL_STRING("fixed")); else *aResult = ToNewUnicode(NS_LITERAL_STRING("proportional")); } return NS_OK; }
NS_IMETHODIMP nsMenuFrame::HandleEvent(nsPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) { NS_ENSURE_ARG_POINTER(aEventStatus); if (nsEventStatus_eConsumeNoDefault == *aEventStatus || (mMenuParent && mMenuParent->IsMenuLocked())) { return NS_OK; } nsWeakFrame weakFrame(this); if (*aEventStatus == nsEventStatus_eIgnore) *aEventStatus = nsEventStatus_eConsumeDoDefault; PRBool onmenu = IsOnMenu(); if (aEvent->message == NS_KEY_PRESS && !IsDisabled()) { nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent; PRUint32 keyCode = keyEvent->keyCode; #ifdef XP_MACOSX // On mac, open menulist on either up/down arrow or space (w/o Cmd pressed) if (!IsOpen() && ((keyEvent->charCode == NS_VK_SPACE && !keyEvent->isMeta) || (keyCode == NS_VK_UP || keyCode == NS_VK_DOWN))) { *aEventStatus = nsEventStatus_eConsumeNoDefault; OpenMenu(PR_FALSE); } #else // On other platforms, toggle menulist on unmodified F4 or Alt arrow if ((keyCode == NS_VK_F4 && !keyEvent->isAlt) || ((keyCode == NS_VK_UP || keyCode == NS_VK_DOWN) && keyEvent->isAlt)) { *aEventStatus = nsEventStatus_eConsumeNoDefault; ToggleMenuState(); } #endif } else if (aEvent->eventStructType == NS_MOUSE_EVENT && aEvent->message == NS_MOUSE_BUTTON_DOWN && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton && !IsDisabled() && IsMenu()) { // The menu item was selected. Bring up the menu. // We have children. // Don't prevent the default action here, since that will also cancel // potential drag starts. if (!mMenuParent || mMenuParent->IsMenuBar()) { ToggleMenuState(); } else { if (!IsOpen()) { OpenMenu(PR_FALSE); } } } else if ( #ifndef NSCONTEXTMENUISMOUSEUP (aEvent->eventStructType == NS_MOUSE_EVENT && aEvent->message == NS_MOUSE_BUTTON_UP && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eRightButton) && #else aEvent->message == NS_CONTEXTMENU && #endif onmenu && !IsMenu() && !IsDisabled()) { // if this menu is a context menu it accepts right-clicks...fire away! // Make sure we cancel default processing of the context menu event so // that it doesn't bubble and get seen again by the popuplistener and show // another context menu. // // Furthermore (there's always more, isn't there?), on some platforms (win32 // being one of them) we get the context menu event on a mouse up while // on others we get it on a mouse down. For the ones where we get it on a // mouse down, we must continue listening for the right button up event to // dismiss the menu. if (mMenuParent->IsContextMenu()) { *aEventStatus = nsEventStatus_eConsumeNoDefault; Execute(aEvent); } } else if (aEvent->eventStructType == NS_MOUSE_EVENT && aEvent->message == NS_MOUSE_BUTTON_UP && static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton && !IsMenu() && !IsDisabled()) { // Execute the execute event handler. *aEventStatus = nsEventStatus_eConsumeNoDefault; Execute(aEvent); } else if (aEvent->message == NS_MOUSE_EXIT_SYNTH) { // Kill our timer if one is active. if (mOpenTimer) { mOpenTimer->Cancel(); mOpenTimer = nsnull; } // Deactivate the menu. if (mMenuParent) { PRBool onmenubar = mMenuParent->IsMenuBar(); if (!(onmenubar && mMenuParent->IsActive())) { if (IsMenu() && !onmenubar && IsOpen()) { // Submenus don't get closed up immediately. } else if (this == mMenuParent->GetCurrentMenuItem()) { mMenuParent->ChangeMenuItem(nsnull, PR_FALSE); } } } } else if (aEvent->message == NS_MOUSE_MOVE && (onmenu || (mMenuParent && mMenuParent->IsMenuBar()))) { if (gEatMouseMove) { gEatMouseMove = PR_FALSE; return NS_OK; } // Let the menu parent know we're the new item. mMenuParent->ChangeMenuItem(this, PR_FALSE); NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK); NS_ENSURE_TRUE(mMenuParent, NS_OK); // we need to check if we really became the current menu // item or not nsMenuFrame *realCurrentItem = mMenuParent->GetCurrentMenuItem(); if (realCurrentItem != this) { // we didn't (presumably because a context menu was active) return NS_OK; } // Hovering over a menu in a popup should open it without a need for a click. // A timer is used so that it doesn't open if the user moves the mouse quickly // past the menu. This conditional check ensures that only menus have this // behaviour if (!IsDisabled() && IsMenu() && !IsOpen() && !mOpenTimer && !mMenuParent->IsMenuBar()) { PRInt32 menuDelay = 300; // ms nsCOMPtr<nsILookAndFeel> lookAndFeel(do_GetService(kLookAndFeelCID)); if (lookAndFeel) lookAndFeel->GetMetric(nsILookAndFeel::eMetric_SubmenuDelay, menuDelay); // We're a menu, we're built, we're closed, and no timer has been kicked off. mOpenTimer = do_CreateInstance("@mozilla.org/timer;1"); mOpenTimer->InitWithCallback(mTimerMediator, menuDelay, nsITimer::TYPE_ONE_SHOT); } } return NS_OK; }