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