1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef nsMenuBarX_h_ 7 #define nsMenuBarX_h_ 8 9 #import <Cocoa/Cocoa.h> 10 11 #include "mozilla/UniquePtr.h" 12 #include "mozilla/WeakPtr.h" 13 14 #include "nsISupports.h" 15 #include "nsMenuParentX.h" 16 #include "nsMenuGroupOwnerX.h" 17 #include "nsChangeObserver.h" 18 #include "nsTArray.h" 19 #include "nsString.h" 20 21 class nsMenuBarX; 22 class nsMenuX; 23 class nsIWidget; 24 class nsIContent; 25 26 namespace mozilla { 27 namespace dom { 28 class Document; 29 class Element; 30 } 31 } 32 33 // ApplicationMenuDelegate is used to receive Cocoa notifications. 34 @interface ApplicationMenuDelegate : NSObject <NSMenuDelegate> { 35 nsMenuBarX* mApplicationMenu; // weak ref 36 } 37 - (id)initWithApplicationMenu:(nsMenuBarX*)aApplicationMenu; 38 @end 39 40 // Objective-C class used to allow us to intervene with keyboard event handling. 41 // We allow mouse actions to work normally. 42 @interface GeckoNSMenu : NSMenu { 43 } 44 - (BOOL)performSuperKeyEquivalent:(NSEvent*)aEvent; 45 @end 46 47 // Objective-C class used as action target for menu items 48 @interface NativeMenuItemTarget : NSObject { 49 } 50 - (IBAction)menuItemHit:(id)aSender; 51 @end 52 53 // Objective-C class used for menu items on the Services menu to allow Gecko 54 // to override their standard behavior in order to stop key equivalents from 55 // firing in certain instances. 56 @interface GeckoServicesNSMenuItem : NSMenuItem { 57 } 58 - (id)target; 59 - (SEL)action; 60 - (void)_doNothing:(id)aSender; 61 @end 62 63 // Objective-C class used as the Services menu so that Gecko can override the 64 // standard behavior of the Services menu in order to stop key equivalents 65 // from firing in certain instances. 66 @interface GeckoServicesNSMenu : NSMenu { 67 } 68 - (void)addItem:(NSMenuItem*)aNewItem; 69 - (NSMenuItem*)addItemWithTitle:(NSString*)aString 70 action:(SEL)aSelector 71 keyEquivalent:(NSString*)aKeyEquiv; 72 - (void)insertItem:(NSMenuItem*)aNewItem atIndex:(NSInteger)aIndex; 73 - (NSMenuItem*)insertItemWithTitle:(NSString*)aString 74 action:(SEL)aSelector 75 keyEquivalent:(NSString*)aKeyEquiv 76 atIndex:(NSInteger)aIndex; 77 - (void)_overrideClassOfMenuItem:(NSMenuItem*)aMenuItem; 78 @end 79 80 // Once instantiated, this object lives until its DOM node or its parent window is destroyed. 81 // Do not hold references to this, they can become invalid any time the DOM node can be destroyed. 82 class nsMenuBarX : public nsMenuParentX, public nsChangeObserver, public mozilla::SupportsWeakPtr { 83 public: 84 explicit nsMenuBarX(mozilla::dom::Element* aElement); 85 86 NS_INLINE_DECL_REFCOUNTING(nsMenuBarX) 87 88 static NativeMenuItemTarget* sNativeEventTarget; 89 static nsMenuBarX* sLastGeckoMenuBarPainted; 90 91 // The following content nodes have been removed from the menu system. 92 // We save them here for use in command handling. 93 RefPtr<nsIContent> mAboutItemContent; 94 RefPtr<nsIContent> mPrefItemContent; 95 RefPtr<nsIContent> mQuitItemContent; 96 97 // nsChangeObserver 98 NS_DECL_CHANGEOBSERVER 99 100 // nsMenuParentX AsMenuBar()101 nsMenuBarX* AsMenuBar() override { return this; } 102 103 // nsMenuBarX 104 uint32_t GetMenuCount(); 105 bool MenuContainsAppMenu(); 106 nsMenuX* GetMenuAt(uint32_t aIndex); 107 nsMenuX* GetXULHelpMenu(); 108 void SetSystemHelpMenu(); 109 nsresult Paint(); 110 void ForceUpdateNativeMenuAt(const nsAString& aIndexString); 111 void ForceNativeMenuReload(); // used for testing 112 static void ResetNativeApplicationMenu(); 113 void SetNeedsRebuild(); 114 void ApplicationMenuOpened(); 115 bool PerformKeyEquivalent(NSEvent* aEvent); NativeNSMenu()116 GeckoNSMenu* NativeNSMenu() { return mNativeMenu; } 117 118 // nsMenuParentX 119 void MenuChildChangedVisibility(const MenuChild& aChild, bool aIsVisible) override; 120 121 protected: 122 virtual ~nsMenuBarX(); 123 124 void ConstructNativeMenus(); 125 void ConstructFallbackNativeMenus(); 126 void InsertMenuAtIndex(RefPtr<nsMenuX>&& aMenu, uint32_t aIndex); 127 void RemoveMenuAtIndex(uint32_t aIndex); 128 RefPtr<mozilla::dom::Element> HideItem(mozilla::dom::Document* aDocument, const nsAString& aID); 129 void AquifyMenuBar(); 130 NSMenuItem* CreateNativeAppMenuItem(nsMenuX* aMenu, const nsAString& aNodeID, SEL aAction, 131 int aTag, NativeMenuItemTarget* aTarget); 132 void CreateApplicationMenu(nsMenuX* aMenu); 133 134 // Calculates the index at which aChild's NSMenuItem should be inserted into our NSMenu. 135 // The order of NSMenuItems in the NSMenu is the same as the order of nsMenuX objects in 136 // mMenuArray; there are two differences: 137 // - mMenuArray contains both visible and invisible menus, and the NSMenu only contains visible 138 // menus. 139 // - Our NSMenu may also contain an item for the app menu, whereas mMenuArray never does. 140 // So the insertion index is equal to the number of visible previous siblings of aChild in 141 // mMenuArray, plus one if the app menu is present. 142 NSInteger CalculateNativeInsertionPoint(nsMenuX* aChild); 143 144 RefPtr<nsIContent> mContent; 145 RefPtr<nsMenuGroupOwnerX> mMenuGroupOwner; 146 nsTArray<RefPtr<nsMenuX>> mMenuArray; 147 GeckoNSMenu* mNativeMenu; // root menu, representing entire menu bar 148 bool mNeedsRebuild; 149 ApplicationMenuDelegate* mApplicationMenuDelegate; 150 }; 151 152 #endif // nsMenuBarX_h_ 153