summaryrefslogtreecommitdiffstats
path: root/dom/events/KeyEventHandler.h
blob: 5d444cf3227082b4fa94ac0e83e11dbe42834847 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/* -*- 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_KeyEventHandler_h_
#define mozilla_KeyEventHandler_h_

#include "mozilla/EventForwards.h"
#include "mozilla/MemoryReporting.h"
#include "nsAtom.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsIController.h"
#include "nsIWeakReference.h"
#include "nsCycleCollectionParticipant.h"
#include "js/TypeDecls.h"
#include "mozilla/ShortcutKeys.h"

namespace mozilla {

namespace layers {
class KeyboardShortcut;
}  // namespace layers

struct IgnoreModifierState;

namespace dom {
class Event;
class UIEvent;
class Element;
class EventTarget;
class KeyboardEvent;
class Element;
}  // namespace dom

// Values of the reserved attribute. When unset, the default value depends on
// the permissions.default.shortcuts preference.
enum ReservedKey : uint8_t {
  ReservedKey_False = 0,
  ReservedKey_True = 1,
  ReservedKey_Unset = 2,
};

class KeyEventHandler final {
 public:
  // This constructor is used only by XUL key handlers (e.g., <key>)
  explicit KeyEventHandler(dom::Element* aHandlerElement,
                           ReservedKey aReserved);

  // This constructor is used for keyboard handlers for browser, editor, input
  // and textarea elements.
  explicit KeyEventHandler(ShortcutKeyData* aKeyData);

  ~KeyEventHandler();

  /**
   * Try and convert this XBL handler into an APZ KeyboardShortcut for handling
   * key events on the compositor thread. This only works for XBL handlers that
   * represent scroll commands.
   *
   * @param aOut the converted KeyboardShortcut, must be non null
   * @return whether the handler was converted into a KeyboardShortcut
   */
  bool TryConvertToKeyboardShortcut(layers::KeyboardShortcut* aOut) const;

  bool EventTypeEquals(nsAtom* aEventType) const {
    return mEventName == aEventType;
  }

  // if aCharCode is not zero, it is used instead of the charCode of
  // aKeyEventHandler.
  bool KeyEventMatched(dom::KeyboardEvent* aDomKeyboardEvent,
                       uint32_t aCharCode,
                       const IgnoreModifierState& aIgnoreModifierState);

  /**
   * Check whether the handler element is disabled.  Note that this requires
   * a QI to getting GetHandlerELement().  Therefore, this should not be used
   * first in multiple checks.
   */
  bool KeyElementIsDisabled() const;

  already_AddRefed<dom::Element> GetHandlerElement() const;

  ReservedKey GetIsReserved() { return mReserved; }

  KeyEventHandler* GetNextHandler() { return mNextHandler; }
  void SetNextHandler(KeyEventHandler* aHandler) { mNextHandler = aHandler; }

  MOZ_CAN_RUN_SCRIPT
  nsresult ExecuteHandler(dom::EventTarget* aTarget, dom::Event* aEvent);

  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;

  void GetCommand(nsAString& aCommand) const;

 public:
  static uint32_t gRefCnt;

 protected:
  void Init() { ++gRefCnt; }

  already_AddRefed<nsIController> GetController(dom::EventTarget* aTarget);

  inline int32_t GetMatchingKeyCode(const nsAString& aKeyName);
  void ConstructPrototype(dom::Element* aKeyElement,
                          const char16_t* aEvent = nullptr,
                          const char16_t* aCommand = nullptr,
                          const char16_t* aKeyCode = nullptr,
                          const char16_t* aCharCode = nullptr,
                          const char16_t* aModifiers = nullptr);
  void BuildModifiers(nsAString& aModifiers);

  void ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers,
                         dom::Element* aKeyElement, const char* aMessageName);
  void GetEventType(nsAString& aEvent);
  bool ModifiersMatchMask(dom::UIEvent* aEvent,
                          const IgnoreModifierState& aIgnoreModifierState);
  MOZ_CAN_RUN_SCRIPT
  nsresult DispatchXBLCommand(dom::EventTarget* aTarget, dom::Event* aEvent);
  MOZ_CAN_RUN_SCRIPT
  nsresult DispatchXULKeyCommand(dom::Event* aEvent);

  Modifiers GetModifiers() const;
  Modifiers GetModifiersMask() const;

  static int32_t KeyToMask(uint32_t aKey);
  static int32_t AccelKeyMask();

  static const int32_t cShift;
  static const int32_t cAlt;
  static const int32_t cControl;
  static const int32_t cMeta;
  static const int32_t cOS;

  static const int32_t cShiftMask;
  static const int32_t cAltMask;
  static const int32_t cControlMask;
  static const int32_t cMetaMask;
  static const int32_t cOSMask;

  static const int32_t cAllModifiers;

 protected:
  union {
    nsIWeakReference*
        mHandlerElement;  // For XUL <key> element handlers. [STRONG]
    char16_t* mCommand;   // For built-in shortcuts the command to execute.
  };

  // The following four values make up 32 bits.
  bool mIsXULKey;  // This handler is either for a XUL <key> element or it is
                   // a command dispatcher.
  uint8_t mMisc;   // Miscellaneous extra information.  For key events,
                   // stores whether or not we're a key code or char code.
                   // For mouse events, stores the clickCount.

  ReservedKey mReserved;  // <key> is reserved for chrome. Not used by handlers.

  int32_t mKeyMask;  // Which modifier keys this event handler expects to have
                     // down in order to be matched.

  // The primary filter information for mouse/key events.
  int32_t mDetail;  // For key events, contains a charcode or keycode. For
                    // mouse events, stores the button info.

  // Prototype handlers are chained. We own the next handler in the chain.
  KeyEventHandler* mNextHandler;
  RefPtr<nsAtom> mEventName;  // The type of the event, e.g., "keypress"
};

}  // namespace mozilla

#endif