Bug 1613552 [wpt PR 21618] - Fix timeout vs. task-queue race conditions in promise...
[gecko.git] / widget / BasicEvents.h
blob4c8255b34fbca5627c61a0b77088d5edba56f543
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>
11 #include "mozilla/EventForwards.h"
12 #include "mozilla/TimeStamp.h"
13 #include "mozilla/dom/EventTarget.h"
14 #include "mozilla/layers/LayersTypes.h"
15 #include "nsCOMPtr.h"
16 #include "nsAtom.h"
17 #include "nsISupportsImpl.h"
18 #include "nsIWidget.h"
19 #include "nsString.h"
20 #include "Units.h"
22 #ifdef DEBUG
23 # include "nsXULAppAPI.h"
24 #endif // #ifdef DEBUG
26 namespace IPC {
27 template <typename T>
28 struct ParamTraits;
29 } // namespace IPC
31 namespace mozilla {
33 class EventTargetChainItem;
35 enum class CrossProcessForwarding {
36 // eStop prevents the event to be sent to remote process.
37 eStop,
38 // eAllow keeps current state of the event whether it's sent to remote
39 // process. In other words, eAllow does NOT mean that making the event
40 // sent to remote process when IsCrossProcessForwardingStopped() returns
41 // true.
42 eAllow,
45 /******************************************************************************
46 * mozilla::BaseEventFlags
48 * BaseEventFlags must be a POD struct for safe to use memcpy (including
49 * in ParamTraits<BaseEventFlags>). So don't make virtual methods, constructor,
50 * destructor and operators.
51 * This is necessary for VC which is NOT C++0x compiler.
52 ******************************************************************************/
54 struct BaseEventFlags {
55 public:
56 // If mIsTrusted is true, the event is a trusted event. Otherwise, it's
57 // an untrusted event.
58 bool mIsTrusted : 1;
59 // If mInBubblingPhase is true, the event is in bubbling phase or target
60 // phase.
61 bool mInBubblingPhase : 1;
62 // If mInCapturePhase is true, the event is in capture phase or target phase.
63 bool mInCapturePhase : 1;
64 // If mInSystemGroup is true, the event is being dispatched in system group.
65 bool mInSystemGroup : 1;
66 // If mCancelable is true, the event can be consumed. I.e., calling
67 // dom::Event::PreventDefault() can prevent the default action.
68 bool mCancelable : 1;
69 // If mBubbles is true, the event can bubble. Otherwise, cannot be handled
70 // in bubbling phase.
71 bool mBubbles : 1;
72 // If mPropagationStopped is true, dom::Event::StopPropagation() or
73 // dom::Event::StopImmediatePropagation() has been called.
74 bool mPropagationStopped : 1;
75 // If mImmediatePropagationStopped is true,
76 // dom::Event::StopImmediatePropagation() has been called.
77 // Note that mPropagationStopped must be true when this is true.
78 bool mImmediatePropagationStopped : 1;
79 // If mDefaultPrevented is true, the event has been consumed.
80 // E.g., dom::Event::PreventDefault() has been called or
81 // the default action has been performed.
82 bool mDefaultPrevented : 1;
83 // If mDefaultPreventedByContent is true, the event has been
84 // consumed by content.
85 // Note that mDefaultPrevented must be true when this is true.
86 bool mDefaultPreventedByContent : 1;
87 // If mDefaultPreventedByChrome is true, the event has been
88 // consumed by chrome.
89 // Note that mDefaultPrevented must be true when this is true.
90 bool mDefaultPreventedByChrome : 1;
91 // mMultipleActionsPrevented may be used when default handling don't want to
92 // be prevented, but only one of the event targets should handle the event.
93 // For example, when a <label> element is in another <label> element and
94 // the first <label> element is clicked, that one may set this true.
95 // Then, the second <label> element won't handle the event.
96 bool mMultipleActionsPrevented : 1;
97 // Similar to above but expected to be used during PreHandleEvent phase.
98 bool mMultiplePreActionsPrevented : 1;
99 // If mIsBeingDispatched is true, the DOM event created from the event is
100 // dispatching into the DOM tree and not completed.
101 bool mIsBeingDispatched : 1;
102 // If mDispatchedAtLeastOnce is true, the event has been dispatched
103 // as a DOM event and the dispatch has been completed in the process.
104 // So, this is false even if the event has already been dispatched
105 // in another process.
106 bool mDispatchedAtLeastOnce : 1;
107 // If mIsSynthesizedForTests is true, the event has been synthesized for
108 // automated tests or something hacky approach of an add-on.
109 bool mIsSynthesizedForTests : 1;
110 // If mExceptionWasRaised is true, one of the event handlers has raised an
111 // exception.
112 bool mExceptionWasRaised : 1;
113 // If mRetargetToNonNativeAnonymous is true and the target is in a non-native
114 // native anonymous subtree, the event target is set to mOriginalTarget.
115 bool mRetargetToNonNativeAnonymous : 1;
116 // If mNoContentDispatch is true, the event is never dispatched to the
117 // event handlers which are added to the contents, onfoo attributes and
118 // properties. Note that this flag is ignored when
119 // EventChainPreVisitor::mForceContentDispatch is set true. For exapmle,
120 // window and document object sets it true. Therefore, web applications
121 // can handle the event if they add event listeners to the window or the
122 // document.
123 // XXX This is an ancient and broken feature, don't use this for new bug
124 // as far as possible.
125 bool mNoContentDispatch : 1;
126 // If mOnlyChromeDispatch is true, the event is dispatched to only chrome.
127 bool mOnlyChromeDispatch : 1;
128 // Indicates if the key combination is reserved by chrome. This is set by
129 // MarkAsReservedByChrome().
130 bool mIsReservedByChrome : 1;
131 // If mOnlySystemGroupDispatchInContent is true, event listeners added to
132 // the default group for non-chrome EventTarget won't be called.
133 // Be aware, if this is true, EventDispatcher needs to check if each event
134 // listener is added to chrome node, so, don't set this to true for the
135 // events which are fired a lot of times like eMouseMove.
136 bool mOnlySystemGroupDispatchInContent : 1;
137 // If mOnlySystemGroupDispatch is true, the event will be dispatched only to
138 // event listeners added in the system group.
139 bool mOnlySystemGroupDispatch : 1;
140 // The event's action will be handled by APZ. The main thread should not
141 // perform its associated action.
142 bool mHandledByAPZ : 1;
143 // True if the event is currently being handled by an event listener that
144 // was registered as a passive listener.
145 bool mInPassiveListener : 1;
146 // If mComposed is true, the event fired by nodes in shadow DOM can cross the
147 // boundary of shadow DOM and light DOM.
148 bool mComposed : 1;
149 // Similar to mComposed. Set it to true to allow events cross the boundary
150 // between native non-anonymous content and native anonymouse content
151 bool mComposedInNativeAnonymousContent : 1;
152 // Set to true for events which are suppressed or delayed so that later a
153 // DelayedEvent of it is dispatched. This is used when parent side process
154 // the key event after content side, and may drop the event if the event
155 // was suppressed or delayed in contents side.
156 // It is also set to true for the events (in a DelayedInputEvent), which will
157 // be dispatched afterwards.
158 bool mIsSuppressedOrDelayed : 1;
159 // Certain mouse events can be marked as positionless to return 0 from
160 // coordinate related getters.
161 bool mIsPositionless : 1;
163 // Flags managing state of propagation between processes.
164 // Note the the following flags shouldn't be referred directly. Use utility
165 // methods instead.
167 // If mNoRemoteProcessDispatch is true, the event is not allowed to be sent
168 // to remote process.
169 bool mNoRemoteProcessDispatch : 1;
170 // If mWantReplyFromContentProcess is true, the event will be redispatched
171 // in the parent process after the content process has handled it. Useful
172 // for when the parent process need the know first how the event was used
173 // by content before handling it itself.
174 bool mWantReplyFromContentProcess : 1;
175 // If mPostedToRemoteProcess is true, the event has been posted to the
176 // remote process (but it's not handled yet if it's not a duplicated event
177 // instance).
178 bool mPostedToRemoteProcess : 1;
180 // At lease one of the event in the event path had non privileged click
181 // listener.
182 bool mHadNonPrivilegedClickListeners : 1;
184 // If the event is being handled in target phase, returns true.
185 inline bool InTargetPhase() const {
186 return (mInBubblingPhase && mInCapturePhase);
190 * Helper methods for methods of DOM Event.
192 inline void StopPropagation() { mPropagationStopped = true; }
193 inline void StopImmediatePropagation() {
194 StopPropagation();
195 mImmediatePropagationStopped = true;
197 inline void PreventDefault(bool aCalledByDefaultHandler = true) {
198 if (!mCancelable) {
199 return;
201 mDefaultPrevented = true;
202 // Note that even if preventDefault() has already been called by chrome,
203 // a call of preventDefault() by content needs to overwrite
204 // mDefaultPreventedByContent to true because in such case, defaultPrevented
205 // must be true when web apps check it after they call preventDefault().
206 if (aCalledByDefaultHandler) {
207 StopCrossProcessForwarding();
208 mDefaultPreventedByChrome = true;
209 } else {
210 mDefaultPreventedByContent = true;
213 // This should be used only before dispatching events into the DOM tree.
214 inline void PreventDefaultBeforeDispatch(
215 CrossProcessForwarding aCrossProcessForwarding) {
216 if (!mCancelable) {
217 return;
219 mDefaultPrevented = true;
220 if (aCrossProcessForwarding == CrossProcessForwarding::eStop) {
221 StopCrossProcessForwarding();
224 inline bool DefaultPrevented() const { return mDefaultPrevented; }
225 inline bool DefaultPreventedByContent() const {
226 MOZ_ASSERT(!mDefaultPreventedByContent || DefaultPrevented());
227 return mDefaultPreventedByContent;
229 inline bool IsTrusted() const { return mIsTrusted; }
230 inline bool PropagationStopped() const { return mPropagationStopped; }
232 // Helper methods to access flags managing state of propagation between
233 // processes.
236 * Prevent to be dispatched to remote process.
238 inline void StopCrossProcessForwarding() {
239 MOZ_ASSERT(!mPostedToRemoteProcess);
240 mNoRemoteProcessDispatch = true;
241 mWantReplyFromContentProcess = false;
244 * Return true if the event shouldn't be dispatched to remote process.
246 inline bool IsCrossProcessForwardingStopped() const {
247 return mNoRemoteProcessDispatch;
250 * Mark the event as waiting reply from remote process.
251 * If the caller needs to win other keyboard event handlers in chrome,
252 * the caller should call StopPropagation() too.
253 * Otherwise, if the caller just needs to know if the event is consumed by
254 * either content or chrome, it should just call this because the event
255 * may be reserved by chrome and it needs to be dispatched into the DOM
256 * tree in chrome for checking if it's reserved before being sent to any
257 * remote processes.
259 inline void MarkAsWaitingReplyFromRemoteProcess() {
260 MOZ_ASSERT(!mPostedToRemoteProcess);
261 mNoRemoteProcessDispatch = false;
262 mWantReplyFromContentProcess = true;
265 * Reset "waiting reply from remote process" state. This is useful when
266 * you dispatch a copy of an event coming from different process.
268 inline void ResetWaitingReplyFromRemoteProcessState() {
269 if (IsWaitingReplyFromRemoteProcess()) {
270 // FYI: mWantReplyFromContentProcess is also used for indicating
271 // "handled in remote process" state. Therefore, only when
272 // IsWaitingReplyFromRemoteProcess() returns true, this should
273 // reset the flag.
274 mWantReplyFromContentProcess = false;
278 * Return true if the event handler should wait reply event. I.e., if this
279 * returns true, any event handler should do nothing with the event.
281 inline bool IsWaitingReplyFromRemoteProcess() const {
282 return !mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
285 * Mark the event as already handled in the remote process. This should be
286 * called when initializing reply events.
288 inline void MarkAsHandledInRemoteProcess() {
289 mNoRemoteProcessDispatch = true;
290 mWantReplyFromContentProcess = true;
291 mPostedToRemoteProcess = false;
294 * Return true if the event has already been handled in the remote process.
296 inline bool IsHandledInRemoteProcess() const {
297 return mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
300 * Return true if the event should be sent back to its parent process.
302 inline bool WantReplyFromContentProcess() const {
303 MOZ_ASSERT(!XRE_IsParentProcess());
304 return IsWaitingReplyFromRemoteProcess();
307 * Mark the event has already posted to a remote process.
309 inline void MarkAsPostedToRemoteProcess() {
310 MOZ_ASSERT(!IsCrossProcessForwardingStopped());
311 mPostedToRemoteProcess = true;
314 * Reset the cross process dispatching state. This should be used when a
315 * process receives the event because the state is in the sender.
317 inline void ResetCrossProcessDispatchingState() {
318 MOZ_ASSERT(!IsCrossProcessForwardingStopped());
319 mPostedToRemoteProcess = false;
320 // Ignore propagation state in the different process if it's marked as
321 // "waiting reply from remote process" because the process needs to
322 // stop propagation in the process until receiving a reply event.
323 if (IsWaitingReplyFromRemoteProcess()) {
324 mPropagationStopped = mImmediatePropagationStopped = false;
326 // mDispatchedAtLeastOnce indicates the state in current process.
327 mDispatchedAtLeastOnce = false;
330 * Return true if the event has been posted to a remote process.
331 * Note that MarkAsPostedToRemoteProcess() is called by
332 * ParamTraits<mozilla::WidgetEvent>. Therefore, it *might* be possible
333 * that posting the event failed even if this returns true. But that must
334 * really rare. If that'd be problem for you, you should unmark this in
335 * BrowserParent or somewhere.
337 inline bool HasBeenPostedToRemoteProcess() const {
338 return mPostedToRemoteProcess;
341 * Mark the event is reserved by chrome. I.e., shouldn't be dispatched to
342 * content because it shouldn't be cancelable.
344 inline void MarkAsReservedByChrome() {
345 MOZ_ASSERT(!mPostedToRemoteProcess);
346 mIsReservedByChrome = true;
347 // For reserved commands (such as Open New Tab), we don't need to wait for
348 // the content to answer, neither to give a chance for content to override
349 // its behavior.
350 StopCrossProcessForwarding();
351 // If the event is reserved by chrome, we shouldn't expose the event to
352 // web contents because such events shouldn't be cancelable. So, it's not
353 // good behavior to fire such events but to ignore the defaultPrevented
354 // attribute value in chrome.
355 mOnlySystemGroupDispatchInContent = true;
358 * Return true if the event is reserved by chrome.
360 inline bool IsReservedByChrome() const {
361 MOZ_ASSERT(!mIsReservedByChrome || (IsCrossProcessForwardingStopped() &&
362 mOnlySystemGroupDispatchInContent));
363 return mIsReservedByChrome;
366 inline void Clear() { SetRawFlags(0); }
367 // Get if either the instance's bit or the aOther's bit is true, the
368 // instance's bit becomes true. In other words, this works like:
369 // eventFlags |= aOther;
370 inline void Union(const BaseEventFlags& aOther) {
371 RawFlags rawFlags = GetRawFlags() | aOther.GetRawFlags();
372 SetRawFlags(rawFlags);
375 private:
376 typedef uint64_t RawFlags;
378 inline void SetRawFlags(RawFlags aRawFlags) {
379 static_assert(sizeof(BaseEventFlags) <= sizeof(RawFlags),
380 "mozilla::EventFlags must not be bigger than the RawFlags");
381 memcpy(this, &aRawFlags, sizeof(BaseEventFlags));
383 inline RawFlags GetRawFlags() const {
384 RawFlags result = 0;
385 memcpy(&result, this, sizeof(BaseEventFlags));
386 return result;
390 /******************************************************************************
391 * mozilla::EventFlags
392 ******************************************************************************/
394 struct EventFlags : public BaseEventFlags {
395 EventFlags() { Clear(); }
398 /******************************************************************************
399 * mozilla::WidgetEventTime
400 ******************************************************************************/
402 class WidgetEventTime {
403 public:
404 // Elapsed time, in milliseconds, from a platform-specific zero time
405 // to the time the message was created
406 uint64_t mTime;
407 // Timestamp when the message was created. Set in parallel to 'time' until we
408 // determine if it is safe to drop 'time' (see bug 77992).
409 TimeStamp mTimeStamp;
411 WidgetEventTime() : mTime(0), mTimeStamp(TimeStamp::Now()) {}
413 WidgetEventTime(uint64_t aTime, TimeStamp aTimeStamp)
414 : mTime(aTime), mTimeStamp(aTimeStamp) {}
416 void AssignEventTime(const WidgetEventTime& aOther) {
417 mTime = aOther.mTime;
418 mTimeStamp = aOther.mTimeStamp;
422 /******************************************************************************
423 * mozilla::WidgetEvent
424 ******************************************************************************/
426 class WidgetEvent : public WidgetEventTime {
427 private:
428 void SetDefaultCancelableAndBubbles() {
429 switch (mClass) {
430 case eEditorInputEventClass:
431 mFlags.mCancelable = false;
432 mFlags.mBubbles = mFlags.mIsTrusted;
433 break;
434 case eMouseEventClass:
435 mFlags.mCancelable =
436 (mMessage != eMouseEnter && mMessage != eMouseLeave);
437 mFlags.mBubbles = (mMessage != eMouseEnter && mMessage != eMouseLeave);
438 break;
439 case ePointerEventClass:
440 mFlags.mCancelable =
441 (mMessage != ePointerEnter && mMessage != ePointerLeave &&
442 mMessage != ePointerCancel && mMessage != ePointerGotCapture &&
443 mMessage != ePointerLostCapture);
444 mFlags.mBubbles =
445 (mMessage != ePointerEnter && mMessage != ePointerLeave);
446 break;
447 case eDragEventClass:
448 mFlags.mCancelable = (mMessage != eDragExit && mMessage != eDragLeave &&
449 mMessage != eDragEnd);
450 mFlags.mBubbles = true;
451 break;
452 case eSMILTimeEventClass:
453 mFlags.mCancelable = false;
454 mFlags.mBubbles = false;
455 break;
456 case eTransitionEventClass:
457 case eAnimationEventClass:
458 mFlags.mCancelable = false;
459 mFlags.mBubbles = true;
460 break;
461 case eCompositionEventClass:
462 // XXX compositionstart is cancelable in draft of DOM3 Events.
463 // However, it doesn't make sense for us, we cannot cancel
464 // composition when we send compositionstart event.
465 mFlags.mCancelable = false;
466 mFlags.mBubbles = true;
467 break;
468 default:
469 if (mMessage == eResize || mMessage == eMozVisualResize ||
470 mMessage == eMozVisualScroll || mMessage == eEditorInput) {
471 mFlags.mCancelable = false;
472 } else {
473 mFlags.mCancelable = true;
475 mFlags.mBubbles = true;
476 break;
480 protected:
481 WidgetEvent(bool aIsTrusted, EventMessage aMessage,
482 EventClassID aEventClassID)
483 : WidgetEventTime(),
484 mClass(aEventClassID),
485 mMessage(aMessage),
486 mRefPoint(0, 0),
487 mLastRefPoint(0, 0),
488 mFocusSequenceNumber(0),
489 mSpecifiedEventType(nullptr),
490 mPath(nullptr),
491 mLayersId(layers::LayersId{0}) {
492 MOZ_COUNT_CTOR(WidgetEvent);
493 mFlags.Clear();
494 mFlags.mIsTrusted = aIsTrusted;
495 SetDefaultCancelableAndBubbles();
496 SetDefaultComposed();
497 SetDefaultComposedInNativeAnonymousContent();
500 WidgetEvent() : WidgetEventTime(), mPath(nullptr) {
501 MOZ_COUNT_CTOR(WidgetEvent);
504 public:
505 WidgetEvent(bool aIsTrusted, EventMessage aMessage)
506 : WidgetEvent(aIsTrusted, aMessage, eBasicEventClass) {}
508 virtual ~WidgetEvent() { MOZ_COUNT_DTOR(WidgetEvent); }
510 WidgetEvent(const WidgetEvent& aOther) : WidgetEventTime() {
511 MOZ_COUNT_CTOR(WidgetEvent);
512 *this = aOther;
514 WidgetEvent& operator=(const WidgetEvent& aOther) = default;
516 WidgetEvent(WidgetEvent&& aOther)
517 : WidgetEventTime(std::move(aOther)),
518 mClass(aOther.mClass),
519 mMessage(aOther.mMessage),
520 mRefPoint(std::move(aOther.mRefPoint)),
521 mLastRefPoint(std::move(aOther.mLastRefPoint)),
522 mFocusSequenceNumber(aOther.mFocusSequenceNumber),
523 mFlags(std::move(aOther.mFlags)),
524 mSpecifiedEventType(std::move(aOther.mSpecifiedEventType)),
525 mSpecifiedEventTypeString(std::move(aOther.mSpecifiedEventTypeString)),
526 mTarget(std::move(aOther.mTarget)),
527 mCurrentTarget(std::move(aOther.mCurrentTarget)),
528 mOriginalTarget(std::move(aOther.mOriginalTarget)),
529 mRelatedTarget(std::move(aOther.mRelatedTarget)),
530 mOriginalRelatedTarget(std::move(aOther.mOriginalRelatedTarget)),
531 mPath(std::move(aOther.mPath)) {
532 MOZ_COUNT_CTOR(WidgetEvent);
534 WidgetEvent& operator=(WidgetEvent&& aOther) = default;
536 virtual WidgetEvent* Duplicate() const {
537 MOZ_ASSERT(mClass == eBasicEventClass,
538 "Duplicate() must be overridden by sub class");
539 WidgetEvent* result = new WidgetEvent(false, mMessage);
540 result->AssignEventData(*this, true);
541 result->mFlags = mFlags;
542 return result;
545 EventClassID mClass;
546 EventMessage mMessage;
547 // Relative to the widget of the event, or if there is no widget then it is
548 // in screen coordinates. Not modified by layout code.
549 LayoutDeviceIntPoint mRefPoint;
550 // The previous mRefPoint, if known, used to calculate mouse movement deltas.
551 LayoutDeviceIntPoint mLastRefPoint;
552 // The sequence number of the last potentially focus changing event handled
553 // by APZ. This is used to track when that event has been processed by
554 // content, and focus can be reconfirmed for async keyboard scrolling.
555 uint64_t mFocusSequenceNumber;
556 // See BaseEventFlags definition for the detail.
557 BaseEventFlags mFlags;
559 // If JS creates an event with unknown event type or known event type but
560 // for different event interface, the event type is stored to this.
561 // NOTE: This is always used if the instance is a WidgetCommandEvent instance
562 // or "input" event is dispatched with dom::Event class.
563 RefPtr<nsAtom> mSpecifiedEventType;
565 // nsAtom isn't available on non-main thread due to unsafe. Therefore,
566 // mSpecifiedEventTypeString is used instead of mSpecifiedEventType if
567 // the event is created in non-main thread.
568 nsString mSpecifiedEventTypeString;
570 // Event targets, needed by DOM Events
571 // Note that when you need event target for DOM event, you should use
572 // Get*DOMEventTarget() instead of accessing these members directly.
573 nsCOMPtr<dom::EventTarget> mTarget;
574 nsCOMPtr<dom::EventTarget> mCurrentTarget;
575 nsCOMPtr<dom::EventTarget> mOriginalTarget;
577 /// The possible related target
578 nsCOMPtr<dom::EventTarget> mRelatedTarget;
579 nsCOMPtr<dom::EventTarget> mOriginalRelatedTarget;
581 nsTArray<EventTargetChainItem>* mPath;
583 // The LayersId of the content process that this event should be
584 // dispatched to. This field is only used in the chrome process
585 // and doesn't get remoted to child processes.
586 layers::LayersId mLayersId;
588 dom::EventTarget* GetDOMEventTarget() const;
589 dom::EventTarget* GetCurrentDOMEventTarget() const;
590 dom::EventTarget* GetOriginalDOMEventTarget() const;
592 void AssignEventData(const WidgetEvent& aEvent, bool aCopyTargets) {
593 // mClass should be initialized with the constructor.
594 // mMessage should be initialized with the constructor.
595 mRefPoint = aEvent.mRefPoint;
596 // mLastRefPoint doesn't need to be copied.
597 mFocusSequenceNumber = aEvent.mFocusSequenceNumber;
598 // mLayersId intentionally not copied, since it's not used within content
599 AssignEventTime(aEvent);
600 // mFlags should be copied manually if it's necessary.
601 mSpecifiedEventType = aEvent.mSpecifiedEventType;
602 // mSpecifiedEventTypeString should be copied manually if it's necessary.
603 mTarget = aCopyTargets ? aEvent.mTarget : nullptr;
604 mCurrentTarget = aCopyTargets ? aEvent.mCurrentTarget : nullptr;
605 mOriginalTarget = aCopyTargets ? aEvent.mOriginalTarget : nullptr;
606 mRelatedTarget = aCopyTargets ? aEvent.mRelatedTarget : nullptr;
607 mOriginalRelatedTarget =
608 aCopyTargets ? aEvent.mOriginalRelatedTarget : nullptr;
612 * Helper methods for methods of DOM Event.
614 void StopPropagation() { mFlags.StopPropagation(); }
615 void StopImmediatePropagation() { mFlags.StopImmediatePropagation(); }
616 void PreventDefault(bool aCalledByDefaultHandler = true,
617 nsIPrincipal* aPrincipal = nullptr);
619 void PreventDefaultBeforeDispatch(
620 CrossProcessForwarding aCrossProcessForwarding) {
621 mFlags.PreventDefaultBeforeDispatch(aCrossProcessForwarding);
623 bool DefaultPrevented() const { return mFlags.DefaultPrevented(); }
624 bool DefaultPreventedByContent() const {
625 return mFlags.DefaultPreventedByContent();
627 bool IsTrusted() const { return mFlags.IsTrusted(); }
628 bool PropagationStopped() const { return mFlags.PropagationStopped(); }
631 * Prevent to be dispatched to remote process.
633 inline void StopCrossProcessForwarding() {
634 mFlags.StopCrossProcessForwarding();
637 * Return true if the event shouldn't be dispatched to remote process.
639 inline bool IsCrossProcessForwardingStopped() const {
640 return mFlags.IsCrossProcessForwardingStopped();
643 * Mark the event as waiting reply from remote process.
644 * Note that this also stops immediate propagation in current process.
646 inline void MarkAsWaitingReplyFromRemoteProcess() {
647 mFlags.MarkAsWaitingReplyFromRemoteProcess();
650 * Reset "waiting reply from remote process" state. This is useful when
651 * you dispatch a copy of an event coming from different process.
653 inline void ResetWaitingReplyFromRemoteProcessState() {
654 mFlags.ResetWaitingReplyFromRemoteProcessState();
657 * Return true if the event handler should wait reply event. I.e., if this
658 * returns true, any event handler should do nothing with the event.
660 inline bool IsWaitingReplyFromRemoteProcess() const {
661 return mFlags.IsWaitingReplyFromRemoteProcess();
664 * Mark the event as already handled in the remote process. This should be
665 * called when initializing reply events.
667 inline void MarkAsHandledInRemoteProcess() {
668 mFlags.MarkAsHandledInRemoteProcess();
671 * Return true if the event has already been handled in the remote process.
672 * I.e., if this returns true, the event is a reply event.
674 inline bool IsHandledInRemoteProcess() const {
675 return mFlags.IsHandledInRemoteProcess();
678 * Return true if the event should be sent back to its parent process.
679 * So, usual event handlers shouldn't call this.
681 inline bool WantReplyFromContentProcess() const {
682 return mFlags.WantReplyFromContentProcess();
685 * Mark the event has already posted to a remote process.
687 inline void MarkAsPostedToRemoteProcess() {
688 mFlags.MarkAsPostedToRemoteProcess();
691 * Reset the cross process dispatching state. This should be used when a
692 * process receives the event because the state is in the sender.
694 inline void ResetCrossProcessDispatchingState() {
695 mFlags.ResetCrossProcessDispatchingState();
698 * Return true if the event has been posted to a remote process.
700 inline bool HasBeenPostedToRemoteProcess() const {
701 return mFlags.HasBeenPostedToRemoteProcess();
704 * Mark the event is reserved by chrome. I.e., shouldn't be dispatched to
705 * content because it shouldn't be cancelable.
707 inline void MarkAsReservedByChrome() { mFlags.MarkAsReservedByChrome(); }
709 * Return true if the event is reserved by chrome.
711 inline bool IsReservedByChrome() const { return mFlags.IsReservedByChrome(); }
714 * Utils for checking event types
718 * As*Event() returns the pointer of the instance only when the instance is
719 * the class or one of its derived class.
721 #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
722 #define NS_EVENT_CLASS(aPrefix, aName) \
723 virtual aPrefix##aName* As##aName(); \
724 const aPrefix##aName* As##aName() const;
726 #include "mozilla/EventClassList.h"
728 #undef NS_EVENT_CLASS
729 #undef NS_ROOT_EVENT_CLASS
732 * Returns true if the event is a query content event.
734 bool IsQueryContentEvent() const;
736 * Returns true if the event is a selection event.
738 bool IsSelectionEvent() const;
740 * Returns true if the event is a content command event.
742 bool IsContentCommandEvent() const;
744 * Returns true if the event is a native event deliverer event for plugin.
746 bool IsNativeEventDelivererForPlugin() const;
749 * Returns true if the event mMessage is one of mouse events.
751 bool HasMouseEventMessage() const;
753 * Returns true if the event mMessage is one of drag events.
755 bool HasDragEventMessage() const;
757 * Returns true if aMessage or mMessage is one of key events.
759 static bool IsKeyEventMessage(EventMessage aMessage);
760 bool HasKeyEventMessage() const { return IsKeyEventMessage(mMessage); }
762 * Returns true if the event mMessage is one of composition events or text
763 * event.
765 bool HasIMEEventMessage() const;
767 * Returns true if the event mMessage is one of plugin activation events.
769 bool HasPluginActivationEventMessage() const;
772 * Returns true if the event can be sent to remote process.
774 bool CanBeSentToRemoteProcess() const;
776 * Returns true if the original target is a remote process and the event
777 * will be posted to the remote process later.
779 bool WillBeSentToRemoteProcess() const;
781 * Returns true if the event is native event deliverer event for plugin and
782 * it should be retarted to focused document.
784 bool IsRetargetedNativeEventDelivererForPlugin() const;
786 * Returns true if the event is native event deliverer event for plugin and
787 * it should NOT be retarted to focused document.
789 bool IsNonRetargetedNativeEventDelivererForPlugin() const;
791 * Returns true if the event is related to IME handling. It includes
792 * IME events, query content events and selection events.
793 * Be careful when you use this.
795 bool IsIMERelatedEvent() const;
798 * Whether the event should be handled by the frame of the mouse cursor
799 * position or not. When it should be handled there (e.g., the mouse events),
800 * this returns true.
802 bool IsUsingCoordinates() const;
804 * Whether the event should be handled by the focused DOM window in the
805 * same top level window's or not. E.g., key events, IME related events
806 * (including the query content events, they are used in IME transaction)
807 * should be handled by the (last) focused window rather than the dispatched
808 * window.
810 * NOTE: Even if this returns true, the event isn't going to be handled by the
811 * application level active DOM window which is on another top level window.
812 * So, when the event is fired on a deactive window, the event is going to be
813 * handled by the last focused DOM window in the last focused window.
815 bool IsTargetedAtFocusedWindow() const;
817 * Whether the event should be handled by the focused content or not. E.g.,
818 * key events, IME related events and other input events which are not handled
819 * by the frame of the mouse cursor position.
821 * NOTE: Even if this returns true, the event isn't going to be handled by the
822 * application level active DOM window which is on another top level window.
823 * So, when the event is fired on a deactive window, the event is going to be
824 * handled by the last focused DOM element of the last focused DOM window in
825 * the last focused window.
827 bool IsTargetedAtFocusedContent() const;
829 * Whether the event should cause a DOM event.
831 bool IsAllowedToDispatchDOMEvent() const;
833 * Whether the event should be dispatched in system group.
835 bool IsAllowedToDispatchInSystemGroup() const;
837 * Whether the event should be blocked for fingerprinting resistance.
839 bool IsBlockedForFingerprintingResistance() const;
841 * Initialize mComposed
843 void SetDefaultComposed() {
844 switch (mClass) {
845 case eCompositionEventClass:
846 mFlags.mComposed =
847 mMessage == eCompositionStart || mMessage == eCompositionUpdate ||
848 mMessage == eCompositionChange || mMessage == eCompositionEnd;
849 break;
850 case eDragEventClass:
851 // All drag & drop events are composed
852 mFlags.mComposed = mMessage == eDrag || mMessage == eDragEnd ||
853 mMessage == eDragEnter || mMessage == eDragExit ||
854 mMessage == eDragLeave || mMessage == eDragOver ||
855 mMessage == eDragStart || mMessage == eDrop;
856 break;
857 case eEditorInputEventClass:
858 mFlags.mComposed =
859 mMessage == eEditorInput || mMessage == eEditorBeforeInput;
860 break;
861 case eFocusEventClass:
862 mFlags.mComposed = mMessage == eBlur || mMessage == eFocus ||
863 mMessage == eFocusOut || mMessage == eFocusIn;
864 break;
865 case eKeyboardEventClass:
866 mFlags.mComposed =
867 mMessage == eKeyDown || mMessage == eKeyUp || mMessage == eKeyPress;
868 break;
869 case eMouseEventClass:
870 mFlags.mComposed =
871 mMessage == eMouseClick || mMessage == eMouseDoubleClick ||
872 mMessage == eMouseAuxClick || mMessage == eMouseDown ||
873 mMessage == eMouseUp || mMessage == eMouseOver ||
874 mMessage == eMouseOut || mMessage == eMouseMove ||
875 mMessage == eContextMenu || mMessage == eXULPopupShowing ||
876 mMessage == eXULPopupHiding || mMessage == eXULPopupShown ||
877 mMessage == eXULPopupHidden || mMessage == eXULPopupPositioned;
878 break;
879 case ePointerEventClass:
880 // All pointer events are composed
881 mFlags.mComposed =
882 mMessage == ePointerDown || mMessage == ePointerMove ||
883 mMessage == ePointerUp || mMessage == ePointerCancel ||
884 mMessage == ePointerOver || mMessage == ePointerOut ||
885 mMessage == ePointerGotCapture || mMessage == ePointerLostCapture;
886 break;
887 case eTouchEventClass:
888 // All touch events are composed
889 mFlags.mComposed = mMessage == eTouchStart || mMessage == eTouchEnd ||
890 mMessage == eTouchMove || mMessage == eTouchCancel;
891 break;
892 case eUIEventClass:
893 mFlags.mComposed = mMessage == eLegacyDOMFocusIn ||
894 mMessage == eLegacyDOMFocusOut ||
895 mMessage == eLegacyDOMActivate;
896 break;
897 case eWheelEventClass:
898 // All wheel events are composed
899 mFlags.mComposed = mMessage == eWheel;
900 break;
901 case eMouseScrollEventClass:
902 // Legacy mouse scroll events are composed too, for consistency with
903 // wheel.
904 mFlags.mComposed = mMessage == eLegacyMouseLineOrPageScroll ||
905 mMessage == eLegacyMousePixelScroll;
906 break;
907 default:
908 mFlags.mComposed = false;
909 break;
913 void SetComposed(const nsAString& aEventTypeArg) {
914 mFlags.mComposed = // composition events
915 aEventTypeArg.EqualsLiteral("compositionstart") ||
916 aEventTypeArg.EqualsLiteral("compositionupdate") ||
917 aEventTypeArg.EqualsLiteral("compositionend") ||
918 aEventTypeArg.EqualsLiteral("text") ||
919 // drag and drop events
920 aEventTypeArg.EqualsLiteral("dragstart") ||
921 aEventTypeArg.EqualsLiteral("drag") ||
922 aEventTypeArg.EqualsLiteral("dragenter") ||
923 aEventTypeArg.EqualsLiteral("dragexit") ||
924 aEventTypeArg.EqualsLiteral("dragleave") ||
925 aEventTypeArg.EqualsLiteral("dragover") ||
926 aEventTypeArg.EqualsLiteral("drop") ||
927 aEventTypeArg.EqualsLiteral("dropend") ||
928 // editor input events
929 aEventTypeArg.EqualsLiteral("input") ||
930 aEventTypeArg.EqualsLiteral("beforeinput") ||
931 // focus events
932 aEventTypeArg.EqualsLiteral("blur") ||
933 aEventTypeArg.EqualsLiteral("focus") ||
934 aEventTypeArg.EqualsLiteral("focusin") ||
935 aEventTypeArg.EqualsLiteral("focusout") ||
936 // keyboard events
937 aEventTypeArg.EqualsLiteral("keydown") ||
938 aEventTypeArg.EqualsLiteral("keyup") ||
939 aEventTypeArg.EqualsLiteral("keypress") ||
940 // mouse events
941 aEventTypeArg.EqualsLiteral("click") ||
942 aEventTypeArg.EqualsLiteral("dblclick") ||
943 aEventTypeArg.EqualsLiteral("mousedown") ||
944 aEventTypeArg.EqualsLiteral("mouseup") ||
945 aEventTypeArg.EqualsLiteral("mouseenter") ||
946 aEventTypeArg.EqualsLiteral("mouseleave") ||
947 aEventTypeArg.EqualsLiteral("mouseover") ||
948 aEventTypeArg.EqualsLiteral("mouseout") ||
949 aEventTypeArg.EqualsLiteral("mousemove") ||
950 aEventTypeArg.EqualsLiteral("contextmenu") ||
951 // pointer events
952 aEventTypeArg.EqualsLiteral("pointerdown") ||
953 aEventTypeArg.EqualsLiteral("pointermove") ||
954 aEventTypeArg.EqualsLiteral("pointerup") ||
955 aEventTypeArg.EqualsLiteral("pointercancel") ||
956 aEventTypeArg.EqualsLiteral("pointerover") ||
957 aEventTypeArg.EqualsLiteral("pointerout") ||
958 aEventTypeArg.EqualsLiteral("pointerenter") ||
959 aEventTypeArg.EqualsLiteral("pointerleave") ||
960 aEventTypeArg.EqualsLiteral("gotpointercapture") ||
961 aEventTypeArg.EqualsLiteral("lostpointercapture") ||
962 // touch events
963 aEventTypeArg.EqualsLiteral("touchstart") ||
964 aEventTypeArg.EqualsLiteral("touchend") ||
965 aEventTypeArg.EqualsLiteral("touchmove") ||
966 aEventTypeArg.EqualsLiteral("touchcancel") ||
967 // UI legacy events
968 aEventTypeArg.EqualsLiteral("DOMFocusIn") ||
969 aEventTypeArg.EqualsLiteral("DOMFocusOut") ||
970 aEventTypeArg.EqualsLiteral("DOMActivate") ||
971 // wheel events
972 aEventTypeArg.EqualsLiteral("wheel");
975 void SetComposed(bool aComposed) { mFlags.mComposed = aComposed; }
977 void SetDefaultComposedInNativeAnonymousContent() {
978 // For compatibility concerns, we set mComposedInNativeAnonymousContent to
979 // false for those events we want to stop propagation.
981 // nsVideoFrame may create anonymous image element which fires eLoad,
982 // eLoadStart, eLoadEnd, eLoadError. We don't want these events cross
983 // the boundary of NAC
984 mFlags.mComposedInNativeAnonymousContent =
985 mMessage != eLoad && mMessage != eLoadStart && mMessage != eLoadEnd &&
986 mMessage != eLoadError;
989 bool IsUserAction() const;
992 /******************************************************************************
993 * mozilla::NativeEventData
995 * WidgetGUIEvent's mPluginEvent member used to be a void* pointer,
996 * used to reference external, OS-specific data structures.
998 * That void* pointer wasn't serializable by itself, causing
999 * certain plugin events not to function in e10s. See bug 586656.
1001 * To make this serializable, we changed this void* pointer into
1002 * a proper buffer, and copy these external data structures into this
1003 * buffer.
1005 * That buffer is NativeEventData::mBuffer below.
1007 * We wrap this in that NativeEventData class providing operators to
1008 * be compatible with existing code that was written around
1009 * the old void* field.
1010 ******************************************************************************/
1012 class NativeEventData final {
1013 nsTArray<uint8_t> mBuffer;
1015 friend struct IPC::ParamTraits<mozilla::NativeEventData>;
1017 public:
1018 explicit operator bool() const { return !mBuffer.IsEmpty(); }
1020 template <typename T>
1021 explicit operator const T*() const {
1022 return mBuffer.IsEmpty() ? nullptr
1023 : reinterpret_cast<const T*>(mBuffer.Elements());
1026 template <typename T>
1027 void Copy(const T& other) {
1028 static_assert(!mozilla::IsPointer<T>::value, "Don't want a pointer!");
1029 mBuffer.SetLength(sizeof(T));
1030 memcpy(mBuffer.Elements(), &other, mBuffer.Length());
1033 void Clear() { mBuffer.Clear(); }
1036 /******************************************************************************
1037 * mozilla::WidgetGUIEvent
1038 ******************************************************************************/
1040 class WidgetGUIEvent : public WidgetEvent {
1041 protected:
1042 WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1043 EventClassID aEventClassID)
1044 : WidgetEvent(aIsTrusted, aMessage, aEventClassID), mWidget(aWidget) {}
1046 WidgetGUIEvent() {}
1048 public:
1049 virtual WidgetGUIEvent* AsGUIEvent() override { return this; }
1051 WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
1052 : WidgetEvent(aIsTrusted, aMessage, eGUIEventClass), mWidget(aWidget) {}
1054 virtual WidgetEvent* Duplicate() const override {
1055 MOZ_ASSERT(mClass == eGUIEventClass,
1056 "Duplicate() must be overridden by sub class");
1057 // Not copying widget, it is a weak reference.
1058 WidgetGUIEvent* result = new WidgetGUIEvent(false, mMessage, nullptr);
1059 result->AssignGUIEventData(*this, true);
1060 result->mFlags = mFlags;
1061 return result;
1064 // Originator of the event
1065 nsCOMPtr<nsIWidget> mWidget;
1068 * Ideally though, we wouldn't allow arbitrary reinterpret_cast'ing here;
1069 * instead, we would at least store type information here so that
1070 * this class can't be used to reinterpret one structure type into another.
1071 * We can also wonder if it would be possible to properly extend
1072 * WidgetGUIEvent and other Event classes to remove the need for this
1073 * mPluginEvent field.
1075 typedef NativeEventData PluginEvent;
1077 // Event for NPAPI plugin
1078 PluginEvent mPluginEvent;
1080 void AssignGUIEventData(const WidgetGUIEvent& aEvent, bool aCopyTargets) {
1081 AssignEventData(aEvent, aCopyTargets);
1083 // widget should be initialized with the constructor.
1085 mPluginEvent = aEvent.mPluginEvent;
1089 /******************************************************************************
1090 * mozilla::Modifier
1092 * All modifier keys should be defined here. This is used for managing
1093 * modifier states for DOM Level 3 or later.
1094 ******************************************************************************/
1096 enum Modifier {
1097 MODIFIER_NONE = 0x0000,
1098 MODIFIER_ALT = 0x0001,
1099 MODIFIER_ALTGRAPH = 0x0002,
1100 MODIFIER_CAPSLOCK = 0x0004,
1101 MODIFIER_CONTROL = 0x0008,
1102 MODIFIER_FN = 0x0010,
1103 MODIFIER_FNLOCK = 0x0020,
1104 MODIFIER_META = 0x0040,
1105 MODIFIER_NUMLOCK = 0x0080,
1106 MODIFIER_SCROLLLOCK = 0x0100,
1107 MODIFIER_SHIFT = 0x0200,
1108 MODIFIER_SYMBOL = 0x0400,
1109 MODIFIER_SYMBOLLOCK = 0x0800,
1110 MODIFIER_OS = 0x1000
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 (aModifiers & MODIFIER_OS) {
1188 MaybeAppendSeparator();
1189 AppendLiteral(NS_DOM_KEYNAME_OS);
1191 if (IsEmpty()) {
1192 AssignLiteral("none");
1196 private:
1197 void MaybeAppendSeparator() {
1198 if (!IsEmpty()) {
1199 AppendLiteral(" | ");
1204 /******************************************************************************
1205 * mozilla::WidgetInputEvent
1206 ******************************************************************************/
1208 class WidgetInputEvent : public WidgetGUIEvent {
1209 protected:
1210 WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1211 EventClassID aEventClassID)
1212 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID),
1213 mModifiers(0) {}
1215 WidgetInputEvent() : mModifiers(0) {}
1217 public:
1218 virtual WidgetInputEvent* AsInputEvent() override { return this; }
1220 WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
1221 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eInputEventClass),
1222 mModifiers(0) {}
1224 virtual WidgetEvent* Duplicate() const override {
1225 MOZ_ASSERT(mClass == eInputEventClass,
1226 "Duplicate() must be overridden by sub class");
1227 // Not copying widget, it is a weak reference.
1228 WidgetInputEvent* result = new WidgetInputEvent(false, mMessage, nullptr);
1229 result->AssignInputEventData(*this, true);
1230 result->mFlags = mFlags;
1231 return result;
1235 * Returns a modifier of "Accel" virtual modifier which is used for shortcut
1236 * key.
1238 static Modifier AccelModifier();
1241 * GetModifier() returns a modifier flag which is activated by aDOMKeyName.
1243 static Modifier GetModifier(const nsAString& aDOMKeyName);
1245 // true indicates the accel key on the environment is down
1246 bool IsAccel() const { return ((mModifiers & AccelModifier()) != 0); }
1248 // true indicates the shift key is down
1249 bool IsShift() const { return ((mModifiers & MODIFIER_SHIFT) != 0); }
1250 // true indicates the control key is down
1251 bool IsControl() const { return ((mModifiers & MODIFIER_CONTROL) != 0); }
1252 // true indicates the alt key is down
1253 bool IsAlt() const { return ((mModifiers & MODIFIER_ALT) != 0); }
1254 // true indicates the meta key is down (or, on Mac, the Command key)
1255 bool IsMeta() const { return ((mModifiers & MODIFIER_META) != 0); }
1256 // true indicates the win key is down on Windows. Or the Super or Hyper key
1257 // is down on Linux.
1258 bool IsOS() const { return ((mModifiers & MODIFIER_OS) != 0); }
1259 // true indicates the alt graph key is down
1260 // NOTE: on Mac, the option key press causes both IsAlt() and IsAltGrpah()
1261 // return true.
1262 bool IsAltGraph() const { return ((mModifiers & MODIFIER_ALTGRAPH) != 0); }
1263 // true indicates the CapLock LED is turn on.
1264 bool IsCapsLocked() const { return ((mModifiers & MODIFIER_CAPSLOCK) != 0); }
1265 // true indicates the NumLock LED is turn on.
1266 bool IsNumLocked() const { return ((mModifiers & MODIFIER_NUMLOCK) != 0); }
1267 // true indicates the ScrollLock LED is turn on.
1268 bool IsScrollLocked() const {
1269 return ((mModifiers & MODIFIER_SCROLLLOCK) != 0);
1272 // true indicates the Fn key is down, but this is not supported by native
1273 // key event on any platform.
1274 bool IsFn() const { return ((mModifiers & MODIFIER_FN) != 0); }
1275 // true indicates the FnLock LED is turn on, but we don't know such
1276 // keyboards nor platforms.
1277 bool IsFnLocked() const { return ((mModifiers & MODIFIER_FNLOCK) != 0); }
1278 // true indicates the Symbol is down, but this is not supported by native
1279 // key event on any platforms.
1280 bool IsSymbol() const { return ((mModifiers & MODIFIER_SYMBOL) != 0); }
1281 // true indicates the SymbolLock LED is turn on, but we don't know such
1282 // keyboards nor platforms.
1283 bool IsSymbolLocked() const {
1284 return ((mModifiers & MODIFIER_SYMBOLLOCK) != 0);
1287 void InitBasicModifiers(bool aCtrlKey, bool aAltKey, bool aShiftKey,
1288 bool aMetaKey) {
1289 mModifiers = 0;
1290 if (aCtrlKey) {
1291 mModifiers |= MODIFIER_CONTROL;
1293 if (aAltKey) {
1294 mModifiers |= MODIFIER_ALT;
1296 if (aShiftKey) {
1297 mModifiers |= MODIFIER_SHIFT;
1299 if (aMetaKey) {
1300 mModifiers |= MODIFIER_META;
1304 Modifiers mModifiers;
1306 void AssignInputEventData(const WidgetInputEvent& aEvent, bool aCopyTargets) {
1307 AssignGUIEventData(aEvent, aCopyTargets);
1309 mModifiers = aEvent.mModifiers;
1313 /******************************************************************************
1314 * mozilla::InternalUIEvent
1316 * XXX Why this inherits WidgetGUIEvent rather than WidgetEvent?
1317 ******************************************************************************/
1319 class InternalUIEvent : public WidgetGUIEvent {
1320 protected:
1321 InternalUIEvent() : mDetail(0), mCausedByUntrustedEvent(false) {}
1323 InternalUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1324 EventClassID aEventClassID)
1325 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID),
1326 mDetail(0),
1327 mCausedByUntrustedEvent(false) {}
1329 InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1330 EventClassID aEventClassID)
1331 : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, aEventClassID),
1332 mDetail(0),
1333 mCausedByUntrustedEvent(false) {}
1335 public:
1336 virtual InternalUIEvent* AsUIEvent() override { return this; }
1339 * If the UIEvent is caused by another event (e.g., click event),
1340 * aEventCausesThisEvent should be the event. If there is no such event,
1341 * this should be nullptr.
1343 InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1344 const WidgetEvent* aEventCausesThisEvent)
1345 : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, eUIEventClass),
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 = new InternalUIEvent(false, mMessage, nullptr);
1354 result->AssignUIEventData(*this, true);
1355 result->mFlags = mFlags;
1356 return result;
1359 int32_t mDetail;
1360 // mCausedByUntrustedEvent is true if the event is caused by untrusted event.
1361 bool mCausedByUntrustedEvent;
1363 // If you check the event is a trusted event and NOT caused by an untrusted
1364 // event, IsTrustable() returns what you expected.
1365 bool IsTrustable() const { return IsTrusted() && !mCausedByUntrustedEvent; }
1367 void AssignUIEventData(const InternalUIEvent& aEvent, bool aCopyTargets) {
1368 AssignGUIEventData(aEvent, aCopyTargets);
1370 mDetail = aEvent.mDetail;
1371 mCausedByUntrustedEvent = aEvent.mCausedByUntrustedEvent;
1375 } // namespace mozilla
1377 #endif // mozilla_BasicEvents_h__