GlobalKeyListener.h (6705B)
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_GlobalKeyListener_h_ 8 #define mozilla_GlobalKeyListener_h_ 9 10 #include "mozilla/EventForwards.h" 11 #include "mozilla/layers/KeyboardMap.h" 12 #include "nsIDOMEventListener.h" 13 #include "nsIWeakReferenceUtils.h" 14 15 class nsAtom; 16 17 namespace mozilla { 18 class EventListenerManager; 19 class WidgetKeyboardEvent; 20 struct IgnoreModifierState; 21 22 namespace layers { 23 class KeyboardMap; 24 } 25 26 namespace dom { 27 class Element; 28 class EventTarget; 29 class KeyboardEvent; 30 } // namespace dom 31 32 class KeyEventHandler; 33 34 /** 35 * A generic listener for key events. 36 * 37 * Maintains a list of shortcut handlers and is registered as a listener for DOM 38 * key events from a target. Responsible for executing the appropriate handler 39 * when a keyboard event is received. 40 */ 41 class GlobalKeyListener : public nsIDOMEventListener { 42 public: 43 explicit GlobalKeyListener(dom::EventTarget* aTarget); 44 45 void InstallKeyboardEventListenersTo( 46 EventListenerManager* aEventListenerManager); 47 void RemoveKeyboardEventListenersFrom( 48 EventListenerManager* aEventListenerManager); 49 50 NS_DECL_ISUPPORTS 51 NS_DECL_NSIDOMEVENTLISTENER 52 53 protected: 54 virtual ~GlobalKeyListener() = default; 55 56 MOZ_CAN_RUN_SCRIPT 57 void WalkHandlers(dom::KeyboardEvent* aKeyEvent); 58 59 enum class Purpose { 60 ExecuteCommand, 61 LookForCommand, 62 }; 63 struct MOZ_STACK_CLASS WalkHandlersResult { 64 // Set to true if it found a command matches with given keyboard event and 65 // it's available. 66 bool mMeaningfulHandlerFound = false; 67 // Set to true if the command which is found or executed is reserved for 68 // chrome. 69 bool mReservedHandlerForChromeFound = false; 70 // Set to true if found handler is disabled. 71 bool mDisabledHandlerFound = false; 72 // Set to true if a command is found but may correspond to a different type 73 // of keyboard event. 74 bool mRelevantHandlerFound = false; 75 }; 76 77 // walk the handlers, looking for one to handle the event 78 MOZ_CAN_RUN_SCRIPT 79 WalkHandlersResult WalkHandlersInternal(Purpose aPurpose, 80 dom::KeyboardEvent* aKeyEvent); 81 82 // Walk the handlers for aEvent, aCharCode and aIgnoreModifierState. 83 MOZ_CAN_RUN_SCRIPT 84 WalkHandlersResult WalkHandlersAndExecute( 85 Purpose aPurpose, dom::KeyboardEvent* aKeyEvent, uint32_t aCharCode, 86 const IgnoreModifierState& aIgnoreModifierState); 87 88 // HandleEvent function for the capturing phase in the default event group. 89 MOZ_CAN_RUN_SCRIPT 90 void HandleEventOnCaptureInDefaultEventGroup(dom::KeyboardEvent* aEvent); 91 // HandleEvent function for the capturing phase in the system event group. 92 MOZ_CAN_RUN_SCRIPT 93 void HandleEventOnCaptureInSystemEventGroup(dom::KeyboardEvent* aEvent); 94 95 // Check if any handler would handle the given event. Optionally returns 96 // whether the command handler for the event is marked with the "reserved" 97 // attribute. 98 MOZ_CAN_RUN_SCRIPT 99 WalkHandlersResult HasHandlerForEvent(dom::KeyboardEvent* aEvent); 100 101 // Returns true if the key would be reserved for the given handler. A reserved 102 // key is not sent to a content process or single-process equivalent. 103 bool IsReservedKey(WidgetKeyboardEvent* aKeyEvent, KeyEventHandler* aHandler); 104 105 // lazily load the handlers. Overridden to handle being attached 106 // to a particular element rather than the document 107 virtual void EnsureHandlers() = 0; 108 109 virtual bool CanHandle(KeyEventHandler* aHandler, bool aWillExecute) const { 110 return true; 111 } 112 113 virtual bool IsDisabled() const { return false; } 114 115 virtual already_AddRefed<dom::EventTarget> GetHandlerTarget( 116 KeyEventHandler* aHandler) { 117 return do_AddRef(mTarget); 118 } 119 120 dom::EventTarget* mTarget; // weak ref; 121 122 KeyEventHandler* mHandler; // Linked list of event handlers. 123 }; 124 125 /** 126 * A listener for shortcut keys defined in XUL keyset elements. 127 * 128 * Listens for keyboard events from the document object and triggers the 129 * appropriate XUL key elements. 130 */ 131 class XULKeySetGlobalKeyListener final : public GlobalKeyListener { 132 public: 133 explicit XULKeySetGlobalKeyListener(dom::Element* aElement, 134 dom::EventTarget* aTarget); 135 136 static void AttachKeyHandler(dom::Element* aElementTarget); 137 static void DetachKeyHandler(dom::Element* aElementTarget); 138 139 protected: 140 virtual ~XULKeySetGlobalKeyListener(); 141 142 // Returns the element which was passed as a parameter to the constructor, 143 // unless the element has been removed from the document. Optionally returns 144 // whether the disabled attribute is set on the element (assuming the element 145 // is non-null). 146 dom::Element* GetElement(bool* aIsDisabled = nullptr) const; 147 148 virtual void EnsureHandlers() override; 149 150 virtual bool CanHandle(KeyEventHandler* aHandler, 151 bool aWillExecute) const override; 152 virtual bool IsDisabled() const override; 153 virtual already_AddRefed<dom::EventTarget> GetHandlerTarget( 154 KeyEventHandler* aHandler) override; 155 156 /** 157 * GetElementForHandler() retrieves an element for the handler. The element 158 * may be a command element or a key element. 159 * 160 * @param aHandler The handler. 161 * @param aElementForHandler Must not be nullptr. The element is returned to 162 * this. 163 * @return true if the handler is valid. Otherwise, false. 164 */ 165 bool GetElementForHandler(KeyEventHandler* aHandler, 166 dom::Element** aElementForHandler) const; 167 168 /** 169 * IsExecutableElement() returns true if aElement is executable. 170 * Otherwise, false. aElement should be a command element or a key element. 171 */ 172 bool IsExecutableElement(dom::Element* aElement) const; 173 174 // Using weak pointer to the DOM Element. 175 nsWeakPtr mWeakPtrForElement; 176 }; 177 178 /** 179 * Listens for built-in shortcut keys. 180 * 181 * Listens to DOM keyboard events from the window or text input and runs the 182 * built-in shortcuts (see dom/events/keyevents) as necessary. 183 */ 184 class RootWindowGlobalKeyListener final : public GlobalKeyListener { 185 public: 186 explicit RootWindowGlobalKeyListener(dom::EventTarget* aTarget); 187 188 static void AttachKeyHandler(dom::EventTarget* aTarget); 189 190 static layers::KeyboardMap CollectKeyboardShortcuts(); 191 192 protected: 193 // Is an HTML editable element focused 194 static bool IsHTMLEditorFocused(); 195 196 virtual void EnsureHandlers() override; 197 }; 198 199 } // namespace mozilla 200 201 #endif