Bug 1737746 - Use Permission spec's PermissionState r=mt,peterv
[gecko.git] / widget / BasicEvents.h
blob52fc2009f5730f40dc1387f7da444a478111d0c6
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_BasicEvents_h__
7 #define mozilla_BasicEvents_h__
9 #include <stdint.h>
10 #include <type_traits>
12 #include "mozilla/EventForwards.h"
13 #include "mozilla/TimeStamp.h"
14 #include "mozilla/dom/EventTarget.h"
15 #include "mozilla/layers/LayersTypes.h"
16 #include "nsCOMPtr.h"
17 #include "nsAtom.h"
18 #include "nsISupportsImpl.h"
19 #include "nsIWidget.h"
20 #include "nsString.h"
21 #include "Units.h"
23 #ifdef DEBUG
24 # include "nsXULAppAPI.h"
25 #endif // #ifdef DEBUG
27 class nsIPrincipal;
29 namespace IPC {
30 template <typename T>
31 struct ParamTraits;
32 } // namespace IPC
34 namespace mozilla {
36 class EventTargetChainItem;
38 enum class CrossProcessForwarding {
39 // eStop prevents the event to be sent to remote process.
40 eStop,
41 // eAllow keeps current state of the event whether it's sent to remote
42 // process. In other words, eAllow does NOT mean that making the event
43 // sent to remote process when IsCrossProcessForwardingStopped() returns
44 // true.
45 eAllow,
48 /******************************************************************************
49 * mozilla::BaseEventFlags
51 * BaseEventFlags must be a POD struct for safe to use memcpy (including
52 * in ParamTraits<BaseEventFlags>). So don't make virtual methods, constructor,
53 * destructor and operators.
54 * This is necessary for VC which is NOT C++0x compiler.
55 ******************************************************************************/
57 struct BaseEventFlags {
58 public:
59 // If mIsTrusted is true, the event is a trusted event. Otherwise, it's
60 // an untrusted event.
61 bool mIsTrusted : 1;
62 // If mInBubblingPhase is true, the event is in bubbling phase or target
63 // phase.
64 bool mInBubblingPhase : 1;
65 // If mInCapturePhase is true, the event is in capture phase or target phase.
66 bool mInCapturePhase : 1;
67 // If 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;
166 // Flags managing state of propagation between processes.
167 // Note the the following flags shouldn't be referred directly. Use utility
168 // methods instead.
170 // If mNoRemoteProcessDispatch is true, the event is not allowed to be sent
171 // to remote process.
172 bool mNoRemoteProcessDispatch : 1;
173 // If mWantReplyFromContentProcess is true, the event will be redispatched
174 // in the parent process after the content process has handled it. Useful
175 // for when the parent process need the know first how the event was used
176 // by content before handling it itself.
177 bool mWantReplyFromContentProcess : 1;
178 // If mPostedToRemoteProcess is true, the event has been posted to the
179 // remote process (but it's not handled yet if it's not a duplicated event
180 // instance).
181 bool mPostedToRemoteProcess : 1;
182 // If mCameFromAnotherProcess is true, the event came from another process.
183 bool mCameFromAnotherProcess : 1;
185 // At lease one of the event in the event path had non privileged click
186 // listener.
187 bool mHadNonPrivilegedClickListeners : 1;
189 // If the event is being handled in target phase, returns true.
190 inline bool InTargetPhase() const {
191 return (mInBubblingPhase && mInCapturePhase);
195 * Helper methods for methods of DOM Event.
197 inline void StopPropagation() { mPropagationStopped = true; }
198 inline void StopImmediatePropagation() {
199 StopPropagation();
200 mImmediatePropagationStopped = true;
202 inline void PreventDefault(bool aCalledByDefaultHandler = true) {
203 if (!mCancelable) {
204 return;
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;
218 // This should be used only before dispatching events into the DOM tree.
219 inline void PreventDefaultBeforeDispatch(
220 CrossProcessForwarding aCrossProcessForwarding) {
221 if (!mCancelable) {
222 return;
224 mDefaultPrevented = true;
225 if (aCrossProcessForwarding == CrossProcessForwarding::eStop) {
226 StopCrossProcessForwarding();
229 inline bool DefaultPrevented() const { return mDefaultPrevented; }
230 inline bool DefaultPreventedByContent() const {
231 MOZ_ASSERT(!mDefaultPreventedByContent || DefaultPrevented());
232 return mDefaultPreventedByContent;
234 inline bool IsTrusted() const { return mIsTrusted; }
235 inline bool PropagationStopped() const { return mPropagationStopped; }
237 // Helper methods to access flags managing state of propagation between
238 // processes.
241 * Prevent to be dispatched to remote process.
243 inline void StopCrossProcessForwarding() {
244 MOZ_ASSERT(!mPostedToRemoteProcess);
245 mNoRemoteProcessDispatch = true;
246 mWantReplyFromContentProcess = false;
249 * Return true if the event shouldn't be dispatched to remote process.
251 inline bool IsCrossProcessForwardingStopped() const {
252 return mNoRemoteProcessDispatch;
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.
264 inline void MarkAsWaitingReplyFromRemoteProcess() {
265 MOZ_ASSERT(!mPostedToRemoteProcess);
266 mNoRemoteProcessDispatch = false;
267 mWantReplyFromContentProcess = true;
270 * Reset "waiting reply from remote process" state. This is useful when
271 * you dispatch a copy of an event coming from different process.
273 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;
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.
286 inline bool IsWaitingReplyFromRemoteProcess() const {
287 return !mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
290 * Mark the event as already handled in the remote process. This should be
291 * called when initializing reply events.
293 inline void MarkAsHandledInRemoteProcess() {
294 mNoRemoteProcessDispatch = true;
295 mWantReplyFromContentProcess = true;
296 mPostedToRemoteProcess = false;
299 * Return true if the event has already been handled in the remote process.
301 inline bool IsHandledInRemoteProcess() const {
302 return mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
305 * Return true if the event should be sent back to its parent process.
307 inline bool WantReplyFromContentProcess() const {
308 MOZ_ASSERT(!XRE_IsParentProcess());
309 return IsWaitingReplyFromRemoteProcess();
312 * Mark the event has already posted to a remote process.
314 inline void MarkAsPostedToRemoteProcess() {
315 MOZ_ASSERT(!IsCrossProcessForwardingStopped());
316 mPostedToRemoteProcess = true;
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.
322 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;
331 // mDispatchedAtLeastOnce indicates the state in current process.
332 mDispatchedAtLeastOnce = false;
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.
342 inline bool HasBeenPostedToRemoteProcess() const {
343 return mPostedToRemoteProcess;
346 * Return true if the event came from another process.
348 inline bool CameFromAnotherProcess() const { return mCameFromAnotherProcess; }
350 * Mark the event as coming from another process.
352 inline void MarkAsComingFromAnotherProcess() {
353 mCameFromAnotherProcess = true;
356 * Mark the event is reserved by chrome. I.e., shouldn't be dispatched to
357 * content because it shouldn't be cancelable.
359 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;
373 * Return true if the event is reserved by chrome.
375 inline bool IsReservedByChrome() const {
376 MOZ_ASSERT(!mIsReservedByChrome || (IsCrossProcessForwardingStopped() &&
377 mOnlySystemGroupDispatchInContent));
378 return mIsReservedByChrome;
381 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;
385 inline void Union(const BaseEventFlags& aOther) {
386 RawFlags rawFlags = GetRawFlags() | aOther.GetRawFlags();
387 SetRawFlags(rawFlags);
390 private:
391 typedef uint64_t RawFlags;
393 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));
398 inline RawFlags GetRawFlags() const {
399 RawFlags result = 0;
400 memcpy(&result, this, sizeof(BaseEventFlags));
401 return result;
405 /******************************************************************************
406 * mozilla::EventFlags
407 ******************************************************************************/
409 struct EventFlags : public BaseEventFlags {
410 EventFlags() { Clear(); }
413 /******************************************************************************
414 * mozilla::WidgetEventTime
415 ******************************************************************************/
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;
426 WidgetEventTime() : mTime(0), mTimeStamp(TimeStamp::Now()) {}
428 WidgetEventTime(uint64_t aTime, TimeStamp aTimeStamp)
429 : mTime(aTime), mTimeStamp(aTimeStamp) {}
431 void AssignEventTime(const WidgetEventTime& aOther) {
432 mTime = aOther.mTime;
433 mTimeStamp = aOther.mTimeStamp;
437 /******************************************************************************
438 * mozilla::WidgetEvent
439 ******************************************************************************/
441 class WidgetEvent : public WidgetEventTime {
442 private:
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;
491 mFlags.mBubbles = true;
492 break;
496 protected:
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();
516 WidgetEvent() : WidgetEventTime(), mPath(nullptr) {
517 MOZ_COUNT_CTOR(WidgetEvent);
520 public:
521 WidgetEvent(bool aIsTrusted, EventMessage aMessage)
522 : WidgetEvent(aIsTrusted, aMessage, eBasicEventClass) {}
524 MOZ_COUNTED_DTOR_VIRTUAL(WidgetEvent)
526 WidgetEvent(const WidgetEvent& aOther) : WidgetEventTime() {
527 MOZ_COUNT_CTOR(WidgetEvent);
528 *this = aOther;
530 WidgetEvent& operator=(const WidgetEvent& aOther) = default;
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);
550 WidgetEvent& operator=(WidgetEvent&& aOther) = default;
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;
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;
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;
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;
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;
596 /// The possible related target
597 nsCOMPtr<dom::EventTarget> mRelatedTarget;
598 nsCOMPtr<dom::EventTarget> mOriginalRelatedTarget;
600 nsTArray<EventTargetChainItem>* mPath;
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;
607 dom::EventTarget* GetDOMEventTarget() const;
608 dom::EventTarget* GetCurrentDOMEventTarget() const;
609 dom::EventTarget* GetOriginalDOMEventTarget() const;
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;
631 * Helper methods for methods of DOM Event.
633 void StopPropagation() { mFlags.StopPropagation(); }
634 void StopImmediatePropagation() { mFlags.StopImmediatePropagation(); }
635 void PreventDefault(bool aCalledByDefaultHandler = true,
636 nsIPrincipal* aPrincipal = nullptr);
638 void PreventDefaultBeforeDispatch(
639 CrossProcessForwarding aCrossProcessForwarding) {
640 mFlags.PreventDefaultBeforeDispatch(aCrossProcessForwarding);
642 bool DefaultPrevented() const { return mFlags.DefaultPrevented(); }
643 bool DefaultPreventedByContent() const {
644 return mFlags.DefaultPreventedByContent();
646 bool IsTrusted() const { return mFlags.IsTrusted(); }
647 bool PropagationStopped() const { return mFlags.PropagationStopped(); }
650 * Prevent to be dispatched to remote process.
652 inline void StopCrossProcessForwarding() {
653 mFlags.StopCrossProcessForwarding();
656 * Return true if the event shouldn't be dispatched to remote process.
658 inline bool IsCrossProcessForwardingStopped() const {
659 return mFlags.IsCrossProcessForwardingStopped();
662 * Mark the event as waiting reply from remote process.
663 * Note that this also stops immediate propagation in current process.
665 inline void MarkAsWaitingReplyFromRemoteProcess() {
666 mFlags.MarkAsWaitingReplyFromRemoteProcess();
669 * Reset "waiting reply from remote process" state. This is useful when
670 * you dispatch a copy of an event coming from different process.
672 inline void ResetWaitingReplyFromRemoteProcessState() {
673 mFlags.ResetWaitingReplyFromRemoteProcessState();
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.
679 inline bool IsWaitingReplyFromRemoteProcess() const {
680 return mFlags.IsWaitingReplyFromRemoteProcess();
683 * Mark the event as already handled in the remote process. This should be
684 * called when initializing reply events.
686 inline void MarkAsHandledInRemoteProcess() {
687 mFlags.MarkAsHandledInRemoteProcess();
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.
693 inline bool IsHandledInRemoteProcess() const {
694 return mFlags.IsHandledInRemoteProcess();
697 * Return true if the event should be sent back to its parent process.
698 * So, usual event handlers shouldn't call this.
700 inline bool WantReplyFromContentProcess() const {
701 return mFlags.WantReplyFromContentProcess();
704 * Mark the event has already posted to a remote process.
706 inline void MarkAsPostedToRemoteProcess() {
707 mFlags.MarkAsPostedToRemoteProcess();
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.
713 inline void ResetCrossProcessDispatchingState() {
714 mFlags.ResetCrossProcessDispatchingState();
717 * Return true if the event has been posted to a remote process.
719 inline bool HasBeenPostedToRemoteProcess() const {
720 return mFlags.HasBeenPostedToRemoteProcess();
723 * Return true if the event came from another process.
725 inline bool CameFromAnotherProcess() const {
726 return mFlags.CameFromAnotherProcess();
729 * Mark the event as coming from another process.
731 inline void MarkAsComingFromAnotherProcess() {
732 mFlags.MarkAsComingFromAnotherProcess();
735 * Mark the event is reserved by chrome. I.e., shouldn't be dispatched to
736 * content because it shouldn't be cancelable.
738 inline void MarkAsReservedByChrome() { mFlags.MarkAsReservedByChrome(); }
740 * Return true if the event is reserved by chrome.
742 inline bool IsReservedByChrome() const { return mFlags.IsReservedByChrome(); }
745 * Utils for checking event types
749 * As*Event() returns the pointer of the instance only when the instance is
750 * the class or one of its derived class.
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;
757 #include "mozilla/EventClassList.h"
759 #undef NS_EVENT_CLASS
760 #undef NS_ROOT_EVENT_CLASS
763 * Returns true if the event is a query content event.
765 bool IsQueryContentEvent() const;
767 * Returns true if the event is a selection event.
769 bool IsSelectionEvent() const;
771 * Returns true if the event is a content command event.
773 bool IsContentCommandEvent() const;
776 * Returns true if the event mMessage is one of mouse events.
778 bool HasMouseEventMessage() const;
780 * Returns true if the event mMessage is one of drag events.
782 bool HasDragEventMessage() const;
784 * Returns true if aMessage or mMessage is one of key events.
786 static bool IsKeyEventMessage(EventMessage aMessage);
787 bool HasKeyEventMessage() const { return IsKeyEventMessage(mMessage); }
789 * Returns true if the event mMessage is one of composition events or text
790 * event.
792 bool HasIMEEventMessage() const;
794 * Returns true if the event mMessage is one of plugin activation events.
796 bool HasPluginActivationEventMessage() const;
799 * Returns true if the event can be sent to remote process.
801 bool CanBeSentToRemoteProcess() const;
803 * Returns true if the original target is a remote process and the event
804 * will be posted to the remote process later.
806 bool WillBeSentToRemoteProcess() const;
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.
812 bool IsIMERelatedEvent() const;
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.
819 bool IsUsingCoordinates() const;
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.
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.
832 bool IsTargetedAtFocusedWindow() const;
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.
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.
844 bool IsTargetedAtFocusedContent() const;
846 * Whether the event should cause a DOM event.
848 bool IsAllowedToDispatchDOMEvent() const;
850 * Whether the event should be dispatched in system group.
852 bool IsAllowedToDispatchInSystemGroup() const;
854 * Whether the event should be blocked for fingerprinting resistance.
856 bool IsBlockedForFingerprintingResistance() const;
858 * Initialize mComposed
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;
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");
995 void SetComposed(bool aComposed) { mFlags.mComposed = aComposed; }
997 void SetDefaultComposedInNativeAnonymousContent() {
998 // For compatibility concerns, we set mComposedInNativeAnonymousContent to
999 // false for those events we want to stop propagation.
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;
1009 bool IsUserAction() const;
1012 /******************************************************************************
1013 * mozilla::NativeEventData
1015 * WidgetGUIEvent's mPluginEvent member used to be a void* pointer,
1016 * used to reference external, OS-specific data structures.
1018 * That void* pointer wasn't serializable by itself, causing
1019 * certain plugin events not to function in e10s. See bug 586656.
1021 * To make this serializable, we changed this void* pointer into
1022 * a proper buffer, and copy these external data structures into this
1023 * buffer.
1025 * That buffer is NativeEventData::mBuffer below.
1027 * We wrap this in that NativeEventData class providing operators to
1028 * be compatible with existing code that was written around
1029 * the old void* field.
1030 ******************************************************************************/
1032 class NativeEventData final {
1033 CopyableTArray<uint8_t> mBuffer;
1035 friend struct IPC::ParamTraits<mozilla::NativeEventData>;
1037 public:
1038 explicit operator bool() const { return !mBuffer.IsEmpty(); }
1040 template <typename T>
1041 explicit operator const T*() const {
1042 return mBuffer.IsEmpty() ? nullptr
1043 : reinterpret_cast<const T*>(mBuffer.Elements());
1046 template <typename T>
1047 void Copy(const T& other) {
1048 static_assert(!std::is_pointer_v<T>, "Don't want a pointer!");
1049 mBuffer.SetLength(sizeof(T));
1050 memcpy(mBuffer.Elements(), &other, mBuffer.Length());
1053 void Clear() { mBuffer.Clear(); }
1056 /******************************************************************************
1057 * mozilla::WidgetGUIEvent
1058 ******************************************************************************/
1060 class WidgetGUIEvent : public WidgetEvent {
1061 protected:
1062 WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1063 EventClassID aEventClassID)
1064 : WidgetEvent(aIsTrusted, aMessage, aEventClassID), mWidget(aWidget) {}
1066 WidgetGUIEvent() = default;
1068 public:
1069 virtual WidgetGUIEvent* AsGUIEvent() override { return this; }
1071 WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
1072 : WidgetEvent(aIsTrusted, aMessage, eGUIEventClass), mWidget(aWidget) {}
1074 virtual WidgetEvent* Duplicate() const override {
1075 MOZ_ASSERT(mClass == eGUIEventClass,
1076 "Duplicate() must be overridden by sub class");
1077 // Not copying widget, it is a weak reference.
1078 WidgetGUIEvent* result = new WidgetGUIEvent(false, mMessage, nullptr);
1079 result->AssignGUIEventData(*this, true);
1080 result->mFlags = mFlags;
1081 return result;
1084 // Originator of the event
1085 nsCOMPtr<nsIWidget> mWidget;
1088 * Ideally though, we wouldn't allow arbitrary reinterpret_cast'ing here;
1089 * instead, we would at least store type information here so that
1090 * this class can't be used to reinterpret one structure type into another.
1091 * We can also wonder if it would be possible to properly extend
1092 * WidgetGUIEvent and other Event classes to remove the need for this
1093 * mPluginEvent field.
1095 typedef NativeEventData PluginEvent;
1097 // Event for NPAPI plugin
1098 PluginEvent mPluginEvent;
1100 void AssignGUIEventData(const WidgetGUIEvent& aEvent, bool aCopyTargets) {
1101 AssignEventData(aEvent, aCopyTargets);
1103 // widget should be initialized with the constructor.
1105 mPluginEvent = aEvent.mPluginEvent;
1109 /******************************************************************************
1110 * mozilla::Modifier
1112 * All modifier keys should be defined here. This is used for managing
1113 * modifier states for DOM Level 3 or later.
1114 ******************************************************************************/
1116 enum Modifier {
1117 MODIFIER_NONE = 0x0000,
1118 MODIFIER_ALT = 0x0001,
1119 MODIFIER_ALTGRAPH = 0x0002,
1120 MODIFIER_CAPSLOCK = 0x0004,
1121 MODIFIER_CONTROL = 0x0008,
1122 MODIFIER_FN = 0x0010,
1123 MODIFIER_FNLOCK = 0x0020,
1124 MODIFIER_META = 0x0040,
1125 MODIFIER_NUMLOCK = 0x0080,
1126 MODIFIER_SCROLLLOCK = 0x0100,
1127 MODIFIER_SHIFT = 0x0200,
1128 MODIFIER_SYMBOL = 0x0400,
1129 MODIFIER_SYMBOLLOCK = 0x0800,
1130 MODIFIER_OS = 0x1000
1133 /******************************************************************************
1134 * Modifier key names.
1135 ******************************************************************************/
1137 #define NS_DOM_KEYNAME_ALT "Alt"
1138 #define NS_DOM_KEYNAME_ALTGRAPH "AltGraph"
1139 #define NS_DOM_KEYNAME_CAPSLOCK "CapsLock"
1140 #define NS_DOM_KEYNAME_CONTROL "Control"
1141 #define NS_DOM_KEYNAME_FN "Fn"
1142 #define NS_DOM_KEYNAME_FNLOCK "FnLock"
1143 #define NS_DOM_KEYNAME_META "Meta"
1144 #define NS_DOM_KEYNAME_NUMLOCK "NumLock"
1145 #define NS_DOM_KEYNAME_SCROLLLOCK "ScrollLock"
1146 #define NS_DOM_KEYNAME_SHIFT "Shift"
1147 #define NS_DOM_KEYNAME_SYMBOL "Symbol"
1148 #define NS_DOM_KEYNAME_SYMBOLLOCK "SymbolLock"
1149 #define NS_DOM_KEYNAME_OS "OS"
1151 /******************************************************************************
1152 * mozilla::Modifiers
1153 ******************************************************************************/
1155 typedef uint16_t Modifiers;
1157 class MOZ_STACK_CLASS GetModifiersName final : public nsAutoCString {
1158 public:
1159 explicit GetModifiersName(Modifiers aModifiers) {
1160 if (aModifiers & MODIFIER_ALT) {
1161 AssignLiteral(NS_DOM_KEYNAME_ALT);
1163 if (aModifiers & MODIFIER_ALTGRAPH) {
1164 MaybeAppendSeparator();
1165 AppendLiteral(NS_DOM_KEYNAME_ALTGRAPH);
1167 if (aModifiers & MODIFIER_CAPSLOCK) {
1168 MaybeAppendSeparator();
1169 AppendLiteral(NS_DOM_KEYNAME_CAPSLOCK);
1171 if (aModifiers & MODIFIER_CONTROL) {
1172 MaybeAppendSeparator();
1173 AppendLiteral(NS_DOM_KEYNAME_CONTROL);
1175 if (aModifiers & MODIFIER_FN) {
1176 MaybeAppendSeparator();
1177 AppendLiteral(NS_DOM_KEYNAME_FN);
1179 if (aModifiers & MODIFIER_FNLOCK) {
1180 MaybeAppendSeparator();
1181 AppendLiteral(NS_DOM_KEYNAME_FNLOCK);
1183 if (aModifiers & MODIFIER_META) {
1184 MaybeAppendSeparator();
1185 AppendLiteral(NS_DOM_KEYNAME_META);
1187 if (aModifiers & MODIFIER_NUMLOCK) {
1188 MaybeAppendSeparator();
1189 AppendLiteral(NS_DOM_KEYNAME_NUMLOCK);
1191 if (aModifiers & MODIFIER_SCROLLLOCK) {
1192 MaybeAppendSeparator();
1193 AppendLiteral(NS_DOM_KEYNAME_SCROLLLOCK);
1195 if (aModifiers & MODIFIER_SHIFT) {
1196 MaybeAppendSeparator();
1197 AppendLiteral(NS_DOM_KEYNAME_SHIFT);
1199 if (aModifiers & MODIFIER_SYMBOL) {
1200 MaybeAppendSeparator();
1201 AppendLiteral(NS_DOM_KEYNAME_SYMBOL);
1203 if (aModifiers & MODIFIER_SYMBOLLOCK) {
1204 MaybeAppendSeparator();
1205 AppendLiteral(NS_DOM_KEYNAME_SYMBOLLOCK);
1207 if (aModifiers & MODIFIER_OS) {
1208 MaybeAppendSeparator();
1209 AppendLiteral(NS_DOM_KEYNAME_OS);
1211 if (IsEmpty()) {
1212 AssignLiteral("none");
1216 private:
1217 void MaybeAppendSeparator() {
1218 if (!IsEmpty()) {
1219 AppendLiteral(" | ");
1224 /******************************************************************************
1225 * mozilla::WidgetInputEvent
1226 ******************************************************************************/
1228 class WidgetInputEvent : public WidgetGUIEvent {
1229 protected:
1230 WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1231 EventClassID aEventClassID)
1232 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID),
1233 mModifiers(0) {}
1235 WidgetInputEvent() : mModifiers(0) {}
1237 public:
1238 virtual WidgetInputEvent* AsInputEvent() override { return this; }
1240 WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
1241 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eInputEventClass),
1242 mModifiers(0) {}
1244 virtual WidgetEvent* Duplicate() const override {
1245 MOZ_ASSERT(mClass == eInputEventClass,
1246 "Duplicate() must be overridden by sub class");
1247 // Not copying widget, it is a weak reference.
1248 WidgetInputEvent* result = new WidgetInputEvent(false, mMessage, nullptr);
1249 result->AssignInputEventData(*this, true);
1250 result->mFlags = mFlags;
1251 return result;
1255 * Returns a modifier of "Accel" virtual modifier which is used for shortcut
1256 * key.
1258 static Modifier AccelModifier();
1261 * GetModifier() returns a modifier flag which is activated by aDOMKeyName.
1263 static Modifier GetModifier(const nsAString& aDOMKeyName);
1265 // true indicates the accel key on the environment is down
1266 bool IsAccel() const { return ((mModifiers & AccelModifier()) != 0); }
1268 // true indicates the shift key is down
1269 bool IsShift() const { return ((mModifiers & MODIFIER_SHIFT) != 0); }
1270 // true indicates the control key is down
1271 bool IsControl() const { return ((mModifiers & MODIFIER_CONTROL) != 0); }
1272 // true indicates the alt key is down
1273 bool IsAlt() const { return ((mModifiers & MODIFIER_ALT) != 0); }
1274 // true indicates the meta key is down (or, on Mac, the Command key)
1275 bool IsMeta() const { return ((mModifiers & MODIFIER_META) != 0); }
1276 // true indicates the win key is down on Windows. Or the Super or Hyper key
1277 // is down on Linux.
1278 bool IsOS() const { return ((mModifiers & MODIFIER_OS) != 0); }
1279 // true indicates the alt graph key is down
1280 // NOTE: on Mac, the option key press causes both IsAlt() and IsAltGrpah()
1281 // return true.
1282 bool IsAltGraph() const { return ((mModifiers & MODIFIER_ALTGRAPH) != 0); }
1283 // true indicates the CapLock LED is turn on.
1284 bool IsCapsLocked() const { return ((mModifiers & MODIFIER_CAPSLOCK) != 0); }
1285 // true indicates the NumLock LED is turn on.
1286 bool IsNumLocked() const { return ((mModifiers & MODIFIER_NUMLOCK) != 0); }
1287 // true indicates the ScrollLock LED is turn on.
1288 bool IsScrollLocked() const {
1289 return ((mModifiers & MODIFIER_SCROLLLOCK) != 0);
1292 // true indicates the Fn key is down, but this is not supported by native
1293 // key event on any platform.
1294 bool IsFn() const { return ((mModifiers & MODIFIER_FN) != 0); }
1295 // true indicates the FnLock LED is turn on, but we don't know such
1296 // keyboards nor platforms.
1297 bool IsFnLocked() const { return ((mModifiers & MODIFIER_FNLOCK) != 0); }
1298 // true indicates the Symbol is down, but this is not supported by native
1299 // key event on any platforms.
1300 bool IsSymbol() const { return ((mModifiers & MODIFIER_SYMBOL) != 0); }
1301 // true indicates the SymbolLock LED is turn on, but we don't know such
1302 // keyboards nor platforms.
1303 bool IsSymbolLocked() const {
1304 return ((mModifiers & MODIFIER_SYMBOLLOCK) != 0);
1307 void InitBasicModifiers(bool aCtrlKey, bool aAltKey, bool aShiftKey,
1308 bool aMetaKey) {
1309 mModifiers = 0;
1310 if (aCtrlKey) {
1311 mModifiers |= MODIFIER_CONTROL;
1313 if (aAltKey) {
1314 mModifiers |= MODIFIER_ALT;
1316 if (aShiftKey) {
1317 mModifiers |= MODIFIER_SHIFT;
1319 if (aMetaKey) {
1320 mModifiers |= MODIFIER_META;
1324 Modifiers mModifiers;
1326 void AssignInputEventData(const WidgetInputEvent& aEvent, bool aCopyTargets) {
1327 AssignGUIEventData(aEvent, aCopyTargets);
1329 mModifiers = aEvent.mModifiers;
1333 /******************************************************************************
1334 * mozilla::InternalUIEvent
1336 * XXX Why this inherits WidgetGUIEvent rather than WidgetEvent?
1337 ******************************************************************************/
1339 class InternalUIEvent : public WidgetGUIEvent {
1340 protected:
1341 InternalUIEvent() : mDetail(0), mCausedByUntrustedEvent(false) {}
1343 InternalUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1344 EventClassID aEventClassID)
1345 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID),
1346 mDetail(0),
1347 mCausedByUntrustedEvent(false) {}
1349 InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1350 EventClassID aEventClassID)
1351 : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, aEventClassID),
1352 mDetail(0),
1353 mCausedByUntrustedEvent(false) {}
1355 public:
1356 virtual InternalUIEvent* AsUIEvent() override { return this; }
1359 * If the UIEvent is caused by another event (e.g., click event),
1360 * aEventCausesThisEvent should be the event. If there is no such event,
1361 * this should be nullptr.
1363 InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1364 const WidgetEvent* aEventCausesThisEvent)
1365 : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, eUIEventClass),
1366 mDetail(0),
1367 mCausedByUntrustedEvent(aEventCausesThisEvent &&
1368 !aEventCausesThisEvent->IsTrusted()) {}
1370 virtual WidgetEvent* Duplicate() const override {
1371 MOZ_ASSERT(mClass == eUIEventClass,
1372 "Duplicate() must be overridden by sub class");
1373 InternalUIEvent* result = new InternalUIEvent(false, mMessage, nullptr);
1374 result->AssignUIEventData(*this, true);
1375 result->mFlags = mFlags;
1376 return result;
1379 int32_t mDetail;
1380 // mCausedByUntrustedEvent is true if the event is caused by untrusted event.
1381 bool mCausedByUntrustedEvent;
1383 // If you check the event is a trusted event and NOT caused by an untrusted
1384 // event, IsTrustable() returns what you expected.
1385 bool IsTrustable() const { return IsTrusted() && !mCausedByUntrustedEvent; }
1387 void AssignUIEventData(const InternalUIEvent& aEvent, bool aCopyTargets) {
1388 AssignGUIEventData(aEvent, aCopyTargets);
1390 mDetail = aEvent.mDetail;
1391 mCausedByUntrustedEvent = aEvent.mCausedByUntrustedEvent;
1395 } // namespace mozilla
1397 #endif // mozilla_BasicEvents_h__