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 #ifndef mozilla_KeyEventHandler_h_ 8 #define mozilla_KeyEventHandler_h_ 9 10 #include "mozilla/EventForwards.h" 11 #include "mozilla/MemoryReporting.h" 12 #include "nsAtom.h" 13 #include "nsString.h" 14 #include "nsCOMPtr.h" 15 #include "nsIController.h" 16 #include "nsIWeakReference.h" 17 #include "nsCycleCollectionParticipant.h" 18 #include "js/TypeDecls.h" 19 #include "mozilla/ShortcutKeys.h" 20 21 namespace mozilla { 22 23 namespace layers { 24 class KeyboardShortcut; 25 } // namespace layers 26 27 struct IgnoreModifierState; 28 29 namespace dom { 30 class Event; 31 class UIEvent; 32 class Element; 33 class EventTarget; 34 class KeyboardEvent; 35 class Element; 36 } // namespace dom 37 38 // Values of the reserved attribute. When unset, the default value depends on 39 // the permissions.default.shortcuts preference. 40 enum ReservedKey : uint8_t { 41 ReservedKey_False = 0, 42 ReservedKey_True = 1, 43 ReservedKey_Unset = 2, 44 }; 45 46 class KeyEventHandler final { 47 public: 48 // This constructor is used only by XUL key handlers (e.g., <key>) 49 explicit KeyEventHandler(dom::Element* aHandlerElement, 50 ReservedKey aReserved); 51 52 // This constructor is used for keyboard handlers for browser, editor, input 53 // and textarea elements. 54 explicit KeyEventHandler(ShortcutKeyData* aKeyData); 55 56 ~KeyEventHandler(); 57 58 /** 59 * Try and convert this XBL handler into an APZ KeyboardShortcut for handling 60 * key events on the compositor thread. This only works for XBL handlers that 61 * represent scroll commands. 62 * 63 * @param aOut the converted KeyboardShortcut, must be non null 64 * @return whether the handler was converted into a KeyboardShortcut 65 */ 66 bool TryConvertToKeyboardShortcut(layers::KeyboardShortcut* aOut) const; 67 EventTypeEquals(nsAtom * aEventType)68 bool EventTypeEquals(nsAtom* aEventType) const { 69 return mEventName == aEventType; 70 } 71 72 // if aCharCode is not zero, it is used instead of the charCode of 73 // aKeyEventHandler. 74 bool KeyEventMatched(dom::KeyboardEvent* aDomKeyboardEvent, 75 uint32_t aCharCode, 76 const IgnoreModifierState& aIgnoreModifierState); 77 78 already_AddRefed<dom::Element> GetHandlerElement(); 79 GetIsReserved()80 ReservedKey GetIsReserved() { return mReserved; } 81 GetNextHandler()82 KeyEventHandler* GetNextHandler() { return mNextHandler; } SetNextHandler(KeyEventHandler * aHandler)83 void SetNextHandler(KeyEventHandler* aHandler) { mNextHandler = aHandler; } 84 85 MOZ_CAN_RUN_SCRIPT 86 nsresult ExecuteHandler(dom::EventTarget* aTarget, dom::Event* aEvent); 87 88 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 89 90 void GetCommand(nsAString& aCommand) const; 91 92 public: 93 static uint32_t gRefCnt; 94 95 protected: Init()96 void Init() { 97 ++gRefCnt; 98 if (gRefCnt == 1) { 99 // Get the primary accelerator key. 100 InitAccessKeys(); 101 } 102 } 103 104 already_AddRefed<nsIController> GetController(dom::EventTarget* aTarget); 105 106 inline int32_t GetMatchingKeyCode(const nsAString& aKeyName); 107 void ConstructPrototype(dom::Element* aKeyElement, 108 const char16_t* aEvent = nullptr, 109 const char16_t* aCommand = nullptr, 110 const char16_t* aKeyCode = nullptr, 111 const char16_t* aCharCode = nullptr, 112 const char16_t* aModifiers = nullptr); 113 void BuildModifiers(nsAString& aModifiers); 114 115 void ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers, 116 dom::Element* aKeyElement, const char* aMessageName); 117 void GetEventType(nsAString& aEvent); 118 bool ModifiersMatchMask(dom::UIEvent* aEvent, 119 const IgnoreModifierState& aIgnoreModifierState); 120 MOZ_CAN_RUN_SCRIPT 121 nsresult DispatchXBLCommand(dom::EventTarget* aTarget, dom::Event* aEvent); 122 MOZ_CAN_RUN_SCRIPT 123 nsresult DispatchXULKeyCommand(dom::Event* aEvent); 124 125 Modifiers GetModifiers() const; 126 Modifiers GetModifiersMask() const; 127 128 static int32_t KeyToMask(int32_t key); 129 static int32_t AccelKeyMask(); 130 131 static int32_t kMenuAccessKey; 132 static void InitAccessKeys(); 133 134 static const int32_t cShift; 135 static const int32_t cAlt; 136 static const int32_t cControl; 137 static const int32_t cMeta; 138 static const int32_t cOS; 139 140 static const int32_t cShiftMask; 141 static const int32_t cAltMask; 142 static const int32_t cControlMask; 143 static const int32_t cMetaMask; 144 static const int32_t cOSMask; 145 146 static const int32_t cAllModifiers; 147 148 protected: 149 union { 150 nsIWeakReference* 151 mHandlerElement; // For XUL <key> element handlers. [STRONG] 152 char16_t* mCommand; // For built-in shortcuts the command to execute. 153 }; 154 155 // The following four values make up 32 bits. 156 bool mIsXULKey; // This handler is either for a XUL <key> element or it is 157 // a command dispatcher. 158 uint8_t mMisc; // Miscellaneous extra information. For key events, 159 // stores whether or not we're a key code or char code. 160 // For mouse events, stores the clickCount. 161 162 ReservedKey mReserved; // <key> is reserved for chrome. Not used by handlers. 163 164 int32_t mKeyMask; // Which modifier keys this event handler expects to have 165 // down in order to be matched. 166 167 // The primary filter information for mouse/key events. 168 int32_t mDetail; // For key events, contains a charcode or keycode. For 169 // mouse events, stores the button info. 170 171 // Prototype handlers are chained. We own the next handler in the chain. 172 KeyEventHandler* mNextHandler; 173 RefPtr<nsAtom> mEventName; // The type of the event, e.g., "keypress" 174 }; 175 176 } // namespace mozilla 177 178 #endif 179