forked from mirrors/gecko-dev
		
	 fe2b9f4618
			
		
	
	
		fe2b9f4618
		
	
	
	
	
		
			
			Unfortunately, we returned a `CompositionEvent` for
`Document.createEvent("textevent")` because we had a text event which we stopped
exposing to the web and was replaced with `eCompositionChange` event.
Therefore, this change could potentially have a compatibility risk.
Differential Revision: https://phabricator.services.mozilla.com/D200120
		
	
			
		
			
				
	
	
		
			1339 lines
		
	
	
	
		
			50 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1339 lines
		
	
	
	
		
			50 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #ifndef mozilla_BasicEvents_h__
 | |
| #define mozilla_BasicEvents_h__
 | |
| 
 | |
| #include <stdint.h>
 | |
| #include <type_traits>
 | |
| 
 | |
| #include "mozilla/EventForwards.h"
 | |
| #include "mozilla/TimeStamp.h"
 | |
| #include "mozilla/dom/EventTarget.h"
 | |
| #include "mozilla/layers/LayersTypes.h"
 | |
| #include "nsCOMPtr.h"
 | |
| #include "nsAtom.h"
 | |
| #include "nsISupportsImpl.h"
 | |
| #include "nsIWidget.h"
 | |
| #include "nsString.h"
 | |
| #include "Units.h"
 | |
| 
 | |
| #ifdef DEBUG
 | |
| #  include "nsXULAppAPI.h"
 | |
| #endif  // #ifdef DEBUG
 | |
| 
 | |
| class nsIPrincipal;
 | |
| 
 | |
| namespace IPC {
 | |
| template <typename T>
 | |
| struct ParamTraits;
 | |
| }  // namespace IPC
 | |
| 
 | |
| namespace mozilla {
 | |
| 
 | |
| class EventTargetChainItem;
 | |
| 
 | |
| enum class CrossProcessForwarding {
 | |
|   // eStop prevents the event to be sent to remote process.
 | |
|   eStop,
 | |
|   // eAllow keeps current state of the event whether it's sent to remote
 | |
|   // process.  In other words, eAllow does NOT mean that making the event
 | |
|   // sent to remote process when IsCrossProcessForwardingStopped() returns
 | |
|   // true.
 | |
|   eAllow,
 | |
| };
 | |
| 
 | |
| /******************************************************************************
 | |
|  * mozilla::BaseEventFlags
 | |
|  *
 | |
|  * BaseEventFlags must be a POD struct for safe to use memcpy (including
 | |
|  * in ParamTraits<BaseEventFlags>).  So don't make virtual methods, constructor,
 | |
|  * destructor and operators.
 | |
|  * This is necessary for VC which is NOT C++0x compiler.
 | |
|  ******************************************************************************/
 | |
| 
 | |
| struct BaseEventFlags {
 | |
|  public:
 | |
|   // If mIsTrusted is true, the event is a trusted event.  Otherwise, it's
 | |
|   // an untrusted event.
 | |
|   bool mIsTrusted : 1;
 | |
|   // If mInBubblingPhase is true, the event is in bubbling phase or target
 | |
|   // phase.
 | |
|   bool mInBubblingPhase : 1;
 | |
|   // If mInCapturePhase is true, the event is in capture phase or target phase.
 | |
|   bool mInCapturePhase : 1;
 | |
|   // If mInTargetPhase is true, the event is in target phase.
 | |
|   bool mInTargetPhase : 1;
 | |
|   // If mInSystemGroup is true, the event is being dispatched in system group.
 | |
|   bool mInSystemGroup : 1;
 | |
|   // If mCancelable is true, the event can be consumed.  I.e., calling
 | |
|   // dom::Event::PreventDefault() can prevent the default action.
 | |
|   bool mCancelable : 1;
 | |
|   // If mBubbles is true, the event can bubble.  Otherwise, cannot be handled
 | |
|   // in bubbling phase.
 | |
|   bool mBubbles : 1;
 | |
|   // If mPropagationStopped is true, dom::Event::StopPropagation() or
 | |
|   // dom::Event::StopImmediatePropagation() has been called.
 | |
|   bool mPropagationStopped : 1;
 | |
|   // If mImmediatePropagationStopped is true,
 | |
|   // dom::Event::StopImmediatePropagation() has been called.
 | |
|   // Note that mPropagationStopped must be true when this is true.
 | |
|   bool mImmediatePropagationStopped : 1;
 | |
|   // If mDefaultPrevented is true, the event has been consumed.
 | |
|   // E.g., dom::Event::PreventDefault() has been called or
 | |
|   // the default action has been performed.
 | |
|   bool mDefaultPrevented : 1;
 | |
|   // If mDefaultPreventedByContent is true, the event has been
 | |
|   // consumed by content.
 | |
|   // Note that mDefaultPrevented must be true when this is true.
 | |
|   bool mDefaultPreventedByContent : 1;
 | |
|   // If mDefaultPreventedByChrome is true, the event has been
 | |
|   // consumed by chrome.
 | |
|   // Note that mDefaultPrevented must be true when this is true.
 | |
|   bool mDefaultPreventedByChrome : 1;
 | |
|   // mMultipleActionsPrevented may be used when default handling don't want to
 | |
|   // be prevented, but only one of the event targets should handle the event.
 | |
|   // For example, when a <label> element is in another <label> element and
 | |
|   // the first <label> element is clicked, that one may set this true.
 | |
|   // Then, the second <label> element won't handle the event.
 | |
|   bool mMultipleActionsPrevented : 1;
 | |
|   // If mIsBeingDispatched is true, the DOM event created from the event is
 | |
|   // dispatching into the DOM tree and not completed.
 | |
|   bool mIsBeingDispatched : 1;
 | |
|   // If mDispatchedAtLeastOnce is true, the event has been dispatched
 | |
|   // as a DOM event and the dispatch has been completed in the process.
 | |
|   // So, this is false even if the event has already been dispatched
 | |
|   // in another process.
 | |
|   bool mDispatchedAtLeastOnce : 1;
 | |
|   // If mIsSynthesizedForTests is true, the event has been synthesized for
 | |
|   // automated tests or something hacky approach of an add-on.
 | |
|   bool mIsSynthesizedForTests : 1;
 | |
|   // If mExceptionWasRaised is true, one of the event handlers has raised an
 | |
|   // exception.
 | |
|   bool mExceptionWasRaised : 1;
 | |
|   // If mRetargetToNonNativeAnonymous is true and the target is in a non-native
 | |
|   // native anonymous subtree, the event target is set to mOriginalTarget.
 | |
|   bool mRetargetToNonNativeAnonymous : 1;
 | |
|   // If mNoContentDispatch is true, the event is never dispatched to the
 | |
|   // event handlers which are added to the contents, onfoo attributes and
 | |
|   // properties.  Note that this flag is ignored when
 | |
|   // EventChainPreVisitor::mForceContentDispatch is set true.  For exapmle,
 | |
|   // window and document object sets it true.  Therefore, web applications
 | |
|   // can handle the event if they add event listeners to the window or the
 | |
|   // document.
 | |
|   // XXX This is an ancient and broken feature, don't use this for new bug
 | |
|   //     as far as possible.
 | |
|   bool mNoContentDispatch : 1;
 | |
|   // If mOnlyChromeDispatch is true, the event is dispatched to only chrome.
 | |
|   bool mOnlyChromeDispatch : 1;
 | |
|   // Indicates if the key combination is reserved by chrome.  This is set by
 | |
|   // MarkAsReservedByChrome().
 | |
|   bool mIsReservedByChrome : 1;
 | |
|   // If mOnlySystemGroupDispatchInContent is true, event listeners added to
 | |
|   // the default group for non-chrome EventTarget won't be called.
 | |
|   // Be aware, if this is true, EventDispatcher needs to check if each event
 | |
|   // listener is added to chrome node, so, don't set this to true for the
 | |
|   // events which are fired a lot of times like eMouseMove.
 | |
|   bool mOnlySystemGroupDispatchInContent : 1;
 | |
|   // If mOnlySystemGroupDispatch is true, the event will be dispatched only to
 | |
|   // event listeners added in the system group.
 | |
|   bool mOnlySystemGroupDispatch : 1;
 | |
|   // The event's action will be handled by APZ. The main thread should not
 | |
|   // perform its associated action.
 | |
|   bool mHandledByAPZ : 1;
 | |
|   // True if the event is currently being handled by an event listener that
 | |
|   // was registered as a passive listener.
 | |
|   bool mInPassiveListener : 1;
 | |
|   // If mComposed is true, the event fired by nodes in shadow DOM can cross the
 | |
|   // boundary of shadow DOM and light DOM.
 | |
|   bool mComposed : 1;
 | |
|   // Similar to mComposed. Set it to true to allow events cross the boundary
 | |
|   // between native non-anonymous content and native anonymouse content
 | |
|   bool mComposedInNativeAnonymousContent : 1;
 | |
|   // Set to true for events which are suppressed or delayed so that later a
 | |
|   // DelayedEvent of it is dispatched. This is used when parent side process
 | |
|   // the key event after content side, and may drop the event if the event
 | |
|   // was suppressed or delayed in contents side.
 | |
|   // It is also set to true for the events (in a DelayedInputEvent), which will
 | |
|   // be dispatched afterwards.
 | |
|   bool mIsSuppressedOrDelayed : 1;
 | |
|   // Certain mouse events can be marked as positionless to return 0 from
 | |
|   // coordinate related getters.
 | |
|   bool mIsPositionless : 1;
 | |
| 
 | |
|   // Flags managing state of propagation between processes.
 | |
|   // Note the the following flags shouldn't be referred directly.  Use utility
 | |
|   // methods instead.
 | |
| 
 | |
|   // If mNoRemoteProcessDispatch is true, the event is not allowed to be sent
 | |
|   // to remote process.
 | |
|   bool mNoRemoteProcessDispatch : 1;
 | |
|   // If mWantReplyFromContentProcess is true, the event will be redispatched
 | |
|   // in the parent process after the content process has handled it. Useful
 | |
|   // for when the parent process need the know first how the event was used
 | |
|   // by content before handling it itself.
 | |
|   bool mWantReplyFromContentProcess : 1;
 | |
|   // If mPostedToRemoteProcess is true, the event has been posted to the
 | |
|   // remote process (but it's not handled yet if it's not a duplicated event
 | |
|   // instance).
 | |
|   bool mPostedToRemoteProcess : 1;
 | |
|   // If mCameFromAnotherProcess is true, the event came from another process.
 | |
|   bool mCameFromAnotherProcess : 1;
 | |
| 
 | |
|   /**
 | |
|    * Helper methods for methods of DOM Event.
 | |
|    */
 | |
|   inline void StopPropagation() { mPropagationStopped = true; }
 | |
|   inline void StopImmediatePropagation() {
 | |
|     StopPropagation();
 | |
|     mImmediatePropagationStopped = true;
 | |
|   }
 | |
|   inline void PreventDefault(bool aCalledByDefaultHandler = true) {
 | |
|     if (!mCancelable) {
 | |
|       return;
 | |
|     }
 | |
|     mDefaultPrevented = true;
 | |
|     // Note that even if preventDefault() has already been called by chrome,
 | |
|     // a call of preventDefault() by content needs to overwrite
 | |
|     // mDefaultPreventedByContent to true because in such case, defaultPrevented
 | |
|     // must be true when web apps check it after they call preventDefault().
 | |
|     if (aCalledByDefaultHandler) {
 | |
|       StopCrossProcessForwarding();
 | |
|       mDefaultPreventedByChrome = true;
 | |
|     } else {
 | |
|       mDefaultPreventedByContent = true;
 | |
|     }
 | |
|   }
 | |
|   // This should be used only before dispatching events into the DOM tree.
 | |
|   inline void PreventDefaultBeforeDispatch(
 | |
|       CrossProcessForwarding aCrossProcessForwarding) {
 | |
|     if (!mCancelable) {
 | |
|       return;
 | |
|     }
 | |
|     mDefaultPrevented = true;
 | |
|     if (aCrossProcessForwarding == CrossProcessForwarding::eStop) {
 | |
|       StopCrossProcessForwarding();
 | |
|     }
 | |
|   }
 | |
|   inline bool DefaultPrevented() const { return mDefaultPrevented; }
 | |
|   inline bool DefaultPreventedByContent() const {
 | |
|     MOZ_ASSERT(!mDefaultPreventedByContent || DefaultPrevented());
 | |
|     return mDefaultPreventedByContent;
 | |
|   }
 | |
|   inline bool IsTrusted() const { return mIsTrusted; }
 | |
|   inline bool PropagationStopped() const { return mPropagationStopped; }
 | |
| 
 | |
|   // Helper methods to access flags managing state of propagation between
 | |
|   // processes.
 | |
| 
 | |
|   /**
 | |
|    * Prevent to be dispatched to remote process.
 | |
|    */
 | |
|   inline void StopCrossProcessForwarding() {
 | |
|     MOZ_ASSERT(!mPostedToRemoteProcess);
 | |
|     mNoRemoteProcessDispatch = true;
 | |
|     mWantReplyFromContentProcess = false;
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event shouldn't be dispatched to remote process.
 | |
|    */
 | |
|   inline bool IsCrossProcessForwardingStopped() const {
 | |
|     return mNoRemoteProcessDispatch;
 | |
|   }
 | |
|   /**
 | |
|    * Mark the event as waiting reply from remote process.
 | |
|    * If the caller needs to win other keyboard event handlers in chrome,
 | |
|    * the caller should call StopPropagation() too.
 | |
|    * Otherwise, if the caller just needs to know if the event is consumed by
 | |
|    * either content or chrome, it should just call this because the event
 | |
|    * may be reserved by chrome and it needs to be dispatched into the DOM
 | |
|    * tree in chrome for checking if it's reserved before being sent to any
 | |
|    * remote processes.
 | |
|    */
 | |
|   inline void MarkAsWaitingReplyFromRemoteProcess() {
 | |
|     MOZ_ASSERT(!mPostedToRemoteProcess);
 | |
|     mNoRemoteProcessDispatch = false;
 | |
|     mWantReplyFromContentProcess = true;
 | |
|   }
 | |
|   /**
 | |
|    * Reset "waiting reply from remote process" state.  This is useful when
 | |
|    * you dispatch a copy of an event coming from different process.
 | |
|    */
 | |
|   inline void ResetWaitingReplyFromRemoteProcessState() {
 | |
|     if (IsWaitingReplyFromRemoteProcess()) {
 | |
|       // FYI: mWantReplyFromContentProcess is also used for indicating
 | |
|       //      "handled in remote process" state.  Therefore, only when
 | |
|       //      IsWaitingReplyFromRemoteProcess() returns true, this should
 | |
|       //      reset the flag.
 | |
|       mWantReplyFromContentProcess = false;
 | |
|     }
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event handler should wait reply event.  I.e., if this
 | |
|    * returns true, any event handler should do nothing with the event.
 | |
|    */
 | |
|   inline bool IsWaitingReplyFromRemoteProcess() const {
 | |
|     return !mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
 | |
|   }
 | |
|   /**
 | |
|    * Mark the event as already handled in the remote process.  This should be
 | |
|    * called when initializing reply events.
 | |
|    */
 | |
|   inline void MarkAsHandledInRemoteProcess() {
 | |
|     mNoRemoteProcessDispatch = true;
 | |
|     mWantReplyFromContentProcess = true;
 | |
|     mPostedToRemoteProcess = false;
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event has already been handled in the remote process.
 | |
|    */
 | |
|   inline bool IsHandledInRemoteProcess() const {
 | |
|     return mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event should be sent back to its parent process.
 | |
|    */
 | |
|   inline bool WantReplyFromContentProcess() const {
 | |
|     MOZ_ASSERT(!XRE_IsParentProcess());
 | |
|     return IsWaitingReplyFromRemoteProcess();
 | |
|   }
 | |
|   /**
 | |
|    * Mark the event has already posted to a remote process.
 | |
|    */
 | |
|   inline void MarkAsPostedToRemoteProcess() {
 | |
|     MOZ_ASSERT(!IsCrossProcessForwardingStopped());
 | |
|     mPostedToRemoteProcess = true;
 | |
|   }
 | |
|   /**
 | |
|    * Reset the cross process dispatching state.  This should be used when a
 | |
|    * process receives the event because the state is in the sender.
 | |
|    */
 | |
|   inline void ResetCrossProcessDispatchingState() {
 | |
|     MOZ_ASSERT(!IsCrossProcessForwardingStopped());
 | |
|     mPostedToRemoteProcess = false;
 | |
|     // Ignore propagation state in the remote process if it's marked as
 | |
|     // "waiting reply from remote process" because the process needs to
 | |
|     // stop propagation in the process until receiving a reply event.
 | |
|     // Note that the propagation stopped flag is important for the reply event
 | |
|     // handler in the main process because it's used for making whether it's
 | |
|     // ignored by the remote process or not.
 | |
|     if (!XRE_IsParentProcess() && IsWaitingReplyFromRemoteProcess()) {
 | |
|       mPropagationStopped = mImmediatePropagationStopped = false;
 | |
|     }
 | |
|     // mDispatchedAtLeastOnce indicates the state in current process.
 | |
|     mDispatchedAtLeastOnce = false;
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event has been posted to a remote process.
 | |
|    * Note that MarkAsPostedToRemoteProcess() is called by
 | |
|    * ParamTraits<mozilla::WidgetEvent>.  Therefore, it *might* be possible
 | |
|    * that posting the event failed even if this returns true.  But that must
 | |
|    * really rare.  If that'd be problem for you, you should unmark this in
 | |
|    * BrowserParent or somewhere.
 | |
|    */
 | |
|   inline bool HasBeenPostedToRemoteProcess() const {
 | |
|     return mPostedToRemoteProcess;
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event came from another process.
 | |
|    */
 | |
|   inline bool CameFromAnotherProcess() const { return mCameFromAnotherProcess; }
 | |
|   /**
 | |
|    * Mark the event as coming from another process.
 | |
|    */
 | |
|   inline void MarkAsComingFromAnotherProcess() {
 | |
|     mCameFromAnotherProcess = true;
 | |
|   }
 | |
|   /**
 | |
|    * Mark the event is reserved by chrome.  I.e., shouldn't be dispatched to
 | |
|    * content because it shouldn't be cancelable.
 | |
|    */
 | |
|   inline void MarkAsReservedByChrome() {
 | |
|     MOZ_ASSERT(!mPostedToRemoteProcess);
 | |
|     mIsReservedByChrome = true;
 | |
|     // For reserved commands (such as Open New Tab), we don't need to wait for
 | |
|     // the content to answer, neither to give a chance for content to override
 | |
|     // its behavior.
 | |
|     StopCrossProcessForwarding();
 | |
|     // If the event is reserved by chrome, we shouldn't expose the event to
 | |
|     // web contents because such events shouldn't be cancelable.  So, it's not
 | |
|     // good behavior to fire such events but to ignore the defaultPrevented
 | |
|     // attribute value in chrome.
 | |
|     mOnlySystemGroupDispatchInContent = true;
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event is reserved by chrome.
 | |
|    */
 | |
|   inline bool IsReservedByChrome() const {
 | |
|     MOZ_ASSERT(!mIsReservedByChrome || (IsCrossProcessForwardingStopped() &&
 | |
|                                         mOnlySystemGroupDispatchInContent));
 | |
|     return mIsReservedByChrome;
 | |
|   }
 | |
| 
 | |
|   inline void Clear() { SetRawFlags(0); }
 | |
|   // Get if either the instance's bit or the aOther's bit is true, the
 | |
|   // instance's bit becomes true.  In other words, this works like:
 | |
|   // eventFlags |= aOther;
 | |
|   inline void Union(const BaseEventFlags& aOther) {
 | |
|     RawFlags rawFlags = GetRawFlags() | aOther.GetRawFlags();
 | |
|     SetRawFlags(rawFlags);
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   typedef uint64_t RawFlags;
 | |
| 
 | |
|   inline void SetRawFlags(RawFlags aRawFlags) {
 | |
|     static_assert(sizeof(BaseEventFlags) <= sizeof(RawFlags),
 | |
|                   "mozilla::EventFlags must not be bigger than the RawFlags");
 | |
|     memcpy(this, &aRawFlags, sizeof(BaseEventFlags));
 | |
|   }
 | |
|   inline RawFlags GetRawFlags() const {
 | |
|     RawFlags result = 0;
 | |
|     memcpy(&result, this, sizeof(BaseEventFlags));
 | |
|     return result;
 | |
|   }
 | |
| };
 | |
| 
 | |
| /******************************************************************************
 | |
|  * mozilla::EventFlags
 | |
|  ******************************************************************************/
 | |
| 
 | |
| struct EventFlags : public BaseEventFlags {
 | |
|   EventFlags() { Clear(); }
 | |
| };
 | |
| 
 | |
| /******************************************************************************
 | |
|  * mozilla::WidgetEventTime
 | |
|  ******************************************************************************/
 | |
| 
 | |
| class WidgetEventTime {
 | |
|  public:
 | |
|   // Timestamp when the message was created.
 | |
|   TimeStamp mTimeStamp;
 | |
| 
 | |
|   WidgetEventTime() : mTimeStamp(TimeStamp::Now()) {}
 | |
| 
 | |
|   explicit WidgetEventTime(const WidgetEventTime* aTime)
 | |
|       : mTimeStamp(aTime ? aTime->mTimeStamp : TimeStamp::Now()) {
 | |
|     MOZ_ASSERT(aTime != this);
 | |
|     MOZ_ASSERT_IF(aTime, !aTime->mTimeStamp.IsNull());
 | |
|   }
 | |
| 
 | |
|   explicit WidgetEventTime(TimeStamp aTimeStamp) : mTimeStamp(aTimeStamp) {}
 | |
| 
 | |
|   void AssignEventTime(const WidgetEventTime& aOther) {
 | |
|     mTimeStamp = aOther.mTimeStamp;
 | |
|   }
 | |
| };
 | |
| 
 | |
| /******************************************************************************
 | |
|  * mozilla::WidgetEvent
 | |
|  ******************************************************************************/
 | |
| 
 | |
| class WidgetEvent : public WidgetEventTime {
 | |
|  private:
 | |
|   void SetDefaultCancelableAndBubbles() {
 | |
|     switch (mClass) {
 | |
|       case eEditorInputEventClass:
 | |
|         mFlags.mCancelable = false;
 | |
|         mFlags.mBubbles = mFlags.mIsTrusted;
 | |
|         break;
 | |
|       case eLegacyTextEventClass:
 | |
|         mFlags.mCancelable = mFlags.mIsTrusted && mMessage == eLegacyTextInput;
 | |
|         mFlags.mBubbles = mFlags.mIsTrusted && mMessage == eLegacyTextInput;
 | |
|         break;
 | |
|       case eMouseEventClass:
 | |
|         mFlags.mCancelable =
 | |
|             (mMessage != eMouseEnter && mMessage != eMouseLeave);
 | |
|         mFlags.mBubbles = (mMessage != eMouseEnter && mMessage != eMouseLeave);
 | |
|         break;
 | |
|       case ePointerEventClass:
 | |
|         mFlags.mCancelable =
 | |
|             (mMessage != ePointerEnter && mMessage != ePointerLeave &&
 | |
|              mMessage != ePointerCancel && mMessage != ePointerGotCapture &&
 | |
|              mMessage != ePointerLostCapture);
 | |
|         mFlags.mBubbles =
 | |
|             (mMessage != ePointerEnter && mMessage != ePointerLeave);
 | |
|         break;
 | |
|       case eDragEventClass:
 | |
|         mFlags.mCancelable = (mMessage != eDragExit && mMessage != eDragLeave &&
 | |
|                               mMessage != eDragEnd);
 | |
|         mFlags.mBubbles = true;
 | |
|         break;
 | |
|       case eSMILTimeEventClass:
 | |
|         mFlags.mCancelable = false;
 | |
|         mFlags.mBubbles = false;
 | |
|         break;
 | |
|       case eTransitionEventClass:
 | |
|       case eAnimationEventClass:
 | |
|         mFlags.mCancelable = false;
 | |
|         mFlags.mBubbles = true;
 | |
|         break;
 | |
|       case eCompositionEventClass:
 | |
|         // XXX compositionstart is cancelable in draft of DOM3 Events.
 | |
|         //     However, it doesn't make sense for us, we cannot cancel
 | |
|         //     composition when we send compositionstart event.
 | |
|         mFlags.mCancelable = false;
 | |
|         mFlags.mBubbles = true;
 | |
|         break;
 | |
|       default:
 | |
|         if (mMessage == eResize || mMessage == eMozVisualResize ||
 | |
|             mMessage == eMozVisualScroll || mMessage == eEditorInput ||
 | |
|             mMessage == eFormSelect) {
 | |
|           mFlags.mCancelable = false;
 | |
|         } else {
 | |
|           mFlags.mCancelable = true;
 | |
|         }
 | |
|         mFlags.mBubbles = true;
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|  protected:
 | |
|   WidgetEvent(bool aIsTrusted, EventMessage aMessage,
 | |
|               EventClassID aEventClassID,
 | |
|               const WidgetEventTime* aTime = nullptr)
 | |
|       : WidgetEventTime(aTime),
 | |
|         mClass(aEventClassID),
 | |
|         mMessage(aMessage),
 | |
|         mRefPoint(0, 0),
 | |
|         mLastRefPoint(0, 0),
 | |
|         mFocusSequenceNumber(0),
 | |
|         mSpecifiedEventType(nullptr),
 | |
|         mPath(nullptr),
 | |
|         mLayersId(layers::LayersId{0}) {
 | |
|     MOZ_COUNT_CTOR(WidgetEvent);
 | |
|     mFlags.Clear();
 | |
|     mFlags.mIsTrusted = aIsTrusted;
 | |
|     SetDefaultCancelableAndBubbles();
 | |
|     SetDefaultComposed();
 | |
|     SetDefaultComposedInNativeAnonymousContent();
 | |
|   }
 | |
| 
 | |
|   WidgetEvent() : mPath(nullptr) { MOZ_COUNT_CTOR(WidgetEvent); }
 | |
| 
 | |
|  public:
 | |
|   WidgetEvent(bool aIsTrusted, EventMessage aMessage,
 | |
|               const WidgetEventTime* aTime = nullptr)
 | |
|       : WidgetEvent(aIsTrusted, aMessage, eBasicEventClass, aTime) {}
 | |
| 
 | |
|   MOZ_COUNTED_DTOR_VIRTUAL(WidgetEvent)
 | |
| 
 | |
|   WidgetEvent(const WidgetEvent& aOther) : WidgetEventTime(aOther) {
 | |
|     MOZ_COUNT_CTOR(WidgetEvent);
 | |
|     *this = aOther;
 | |
|   }
 | |
|   WidgetEvent& operator=(const WidgetEvent& aOther) = default;
 | |
| 
 | |
|   WidgetEvent(WidgetEvent&& aOther)
 | |
|       : WidgetEventTime(std::move(aOther)),
 | |
|         mClass(aOther.mClass),
 | |
|         mMessage(aOther.mMessage),
 | |
|         mRefPoint(std::move(aOther.mRefPoint)),
 | |
|         mLastRefPoint(std::move(aOther.mLastRefPoint)),
 | |
|         mFocusSequenceNumber(aOther.mFocusSequenceNumber),
 | |
|         mFlags(std::move(aOther.mFlags)),
 | |
|         mSpecifiedEventType(std::move(aOther.mSpecifiedEventType)),
 | |
|         mSpecifiedEventTypeString(std::move(aOther.mSpecifiedEventTypeString)),
 | |
|         mTarget(std::move(aOther.mTarget)),
 | |
|         mCurrentTarget(std::move(aOther.mCurrentTarget)),
 | |
|         mOriginalTarget(std::move(aOther.mOriginalTarget)),
 | |
|         mRelatedTarget(std::move(aOther.mRelatedTarget)),
 | |
|         mOriginalRelatedTarget(std::move(aOther.mOriginalRelatedTarget)),
 | |
|         mPath(std::move(aOther.mPath)) {
 | |
|     MOZ_COUNT_CTOR(WidgetEvent);
 | |
|   }
 | |
|   WidgetEvent& operator=(WidgetEvent&& aOther) = default;
 | |
| 
 | |
|   virtual WidgetEvent* Duplicate() const {
 | |
|     MOZ_ASSERT(mClass == eBasicEventClass,
 | |
|                "Duplicate() must be overridden by sub class");
 | |
|     WidgetEvent* result = new WidgetEvent(false, mMessage, this);
 | |
|     result->AssignEventData(*this, true);
 | |
|     result->mFlags = mFlags;
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   EventClassID mClass;
 | |
|   EventMessage mMessage;
 | |
|   // Relative to the widget of the event, or if there is no widget then it is
 | |
|   // in screen coordinates. Not modified by layout code.
 | |
|   // This is in visual coordinates, i.e. the correct RelativeTo value that
 | |
|   // expresses what this is relative to is `{viewportFrame, Visual}`, where
 | |
|   // `viewportFrame` is the viewport frame of the widget's root document.
 | |
|   LayoutDeviceIntPoint mRefPoint;
 | |
|   // The previous mRefPoint, if known, used to calculate mouse movement deltas.
 | |
|   LayoutDeviceIntPoint mLastRefPoint;
 | |
|   // The sequence number of the last potentially focus changing event handled
 | |
|   // by APZ. This is used to track when that event has been processed by
 | |
|   // content, and focus can be reconfirmed for async keyboard scrolling.
 | |
|   uint64_t mFocusSequenceNumber;
 | |
|   // See BaseEventFlags definition for the detail.
 | |
|   BaseEventFlags mFlags;
 | |
| 
 | |
|   // If JS creates an event with unknown event type or known event type but
 | |
|   // for different event interface, the event type is stored to this.
 | |
|   // NOTE: This is always used if the instance is a WidgetCommandEvent instance
 | |
|   //       or "input" event is dispatched with dom::Event class.
 | |
|   RefPtr<nsAtom> mSpecifiedEventType;
 | |
| 
 | |
|   // nsAtom isn't available on non-main thread due to unsafe.  Therefore,
 | |
|   // mSpecifiedEventTypeString is used instead of mSpecifiedEventType if
 | |
|   // the event is created in non-main thread.
 | |
|   nsString mSpecifiedEventTypeString;
 | |
| 
 | |
|   // Event targets, needed by DOM Events
 | |
|   // Note that when you need event target for DOM event, you should use
 | |
|   // Get*DOMEventTarget() instead of accessing these members directly.
 | |
|   nsCOMPtr<dom::EventTarget> mTarget;
 | |
|   nsCOMPtr<dom::EventTarget> mCurrentTarget;
 | |
|   nsCOMPtr<dom::EventTarget> mOriginalTarget;
 | |
| 
 | |
|   /// The possible related target
 | |
|   nsCOMPtr<dom::EventTarget> mRelatedTarget;
 | |
|   nsCOMPtr<dom::EventTarget> mOriginalRelatedTarget;
 | |
| 
 | |
|   nsTArray<EventTargetChainItem>* mPath;
 | |
| 
 | |
|   // The LayersId of the content process that this event should be
 | |
|   // dispatched to. This field is only used in the chrome process
 | |
|   // and doesn't get remoted to child processes.
 | |
|   layers::LayersId mLayersId;
 | |
| 
 | |
|   dom::EventTarget* GetDOMEventTarget() const;
 | |
|   dom::EventTarget* GetCurrentDOMEventTarget() const;
 | |
|   dom::EventTarget* GetOriginalDOMEventTarget() const;
 | |
| 
 | |
|   void AssignEventData(const WidgetEvent& aEvent, bool aCopyTargets) {
 | |
|     // mClass should be initialized with the constructor.
 | |
|     // mMessage should be initialized with the constructor.
 | |
|     mRefPoint = aEvent.mRefPoint;
 | |
|     // mLastRefPoint doesn't need to be copied.
 | |
|     mFocusSequenceNumber = aEvent.mFocusSequenceNumber;
 | |
|     // mLayersId intentionally not copied, since it's not used within content
 | |
|     AssignEventTime(aEvent);
 | |
|     // mFlags should be copied manually if it's necessary.
 | |
|     mSpecifiedEventType = aEvent.mSpecifiedEventType;
 | |
|     // mSpecifiedEventTypeString should be copied manually if it's necessary.
 | |
|     mTarget = aCopyTargets ? aEvent.mTarget : nullptr;
 | |
|     mCurrentTarget = aCopyTargets ? aEvent.mCurrentTarget : nullptr;
 | |
|     mOriginalTarget = aCopyTargets ? aEvent.mOriginalTarget : nullptr;
 | |
|     mRelatedTarget = aCopyTargets ? aEvent.mRelatedTarget : nullptr;
 | |
|     mOriginalRelatedTarget =
 | |
|         aCopyTargets ? aEvent.mOriginalRelatedTarget : nullptr;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Helper methods for methods of DOM Event.
 | |
|    */
 | |
|   void StopPropagation() { mFlags.StopPropagation(); }
 | |
|   void StopImmediatePropagation() { mFlags.StopImmediatePropagation(); }
 | |
|   void PreventDefault(bool aCalledByDefaultHandler = true,
 | |
|                       nsIPrincipal* aPrincipal = nullptr);
 | |
| 
 | |
|   void PreventDefaultBeforeDispatch(
 | |
|       CrossProcessForwarding aCrossProcessForwarding) {
 | |
|     mFlags.PreventDefaultBeforeDispatch(aCrossProcessForwarding);
 | |
|   }
 | |
|   bool DefaultPrevented() const { return mFlags.DefaultPrevented(); }
 | |
|   bool DefaultPreventedByContent() const {
 | |
|     return mFlags.DefaultPreventedByContent();
 | |
|   }
 | |
|   bool IsTrusted() const { return mFlags.IsTrusted(); }
 | |
|   bool PropagationStopped() const { return mFlags.PropagationStopped(); }
 | |
| 
 | |
|   /**
 | |
|    * Prevent to be dispatched to remote process.
 | |
|    */
 | |
|   inline void StopCrossProcessForwarding() {
 | |
|     mFlags.StopCrossProcessForwarding();
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event shouldn't be dispatched to remote process.
 | |
|    */
 | |
|   inline bool IsCrossProcessForwardingStopped() const {
 | |
|     return mFlags.IsCrossProcessForwardingStopped();
 | |
|   }
 | |
|   /**
 | |
|    * Mark the event as waiting reply from remote process.
 | |
|    * Note that this also stops immediate propagation in current process.
 | |
|    */
 | |
|   inline void MarkAsWaitingReplyFromRemoteProcess() {
 | |
|     mFlags.MarkAsWaitingReplyFromRemoteProcess();
 | |
|   }
 | |
|   /**
 | |
|    * Reset "waiting reply from remote process" state.  This is useful when
 | |
|    * you dispatch a copy of an event coming from different process.
 | |
|    */
 | |
|   inline void ResetWaitingReplyFromRemoteProcessState() {
 | |
|     mFlags.ResetWaitingReplyFromRemoteProcessState();
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event handler should wait reply event.  I.e., if this
 | |
|    * returns true, any event handler should do nothing with the event.
 | |
|    */
 | |
|   inline bool IsWaitingReplyFromRemoteProcess() const {
 | |
|     return mFlags.IsWaitingReplyFromRemoteProcess();
 | |
|   }
 | |
|   /**
 | |
|    * Mark the event as already handled in the remote process.  This should be
 | |
|    * called when initializing reply events.
 | |
|    */
 | |
|   inline void MarkAsHandledInRemoteProcess() {
 | |
|     mFlags.MarkAsHandledInRemoteProcess();
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event has already been handled in the remote process.
 | |
|    * I.e., if this returns true, the event is a reply event.
 | |
|    */
 | |
|   inline bool IsHandledInRemoteProcess() const {
 | |
|     return mFlags.IsHandledInRemoteProcess();
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event should be sent back to its parent process.
 | |
|    * So, usual event handlers shouldn't call this.
 | |
|    */
 | |
|   inline bool WantReplyFromContentProcess() const {
 | |
|     return mFlags.WantReplyFromContentProcess();
 | |
|   }
 | |
|   /**
 | |
|    * Mark the event has already posted to a remote process.
 | |
|    */
 | |
|   inline void MarkAsPostedToRemoteProcess() {
 | |
|     mFlags.MarkAsPostedToRemoteProcess();
 | |
|   }
 | |
|   /**
 | |
|    * Reset the cross process dispatching state.  This should be used when a
 | |
|    * process receives the event because the state is in the sender.
 | |
|    */
 | |
|   inline void ResetCrossProcessDispatchingState() {
 | |
|     mFlags.ResetCrossProcessDispatchingState();
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event has been posted to a remote process.
 | |
|    */
 | |
|   inline bool HasBeenPostedToRemoteProcess() const {
 | |
|     return mFlags.HasBeenPostedToRemoteProcess();
 | |
|   }
 | |
|   /**
 | |
|    * Return true if the event came from another process.
 | |
|    */
 | |
|   inline bool CameFromAnotherProcess() const {
 | |
|     return mFlags.CameFromAnotherProcess();
 | |
|   }
 | |
|   /**
 | |
|    * Mark the event as coming from another process.
 | |
|    */
 | |
|   inline void MarkAsComingFromAnotherProcess() {
 | |
|     mFlags.MarkAsComingFromAnotherProcess();
 | |
|   }
 | |
|   /**
 | |
|    * Mark the event is reserved by chrome.  I.e., shouldn't be dispatched to
 | |
|    * content because it shouldn't be cancelable.
 | |
|    */
 | |
|   inline void MarkAsReservedByChrome() { mFlags.MarkAsReservedByChrome(); }
 | |
|   /**
 | |
|    * Return true if the event is reserved by chrome.
 | |
|    */
 | |
|   inline bool IsReservedByChrome() const { return mFlags.IsReservedByChrome(); }
 | |
| 
 | |
|   /**
 | |
|    * Utils for checking event types
 | |
|    */
 | |
| 
 | |
|   /**
 | |
|    * As*Event() returns the pointer of the instance only when the instance is
 | |
|    * the class or one of its derived class.
 | |
|    */
 | |
| #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
 | |
| #define NS_EVENT_CLASS(aPrefix, aName) \
 | |
|   virtual aPrefix##aName* As##aName(); \
 | |
|   const aPrefix##aName* As##aName() const;
 | |
| 
 | |
| #include "mozilla/EventClassList.h"
 | |
| 
 | |
| #undef NS_EVENT_CLASS
 | |
| #undef NS_ROOT_EVENT_CLASS
 | |
| 
 | |
|   /**
 | |
|    * Returns true if the event is a query content event.
 | |
|    */
 | |
|   bool IsQueryContentEvent() const;
 | |
|   /**
 | |
|    * Returns true if the event is a selection event.
 | |
|    */
 | |
|   bool IsSelectionEvent() const;
 | |
|   /**
 | |
|    * Returns true if the event is a content command event.
 | |
|    */
 | |
|   bool IsContentCommandEvent() const;
 | |
| 
 | |
|   /**
 | |
|    * Returns true if the event mMessage is one of mouse events.
 | |
|    */
 | |
|   bool HasMouseEventMessage() const;
 | |
|   /**
 | |
|    * Returns true if the event mMessage is one of drag events.
 | |
|    */
 | |
|   bool HasDragEventMessage() const;
 | |
|   /**
 | |
|    * Returns true if aMessage or mMessage is one of key events.
 | |
|    */
 | |
|   static bool IsKeyEventMessage(EventMessage aMessage);
 | |
|   bool HasKeyEventMessage() const { return IsKeyEventMessage(mMessage); }
 | |
|   /**
 | |
|    * Returns true if the event mMessage is one of composition events or text
 | |
|    * event.
 | |
|    */
 | |
|   bool HasIMEEventMessage() const;
 | |
| 
 | |
|   /**
 | |
|    * Returns true if the event can be sent to remote process.
 | |
|    */
 | |
|   bool CanBeSentToRemoteProcess() const;
 | |
|   /**
 | |
|    * Returns true if the original target is a remote process and the event
 | |
|    * will be posted to the remote process later.
 | |
|    */
 | |
|   bool WillBeSentToRemoteProcess() const;
 | |
|   /**
 | |
|    * Returns true if the event is related to IME handling.  It includes
 | |
|    * IME events, query content events and selection events.
 | |
|    * Be careful when you use this.
 | |
|    */
 | |
|   bool IsIMERelatedEvent() const;
 | |
| 
 | |
|   /**
 | |
|    * Whether the event should be handled by the frame of the mouse cursor
 | |
|    * position or not.  When it should be handled there (e.g., the mouse events),
 | |
|    * this returns true.
 | |
|    */
 | |
|   bool IsUsingCoordinates() const;
 | |
|   /**
 | |
|    * Whether the event should be handled by the focused DOM window in the
 | |
|    * same top level window's or not.  E.g., key events, IME related events
 | |
|    * (including the query content events, they are used in IME transaction)
 | |
|    * should be handled by the (last) focused window rather than the dispatched
 | |
|    * window.
 | |
|    *
 | |
|    * NOTE: Even if this returns true, the event isn't going to be handled by the
 | |
|    * application level active DOM window which is on another top level window.
 | |
|    * So, when the event is fired on a deactive window, the event is going to be
 | |
|    * handled by the last focused DOM window in the last focused window.
 | |
|    */
 | |
|   bool IsTargetedAtFocusedWindow() const;
 | |
|   /**
 | |
|    * Whether the event should be handled by the focused content or not.  E.g.,
 | |
|    * key events, IME related events and other input events which are not handled
 | |
|    * by the frame of the mouse cursor position.
 | |
|    *
 | |
|    * NOTE: Even if this returns true, the event isn't going to be handled by the
 | |
|    * application level active DOM window which is on another top level window.
 | |
|    * So, when the event is fired on a deactive window, the event is going to be
 | |
|    * handled by the last focused DOM element of the last focused DOM window in
 | |
|    * the last focused window.
 | |
|    */
 | |
|   bool IsTargetedAtFocusedContent() const;
 | |
|   /**
 | |
|    * Whether the event should cause a DOM event.
 | |
|    */
 | |
|   bool IsAllowedToDispatchDOMEvent() const;
 | |
|   /**
 | |
|    * Whether the event should be dispatched in system group.
 | |
|    */
 | |
|   bool IsAllowedToDispatchInSystemGroup() const;
 | |
|   /**
 | |
|    * Whether the event should be blocked for fingerprinting resistance.
 | |
|    */
 | |
|   bool IsBlockedForFingerprintingResistance() const;
 | |
|   /**
 | |
|    * Whether the event handler can flush pending notifications or not.
 | |
|    */
 | |
|   bool AllowFlushingPendingNotifications() const;
 | |
|   /**
 | |
|    * Initialize mComposed
 | |
|    */
 | |
|   void SetDefaultComposed() {
 | |
|     switch (mClass) {
 | |
|       case eClipboardEventClass:
 | |
|         mFlags.mComposed = true;
 | |
|         break;
 | |
|       case eCompositionEventClass:
 | |
|         mFlags.mComposed =
 | |
|             mMessage == eCompositionStart || mMessage == eCompositionUpdate ||
 | |
|             mMessage == eCompositionChange || mMessage == eCompositionEnd;
 | |
|         break;
 | |
|       case eDragEventClass:
 | |
|         // All drag & drop events are composed
 | |
|         mFlags.mComposed = mMessage == eDrag || mMessage == eDragEnd ||
 | |
|                            mMessage == eDragEnter || mMessage == eDragExit ||
 | |
|                            mMessage == eDragLeave || mMessage == eDragOver ||
 | |
|                            mMessage == eDragStart || mMessage == eDrop;
 | |
|         break;
 | |
|       case eEditorInputEventClass:
 | |
|         mFlags.mComposed =
 | |
|             mMessage == eEditorInput || mMessage == eEditorBeforeInput;
 | |
|         break;
 | |
|       case eFocusEventClass:
 | |
|         mFlags.mComposed = mMessage == eBlur || mMessage == eFocus ||
 | |
|                            mMessage == eFocusOut || mMessage == eFocusIn;
 | |
|         break;
 | |
|       case eKeyboardEventClass:
 | |
|         mFlags.mComposed =
 | |
|             mMessage == eKeyDown || mMessage == eKeyUp || mMessage == eKeyPress;
 | |
|         break;
 | |
|       case eMouseEventClass:
 | |
|         mFlags.mComposed =
 | |
|             mMessage == eMouseClick || mMessage == eMouseDoubleClick ||
 | |
|             mMessage == eMouseAuxClick || mMessage == eMouseDown ||
 | |
|             mMessage == eMouseUp || mMessage == eMouseOver ||
 | |
|             mMessage == eMouseOut || mMessage == eMouseMove ||
 | |
|             mMessage == eContextMenu || mMessage == eXULPopupShowing ||
 | |
|             mMessage == eXULPopupHiding || mMessage == eXULPopupShown ||
 | |
|             mMessage == eXULPopupHidden;
 | |
|         break;
 | |
|       case ePointerEventClass:
 | |
|         // All pointer events are composed
 | |
|         mFlags.mComposed =
 | |
|             mMessage == ePointerDown || mMessage == ePointerMove ||
 | |
|             mMessage == ePointerUp || mMessage == ePointerCancel ||
 | |
|             mMessage == ePointerOver || mMessage == ePointerOut ||
 | |
|             mMessage == ePointerGotCapture || mMessage == ePointerLostCapture;
 | |
|         break;
 | |
|       case eTouchEventClass:
 | |
|         // All touch events are composed
 | |
|         mFlags.mComposed = mMessage == eTouchStart || mMessage == eTouchEnd ||
 | |
|                            mMessage == eTouchMove || mMessage == eTouchCancel;
 | |
|         break;
 | |
|       case eUIEventClass:
 | |
|         mFlags.mComposed = mMessage == eLegacyDOMFocusIn ||
 | |
|                            mMessage == eLegacyDOMFocusOut ||
 | |
|                            mMessage == eLegacyDOMActivate;
 | |
|         break;
 | |
|       case eWheelEventClass:
 | |
|         // All wheel events are composed
 | |
|         mFlags.mComposed = mMessage == eWheel;
 | |
|         break;
 | |
|       case eMouseScrollEventClass:
 | |
|         // Legacy mouse scroll events are composed too, for consistency with
 | |
|         // wheel.
 | |
|         mFlags.mComposed = mMessage == eLegacyMouseLineOrPageScroll ||
 | |
|                            mMessage == eLegacyMousePixelScroll;
 | |
|         break;
 | |
|       default:
 | |
|         mFlags.mComposed = false;
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void SetComposed(const nsAString& aEventTypeArg) {
 | |
|     mFlags.mComposed =  // composition events
 | |
|         aEventTypeArg.EqualsLiteral("compositionstart") ||
 | |
|         aEventTypeArg.EqualsLiteral("compositionupdate") ||
 | |
|         aEventTypeArg.EqualsLiteral("compositionend") ||
 | |
|         aEventTypeArg.EqualsLiteral("text") ||
 | |
|         // drag and drop events
 | |
|         aEventTypeArg.EqualsLiteral("dragstart") ||
 | |
|         aEventTypeArg.EqualsLiteral("drag") ||
 | |
|         aEventTypeArg.EqualsLiteral("dragenter") ||
 | |
|         aEventTypeArg.EqualsLiteral("dragexit") ||
 | |
|         aEventTypeArg.EqualsLiteral("dragleave") ||
 | |
|         aEventTypeArg.EqualsLiteral("dragover") ||
 | |
|         aEventTypeArg.EqualsLiteral("drop") ||
 | |
|         aEventTypeArg.EqualsLiteral("dropend") ||
 | |
|         // editor input events
 | |
|         aEventTypeArg.EqualsLiteral("input") ||
 | |
|         aEventTypeArg.EqualsLiteral("beforeinput") ||
 | |
|         // focus events
 | |
|         aEventTypeArg.EqualsLiteral("blur") ||
 | |
|         aEventTypeArg.EqualsLiteral("focus") ||
 | |
|         aEventTypeArg.EqualsLiteral("focusin") ||
 | |
|         aEventTypeArg.EqualsLiteral("focusout") ||
 | |
|         // keyboard events
 | |
|         aEventTypeArg.EqualsLiteral("keydown") ||
 | |
|         aEventTypeArg.EqualsLiteral("keyup") ||
 | |
|         aEventTypeArg.EqualsLiteral("keypress") ||
 | |
|         // mouse events
 | |
|         aEventTypeArg.EqualsLiteral("click") ||
 | |
|         aEventTypeArg.EqualsLiteral("dblclick") ||
 | |
|         aEventTypeArg.EqualsLiteral("mousedown") ||
 | |
|         aEventTypeArg.EqualsLiteral("mouseup") ||
 | |
|         aEventTypeArg.EqualsLiteral("mouseenter") ||
 | |
|         aEventTypeArg.EqualsLiteral("mouseleave") ||
 | |
|         aEventTypeArg.EqualsLiteral("mouseover") ||
 | |
|         aEventTypeArg.EqualsLiteral("mouseout") ||
 | |
|         aEventTypeArg.EqualsLiteral("mousemove") ||
 | |
|         aEventTypeArg.EqualsLiteral("contextmenu") ||
 | |
|         // pointer events
 | |
|         aEventTypeArg.EqualsLiteral("pointerdown") ||
 | |
|         aEventTypeArg.EqualsLiteral("pointermove") ||
 | |
|         aEventTypeArg.EqualsLiteral("pointerup") ||
 | |
|         aEventTypeArg.EqualsLiteral("pointercancel") ||
 | |
|         aEventTypeArg.EqualsLiteral("pointerover") ||
 | |
|         aEventTypeArg.EqualsLiteral("pointerout") ||
 | |
|         aEventTypeArg.EqualsLiteral("pointerenter") ||
 | |
|         aEventTypeArg.EqualsLiteral("pointerleave") ||
 | |
|         aEventTypeArg.EqualsLiteral("gotpointercapture") ||
 | |
|         aEventTypeArg.EqualsLiteral("lostpointercapture") ||
 | |
|         // touch events
 | |
|         aEventTypeArg.EqualsLiteral("touchstart") ||
 | |
|         aEventTypeArg.EqualsLiteral("touchend") ||
 | |
|         aEventTypeArg.EqualsLiteral("touchmove") ||
 | |
|         aEventTypeArg.EqualsLiteral("touchcancel") ||
 | |
|         // UI legacy events
 | |
|         aEventTypeArg.EqualsLiteral("DOMFocusIn") ||
 | |
|         aEventTypeArg.EqualsLiteral("DOMFocusOut") ||
 | |
|         aEventTypeArg.EqualsLiteral("DOMActivate") ||
 | |
|         // wheel events
 | |
|         aEventTypeArg.EqualsLiteral("wheel");
 | |
|   }
 | |
| 
 | |
|   void SetComposed(bool aComposed) { mFlags.mComposed = aComposed; }
 | |
| 
 | |
|   void SetDefaultComposedInNativeAnonymousContent() {
 | |
|     // For compatibility concerns, we set mComposedInNativeAnonymousContent to
 | |
|     // false for those events we want to stop propagation.
 | |
|     //
 | |
|     // nsVideoFrame may create anonymous image element which fires eLoad,
 | |
|     // eLoadStart, eLoadEnd, eLoadError. We don't want these events cross
 | |
|     // the boundary of NAC
 | |
|     mFlags.mComposedInNativeAnonymousContent =
 | |
|         mMessage != eLoad && mMessage != eLoadStart && mMessage != eLoadEnd &&
 | |
|         mMessage != eLoadError;
 | |
|   }
 | |
| 
 | |
|   bool IsUserAction() const;
 | |
| };
 | |
| 
 | |
| /******************************************************************************
 | |
|  * mozilla::WidgetGUIEvent
 | |
|  ******************************************************************************/
 | |
| 
 | |
| class WidgetGUIEvent : public WidgetEvent {
 | |
|  protected:
 | |
|   WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
 | |
|                  EventClassID aEventClassID,
 | |
|                  const WidgetEventTime* aTime = nullptr)
 | |
|       : WidgetEvent(aIsTrusted, aMessage, aEventClassID, aTime),
 | |
|         mWidget(aWidget) {}
 | |
| 
 | |
|   WidgetGUIEvent() = default;
 | |
| 
 | |
|  public:
 | |
|   virtual WidgetGUIEvent* AsGUIEvent() override { return this; }
 | |
| 
 | |
|   WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
 | |
|                  const WidgetEventTime* aTime = nullptr)
 | |
|       : WidgetEvent(aIsTrusted, aMessage, eGUIEventClass, aTime),
 | |
|         mWidget(aWidget) {}
 | |
| 
 | |
|   virtual WidgetEvent* Duplicate() const override {
 | |
|     MOZ_ASSERT(mClass == eGUIEventClass,
 | |
|                "Duplicate() must be overridden by sub class");
 | |
|     // Not copying widget, it is a weak reference.
 | |
|     WidgetGUIEvent* result = new WidgetGUIEvent(false, mMessage, nullptr, this);
 | |
|     result->AssignGUIEventData(*this, true);
 | |
|     result->mFlags = mFlags;
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   // Originator of the event
 | |
|   nsCOMPtr<nsIWidget> mWidget;
 | |
| 
 | |
|   void AssignGUIEventData(const WidgetGUIEvent& aEvent, bool aCopyTargets) {
 | |
|     AssignEventData(aEvent, aCopyTargets);
 | |
|     // widget should be initialized with the constructor.
 | |
|   }
 | |
| };
 | |
| 
 | |
| /******************************************************************************
 | |
|  * mozilla::Modifier
 | |
|  *
 | |
|  * All modifier keys should be defined here.  This is used for managing
 | |
|  * modifier states for DOM Level 3 or later.
 | |
|  ******************************************************************************/
 | |
| 
 | |
| enum Modifier {
 | |
|   MODIFIER_NONE = 0x0000,
 | |
|   MODIFIER_ALT = 0x0001,
 | |
|   MODIFIER_ALTGRAPH = 0x0002,
 | |
|   MODIFIER_CAPSLOCK = 0x0004,
 | |
|   MODIFIER_CONTROL = 0x0008,
 | |
|   MODIFIER_FN = 0x0010,
 | |
|   MODIFIER_FNLOCK = 0x0020,
 | |
|   MODIFIER_META = 0x0040,
 | |
|   MODIFIER_NUMLOCK = 0x0080,
 | |
|   MODIFIER_SCROLLLOCK = 0x0100,
 | |
|   MODIFIER_SHIFT = 0x0200,
 | |
|   MODIFIER_SYMBOL = 0x0400,
 | |
|   MODIFIER_SYMBOLLOCK = 0x0800,
 | |
| };
 | |
| 
 | |
| /******************************************************************************
 | |
|  * Modifier key names.
 | |
|  ******************************************************************************/
 | |
| 
 | |
| #define NS_DOM_KEYNAME_ALT "Alt"
 | |
| #define NS_DOM_KEYNAME_ALTGRAPH "AltGraph"
 | |
| #define NS_DOM_KEYNAME_CAPSLOCK "CapsLock"
 | |
| #define NS_DOM_KEYNAME_CONTROL "Control"
 | |
| #define NS_DOM_KEYNAME_FN "Fn"
 | |
| #define NS_DOM_KEYNAME_FNLOCK "FnLock"
 | |
| #define NS_DOM_KEYNAME_META "Meta"
 | |
| #define NS_DOM_KEYNAME_NUMLOCK "NumLock"
 | |
| #define NS_DOM_KEYNAME_SCROLLLOCK "ScrollLock"
 | |
| #define NS_DOM_KEYNAME_SHIFT "Shift"
 | |
| #define NS_DOM_KEYNAME_SYMBOL "Symbol"
 | |
| #define NS_DOM_KEYNAME_SYMBOLLOCK "SymbolLock"
 | |
| #define NS_DOM_KEYNAME_OS "OS"
 | |
| 
 | |
| /******************************************************************************
 | |
|  * mozilla::Modifiers
 | |
|  ******************************************************************************/
 | |
| 
 | |
| typedef uint16_t Modifiers;
 | |
| 
 | |
| class MOZ_STACK_CLASS GetModifiersName final : public nsAutoCString {
 | |
|  public:
 | |
|   explicit GetModifiersName(Modifiers aModifiers) {
 | |
|     if (aModifiers & MODIFIER_ALT) {
 | |
|       AssignLiteral(NS_DOM_KEYNAME_ALT);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_ALTGRAPH) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_ALTGRAPH);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_CAPSLOCK) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_CAPSLOCK);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_CONTROL) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_CONTROL);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_FN) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_FN);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_FNLOCK) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_FNLOCK);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_META) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_META);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_NUMLOCK) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_NUMLOCK);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_SCROLLLOCK) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_SCROLLLOCK);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_SHIFT) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_SHIFT);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_SYMBOL) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_SYMBOL);
 | |
|     }
 | |
|     if (aModifiers & MODIFIER_SYMBOLLOCK) {
 | |
|       MaybeAppendSeparator();
 | |
|       AppendLiteral(NS_DOM_KEYNAME_SYMBOLLOCK);
 | |
|     }
 | |
|     if (IsEmpty()) {
 | |
|       AssignLiteral("none");
 | |
|     }
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   void MaybeAppendSeparator() {
 | |
|     if (!IsEmpty()) {
 | |
|       AppendLiteral(" | ");
 | |
|     }
 | |
|   }
 | |
| };
 | |
| 
 | |
| /******************************************************************************
 | |
|  * mozilla::WidgetInputEvent
 | |
|  ******************************************************************************/
 | |
| 
 | |
| class WidgetInputEvent : public WidgetGUIEvent {
 | |
|  protected:
 | |
|   WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
 | |
|                    EventClassID aEventClassID,
 | |
|                    const WidgetEventTime* aTime = nullptr)
 | |
|       : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID, aTime),
 | |
|         mModifiers(0) {}
 | |
| 
 | |
|   WidgetInputEvent() : mModifiers(0) {}
 | |
| 
 | |
|  public:
 | |
|   virtual WidgetInputEvent* AsInputEvent() override { return this; }
 | |
| 
 | |
|   WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
 | |
|                    const WidgetEventTime* aTime = nullptr)
 | |
|       : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eInputEventClass, aTime),
 | |
|         mModifiers(0) {}
 | |
| 
 | |
|   virtual WidgetEvent* Duplicate() const override {
 | |
|     MOZ_ASSERT(mClass == eInputEventClass,
 | |
|                "Duplicate() must be overridden by sub class");
 | |
|     // Not copying widget, it is a weak reference.
 | |
|     WidgetInputEvent* result =
 | |
|         new WidgetInputEvent(false, mMessage, nullptr, this);
 | |
|     result->AssignInputEventData(*this, true);
 | |
|     result->mFlags = mFlags;
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns a modifier of "Accel" virtual modifier which is used for shortcut
 | |
|    * key.
 | |
|    */
 | |
|   static Modifier AccelModifier();
 | |
| 
 | |
|   /**
 | |
|    * GetModifier() returns a modifier flag which is activated by aDOMKeyName.
 | |
|    */
 | |
|   static Modifier GetModifier(const nsAString& aDOMKeyName);
 | |
| 
 | |
|   // true indicates the accel key on the environment is down
 | |
|   bool IsAccel() const { return ((mModifiers & AccelModifier()) != 0); }
 | |
| 
 | |
|   // true indicates the shift key is down
 | |
|   bool IsShift() const { return ((mModifiers & MODIFIER_SHIFT) != 0); }
 | |
|   // true indicates the control key is down
 | |
|   bool IsControl() const { return ((mModifiers & MODIFIER_CONTROL) != 0); }
 | |
|   // true indicates the alt key is down
 | |
|   bool IsAlt() const { return ((mModifiers & MODIFIER_ALT) != 0); }
 | |
|   // true indicates the meta key is down (Command key on macOS, Windows logo key
 | |
|   // on Windows, Super/Hyper key on Linux, Meta key on Android).
 | |
|   bool IsMeta() const { return ((mModifiers & MODIFIER_META) != 0); }
 | |
|   // true indicates the alt graph key is down
 | |
|   // NOTE: on Mac, the option key press causes both IsAlt() and IsAltGrpah()
 | |
|   //       return true.
 | |
|   bool IsAltGraph() const { return ((mModifiers & MODIFIER_ALTGRAPH) != 0); }
 | |
|   // true indicates the CapLock LED is turn on.
 | |
|   bool IsCapsLocked() const { return ((mModifiers & MODIFIER_CAPSLOCK) != 0); }
 | |
|   // true indicates the NumLock LED is turn on.
 | |
|   bool IsNumLocked() const { return ((mModifiers & MODIFIER_NUMLOCK) != 0); }
 | |
|   // true indicates the ScrollLock LED is turn on.
 | |
|   bool IsScrollLocked() const {
 | |
|     return ((mModifiers & MODIFIER_SCROLLLOCK) != 0);
 | |
|   }
 | |
| 
 | |
|   // true indicates the Fn key is down, but this is not supported by native
 | |
|   // key event on any platform.
 | |
|   bool IsFn() const { return ((mModifiers & MODIFIER_FN) != 0); }
 | |
|   // true indicates the FnLock LED is turn on, but we don't know such
 | |
|   // keyboards nor platforms.
 | |
|   bool IsFnLocked() const { return ((mModifiers & MODIFIER_FNLOCK) != 0); }
 | |
|   // true indicates the Symbol is down, but this is not supported by native
 | |
|   // key event on any platforms.
 | |
|   bool IsSymbol() const { return ((mModifiers & MODIFIER_SYMBOL) != 0); }
 | |
|   // true indicates the SymbolLock LED is turn on, but we don't know such
 | |
|   // keyboards nor platforms.
 | |
|   bool IsSymbolLocked() const {
 | |
|     return ((mModifiers & MODIFIER_SYMBOLLOCK) != 0);
 | |
|   }
 | |
| 
 | |
|   void InitBasicModifiers(bool aCtrlKey, bool aAltKey, bool aShiftKey,
 | |
|                           bool aMetaKey) {
 | |
|     mModifiers = 0;
 | |
|     if (aCtrlKey) {
 | |
|       mModifiers |= MODIFIER_CONTROL;
 | |
|     }
 | |
|     if (aAltKey) {
 | |
|       mModifiers |= MODIFIER_ALT;
 | |
|     }
 | |
|     if (aShiftKey) {
 | |
|       mModifiers |= MODIFIER_SHIFT;
 | |
|     }
 | |
|     if (aMetaKey) {
 | |
|       mModifiers |= MODIFIER_META;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Modifiers mModifiers;
 | |
| 
 | |
|   void AssignInputEventData(const WidgetInputEvent& aEvent, bool aCopyTargets) {
 | |
|     AssignGUIEventData(aEvent, aCopyTargets);
 | |
| 
 | |
|     mModifiers = aEvent.mModifiers;
 | |
|   }
 | |
| };
 | |
| 
 | |
| /******************************************************************************
 | |
|  * mozilla::InternalUIEvent
 | |
|  *
 | |
|  * XXX Why this inherits WidgetGUIEvent rather than WidgetEvent?
 | |
|  ******************************************************************************/
 | |
| 
 | |
| class InternalUIEvent : public WidgetGUIEvent {
 | |
|  protected:
 | |
|   InternalUIEvent() : mDetail(0), mCausedByUntrustedEvent(false) {}
 | |
| 
 | |
|   InternalUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
 | |
|                   EventClassID aEventClassID,
 | |
|                   const WidgetEventTime* aTime = nullptr)
 | |
|       : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID, aTime),
 | |
|         mDetail(0),
 | |
|         mCausedByUntrustedEvent(false) {}
 | |
| 
 | |
|   InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
 | |
|                   EventClassID aEventClassID,
 | |
|                   const WidgetEventTime* aTime = nullptr)
 | |
|       : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, aEventClassID, aTime),
 | |
|         mDetail(0),
 | |
|         mCausedByUntrustedEvent(false) {}
 | |
| 
 | |
|  public:
 | |
|   virtual InternalUIEvent* AsUIEvent() override { return this; }
 | |
| 
 | |
|   /**
 | |
|    * If the UIEvent is caused by another event (e.g., click event),
 | |
|    * aEventCausesThisEvent should be the event.  If there is no such event,
 | |
|    * this should be nullptr.
 | |
|    */
 | |
|   InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
 | |
|                   const WidgetEvent* aEventCausesThisEvent,
 | |
|                   const WidgetEventTime* aTime = nullptr)
 | |
|       : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, eUIEventClass, aTime),
 | |
|         mDetail(0),
 | |
|         mCausedByUntrustedEvent(aEventCausesThisEvent &&
 | |
|                                 !aEventCausesThisEvent->IsTrusted()) {}
 | |
| 
 | |
|   virtual WidgetEvent* Duplicate() const override {
 | |
|     MOZ_ASSERT(mClass == eUIEventClass,
 | |
|                "Duplicate() must be overridden by sub class");
 | |
|     InternalUIEvent* result =
 | |
|         new InternalUIEvent(false, mMessage, nullptr, this);
 | |
|     result->AssignUIEventData(*this, true);
 | |
|     result->mFlags = mFlags;
 | |
|     return result;
 | |
|   }
 | |
| 
 | |
|   int32_t mDetail;
 | |
|   // mCausedByUntrustedEvent is true if the event is caused by untrusted event.
 | |
|   bool mCausedByUntrustedEvent;
 | |
| 
 | |
|   // If you check the event is a trusted event and NOT caused by an untrusted
 | |
|   // event, IsTrustable() returns what you expected.
 | |
|   bool IsTrustable() const { return IsTrusted() && !mCausedByUntrustedEvent; }
 | |
| 
 | |
|   void AssignUIEventData(const InternalUIEvent& aEvent, bool aCopyTargets) {
 | |
|     AssignGUIEventData(aEvent, aCopyTargets);
 | |
| 
 | |
|     mDetail = aEvent.mDetail;
 | |
|     mCausedByUntrustedEvent = aEvent.mCausedByUntrustedEvent;
 | |
|   }
 | |
| };
 | |
| 
 | |
| }  // namespace mozilla
 | |
| 
 | |
| #endif  // mozilla_BasicEvents_h__
 |