1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 //
8 // nsMenuBarFrame
9 //
10 
11 #ifndef nsMenuBarFrame_h__
12 #define nsMenuBarFrame_h__
13 
14 #include "mozilla/Attributes.h"
15 #include "nsAtom.h"
16 #include "nsCOMPtr.h"
17 #include "nsBoxFrame.h"
18 #include "nsMenuFrame.h"
19 #include "nsMenuBarListener.h"
20 #include "nsMenuParent.h"
21 
22 class nsIContent;
23 
24 namespace mozilla {
25 class PresShell;
26 namespace dom {
27 class KeyboardEvent;
28 }  // namespace dom
29 }  // namespace mozilla
30 
31 nsIFrame* NS_NewMenuBarFrame(mozilla::PresShell* aPresShell,
32                              mozilla::ComputedStyle* aStyle);
33 
34 class nsMenuBarFrame final : public nsBoxFrame, public nsMenuParent {
35  public:
36   NS_DECL_QUERYFRAME
37   NS_DECL_FRAMEARENA_HELPERS(nsMenuBarFrame)
38 
39   explicit nsMenuBarFrame(ComputedStyle* aStyle, nsPresContext* aPresContext);
40 
41   // nsMenuParent interface
42   virtual nsMenuFrame* GetCurrentMenuItem() override;
43   NS_IMETHOD SetCurrentMenuItem(nsMenuFrame* aMenuItem) override;
44   virtual void CurrentMenuIsBeingDestroyed() override;
45   NS_IMETHOD ChangeMenuItem(nsMenuFrame* aMenuItem, bool aSelectFirstItem,
46                             bool aFromKey) override;
47 
48   NS_IMETHOD SetActive(bool aActiveFlag) override;
49 
IsMenuBar()50   virtual bool IsMenuBar() override { return true; }
IsContextMenu()51   virtual bool IsContextMenu() override { return false; }
IsActive()52   virtual bool IsActive() override { return mIsActive; }
IsMenu()53   virtual bool IsMenu() override { return false; }
IsOpen()54   virtual bool IsOpen() override {
55     // menubars are considered always open
56     return true;
57   }
58 
IsMenuOpen()59   bool IsMenuOpen() { return mCurrentMenu && mCurrentMenu->IsOpen(); }
60 
61   void InstallKeyboardNavigator();
62   void RemoveKeyboardNavigator();
63 
64   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
65                     nsIFrame* aPrevInFlow) override;
66 
67   virtual void DestroyFrom(nsIFrame* aDestructRoot,
68                            PostDestroyData& aPostDestroyData) override;
69 
LockMenuUntilClosed(bool aLock)70   virtual void LockMenuUntilClosed(bool aLock) override {}
IsMenuLocked()71   virtual bool IsMenuLocked() override { return false; }
72 
73   // Non-interface helpers
74 
75   // The 'stay active' flag is set when navigating from one top-level menu
76   // to another, to prevent the menubar from deactivating and submenus from
77   // firing extra DOMMenuItemActive events.
GetStayActive()78   bool GetStayActive() { return mStayActive; }
SetStayActive(bool aStayActive)79   void SetStayActive(bool aStayActive) { mStayActive = aStayActive; }
80 
81   // Called when a menu on the menu bar is clicked on. Returns a menu if one
82   // needs to be closed.
83   nsMenuFrame* ToggleMenuActiveState();
84 
IsActiveByKeyboard()85   bool IsActiveByKeyboard() { return mActiveByKeyboard; }
SetActiveByKeyboard()86   void SetActiveByKeyboard() { mActiveByKeyboard = true; }
87 
88   // indicate that a menu on the menubar was closed. Returns true if the caller
89   // may deselect the menuitem.
90   virtual bool MenuClosed() override;
91 
92   // Called when Enter is pressed while the menubar is focused. If the current
93   // menu is open, let the child handle the key.
94   nsMenuFrame* Enter(mozilla::WidgetGUIEvent* aEvent);
95 
96   // Used to handle ALT+key combos
97   nsMenuFrame* FindMenuWithShortcut(mozilla::dom::KeyboardEvent* aKeyEvent,
98                                     bool aPeek);
99 
IsFrameOfType(uint32_t aFlags)100   virtual bool IsFrameOfType(uint32_t aFlags) const override {
101     // Override bogus IsFrameOfType in nsBoxFrame.
102     if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
103       return false;
104     return nsBoxFrame::IsFrameOfType(aFlags);
105   }
106 
107 #ifdef DEBUG_FRAME_DUMP
GetFrameName(nsAString & aResult)108   virtual nsresult GetFrameName(nsAString& aResult) const override {
109     return MakeFrameName(NS_LITERAL_STRING("MenuBar"), aResult);
110   }
111 #endif
112 
113  protected:
114   RefPtr<nsMenuBarListener> mMenuBarListener;  // The listener that tells us
115                                                // about key and mouse events.
116 
117   // flag that is temporarily set when switching from one menu on the menubar to
118   // another to indicate that the menubar should not be deactivated.
119   bool mStayActive;
120 
121   bool mIsActive;  // Whether or not the menu bar is active (a menu item is
122                    // highlighted or shown).
123 
124   // whether the menubar was made active via the keyboard.
125   bool mActiveByKeyboard;
126 
127   // The current menu that is active (highlighted), which may not be open. This
128   // will be null if no menu is active.
129   nsMenuFrame* mCurrentMenu;
130 };  // class nsMenuBarFrame
131 
132 #endif
133