Bug 1812329 - Remove nsMenuBarFrame. r=smaug

This ended up being a lot more straight-forward than the menu changes.

TLDR:

 * nsMenuBarFrame -> XULMenuBarElement
 * nsMenuBarListener -> MenuBarListener

Rest should be rather straight-forward.

Depends on D168649

Differential Revision: https://phabricator.services.mozilla.com/D167809
This commit is contained in:
Emilio Cobos Álvarez 2023-02-07 18:09:37 +00:00
parent 720ce2d73f
commit b9833bfcca
23 changed files with 379 additions and 476 deletions

View file

@ -6,6 +6,7 @@
#include "XULMenuAccessible.h" #include "XULMenuAccessible.h"
#include "LocalAccessible-inl.h" #include "LocalAccessible-inl.h"
#include "XULMenuBarElement.h"
#include "XULMenuParentElement.h" #include "XULMenuParentElement.h"
#include "XULPopupElement.h" #include "XULPopupElement.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
@ -21,7 +22,6 @@
#include "nsIDOMXULSelectCntrlEl.h" #include "nsIDOMXULSelectCntrlEl.h"
#include "nsIDOMXULSelectCntrlItemEl.h" #include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsMenuBarFrame.h"
#include "nsMenuPopupFrame.h" #include "nsMenuPopupFrame.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
@ -464,8 +464,8 @@ role XULMenubarAccessible::NativeRole() const { return roles::MENUBAR; }
// XULMenubarAccessible: Widgets // XULMenubarAccessible: Widgets
bool XULMenubarAccessible::IsActiveWidget() const { bool XULMenubarAccessible::IsActiveWidget() const {
nsMenuBarFrame* menuBarFrame = do_QueryFrame(GetFrame()); auto* menuBar = dom::XULMenuBarElement::FromNode(GetContent());
return menuBarFrame && menuBarFrame->IsActive(); return menuBar && menuBar->IsActive();
} }
bool XULMenubarAccessible::AreItemsOperable() const { return true; } bool XULMenubarAccessible::AreItemsOperable() const { return true; }

View file

@ -4,24 +4,21 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsMenuBarListener.h" #include "MenuBarListener.h"
#include "XULButtonElement.h" #include "XULButtonElement.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/dom/XULButtonElement.h"
#include "nsMenuBarFrame.h"
#include "nsMenuPopupFrame.h"
#include "nsPIWindowRoot.h"
#include "nsISound.h" #include "nsISound.h"
// Drag & Drop, Clipboard // Drag & Drop, Clipboard
#include "nsWidgetsCID.h" #include "nsWidgetsCID.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIContent.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsPIWindowRoot.h"
#include "nsIFrame.h"
#include "mozilla/BasicEvents.h" #include "mozilla/BasicEvents.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/StaticPrefs_ui.h" #include "mozilla/StaticPrefs_ui.h"
#include "mozilla/TextEvents.h" #include "mozilla/TextEvents.h"
#include "mozilla/dom/Document.h" #include "mozilla/dom/Document.h"
@ -29,31 +26,30 @@
#include "mozilla/dom/EventBinding.h" #include "mozilla/dom/EventBinding.h"
#include "mozilla/dom/KeyboardEvent.h" #include "mozilla/dom/KeyboardEvent.h"
#include "mozilla/dom/KeyboardEventBinding.h" #include "mozilla/dom/KeyboardEventBinding.h"
#include "mozilla/dom/XULButtonElement.h"
#include "mozilla/dom/XULMenuBarElement.h"
#include "mozilla/dom/XULMenuParentElement.h" #include "mozilla/dom/XULMenuParentElement.h"
#include "nsXULPopupManager.h" #include "nsXULPopupManager.h"
using namespace mozilla; namespace mozilla::dom {
using mozilla::dom::Event;
using mozilla::dom::KeyboardEvent;
/* NS_IMPL_CYCLE_COLLECTION(MenuBarListener, mTopWindowEventTarget)
* nsMenuBarListener implementation
*/
NS_IMPL_ISUPPORTS(nsMenuBarListener, nsIDOMEventListener) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MenuBarListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_END
//////////////////////////////////////////////////////////////////////// NS_IMPL_CYCLE_COLLECTING_ADDREF(MenuBarListener)
NS_IMPL_CYCLE_COLLECTING_RELEASE(MenuBarListener)
nsMenuBarListener::nsMenuBarListener(nsMenuBarFrame* aMenuBarFrame, MenuBarListener::MenuBarListener(XULMenuBarElement& aElement)
nsIContent* aMenuBarContent) : mMenuBar(&aElement),
: mMenuBarFrame(aMenuBarFrame), mEventTarget(aElement.GetComposedDoc()),
mContent(dom::XULMenuParentElement::FromNode(aMenuBarContent)),
mEventTarget(aMenuBarContent->GetComposedDoc()),
mTopWindowEventTarget(nullptr), mTopWindowEventTarget(nullptr),
mAccessKeyDown(false), mAccessKeyDown(false),
mAccessKeyDownCanceled(false) { mAccessKeyDownCanceled(false) {
MOZ_ASSERT(mEventTarget); MOZ_ASSERT(mEventTarget);
MOZ_ASSERT(mContent); MOZ_ASSERT(mMenuBar);
// Hook up the menubar as a key listener on the whole document. This will // Hook up the menubar as a key listener on the whole document. This will
// see every keypress that occurs, but after everyone else does. // see every keypress that occurs, but after everyone else does.
@ -78,20 +74,16 @@ nsMenuBarListener::nsMenuBarListener(nsMenuBarFrame* aMenuBarFrame,
mEventTarget->AddEventListener(u"MozDOMFullscreen:Entered"_ns, this, false); mEventTarget->AddEventListener(u"MozDOMFullscreen:Entered"_ns, this, false);
// Needs to listen to the deactivate event of the window. // Needs to listen to the deactivate event of the window.
RefPtr<dom::EventTarget> topWindowEventTarget = mTopWindowEventTarget = nsContentUtils::GetWindowRoot(mEventTarget);
nsContentUtils::GetWindowRoot(aMenuBarContent->GetComposedDoc());
mTopWindowEventTarget = topWindowEventTarget.get();
mTopWindowEventTarget->AddSystemEventListener(u"deactivate"_ns, this, true); mTopWindowEventTarget->AddSystemEventListener(u"deactivate"_ns, this, true);
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
nsMenuBarListener::~nsMenuBarListener() { MenuBarListener::~MenuBarListener() {
MOZ_ASSERT(!mEventTarget, MOZ_ASSERT(!mEventTarget, "Should've detached always");
"OnDestroyMenuBarFrame() should've alreay been called");
} }
void nsMenuBarListener::OnDestroyMenuBarFrame() { void MenuBarListener::Detach() {
mEventTarget->RemoveSystemEventListener(u"keypress"_ns, this, false); mEventTarget->RemoveSystemEventListener(u"keypress"_ns, this, false);
mEventTarget->RemoveSystemEventListener(u"keydown"_ns, this, false); mEventTarget->RemoveSystemEventListener(u"keydown"_ns, this, false);
mEventTarget->RemoveSystemEventListener(u"keyup"_ns, this, false); mEventTarget->RemoveSystemEventListener(u"keyup"_ns, this, false);
@ -109,23 +101,26 @@ void nsMenuBarListener::OnDestroyMenuBarFrame() {
mTopWindowEventTarget->RemoveSystemEventListener(u"deactivate"_ns, this, mTopWindowEventTarget->RemoveSystemEventListener(u"deactivate"_ns, this,
true); true);
mMenuBarFrame = nullptr; mMenuBar = nullptr;
mEventTarget = nullptr; mEventTarget = nullptr;
mTopWindowEventTarget = nullptr; mTopWindowEventTarget = nullptr;
} }
void nsMenuBarListener::ToggleMenuActiveState() { void MenuBarListener::ToggleMenuActiveState(ByKeyboard aByKeyboard) {
if (mMenuBarFrame->IsActive()) { RefPtr menuBar = mMenuBar;
mMenuBarFrame->SetActive(false); if (menuBar->IsActive()) {
menuBar->SetActive(false);
} else { } else {
RefPtr content = mContent; if (aByKeyboard == ByKeyboard::Yes) {
mMenuBarFrame->SetActive(true); menuBar->SetActiveByKeyboard();
content->SelectFirstItem(); }
menuBar->SetActive(true);
menuBar->SelectFirstItem();
} }
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
nsresult nsMenuBarListener::KeyUp(Event* aKeyEvent) { nsresult MenuBarListener::KeyUp(Event* aKeyEvent) {
WidgetKeyboardEvent* nativeKeyEvent = WidgetKeyboardEvent* nativeKeyEvent =
aKeyEvent->WidgetEventPtr()->AsKeyboardEvent(); aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
if (!nativeKeyEvent) { if (!nativeKeyEvent) {
@ -149,7 +144,7 @@ nsresult nsMenuBarListener::KeyUp(Event* aKeyEvent) {
// The access key was down and is now up, and no other // The access key was down and is now up, and no other
// keys were pressed in between. // keys were pressed in between.
bool toggleMenuActiveState = true; bool toggleMenuActiveState = true;
if (!mMenuBarFrame->IsActive()) { if (!mMenuBar->IsActive()) {
// If the focused content is in a remote process, we should allow the // If the focused content is in a remote process, we should allow the
// focused web app to prevent to activate the menubar. // focused web app to prevent to activate the menubar.
if (nativeKeyEvent->WillBeSentToRemoteProcess()) { if (nativeKeyEvent->WillBeSentToRemoteProcess()) {
@ -165,20 +160,17 @@ nsresult nsMenuBarListener::KeyUp(Event* aKeyEvent) {
} }
// If menubar active state is changed or the menubar is destroyed // If menubar active state is changed or the menubar is destroyed
// during closing the popups, we should do nothing anymore. // during closing the popups, we should do nothing anymore.
toggleMenuActiveState = !Destroyed() && !mMenuBarFrame->IsActive(); toggleMenuActiveState = !Destroyed() && !mMenuBar->IsActive();
} }
if (toggleMenuActiveState) { if (toggleMenuActiveState) {
if (!mMenuBarFrame->IsActive()) { ToggleMenuActiveState(ByKeyboard::Yes);
mMenuBarFrame->SetActiveByKeyboard();
}
ToggleMenuActiveState();
} }
} }
mAccessKeyDown = false; mAccessKeyDown = false;
mAccessKeyDownCanceled = false; mAccessKeyDownCanceled = false;
if (!Destroyed() && mMenuBarFrame->IsActive()) { if (!Destroyed() && mMenuBar->IsActive()) {
nativeKeyEvent->StopPropagation(); nativeKeyEvent->StopPropagation();
nativeKeyEvent->PreventDefault(); nativeKeyEvent->PreventDefault();
} }
@ -187,7 +179,7 @@ nsresult nsMenuBarListener::KeyUp(Event* aKeyEvent) {
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
nsresult nsMenuBarListener::KeyPress(Event* aKeyEvent) { nsresult MenuBarListener::KeyPress(Event* aKeyEvent) {
// if event has already been handled, bail // if event has already been handled, bail
if (!aKeyEvent || aKeyEvent->DefaultPrevented()) { if (!aKeyEvent || aKeyEvent->DefaultPrevented()) {
return NS_OK; // don't consume event return NS_OK; // don't consume event
@ -198,7 +190,7 @@ nsresult nsMenuBarListener::KeyPress(Event* aKeyEvent) {
return NS_OK; return NS_OK;
} }
auto accessKey = LookAndFeel::GetMenuAccessKey(); const auto accessKey = LookAndFeel::GetMenuAccessKey();
if (!accessKey) { if (!accessKey) {
return NS_OK; return NS_OK;
} }
@ -235,12 +227,11 @@ nsresult nsMenuBarListener::KeyPress(Event* aKeyEvent) {
} }
// The F10 key just went down by itself or with ctrl pressed. // The F10 key just went down by itself or with ctrl pressed.
// In Windows, both of these activate the menu bar. // In Windows, both of these activate the menu bar.
mMenuBarFrame->SetActiveByKeyboard(); ToggleMenuActiveState(ByKeyboard::Yes);
ToggleMenuActiveState();
if (mMenuBarFrame->IsActive()) { if (mMenuBar && mMenuBar->IsActive()) {
# ifdef MOZ_WIDGET_GTK # ifdef MOZ_WIDGET_GTK
RefPtr child = mContent->GetActiveMenuChild(); RefPtr child = mMenuBar->GetActiveMenuChild();
// In GTK, this also opens the first menu. // In GTK, this also opens the first menu.
child->OpenMenuPopup(false); child->OpenMenuPopup(false);
# endif # endif
@ -260,11 +251,11 @@ nsresult nsMenuBarListener::KeyPress(Event* aKeyEvent) {
// the menu bar. // the menu bar.
// TODO(emilio): This is rather odd, and I cannot get the beep to work, // TODO(emilio): This is rather odd, and I cannot get the beep to work,
// but this matches what old code was doing... // but this matches what old code was doing...
if (mMenuBarFrame->IsActive()) { if (mMenuBar && mMenuBar->IsActive()) {
if (nsCOMPtr<nsISound> sound = do_GetService("@mozilla.org/sound;1")) { if (nsCOMPtr<nsISound> sound = do_GetService("@mozilla.org/sound;1")) {
sound->Beep(); sound->Beep();
} }
mMenuBarFrame->SetActive(false); ToggleMenuActiveState(ByKeyboard::Yes);
} }
#endif #endif
return NS_OK; return NS_OK;
@ -282,8 +273,9 @@ nsresult nsMenuBarListener::KeyPress(Event* aKeyEvent) {
return NS_OK; return NS_OK;
} }
mMenuBarFrame->SetActiveByKeyboard(); RefPtr menuBar = mMenuBar;
mMenuBarFrame->SetActive(true); menuBar->SetActiveByKeyboard();
menuBar->SetActive(true);
menuForKey->OpenMenuPopup(true); menuForKey->OpenMenuPopup(true);
// The opened menu will listen next keyup event. // The opened menu will listen next keyup event.
@ -292,11 +284,10 @@ nsresult nsMenuBarListener::KeyPress(Event* aKeyEvent) {
aKeyEvent->StopPropagation(); aKeyEvent->StopPropagation();
aKeyEvent->PreventDefault(); aKeyEvent->PreventDefault();
return NS_OK; return NS_OK;
} }
dom::XULButtonElement* nsMenuBarListener::GetMenuForKeyEvent( dom::XULButtonElement* MenuBarListener::GetMenuForKeyEvent(
KeyboardEvent& aKeyEvent) { KeyboardEvent& aKeyEvent) {
if (!aKeyEvent.IsMenuAccessKeyPressed()) { if (!aKeyEvent.IsMenuAccessKeyPressed()) {
return nullptr; return nullptr;
@ -318,10 +309,10 @@ dom::XULButtonElement* nsMenuBarListener::GetMenuForKeyEvent(
// Do shortcut navigation. // Do shortcut navigation.
// A letter was pressed. We want to see if a shortcut gets matched. If // A letter was pressed. We want to see if a shortcut gets matched. If
// so, we'll know the menu got activated. // so, we'll know the menu got activated.
return mMenuBarFrame->MenubarElement().FindMenuWithShortcut(aKeyEvent); return mMenuBar->FindMenuWithShortcut(aKeyEvent);
} }
void nsMenuBarListener::ReserveKeyIfNeeded(Event* aKeyEvent) { void MenuBarListener::ReserveKeyIfNeeded(Event* aKeyEvent) {
WidgetKeyboardEvent* nativeKeyEvent = WidgetKeyboardEvent* nativeKeyEvent =
aKeyEvent->WidgetEventPtr()->AsKeyboardEvent(); aKeyEvent->WidgetEventPtr()->AsKeyboardEvent();
if (nsContentUtils::ShouldBlockReservedKeys(nativeKeyEvent)) { if (nsContentUtils::ShouldBlockReservedKeys(nativeKeyEvent)) {
@ -330,7 +321,7 @@ void nsMenuBarListener::ReserveKeyIfNeeded(Event* aKeyEvent) {
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
nsresult nsMenuBarListener::KeyDown(Event* aKeyEvent) { nsresult MenuBarListener::KeyDown(Event* aKeyEvent) {
// handlers shouldn't be triggered by non-trusted events. // handlers shouldn't be triggered by non-trusted events.
if (!aKeyEvent || !aKeyEvent->IsTrusted()) { if (!aKeyEvent || !aKeyEvent->IsTrusted()) {
return NS_OK; return NS_OK;
@ -360,9 +351,9 @@ nsresult nsMenuBarListener::KeyDown(Event* aKeyEvent) {
// Especially CTRL. CTRL+ALT == AltGR, and we'll break on non-US // Especially CTRL. CTRL+ALT == AltGR, and we'll break on non-US
// enhanced 102-key keyboards if we don't check this. // enhanced 102-key keyboards if we don't check this.
bool isAccessKeyDownEvent = bool isAccessKeyDownEvent =
theChar == accessKey && (theChar == accessKey &&
(keyEvent->GetModifiersForMenuAccessKey() & (keyEvent->GetModifiersForMenuAccessKey() &
~LookAndFeel::GetMenuAccessKeyModifiers()) == 0; ~LookAndFeel::GetMenuAccessKeyModifiers()) == 0);
if (!capturing && !mAccessKeyDown) { if (!capturing && !mAccessKeyDown) {
// If accesskey isn't being pressed and the key isn't the accesskey, // If accesskey isn't being pressed and the key isn't the accesskey,
@ -389,7 +380,7 @@ nsresult nsMenuBarListener::KeyDown(Event* aKeyEvent) {
mAccessKeyDownCanceled = !isAccessKeyDownEvent; mAccessKeyDownCanceled = !isAccessKeyDownEvent;
} }
if (capturing && LookAndFeel::GetMenuAccessKey()) { if (capturing && accessKey) {
if (GetMenuForKeyEvent(*keyEvent)) { if (GetMenuForKeyEvent(*keyEvent)) {
ReserveKeyIfNeeded(aKeyEvent); ReserveKeyIfNeeded(aKeyEvent);
} }
@ -400,9 +391,9 @@ nsresult nsMenuBarListener::KeyDown(Event* aKeyEvent) {
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
nsresult nsMenuBarListener::Blur(Event* aEvent) { nsresult MenuBarListener::Blur(Event* aEvent) {
if (!IsMenuOpen() && mMenuBarFrame->IsActive()) { if (!IsMenuOpen() && mMenuBar->IsActive()) {
ToggleMenuActiveState(); ToggleMenuActiveState(ByKeyboard::No);
mAccessKeyDown = false; mAccessKeyDown = false;
mAccessKeyDownCanceled = false; mAccessKeyDownCanceled = false;
} }
@ -411,7 +402,7 @@ nsresult nsMenuBarListener::Blur(Event* aEvent) {
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
nsresult nsMenuBarListener::OnWindowDeactivated(Event* aEvent) { nsresult MenuBarListener::OnWindowDeactivated(Event* aEvent) {
// Reset the accesskey state because we cannot receive the keyup event for // Reset the accesskey state because we cannot receive the keyup event for
// the pressing accesskey. // the pressing accesskey.
mAccessKeyDown = false; mAccessKeyDown = false;
@ -419,13 +410,13 @@ nsresult nsMenuBarListener::OnWindowDeactivated(Event* aEvent) {
return NS_OK; // means I am NOT consuming event return NS_OK; // means I am NOT consuming event
} }
bool nsMenuBarListener::IsMenuOpen() const { bool MenuBarListener::IsMenuOpen() const {
auto* activeChild = mContent->GetActiveMenuChild(); auto* activeChild = mMenuBar->GetActiveMenuChild();
return activeChild && activeChild->IsMenuPopupOpen(); return activeChild && activeChild->IsMenuPopupOpen();
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
nsresult nsMenuBarListener::MouseDown(Event* aMouseEvent) { nsresult MenuBarListener::MouseDown(Event* aMouseEvent) {
// NOTE: MouseDown method listens all phases // NOTE: MouseDown method listens all phases
// Even if the mousedown event is canceled, it means the user don't want // Even if the mousedown event is canceled, it means the user don't want
@ -440,8 +431,8 @@ nsresult nsMenuBarListener::MouseDown(Event* aMouseEvent) {
return NS_OK; return NS_OK;
} }
if (!IsMenuOpen() && mMenuBarFrame->IsActive()) { if (!IsMenuOpen() && mMenuBar->IsActive()) {
ToggleMenuActiveState(); ToggleMenuActiveState(ByKeyboard::No);
} }
return NS_OK; // means I am NOT consuming event return NS_OK; // means I am NOT consuming event
@ -449,18 +440,19 @@ nsresult nsMenuBarListener::MouseDown(Event* aMouseEvent) {
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
nsresult nsMenuBarListener::Fullscreen(Event* aEvent) { nsresult MenuBarListener::Fullscreen(Event* aEvent) {
if (mMenuBarFrame->IsActive()) { if (mMenuBar->IsActive()) {
ToggleMenuActiveState(); ToggleMenuActiveState(ByKeyboard::No);
} }
return NS_OK; return NS_OK;
} }
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
nsMenuBarListener::HandleEvent(Event* aEvent) { MenuBarListener::HandleEvent(Event* aEvent) {
// If the menu bar is collapsed, don't do anything. // If the menu bar is collapsed, don't do anything.
if (!mMenuBarFrame->StyleVisibility()->IsVisible()) { if (!mMenuBar->GetPrimaryFrame() ||
!mMenuBar->GetPrimaryFrame()->StyleVisibility()->IsVisible()) {
return NS_OK; return NS_OK;
} }
@ -495,3 +487,5 @@ nsMenuBarListener::HandleEvent(Event* aEvent) {
MOZ_ASSERT_UNREACHABLE("Unexpected eventType"); MOZ_ASSERT_UNREACHABLE("Unexpected eventType");
return NS_OK; return NS_OK;
} }
} // namespace mozilla::dom

83
dom/xul/MenuBarListener.h Normal file
View file

@ -0,0 +1,83 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef mozilla_dom_MenuBarListener_h
#define mozilla_dom_MenuBarListener_h
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
#include "nsIDOMEventListener.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISupports.h"
namespace mozilla::dom {
class Document;
class EventTarget;
class KeyboardEvent;
class XULMenuBarElement;
class XULButtonElement;
class MenuBarListener final : public nsIDOMEventListener {
public:
explicit MenuBarListener(XULMenuBarElement&);
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(MenuBarListener)
NS_DECL_NSIDOMEVENTLISTENER
// Should be called when unbound from the document and so on.
void Detach();
protected:
virtual ~MenuBarListener();
bool IsMenuOpen() const;
MOZ_CAN_RUN_SCRIPT nsresult KeyUp(Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT nsresult KeyDown(Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT nsresult KeyPress(Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT nsresult Blur(Event* aEvent);
MOZ_CAN_RUN_SCRIPT nsresult OnWindowDeactivated(Event* aEvent);
MOZ_CAN_RUN_SCRIPT nsresult MouseDown(Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT nsresult Fullscreen(Event* aEvent);
/**
* Given a key event for an Alt+shortcut combination,
* return the menu, if any, that would be opened. If aPeek
* is false, then play a beep and deactivate the menubar on Windows.
*/
XULButtonElement* GetMenuForKeyEvent(KeyboardEvent& aKeyEvent);
/**
* Call MarkAsReservedByChrome if the user's preferences indicate that
* the key should be chrome-only.
*/
void ReserveKeyIfNeeded(Event* aKeyEvent);
// This should only be called by the MenuBarListener during event dispatch.
enum class ByKeyboard : bool { No, Yes };
MOZ_CAN_RUN_SCRIPT void ToggleMenuActiveState(ByKeyboard);
bool Destroyed() const { return !mMenuBar; }
// The menu bar object. Safe because it keeps us alive.
XULMenuBarElement* mMenuBar;
// The event target to listen to the events.
//
// Weak reference is safe because we clear the listener on unbind from the
// document.
Document* mEventTarget;
// The top window as EventTarget.
RefPtr<EventTarget> mTopWindowEventTarget;
// Whether or not the ALT key is currently down.
bool mAccessKeyDown = false;
// Whether or not the ALT key down is canceled by other action.
bool mAccessKeyDownCanceled = false;
};
} // namespace mozilla::dom
#endif // #ifndef mozilla_dom_MenuBarListener_h

View file

@ -18,12 +18,12 @@
#include "mozilla/dom/MouseEventBinding.h" #include "mozilla/dom/MouseEventBinding.h"
#include "mozilla/dom/NameSpaceConstants.h" #include "mozilla/dom/NameSpaceConstants.h"
#include "mozilla/dom/AncestorIterator.h" #include "mozilla/dom/AncestorIterator.h"
#include "mozilla/dom/XULMenuBarElement.h"
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "nsITimer.h" #include "nsITimer.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "nsCaseTreatment.h" #include "nsCaseTreatment.h"
#include "nsChangeHint.h" #include "nsChangeHint.h"
#include "nsMenuBarFrame.h"
#include "nsMenuPopupFrame.h" #include "nsMenuPopupFrame.h"
#include "nsPlaceholderFrame.h" #include "nsPlaceholderFrame.h"
#include "nsPresContext.h" #include "nsPresContext.h"
@ -444,7 +444,8 @@ void XULButtonElement::PostHandleEventForMenus(
// If we're open we never deselect. PopupClosed will do as needed. // If we're open we never deselect. PopupClosed will do as needed.
return false; return false;
} }
if (!parent->IsMenuBar()) { auto* menubar = XULMenuBarElement::FromNode(*parent);
if (!menubar) {
// Don't de-select when not in the menubar. // Don't de-select when not in the menubar.
// NOTE(emilio): Behavior from before bug 1811466 is equivalent to // NOTE(emilio): Behavior from before bug 1811466 is equivalent to
// returning true here, consider flipping this. // returning true here, consider flipping this.
@ -452,9 +453,7 @@ void XULButtonElement::PostHandleEventForMenus(
} }
// De-select when exiting a menubar item, if the menubar wasn't // De-select when exiting a menubar item, if the menubar wasn't
// activated by keyboard. // activated by keyboard.
nsMenuBarFrame* menubar = do_QueryFrame(parent->GetPrimaryFrame()); return !menubar->IsActiveByKeyboard();
const bool openedByKey = menubar && menubar->IsActiveByKeyboard();
return !openedByKey;
}(); }();
if (shouldDeactivate) { if (shouldDeactivate) {
@ -756,17 +755,11 @@ auto XULButtonElement::GetMenuType() const -> Maybe<MenuType> {
} }
} }
nsMenuBarFrame* XULButtonElement::GetMenuBar(FlushType aFlushType) { XULMenuBarElement* XULButtonElement::GetMenuBar() const {
if (!IsMenu()) { if (!IsMenu()) {
return nullptr; return nullptr;
} }
nsIFrame* frame = GetPrimaryFrame(aFlushType); return FirstAncestorOfType<XULMenuBarElement>();
for (; frame; frame = frame->GetParent()) {
if (nsMenuBarFrame* menubar = do_QueryFrame(frame)) {
return menubar;
}
}
return nullptr;
} }
XULMenuParentElement* XULButtonElement::GetMenuParent() const { XULMenuParentElement* XULButtonElement::GetMenuParent() const {
@ -800,8 +793,8 @@ nsMenuPopupFrame* XULButtonElement::GetMenuPopup(FlushType aFlushType) {
return do_QueryFrame(popup->GetPrimaryFrame(aFlushType)); return do_QueryFrame(popup->GetPrimaryFrame(aFlushType));
} }
bool XULButtonElement::OpenedWithKey() { bool XULButtonElement::OpenedWithKey() const {
nsMenuBarFrame* menubar = GetMenuBar(FlushType::Frames); auto* menubar = GetMenuBar();
return menubar && menubar->IsActiveByKeyboard(); return menubar && menubar->IsActiveByKeyboard();
} }

View file

@ -19,6 +19,7 @@ namespace mozilla::dom {
class KeyboardEvent; class KeyboardEvent;
class XULPopupElement; class XULPopupElement;
class XULMenuBarElement;
class XULMenuParentElement; class XULMenuParentElement;
class XULButtonElement : public nsXULElement { class XULButtonElement : public nsXULElement {
@ -57,7 +58,7 @@ class XULButtonElement : public nsXULElement {
void UnbindFromTree(bool aNullParent) override; void UnbindFromTree(bool aNullParent) override;
MOZ_CAN_RUN_SCRIPT bool HandleKeyPress(KeyboardEvent& keyEvent); MOZ_CAN_RUN_SCRIPT bool HandleKeyPress(KeyboardEvent& keyEvent);
MOZ_CAN_RUN_SCRIPT bool OpenedWithKey(); bool OpenedWithKey() const;
// Called to execute our command handler. // Called to execute our command handler.
MOZ_CAN_RUN_SCRIPT void ExecuteMenu(WidgetEvent&); MOZ_CAN_RUN_SCRIPT void ExecuteMenu(WidgetEvent&);
MOZ_CAN_RUN_SCRIPT void ExecuteMenu(Modifiers, int16_t aButton, MOZ_CAN_RUN_SCRIPT void ExecuteMenu(Modifiers, int16_t aButton,
@ -93,8 +94,8 @@ class XULButtonElement : public nsXULElement {
bool IsDisabled() const { return GetXULBoolAttr(nsGkAtoms::disabled); } bool IsDisabled() const { return GetXULBoolAttr(nsGkAtoms::disabled); }
private: private:
XULMenuBarElement* GetMenuBar() const;
void Blurred(); void Blurred();
nsMenuBarFrame* GetMenuBar(FlushType aFlushType);
enum class MenuType { enum class MenuType {
Checkbox, Checkbox,
Radio, Radio,

View file

@ -0,0 +1,92 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "XULMenuBarElement.h"
#include "MenuBarListener.h"
#include "XULButtonElement.h"
#include "nsXULPopupManager.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/BindContext.h"
#include "mozilla/AsyncEventDispatcher.h"
namespace mozilla::dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED(XULMenuBarElement, XULMenuParentElement,
mListener)
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(XULMenuBarElement,
XULMenuParentElement)
XULMenuBarElement::XULMenuBarElement(
already_AddRefed<class NodeInfo>&& aNodeInfo)
: XULMenuParentElement(std::move(aNodeInfo)) {}
XULMenuBarElement::~XULMenuBarElement() { MOZ_DIAGNOSTIC_ASSERT(!mListener); }
void XULMenuBarElement::SetActive(bool aActiveFlag) {
// If the activity is not changed, there is nothing to do.
if (mIsActive == aActiveFlag) {
return;
}
// We can't activate a menubar outside of the document.
if (!IsInComposedDoc()) {
MOZ_ASSERT(!mIsActive, "How?");
return;
}
if (!aActiveFlag) {
// If there is a request to deactivate the menu bar, check to see whether
// there is a menu popup open for the menu bar. In this case, don't
// deactivate the menu bar.
if (auto* activeChild = GetActiveMenuChild()) {
if (activeChild->IsMenuPopupOpen()) {
return;
}
}
}
mIsActive = aActiveFlag;
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
pm->SetActiveMenuBar(this, aActiveFlag);
}
if (!aActiveFlag) {
mActiveByKeyboard = false;
SetActiveMenuChild(nullptr);
}
RefPtr dispatcher = new AsyncEventDispatcher(
this, aActiveFlag ? u"DOMMenuBarActive"_ns : u"DOMMenuBarInactive"_ns,
CanBubble::eYes, ChromeOnlyDispatch::eNo);
DebugOnly<nsresult> rv = dispatcher->PostDOMEvent();
NS_ASSERTION(NS_SUCCEEDED(rv), "AsyncEventDispatcher failed to dispatch");
}
nsresult XULMenuBarElement::BindToTree(BindContext& aContext,
nsINode& aParent) {
MOZ_TRY(XULMenuParentElement::BindToTree(aContext, aParent));
MOZ_DIAGNOSTIC_ASSERT(!mListener);
if (aContext.InComposedDoc()) {
mListener = new MenuBarListener(*this);
}
return NS_OK;
}
void XULMenuBarElement::UnbindFromTree(bool aNullParent) {
if (mListener) {
mListener->Detach();
mListener = nullptr;
}
if (NS_WARN_IF(mIsActive)) {
// Clean up silently when getting removed from the document while active.
mIsActive = false;
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
pm->SetActiveMenuBar(this, false);
}
}
return XULMenuParentElement::UnbindFromTree(aNullParent);
}
} // namespace mozilla::dom

View file

@ -0,0 +1,61 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef XULMenuBarElement_h__
#define XULMenuBarElement_h__
#include "mozilla/Attributes.h"
#include "mozilla/dom/NameSpaceConstants.h"
#include "nsINode.h"
#include "nsISupports.h"
#include "XULMenuParentElement.h"
namespace mozilla::dom {
class KeyboardEvent;
class XULButtonElement;
class MenuBarListener;
nsXULElement* NS_NewXULMenuBarElement(
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
class XULMenuBarElement final : public XULMenuParentElement {
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(XULMenuBarElement,
XULMenuParentElement)
NS_IMPL_FROMNODE_WITH_TAG(XULMenuBarElement, kNameSpaceID_XUL, menubar)
explicit XULMenuBarElement(already_AddRefed<class NodeInfo>&&);
MOZ_CAN_RUN_SCRIPT void SetActive(bool);
bool IsActive() const { return mIsActive; }
void SetActiveByKeyboard() { mActiveByKeyboard = true; }
bool IsActiveByKeyboard() const { return mActiveByKeyboard; }
MOZ_CAN_RUN_SCRIPT void MenuClosed() { SetActive(false); }
nsresult BindToTree(BindContext&, nsINode& aParent) override;
void UnbindFromTree(bool aNullParent) override;
protected:
~XULMenuBarElement() override;
// Whether or not the menu bar is active (a menu item is highlighted or
// shown).
bool mIsActive = false;
// Whether the menubar was made active via the keyboard.
bool mActiveByKeyboard = false;
// The event listener that listens to document key presses and so on.
RefPtr<MenuBarListener> mListener;
};
} // namespace mozilla::dom
#endif // XULMenuBarElement_h

View file

@ -11,7 +11,6 @@
#include "mozilla/dom/XULPopupElement.h" #include "mozilla/dom/XULPopupElement.h"
#include "mozilla/dom/KeyboardEvent.h" #include "mozilla/dom/KeyboardEvent.h"
#include "mozilla/dom/KeyboardEventBinding.h" #include "mozilla/dom/KeyboardEventBinding.h"
#include "nsMenuBarListener.h"
#include "nsXULPopupManager.h" #include "nsXULPopupManager.h"
#include "nsMenuPopupFrame.h" #include "nsMenuPopupFrame.h"

View file

@ -5,20 +5,20 @@
#include "XULMenuParentElement.h" #include "XULMenuParentElement.h"
#include "XULButtonElement.h" #include "XULButtonElement.h"
#include "XULMenuBarElement.h"
#include "XULPopupElement.h" #include "XULPopupElement.h"
#include "mozilla/LookAndFeel.h" #include "mozilla/LookAndFeel.h"
#include "mozilla/StaticAnalysisFunctions.h"
#include "mozilla/TextEvents.h" #include "mozilla/TextEvents.h"
#include "mozilla/dom/DocumentInlines.h" #include "mozilla/dom/DocumentInlines.h"
#include "mozilla/dom/KeyboardEvent.h" #include "mozilla/dom/KeyboardEvent.h"
#include "mozilla/EventDispatcher.h" #include "mozilla/EventDispatcher.h"
#include "nsDebug.h" #include "nsDebug.h"
#include "nsMenuBarFrame.h"
#include "nsMenuPopupFrame.h" #include "nsMenuPopupFrame.h"
#include "nsString.h" #include "nsString.h"
#include "nsStringFwd.h" #include "nsStringFwd.h"
#include "nsUTF8Utils.h" #include "nsUTF8Utils.h"
#include "nsXULElement.h" #include "nsXULElement.h"
#include "nsMenuBarListener.h"
#include "nsXULPopupManager.h" #include "nsXULPopupManager.h"
namespace mozilla::dom { namespace mozilla::dom {
@ -127,8 +127,9 @@ void XULMenuParentElement::SetActiveMenuChild(XULButtonElement* aChild,
} }
mActiveItem = nullptr; mActiveItem = nullptr;
if (nsMenuBarFrame* f = do_QueryFrame(GetPrimaryFrame())) { if (auto* menuBar = XULMenuBarElement::FromNode(*this)) {
f->SetActive(!!aChild); // KnownLive because `this` is known-live by definition.
MOZ_KnownLive(menuBar)->SetActive(!!aChild);
} }
if (!aChild) { if (!aChild) {
@ -388,4 +389,10 @@ XULButtonElement* XULMenuParentElement::FindMenuWithShortcut(
return foundMenuBeforeCurrent; return foundMenuBeforeCurrent;
} }
void XULMenuParentElement::HandleEnterKeyPress(WidgetEvent& aEvent) {
if (RefPtr child = GetActiveMenuChild()) {
child->HandleEnterKeyPress(aEvent);
}
}
} // namespace mozilla::dom } // namespace mozilla::dom

View file

@ -41,6 +41,7 @@ class XULMenuParentElement : public nsXULElement {
XULButtonElement* FindMenuWithShortcut(KeyboardEvent&) const; XULButtonElement* FindMenuWithShortcut(KeyboardEvent&) const;
XULButtonElement* FindMenuWithShortcut(const nsAString& aString, XULButtonElement* FindMenuWithShortcut(const nsAString& aString,
bool& aDoAction) const; bool& aDoAction) const;
MOZ_CAN_RUN_SCRIPT void HandleEnterKeyPress(WidgetEvent&);
NS_IMPL_FROMNODE_HELPER(XULMenuParentElement, NS_IMPL_FROMNODE_HELPER(XULMenuParentElement,
IsAnyOfXULElements(nsGkAtoms::menupopup, IsAnyOfXULElements(nsGkAtoms::menupopup,

View file

@ -7,7 +7,6 @@
#include "XULMenuParentElement.h" #include "XULMenuParentElement.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsMenuBarListener.h"
#include "nsNameSpaceManager.h" #include "nsNameSpaceManager.h"
#include "nsGkAtoms.h" #include "nsGkAtoms.h"
#include "nsMenuPopupFrame.h" #include "nsMenuPopupFrame.h"

View file

@ -24,6 +24,7 @@ EXPORTS.mozilla.dom += [
"XULBroadcastManager.h", "XULBroadcastManager.h",
"XULButtonElement.h", "XULButtonElement.h",
"XULFrameElement.h", "XULFrameElement.h",
"XULMenuBarElement.h",
"XULMenuElement.h", "XULMenuElement.h",
"XULMenuParentElement.h", "XULMenuParentElement.h",
"XULPersist.h", "XULPersist.h",
@ -35,6 +36,7 @@ EXPORTS.mozilla.dom += [
] ]
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
"MenuBarListener.cpp",
"nsXULCommandDispatcher.cpp", "nsXULCommandDispatcher.cpp",
"nsXULContentSink.cpp", "nsXULContentSink.cpp",
"nsXULContentUtils.cpp", "nsXULContentUtils.cpp",
@ -46,6 +48,7 @@ UNIFIED_SOURCES += [
"XULBroadcastManager.cpp", "XULBroadcastManager.cpp",
"XULButtonElement.cpp", "XULButtonElement.cpp",
"XULFrameElement.cpp", "XULFrameElement.cpp",
"XULMenuBarElement.cpp",
"XULMenuElement.cpp", "XULMenuElement.cpp",
"XULMenuParentElement.cpp", "XULMenuParentElement.cpp",
"XULPersist.cpp", "XULPersist.cpp",

View file

@ -14,6 +14,7 @@
#include "XULButtonElement.h" #include "XULButtonElement.h"
#include "XULFrameElement.h" #include "XULFrameElement.h"
#include "XULMenuElement.h" #include "XULMenuElement.h"
#include "XULMenuBarElement.h"
#include "XULPopupElement.h" #include "XULPopupElement.h"
#include "XULResizerElement.h" #include "XULResizerElement.h"
#include "XULTextElement.h" #include "XULTextElement.h"
@ -185,7 +186,7 @@ nsXULElement* nsXULElement::Construct(
if (nodeInfo->Equals(nsGkAtoms::menubar)) { if (nodeInfo->Equals(nsGkAtoms::menubar)) {
auto* nim = nodeInfo->NodeInfoManager(); auto* nim = nodeInfo->NodeInfoManager();
return new (nim) XULMenuParentElement(nodeInfo.forget()); return new (nim) XULMenuBarElement(nodeInfo.forget());
} }
if (nodeInfo->Equals(nsGkAtoms::menu) || if (nodeInfo->Equals(nsGkAtoms::menu) ||

View file

@ -39,7 +39,6 @@
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "RetainedDisplayListBuilder.h" #include "RetainedDisplayListBuilder.h"
#include "nsAbsoluteContainingBlock.h" #include "nsAbsoluteContainingBlock.h"
#include "nsMenuBarListener.h"
#include "nsCSSPseudoElements.h" #include "nsCSSPseudoElements.h"
#include "nsCheckboxRadioFrame.h" #include "nsCheckboxRadioFrame.h"
#include "nsCRT.h" #include "nsCRT.h"
@ -221,8 +220,6 @@ nsIFrame* NS_NewMenuPopupFrame(PresShell* aPresShell, ComputedStyle* aStyle);
nsIFrame* NS_NewMenuFrame(PresShell* aPresShell, ComputedStyle* aStyle, nsIFrame* NS_NewMenuFrame(PresShell* aPresShell, ComputedStyle* aStyle,
uint32_t aFlags); uint32_t aFlags);
nsIFrame* NS_NewMenuBarFrame(PresShell* aPresShell, ComputedStyle* aStyle);
nsIFrame* NS_NewTreeBodyFrame(PresShell* aPresShell, ComputedStyle* aStyle); nsIFrame* NS_NewTreeBodyFrame(PresShell* aPresShell, ComputedStyle* aStyle);
nsHTMLScrollFrame* NS_NewHTMLScrollFrame(PresShell* aPresShell, nsHTMLScrollFrame* NS_NewHTMLScrollFrame(PresShell* aPresShell,
@ -4155,8 +4152,6 @@ nsCSSFrameConstructor::FindXULTagData(const Element& aElement,
nsCSSFrameConstructor::FindXULLabelOrDescriptionData), nsCSSFrameConstructor::FindXULLabelOrDescriptionData),
#ifdef XP_MACOSX #ifdef XP_MACOSX
SIMPLE_TAG_CHAIN(menubar, nsCSSFrameConstructor::FindXULMenubarData), SIMPLE_TAG_CHAIN(menubar, nsCSSFrameConstructor::FindXULMenubarData),
#else
SIMPLE_XUL_CREATE(menubar, NS_NewMenuBarFrame),
#endif /* XP_MACOSX */ #endif /* XP_MACOSX */
SIMPLE_XUL_CREATE(iframe, NS_NewSubDocumentFrame), SIMPLE_XUL_CREATE(iframe, NS_NewSubDocumentFrame),
SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame), SIMPLE_XUL_CREATE(editor, NS_NewSubDocumentFrame),
@ -4209,9 +4204,7 @@ nsCSSFrameConstructor::FindXULMenubarData(const Element& aElement,
} }
} }
static constexpr FrameConstructionData sMenubarData = return nullptr;
SIMPLE_XUL_FCDATA(NS_NewMenuBarFrame);
return &sMenubarData;
} }
#endif /* XP_MACOSX */ #endif /* XP_MACOSX */

View file

@ -63,7 +63,6 @@ FRAME_CLASSES = [
Frame("nsMathMLmunderoverFrame", "None", NOT_LEAF), Frame("nsMathMLmunderoverFrame", "None", NOT_LEAF),
Frame("nsMathMLsemanticsFrame", "None", NOT_LEAF), Frame("nsMathMLsemanticsFrame", "None", NOT_LEAF),
Frame("nsMathMLTokenFrame", "None", NOT_LEAF), Frame("nsMathMLTokenFrame", "None", NOT_LEAF),
Frame("nsMenuBarFrame", "Box", NOT_LEAF),
Frame("nsMenuPopupFrame", "MenuPopup", NOT_LEAF), Frame("nsMenuPopupFrame", "MenuPopup", NOT_LEAF),
Frame("nsMeterFrame", "Meter", LEAF), Frame("nsMeterFrame", "Meter", LEAF),
Frame("nsNumberControlFrame", "TextInput", LEAF), Frame("nsNumberControlFrame", "TextInput", LEAF),

View file

@ -25,8 +25,6 @@ UNIFIED_SOURCES += [
"nsBoxLayoutState.cpp", "nsBoxLayoutState.cpp",
"nsImageBoxFrame.cpp", "nsImageBoxFrame.cpp",
"nsLeafBoxFrame.cpp", "nsLeafBoxFrame.cpp",
"nsMenuBarFrame.cpp",
"nsMenuBarListener.cpp",
"nsMenuPopupFrame.cpp", "nsMenuPopupFrame.cpp",
"nsRepeatService.cpp", "nsRepeatService.cpp",
"nsScrollbarButtonFrame.cpp", "nsScrollbarButtonFrame.cpp",

View file

@ -1,136 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 "nsMenuBarFrame.h"
#include "mozilla/BasicEvents.h"
#include "nsIContent.h"
#include "nsAtom.h"
#include "nsPresContext.h"
#include "nsCSSRendering.h"
#include "nsNameSpaceManager.h"
#include "nsGkAtoms.h"
#include "nsMenuPopupFrame.h"
#include "nsUnicharUtils.h"
#include "nsPIDOMWindow.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsCSSFrameConstructor.h"
#ifdef XP_WIN
# include "nsISound.h"
# include "nsWidgetsCID.h"
#endif
#include "nsUTF8Utils.h"
#include "mozilla/ComputedStyle.h"
#include "mozilla/PresShell.h"
#include "mozilla/dom/Document.h"
#include "mozilla/dom/XULMenuParentElement.h"
#include "mozilla/dom/XULButtonElement.h"
using namespace mozilla;
//
// NS_NewMenuBarFrame
//
// Wrapper for creating a new menu Bar container
//
nsIFrame* NS_NewMenuBarFrame(PresShell* aPresShell, ComputedStyle* aStyle) {
return new (aPresShell) nsMenuBarFrame(aStyle, aPresShell->GetPresContext());
}
NS_IMPL_FRAMEARENA_HELPERS(nsMenuBarFrame)
NS_QUERYFRAME_HEAD(nsMenuBarFrame)
NS_QUERYFRAME_ENTRY(nsMenuBarFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsBoxFrame)
//
// nsMenuBarFrame cntr
//
nsMenuBarFrame::nsMenuBarFrame(ComputedStyle* aStyle,
nsPresContext* aPresContext)
: nsBoxFrame(aStyle, aPresContext, kClassID) {}
void nsMenuBarFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) {
nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
// Create the menu bar listener.
mMenuBarListener = new nsMenuBarListener(this, aContent);
}
dom::XULMenuParentElement& nsMenuBarFrame::MenubarElement() const {
auto* content = dom::XULMenuParentElement::FromNode(GetContent());
MOZ_DIAGNOSTIC_ASSERT(content);
return *content;
}
MOZ_CAN_RUN_SCRIPT void nsMenuBarFrame::SetActive(bool aActiveFlag) {
// If the activity is not changed, there is nothing to do.
if (mIsActive == aActiveFlag) {
return;
}
if (!aActiveFlag) {
// If there is a request to deactivate the menu bar, check to see whether
// there is a menu popup open for the menu bar. In this case, don't
// deactivate the menu bar.
if (auto* activeChild = MenubarElement().GetActiveMenuChild()) {
if (activeChild->IsMenuPopupOpen()) {
return;
}
}
}
mIsActive = aActiveFlag;
if (mIsActive) {
InstallKeyboardNavigator();
} else {
mActiveByKeyboard = false;
RemoveKeyboardNavigator();
}
RefPtr menubar = &MenubarElement();
if (!aActiveFlag) {
menubar->SetActiveMenuChild(nullptr);
}
constexpr auto active = u"DOMMenuBarActive"_ns;
constexpr auto inactive = u"DOMMenuBarInactive"_ns;
FireDOMEvent(aActiveFlag ? active : inactive, menubar);
}
void nsMenuBarFrame::InstallKeyboardNavigator() {
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
pm->SetActiveMenuBar(this, true);
}
}
void nsMenuBarFrame::MenuClosed() { SetActive(false); }
void nsMenuBarFrame::HandleEnterKeyPress(WidgetEvent& aEvent) {
if (RefPtr<dom::XULButtonElement> activeChild =
MenubarElement().GetActiveMenuChild()) {
activeChild->HandleEnterKeyPress(aEvent);
}
}
void nsMenuBarFrame::RemoveKeyboardNavigator() {
if (!mIsActive) {
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
pm->SetActiveMenuBar(this, false);
}
}
}
void nsMenuBarFrame::DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) {
nsXULPopupManager* pm = nsXULPopupManager::GetInstance();
if (pm) pm->SetActiveMenuBar(this, false);
mMenuBarListener->OnDestroyMenuBarFrame();
mMenuBarListener = nullptr;
nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
}

View file

@ -1,83 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
//
// nsMenuBarFrame
//
#ifndef nsMenuBarFrame_h__
#define nsMenuBarFrame_h__
#include "nsAtom.h"
#include "nsCOMPtr.h"
#include "nsBoxFrame.h"
#include "nsMenuBarListener.h"
class nsIContent;
namespace mozilla {
class PresShell;
namespace dom {
class KeyboardEvent;
class XULMenuParentElement;
} // namespace dom
} // namespace mozilla
nsIFrame* NS_NewMenuBarFrame(mozilla::PresShell* aPresShell,
mozilla::ComputedStyle* aStyle);
class nsMenuBarFrame final : public nsBoxFrame {
public:
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsMenuBarFrame)
explicit nsMenuBarFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
void InstallKeyboardNavigator();
void RemoveKeyboardNavigator();
MOZ_CAN_RUN_SCRIPT void MenuClosed();
void Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) override;
void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) override;
bool IsActiveByKeyboard() { return mActiveByKeyboard; }
void SetActiveByKeyboard() { mActiveByKeyboard = true; }
MOZ_CAN_RUN_SCRIPT void SetActive(bool aActive);
bool IsActive() const { return mIsActive; }
mozilla::dom::XULMenuParentElement& MenubarElement() const;
// Called when Enter is pressed while the menubar is focused. If the current
// menu is open, let the child handle the key.
MOZ_CAN_RUN_SCRIPT void HandleEnterKeyPress(mozilla::WidgetEvent&);
bool IsFrameOfType(uint32_t aFlags) const override {
// Override bogus IsFrameOfType in nsBoxFrame.
if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
return false;
return nsBoxFrame::IsFrameOfType(aFlags);
}
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const override {
return MakeFrameName(u"MenuBar"_ns, aResult);
}
#endif
protected:
RefPtr<nsMenuBarListener> mMenuBarListener; // The listener that tells us
// about key and mouse events.
bool mIsActive = false; // Whether or not the menu bar is active (a menu item
// is highlighted or shown).
// Whether the menubar was made active via the keyboard.
bool mActiveByKeyboard = false;
}; // class nsMenuBarFrame
#endif

View file

@ -1,100 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef nsMenuBarListener_h
#define nsMenuBarListener_h
#include "mozilla/Attributes.h"
#include "mozilla/EventForwards.h"
#include "nsIContent.h"
#include "nsIDOMEventListener.h"
// X.h defines KeyPress
#ifdef KeyPress
# undef KeyPress
#endif
class nsMenuFrame;
class nsMenuBarFrame;
namespace mozilla {
namespace dom {
class EventTarget;
class KeyboardEvent;
class XULMenuParentElement;
class XULButtonElement;
} // namespace dom
} // namespace mozilla
/**
* EventListener implementation for menubar.
*/
class nsMenuBarListener final : public nsIDOMEventListener {
public:
explicit nsMenuBarListener(nsMenuBarFrame* aMenuBarFrame,
nsIContent* aMenuBarContent);
NS_DECL_ISUPPORTS
/**
* nsIDOMEventListener interface method.
*/
NS_DECL_NSIDOMEVENTLISTENER
/**
* When mMenuBarFrame is being destroyed, this should be called.
*/
void OnDestroyMenuBarFrame();
protected:
virtual ~nsMenuBarListener();
bool IsMenuOpen() const;
MOZ_CAN_RUN_SCRIPT nsresult KeyUp(mozilla::dom::Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT nsresult KeyDown(mozilla::dom::Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT nsresult KeyPress(mozilla::dom::Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT nsresult Blur(mozilla::dom::Event* aEvent);
MOZ_CAN_RUN_SCRIPT nsresult OnWindowDeactivated(mozilla::dom::Event* aEvent);
MOZ_CAN_RUN_SCRIPT nsresult MouseDown(mozilla::dom::Event* aMouseEvent);
MOZ_CAN_RUN_SCRIPT nsresult Fullscreen(mozilla::dom::Event* aEvent);
/**
* Given a key event for an Alt+shortcut combination,
* return the menu, if any, that would be opened. If aPeek
* is false, then play a beep and deactivate the menubar on Windows.
*/
mozilla::dom::XULButtonElement* GetMenuForKeyEvent(
mozilla::dom::KeyboardEvent& aKeyEvent);
/**
* Call MarkAsReservedByChrome if the user's preferences indicate that
* the key should be chrome-only.
*/
void ReserveKeyIfNeeded(mozilla::dom::Event* aKeyEvent);
// This should only be called by the nsMenuBarListener during event dispatch,
// thus ensuring that this doesn't get destroyed during the process.
MOZ_CAN_RUN_SCRIPT void ToggleMenuActiveState();
bool Destroyed() const { return !mMenuBarFrame; }
// The menu bar object.
nsMenuBarFrame* mMenuBarFrame;
mozilla::dom::XULMenuParentElement* mContent;
// The event target to listen to the events.
// XXX Should this store this as strong reference? However,
// OnDestroyMenuBarFrame() should be called at destroying mMenuBarFrame.
// So, weak reference must be safe.
mozilla::dom::EventTarget* mEventTarget;
// The top window as EventTarget.
mozilla::dom::EventTarget* mTopWindowEventTarget;
// Whether or not the ALT key is currently down.
bool mAccessKeyDown;
// Whether or not the ALT key down is canceled by other action.
bool mAccessKeyDownCanceled;
};
#endif // #ifndef nsMenuBarListener_h

View file

@ -19,7 +19,6 @@
#include "nsIFrameInlines.h" #include "nsIFrameInlines.h"
#include "nsViewManager.h" #include "nsViewManager.h"
#include "nsWidgetsCID.h" #include "nsWidgetsCID.h"
#include "nsMenuBarFrame.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "nsFrameManager.h" #include "nsFrameManager.h"
#include "mozilla/dom/Document.h" #include "mozilla/dom/Document.h"
@ -2028,10 +2027,8 @@ nsIFrame* nsMenuPopupFrame::GetCurrentMenuItemFrame() const {
void nsMenuPopupFrame::HandleEnterKeyPress(WidgetEvent& aEvent) { void nsMenuPopupFrame::HandleEnterKeyPress(WidgetEvent& aEvent) {
mIncrementalString.Truncate(); mIncrementalString.Truncate();
if (RefPtr menu = GetCurrentMenuItem()) { RefPtr popup = &PopupElement();
// Give it to the child. popup->HandleEnterKeyPress(aEvent);
menu->HandleEnterKeyPress(aEvent);
}
} }
XULButtonElement* nsMenuPopupFrame::FindMenuWithShortcut( XULButtonElement* nsMenuPopupFrame::FindMenuWithShortcut(

View file

@ -26,7 +26,6 @@
#include "nsIContent.h" #include "nsIContent.h"
#include "nsNameSpaceManager.h" #include "nsNameSpaceManager.h"
#include "nsBoxLayoutState.h" #include "nsBoxLayoutState.h"
#include "nsMenuBarListener.h"
#include "nsString.h" #include "nsString.h"
#include "nsITheme.h" #include "nsITheme.h"
#include "nsUnicharUtils.h" #include "nsUnicharUtils.h"

View file

@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "XULButtonElement.h" #include "XULButtonElement.h"
#include "XULMenuParentElement.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/FlushType.h" #include "mozilla/FlushType.h"
@ -14,8 +13,6 @@
#include "nsISound.h" #include "nsISound.h"
#include "nsXULPopupManager.h" #include "nsXULPopupManager.h"
#include "nsMenuPopupFrame.h" #include "nsMenuPopupFrame.h"
#include "nsMenuBarFrame.h"
#include "nsMenuBarListener.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsXULElement.h" #include "nsXULElement.h"
#include "nsIDOMXULCommandDispatcher.h" #include "nsIDOMXULCommandDispatcher.h"
@ -50,6 +47,7 @@
#include "mozilla/dom/PopupPositionedEventBinding.h" #include "mozilla/dom/PopupPositionedEventBinding.h"
#include "mozilla/dom/XULCommandEvent.h" #include "mozilla/dom/XULCommandEvent.h"
#include "mozilla/dom/XULMenuElement.h" #include "mozilla/dom/XULMenuElement.h"
#include "mozilla/dom/XULMenuBarElement.h"
#include "mozilla/dom/XULPopupElement.h" #include "mozilla/dom/XULPopupElement.h"
#include "mozilla/EventDispatcher.h" #include "mozilla/EventDispatcher.h"
#include "mozilla/EventStateManager.h" #include "mozilla/EventStateManager.h"
@ -77,6 +75,17 @@ static_assert(KeyboardEvent_Binding::DOM_VK_HOME ==
KeyboardEvent_Binding::DOM_VK_END + 5, KeyboardEvent_Binding::DOM_VK_END + 5,
"nsXULPopupManager assumes some keyCode values are consecutive"); "nsXULPopupManager assumes some keyCode values are consecutive");
#define NS_DIRECTION_IS_INLINE(dir) \
(dir == eNavigationDirection_Start || dir == eNavigationDirection_End)
#define NS_DIRECTION_IS_BLOCK(dir) \
(dir == eNavigationDirection_Before || dir == eNavigationDirection_After)
#define NS_DIRECTION_IS_BLOCK_TO_EDGE(dir) \
(dir == eNavigationDirection_First || dir == eNavigationDirection_Last)
static_assert(static_cast<uint8_t>(mozilla::StyleDirection::Ltr) == 0 &&
static_cast<uint8_t>(mozilla::StyleDirection::Rtl) == 1,
"Left to Right should be 0 and Right to Left should be 1");
const nsNavigationDirection DirectionFromKeyCodeTable[2][6] = { const nsNavigationDirection DirectionFromKeyCodeTable[2][6] = {
{ {
eNavigationDirection_Last, // KeyboardEvent_Binding::DOM_VK_END eNavigationDirection_Last, // KeyboardEvent_Binding::DOM_VK_END
@ -707,7 +716,7 @@ nsMenuChainItem* nsXULPopupManager::GetRollupItem(RollupKind aKind) {
return nullptr; return nullptr;
} }
void nsXULPopupManager::SetActiveMenuBar(nsMenuBarFrame* aMenuBar, void nsXULPopupManager::SetActiveMenuBar(XULMenuBarElement* aMenuBar,
bool aActivate) { bool aActivate) {
if (aActivate) { if (aActivate) {
mActiveMenuBar = aMenuBar; mActiveMenuBar = aMenuBar;
@ -2010,7 +2019,7 @@ void nsXULPopupManager::UpdateKeyboardListeners() {
} }
isForMenu = item->GetPopupType() == PopupType::Menu; isForMenu = item->GetPopupType() == PopupType::Menu;
} else if (mActiveMenuBar) { } else if (mActiveMenuBar) {
newTarget = mActiveMenuBar->GetContent()->GetComposedDoc(); newTarget = mActiveMenuBar->GetComposedDoc();
isForMenu = true; isForMenu = true;
} }
@ -2209,7 +2218,7 @@ bool nsXULPopupManager::HandleShortcutNavigation(KeyboardEvent& aKeyEvent,
} }
if (mActiveMenuBar) { if (mActiveMenuBar) {
RefPtr menubar = &mActiveMenuBar->MenubarElement(); RefPtr menubar = mActiveMenuBar;
if (RefPtr result = menubar->FindMenuWithShortcut(aKeyEvent)) { if (RefPtr result = menubar->FindMenuWithShortcut(aKeyEvent)) {
result->OpenMenuPopup(true); result->OpenMenuPopup(true);
return true; return true;
@ -2222,7 +2231,7 @@ bool nsXULPopupManager::HandleShortcutNavigation(KeyboardEvent& aKeyEvent,
if (nsCOMPtr<nsISound> sound = do_GetService("@mozilla.org/sound;1")) { if (nsCOMPtr<nsISound> sound = do_GetService("@mozilla.org/sound;1")) {
sound->Beep(); sound->Beep();
} }
mActiveMenuBar->SetActive(false); menubar->SetActive(false);
#endif #endif
} }
return false; return false;
@ -2264,7 +2273,10 @@ bool nsXULPopupManager::HandleKeyboardNavigation(uint32_t aKeyCode) {
if (item) { if (item) {
itemFrame = item->Frame(); itemFrame = item->Frame();
} else if (mActiveMenuBar) { } else if (mActiveMenuBar) {
itemFrame = mActiveMenuBar; itemFrame = mActiveMenuBar->GetPrimaryFrame();
if (!itemFrame) {
return false;
}
} else { } else {
return false; return false;
} }
@ -2301,7 +2313,7 @@ bool nsXULPopupManager::HandleKeyboardNavigation(uint32_t aKeyCode) {
if (!mActiveMenuBar) { if (!mActiveMenuBar) {
return false; return false;
} }
RefPtr menubar = XULMenuParentElement::FromNode(mActiveMenuBar->GetContent()); RefPtr menubar = mActiveMenuBar;
if (NS_DIRECTION_IS_INLINE(theDirection)) { if (NS_DIRECTION_IS_INLINE(theDirection)) {
RefPtr prevActiveItem = menubar->GetActiveMenuChild(); RefPtr prevActiveItem = menubar->GetActiveMenuChild();
const bool open = prevActiveItem && prevActiveItem->IsMenuPopupOpen(); const bool open = prevActiveItem && prevActiveItem->IsMenuPopupOpen();
@ -2460,7 +2472,8 @@ bool nsXULPopupManager::HandleKeyboardEventWithKeyCode(
if (aTopVisibleMenuItem) { if (aTopVisibleMenuItem) {
HidePopup(aTopVisibleMenuItem->Content(), {HidePopupOption::IsRollup}); HidePopup(aTopVisibleMenuItem->Content(), {HidePopupOption::IsRollup});
} else if (mActiveMenuBar) { } else if (mActiveMenuBar) {
mActiveMenuBar->MenuClosed(); RefPtr menubar = mActiveMenuBar;
menubar->MenuClosed();
} }
break; break;
@ -2476,7 +2489,8 @@ bool nsXULPopupManager::HandleKeyboardEventWithKeyCode(
Rollup({}); Rollup({});
break; break;
} else if (mActiveMenuBar) { } else if (mActiveMenuBar) {
mActiveMenuBar->MenuClosed(); RefPtr menubar = mActiveMenuBar;
menubar->MenuClosed();
break; break;
} }
// Intentional fall-through to RETURN case // Intentional fall-through to RETURN case
@ -2490,7 +2504,8 @@ bool nsXULPopupManager::HandleKeyboardEventWithKeyCode(
if (aTopVisibleMenuItem) { if (aTopVisibleMenuItem) {
aTopVisibleMenuItem->Frame()->HandleEnterKeyPress(*event); aTopVisibleMenuItem->Frame()->HandleEnterKeyPress(*event);
} else if (mActiveMenuBar) { } else if (mActiveMenuBar) {
mActiveMenuBar->HandleEnterKeyPress(*event); RefPtr menubar = mActiveMenuBar;
menubar->HandleEnterKeyPress(*event);
} }
break; break;
} }
@ -2541,8 +2556,7 @@ nsresult nsXULPopupManager::UpdateIgnoreKeys(bool aIgnoreKeys) {
return NS_OK; return NS_OK;
} }
nsPopupState nsXULPopupManager::GetPopupState( nsPopupState nsXULPopupManager::GetPopupState(Element* aPopupElement) {
mozilla::dom::Element* aPopupElement) {
if (mNativeMenu && mNativeMenu->Element()->Contains(aPopupElement)) { if (mNativeMenu && mNativeMenu->Element()->Contains(aPopupElement)) {
if (aPopupElement != mNativeMenu->Element()) { if (aPopupElement != mNativeMenu->Element()) {
// Submenu state is stored in mNativeMenuSubmenuStates. // Submenu state is stored in mNativeMenuSubmenuStates.
@ -2621,7 +2635,8 @@ nsresult nsXULPopupManager::KeyDown(KeyboardEvent* aKeyEvent) {
if (item && !item->Frame()->IsMenuList()) { if (item && !item->Frame()->IsMenuList()) {
Rollup({}); Rollup({});
} else if (mActiveMenuBar) { } else if (mActiveMenuBar) {
mActiveMenuBar->MenuClosed(); RefPtr menubar = mActiveMenuBar;
menubar->MenuClosed();
} }
// Clear the item to avoid bugs as it may have been deleted during // Clear the item to avoid bugs as it may have been deleted during

View file

@ -12,23 +12,19 @@
#define nsXULPopupManager_h__ #define nsXULPopupManager_h__
#include "mozilla/Logging.h" #include "mozilla/Logging.h"
#include "mozilla/widget/InitData.h"
#include "nsHashtablesFwd.h" #include "nsHashtablesFwd.h"
#include "nsIContent.h" #include "nsIContent.h"
#include "nsIRollupListener.h" #include "nsIRollupListener.h"
#include "nsIDOMEventListener.h" #include "nsIDOMEventListener.h"
#include "Units.h"
#include "nsPoint.h" #include "nsPoint.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsIObserver.h" #include "nsIObserver.h"
#include "nsITimer.h"
#include "nsIReflowCallback.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsPresContext.h"
#include "nsStyleConsts.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/widget/InitData.h"
#include "mozilla/widget/NativeMenu.h" #include "mozilla/widget/NativeMenu.h"
#include "Units.h"
// XXX Avoid including this here by moving function bodies to the cpp file. // XXX Avoid including this here by moving function bodies to the cpp file.
#include "mozilla/dom/Element.h" #include "mozilla/dom/Element.h"
@ -54,9 +50,9 @@
*/ */
class nsContainerFrame; class nsContainerFrame;
class nsMenuPopupFrame; class nsITimer;
class nsMenuBarFrame;
class nsIDocShellTreeItem; class nsIDocShellTreeItem;
class nsMenuPopupFrame;
class nsPIDOMWindowOuter; class nsPIDOMWindowOuter;
class nsRefreshDriver; class nsRefreshDriver;
@ -67,6 +63,7 @@ class Event;
class KeyboardEvent; class KeyboardEvent;
class UIEvent; class UIEvent;
class XULButtonElement; class XULButtonElement;
class XULMenuBarElement;
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla
@ -178,17 +175,6 @@ enum class HidePopupOption : uint8_t {
using HidePopupOptions = mozilla::EnumSet<HidePopupOption>; using HidePopupOptions = mozilla::EnumSet<HidePopupOption>;
#define NS_DIRECTION_IS_INLINE(dir) \
(dir == eNavigationDirection_Start || dir == eNavigationDirection_End)
#define NS_DIRECTION_IS_BLOCK(dir) \
(dir == eNavigationDirection_Before || dir == eNavigationDirection_After)
#define NS_DIRECTION_IS_BLOCK_TO_EDGE(dir) \
(dir == eNavigationDirection_First || dir == eNavigationDirection_Last)
static_assert(static_cast<uint8_t>(mozilla::StyleDirection::Ltr) == 0 &&
static_cast<uint8_t>(mozilla::StyleDirection::Rtl) == 1,
"Left to Right should be 0 and Right to Left should be 1");
/** /**
* DirectionFromKeyCodeTable: two arrays, the first for left-to-right and the * DirectionFromKeyCodeTable: two arrays, the first for left-to-right and the
* other for right-to-left, that map keycodes to values of * other for right-to-left, that map keycodes to values of
@ -437,7 +423,8 @@ class nsXULPopupManager final : public nsIDOMEventListener,
// when the active menu bar should be defocused. In the latter case, if // when the active menu bar should be defocused. In the latter case, if
// aMenuBar isn't currently active, yet another menu bar is, that menu bar // aMenuBar isn't currently active, yet another menu bar is, that menu bar
// will remain active. // will remain active.
void SetActiveMenuBar(nsMenuBarFrame* aMenuBar, bool aActivate); void SetActiveMenuBar(mozilla::dom::XULMenuBarElement* aMenuBar,
bool aActivate);
struct MayShowMenuResult { struct MayShowMenuResult {
const bool mIsNative = false; const bool mIsNative = false;
@ -865,7 +852,7 @@ class nsXULPopupManager final : public nsIDOMEventListener,
nsCOMPtr<nsIWidget> mWidget; nsCOMPtr<nsIWidget> mWidget;
// set to the currently active menu bar, if any // set to the currently active menu bar, if any
nsMenuBarFrame* mActiveMenuBar; mozilla::dom::XULMenuBarElement* mActiveMenuBar;
// linked list of normal menus and panels. mPopups points to the innermost // linked list of normal menus and panels. mPopups points to the innermost
// popup, which keeps alive all their parents. // popup, which keeps alive all their parents.