diff -r 000000000000 -r 6474c204b198 layout/xul/nsMenuBoxObject.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layout/xul/nsMenuBoxObject.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "nsISupportsUtils.h" +#include "nsIMenuBoxObject.h" +#include "nsBoxObject.h" +#include "nsIDOMKeyEvent.h" +#include "nsIFrame.h" +#include "nsMenuBarFrame.h" +#include "nsMenuBarListener.h" +#include "nsMenuFrame.h" +#include "nsMenuPopupFrame.h" + +class nsMenuBoxObject : public nsIMenuBoxObject, + public nsBoxObject +{ +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIMENUBOXOBJECT + + nsMenuBoxObject(); + virtual ~nsMenuBoxObject(); +}; + +nsMenuBoxObject::nsMenuBoxObject() +{ +} + +nsMenuBoxObject::~nsMenuBoxObject() +{ +} + +NS_IMPL_ISUPPORTS_INHERITED(nsMenuBoxObject, nsBoxObject, nsIMenuBoxObject) + +/* void openMenu (in boolean openFlag); */ +NS_IMETHODIMP nsMenuBoxObject::OpenMenu(bool aOpenFlag) +{ + nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); + if (pm) { + nsIFrame* frame = GetFrame(false); + if (frame) { + if (aOpenFlag) { + nsCOMPtr content = mContent; + pm->ShowMenu(content, false, false); + } + else { + nsMenuFrame* menu = do_QueryFrame(frame); + if (menu) { + nsMenuPopupFrame* popupFrame = menu->GetPopup(); + if (popupFrame) + pm->HidePopup(popupFrame->GetContent(), false, true, false, false); + } + } + } + } + + return NS_OK; +} + +NS_IMETHODIMP nsMenuBoxObject::GetActiveChild(nsIDOMElement** aResult) +{ + *aResult = nullptr; + nsMenuFrame* menu = do_QueryFrame(GetFrame(false)); + if (menu) + return menu->GetActiveChild(aResult); + return NS_OK; +} + +NS_IMETHODIMP nsMenuBoxObject::SetActiveChild(nsIDOMElement* aResult) +{ + nsMenuFrame* menu = do_QueryFrame(GetFrame(false)); + if (menu) + return menu->SetActiveChild(aResult); + return NS_OK; +} + +/* boolean handleKeyPress (in nsIDOMKeyEvent keyEvent); */ +NS_IMETHODIMP nsMenuBoxObject::HandleKeyPress(nsIDOMKeyEvent* aKeyEvent, bool* aHandledFlag) +{ + *aHandledFlag = false; + NS_ENSURE_ARG(aKeyEvent); + + nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); + if (!pm) + return NS_OK; + + // if event has already been handled, bail + bool eventHandled = false; + aKeyEvent->GetDefaultPrevented(&eventHandled); + if (eventHandled) + return NS_OK; + + if (nsMenuBarListener::IsAccessKeyPressed(aKeyEvent)) + return NS_OK; + + nsMenuFrame* menu = do_QueryFrame(GetFrame(false)); + if (!menu) + return NS_OK; + + nsMenuPopupFrame* popupFrame = menu->GetPopup(); + if (!popupFrame) + return NS_OK; + + uint32_t keyCode; + aKeyEvent->GetKeyCode(&keyCode); + switch (keyCode) { + case nsIDOMKeyEvent::DOM_VK_UP: + case nsIDOMKeyEvent::DOM_VK_DOWN: + case nsIDOMKeyEvent::DOM_VK_HOME: + case nsIDOMKeyEvent::DOM_VK_END: + { + nsNavigationDirection theDirection; + theDirection = NS_DIRECTION_FROM_KEY_CODE(popupFrame, keyCode); + *aHandledFlag = + pm->HandleKeyboardNavigationInPopup(popupFrame, theDirection); + return NS_OK; + } + default: + *aHandledFlag = pm->HandleShortcutNavigation(aKeyEvent, popupFrame); + return NS_OK; + } +} + +NS_IMETHODIMP +nsMenuBoxObject::GetOpenedWithKey(bool* aOpenedWithKey) +{ + *aOpenedWithKey = false; + + nsMenuFrame* menuframe = do_QueryFrame(GetFrame(false)); + if (!menuframe) + return NS_OK; + + nsIFrame* frame = menuframe->GetParent(); + while (frame) { + nsMenuBarFrame* menubar = do_QueryFrame(frame); + if (menubar) { + *aOpenedWithKey = menubar->IsActiveByKeyboard(); + return NS_OK; + } + frame = frame->GetParent(); + } + + return NS_OK; +} + + +// Creation Routine /////////////////////////////////////////////////////////////////////// + +nsresult +NS_NewMenuBoxObject(nsIBoxObject** aResult) +{ + *aResult = new nsMenuBoxObject; + if (!*aResult) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(*aResult); + return NS_OK; +} +