Backed out changeset b71c8c052463 (bug 1943846) for causing mass failures. CLOSED...
[gecko.git] / widget / BasicEvents.h
blob22d9486b7d13daf600bb9b46f652f332ad254f3c
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/. */
6 #ifndef mozilla_BasicEvents_h__
7 #define mozilla_BasicEvents_h__
9 #include <stdint.h>
10 #include <type_traits>
12 #include "mozilla/EventForwards.h"
13 #include "mozilla/TimeStamp.h"
14 #include "mozilla/dom/EventTarget.h"
15 #include "mozilla/layers/LayersTypes.h"
16 #include "nsCOMPtr.h"
17 #include "nsAtom.h"
18 #include "nsISupportsImpl.h"
19 #include "nsIWidget.h"
20 #include "nsString.h"
21 #include "Units.h"
23 #ifdef DEBUG
24 # include "nsXULAppAPI.h"
25 #endif // #ifdef DEBUG
27 class nsIPrincipal;
29 namespace IPC {
30 template <typename T>
31 struct ParamTraits;
32 } // namespace IPC
34 namespace mozilla {
36 class EventTargetChainItem;
38 enum class CrossProcessForwarding {
39 // eStop prevents the event to be sent to remote process.
40 eStop,
41 // eAllow keeps current state of the event whether it's sent to remote
42 // process. In other words, eAllow does NOT mean that making the event
43 // sent to remote process when IsCrossProcessForwardingStopped() returns
44 // true.
45 eAllow,
48 /******************************************************************************
49 * mozilla::BaseEventFlags
51 * BaseEventFlags must be a POD struct for safe to use memcpy (including
52 * in ParamTraits<BaseEventFlags>). So don't make virtual methods, constructor,
53 * destructor and operators.
54 * This is necessary for VC which is NOT C++0x compiler.
55 ******************************************************************************/
57 struct BaseEventFlags {
58 public:
59 // If mIsTrusted is true, the event is a trusted event. Otherwise, it's
60 // an untrusted event.
61 bool mIsTrusted : 1;
62 // If mInBubblingPhase is true, the event is in bubbling phase or target
63 // phase.
64 bool mInBubblingPhase : 1;
65 // If mInCapturePhase is true, the event is in capture phase or target phase.
66 bool mInCapturePhase : 1;
67 // If mInTargetPhase is true, the event is in target phase.
68 bool mInTargetPhase : 1;
69 // If mInSystemGroup is true, the event is being dispatched in system group.
70 bool mInSystemGroup : 1;
71 // If mCancelable is true, the event can be consumed. I.e., calling
72 // dom::Event::PreventDefault() can prevent the default action.
73 bool mCancelable : 1;
74 // If mBubbles is true, the event can bubble. Otherwise, cannot be handled
75 // in bubbling phase.
76 bool mBubbles : 1;
77 // If mPropagationStopped is true, dom::Event::StopPropagation() or
78 // dom::Event::StopImmediatePropagation() has been called.
79 bool mPropagationStopped : 1;
80 // If mImmediatePropagationStopped is true,
81 // dom::Event::StopImmediatePropagation() has been called.
82 // Note that mPropagationStopped must be true when this is true.
83 bool mImmediatePropagationStopped : 1;
84 // If mDefaultPrevented is true, the event has been consumed.
85 // E.g., dom::Event::PreventDefault() has been called or
86 // the default action has been performed.
87 bool mDefaultPrevented : 1;
88 // If mDefaultPreventedByContent is true, the event has been
89 // consumed by content.
90 // Note that mDefaultPrevented must be true when this is true.
91 bool mDefaultPreventedByContent : 1;
92 // If mDefaultPreventedByChrome is true, the event has been
93 // consumed by chrome.
94 // Note that mDefaultPrevented must be true when this is true.
95 bool mDefaultPreventedByChrome : 1;
96 // mMultipleActionsPrevented may be used when default handling don't want to
97 // be prevented, but only one of the event targets should handle the event.
98 // For example, when a <label> element is in another <label> element and
99 // the first <label> element is clicked, that one may set this true.
100 // Then, the second <label> element won't handle the event.
101 bool mMultipleActionsPrevented : 1;
102 // If mIsBeingDispatched is true, the DOM event created from the event is
103 // dispatching into the DOM tree and not completed.
104 bool mIsBeingDispatched : 1;
105 // If mDispatchedAtLeastOnce is true, the event has been dispatched
106 // as a DOM event and the dispatch has been completed in the process.
107 // So, this is false even if the event has already been dispatched
108 // in another process.
109 bool mDispatchedAtLeastOnce : 1;
110 // If mIsSynthesizedForTests is true, the event has been synthesized for
111 // automated tests or something hacky approach of an add-on.
112 bool mIsSynthesizedForTests : 1;
113 // If mExceptionWasRaised is true, one of the event handlers has raised an
114 // exception.
115 bool mExceptionWasRaised : 1;
116 // If mRetargetToNonNativeAnonymous is true and the target is in a non-native
117 // native anonymous subtree, the event target is set to mOriginalTarget.
118 bool mRetargetToNonNativeAnonymous : 1;
119 // If mNoContentDispatch is true, the event is never dispatched to the
120 // event handlers which are added to the contents, onfoo attributes and
121 // properties. Note that this flag is ignored when
122 // EventChainPreVisitor::mForceContentDispatch is set true. For exapmle,
123 // window and document object sets it true. Therefore, web applications
124 // can handle the event if they add event listeners to the window or the
125 // document.
126 // XXX This is an ancient and broken feature, don't use this for new bug
127 // as far as possible.
128 bool mNoContentDispatch : 1;
129 // If mOnlyChromeDispatch is true, the event is dispatched to only chrome.
130 bool mOnlyChromeDispatch : 1;
131 // Indicates if the key combination is reserved by chrome. This is set by
132 // MarkAsReservedByChrome().
133 bool mIsReservedByChrome : 1;
134 // If mOnlySystemGroupDispatchInContent is true, event listeners added to
135 // the default group for non-chrome EventTarget won't be called.
136 // Be aware, if this is true, EventDispatcher needs to check if each event
137 // listener is added to chrome node, so, don't set this to true for the
138 // events which are fired a lot of times like eMouseMove.
139 bool mOnlySystemGroupDispatchInContent : 1;
140 // If mOnlySystemGroupDispatch is true, the event will be dispatched only to
141 // event listeners added in the system group.
142 bool mOnlySystemGroupDispatch : 1;
143 // The event's action will be handled by APZ. The main thread should not
144 // perform its associated action.
145 bool mHandledByAPZ : 1;
146 // True if the event is currently being handled by an event listener that
147 // was registered as a passive listener.
148 bool mInPassiveListener : 1;
149 // If mComposed is true, the event fired by nodes in shadow DOM can cross the
150 // boundary of shadow DOM and light DOM.
151 bool mComposed : 1;
152 // Similar to mComposed. Set it to true to allow events cross the boundary
153 // between native non-anonymous content and native anonymouse content
154 bool mComposedInNativeAnonymousContent : 1;
155 // Set to true for events which are suppressed or delayed so that later a
156 // DelayedEvent of it is dispatched. This is used when parent side process
157 // the key event after content side, and may drop the event if the event
158 // was suppressed or delayed in contents side.
159 // It is also set to true for the events (in a DelayedInputEvent), which will
160 // be dispatched afterwards.
161 bool mIsSuppressedOrDelayed : 1;
162 // Certain mouse events can be marked as positionless to return 0 from
163 // coordinate related getters.
164 bool mIsPositionless : 1;
166 // Flags managing state of propagation between processes.
167 // Note the the following flags shouldn't be referred directly. Use utility
168 // methods instead.
170 // If mNoRemoteProcessDispatch is true, the event is not allowed to be sent
171 // to remote process.
172 bool mNoRemoteProcessDispatch : 1;
173 // If mWantReplyFromContentProcess is true, the event will be redispatched
174 // in the parent process after the content process has handled it. Useful
175 // for when the parent process need the know first how the event was used
176 // by content before handling it itself.
177 bool mWantReplyFromContentProcess : 1;
178 // If mPostedToRemoteProcess is true, the event has been posted to the
179 // remote process (but it's not handled yet if it's not a duplicated event
180 // instance).
181 bool mPostedToRemoteProcess : 1;
182 // If mCameFromAnotherProcess is true, the event came from another process.
183 bool mCameFromAnotherProcess : 1;
186 * Helper methods for methods of DOM Event.
188 inline void StopPropagation() { mPropagationStopped = true; }
189 inline void StopImmediatePropagation() {
190 StopPropagation();
191 mImmediatePropagationStopped = true;
193 inline void PreventDefault(bool aCalledByDefaultHandler = true) {
194 if (!mCancelable) {
195 return;
197 mDefaultPrevented = true;
198 // Note that even if preventDefault() has already been called by chrome,
199 // a call of preventDefault() by content needs to overwrite
200 // mDefaultPreventedByContent to true because in such case, defaultPrevented
201 // must be true when web apps check it after they call preventDefault().
202 if (aCalledByDefaultHandler) {
203 StopCrossProcessForwarding();
204 mDefaultPreventedByChrome = true;
205 } else {
206 mDefaultPreventedByContent = true;
209 // This should be used only before dispatching events into the DOM tree.
210 inline void PreventDefaultBeforeDispatch(
211 CrossProcessForwarding aCrossProcessForwarding) {
212 if (!mCancelable) {
213 return;
215 mDefaultPrevented = true;
216 if (aCrossProcessForwarding == CrossProcessForwarding::eStop) {
217 StopCrossProcessForwarding();
220 inline bool DefaultPrevented() const { return mDefaultPrevented; }
221 inline bool DefaultPreventedByContent() const {
222 MOZ_ASSERT(!mDefaultPreventedByContent || DefaultPrevented());
223 return mDefaultPreventedByContent;
225 inline bool IsTrusted() const { return mIsTrusted; }
226 inline bool PropagationStopped() const { return mPropagationStopped; }
228 // Helper methods to access flags managing state of propagation between
229 // processes.
232 * Prevent to be dispatched to remote process.
234 inline void StopCrossProcessForwarding() {
235 MOZ_ASSERT(!mPostedToRemoteProcess);
236 mNoRemoteProcessDispatch = true;
237 mWantReplyFromContentProcess = false;
240 * Return true if the event shouldn't be dispatched to remote process.
242 inline bool IsCrossProcessForwardingStopped() const {
243 return mNoRemoteProcessDispatch;
246 * Mark the event as waiting reply from remote process.
247 * If the caller needs to win other keyboard event handlers in chrome,
248 * the caller should call StopPropagation() too.
249 * Otherwise, if the caller just needs to know if the event is consumed by
250 * either content or chrome, it should just call this because the event
251 * may be reserved by chrome and it needs to be dispatched into the DOM
252 * tree in chrome for checking if it's reserved before being sent to any
253 * remote processes.
255 inline void MarkAsWaitingReplyFromRemoteProcess() {
256 MOZ_ASSERT(!mPostedToRemoteProcess);
257 mNoRemoteProcessDispatch = false;
258 mWantReplyFromContentProcess = true;
261 * Reset "waiting reply from remote process" state. This is useful when
262 * you dispatch a copy of an event coming from different process.
264 inline void ResetWaitingReplyFromRemoteProcessState() {
265 if (IsWaitingReplyFromRemoteProcess()) {
266 // FYI: mWantReplyFromContentProcess is also used for indicating
267 // "handled in remote process" state. Therefore, only when
268 // IsWaitingReplyFromRemoteProcess() returns true, this should
269 // reset the flag.
270 mWantReplyFromContentProcess = false;
274 * Return true if the event handler should wait reply event. I.e., if this
275 * returns true, any event handler should do nothing with the event.
277 inline bool IsWaitingReplyFromRemoteProcess() const {
278 return !mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
281 * Mark the event as already handled in the remote process. This should be
282 * called when initializing reply events.
284 inline void MarkAsHandledInRemoteProcess() {
285 mNoRemoteProcessDispatch = true;
286 mWantReplyFromContentProcess = true;
287 mPostedToRemoteProcess = false;
290 * Return true if the event has already been handled in the remote process.
292 inline bool IsHandledInRemoteProcess() const {
293 return mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
296 * Return true if the event should be sent back to its parent process.
298 inline bool WantReplyFromContentProcess() const {
299 MOZ_ASSERT(!XRE_IsParentProcess());
300 return IsWaitingReplyFromRemoteProcess();
303 * Mark the event has already posted to a remote process.
305 inline void MarkAsPostedToRemoteProcess() {
306 MOZ_ASSERT(!IsCrossProcessForwardingStopped());
307 mPostedToRemoteProcess = true;
310 * Reset the cross process dispatching state. This should be used when a
311 * process receives the event because the state is in the sender.
313 inline void ResetCrossProcessDispatchingState() {
314 MOZ_ASSERT(!IsCrossProcessForwardingStopped());
315 mPostedToRemoteProcess = false;
316 // Ignore propagation state in the remote process if it's marked as
317 // "waiting reply from remote process" because the process needs to
318 // stop propagation in the process until receiving a reply event.
319 // Note that the propagation stopped flag is important for the reply event
320 // handler in the main process because it's used for making whether it's
321 // ignored by the remote process or not.
322 if (!XRE_IsParentProcess() && IsWaitingReplyFromRemoteProcess()) {
323 mPropagationStopped = mImmediatePropagationStopped = false;
325 // mDispatchedAtLeastOnce indicates the state in current process.
326 mDispatchedAtLeastOnce = false;
329 * Return true if the event has been posted to a remote process.
330 * Note that MarkAsPostedToRemoteProcess() is called by
331 * ParamTraits<mozilla::WidgetEvent>. Therefore, it *might* be possible
332 * that posting the event failed even if this returns true. But that must
333 * really rare. If that'd be problem for you, you should unmark this in
334 * BrowserParent or somewhere.
336 inline bool HasBeenPostedToRemoteProcess() const {
337 return mPostedToRemoteProcess;
340 * Return true if the event came from another process.
342 inline bool CameFromAnotherProcess() const { return mCameFromAnotherProcess; }
344 * Mark the event as coming from another process.
346 inline void MarkAsComingFromAnotherProcess() {
347 mCameFromAnotherProcess = true;
350 * Mark the event is reserved by chrome. I.e., shouldn't be dispatched to
351 * content because it shouldn't be cancelable.
353 inline void MarkAsReservedByChrome() {
354 MOZ_ASSERT(!mPostedToRemoteProcess);
355 mIsReservedByChrome = true;
356 // For reserved commands (such as Open New Tab), we don't need to wait for
357 // the content to answer, neither to give a chance for content to override
358 // its behavior.
359 StopCrossProcessForwarding();
360 // If the event is reserved by chrome, we shouldn't expose the event to
361 // web contents because such events shouldn't be cancelable. So, it's not
362 // good behavior to fire such events but to ignore the defaultPrevented
363 // attribute value in chrome.
364 mOnlySystemGroupDispatchInContent = true;
367 * Return true if the event is reserved by chrome.
369 inline bool IsReservedByChrome() const {
370 MOZ_ASSERT(!mIsReservedByChrome || (IsCrossProcessForwardingStopped() &&
371 mOnlySystemGroupDispatchInContent));
372 return mIsReservedByChrome;
375 inline void Clear() { SetRawFlags(0); }
376 // Get if either the instance's bit or the aOther's bit is true, the
377 // instance's bit becomes true. In other words, this works like:
378 // eventFlags |= aOther;
379 inline void Union(const BaseEventFlags& aOther) {
380 RawFlags rawFlags = GetRawFlags() | aOther.GetRawFlags();
381 SetRawFlags(rawFlags);
384 private:
385 typedef uint64_t RawFlags;
387 inline void SetRawFlags(RawFlags aRawFlags) {
388 static_assert(sizeof(BaseEventFlags) <= sizeof(RawFlags),
389 "mozilla::EventFlags must not be bigger than the RawFlags");
390 memcpy(this, &aRawFlags, sizeof(BaseEventFlags));
392 inline RawFlags GetRawFlags() const {
393 RawFlags result = 0;
394 memcpy(&result, this, sizeof(BaseEventFlags));
395 return result;
399 /******************************************************************************
400 * mozilla::EventFlags
401 ******************************************************************************/
403 struct EventFlags : public BaseEventFlags {
404 EventFlags() { Clear(); }
407 /******************************************************************************
408 * mozilla::WidgetEventTime
409 ******************************************************************************/
411 class WidgetEventTime {
412 public:
413 // Timestamp when the message was created.
414 TimeStamp mTimeStamp;
416 WidgetEventTime() : mTimeStamp(TimeStamp::Now()) {}
418 explicit WidgetEventTime(const WidgetEventTime* aTime)
419 : mTimeStamp(aTime ? aTime->mTimeStamp : TimeStamp::Now()) {
420 MOZ_ASSERT(aTime != this);
421 MOZ_ASSERT_IF(aTime, !aTime->mTimeStamp.IsNull());
424 explicit WidgetEventTime(TimeStamp aTimeStamp) : mTimeStamp(aTimeStamp) {}
426 void AssignEventTime(const WidgetEventTime& aOther) {
427 mTimeStamp = aOther.mTimeStamp;
431 /******************************************************************************
432 * mozilla::WidgetEvent
433 ******************************************************************************/
435 class WidgetEvent : public WidgetEventTime {
436 private:
437 void SetDefaultCancelableAndBubbles() {
438 switch (mClass) {
439 case eEditorInputEventClass:
440 mFlags.mCancelable = false;
441 mFlags.mBubbles = mFlags.mIsTrusted;
442 break;
443 case eLegacyTextEventClass:
444 mFlags.mCancelable = mFlags.mIsTrusted && mMessage == eLegacyTextInput;
445 mFlags.mBubbles = mFlags.mIsTrusted && mMessage == eLegacyTextInput;
446 break;
447 case eMouseEventClass:
448 mFlags.mCancelable =
449 (mMessage != eMouseEnter && mMessage != eMouseLeave);
450 mFlags.mBubbles = (mMessage != eMouseEnter && mMessage != eMouseLeave);
451 break;
452 case ePointerEventClass:
453 mFlags.mCancelable =
454 (mMessage != ePointerEnter && mMessage != ePointerLeave &&
455 mMessage != ePointerCancel && mMessage != ePointerGotCapture &&
456 mMessage != ePointerLostCapture);
457 mFlags.mBubbles =
458 (mMessage != ePointerEnter && mMessage != ePointerLeave);
459 break;
460 case eDragEventClass:
461 mFlags.mCancelable = (mMessage != eDragExit && mMessage != eDragLeave &&
462 mMessage != eDragEnd);
463 mFlags.mBubbles = true;
464 break;
465 case eSMILTimeEventClass:
466 mFlags.mCancelable = false;
467 mFlags.mBubbles = false;
468 break;
469 case eTransitionEventClass:
470 case eAnimationEventClass:
471 mFlags.mCancelable = false;
472 mFlags.mBubbles = true;
473 break;
474 case eCompositionEventClass:
475 // XXX compositionstart is cancelable in draft of DOM3 Events.
476 // However, it doesn't make sense for us, we cannot cancel
477 // composition when we send compositionstart event.
478 mFlags.mCancelable = false;
479 mFlags.mBubbles = true;
480 break;
481 default:
482 if (mMessage == eResize || mMessage == eMozVisualResize ||
483 mMessage == eMozVisualScroll || mMessage == eEditorInput ||
484 mMessage == eFormSelect) {
485 mFlags.mCancelable = false;
486 } else {
487 mFlags.mCancelable = true;
489 mFlags.mBubbles = true;
490 break;
494 protected:
495 WidgetEvent(bool aIsTrusted, EventMessage aMessage,
496 EventClassID aEventClassID,
497 const WidgetEventTime* aTime = nullptr)
498 : WidgetEventTime(aTime),
499 mClass(aEventClassID),
500 mMessage(aMessage),
501 mRefPoint(0, 0),
502 mLastRefPoint(0, 0),
503 mFocusSequenceNumber(0),
504 mSpecifiedEventType(nullptr),
505 mPath(nullptr),
506 mLayersId(layers::LayersId{0}) {
507 MOZ_COUNT_CTOR(WidgetEvent);
508 mFlags.Clear();
509 mFlags.mIsTrusted = aIsTrusted;
510 SetDefaultCancelableAndBubbles();
511 SetDefaultComposed();
512 SetDefaultComposedInNativeAnonymousContent();
515 WidgetEvent() : mPath(nullptr) { MOZ_COUNT_CTOR(WidgetEvent); }
517 public:
518 WidgetEvent(bool aIsTrusted, EventMessage aMessage,
519 const WidgetEventTime* aTime = nullptr)
520 : WidgetEvent(aIsTrusted, aMessage, eBasicEventClass, aTime) {}
522 MOZ_COUNTED_DTOR_VIRTUAL(WidgetEvent)
524 WidgetEvent(const WidgetEvent& aOther) : WidgetEventTime(aOther) {
525 MOZ_COUNT_CTOR(WidgetEvent);
526 *this = aOther;
528 WidgetEvent& operator=(const WidgetEvent& aOther) = default;
530 WidgetEvent(WidgetEvent&& aOther)
531 : WidgetEventTime(std::move(aOther)),
532 mClass(aOther.mClass),
533 mMessage(aOther.mMessage),
534 mRefPoint(std::move(aOther.mRefPoint)),
535 mLastRefPoint(std::move(aOther.mLastRefPoint)),
536 mFocusSequenceNumber(aOther.mFocusSequenceNumber),
537 mFlags(std::move(aOther.mFlags)),
538 mSpecifiedEventType(std::move(aOther.mSpecifiedEventType)),
539 mSpecifiedEventTypeString(std::move(aOther.mSpecifiedEventTypeString)),
540 mTarget(std::move(aOther.mTarget)),
541 mCurrentTarget(std::move(aOther.mCurrentTarget)),
542 mOriginalTarget(std::move(aOther.mOriginalTarget)),
543 mRelatedTarget(std::move(aOther.mRelatedTarget)),
544 mOriginalRelatedTarget(std::move(aOther.mOriginalRelatedTarget)),
545 mPath(std::move(aOther.mPath)) {
546 MOZ_COUNT_CTOR(WidgetEvent);
548 WidgetEvent& operator=(WidgetEvent&& aOther) = default;
550 virtual WidgetEvent* Duplicate() const {
551 MOZ_ASSERT(mClass == eBasicEventClass,
552 "Duplicate() must be overridden by sub class");
553 WidgetEvent* result = new WidgetEvent(false, mMessage, this);
554 result->AssignEventData(*this, true);
555 result->mFlags = mFlags;
556 return result;
559 EventClassID mClass;
560 EventMessage mMessage;
561 // Relative to the widget of the event, or if there is no widget then it is
562 // in screen coordinates. Not modified by layout code.
563 // This is in visual coordinates, i.e. the correct RelativeTo value that
564 // expresses what this is relative to is `{viewportFrame, Visual}`, where
565 // `viewportFrame` is the viewport frame of the widget's root document.
566 LayoutDeviceIntPoint mRefPoint;
567 // The previous mRefPoint, if known, used to calculate mouse movement deltas.
568 LayoutDeviceIntPoint mLastRefPoint;
569 // The sequence number of the last potentially focus changing event handled
570 // by APZ. This is used to track when that event has been processed by
571 // content, and focus can be reconfirmed for async keyboard scrolling.
572 uint64_t mFocusSequenceNumber;
573 // See BaseEventFlags definition for the detail.
574 BaseEventFlags mFlags;
576 // If JS creates an event with unknown event type or known event type but
577 // for different event interface, the event type is stored to this.
578 // NOTE: This is always used if the instance is a WidgetCommandEvent instance
579 // or "input" event is dispatched with dom::Event class.
580 RefPtr<nsAtom> mSpecifiedEventType;
582 // nsAtom isn't available on non-main thread due to unsafe. Therefore,
583 // mSpecifiedEventTypeString is used instead of mSpecifiedEventType if
584 // the event is created in non-main thread.
585 nsString mSpecifiedEventTypeString;
587 // Event targets, needed by DOM Events
588 // Note that when you need event target for DOM event, you should use
589 // Get*DOMEventTarget() instead of accessing these members directly.
590 nsCOMPtr<dom::EventTarget> mTarget;
591 nsCOMPtr<dom::EventTarget> mCurrentTarget;
592 nsCOMPtr<dom::EventTarget> mOriginalTarget;
594 /// The possible related target
595 nsCOMPtr<dom::EventTarget> mRelatedTarget;
596 nsCOMPtr<dom::EventTarget> mOriginalRelatedTarget;
598 nsTArray<EventTargetChainItem>* mPath;
600 // The LayersId of the content process that this event should be
601 // dispatched to. This field is only used in the chrome process
602 // and doesn't get remoted to child processes.
603 layers::LayersId mLayersId;
605 dom::EventTarget* GetDOMEventTarget() const;
606 dom::EventTarget* GetCurrentDOMEventTarget() const;
607 dom::EventTarget* GetOriginalDOMEventTarget() const;
609 void AssignEventData(const WidgetEvent& aEvent, bool aCopyTargets) {
610 // mClass should be initialized with the constructor.
611 // mMessage should be initialized with the constructor.
612 mRefPoint = aEvent.mRefPoint;
613 // mLastRefPoint doesn't need to be copied.
614 mFocusSequenceNumber = aEvent.mFocusSequenceNumber;
615 // mLayersId intentionally not copied, since it's not used within content
616 AssignEventTime(aEvent);
617 // mFlags should be copied manually if it's necessary.
618 mSpecifiedEventType = aEvent.mSpecifiedEventType;
619 // mSpecifiedEventTypeString should be copied manually if it's necessary.
620 mTarget = aCopyTargets ? aEvent.mTarget : nullptr;
621 mCurrentTarget = aCopyTargets ? aEvent.mCurrentTarget : nullptr;
622 mOriginalTarget = aCopyTargets ? aEvent.mOriginalTarget : nullptr;
623 mRelatedTarget = aCopyTargets ? aEvent.mRelatedTarget : nullptr;
624 mOriginalRelatedTarget =
625 aCopyTargets ? aEvent.mOriginalRelatedTarget : nullptr;
629 * Helper methods for methods of DOM Event.
631 void StopPropagation() { mFlags.StopPropagation(); }
632 void StopImmediatePropagation() { mFlags.StopImmediatePropagation(); }
633 void PreventDefault(bool aCalledByDefaultHandler = true,
634 nsIPrincipal* aPrincipal = nullptr);
636 void PreventDefaultBeforeDispatch(
637 CrossProcessForwarding aCrossProcessForwarding) {
638 mFlags.PreventDefaultBeforeDispatch(aCrossProcessForwarding);
640 bool DefaultPrevented() const { return mFlags.DefaultPrevented(); }
641 bool DefaultPreventedByContent() const {
642 return mFlags.DefaultPreventedByContent();
644 bool IsTrusted() const { return mFlags.IsTrusted(); }
645 bool PropagationStopped() const { return mFlags.PropagationStopped(); }
648 * Prevent to be dispatched to remote process.
650 inline void StopCrossProcessForwarding() {
651 mFlags.StopCrossProcessForwarding();
654 * Return true if the event shouldn't be dispatched to remote process.
656 inline bool IsCrossProcessForwardingStopped() const {
657 return mFlags.IsCrossProcessForwardingStopped();
660 * Mark the event as waiting reply from remote process.
661 * Note that this also stops immediate propagation in current process.
663 inline void MarkAsWaitingReplyFromRemoteProcess() {
664 mFlags.MarkAsWaitingReplyFromRemoteProcess();
667 * Reset "waiting reply from remote process" state. This is useful when
668 * you dispatch a copy of an event coming from different process.
670 inline void ResetWaitingReplyFromRemoteProcessState() {
671 mFlags.ResetWaitingReplyFromRemoteProcessState();
674 * Return true if the event handler should wait reply event. I.e., if this
675 * returns true, any event handler should do nothing with the event.
677 inline bool IsWaitingReplyFromRemoteProcess() const {
678 return mFlags.IsWaitingReplyFromRemoteProcess();
681 * Mark the event as already handled in the remote process. This should be
682 * called when initializing reply events.
684 inline void MarkAsHandledInRemoteProcess() {
685 mFlags.MarkAsHandledInRemoteProcess();
688 * Return true if the event has already been handled in the remote process.
689 * I.e., if this returns true, the event is a reply event.
691 inline bool IsHandledInRemoteProcess() const {
692 return mFlags.IsHandledInRemoteProcess();
695 * Return true if the event should be sent back to its parent process.
696 * So, usual event handlers shouldn't call this.
698 inline bool WantReplyFromContentProcess() const {
699 return mFlags.WantReplyFromContentProcess();
702 * Mark the event has already posted to a remote process.
704 inline void MarkAsPostedToRemoteProcess() {
705 mFlags.MarkAsPostedToRemoteProcess();
708 * Reset the cross process dispatching state. This should be used when a
709 * process receives the event because the state is in the sender.
711 inline void ResetCrossProcessDispatchingState() {
712 mFlags.ResetCrossProcessDispatchingState();
715 * Return true if the event has been posted to a remote process.
717 inline bool HasBeenPostedToRemoteProcess() const {
718 return mFlags.HasBeenPostedToRemoteProcess();
721 * Return true if the event came from another process.
723 inline bool CameFromAnotherProcess() const {
724 return mFlags.CameFromAnotherProcess();
727 * Mark the event as coming from another process.
729 inline void MarkAsComingFromAnotherProcess() {
730 mFlags.MarkAsComingFromAnotherProcess();
733 * Mark the event is reserved by chrome. I.e., shouldn't be dispatched to
734 * content because it shouldn't be cancelable.
736 inline void MarkAsReservedByChrome() { mFlags.MarkAsReservedByChrome(); }
738 * Return true if the event is reserved by chrome.
740 inline bool IsReservedByChrome() const { return mFlags.IsReservedByChrome(); }
743 * Return true if the corresponding DOM event supports screen(X|Y), etc.
745 [[nodiscard]] inline bool DOMEventSupportsCoords() const {
746 switch (mClass) {
747 case eMouseEventClass:
748 case eMouseScrollEventClass:
749 case eWheelEventClass:
750 case eTouchEventClass:
751 case eDragEventClass:
752 case ePointerEventClass:
753 case eSimpleGestureEventClass:
754 return true;
755 default:
756 return false;
761 * Utils for checking event types
765 * As*Event() returns the pointer of the instance only when the instance is
766 * the class or one of its derived class.
768 #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
769 #define NS_EVENT_CLASS(aPrefix, aName) \
770 virtual aPrefix##aName* As##aName(); \
771 const aPrefix##aName* As##aName() const;
773 #include "mozilla/EventClassList.h"
775 #undef NS_EVENT_CLASS
776 #undef NS_ROOT_EVENT_CLASS
779 * Returns true if the event is a query content event.
781 bool IsQueryContentEvent() const;
783 * Returns true if the event is a selection event.
785 bool IsSelectionEvent() const;
787 * Returns true if the event is a content command event.
789 bool IsContentCommandEvent() const;
792 * Returns true if the event mMessage is one of mouse events.
794 bool HasMouseEventMessage() const;
797 * Returns true if the event class is eMouseEventClass or the event message
798 * is ePointerClick.
800 [[nodiscard]] bool IsMouseEventClassOrHasClickRelatedPointerEvent() const;
803 * Returns true if the event mMessage is one of drag events.
805 bool HasDragEventMessage() const;
807 * Returns true if aMessage or mMessage is one of key events.
809 static bool IsKeyEventMessage(EventMessage aMessage);
810 bool HasKeyEventMessage() const { return IsKeyEventMessage(mMessage); }
812 * Returns true if the event mMessage is one of composition events or text
813 * event.
815 bool HasIMEEventMessage() const;
818 * Returns true if the event can be sent to remote process.
820 bool CanBeSentToRemoteProcess() const;
822 * Returns true if the original target is a remote process and the event
823 * will be posted to the remote process later.
825 bool WillBeSentToRemoteProcess() const;
827 * Returns true if the event is related to IME handling. It includes
828 * IME events, query content events and selection events.
829 * Be careful when you use this.
831 bool IsIMERelatedEvent() const;
834 * Whether the event should be handled by the frame of the mouse cursor
835 * position or not. When it should be handled there (e.g., the mouse events),
836 * this returns true.
838 bool IsUsingCoordinates() const;
840 * Whether the event should be handled by the focused DOM window in the
841 * same top level window's or not. E.g., key events, IME related events
842 * (including the query content events, they are used in IME transaction)
843 * should be handled by the (last) focused window rather than the dispatched
844 * window.
846 * NOTE: Even if this returns true, the event isn't going to be handled by the
847 * application level active DOM window which is on another top level window.
848 * So, when the event is fired on a deactive window, the event is going to be
849 * handled by the last focused DOM window in the last focused window.
851 bool IsTargetedAtFocusedWindow() const;
853 * Whether the event should be handled by the focused content or not. E.g.,
854 * key events, IME related events and other input events which are not handled
855 * by the frame of the mouse cursor position.
857 * NOTE: Even if this returns true, the event isn't going to be handled by the
858 * application level active DOM window which is on another top level window.
859 * So, when the event is fired on a deactive window, the event is going to be
860 * handled by the last focused DOM element of the last focused DOM window in
861 * the last focused window.
863 bool IsTargetedAtFocusedContent() const;
865 * Whether the event should cause a DOM event.
867 bool IsAllowedToDispatchDOMEvent() const;
869 * Whether the event should be dispatched in system group.
871 bool IsAllowedToDispatchInSystemGroup() const;
873 * Whether the event should be blocked for fingerprinting resistance.
875 bool IsBlockedForFingerprintingResistance() const;
877 * Whether the event handler can flush pending notifications or not.
879 bool AllowFlushingPendingNotifications() const;
881 * Initialize mComposed
883 void SetDefaultComposed() {
884 switch (mClass) {
885 case eClipboardEventClass:
886 mFlags.mComposed = true;
887 break;
888 case eCompositionEventClass:
889 mFlags.mComposed =
890 mMessage == eCompositionStart || mMessage == eCompositionUpdate ||
891 mMessage == eCompositionChange || mMessage == eCompositionEnd;
892 break;
893 case eDragEventClass:
894 // All drag & drop events are composed
895 mFlags.mComposed = mMessage == eDrag || mMessage == eDragEnd ||
896 mMessage == eDragEnter || mMessage == eDragExit ||
897 mMessage == eDragLeave || mMessage == eDragOver ||
898 mMessage == eDragStart || mMessage == eDrop;
899 break;
900 case eEditorInputEventClass:
901 mFlags.mComposed =
902 mMessage == eEditorInput || mMessage == eEditorBeforeInput;
903 break;
904 case eFocusEventClass:
905 mFlags.mComposed = mMessage == eBlur || mMessage == eFocus ||
906 mMessage == eFocusOut || mMessage == eFocusIn;
907 break;
908 case eKeyboardEventClass:
909 mFlags.mComposed =
910 mMessage == eKeyDown || mMessage == eKeyUp || mMessage == eKeyPress;
911 break;
912 case eMouseEventClass:
913 mFlags.mComposed =
914 mMessage == eMouseDoubleClick || mMessage == eMouseDown ||
915 mMessage == eMouseUp || mMessage == eMouseOver ||
916 mMessage == eMouseOut || mMessage == eMouseMove ||
917 mMessage == eXULPopupShowing || mMessage == eXULPopupHiding ||
918 mMessage == eXULPopupShown || mMessage == eXULPopupHidden ||
919 // `click` event, `auxclick` event and `contextmenu` event should be
920 // created as a PointerEvent, but they were MouseEvent before.
921 // Additionally, we support dispatching untrusted these events to
922 // some elements may cause a default action of it even if they are
923 // created with MouseEvent. Therefore, we need to allow these event
924 // messages here.
925 mMessage == ePointerClick || mMessage == ePointerAuxClick ||
926 mMessage == eContextMenu;
927 break;
928 case ePointerEventClass:
929 // All pointer events are composed
930 mFlags.mComposed =
931 mMessage == ePointerClick || mMessage == ePointerAuxClick ||
932 mMessage == eContextMenu || mMessage == ePointerDown ||
933 mMessage == ePointerMove || mMessage == ePointerUp ||
934 mMessage == ePointerCancel || mMessage == ePointerOver ||
935 mMessage == ePointerOut || mMessage == ePointerGotCapture ||
936 mMessage == ePointerLostCapture;
937 break;
938 case eTouchEventClass:
939 // All touch events are composed
940 mFlags.mComposed = mMessage == eTouchStart || mMessage == eTouchEnd ||
941 mMessage == eTouchMove || mMessage == eTouchCancel;
942 break;
943 case eUIEventClass:
944 mFlags.mComposed = mMessage == eLegacyDOMFocusIn ||
945 mMessage == eLegacyDOMFocusOut ||
946 mMessage == eLegacyDOMActivate;
947 break;
948 case eWheelEventClass:
949 // All wheel events are composed
950 mFlags.mComposed = mMessage == eWheel;
951 break;
952 case eMouseScrollEventClass:
953 // Legacy mouse scroll events are composed too, for consistency with
954 // wheel.
955 mFlags.mComposed = mMessage == eLegacyMouseLineOrPageScroll ||
956 mMessage == eLegacyMousePixelScroll;
957 break;
958 default:
959 mFlags.mComposed = false;
960 break;
964 void SetComposed(const nsAString& aEventTypeArg) {
965 mFlags.mComposed = // composition events
966 aEventTypeArg.EqualsLiteral("compositionstart") ||
967 aEventTypeArg.EqualsLiteral("compositionupdate") ||
968 aEventTypeArg.EqualsLiteral("compositionend") ||
969 aEventTypeArg.EqualsLiteral("text") ||
970 // drag and drop events
971 aEventTypeArg.EqualsLiteral("dragstart") ||
972 aEventTypeArg.EqualsLiteral("drag") ||
973 aEventTypeArg.EqualsLiteral("dragenter") ||
974 aEventTypeArg.EqualsLiteral("dragexit") ||
975 aEventTypeArg.EqualsLiteral("dragleave") ||
976 aEventTypeArg.EqualsLiteral("dragover") ||
977 aEventTypeArg.EqualsLiteral("drop") ||
978 aEventTypeArg.EqualsLiteral("dropend") ||
979 // editor input events
980 aEventTypeArg.EqualsLiteral("input") ||
981 aEventTypeArg.EqualsLiteral("beforeinput") ||
982 // focus events
983 aEventTypeArg.EqualsLiteral("blur") ||
984 aEventTypeArg.EqualsLiteral("focus") ||
985 aEventTypeArg.EqualsLiteral("focusin") ||
986 aEventTypeArg.EqualsLiteral("focusout") ||
987 // keyboard events
988 aEventTypeArg.EqualsLiteral("keydown") ||
989 aEventTypeArg.EqualsLiteral("keyup") ||
990 aEventTypeArg.EqualsLiteral("keypress") ||
991 // mouse events
992 aEventTypeArg.EqualsLiteral("click") ||
993 aEventTypeArg.EqualsLiteral("dblclick") ||
994 aEventTypeArg.EqualsLiteral("mousedown") ||
995 aEventTypeArg.EqualsLiteral("mouseup") ||
996 aEventTypeArg.EqualsLiteral("mouseenter") ||
997 aEventTypeArg.EqualsLiteral("mouseleave") ||
998 aEventTypeArg.EqualsLiteral("mouseover") ||
999 aEventTypeArg.EqualsLiteral("mouseout") ||
1000 aEventTypeArg.EqualsLiteral("mousemove") ||
1001 aEventTypeArg.EqualsLiteral("contextmenu") ||
1002 // pointer events
1003 aEventTypeArg.EqualsLiteral("pointerdown") ||
1004 aEventTypeArg.EqualsLiteral("pointermove") ||
1005 aEventTypeArg.EqualsLiteral("pointerup") ||
1006 aEventTypeArg.EqualsLiteral("pointercancel") ||
1007 aEventTypeArg.EqualsLiteral("pointerover") ||
1008 aEventTypeArg.EqualsLiteral("pointerout") ||
1009 aEventTypeArg.EqualsLiteral("pointerenter") ||
1010 aEventTypeArg.EqualsLiteral("pointerleave") ||
1011 aEventTypeArg.EqualsLiteral("gotpointercapture") ||
1012 aEventTypeArg.EqualsLiteral("lostpointercapture") ||
1013 // touch events
1014 aEventTypeArg.EqualsLiteral("touchstart") ||
1015 aEventTypeArg.EqualsLiteral("touchend") ||
1016 aEventTypeArg.EqualsLiteral("touchmove") ||
1017 aEventTypeArg.EqualsLiteral("touchcancel") ||
1018 // UI legacy events
1019 aEventTypeArg.EqualsLiteral("DOMFocusIn") ||
1020 aEventTypeArg.EqualsLiteral("DOMFocusOut") ||
1021 aEventTypeArg.EqualsLiteral("DOMActivate") ||
1022 // wheel events
1023 aEventTypeArg.EqualsLiteral("wheel");
1026 void SetComposed(bool aComposed) { mFlags.mComposed = aComposed; }
1028 void SetDefaultComposedInNativeAnonymousContent() {
1029 // For compatibility concerns, we set mComposedInNativeAnonymousContent to
1030 // false for those events we want to stop propagation.
1032 // nsVideoFrame may create anonymous image element which fires eLoad,
1033 // eLoadStart, eLoadEnd, eLoadError. We don't want these events cross
1034 // the boundary of NAC
1035 mFlags.mComposedInNativeAnonymousContent =
1036 mMessage != eLoad && mMessage != eLoadStart && mMessage != eLoadEnd &&
1037 mMessage != eLoadError;
1040 bool IsUserAction() const;
1043 * Return true if the event should be handled without (pointer) capturing
1044 * element.
1046 [[nodiscard]] bool ShouldIgnoreCapturingContent() const;
1049 /******************************************************************************
1050 * mozilla::WidgetGUIEvent
1051 ******************************************************************************/
1053 class WidgetGUIEvent : public WidgetEvent {
1054 protected:
1055 WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1056 EventClassID aEventClassID,
1057 const WidgetEventTime* aTime = nullptr)
1058 : WidgetEvent(aIsTrusted, aMessage, aEventClassID, aTime),
1059 mWidget(aWidget) {}
1061 WidgetGUIEvent() = default;
1063 public:
1064 virtual WidgetGUIEvent* AsGUIEvent() override { return this; }
1066 WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1067 const WidgetEventTime* aTime = nullptr)
1068 : WidgetEvent(aIsTrusted, aMessage, eGUIEventClass, aTime),
1069 mWidget(aWidget) {}
1071 virtual WidgetEvent* Duplicate() const override {
1072 MOZ_ASSERT(mClass == eGUIEventClass,
1073 "Duplicate() must be overridden by sub class");
1074 // Not copying widget, it is a weak reference.
1075 WidgetGUIEvent* result = new WidgetGUIEvent(false, mMessage, nullptr, this);
1076 result->AssignGUIEventData(*this, true);
1077 result->mFlags = mFlags;
1078 return result;
1081 // Originator of the event
1082 nsCOMPtr<nsIWidget> mWidget;
1084 void AssignGUIEventData(const WidgetGUIEvent& aEvent, bool aCopyTargets) {
1085 AssignEventData(aEvent, aCopyTargets);
1086 // widget should be initialized with the constructor.
1090 /******************************************************************************
1091 * mozilla::Modifier
1093 * All modifier keys should be defined here. This is used for managing
1094 * modifier states for DOM Level 3 or later.
1095 ******************************************************************************/
1097 enum Modifier {
1098 MODIFIER_NONE = 0x0000,
1099 MODIFIER_ALT = 0x0001,
1100 MODIFIER_ALTGRAPH = 0x0002,
1101 MODIFIER_CAPSLOCK = 0x0004,
1102 MODIFIER_CONTROL = 0x0008,
1103 MODIFIER_FN = 0x0010,
1104 MODIFIER_FNLOCK = 0x0020,
1105 MODIFIER_META = 0x0040,
1106 MODIFIER_NUMLOCK = 0x0080,
1107 MODIFIER_SCROLLLOCK = 0x0100,
1108 MODIFIER_SHIFT = 0x0200,
1109 MODIFIER_SYMBOL = 0x0400,
1110 MODIFIER_SYMBOLLOCK = 0x0800,
1113 /******************************************************************************
1114 * Modifier key names.
1115 ******************************************************************************/
1117 #define NS_DOM_KEYNAME_ALT "Alt"
1118 #define NS_DOM_KEYNAME_ALTGRAPH "AltGraph"
1119 #define NS_DOM_KEYNAME_CAPSLOCK "CapsLock"
1120 #define NS_DOM_KEYNAME_CONTROL "Control"
1121 #define NS_DOM_KEYNAME_FN "Fn"
1122 #define NS_DOM_KEYNAME_FNLOCK "FnLock"
1123 #define NS_DOM_KEYNAME_META "Meta"
1124 #define NS_DOM_KEYNAME_NUMLOCK "NumLock"
1125 #define NS_DOM_KEYNAME_SCROLLLOCK "ScrollLock"
1126 #define NS_DOM_KEYNAME_SHIFT "Shift"
1127 #define NS_DOM_KEYNAME_SYMBOL "Symbol"
1128 #define NS_DOM_KEYNAME_SYMBOLLOCK "SymbolLock"
1129 #define NS_DOM_KEYNAME_OS "OS"
1131 /******************************************************************************
1132 * mozilla::Modifiers
1133 ******************************************************************************/
1135 typedef uint16_t Modifiers;
1137 class MOZ_STACK_CLASS GetModifiersName final : public nsAutoCString {
1138 public:
1139 explicit GetModifiersName(Modifiers aModifiers) {
1140 if (aModifiers & MODIFIER_ALT) {
1141 AssignLiteral(NS_DOM_KEYNAME_ALT);
1143 if (aModifiers & MODIFIER_ALTGRAPH) {
1144 MaybeAppendSeparator();
1145 AppendLiteral(NS_DOM_KEYNAME_ALTGRAPH);
1147 if (aModifiers & MODIFIER_CAPSLOCK) {
1148 MaybeAppendSeparator();
1149 AppendLiteral(NS_DOM_KEYNAME_CAPSLOCK);
1151 if (aModifiers & MODIFIER_CONTROL) {
1152 MaybeAppendSeparator();
1153 AppendLiteral(NS_DOM_KEYNAME_CONTROL);
1155 if (aModifiers & MODIFIER_FN) {
1156 MaybeAppendSeparator();
1157 AppendLiteral(NS_DOM_KEYNAME_FN);
1159 if (aModifiers & MODIFIER_FNLOCK) {
1160 MaybeAppendSeparator();
1161 AppendLiteral(NS_DOM_KEYNAME_FNLOCK);
1163 if (aModifiers & MODIFIER_META) {
1164 MaybeAppendSeparator();
1165 AppendLiteral(NS_DOM_KEYNAME_META);
1167 if (aModifiers & MODIFIER_NUMLOCK) {
1168 MaybeAppendSeparator();
1169 AppendLiteral(NS_DOM_KEYNAME_NUMLOCK);
1171 if (aModifiers & MODIFIER_SCROLLLOCK) {
1172 MaybeAppendSeparator();
1173 AppendLiteral(NS_DOM_KEYNAME_SCROLLLOCK);
1175 if (aModifiers & MODIFIER_SHIFT) {
1176 MaybeAppendSeparator();
1177 AppendLiteral(NS_DOM_KEYNAME_SHIFT);
1179 if (aModifiers & MODIFIER_SYMBOL) {
1180 MaybeAppendSeparator();
1181 AppendLiteral(NS_DOM_KEYNAME_SYMBOL);
1183 if (aModifiers & MODIFIER_SYMBOLLOCK) {
1184 MaybeAppendSeparator();
1185 AppendLiteral(NS_DOM_KEYNAME_SYMBOLLOCK);
1187 if (IsEmpty()) {
1188 AssignLiteral("none");
1192 private:
1193 void MaybeAppendSeparator() {
1194 if (!IsEmpty()) {
1195 AppendLiteral(" | ");
1200 /******************************************************************************
1201 * mozilla::WidgetInputEvent
1202 ******************************************************************************/
1204 class WidgetInputEvent : public WidgetGUIEvent {
1205 protected:
1206 WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1207 EventClassID aEventClassID,
1208 const WidgetEventTime* aTime = nullptr)
1209 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID, aTime),
1210 mModifiers(0) {}
1212 WidgetInputEvent() : mModifiers(0) {}
1214 public:
1215 virtual WidgetInputEvent* AsInputEvent() override { return this; }
1217 WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1218 const WidgetEventTime* aTime = nullptr)
1219 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eInputEventClass, aTime),
1220 mModifiers(0) {}
1222 virtual WidgetEvent* Duplicate() const override {
1223 MOZ_ASSERT(mClass == eInputEventClass,
1224 "Duplicate() must be overridden by sub class");
1225 // Not copying widget, it is a weak reference.
1226 WidgetInputEvent* result =
1227 new WidgetInputEvent(false, mMessage, nullptr, this);
1228 result->AssignInputEventData(*this, true);
1229 result->mFlags = mFlags;
1230 return result;
1234 * Returns a modifier of "Accel" virtual modifier which is used for shortcut
1235 * key.
1237 static Modifier AccelModifier();
1240 * GetModifier() returns a modifier flag which is activated by aDOMKeyName.
1242 static Modifier GetModifier(const nsAString& aDOMKeyName);
1244 // true indicates the accel key on the environment is down
1245 bool IsAccel() const { return ((mModifiers & AccelModifier()) != 0); }
1247 // true indicates the shift key is down
1248 bool IsShift() const { return ((mModifiers & MODIFIER_SHIFT) != 0); }
1249 // true indicates the control key is down
1250 bool IsControl() const { return ((mModifiers & MODIFIER_CONTROL) != 0); }
1251 // true indicates the alt key is down
1252 bool IsAlt() const { return ((mModifiers & MODIFIER_ALT) != 0); }
1253 // true indicates the meta key is down (Command key on macOS, Windows logo key
1254 // on Windows, Super/Hyper key on Linux, Meta key on Android).
1255 bool IsMeta() const { return ((mModifiers & MODIFIER_META) != 0); }
1256 // true indicates the alt graph key is down
1257 // NOTE: on Mac, the option key press causes both IsAlt() and IsAltGrpah()
1258 // return true.
1259 bool IsAltGraph() const { return ((mModifiers & MODIFIER_ALTGRAPH) != 0); }
1260 // true indicates the CapLock LED is turn on.
1261 bool IsCapsLocked() const { return ((mModifiers & MODIFIER_CAPSLOCK) != 0); }
1262 // true indicates the NumLock LED is turn on.
1263 bool IsNumLocked() const { return ((mModifiers & MODIFIER_NUMLOCK) != 0); }
1264 // true indicates the ScrollLock LED is turn on.
1265 bool IsScrollLocked() const {
1266 return ((mModifiers & MODIFIER_SCROLLLOCK) != 0);
1269 // true indicates the Fn key is down, but this is not supported by native
1270 // key event on any platform.
1271 bool IsFn() const { return ((mModifiers & MODIFIER_FN) != 0); }
1272 // true indicates the FnLock LED is turn on, but we don't know such
1273 // keyboards nor platforms.
1274 bool IsFnLocked() const { return ((mModifiers & MODIFIER_FNLOCK) != 0); }
1275 // true indicates the Symbol is down, but this is not supported by native
1276 // key event on any platforms.
1277 bool IsSymbol() const { return ((mModifiers & MODIFIER_SYMBOL) != 0); }
1278 // true indicates the SymbolLock LED is turn on, but we don't know such
1279 // keyboards nor platforms.
1280 bool IsSymbolLocked() const {
1281 return ((mModifiers & MODIFIER_SYMBOLLOCK) != 0);
1284 void InitBasicModifiers(bool aCtrlKey, bool aAltKey, bool aShiftKey,
1285 bool aMetaKey) {
1286 mModifiers = 0;
1287 if (aCtrlKey) {
1288 mModifiers |= MODIFIER_CONTROL;
1290 if (aAltKey) {
1291 mModifiers |= MODIFIER_ALT;
1293 if (aShiftKey) {
1294 mModifiers |= MODIFIER_SHIFT;
1296 if (aMetaKey) {
1297 mModifiers |= MODIFIER_META;
1301 Modifiers mModifiers;
1303 void AssignInputEventData(const WidgetInputEvent& aEvent, bool aCopyTargets) {
1304 AssignGUIEventData(aEvent, aCopyTargets);
1306 mModifiers = aEvent.mModifiers;
1310 /******************************************************************************
1311 * mozilla::InternalUIEvent
1313 * XXX Why this inherits WidgetGUIEvent rather than WidgetEvent?
1314 ******************************************************************************/
1316 class InternalUIEvent : public WidgetGUIEvent {
1317 protected:
1318 InternalUIEvent() : mDetail(0), mCausedByUntrustedEvent(false) {}
1320 InternalUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1321 EventClassID aEventClassID,
1322 const WidgetEventTime* aTime = nullptr)
1323 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID, aTime),
1324 mDetail(0),
1325 mCausedByUntrustedEvent(false) {}
1327 InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1328 EventClassID aEventClassID,
1329 const WidgetEventTime* aTime = nullptr)
1330 : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, aEventClassID, aTime),
1331 mDetail(0),
1332 mCausedByUntrustedEvent(false) {}
1334 public:
1335 virtual InternalUIEvent* AsUIEvent() override { return this; }
1338 * If the UIEvent is caused by another event (e.g., click event),
1339 * aEventCausesThisEvent should be the event. If there is no such event,
1340 * this should be nullptr.
1342 InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1343 const WidgetEvent* aEventCausesThisEvent,
1344 const WidgetEventTime* aTime = nullptr)
1345 : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, eUIEventClass, aTime),
1346 mDetail(0),
1347 mCausedByUntrustedEvent(aEventCausesThisEvent &&
1348 !aEventCausesThisEvent->IsTrusted()) {}
1350 virtual WidgetEvent* Duplicate() const override {
1351 MOZ_ASSERT(mClass == eUIEventClass,
1352 "Duplicate() must be overridden by sub class");
1353 InternalUIEvent* result =
1354 new InternalUIEvent(false, mMessage, nullptr, this);
1355 result->AssignUIEventData(*this, true);
1356 result->mFlags = mFlags;
1357 return result;
1360 int32_t mDetail;
1361 // mCausedByUntrustedEvent is true if the event is caused by untrusted event.
1362 bool mCausedByUntrustedEvent;
1364 // If you check the event is a trusted event and NOT caused by an untrusted
1365 // event, IsTrustable() returns what you expected.
1366 bool IsTrustable() const { return IsTrusted() && !mCausedByUntrustedEvent; }
1368 void AssignUIEventData(const InternalUIEvent& aEvent, bool aCopyTargets) {
1369 AssignGUIEventData(aEvent, aCopyTargets);
1371 mDetail = aEvent.mDetail;
1372 mCausedByUntrustedEvent = aEvent.mCausedByUntrustedEvent;
1376 } // namespace mozilla
1378 #endif // mozilla_BasicEvents_h__