Bug 1550519 - Show a translucent parent highlight when a subgrid is highlighted....
[gecko.git] / widget / BasicEvents.h
blob026aaf60833e5ba2f5e3b051eadfb150ca2404f9
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_BasicEvents_h__
7 #define mozilla_BasicEvents_h__
9 #include <stdint.h>
11 #include "mozilla/dom/EventTarget.h"
12 #include "mozilla/layers/LayersTypes.h"
13 #include "mozilla/EventForwards.h"
14 #include "mozilla/TimeStamp.h"
15 #include "nsCOMPtr.h"
16 #include "nsAtom.h"
17 #include "nsISupportsImpl.h"
18 #include "nsIWidget.h"
19 #include "nsString.h"
20 #include "Units.h"
22 #ifdef DEBUG
23 # include "nsXULAppAPI.h"
24 #endif // #ifdef DEBUG
26 namespace IPC {
27 template <typename T>
28 struct ParamTraits;
29 } // namespace IPC
31 namespace mozilla {
33 class EventTargetChainItem;
35 enum class CrossProcessForwarding {
36 // eStop prevents the event to be sent to remote process.
37 eStop,
38 // eAllow keeps current state of the event whether it's sent to remote
39 // process. In other words, eAllow does NOT mean that making the event
40 // sent to remote process when IsCrossProcessForwardingStopped() returns
41 // true.
42 eAllow,
45 /******************************************************************************
46 * mozilla::BaseEventFlags
48 * BaseEventFlags must be a POD struct for safe to use memcpy (including
49 * in ParamTraits<BaseEventFlags>). So don't make virtual methods, constructor,
50 * destructor and operators.
51 * This is necessary for VC which is NOT C++0x compiler.
52 ******************************************************************************/
54 struct BaseEventFlags {
55 public:
56 // If mIsTrusted is true, the event is a trusted event. Otherwise, it's
57 // an untrusted event.
58 bool mIsTrusted : 1;
59 // If mInBubblingPhase is true, the event is in bubbling phase or target
60 // phase.
61 bool mInBubblingPhase : 1;
62 // If mInCapturePhase is true, the event is in capture phase or target phase.
63 bool mInCapturePhase : 1;
64 // If mInSystemGroup is true, the event is being dispatched in system group.
65 bool mInSystemGroup : 1;
66 // If mCancelable is true, the event can be consumed. I.e., calling
67 // dom::Event::PreventDefault() can prevent the default action.
68 bool mCancelable : 1;
69 // If mBubbles is true, the event can bubble. Otherwise, cannot be handled
70 // in bubbling phase.
71 bool mBubbles : 1;
72 // If mPropagationStopped is true, dom::Event::StopPropagation() or
73 // dom::Event::StopImmediatePropagation() has been called.
74 bool mPropagationStopped : 1;
75 // If mImmediatePropagationStopped is true,
76 // dom::Event::StopImmediatePropagation() has been called.
77 // Note that mPropagationStopped must be true when this is true.
78 bool mImmediatePropagationStopped : 1;
79 // If mDefaultPrevented is true, the event has been consumed.
80 // E.g., dom::Event::PreventDefault() has been called or
81 // the default action has been performed.
82 bool mDefaultPrevented : 1;
83 // If mDefaultPreventedByContent is true, the event has been
84 // consumed by content.
85 // Note that mDefaultPrevented must be true when this is true.
86 bool mDefaultPreventedByContent : 1;
87 // If mDefaultPreventedByChrome is true, the event has been
88 // consumed by chrome.
89 // Note that mDefaultPrevented must be true when this is true.
90 bool mDefaultPreventedByChrome : 1;
91 // mMultipleActionsPrevented may be used when default handling don't want to
92 // be prevented, but only one of the event targets should handle the event.
93 // For example, when a <label> element is in another <label> element and
94 // the first <label> element is clicked, that one may set this true.
95 // Then, the second <label> element won't handle the event.
96 bool mMultipleActionsPrevented : 1;
97 // Similar to above but expected to be used during PreHandleEvent phase.
98 bool mMultiplePreActionsPrevented : 1;
99 // If mIsBeingDispatched is true, the DOM event created from the event is
100 // dispatching into the DOM tree and not completed.
101 bool mIsBeingDispatched : 1;
102 // If mDispatchedAtLeastOnce is true, the event has been dispatched
103 // as a DOM event and the dispatch has been completed.
104 bool mDispatchedAtLeastOnce : 1;
105 // If mIsSynthesizedForTests is true, the event has been synthesized for
106 // automated tests or something hacky approach of an add-on.
107 bool mIsSynthesizedForTests : 1;
108 // If mExceptionWasRaised is true, one of the event handlers has raised an
109 // exception.
110 bool mExceptionWasRaised : 1;
111 // If mRetargetToNonNativeAnonymous is true and the target is in a non-native
112 // native anonymous subtree, the event target is set to mOriginalTarget.
113 bool mRetargetToNonNativeAnonymous : 1;
114 // If mNoContentDispatch is true, the event is never dispatched to the
115 // event handlers which are added to the contents, onfoo attributes and
116 // properties. Note that this flag is ignored when
117 // EventChainPreVisitor::mForceContentDispatch is set true. For exapmle,
118 // window and document object sets it true. Therefore, web applications
119 // can handle the event if they add event listeners to the window or the
120 // document.
121 // XXX This is an ancient and broken feature, don't use this for new bug
122 // as far as possible.
123 bool mNoContentDispatch : 1;
124 // If mOnlyChromeDispatch is true, the event is dispatched to only chrome.
125 bool mOnlyChromeDispatch : 1;
126 // Indicates if the key combination is reserved by chrome. This is set by
127 // MarkAsReservedByChrome().
128 bool mIsReservedByChrome : 1;
129 // If mOnlySystemGroupDispatchInContent is true, event listeners added to
130 // the default group for non-chrome EventTarget won't be called.
131 // Be aware, if this is true, EventDispatcher needs to check if each event
132 // listener is added to chrome node, so, don't set this to true for the
133 // events which are fired a lot of times like eMouseMove.
134 bool mOnlySystemGroupDispatchInContent : 1;
135 // If mOnlySystemGroupDispatch is true, the event will be dispatched only to
136 // event listeners added in the system group.
137 bool mOnlySystemGroupDispatch : 1;
138 // The event's action will be handled by APZ. The main thread should not
139 // perform its associated action.
140 bool mHandledByAPZ : 1;
141 // True if the event is currently being handled by an event listener that
142 // was registered as a passive listener.
143 bool mInPassiveListener : 1;
144 // If mComposed is true, the event fired by nodes in shadow DOM can cross the
145 // boundary of shadow DOM and light DOM.
146 bool mComposed : 1;
147 // Similar to mComposed. Set it to true to allow events cross the boundary
148 // between native non-anonymous content and native anonymouse content
149 bool mComposedInNativeAnonymousContent : 1;
150 // Set to true for events which are suppressed or delayed so that later a
151 // DelayedEvent of it is dispatched. This is used when parent side process
152 // the key event after content side, and may drop the event if the event
153 // was suppressed or delayed in contents side.
154 // It is also set to true for the events (in a DelayedInputEvent), which will
155 // be dispatched afterwards.
156 bool mIsSuppressedOrDelayed : 1;
157 // Certain mouse events can be marked as positionless to return 0 from
158 // coordinate related getters.
159 bool mIsPositionless : 1;
161 // Flags managing state of propagation between processes.
162 // Note the the following flags shouldn't be referred directly. Use utility
163 // methods instead.
165 // If mNoRemoteProcessDispatch is true, the event is not allowed to be sent
166 // to remote process.
167 bool mNoRemoteProcessDispatch : 1;
168 // If mWantReplyFromContentProcess is true, the event will be redispatched
169 // in the parent process after the content process has handled it. Useful
170 // for when the parent process need the know first how the event was used
171 // by content before handling it itself.
172 bool mWantReplyFromContentProcess : 1;
173 // If mPostedToRemoteProcess is true, the event has been posted to the
174 // remote process (but it's not handled yet if it's not a duplicated event
175 // instance).
176 bool mPostedToRemoteProcess : 1;
178 // If the event is being handled in target phase, returns true.
179 inline bool InTargetPhase() const {
180 return (mInBubblingPhase && mInCapturePhase);
184 * Helper methods for methods of DOM Event.
186 inline void StopPropagation() { mPropagationStopped = true; }
187 inline void StopImmediatePropagation() {
188 StopPropagation();
189 mImmediatePropagationStopped = true;
191 inline void PreventDefault(bool aCalledByDefaultHandler = true) {
192 if (!mCancelable) {
193 return;
195 mDefaultPrevented = true;
196 // Note that even if preventDefault() has already been called by chrome,
197 // a call of preventDefault() by content needs to overwrite
198 // mDefaultPreventedByContent to true because in such case, defaultPrevented
199 // must be true when web apps check it after they call preventDefault().
200 if (aCalledByDefaultHandler) {
201 StopCrossProcessForwarding();
202 mDefaultPreventedByChrome = true;
203 } else {
204 mDefaultPreventedByContent = true;
207 // This should be used only before dispatching events into the DOM tree.
208 inline void PreventDefaultBeforeDispatch(
209 CrossProcessForwarding aCrossProcessForwarding) {
210 if (!mCancelable) {
211 return;
213 mDefaultPrevented = true;
214 if (aCrossProcessForwarding == CrossProcessForwarding::eStop) {
215 StopCrossProcessForwarding();
218 inline bool DefaultPrevented() const { return mDefaultPrevented; }
219 inline bool DefaultPreventedByContent() const {
220 MOZ_ASSERT(!mDefaultPreventedByContent || DefaultPrevented());
221 return mDefaultPreventedByContent;
223 inline bool IsTrusted() const { return mIsTrusted; }
224 inline bool PropagationStopped() const { return mPropagationStopped; }
226 // Helper methods to access flags managing state of propagation between
227 // processes.
230 * Prevent to be dispatched to remote process.
232 inline void StopCrossProcessForwarding() {
233 MOZ_ASSERT(!mPostedToRemoteProcess);
234 mNoRemoteProcessDispatch = true;
235 mWantReplyFromContentProcess = false;
238 * Return true if the event shouldn't be dispatched to remote process.
240 inline bool IsCrossProcessForwardingStopped() const {
241 return mNoRemoteProcessDispatch;
244 * Mark the event as waiting reply from remote process.
245 * If the caller needs to win other keyboard event handlers in chrome,
246 * the caller should call StopPropagation() too.
247 * Otherwise, if the caller just needs to know if the event is consumed by
248 * either content or chrome, it should just call this because the event
249 * may be reserved by chrome and it needs to be dispatched into the DOM
250 * tree in chrome for checking if it's reserved before being sent to any
251 * remote processes.
253 inline void MarkAsWaitingReplyFromRemoteProcess() {
254 MOZ_ASSERT(!mPostedToRemoteProcess);
255 mNoRemoteProcessDispatch = false;
256 mWantReplyFromContentProcess = true;
259 * Reset "waiting reply from remote process" state. This is useful when
260 * you dispatch a copy of an event coming from different process.
262 inline void ResetWaitingReplyFromRemoteProcessState() {
263 if (IsWaitingReplyFromRemoteProcess()) {
264 // FYI: mWantReplyFromContentProcess is also used for indicating
265 // "handled in remote process" state. Therefore, only when
266 // IsWaitingReplyFromRemoteProcess() returns true, this should
267 // reset the flag.
268 mWantReplyFromContentProcess = false;
272 * Return true if the event handler should wait reply event. I.e., if this
273 * returns true, any event handler should do nothing with the event.
275 inline bool IsWaitingReplyFromRemoteProcess() const {
276 return !mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
279 * Mark the event as already handled in the remote process. This should be
280 * called when initializing reply events.
282 inline void MarkAsHandledInRemoteProcess() {
283 mNoRemoteProcessDispatch = true;
284 mWantReplyFromContentProcess = true;
285 mPostedToRemoteProcess = false;
288 * Return true if the event has already been handled in the remote process.
290 inline bool IsHandledInRemoteProcess() const {
291 return mNoRemoteProcessDispatch && mWantReplyFromContentProcess;
294 * Return true if the event should be sent back to its parent process.
296 inline bool WantReplyFromContentProcess() const {
297 MOZ_ASSERT(!XRE_IsParentProcess());
298 return IsWaitingReplyFromRemoteProcess();
301 * Mark the event has already posted to a remote process.
303 inline void MarkAsPostedToRemoteProcess() {
304 MOZ_ASSERT(!IsCrossProcessForwardingStopped());
305 mPostedToRemoteProcess = true;
308 * Reset the cross process dispatching state. This should be used when a
309 * process receives the event because the state is in the sender.
311 inline void ResetCrossProcessDispatchingState() {
312 MOZ_ASSERT(!IsCrossProcessForwardingStopped());
313 mPostedToRemoteProcess = false;
314 // Ignore propagation state in the different process if it's marked as
315 // "waiting reply from remote process" because the process needs to
316 // stop propagation in the process until receiving a reply event.
317 if (IsWaitingReplyFromRemoteProcess()) {
318 mPropagationStopped = mImmediatePropagationStopped = false;
322 * Return true if the event has been posted to a remote process.
323 * Note that MarkAsPostedToRemoteProcess() is called by
324 * ParamTraits<mozilla::WidgetEvent>. Therefore, it *might* be possible
325 * that posting the event failed even if this returns true. But that must
326 * really rare. If that'd be problem for you, you should unmark this in
327 * BrowserParent or somewhere.
329 inline bool HasBeenPostedToRemoteProcess() const {
330 return mPostedToRemoteProcess;
333 * Mark the event is reserved by chrome. I.e., shouldn't be dispatched to
334 * content because it shouldn't be cancelable.
336 inline void MarkAsReservedByChrome() {
337 MOZ_ASSERT(!mPostedToRemoteProcess);
338 mIsReservedByChrome = true;
339 // For reserved commands (such as Open New Tab), we don't need to wait for
340 // the content to answer, neither to give a chance for content to override
341 // its behavior.
342 StopCrossProcessForwarding();
343 // If the event is reserved by chrome, we shouldn't expose the event to
344 // web contents because such events shouldn't be cancelable. So, it's not
345 // good behavior to fire such events but to ignore the defaultPrevented
346 // attribute value in chrome.
347 mOnlySystemGroupDispatchInContent = true;
350 * Return true if the event is reserved by chrome.
352 inline bool IsReservedByChrome() const {
353 MOZ_ASSERT(!mIsReservedByChrome || (IsCrossProcessForwardingStopped() &&
354 mOnlySystemGroupDispatchInContent));
355 return mIsReservedByChrome;
358 inline void Clear() { SetRawFlags(0); }
359 // Get if either the instance's bit or the aOther's bit is true, the
360 // instance's bit becomes true. In other words, this works like:
361 // eventFlags |= aOther;
362 inline void Union(const BaseEventFlags& aOther) {
363 RawFlags rawFlags = GetRawFlags() | aOther.GetRawFlags();
364 SetRawFlags(rawFlags);
367 private:
368 typedef uint32_t RawFlags;
370 inline void SetRawFlags(RawFlags aRawFlags) {
371 static_assert(sizeof(BaseEventFlags) <= sizeof(RawFlags),
372 "mozilla::EventFlags must not be bigger than the RawFlags");
373 memcpy(this, &aRawFlags, sizeof(BaseEventFlags));
375 inline RawFlags GetRawFlags() const {
376 RawFlags result = 0;
377 memcpy(&result, this, sizeof(BaseEventFlags));
378 return result;
382 /******************************************************************************
383 * mozilla::EventFlags
384 ******************************************************************************/
386 struct EventFlags : public BaseEventFlags {
387 EventFlags() { Clear(); }
390 /******************************************************************************
391 * mozilla::WidgetEventTime
392 ******************************************************************************/
394 class WidgetEventTime {
395 public:
396 // Elapsed time, in milliseconds, from a platform-specific zero time
397 // to the time the message was created
398 uint64_t mTime;
399 // Timestamp when the message was created. Set in parallel to 'time' until we
400 // determine if it is safe to drop 'time' (see bug 77992).
401 TimeStamp mTimeStamp;
403 WidgetEventTime() : mTime(0), mTimeStamp(TimeStamp::Now()) {}
405 WidgetEventTime(uint64_t aTime, TimeStamp aTimeStamp)
406 : mTime(aTime), mTimeStamp(aTimeStamp) {}
408 void AssignEventTime(const WidgetEventTime& aOther) {
409 mTime = aOther.mTime;
410 mTimeStamp = aOther.mTimeStamp;
414 /******************************************************************************
415 * mozilla::WidgetEvent
416 ******************************************************************************/
418 class WidgetEvent : public WidgetEventTime {
419 private:
420 void SetDefaultCancelableAndBubbles() {
421 switch (mClass) {
422 case eEditorInputEventClass:
423 mFlags.mCancelable = false;
424 mFlags.mBubbles = mFlags.mIsTrusted;
425 break;
426 case eMouseEventClass:
427 mFlags.mCancelable =
428 (mMessage != eMouseEnter && mMessage != eMouseLeave);
429 mFlags.mBubbles = (mMessage != eMouseEnter && mMessage != eMouseLeave);
430 break;
431 case ePointerEventClass:
432 mFlags.mCancelable =
433 (mMessage != ePointerEnter && mMessage != ePointerLeave &&
434 mMessage != ePointerCancel && mMessage != ePointerGotCapture &&
435 mMessage != ePointerLostCapture);
436 mFlags.mBubbles =
437 (mMessage != ePointerEnter && mMessage != ePointerLeave);
438 break;
439 case eDragEventClass:
440 mFlags.mCancelable = (mMessage != eDragExit && mMessage != eDragLeave &&
441 mMessage != eDragEnd);
442 mFlags.mBubbles = true;
443 break;
444 case eSMILTimeEventClass:
445 mFlags.mCancelable = false;
446 mFlags.mBubbles = false;
447 break;
448 case eTransitionEventClass:
449 case eAnimationEventClass:
450 mFlags.mCancelable = false;
451 mFlags.mBubbles = true;
452 break;
453 case eCompositionEventClass:
454 // XXX compositionstart is cancelable in draft of DOM3 Events.
455 // However, it doesn't make sense for us, we cannot cancel
456 // composition when we send compositionstart event.
457 mFlags.mCancelable = false;
458 mFlags.mBubbles = true;
459 break;
460 default:
461 if (mMessage == eResize || mMessage == eMozVisualResize ||
462 mMessage == eMozVisualScroll || mMessage == eEditorInput) {
463 mFlags.mCancelable = false;
464 } else {
465 mFlags.mCancelable = true;
467 mFlags.mBubbles = true;
468 break;
472 protected:
473 WidgetEvent(bool aIsTrusted, EventMessage aMessage,
474 EventClassID aEventClassID)
475 : WidgetEventTime(),
476 mClass(aEventClassID),
477 mMessage(aMessage),
478 mRefPoint(0, 0),
479 mLastRefPoint(0, 0),
480 mFocusSequenceNumber(0),
481 mSpecifiedEventType(nullptr),
482 mPath(nullptr),
483 mLayersId(layers::LayersId{0}) {
484 MOZ_COUNT_CTOR(WidgetEvent);
485 mFlags.Clear();
486 mFlags.mIsTrusted = aIsTrusted;
487 SetDefaultCancelableAndBubbles();
488 SetDefaultComposed();
489 SetDefaultComposedInNativeAnonymousContent();
492 WidgetEvent() : WidgetEventTime(), mPath(nullptr) {
493 MOZ_COUNT_CTOR(WidgetEvent);
496 public:
497 WidgetEvent(bool aIsTrusted, EventMessage aMessage)
498 : WidgetEvent(aIsTrusted, aMessage, eBasicEventClass) {}
500 virtual ~WidgetEvent() { MOZ_COUNT_DTOR(WidgetEvent); }
502 WidgetEvent(const WidgetEvent& aOther) : WidgetEventTime() {
503 MOZ_COUNT_CTOR(WidgetEvent);
504 *this = aOther;
506 WidgetEvent& operator=(const WidgetEvent& aOther) = default;
508 WidgetEvent(WidgetEvent&& aOther)
509 : WidgetEventTime(std::move(aOther)),
510 mClass(aOther.mClass),
511 mMessage(aOther.mMessage),
512 mRefPoint(std::move(aOther.mRefPoint)),
513 mLastRefPoint(std::move(aOther.mLastRefPoint)),
514 mFocusSequenceNumber(aOther.mFocusSequenceNumber),
515 mFlags(std::move(aOther.mFlags)),
516 mSpecifiedEventType(std::move(aOther.mSpecifiedEventType)),
517 mSpecifiedEventTypeString(std::move(aOther.mSpecifiedEventTypeString)),
518 mTarget(std::move(aOther.mTarget)),
519 mCurrentTarget(std::move(aOther.mCurrentTarget)),
520 mOriginalTarget(std::move(aOther.mOriginalTarget)),
521 mRelatedTarget(std::move(aOther.mRelatedTarget)),
522 mOriginalRelatedTarget(std::move(aOther.mOriginalRelatedTarget)),
523 mPath(std::move(aOther.mPath)) {
524 MOZ_COUNT_CTOR(WidgetEvent);
526 WidgetEvent& operator=(WidgetEvent&& aOther) = default;
528 virtual WidgetEvent* Duplicate() const {
529 MOZ_ASSERT(mClass == eBasicEventClass,
530 "Duplicate() must be overridden by sub class");
531 WidgetEvent* result = new WidgetEvent(false, mMessage);
532 result->AssignEventData(*this, true);
533 result->mFlags = mFlags;
534 return result;
537 EventClassID mClass;
538 EventMessage mMessage;
539 // Relative to the widget of the event, or if there is no widget then it is
540 // in screen coordinates. Not modified by layout code.
541 LayoutDeviceIntPoint mRefPoint;
542 // The previous mRefPoint, if known, used to calculate mouse movement deltas.
543 LayoutDeviceIntPoint mLastRefPoint;
544 // The sequence number of the last potentially focus changing event handled
545 // by APZ. This is used to track when that event has been processed by
546 // content, and focus can be reconfirmed for async keyboard scrolling.
547 uint64_t mFocusSequenceNumber;
548 // See BaseEventFlags definition for the detail.
549 BaseEventFlags mFlags;
551 // If JS creates an event with unknown event type or known event type but
552 // for different event interface, the event type is stored to this.
553 // NOTE: This is always used if the instance is a WidgetCommandEvent instance
554 // or "input" event is dispatched with dom::Event class.
555 RefPtr<nsAtom> mSpecifiedEventType;
557 // nsAtom isn't available on non-main thread due to unsafe. Therefore,
558 // mSpecifiedEventTypeString is used instead of mSpecifiedEventType if
559 // the event is created in non-main thread.
560 nsString mSpecifiedEventTypeString;
562 // Event targets, needed by DOM Events
563 // Note that when you need event target for DOM event, you should use
564 // Get*DOMEventTarget() instead of accessing these members directly.
565 nsCOMPtr<dom::EventTarget> mTarget;
566 nsCOMPtr<dom::EventTarget> mCurrentTarget;
567 nsCOMPtr<dom::EventTarget> mOriginalTarget;
569 /// The possible related target
570 nsCOMPtr<dom::EventTarget> mRelatedTarget;
571 nsCOMPtr<dom::EventTarget> mOriginalRelatedTarget;
573 nsTArray<EventTargetChainItem>* mPath;
575 // The LayersId of the content process that this event should be
576 // dispatched to. This field is only used in the chrome process
577 // and doesn't get remoted to child processes.
578 layers::LayersId mLayersId;
580 dom::EventTarget* GetDOMEventTarget() const;
581 dom::EventTarget* GetCurrentDOMEventTarget() const;
582 dom::EventTarget* GetOriginalDOMEventTarget() const;
584 void AssignEventData(const WidgetEvent& aEvent, bool aCopyTargets) {
585 // mClass should be initialized with the constructor.
586 // mMessage should be initialized with the constructor.
587 mRefPoint = aEvent.mRefPoint;
588 // mLastRefPoint doesn't need to be copied.
589 mFocusSequenceNumber = aEvent.mFocusSequenceNumber;
590 // mLayersId intentionally not copied, since it's not used within content
591 AssignEventTime(aEvent);
592 // mFlags should be copied manually if it's necessary.
593 mSpecifiedEventType = aEvent.mSpecifiedEventType;
594 // mSpecifiedEventTypeString should be copied manually if it's necessary.
595 mTarget = aCopyTargets ? aEvent.mTarget : nullptr;
596 mCurrentTarget = aCopyTargets ? aEvent.mCurrentTarget : nullptr;
597 mOriginalTarget = aCopyTargets ? aEvent.mOriginalTarget : nullptr;
598 mRelatedTarget = aCopyTargets ? aEvent.mRelatedTarget : nullptr;
599 mOriginalRelatedTarget =
600 aCopyTargets ? aEvent.mOriginalRelatedTarget : nullptr;
604 * Helper methods for methods of DOM Event.
606 void StopPropagation() { mFlags.StopPropagation(); }
607 void StopImmediatePropagation() { mFlags.StopImmediatePropagation(); }
608 void PreventDefault(bool aCalledByDefaultHandler = true,
609 nsIPrincipal* aPrincipal = nullptr);
611 void PreventDefaultBeforeDispatch(
612 CrossProcessForwarding aCrossProcessForwarding) {
613 mFlags.PreventDefaultBeforeDispatch(aCrossProcessForwarding);
615 bool DefaultPrevented() const { return mFlags.DefaultPrevented(); }
616 bool DefaultPreventedByContent() const {
617 return mFlags.DefaultPreventedByContent();
619 bool IsTrusted() const { return mFlags.IsTrusted(); }
620 bool PropagationStopped() const { return mFlags.PropagationStopped(); }
623 * Prevent to be dispatched to remote process.
625 inline void StopCrossProcessForwarding() {
626 mFlags.StopCrossProcessForwarding();
629 * Return true if the event shouldn't be dispatched to remote process.
631 inline bool IsCrossProcessForwardingStopped() const {
632 return mFlags.IsCrossProcessForwardingStopped();
635 * Mark the event as waiting reply from remote process.
636 * Note that this also stops immediate propagation in current process.
638 inline void MarkAsWaitingReplyFromRemoteProcess() {
639 mFlags.MarkAsWaitingReplyFromRemoteProcess();
642 * Reset "waiting reply from remote process" state. This is useful when
643 * you dispatch a copy of an event coming from different process.
645 inline void ResetWaitingReplyFromRemoteProcessState() {
646 mFlags.ResetWaitingReplyFromRemoteProcessState();
649 * Return true if the event handler should wait reply event. I.e., if this
650 * returns true, any event handler should do nothing with the event.
652 inline bool IsWaitingReplyFromRemoteProcess() const {
653 return mFlags.IsWaitingReplyFromRemoteProcess();
656 * Mark the event as already handled in the remote process. This should be
657 * called when initializing reply events.
659 inline void MarkAsHandledInRemoteProcess() {
660 mFlags.MarkAsHandledInRemoteProcess();
663 * Return true if the event has already been handled in the remote process.
664 * I.e., if this returns true, the event is a reply event.
666 inline bool IsHandledInRemoteProcess() const {
667 return mFlags.IsHandledInRemoteProcess();
670 * Return true if the event should be sent back to its parent process.
671 * So, usual event handlers shouldn't call this.
673 inline bool WantReplyFromContentProcess() const {
674 return mFlags.WantReplyFromContentProcess();
677 * Mark the event has already posted to a remote process.
679 inline void MarkAsPostedToRemoteProcess() {
680 mFlags.MarkAsPostedToRemoteProcess();
683 * Reset the cross process dispatching state. This should be used when a
684 * process receives the event because the state is in the sender.
686 inline void ResetCrossProcessDispatchingState() {
687 mFlags.ResetCrossProcessDispatchingState();
690 * Return true if the event has been posted to a remote process.
692 inline bool HasBeenPostedToRemoteProcess() const {
693 return mFlags.HasBeenPostedToRemoteProcess();
696 * Mark the event is reserved by chrome. I.e., shouldn't be dispatched to
697 * content because it shouldn't be cancelable.
699 inline void MarkAsReservedByChrome() { mFlags.MarkAsReservedByChrome(); }
701 * Return true if the event is reserved by chrome.
703 inline bool IsReservedByChrome() const { return mFlags.IsReservedByChrome(); }
706 * Utils for checking event types
710 * As*Event() returns the pointer of the instance only when the instance is
711 * the class or one of its derived class.
713 #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
714 #define NS_EVENT_CLASS(aPrefix, aName) \
715 virtual aPrefix##aName* As##aName(); \
716 const aPrefix##aName* As##aName() const;
718 #include "mozilla/EventClassList.h"
720 #undef NS_EVENT_CLASS
721 #undef NS_ROOT_EVENT_CLASS
724 * Returns true if the event is a query content event.
726 bool IsQueryContentEvent() const;
728 * Returns true if the event is a selection event.
730 bool IsSelectionEvent() const;
732 * Returns true if the event is a content command event.
734 bool IsContentCommandEvent() const;
736 * Returns true if the event is a native event deliverer event for plugin.
738 bool IsNativeEventDelivererForPlugin() const;
741 * Returns true if the event mMessage is one of mouse events.
743 bool HasMouseEventMessage() const;
745 * Returns true if the event mMessage is one of drag events.
747 bool HasDragEventMessage() const;
749 * Returns true if aMessage or mMessage is one of key events.
751 static bool IsKeyEventMessage(EventMessage aMessage);
752 bool HasKeyEventMessage() const { return IsKeyEventMessage(mMessage); }
754 * Returns true if the event mMessage is one of composition events or text
755 * event.
757 bool HasIMEEventMessage() const;
759 * Returns true if the event mMessage is one of plugin activation events.
761 bool HasPluginActivationEventMessage() const;
764 * Returns true if the event can be sent to remote process.
766 bool CanBeSentToRemoteProcess() const;
768 * Returns true if the original target is a remote process and the event
769 * will be posted to the remote process later.
771 bool WillBeSentToRemoteProcess() const;
773 * Returns true if the event is native event deliverer event for plugin and
774 * it should be retarted to focused document.
776 bool IsRetargetedNativeEventDelivererForPlugin() const;
778 * Returns true if the event is native event deliverer event for plugin and
779 * it should NOT be retarted to focused document.
781 bool IsNonRetargetedNativeEventDelivererForPlugin() const;
783 * Returns true if the event is related to IME handling. It includes
784 * IME events, query content events and selection events.
785 * Be careful when you use this.
787 bool IsIMERelatedEvent() const;
790 * Whether the event should be handled by the frame of the mouse cursor
791 * position or not. When it should be handled there (e.g., the mouse events),
792 * this returns true.
794 bool IsUsingCoordinates() const;
796 * Whether the event should be handled by the focused DOM window in the
797 * same top level window's or not. E.g., key events, IME related events
798 * (including the query content events, they are used in IME transaction)
799 * should be handled by the (last) focused window rather than the dispatched
800 * window.
802 * NOTE: Even if this returns true, the event isn't going to be handled by the
803 * application level active DOM window which is on another top level window.
804 * So, when the event is fired on a deactive window, the event is going to be
805 * handled by the last focused DOM window in the last focused window.
807 bool IsTargetedAtFocusedWindow() const;
809 * Whether the event should be handled by the focused content or not. E.g.,
810 * key events, IME related events and other input events which are not handled
811 * by the frame of the mouse cursor position.
813 * NOTE: Even if this returns true, the event isn't going to be handled by the
814 * application level active DOM window which is on another top level window.
815 * So, when the event is fired on a deactive window, the event is going to be
816 * handled by the last focused DOM element of the last focused DOM window in
817 * the last focused window.
819 bool IsTargetedAtFocusedContent() const;
821 * Whether the event should cause a DOM event.
823 bool IsAllowedToDispatchDOMEvent() const;
825 * Whether the event should be dispatched in system group.
827 bool IsAllowedToDispatchInSystemGroup() const;
829 * Whether the event should be blocked for fingerprinting resistance.
831 bool IsBlockedForFingerprintingResistance() const;
833 * Initialize mComposed
835 void SetDefaultComposed() {
836 switch (mClass) {
837 case eCompositionEventClass:
838 mFlags.mComposed =
839 mMessage == eCompositionStart || mMessage == eCompositionUpdate ||
840 mMessage == eCompositionChange || mMessage == eCompositionEnd;
841 break;
842 case eDragEventClass:
843 // All drag & drop events are composed
844 mFlags.mComposed = mMessage == eDrag || mMessage == eDragEnd ||
845 mMessage == eDragEnter || mMessage == eDragExit ||
846 mMessage == eDragLeave || mMessage == eDragOver ||
847 mMessage == eDragStart || mMessage == eDrop;
848 break;
849 case eEditorInputEventClass:
850 mFlags.mComposed = mMessage == eEditorInput;
851 break;
852 case eFocusEventClass:
853 mFlags.mComposed = mMessage == eBlur || mMessage == eFocus ||
854 mMessage == eFocusOut || mMessage == eFocusIn;
855 break;
856 case eKeyboardEventClass:
857 mFlags.mComposed =
858 mMessage == eKeyDown || mMessage == eKeyUp || mMessage == eKeyPress;
859 break;
860 case eMouseEventClass:
861 mFlags.mComposed =
862 mMessage == eMouseClick || mMessage == eMouseDoubleClick ||
863 mMessage == eMouseAuxClick || mMessage == eMouseDown ||
864 mMessage == eMouseUp || mMessage == eMouseOver ||
865 mMessage == eMouseOut || mMessage == eMouseMove ||
866 mMessage == eContextMenu || mMessage == eXULPopupShowing ||
867 mMessage == eXULPopupHiding || mMessage == eXULPopupShown ||
868 mMessage == eXULPopupHidden || mMessage == eXULPopupPositioned;
869 break;
870 case ePointerEventClass:
871 // All pointer events are composed
872 mFlags.mComposed =
873 mMessage == ePointerDown || mMessage == ePointerMove ||
874 mMessage == ePointerUp || mMessage == ePointerCancel ||
875 mMessage == ePointerOver || mMessage == ePointerOut ||
876 mMessage == ePointerGotCapture || mMessage == ePointerLostCapture;
877 break;
878 case eTouchEventClass:
879 // All touch events are composed
880 mFlags.mComposed = mMessage == eTouchStart || mMessage == eTouchEnd ||
881 mMessage == eTouchMove || mMessage == eTouchCancel;
882 break;
883 case eUIEventClass:
884 mFlags.mComposed = mMessage == eLegacyDOMFocusIn ||
885 mMessage == eLegacyDOMFocusOut ||
886 mMessage == eLegacyDOMActivate;
887 break;
888 case eWheelEventClass:
889 // All wheel events are composed
890 mFlags.mComposed = mMessage == eWheel;
891 break;
892 default:
893 mFlags.mComposed = false;
894 break;
898 void SetComposed(const nsAString& aEventTypeArg) {
899 mFlags.mComposed = // composition events
900 aEventTypeArg.EqualsLiteral("compositionstart") ||
901 aEventTypeArg.EqualsLiteral("compositionupdate") ||
902 aEventTypeArg.EqualsLiteral("compositionend") ||
903 aEventTypeArg.EqualsLiteral("text") ||
904 // drag and drop events
905 aEventTypeArg.EqualsLiteral("dragstart") ||
906 aEventTypeArg.EqualsLiteral("drag") ||
907 aEventTypeArg.EqualsLiteral("dragenter") ||
908 aEventTypeArg.EqualsLiteral("dragexit") ||
909 aEventTypeArg.EqualsLiteral("dragleave") ||
910 aEventTypeArg.EqualsLiteral("dragover") ||
911 aEventTypeArg.EqualsLiteral("drop") ||
912 aEventTypeArg.EqualsLiteral("dropend") ||
913 // editor input events
914 aEventTypeArg.EqualsLiteral("input") ||
915 aEventTypeArg.EqualsLiteral("beforeinput") ||
916 // focus events
917 aEventTypeArg.EqualsLiteral("blur") ||
918 aEventTypeArg.EqualsLiteral("focus") ||
919 aEventTypeArg.EqualsLiteral("focusin") ||
920 aEventTypeArg.EqualsLiteral("focusout") ||
921 // keyboard events
922 aEventTypeArg.EqualsLiteral("keydown") ||
923 aEventTypeArg.EqualsLiteral("keyup") ||
924 aEventTypeArg.EqualsLiteral("keypress") ||
925 // mouse events
926 aEventTypeArg.EqualsLiteral("click") ||
927 aEventTypeArg.EqualsLiteral("dblclick") ||
928 aEventTypeArg.EqualsLiteral("mousedown") ||
929 aEventTypeArg.EqualsLiteral("mouseup") ||
930 aEventTypeArg.EqualsLiteral("mouseenter") ||
931 aEventTypeArg.EqualsLiteral("mouseleave") ||
932 aEventTypeArg.EqualsLiteral("mouseover") ||
933 aEventTypeArg.EqualsLiteral("mouseout") ||
934 aEventTypeArg.EqualsLiteral("mousemove") ||
935 aEventTypeArg.EqualsLiteral("contextmenu") ||
936 // pointer events
937 aEventTypeArg.EqualsLiteral("pointerdown") ||
938 aEventTypeArg.EqualsLiteral("pointermove") ||
939 aEventTypeArg.EqualsLiteral("pointerup") ||
940 aEventTypeArg.EqualsLiteral("pointercancel") ||
941 aEventTypeArg.EqualsLiteral("pointerover") ||
942 aEventTypeArg.EqualsLiteral("pointerout") ||
943 aEventTypeArg.EqualsLiteral("pointerenter") ||
944 aEventTypeArg.EqualsLiteral("pointerleave") ||
945 aEventTypeArg.EqualsLiteral("gotpointercapture") ||
946 aEventTypeArg.EqualsLiteral("lostpointercapture") ||
947 // touch events
948 aEventTypeArg.EqualsLiteral("touchstart") ||
949 aEventTypeArg.EqualsLiteral("touchend") ||
950 aEventTypeArg.EqualsLiteral("touchmove") ||
951 aEventTypeArg.EqualsLiteral("touchcancel") ||
952 // UI legacy events
953 aEventTypeArg.EqualsLiteral("DOMFocusIn") ||
954 aEventTypeArg.EqualsLiteral("DOMFocusOut") ||
955 aEventTypeArg.EqualsLiteral("DOMActivate") ||
956 // wheel events
957 aEventTypeArg.EqualsLiteral("wheel");
960 void SetComposed(bool aComposed) { mFlags.mComposed = aComposed; }
962 void SetDefaultComposedInNativeAnonymousContent() {
963 // For compatibility concerns, we set mComposedInNativeAnonymousContent to
964 // false for those events we want to stop propagation.
966 // nsVideoFrame may create anonymous image element which fires eLoad,
967 // eLoadStart, eLoadEnd, eLoadError. We don't want these events cross
968 // the boundary of NAC
969 mFlags.mComposedInNativeAnonymousContent =
970 mMessage != eLoad && mMessage != eLoadStart && mMessage != eLoadEnd &&
971 mMessage != eLoadError;
974 bool IsUserAction() const;
977 /******************************************************************************
978 * mozilla::NativeEventData
980 * WidgetGUIEvent's mPluginEvent member used to be a void* pointer,
981 * used to reference external, OS-specific data structures.
983 * That void* pointer wasn't serializable by itself, causing
984 * certain plugin events not to function in e10s. See bug 586656.
986 * To make this serializable, we changed this void* pointer into
987 * a proper buffer, and copy these external data structures into this
988 * buffer.
990 * That buffer is NativeEventData::mBuffer below.
992 * We wrap this in that NativeEventData class providing operators to
993 * be compatible with existing code that was written around
994 * the old void* field.
995 ******************************************************************************/
997 class NativeEventData final {
998 nsTArray<uint8_t> mBuffer;
1000 friend struct IPC::ParamTraits<mozilla::NativeEventData>;
1002 public:
1003 explicit operator bool() const { return !mBuffer.IsEmpty(); }
1005 template <typename T>
1006 explicit operator const T*() const {
1007 return mBuffer.IsEmpty() ? nullptr
1008 : reinterpret_cast<const T*>(mBuffer.Elements());
1011 template <typename T>
1012 void Copy(const T& other) {
1013 static_assert(!mozilla::IsPointer<T>::value, "Don't want a pointer!");
1014 mBuffer.SetLength(sizeof(T));
1015 memcpy(mBuffer.Elements(), &other, mBuffer.Length());
1018 void Clear() { mBuffer.Clear(); }
1021 /******************************************************************************
1022 * mozilla::WidgetGUIEvent
1023 ******************************************************************************/
1025 class WidgetGUIEvent : public WidgetEvent {
1026 protected:
1027 WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1028 EventClassID aEventClassID)
1029 : WidgetEvent(aIsTrusted, aMessage, aEventClassID), mWidget(aWidget) {}
1031 WidgetGUIEvent() {}
1033 public:
1034 virtual WidgetGUIEvent* AsGUIEvent() override { return this; }
1036 WidgetGUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
1037 : WidgetEvent(aIsTrusted, aMessage, eGUIEventClass), mWidget(aWidget) {}
1039 virtual WidgetEvent* Duplicate() const override {
1040 MOZ_ASSERT(mClass == eGUIEventClass,
1041 "Duplicate() must be overridden by sub class");
1042 // Not copying widget, it is a weak reference.
1043 WidgetGUIEvent* result = new WidgetGUIEvent(false, mMessage, nullptr);
1044 result->AssignGUIEventData(*this, true);
1045 result->mFlags = mFlags;
1046 return result;
1049 // Originator of the event
1050 nsCOMPtr<nsIWidget> mWidget;
1053 * Ideally though, we wouldn't allow arbitrary reinterpret_cast'ing here;
1054 * instead, we would at least store type information here so that
1055 * this class can't be used to reinterpret one structure type into another.
1056 * We can also wonder if it would be possible to properly extend
1057 * WidgetGUIEvent and other Event classes to remove the need for this
1058 * mPluginEvent field.
1060 typedef NativeEventData PluginEvent;
1062 // Event for NPAPI plugin
1063 PluginEvent mPluginEvent;
1065 void AssignGUIEventData(const WidgetGUIEvent& aEvent, bool aCopyTargets) {
1066 AssignEventData(aEvent, aCopyTargets);
1068 // widget should be initialized with the constructor.
1070 mPluginEvent = aEvent.mPluginEvent;
1074 /******************************************************************************
1075 * mozilla::Modifier
1077 * All modifier keys should be defined here. This is used for managing
1078 * modifier states for DOM Level 3 or later.
1079 ******************************************************************************/
1081 enum Modifier {
1082 MODIFIER_NONE = 0x0000,
1083 MODIFIER_ALT = 0x0001,
1084 MODIFIER_ALTGRAPH = 0x0002,
1085 MODIFIER_CAPSLOCK = 0x0004,
1086 MODIFIER_CONTROL = 0x0008,
1087 MODIFIER_FN = 0x0010,
1088 MODIFIER_FNLOCK = 0x0020,
1089 MODIFIER_META = 0x0040,
1090 MODIFIER_NUMLOCK = 0x0080,
1091 MODIFIER_SCROLLLOCK = 0x0100,
1092 MODIFIER_SHIFT = 0x0200,
1093 MODIFIER_SYMBOL = 0x0400,
1094 MODIFIER_SYMBOLLOCK = 0x0800,
1095 MODIFIER_OS = 0x1000
1098 /******************************************************************************
1099 * Modifier key names.
1100 ******************************************************************************/
1102 #define NS_DOM_KEYNAME_ALT "Alt"
1103 #define NS_DOM_KEYNAME_ALTGRAPH "AltGraph"
1104 #define NS_DOM_KEYNAME_CAPSLOCK "CapsLock"
1105 #define NS_DOM_KEYNAME_CONTROL "Control"
1106 #define NS_DOM_KEYNAME_FN "Fn"
1107 #define NS_DOM_KEYNAME_FNLOCK "FnLock"
1108 #define NS_DOM_KEYNAME_META "Meta"
1109 #define NS_DOM_KEYNAME_NUMLOCK "NumLock"
1110 #define NS_DOM_KEYNAME_SCROLLLOCK "ScrollLock"
1111 #define NS_DOM_KEYNAME_SHIFT "Shift"
1112 #define NS_DOM_KEYNAME_SYMBOL "Symbol"
1113 #define NS_DOM_KEYNAME_SYMBOLLOCK "SymbolLock"
1114 #define NS_DOM_KEYNAME_OS "OS"
1116 /******************************************************************************
1117 * mozilla::Modifiers
1118 ******************************************************************************/
1120 typedef uint16_t Modifiers;
1122 class MOZ_STACK_CLASS GetModifiersName final : public nsAutoCString {
1123 public:
1124 explicit GetModifiersName(Modifiers aModifiers) {
1125 if (aModifiers & MODIFIER_ALT) {
1126 AssignLiteral(NS_DOM_KEYNAME_ALT);
1128 if (aModifiers & MODIFIER_ALTGRAPH) {
1129 MaybeAppendSeparator();
1130 AppendLiteral(NS_DOM_KEYNAME_ALTGRAPH);
1132 if (aModifiers & MODIFIER_CAPSLOCK) {
1133 MaybeAppendSeparator();
1134 AppendLiteral(NS_DOM_KEYNAME_CAPSLOCK);
1136 if (aModifiers & MODIFIER_CONTROL) {
1137 MaybeAppendSeparator();
1138 AppendLiteral(NS_DOM_KEYNAME_CONTROL);
1140 if (aModifiers & MODIFIER_FN) {
1141 MaybeAppendSeparator();
1142 AppendLiteral(NS_DOM_KEYNAME_FN);
1144 if (aModifiers & MODIFIER_FNLOCK) {
1145 MaybeAppendSeparator();
1146 AppendLiteral(NS_DOM_KEYNAME_FNLOCK);
1148 if (aModifiers & MODIFIER_META) {
1149 MaybeAppendSeparator();
1150 AppendLiteral(NS_DOM_KEYNAME_META);
1152 if (aModifiers & MODIFIER_NUMLOCK) {
1153 MaybeAppendSeparator();
1154 AppendLiteral(NS_DOM_KEYNAME_NUMLOCK);
1156 if (aModifiers & MODIFIER_SCROLLLOCK) {
1157 MaybeAppendSeparator();
1158 AppendLiteral(NS_DOM_KEYNAME_SCROLLLOCK);
1160 if (aModifiers & MODIFIER_SHIFT) {
1161 MaybeAppendSeparator();
1162 AppendLiteral(NS_DOM_KEYNAME_SHIFT);
1164 if (aModifiers & MODIFIER_SYMBOL) {
1165 MaybeAppendSeparator();
1166 AppendLiteral(NS_DOM_KEYNAME_SYMBOL);
1168 if (aModifiers & MODIFIER_SYMBOLLOCK) {
1169 MaybeAppendSeparator();
1170 AppendLiteral(NS_DOM_KEYNAME_SYMBOLLOCK);
1172 if (aModifiers & MODIFIER_OS) {
1173 MaybeAppendSeparator();
1174 AppendLiteral(NS_DOM_KEYNAME_OS);
1176 if (IsEmpty()) {
1177 AssignLiteral("none");
1181 private:
1182 void MaybeAppendSeparator() {
1183 if (!IsEmpty()) {
1184 AppendLiteral(" | ");
1189 /******************************************************************************
1190 * mozilla::WidgetInputEvent
1191 ******************************************************************************/
1193 class WidgetInputEvent : public WidgetGUIEvent {
1194 protected:
1195 WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1196 EventClassID aEventClassID)
1197 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID),
1198 mModifiers(0) {}
1200 WidgetInputEvent() : mModifiers(0) {}
1202 public:
1203 virtual WidgetInputEvent* AsInputEvent() override { return this; }
1205 WidgetInputEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget)
1206 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eInputEventClass),
1207 mModifiers(0) {}
1209 virtual WidgetEvent* Duplicate() const override {
1210 MOZ_ASSERT(mClass == eInputEventClass,
1211 "Duplicate() must be overridden by sub class");
1212 // Not copying widget, it is a weak reference.
1213 WidgetInputEvent* result = new WidgetInputEvent(false, mMessage, nullptr);
1214 result->AssignInputEventData(*this, true);
1215 result->mFlags = mFlags;
1216 return result;
1220 * Returns a modifier of "Accel" virtual modifier which is used for shortcut
1221 * key.
1223 static Modifier AccelModifier();
1226 * GetModifier() returns a modifier flag which is activated by aDOMKeyName.
1228 static Modifier GetModifier(const nsAString& aDOMKeyName);
1230 // true indicates the accel key on the environment is down
1231 bool IsAccel() const { return ((mModifiers & AccelModifier()) != 0); }
1233 // true indicates the shift key is down
1234 bool IsShift() const { return ((mModifiers & MODIFIER_SHIFT) != 0); }
1235 // true indicates the control key is down
1236 bool IsControl() const { return ((mModifiers & MODIFIER_CONTROL) != 0); }
1237 // true indicates the alt key is down
1238 bool IsAlt() const { return ((mModifiers & MODIFIER_ALT) != 0); }
1239 // true indicates the meta key is down (or, on Mac, the Command key)
1240 bool IsMeta() const { return ((mModifiers & MODIFIER_META) != 0); }
1241 // true indicates the win key is down on Windows. Or the Super or Hyper key
1242 // is down on Linux.
1243 bool IsOS() const { return ((mModifiers & MODIFIER_OS) != 0); }
1244 // true indicates the alt graph key is down
1245 // NOTE: on Mac, the option key press causes both IsAlt() and IsAltGrpah()
1246 // return true.
1247 bool IsAltGraph() const { return ((mModifiers & MODIFIER_ALTGRAPH) != 0); }
1248 // true indicates the CapLock LED is turn on.
1249 bool IsCapsLocked() const { return ((mModifiers & MODIFIER_CAPSLOCK) != 0); }
1250 // true indicates the NumLock LED is turn on.
1251 bool IsNumLocked() const { return ((mModifiers & MODIFIER_NUMLOCK) != 0); }
1252 // true indicates the ScrollLock LED is turn on.
1253 bool IsScrollLocked() const {
1254 return ((mModifiers & MODIFIER_SCROLLLOCK) != 0);
1257 // true indicates the Fn key is down, but this is not supported by native
1258 // key event on any platform.
1259 bool IsFn() const { return ((mModifiers & MODIFIER_FN) != 0); }
1260 // true indicates the FnLock LED is turn on, but we don't know such
1261 // keyboards nor platforms.
1262 bool IsFnLocked() const { return ((mModifiers & MODIFIER_FNLOCK) != 0); }
1263 // true indicates the Symbol is down, but this is not supported by native
1264 // key event on any platforms.
1265 bool IsSymbol() const { return ((mModifiers & MODIFIER_SYMBOL) != 0); }
1266 // true indicates the SymbolLock LED is turn on, but we don't know such
1267 // keyboards nor platforms.
1268 bool IsSymbolLocked() const {
1269 return ((mModifiers & MODIFIER_SYMBOLLOCK) != 0);
1272 void InitBasicModifiers(bool aCtrlKey, bool aAltKey, bool aShiftKey,
1273 bool aMetaKey) {
1274 mModifiers = 0;
1275 if (aCtrlKey) {
1276 mModifiers |= MODIFIER_CONTROL;
1278 if (aAltKey) {
1279 mModifiers |= MODIFIER_ALT;
1281 if (aShiftKey) {
1282 mModifiers |= MODIFIER_SHIFT;
1284 if (aMetaKey) {
1285 mModifiers |= MODIFIER_META;
1289 Modifiers mModifiers;
1291 void AssignInputEventData(const WidgetInputEvent& aEvent, bool aCopyTargets) {
1292 AssignGUIEventData(aEvent, aCopyTargets);
1294 mModifiers = aEvent.mModifiers;
1298 /******************************************************************************
1299 * mozilla::InternalUIEvent
1301 * XXX Why this inherits WidgetGUIEvent rather than WidgetEvent?
1302 ******************************************************************************/
1304 class InternalUIEvent : public WidgetGUIEvent {
1305 protected:
1306 InternalUIEvent() : mDetail(0), mCausedByUntrustedEvent(false) {}
1308 InternalUIEvent(bool aIsTrusted, EventMessage aMessage, nsIWidget* aWidget,
1309 EventClassID aEventClassID)
1310 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, aEventClassID),
1311 mDetail(0),
1312 mCausedByUntrustedEvent(false) {}
1314 InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1315 EventClassID aEventClassID)
1316 : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, aEventClassID),
1317 mDetail(0),
1318 mCausedByUntrustedEvent(false) {}
1320 public:
1321 virtual InternalUIEvent* AsUIEvent() override { return this; }
1324 * If the UIEvent is caused by another event (e.g., click event),
1325 * aEventCausesThisEvent should be the event. If there is no such event,
1326 * this should be nullptr.
1328 InternalUIEvent(bool aIsTrusted, EventMessage aMessage,
1329 const WidgetEvent* aEventCausesThisEvent)
1330 : WidgetGUIEvent(aIsTrusted, aMessage, nullptr, eUIEventClass),
1331 mDetail(0),
1332 mCausedByUntrustedEvent(aEventCausesThisEvent &&
1333 !aEventCausesThisEvent->IsTrusted()) {}
1335 virtual WidgetEvent* Duplicate() const override {
1336 MOZ_ASSERT(mClass == eUIEventClass,
1337 "Duplicate() must be overridden by sub class");
1338 InternalUIEvent* result = new InternalUIEvent(false, mMessage, nullptr);
1339 result->AssignUIEventData(*this, true);
1340 result->mFlags = mFlags;
1341 return result;
1344 int32_t mDetail;
1345 // mCausedByUntrustedEvent is true if the event is caused by untrusted event.
1346 bool mCausedByUntrustedEvent;
1348 // If you check the event is a trusted event and NOT caused by an untrusted
1349 // event, IsTrustable() returns what you expected.
1350 bool IsTrustable() const { return IsTrusted() && !mCausedByUntrustedEvent; }
1352 void AssignUIEventData(const InternalUIEvent& aEvent, bool aCopyTargets) {
1353 AssignGUIEventData(aEvent, aCopyTargets);
1355 mDetail = aEvent.mDetail;
1356 mCausedByUntrustedEvent = aEvent.mCausedByUntrustedEvent;
1360 } // namespace mozilla
1362 #endif // mozilla_BasicEvents_h__