Bug 1523562 [wpt PR 14965] - Sync Mozilla CSS tests as of 2019-01-20, a=testonly
[gecko.git] / widget / BasicEvents.h
blobec1ff26bfd41439252bfaf18609ef5737ae7dcb6
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/dom/EventTarget.h"
12 #include "mozilla/EventForwards.h"
13 #include "mozilla/TimeStamp.h"
14 #include "nsCOMPtr.h"
15 #include "nsAtom.h"
16 #include "nsISupportsImpl.h"
17 #include "nsIWidget.h"
18 #include "nsString.h"
19 #include "Units.h"
21 #ifdef DEBUG
22 # include "nsXULAppAPI.h"
23 #endif // #ifdef DEBUG
25 namespace IPC {
26 template <typename T>
27 struct ParamTraits;
28 } // namespace IPC
30 namespace mozilla {
32 class EventTargetChainItem;
34 enum class CrossProcessForwarding {
35 // eStop prevents the event to be sent to remote process.
36 eStop,
37 // eAllow keeps current state of the event whether it's sent to remote
38 // process. In other words, eAllow does NOT mean that making the event
39 // sent to remote process when IsCrossProcessForwardingStopped() returns
40 // true.
41 eAllow,
44 /******************************************************************************
45 * mozilla::BaseEventFlags
47 * BaseEventFlags must be a POD struct for safe to use memcpy (including
48 * in ParamTraits<BaseEventFlags>). So don't make virtual methods, constructor,
49 * destructor and operators.
50 * This is necessary for VC which is NOT C++0x compiler.
51 ******************************************************************************/
53 struct BaseEventFlags {
54 public:
55 // If mIsTrusted is true, the event is a trusted event. Otherwise, it's
56 // an untrusted event.
57 bool mIsTrusted : 1;
58 // If mInBubblingPhase is true, the event is in bubbling phase or target
59 // phase.
60 bool mInBubblingPhase : 1;
61 // If mInCapturePhase is true, the event is in capture phase or target phase.
62 bool mInCapturePhase : 1;
63 // If mInSystemGroup is true, the event is being dispatched in system group.
64 bool mInSystemGroup : 1;
65 // If mCancelable is true, the event can be consumed. I.e., calling
66 // dom::Event::PreventDefault() can prevent the default action.
67 bool mCancelable : 1;
68 // If mBubbles is true, the event can bubble. Otherwise, cannot be handled
69 // in bubbling phase.
70 bool mBubbles : 1;
71 // If mPropagationStopped is true, dom::Event::StopPropagation() or
72 // dom::Event::StopImmediatePropagation() has been called.
73 bool mPropagationStopped : 1;
74 // If mImmediatePropagationStopped is true,
75 // dom::Event::StopImmediatePropagation() has been called.
76 // Note that mPropagationStopped must be true when this is true.
77 bool mImmediatePropagationStopped : 1;
78 // If mDefaultPrevented is true, the event has been consumed.
79 // E.g., dom::Event::PreventDefault() has been called or
80 // the default action has been performed.
81 bool mDefaultPrevented : 1;
82 // If mDefaultPreventedByContent is true, the event has been
83 // consumed by content.
84 // Note that mDefaultPrevented must be true when this is true.
85 bool mDefaultPreventedByContent : 1;
86 // If mDefaultPreventedByChrome is true, the event has been
87 // consumed by chrome.
88 // Note that mDefaultPrevented must be true when this is true.
89 bool mDefaultPreventedByChrome : 1;
90 // mMultipleActionsPrevented may be used when default handling don't want to
91 // be prevented, but only one of the event targets should handle the event.
92 // For example, when a <label> element is in another <label> element and
93 // the first <label> element is clicked, that one may set this true.
94 // Then, the second <label> element won't handle the event.
95 bool mMultipleActionsPrevented : 1;
96 // Similar to above but expected to be used during PreHandleEvent phase.
97 bool mMultiplePreActionsPrevented : 1;
98 // If mIsBeingDispatched is true, the DOM event created from the event is
99 // dispatching into the DOM tree and not completed.
100 bool mIsBeingDispatched : 1;
101 // If mDispatchedAtLeastOnce is true, the event has been dispatched
102 // as a DOM event and the dispatch has been completed.
103 bool mDispatchedAtLeastOnce : 1;
104 // If mIsSynthesizedForTests is true, the event has been synthesized for
105 // automated tests or something hacky approach of an add-on.
106 bool mIsSynthesizedForTests : 1;
107 // If mExceptionWasRaised is true, one of the event handlers has raised an
108 // exception.
109 bool mExceptionWasRaised : 1;
110 // If mRetargetToNonNativeAnonymous is true and the target is in a non-native
111 // native anonymous subtree, the event target is set to mOriginalTarget.
112 bool mRetargetToNonNativeAnonymous : 1;
113 // If mNoContentDispatch is true, the event is never dispatched to the
114 // event handlers which are added to the contents, onfoo attributes and
115 // properties. Note that this flag is ignored when
116 // EventChainPreVisitor::mForceContentDispatch is set true. For exapmle,
117 // window and document object sets it true. Therefore, web applications
118 // can handle the event if they add event listeners to the window or the
119 // document.
120 // XXX This is an ancient and broken feature, don't use this for new bug
121 // as far as possible.
122 bool mNoContentDispatch : 1;
123 // If mOnlyChromeDispatch is true, the event is dispatched to only chrome.
124 bool mOnlyChromeDispatch : 1;
125 // Indicates if the key combination is reserved by chrome. This is set by
126 // MarkAsReservedByChrome().
127 bool mIsReservedByChrome : 1;
128 // If mOnlySystemGroupDispatchInContent is true, event listeners added to
129 // the default group for non-chrome EventTarget won't be called.
130 // Be aware, if this is true, EventDispatcher needs to check if each event
131 // listener is added to chrome node, so, don't set this to true for the
132 // events which are fired a lot of times like eMouseMove.
133 bool mOnlySystemGroupDispatchInContent : 1;
134 // If mOnlySystemGroupDispatch is true, the event will be dispatched only to
135 // event listeners added in the system group.
136 bool mOnlySystemGroupDispatch : 1;
137 // The event's action will be handled by APZ. The main thread should not
138 // perform its associated action.
139 bool mHandledByAPZ : 1;
140 // True if the event is currently being handled by an event listener that
141 // was registered as a passive listener.
142 bool mInPassiveListener : 1;
143 // If mComposed is true, the event fired by nodes in shadow DOM can cross the
144 // boundary of shadow DOM and light DOM.
145 bool mComposed : 1;
146 // Similar to mComposed. Set it to true to allow events cross the boundary
147 // between native non-anonymous content and native anonymouse content
148 bool mComposedInNativeAnonymousContent : 1;
149 // Set to true for events which are suppressed or delayed so that later a
150 // DelayedEvent of it is dispatched. This is used when parent side process
151 // the key event after content side, and may drop the event if the event
152 // was suppressed or delayed in contents side.
153 // It is also set to true for the events (in a DelayedInputEvent), which will
154 // be dispatched afterwards.
155 bool mIsSuppressedOrDelayed : 1;
156 // Certain mouse events can be marked as positionless to return 0 from
157 // coordinate related getters.
158 bool mIsPositionless : 1;
160 // Flags managing state of propagation between processes.
161 // Note the the following flags shouldn't be referred directly. Use utility
162 // methods instead.
164 // If mNoRemoteProcessDispatch is true, the event is not allowed to be sent
165 // to remote process.
166 bool mNoRemoteProcessDispatch : 1;
167 // If mWantReplyFromContentProcess is true, the event will be redispatched
168 // in the parent process after the content process has handled it. Useful
169 // for when the parent process need the know first how the event was used
170 // by content before handling it itself.
171 bool mWantReplyFromContentProcess : 1;
172 // If mPostedToRemoteProcess is true, the event has been posted to the
173 // remote process (but it's not handled yet if it's not a duplicated event
174 // instance).
175 bool mPostedToRemoteProcess : 1;
177 // If the event is being handled in target phase, returns true.
178 inline bool InTargetPhase() const {
179 return (mInBubblingPhase && mInCapturePhase);
183 * Helper methods for methods of DOM Event.
185 inline void StopPropagation() { mPropagationStopped = true; }
186 inline void StopImmediatePropagation() {
187 StopPropagation();
188 mImmediatePropagationStopped = true;
190 inline void PreventDefault(bool aCalledByDefaultHandler = true) {
191 if (!mCancelable) {
192 return;
194 mDefaultPrevented = true;
195 // Note that even if preventDefault() has already been called by chrome,
196 // a call of preventDefault() by content needs to overwrite
197 // mDefaultPreventedByContent to true because in such case, defaultPrevented
198 // must be true when web apps check it after they call preventDefault().
199 if (aCalledByDefaultHandler) {
200 StopCrossProcessForwarding();
201 mDefaultPreventedByChrome = true;
202 } else {
203 mDefaultPreventedByContent = true;
206 // This should be used only before dispatching events into the DOM tree.
207 inline void PreventDefaultBeforeDispatch(
208 CrossProcessForwarding aCrossProcessForwarding) {
209 if (!mCancelable) {
210 return;
212 mDefaultPrevented = true;
213 if (aCrossProcessForwarding == CrossProcessForwarding::eStop) {
214 StopCrossProcessForwarding();
217 inline bool DefaultPrevented() const { return mDefaultPrevented; }
218 inline bool DefaultPreventedByContent() const {
219 MOZ_ASSERT(!mDefaultPreventedByContent || DefaultPrevented());
220 return mDefaultPreventedByContent;
222 inline bool IsTrusted() const { return mIsTrusted; }
223 inline bool PropagationStopped() const { return mPropagationStopped; }
225 // Helper methods to access flags managing state of propagation between
226 // processes.
229 * Prevent to be dispatched to remote process.
231 inline void StopCrossProcessForwarding() {
232 MOZ_ASSERT(!mPostedToRemoteProcess);
233 mNoRemoteProcessDispatch = true;
234 mWantReplyFromContentProcess = false;
237 * Return true if the event shouldn't be dispatched to remote process.
239 inline bool IsCrossProcessForwardingStopped() const {
240 return mNoRemoteProcessDispatch;
243 * Mark the event as waiting reply from remote process.
244 * If the caller needs to win other keyboard event handlers in chrome,
245 * the caller should call StopPropagation() too.
246 * Otherwise, if the caller just needs to know if the event is consumed by
247 * either content or chrome, it should just call this because the event
248 * may be reserved by chrome and it needs to be dispatched into the DOM
249 * tree in chrome for checking if it's reserved before being sent to any
250 * remote processes.
252 inline void MarkAsWaitingReplyFromRemoteProcess() {
253 MOZ_ASSERT(!mPostedToRemoteProcess);
254 mNoRemoteProcessDispatch = false;
255 mWantReplyFromContentProcess = true;
258 * Reset "waiting reply from remote process" state. This is useful when
259 * you dispatch a copy of an event coming from different process.
261 inline void ResetWaitingReplyFromRemoteProcessState() {
262 if (IsWaitingReplyFromRemoteProcess()) {
263 // FYI: mWantReplyFromContentProcess is also used for indicating
264 // "handled in remote process" state. Therefore, only when
265 // IsWaitingReplyFromRemoteProcess() returns true, this should
266 // reset the flag.
267 mWantReplyFromContentProcess = false;
271 * Return true if the event handler should wait reply event. I.e., if this
272 * returns true, any event handler should do nothing with the event.
274 inline bool IsWaitingReplyFromRemoteProcess() const {
275 return !mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
278 * Mark the event as already handled in the remote process. This should be
279 * called when initializing reply events.
281 inline void MarkAsHandledInRemoteProcess() {
282 mNoRemoteProcessDispatch = true;
283 mWantReplyFromContentProcess = true;
284 mPostedToRemoteProcess = false;
287 * Return true if the event has already been handled in the remote process.
289 inline bool IsHandledInRemoteProcess() const {
290 return mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
293 * Return true if the event should be sent back to its parent process.
295 inline bool WantReplyFromContentProcess() const {
296 MOZ_ASSERT(!XRE_IsParentProcess());
297 return IsWaitingReplyFromRemoteProcess();
300 * Mark the event has already posted to a remote process.
302 inline void MarkAsPostedToRemoteProcess() {
303 MOZ_ASSERT(!IsCrossProcessForwardingStopped());
304 mPostedToRemoteProcess = true;
307 * Reset the cross process dispatching state. This should be used when a
308 * process receives the event because the state is in the sender.
310 inline void ResetCrossProcessDispatchingState() {
311 MOZ_ASSERT(!IsCrossProcessForwardingStopped());
312 mPostedToRemoteProcess = false;
313 // Ignore propagation state in the different process if it's marked as
314 // "waiting reply from remote process" because the process needs to
315 // stop propagation in the process until receiving a reply event.
316 if (IsWaitingReplyFromRemoteProcess()) {
317 mPropagationStopped = mImmediatePropagationStopped = false;
321 * Return true if the event has been posted to a remote process.
322 * Note that MarkAsPostedToRemoteProcess() is called by
323 * ParamTraits<mozilla::WidgetEvent>. Therefore, it *might* be possible
324 * that posting the event failed even if this returns true. But that must
325 * really rare. If that'd be problem for you, you should unmark this in
326 * TabParent or somewhere.
328 inline bool HasBeenPostedToRemoteProcess() const {
329 return mPostedToRemoteProcess;
332 * Mark the event is reserved by chrome. I.e., shouldn't be dispatched to
333 * content because it shouldn't be cancelable.
335 inline void MarkAsReservedByChrome() {
336 MOZ_ASSERT(!mPostedToRemoteProcess);
337 mIsReservedByChrome = true;
338 // For reserved commands (such as Open New Tab), we don't need to wait for
339 // the content to answer, neither to give a chance for content to override
340 // its behavior.
341 StopCrossProcessForwarding();
342 // If the event is reserved by chrome, we shouldn't expose the event to
343 // web contents because such events shouldn't be cancelable. So, it's not
344 // good behavior to fire such events but to ignore the defaultPrevented
345 // attribute value in chrome.
346 mOnlySystemGroupDispatchInContent = true;
349 * Return true if the event is reserved by chrome.
351 inline bool IsReservedByChrome() const {
352 MOZ_ASSERT(!mIsReservedByChrome || (IsCrossProcessForwardingStopped() &&
353 mOnlySystemGroupDispatchInContent));
354 return mIsReservedByChrome;
357 inline void Clear() { SetRawFlags(0); }
358 // Get if either the instance's bit or the aOther's bit is true, the
359 // instance's bit becomes true. In other words, this works like:
360 // eventFlags |= aOther;
361 inline void Union(const BaseEventFlags& aOther) {
362 RawFlags rawFlags = GetRawFlags() | aOther.GetRawFlags();
363 SetRawFlags(rawFlags);
366 private:
367 typedef uint32_t RawFlags;
369 inline void SetRawFlags(RawFlags aRawFlags) {
370 static_assert(sizeof(BaseEventFlags) <= sizeof(RawFlags),
371 "mozilla::EventFlags must not be bigger than the RawFlags");
372 memcpy(this, &aRawFlags, sizeof(BaseEventFlags));
374 inline RawFlags GetRawFlags() const {
375 RawFlags result = 0;
376 memcpy(&result, this, sizeof(BaseEventFlags));
377 return result;
381 /******************************************************************************
382 * mozilla::EventFlags
383 ******************************************************************************/
385 struct EventFlags : public BaseEventFlags {
386 EventFlags() { Clear(); }
389 /******************************************************************************
390 * mozilla::WidgetEventTime
391 ******************************************************************************/
393 class WidgetEventTime {
394 public:
395 // Elapsed time, in milliseconds, from a platform-specific zero time
396 // to the time the message was created
397 uint64_t mTime;
398 // Timestamp when the message was created. Set in parallel to 'time' until we
399 // determine if it is safe to drop 'time' (see bug 77992).
400 TimeStamp mTimeStamp;
402 WidgetEventTime() : mTime(0), mTimeStamp(TimeStamp::Now()) {}
404 WidgetEventTime(uint64_t aTime, TimeStamp aTimeStamp)
405 : mTime(aTime), mTimeStamp(aTimeStamp) {}
407 void AssignEventTime(const WidgetEventTime& aOther) {
408 mTime = aOther.mTime;
409 mTimeStamp = aOther.mTimeStamp;
413 /******************************************************************************
414 * mozilla::WidgetEvent
415 ******************************************************************************/
417 class WidgetEvent : public WidgetEventTime {
418 private:
419 void SetDefaultCancelableAndBubbles() {
420 switch (mClass) {
421 case eEditorInputEventClass:
422 mFlags.mCancelable = false;
423 mFlags.mBubbles = mFlags.mIsTrusted;
424 break;
425 case eMouseEventClass:
426 mFlags.mCancelable =
427 (mMessage != eMouseEnter && mMessage != eMouseLeave);
428 mFlags.mBubbles = (mMessage != eMouseEnter && mMessage != eMouseLeave);
429 break;
430 case ePointerEventClass:
431 mFlags.mCancelable =
432 (mMessage != ePointerEnter && mMessage != ePointerLeave &&
433 mMessage != ePointerCancel && mMessage != ePointerGotCapture &&
434 mMessage != ePointerLostCapture);
435 mFlags.mBubbles =
436 (mMessage != ePointerEnter && mMessage != ePointerLeave);
437 break;
438 case eDragEventClass:
439 mFlags.mCancelable = (mMessage != eDragExit && mMessage != eDragLeave &&
440 mMessage != eDragEnd);
441 mFlags.mBubbles = true;
442 break;
443 case eSMILTimeEventClass:
444 mFlags.mCancelable = false;
445 mFlags.mBubbles = false;
446 break;
447 case eTransitionEventClass:
448 case eAnimationEventClass:
449 mFlags.mCancelable = false;
450 mFlags.mBubbles = true;
451 break;
452 case eCompositionEventClass:
453 // XXX compositionstart is cancelable in draft of DOM3 Events.
454 // However, it doesn't make sense for us, we cannot cancel
455 // composition when we send compositionstart event.
456 mFlags.mCancelable = false;
457 mFlags.mBubbles = true;
458 break;
459 default:
460 if (mMessage == eResize || mMessage == eMozVisualResize ||
461 mMessage == eMozVisualScroll || mMessage == eEditorInput) {
462 mFlags.mCancelable = false;
463 } else {
464 mFlags.mCancelable = true;
466 mFlags.mBubbles = true;
467 break;
471 protected:
472 WidgetEvent(bool aIsTrusted, EventMessage aMessage,
473 EventClassID aEventClassID)
474 : WidgetEventTime(),
475 mClass(aEventClassID),
476 mMessage(aMessage),
477 mRefPoint(0, 0),
478 mLastRefPoint(0, 0),
479 mFocusSequenceNumber(0),
480 mSpecifiedEventType(nullptr),
481 mPath(nullptr) {
482 MOZ_COUNT_CTOR(WidgetEvent);
483 mFlags.Clear();
484 mFlags.mIsTrusted = aIsTrusted;
485 SetDefaultCancelableAndBubbles();
486 SetDefaultComposed();
487 SetDefaultComposedInNativeAnonymousContent();
490 WidgetEvent() : WidgetEventTime(), mPath(nullptr) {
491 MOZ_COUNT_CTOR(WidgetEvent);
494 public:
495 WidgetEvent(bool aIsTrusted, EventMessage aMessage)
496 : WidgetEvent(aIsTrusted, aMessage, eBasicEventClass) {}
498 virtual ~WidgetEvent() { MOZ_COUNT_DTOR(WidgetEvent); }
500 WidgetEvent(const WidgetEvent& aOther) : WidgetEventTime() {
501 MOZ_COUNT_CTOR(WidgetEvent);
502 *this = aOther;
504 WidgetEvent& operator=(const WidgetEvent& aOther) = default;
506 WidgetEvent(WidgetEvent&& aOther)
507 : WidgetEventTime(std::move(aOther)),
508 mClass(aOther.mClass),
509 mMessage(aOther.mMessage),
510 mRefPoint(std::move(aOther.mRefPoint)),
511 mLastRefPoint(std::move(aOther.mLastRefPoint)),
512 mFocusSequenceNumber(aOther.mFocusSequenceNumber),
513 mFlags(std::move(aOther.mFlags)),
514 mSpecifiedEventType(std::move(aOther.mSpecifiedEventType)),
515 mSpecifiedEventTypeString(std::move(aOther.mSpecifiedEventTypeString)),
516 mTarget(std::move(aOther.mTarget)),
517 mCurrentTarget(std::move(aOther.mCurrentTarget)),
518 mOriginalTarget(std::move(aOther.mOriginalTarget)),
519 mRelatedTarget(std::move(aOther.mRelatedTarget)),
520 mOriginalRelatedTarget(std::move(aOther.mOriginalRelatedTarget)),
521 mPath(std::move(aOther.mPath)) {
522 MOZ_COUNT_CTOR(WidgetEvent);
524 WidgetEvent& operator=(WidgetEvent&& aOther) = default;
526 virtual WidgetEvent* Duplicate() const {
527 MOZ_ASSERT(mClass == eBasicEventClass,
528 "Duplicate() must be overridden by sub class");
529 WidgetEvent* result = new WidgetEvent(false, mMessage);
530 result->AssignEventData(*this, true);
531 result->mFlags = mFlags;
532 return result;
535 EventClassID mClass;
536 EventMessage mMessage;
537 // Relative to the widget of the event, or if there is no widget then it is
538 // in screen coordinates. Not modified by layout code.
539 LayoutDeviceIntPoint mRefPoint;
540 // The previous mRefPoint, if known, used to calculate mouse movement deltas.
541 LayoutDeviceIntPoint mLastRefPoint;
542 // The sequence number of the last potentially focus changing event handled
543 // by APZ. This is used to track when that event has been processed by
544 // content, and focus can be reconfirmed for async keyboard scrolling.
545 uint64_t mFocusSequenceNumber;
546 // See BaseEventFlags definition for the detail.
547 BaseEventFlags mFlags;
549 // If JS creates an event with unknown event type or known event type but
550 // for different event interface, the event type is stored to this.
551 // NOTE: This is always used if the instance is a WidgetCommandEvent instance
552 // or "input" event is dispatched with dom::Event class.
553 RefPtr<nsAtom> mSpecifiedEventType;
555 // nsAtom isn't available on non-main thread due to unsafe. Therefore,
556 // mSpecifiedEventTypeString is used instead of mSpecifiedEventType if
557 // the event is created in non-main thread.
558 nsString mSpecifiedEventTypeString;
560 // Event targets, needed by DOM Events
561 // Note that when you need event target for DOM event, you should use
562 // Get*DOMEventTarget() instead of accessing these members directly.
563 nsCOMPtr<dom::EventTarget> mTarget;
564 nsCOMPtr<dom::EventTarget> mCurrentTarget;
565 nsCOMPtr<dom::EventTarget> mOriginalTarget;
567 /// The possible related target
568 nsCOMPtr<dom::EventTarget> mRelatedTarget;
569 nsCOMPtr<dom::EventTarget> mOriginalRelatedTarget;
571 nsTArray<EventTargetChainItem>* mPath;
573 dom::EventTarget* GetDOMEventTarget() const;
574 dom::EventTarget* GetCurrentDOMEventTarget() const;
575 dom::EventTarget* GetOriginalDOMEventTarget() const;
577 void AssignEventData(const WidgetEvent& aEvent, bool aCopyTargets) {
578 // mClass should be initialized with the constructor.
579 // mMessage should be initialized with the constructor.
580 mRefPoint = aEvent.mRefPoint;
581 // mLastRefPoint doesn't need to be copied.
582 mFocusSequenceNumber = aEvent.mFocusSequenceNumber;
583 AssignEventTime(aEvent);
584 // mFlags should be copied manually if it's necessary.
585 mSpecifiedEventType = aEvent.mSpecifiedEventType;
586 // mSpecifiedEventTypeString should be copied manually if it's necessary.
587 mTarget = aCopyTargets ? aEvent.mTarget : nullptr;
588 mCurrentTarget = aCopyTargets ? aEvent.mCurrentTarget : nullptr;
589 mOriginalTarget = aCopyTargets ? aEvent.mOriginalTarget : nullptr;
590 mRelatedTarget = aCopyTargets ? aEvent.mRelatedTarget : nullptr;
591 mOriginalRelatedTarget =
592 aCopyTargets ? aEvent.mOriginalRelatedTarget : nullptr;
596 * Helper methods for methods of DOM Event.
598 void StopPropagation() { mFlags.StopPropagation(); }
599 void StopImmediatePropagation() { mFlags.StopImmediatePropagation(); }
600 void PreventDefault(bool aCalledByDefaultHandler = true,
601 nsIPrincipal* aPrincipal = nullptr);
603 void PreventDefaultBeforeDispatch(
604 CrossProcessForwarding aCrossProcessForwarding) {
605 mFlags.PreventDefaultBeforeDispatch(aCrossProcessForwarding);
607 bool DefaultPrevented() const { return mFlags.DefaultPrevented(); }
608 bool DefaultPreventedByContent() const {
609 return mFlags.DefaultPreventedByContent();
611 bool IsTrusted() const { return mFlags.IsTrusted(); }
612 bool PropagationStopped() const { return mFlags.PropagationStopped(); }
615 * Prevent to be dispatched to remote process.
617 inline void StopCrossProcessForwarding() {
618 mFlags.StopCrossProcessForwarding();
621 * Return true if the event shouldn't be dispatched to remote process.
623 inline bool IsCrossProcessForwardingStopped() const {
624 return mFlags.IsCrossProcessForwardingStopped();
627 * Mark the event as waiting reply from remote process.
628 * Note that this also stops immediate propagation in current process.
630 inline void MarkAsWaitingReplyFromRemoteProcess() {
631 mFlags.MarkAsWaitingReplyFromRemoteProcess();
634 * Reset "waiting reply from remote process" state. This is useful when
635 * you dispatch a copy of an event coming from different process.
637 inline void ResetWaitingReplyFromRemoteProcessState() {
638 mFlags.ResetWaitingReplyFromRemoteProcessState();
641 * Return true if the event handler should wait reply event. I.e., if this
642 * returns true, any event handler should do nothing with the event.
644 inline bool IsWaitingReplyFromRemoteProcess() const {
645 return mFlags.IsWaitingReplyFromRemoteProcess();
648 * Mark the event as already handled in the remote process. This should be
649 * called when initializing reply events.
651 inline void MarkAsHandledInRemoteProcess() {
652 mFlags.MarkAsHandledInRemoteProcess();
655 * Return true if the event has already been handled in the remote process.
656 * I.e., if this returns true, the event is a reply event.
658 inline bool IsHandledInRemoteProcess() const {
659 return mFlags.IsHandledInRemoteProcess();
662 * Return true if the event should be sent back to its parent process.
663 * So, usual event handlers shouldn't call this.
665 inline bool WantReplyFromContentProcess() const {
666 return mFlags.WantReplyFromContentProcess();
669 * Mark the event has already posted to a remote process.
671 inline void MarkAsPostedToRemoteProcess() {
672 mFlags.MarkAsPostedToRemoteProcess();
675 * Reset the cross process dispatching state. This should be used when a
676 * process receives the event because the state is in the sender.
678 inline void ResetCrossProcessDispatchingState() {
679 mFlags.ResetCrossProcessDispatchingState();
682 * Return true if the event has been posted to a remote process.
684 inline bool HasBeenPostedToRemoteProcess() const {
685 return mFlags.HasBeenPostedToRemoteProcess();
688 * Mark the event is reserved by chrome. I.e., shouldn't be dispatched to
689 * content because it shouldn't be cancelable.
691 inline void MarkAsReservedByChrome() { mFlags.MarkAsReservedByChrome(); }
693 * Return true if the event is reserved by chrome.
695 inline bool IsReservedByChrome() const { return mFlags.IsReservedByChrome(); }
698 * Utils for checking event types
702 * As*Event() returns the pointer of the instance only when the instance is
703 * the class or one of its derived class.
705 #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
706 #define NS_EVENT_CLASS(aPrefix, aName) \
707 virtual aPrefix##aName* As##aName(); \
708 const aPrefix##aName* As##aName() const;
710 #include "mozilla/EventClassList.h"
712 #undef NS_EVENT_CLASS
713 #undef NS_ROOT_EVENT_CLASS
716 * Returns true if the event is a query content event.
718 bool IsQueryContentEvent() const;
720 * Returns true if the event is a selection event.
722 bool IsSelectionEvent() const;
724 * Returns true if the event is a content command event.
726 bool IsContentCommandEvent() const;
728 * Returns true if the event is a native event deliverer event for plugin.
730 bool IsNativeEventDelivererForPlugin() const;
733 * Returns true if the event mMessage is one of mouse events.
735 bool HasMouseEventMessage() const;
737 * Returns true if the event mMessage is one of drag events.
739 bool HasDragEventMessage() const;
741 * Returns true if aMessage or mMessage is one of key events.
743 static bool IsKeyEventMessage(EventMessage aMessage);
744 bool HasKeyEventMessage() const { return IsKeyEventMessage(mMessage); }
746 * Returns true if the event mMessage is one of composition events or text
747 * event.
749 bool HasIMEEventMessage() const;
751 * Returns true if the event mMessage is one of plugin activation events.
753 bool HasPluginActivationEventMessage() const;
756 * Returns true if the event can be sent to remote process.
758 bool CanBeSentToRemoteProcess() const;
760 * Returns true if the original target is a remote process and the event
761 * will be posted to the remote process later.
763 bool WillBeSentToRemoteProcess() const;
765 * Returns true if the event is native event deliverer event for plugin and
766 * it should be retarted to focused document.
768 bool IsRetargetedNativeEventDelivererForPlugin() const;
770 * Returns true if the event is native event deliverer event for plugin and
771 * it should NOT be retarted to focused document.
773 bool IsNonRetargetedNativeEventDelivererForPlugin() const;
775 * Returns true if the event is related to IME handling. It includes
776 * IME events, query content events and selection events.
777 * Be careful when you use this.
779 bool IsIMERelatedEvent() const;
782 * Whether the event should be handled by the frame of the mouse cursor
783 * position or not. When it should be handled there (e.g., the mouse events),
784 * this returns true.
786 bool IsUsingCoordinates() const;
788 * Whether the event should be handled by the focused DOM window in the
789 * same top level window's or not. E.g., key events, IME related events
790 * (including the query content events, they are used in IME transaction)
791 * should be handled by the (last) focused window rather than the dispatched
792 * window.
794 * NOTE: Even if this returns true, the event isn't going to be handled by the
795 * application level active DOM window which is on another top level window.
796 * So, when the event is fired on a deactive window, the event is going to be
797 * handled by the last focused DOM window in the last focused window.
799 bool IsTargetedAtFocusedWindow() const;
801 * Whether the event should be handled by the focused content or not. E.g.,
802 * key events, IME related events and other input events which are not handled
803 * by the frame of the mouse cursor position.
805 * NOTE: Even if this returns true, the event isn't going to be handled by the
806 * application level active DOM window which is on another top level window.
807 * So, when the event is fired on a deactive window, the event is going to be
808 * handled by the last focused DOM element of the last focused DOM window in
809 * the last focused window.
811 bool IsTargetedAtFocusedContent() const;
813 * Whether the event should cause a DOM event.
815 bool IsAllowedToDispatchDOMEvent() const;
817 * Whether the event should be dispatched in system group.
819 bool IsAllowedToDispatchInSystemGroup() const;
821 * Whether the event should be blocked for fingerprinting resistance.
823 bool IsBlockedForFingerprintingResistance() const;
825 * Initialize mComposed
827 void SetDefaultComposed() {
828 switch (mClass) {
829 case eCompositionEventClass:
830 mFlags.mComposed = mMessage == eCompositionStart ||
831 mMessage == eCompositionUpdate ||
832 mMessage == eCompositionEnd;
833 break;
834 case eDragEventClass:
835 // All drag & drop events are composed
836 mFlags.mComposed = mMessage == eDrag || mMessage == eDragEnd ||
837 mMessage == eDragEnter || mMessage == eDragExit ||
838 mMessage == eDragLeave || mMessage == eDragOver ||
839 mMessage == eDragStart || mMessage == eDrop;
840 break;
841 case eEditorInputEventClass:
842 mFlags.mComposed = mMessage == eEditorInput;
843 break;
844 case eFocusEventClass:
845 mFlags.mComposed = mMessage == eBlur || mMessage == eFocus ||
846 mMessage == eFocusOut || mMessage == eFocusIn;
847 break;
848 case eKeyboardEventClass:
849 mFlags.mComposed =
850 mMessage == eKeyDown || mMessage == eKeyUp || mMessage == eKeyPress;
851 break;
852 case eMouseEventClass:
853 mFlags.mComposed = mMessage == eMouseClick ||
854 mMessage == eMouseDoubleClick ||
855 mMessage == eMouseAuxClick ||
856 mMessage == eMouseDown || mMessage == eMouseUp ||
857 mMessage == eMouseOver || mMessage == eMouseOut ||
858 mMessage == eMouseMove || mMessage == eContextMenu;
859 break;
860 case ePointerEventClass:
861 // All pointer events are composed
862 mFlags.mComposed =
863 mMessage == ePointerDown || mMessage == ePointerMove ||
864 mMessage == ePointerUp || mMessage == ePointerCancel ||
865 mMessage == ePointerOver || mMessage == ePointerOut ||
866 mMessage == ePointerGotCapture || mMessage == ePointerLostCapture;
867 break;
868 case eTouchEventClass:
869 // All touch events are composed
870 mFlags.mComposed = mMessage == eTouchStart || mMessage == eTouchEnd ||
871 mMessage == eTouchMove || mMessage == eTouchCancel;
872 break;
873 case eUIEventClass:
874 mFlags.mComposed = mMessage == eLegacyDOMFocusIn ||
875 mMessage == eLegacyDOMFocusOut ||
876 mMessage == eLegacyDOMActivate;
877 break;
878 case eWheelEventClass:
879 // All wheel events are composed
880 mFlags.mComposed = mMessage == eWheel;
881 break;
882 default:
883 mFlags.mComposed = false;
884 break;
888 void SetComposed(const nsAString& aEventTypeArg) {
889 mFlags.mComposed = // composition events
890 aEventTypeArg.EqualsLiteral("compositionstart") ||
891 aEventTypeArg.EqualsLiteral("compositionupdate") ||
892 aEventTypeArg.EqualsLiteral("compositionend") ||
893 // drag and drop events
894 aEventTypeArg.EqualsLiteral("dragstart") ||
895 aEventTypeArg.EqualsLiteral("drag") ||
896 aEventTypeArg.EqualsLiteral("dragenter") ||
897 aEventTypeArg.EqualsLiteral("dragexit") ||
898 aEventTypeArg.EqualsLiteral("dragleave") ||
899 aEventTypeArg.EqualsLiteral("dragover") ||
900 aEventTypeArg.EqualsLiteral("drop") ||
901 aEventTypeArg.EqualsLiteral("dropend") ||
902 // editor input events
903 aEventTypeArg.EqualsLiteral("input") ||
904 aEventTypeArg.EqualsLiteral("beforeinput") ||
905 // focus events
906 aEventTypeArg.EqualsLiteral("blur") ||
907 aEventTypeArg.EqualsLiteral("focus") ||
908 aEventTypeArg.EqualsLiteral("focusin") ||
909 aEventTypeArg.EqualsLiteral("focusout") ||
910 // keyboard events
911 aEventTypeArg.EqualsLiteral("keydown") ||
912 aEventTypeArg.EqualsLiteral("keyup") ||
913 aEventTypeArg.EqualsLiteral("keypress") ||
914 // mouse events
915 aEventTypeArg.EqualsLiteral("click") ||
916 aEventTypeArg.EqualsLiteral("dblclick") ||
917 aEventTypeArg.EqualsLiteral("mousedown") ||
918 aEventTypeArg.EqualsLiteral("mouseup") ||
919 aEventTypeArg.EqualsLiteral("mouseenter") ||
920 aEventTypeArg.EqualsLiteral("mouseleave") ||
921 aEventTypeArg.EqualsLiteral("mouseover") ||
922 aEventTypeArg.EqualsLiteral("mouseout") ||
923 aEventTypeArg.EqualsLiteral("mousemove") ||
924 aEventTypeArg.EqualsLiteral("contextmenu") ||
925 // pointer events
926 aEventTypeArg.EqualsLiteral("pointerdown") ||
927 aEventTypeArg.EqualsLiteral("pointermove") ||
928 aEventTypeArg.EqualsLiteral("pointerup") ||
929 aEventTypeArg.EqualsLiteral("pointercancel") ||
930 aEventTypeArg.EqualsLiteral("pointerover") ||
931 aEventTypeArg.EqualsLiteral("pointerout") ||
932 aEventTypeArg.EqualsLiteral("pointerenter") ||
933 aEventTypeArg.EqualsLiteral("pointerleave") ||
934 aEventTypeArg.EqualsLiteral("gotpointercapture") ||
935 aEventTypeArg.EqualsLiteral("lostpointercapture") ||
936 // touch events
937 aEventTypeArg.EqualsLiteral("touchstart") ||
938 aEventTypeArg.EqualsLiteral("touchend") ||
939 aEventTypeArg.EqualsLiteral("touchmove") ||
940 aEventTypeArg.EqualsLiteral("touchcancel") ||
941 // UI legacy events
942 aEventTypeArg.EqualsLiteral("DOMFocusIn") ||
943 aEventTypeArg.EqualsLiteral("DOMFocusOut") ||
944 aEventTypeArg.EqualsLiteral("DOMActivate") ||
945 // wheel events
946 aEventTypeArg.EqualsLiteral("wheel");
949 void SetComposed(bool aComposed) { mFlags.mComposed = aComposed; }
951 void SetDefaultComposedInNativeAnonymousContent() {
952 // For compatibility concerns, we set mComposedInNativeAnonymousContent to
953 // false for those events we want to stop propagation.
955 // nsVideoFrame may create anonymous image element which fires eLoad,
956 // eLoadStart, eLoadEnd, eLoadError. We don't want these events cross
957 // the boundary of NAC
958 mFlags.mComposedInNativeAnonymousContent =
959 mMessage != eLoad && mMessage != eLoadStart && mMessage != eLoadEnd &&
960 mMessage != eLoadError;
963 bool IsUserAction() const;
966 /******************************************************************************
967 * mozilla::NativeEventData
969 * WidgetGUIEvent's mPluginEvent member used to be a void* pointer,
970 * used to reference external, OS-specific data structures.
972 * That void* pointer wasn't serializable by itself, causing
973 * certain plugin events not to function in e10s. See bug 586656.
975 * To make this serializable, we changed this void* pointer into
976 * a proper buffer, and copy these external data structures into this
977 * buffer.
979 * That buffer is NativeEventData::mBuffer below.
981 * We wrap this in that NativeEventData class providing operators to
982 * be compatible with existing code that was written around
983 * the old void* field.
984 ******************************************************************************/
986 class NativeEventData final {
987 nsTArray<uint8_t> mBuffer;
989 friend struct IPC::ParamTraits<mozilla::NativeEventData>;
991 public:
992 explicit operator bool() const { return !mBuffer.IsEmpty(); }
994 template <typename T>
995 explicit operator const T*() const {
996 return mBuffer.IsEmpty() ? nullptr
997 : reinterpret_cast<const T*>(mBuffer.Elements());
1000 template <typename T>
1001 void Copy(const T& other) {
1002 static_assert(!mozilla::IsPointer<T>::value, "Don't want a pointer!");
1003 mBuffer.SetLength(sizeof(T));
1004 memcpy(mBuffer.Elements(), &other, mBuffer.Length());
1007 void Clear() { mBuffer.Clear(); }
1010 /******************************************************************************
1011 * mozilla::WidgetGUIEvent
1012 ******************************************************************************/
1014 class WidgetGUIEvent : public WidgetEvent {
1015 protected:
1016 WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1017 EventClassID aEventClassID)
1018 : WidgetEvent(aIsTrusted, aMessage, aEventClassID), mWidget(aWidget) {}
1020 WidgetGUIEvent() {}
1022 public:
1023 virtual WidgetGUIEvent* AsGUIEvent() override { return this; }
1025 WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
1026 : WidgetEvent(aIsTrusted, aMessage, eGUIEventClass), mWidget(aWidget) {}
1028 virtual WidgetEvent* Duplicate() const override {
1029 MOZ_ASSERT(mClass == eGUIEventClass,
1030 "Duplicate() must be overridden by sub class");
1031 // Not copying widget, it is a weak reference.
1032 WidgetGUIEvent* result = new WidgetGUIEvent(false, mMessage, nullptr);
1033 result->AssignGUIEventData(*this, true);
1034 result->mFlags = mFlags;
1035 return result;
1038 // Originator of the event
1039 nsCOMPtr<nsIWidget> mWidget;
1042 * Ideally though, we wouldn't allow arbitrary reinterpret_cast'ing here;
1043 * instead, we would at least store type information here so that
1044 * this class can't be used to reinterpret one structure type into another.
1045 * We can also wonder if it would be possible to properly extend
1046 * WidgetGUIEvent and other Event classes to remove the need for this
1047 * mPluginEvent field.
1049 typedef NativeEventData PluginEvent;
1051 // Event for NPAPI plugin
1052 PluginEvent mPluginEvent;
1054 void AssignGUIEventData(const WidgetGUIEvent& aEvent, bool aCopyTargets) {
1055 AssignEventData(aEvent, aCopyTargets);
1057 // widget should be initialized with the constructor.
1059 mPluginEvent = aEvent.mPluginEvent;
1063 /******************************************************************************
1064 * mozilla::Modifier
1066 * All modifier keys should be defined here. This is used for managing
1067 * modifier states for DOM Level 3 or later.
1068 ******************************************************************************/
1070 enum Modifier {
1071 MODIFIER_NONE = 0x0000,
1072 MODIFIER_ALT = 0x0001,
1073 MODIFIER_ALTGRAPH = 0x0002,
1074 MODIFIER_CAPSLOCK = 0x0004,
1075 MODIFIER_CONTROL = 0x0008,
1076 MODIFIER_FN = 0x0010,
1077 MODIFIER_FNLOCK = 0x0020,
1078 MODIFIER_META = 0x0040,
1079 MODIFIER_NUMLOCK = 0x0080,
1080 MODIFIER_SCROLLLOCK = 0x0100,
1081 MODIFIER_SHIFT = 0x0200,
1082 MODIFIER_SYMBOL = 0x0400,
1083 MODIFIER_SYMBOLLOCK = 0x0800,
1084 MODIFIER_OS = 0x1000
1087 /******************************************************************************
1088 * Modifier key names.
1089 ******************************************************************************/
1091 #define NS_DOM_KEYNAME_ALT "Alt"
1092 #define NS_DOM_KEYNAME_ALTGRAPH "AltGraph"
1093 #define NS_DOM_KEYNAME_CAPSLOCK "CapsLock"
1094 #define NS_DOM_KEYNAME_CONTROL "Control"
1095 #define NS_DOM_KEYNAME_FN "Fn"
1096 #define NS_DOM_KEYNAME_FNLOCK "FnLock"
1097 #define NS_DOM_KEYNAME_META "Meta"
1098 #define NS_DOM_KEYNAME_NUMLOCK "NumLock"
1099 #define NS_DOM_KEYNAME_SCROLLLOCK "ScrollLock"
1100 #define NS_DOM_KEYNAME_SHIFT "Shift"
1101 #define NS_DOM_KEYNAME_SYMBOL "Symbol"
1102 #define NS_DOM_KEYNAME_SYMBOLLOCK "SymbolLock"
1103 #define NS_DOM_KEYNAME_OS "OS"
1105 /******************************************************************************
1106 * mozilla::Modifiers
1107 ******************************************************************************/
1109 typedef uint16_t Modifiers;
1111 class MOZ_STACK_CLASS GetModifiersName final : public nsAutoCString {
1112 public:
1113 explicit GetModifiersName(Modifiers aModifiers) {
1114 if (aModifiers & MODIFIER_ALT) {
1115 AssignLiteral(NS_DOM_KEYNAME_ALT);
1117 if (aModifiers & MODIFIER_ALTGRAPH) {
1118 MaybeAppendSeparator();
1119 AppendLiteral(NS_DOM_KEYNAME_ALTGRAPH);
1121 if (aModifiers & MODIFIER_CAPSLOCK) {
1122 MaybeAppendSeparator();
1123 AppendLiteral(NS_DOM_KEYNAME_CAPSLOCK);
1125 if (aModifiers & MODIFIER_CONTROL) {
1126 MaybeAppendSeparator();
1127 AppendLiteral(NS_DOM_KEYNAME_CONTROL);
1129 if (aModifiers & MODIFIER_FN) {
1130 MaybeAppendSeparator();
1131 AppendLiteral(NS_DOM_KEYNAME_FN);
1133 if (aModifiers & MODIFIER_FNLOCK) {
1134 MaybeAppendSeparator();
1135 AppendLiteral(NS_DOM_KEYNAME_FNLOCK);
1137 if (aModifiers & MODIFIER_META) {
1138 MaybeAppendSeparator();
1139 AppendLiteral(NS_DOM_KEYNAME_META);
1141 if (aModifiers & MODIFIER_NUMLOCK) {
1142 MaybeAppendSeparator();
1143 AppendLiteral(NS_DOM_KEYNAME_NUMLOCK);
1145 if (aModifiers & MODIFIER_SCROLLLOCK) {
1146 MaybeAppendSeparator();
1147 AppendLiteral(NS_DOM_KEYNAME_SCROLLLOCK);
1149 if (aModifiers & MODIFIER_SHIFT) {
1150 MaybeAppendSeparator();
1151 AppendLiteral(NS_DOM_KEYNAME_SHIFT);
1153 if (aModifiers & MODIFIER_SYMBOL) {
1154 MaybeAppendSeparator();
1155 AppendLiteral(NS_DOM_KEYNAME_SYMBOL);
1157 if (aModifiers & MODIFIER_SYMBOLLOCK) {
1158 MaybeAppendSeparator();
1159 AppendLiteral(NS_DOM_KEYNAME_SYMBOLLOCK);
1161 if (aModifiers & MODIFIER_OS) {
1162 MaybeAppendSeparator();
1163 AppendLiteral(NS_DOM_KEYNAME_OS);
1165 if (IsEmpty()) {
1166 AssignLiteral("none");
1170 private:
1171 void MaybeAppendSeparator() {
1172 if (!IsEmpty()) {
1173 AppendLiteral(" | ");
1178 /******************************************************************************
1179 * mozilla::WidgetInputEvent
1180 ******************************************************************************/
1182 class WidgetInputEvent : public WidgetGUIEvent {
1183 protected:
1184 WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1185 EventClassID aEventClassID)
1186 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID),
1187 mModifiers(0) {}
1189 WidgetInputEvent() : mModifiers(0) {}
1191 public:
1192 virtual WidgetInputEvent* AsInputEvent() override { return this; }
1194 WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
1195 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eInputEventClass),
1196 mModifiers(0) {}
1198 virtual WidgetEvent* Duplicate() const override {
1199 MOZ_ASSERT(mClass == eInputEventClass,
1200 "Duplicate() must be overridden by sub class");
1201 // Not copying widget, it is a weak reference.
1202 WidgetInputEvent* result = new WidgetInputEvent(false, mMessage, nullptr);
1203 result->AssignInputEventData(*this, true);
1204 result->mFlags = mFlags;
1205 return result;
1209 * Returns a modifier of "Accel" virtual modifier which is used for shortcut
1210 * key.
1212 static Modifier AccelModifier();
1215 * GetModifier() returns a modifier flag which is activated by aDOMKeyName.
1217 static Modifier GetModifier(const nsAString& aDOMKeyName);
1219 // true indicates the accel key on the environment is down
1220 bool IsAccel() const { return ((mModifiers & AccelModifier()) != 0); }
1222 // true indicates the shift key is down
1223 bool IsShift() const { return ((mModifiers & MODIFIER_SHIFT) != 0); }
1224 // true indicates the control key is down
1225 bool IsControl() const { return ((mModifiers & MODIFIER_CONTROL) != 0); }
1226 // true indicates the alt key is down
1227 bool IsAlt() const { return ((mModifiers & MODIFIER_ALT) != 0); }
1228 // true indicates the meta key is down (or, on Mac, the Command key)
1229 bool IsMeta() const { return ((mModifiers & MODIFIER_META) != 0); }
1230 // true indicates the win key is down on Windows. Or the Super or Hyper key
1231 // is down on Linux.
1232 bool IsOS() const { return ((mModifiers & MODIFIER_OS) != 0); }
1233 // true indicates the alt graph key is down
1234 // NOTE: on Mac, the option key press causes both IsAlt() and IsAltGrpah()
1235 // return true.
1236 bool IsAltGraph() const { return ((mModifiers & MODIFIER_ALTGRAPH) != 0); }
1237 // true indicates the CapLock LED is turn on.
1238 bool IsCapsLocked() const { return ((mModifiers & MODIFIER_CAPSLOCK) != 0); }
1239 // true indicates the NumLock LED is turn on.
1240 bool IsNumLocked() const { return ((mModifiers & MODIFIER_NUMLOCK) != 0); }
1241 // true indicates the ScrollLock LED is turn on.
1242 bool IsScrollLocked() const {
1243 return ((mModifiers & MODIFIER_SCROLLLOCK) != 0);
1246 // true indicates the Fn key is down, but this is not supported by native
1247 // key event on any platform.
1248 bool IsFn() const { return ((mModifiers & MODIFIER_FN) != 0); }
1249 // true indicates the FnLock LED is turn on, but we don't know such
1250 // keyboards nor platforms.
1251 bool IsFnLocked() const { return ((mModifiers & MODIFIER_FNLOCK) != 0); }
1252 // true indicates the Symbol is down, but this is not supported by native
1253 // key event on any platforms.
1254 bool IsSymbol() const { return ((mModifiers & MODIFIER_SYMBOL) != 0); }
1255 // true indicates the SymbolLock LED is turn on, but we don't know such
1256 // keyboards nor platforms.
1257 bool IsSymbolLocked() const {
1258 return ((mModifiers & MODIFIER_SYMBOLLOCK) != 0);
1261 void InitBasicModifiers(bool aCtrlKey, bool aAltKey, bool aShiftKey,
1262 bool aMetaKey) {
1263 mModifiers = 0;
1264 if (aCtrlKey) {
1265 mModifiers |= MODIFIER_CONTROL;
1267 if (aAltKey) {
1268 mModifiers |= MODIFIER_ALT;
1270 if (aShiftKey) {
1271 mModifiers |= MODIFIER_SHIFT;
1273 if (aMetaKey) {
1274 mModifiers |= MODIFIER_META;
1278 Modifiers mModifiers;
1280 void AssignInputEventData(const WidgetInputEvent& aEvent, bool aCopyTargets) {
1281 AssignGUIEventData(aEvent, aCopyTargets);
1283 mModifiers = aEvent.mModifiers;
1287 /******************************************************************************
1288 * mozilla::InternalUIEvent
1290 * XXX Why this inherits WidgetGUIEvent rather than WidgetEvent?
1291 ******************************************************************************/
1293 class InternalUIEvent : public WidgetGUIEvent {
1294 protected:
1295 InternalUIEvent() : mDetail(0), mCausedByUntrustedEvent(false) {}
1297 InternalUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1298 EventClassID aEventClassID)
1299 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID),
1300 mDetail(0),
1301 mCausedByUntrustedEvent(false) {}
1303 InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1304 EventClassID aEventClassID)
1305 : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, aEventClassID),
1306 mDetail(0),
1307 mCausedByUntrustedEvent(false) {}
1309 public:
1310 virtual InternalUIEvent* AsUIEvent() override { return this; }
1313 * If the UIEvent is caused by another event (e.g., click event),
1314 * aEventCausesThisEvent should be the event. If there is no such event,
1315 * this should be nullptr.
1317 InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1318 const WidgetEvent* aEventCausesThisEvent)
1319 : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, eUIEventClass),
1320 mDetail(0),
1321 mCausedByUntrustedEvent(aEventCausesThisEvent &&
1322 !aEventCausesThisEvent->IsTrusted()) {}
1324 virtual WidgetEvent* Duplicate() const override {
1325 MOZ_ASSERT(mClass == eUIEventClass,
1326 "Duplicate() must be overridden by sub class");
1327 InternalUIEvent* result = new InternalUIEvent(false, mMessage, nullptr);
1328 result->AssignUIEventData(*this, true);
1329 result->mFlags = mFlags;
1330 return result;
1333 int32_t mDetail;
1334 // mCausedByUntrustedEvent is true if the event is caused by untrusted event.
1335 bool mCausedByUntrustedEvent;
1337 // If you check the event is a trusted event and NOT caused by an untrusted
1338 // event, IsTrustable() returns what you expected.
1339 bool IsTrustable() const { return IsTrusted() && !mCausedByUntrustedEvent; }
1341 void AssignUIEventData(const InternalUIEvent& aEvent, bool aCopyTargets) {
1342 AssignGUIEventData(aEvent, aCopyTargets);
1344 mDetail = aEvent.mDetail;
1345 mCausedByUntrustedEvent = aEvent.mCausedByUntrustedEvent;
1349 } // namespace mozilla
1351 #endif // mozilla_BasicEvents_h__