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