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 #include "AccessCheck.h"
7 #include "base/basictypes.h"
8 #include "ipc/IPCMessageUtils.h"
9 #include "mozilla/dom/Event.h"
10 #include "mozilla/ContentEvents.h"
11 #include "mozilla/DOMEventTargetHelper.h"
12 #include "mozilla/EventStateManager.h"
13 #include "mozilla/InternalMutationEvent.h"
14 #include "mozilla/MiscEvents.h"
15 #include "mozilla/MouseEvents.h"
16 #include "mozilla/Preferences.h"
17 #include "mozilla/TextEvents.h"
18 #include "mozilla/TouchEvents.h"
19 #include "nsContentUtils.h"
21 #include "nsDeviceContext.h"
23 #include "nsGlobalWindow.h"
25 #include "nsIContent.h"
26 #include "nsIDocument.h"
27 #include "nsIPresShell.h"
28 #include "nsIScrollableFrame.h"
29 #include "nsJSEnvironment.h"
30 #include "nsLayoutUtils.h"
31 #include "nsPerformance.h"
32 #include "nsPIWindowRoot.h"
33 #include "WorkerPrivate.h"
39 extern bool IsCurrentThreadRunningChromeWorker();
40 } // namespace workers
42 static char *sPopupAllowedEvents
;
44 static bool sReturnHighResTimeStamp
= false;
45 static bool sReturnHighResTimeStampIsSet
= false;
47 Event::Event(EventTarget
* aOwner
,
48 nsPresContext
* aPresContext
,
51 ConstructorInit(aOwner
, aPresContext
, aEvent
);
54 Event::Event(nsPIDOMWindow
* aParent
)
56 ConstructorInit(static_cast<nsGlobalWindow
*>(aParent
), nullptr, nullptr);
60 Event::ConstructorInit(EventTarget
* aOwner
,
61 nsPresContext
* aPresContext
,
66 mIsMainThreadEvent
= mOwner
|| NS_IsMainThread();
67 if (mIsMainThreadEvent
) {
68 nsJSContext::LikelyShortLivingObjectCreated();
71 if (mIsMainThreadEvent
&& !sReturnHighResTimeStampIsSet
) {
72 Preferences::AddBoolVarCache(&sReturnHighResTimeStamp
,
73 "dom.event.highrestimestamp.enabled",
74 sReturnHighResTimeStamp
);
75 sReturnHighResTimeStampIsSet
= true;
78 mPrivateDataDuplicated
= false;
82 mEventIsInternal
= false;
85 mEventIsInternal
= true;
87 A derived class might want to allocate its own type of aEvent
88 (derived from WidgetEvent). To do this, it should take care to pass
89 a non-nullptr aEvent to this ctor, e.g.:
91 FooEvent::FooEvent(..., WidgetEvent* aEvent)
92 : Event(..., aEvent ? aEvent : new WidgetEvent())
94 Then, to override the mEventIsInternal assignments done by the
95 base ctor, it should do this in its own ctor:
97 FooEvent::FooEvent(..., WidgetEvent* aEvent)
102 mEventIsInternal = false;
105 mEventIsInternal = true;
110 mEvent
= new WidgetEvent(false, 0);
111 mEvent
->time
= PR_Now();
114 InitPresContextData(aPresContext
);
118 Event::InitPresContextData(nsPresContext
* aPresContext
)
120 mPresContext
= aPresContext
;
121 // Get the explicit original target (if it's anonymous make it null)
123 nsCOMPtr
<nsIContent
> content
= GetTargetFromFrame();
124 mExplicitOriginalTarget
= content
;
125 if (content
&& content
->IsInAnonymousSubtree()) {
126 mExplicitOriginalTarget
= nullptr;
133 NS_ASSERT_OWNINGTHREAD(Event
);
135 if (mEventIsInternal
&& mEvent
) {
140 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Event
)
141 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
142 NS_INTERFACE_MAP_ENTRY(nsISupports
)
143 NS_INTERFACE_MAP_ENTRY(nsIDOMEvent
)
146 NS_IMPL_CYCLE_COLLECTING_ADDREF(Event
)
147 NS_IMPL_CYCLE_COLLECTING_RELEASE(Event
)
149 NS_IMPL_CYCLE_COLLECTION_CLASS(Event
)
151 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Event
)
152 NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
153 NS_IMPL_CYCLE_COLLECTION_TRACE_END
155 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Event
)
156 if (tmp
->mEventIsInternal
) {
157 tmp
->mEvent
->target
= nullptr;
158 tmp
->mEvent
->currentTarget
= nullptr;
159 tmp
->mEvent
->originalTarget
= nullptr;
160 switch (tmp
->mEvent
->eventStructType
) {
162 case NS_MOUSE_SCROLL_EVENT
:
164 case NS_SIMPLE_GESTURE_EVENT
:
165 case NS_POINTER_EVENT
:
166 tmp
->mEvent
->AsMouseEventBase()->relatedTarget
= nullptr;
168 case NS_DRAG_EVENT
: {
169 WidgetDragEvent
* dragEvent
= tmp
->mEvent
->AsDragEvent();
170 dragEvent
->dataTransfer
= nullptr;
171 dragEvent
->relatedTarget
= nullptr;
174 case NS_CLIPBOARD_EVENT
:
175 tmp
->mEvent
->AsClipboardEvent()->clipboardData
= nullptr;
177 case NS_MUTATION_EVENT
:
178 tmp
->mEvent
->AsMutationEvent()->mRelatedNode
= nullptr;
181 tmp
->mEvent
->AsFocusEvent()->relatedTarget
= nullptr;
187 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext
);
188 NS_IMPL_CYCLE_COLLECTION_UNLINK(mExplicitOriginalTarget
);
189 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner
);
190 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
191 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
193 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Event
)
194 if (tmp
->mEventIsInternal
) {
195 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent
->target
)
196 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent
->currentTarget
)
197 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent
->originalTarget
)
198 switch (tmp
->mEvent
->eventStructType
) {
200 case NS_MOUSE_SCROLL_EVENT
:
202 case NS_SIMPLE_GESTURE_EVENT
:
203 case NS_POINTER_EVENT
:
204 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->relatedTarget");
205 cb
.NoteXPCOMChild(tmp
->mEvent
->AsMouseEventBase()->relatedTarget
);
207 case NS_DRAG_EVENT
: {
208 WidgetDragEvent
* dragEvent
= tmp
->mEvent
->AsDragEvent();
209 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->dataTransfer");
210 cb
.NoteXPCOMChild(dragEvent
->dataTransfer
);
211 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->relatedTarget");
212 cb
.NoteXPCOMChild(dragEvent
->relatedTarget
);
215 case NS_CLIPBOARD_EVENT
:
216 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->clipboardData");
217 cb
.NoteXPCOMChild(tmp
->mEvent
->AsClipboardEvent()->clipboardData
);
219 case NS_MUTATION_EVENT
:
220 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->mRelatedNode");
221 cb
.NoteXPCOMChild(tmp
->mEvent
->AsMutationEvent()->mRelatedNode
);
224 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->relatedTarget");
225 cb
.NoteXPCOMChild(tmp
->mEvent
->AsFocusEvent()->relatedTarget
);
231 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext
)
232 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExplicitOriginalTarget
)
233 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner
)
234 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
235 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
238 Event::IsChrome(JSContext
* aCx
) const
240 return mIsMainThreadEvent
?
241 xpc::AccessCheck::isChrome(js::GetContextCompartment(aCx
)) :
242 mozilla::dom::workers::IsCurrentThreadRunningChromeWorker();
245 // nsIDOMEventInterface
247 Event::GetType(nsAString
& aType
)
249 if (!mIsMainThreadEvent
|| !mEvent
->typeString
.IsEmpty()) {
250 aType
= mEvent
->typeString
;
253 const char* name
= GetEventName(mEvent
->message
);
256 CopyASCIItoUTF16(name
, aType
);
258 } else if (mEvent
->message
== NS_USER_DEFINED_EVENT
&& mEvent
->userType
) {
259 aType
= Substring(nsDependentAtomString(mEvent
->userType
), 2); // Remove "on"
260 mEvent
->typeString
= aType
;
269 GetDOMEventTarget(nsIDOMEventTarget
* aTarget
)
271 return aTarget
? aTarget
->GetTargetForDOMEvent() : nullptr;
275 Event::GetTarget() const
277 return GetDOMEventTarget(mEvent
->target
);
281 Event::GetTarget(nsIDOMEventTarget
** aTarget
)
283 NS_IF_ADDREF(*aTarget
= GetTarget());
288 Event::GetCurrentTarget() const
290 return GetDOMEventTarget(mEvent
->currentTarget
);
294 Event::GetCurrentTarget(nsIDOMEventTarget
** aCurrentTarget
)
296 NS_IF_ADDREF(*aCurrentTarget
= GetCurrentTarget());
301 // Get the actual event target node (may have been retargeted for mouse events)
303 already_AddRefed
<nsIContent
>
304 Event::GetTargetFromFrame()
306 if (!mPresContext
) { return nullptr; }
308 // Get the target frame (have to get the ESM first)
309 nsIFrame
* targetFrame
= mPresContext
->EventStateManager()->GetEventTarget();
310 if (!targetFrame
) { return nullptr; }
312 // get the real content
313 nsCOMPtr
<nsIContent
> realEventContent
;
314 targetFrame
->GetContentForEvent(mEvent
, getter_AddRefs(realEventContent
));
315 return realEventContent
.forget();
319 Event::GetExplicitOriginalTarget() const
321 if (mExplicitOriginalTarget
) {
322 return mExplicitOriginalTarget
;
328 Event::GetExplicitOriginalTarget(nsIDOMEventTarget
** aRealEventTarget
)
330 NS_IF_ADDREF(*aRealEventTarget
= GetExplicitOriginalTarget());
335 Event::GetOriginalTarget() const
337 if (mEvent
->originalTarget
) {
338 return GetDOMEventTarget(mEvent
->originalTarget
);
345 Event::GetOriginalTarget(nsIDOMEventTarget
** aOriginalTarget
)
347 NS_IF_ADDREF(*aOriginalTarget
= GetOriginalTarget());
352 Event::SetTrusted(bool aTrusted
)
354 mEvent
->mFlags
.mIsTrusted
= aTrusted
;
358 Event::Init(mozilla::dom::EventTarget
* aGlobal
)
360 if (!mIsMainThreadEvent
) {
361 return nsContentUtils::ThreadsafeIsCallerChrome();
363 bool trusted
= false;
364 nsCOMPtr
<nsPIDOMWindow
> w
= do_QueryInterface(aGlobal
);
366 nsCOMPtr
<nsIDocument
> d
= w
->GetExtantDoc();
368 trusted
= nsContentUtils::IsChromeDoc(d
);
369 nsIPresShell
* s
= d
->GetShell();
371 InitPresContextData(s
->GetPresContext());
379 already_AddRefed
<Event
>
380 Event::Constructor(const GlobalObject
& aGlobal
,
381 const nsAString
& aType
,
382 const EventInit
& aParam
,
385 nsCOMPtr
<mozilla::dom::EventTarget
> t
= do_QueryInterface(aGlobal
.GetAsSupports());
386 nsRefPtr
<Event
> e
= new Event(t
, nullptr, nullptr);
387 bool trusted
= e
->Init(t
);
388 aRv
= e
->InitEvent(aType
, aParam
.mBubbles
, aParam
.mCancelable
);
389 e
->SetTrusted(trusted
);
394 Event::EventPhase() const
396 // Note, remember to check that this works also
397 // if or when Bug 235441 is fixed.
398 if ((mEvent
->currentTarget
&&
399 mEvent
->currentTarget
== mEvent
->target
) ||
400 mEvent
->mFlags
.InTargetPhase()) {
401 return nsIDOMEvent::AT_TARGET
;
403 if (mEvent
->mFlags
.mInCapturePhase
) {
404 return nsIDOMEvent::CAPTURING_PHASE
;
406 if (mEvent
->mFlags
.mInBubblingPhase
) {
407 return nsIDOMEvent::BUBBLING_PHASE
;
409 return nsIDOMEvent::NONE
;
413 Event::GetEventPhase(uint16_t* aEventPhase
)
415 *aEventPhase
= EventPhase();
420 Event::GetBubbles(bool* aBubbles
)
422 *aBubbles
= Bubbles();
427 Event::GetCancelable(bool* aCancelable
)
429 *aCancelable
= Cancelable();
434 Event::GetTimeStamp(uint64_t* aTimeStamp
)
436 *aTimeStamp
= mEvent
->time
;
441 Event::StopPropagation()
443 mEvent
->mFlags
.mPropagationStopped
= true;
448 Event::StopImmediatePropagation()
450 mEvent
->mFlags
.mPropagationStopped
= true;
451 mEvent
->mFlags
.mImmediatePropagationStopped
= true;
456 Event::GetIsTrusted(bool* aIsTrusted
)
458 *aIsTrusted
= IsTrusted();
463 Event::PreventDefault()
465 // This method is called only from C++ code which must handle default action
466 // of this event. So, pass true always.
467 PreventDefaultInternal(true);
472 Event::PreventDefault(JSContext
* aCx
)
474 MOZ_ASSERT(aCx
, "JS context must be specified");
476 // Note that at handling default action, another event may be dispatched.
477 // Then, JS in content mey be call preventDefault()
478 // even in the event is in system event group. Therefore, don't refer
479 // mInSystemGroup here.
480 PreventDefaultInternal(IsChrome(aCx
));
484 Event::PreventDefaultInternal(bool aCalledByDefaultHandler
)
486 if (!mEvent
->mFlags
.mCancelable
) {
490 mEvent
->mFlags
.mDefaultPrevented
= true;
492 // Note that even if preventDefault() has already been called by chrome,
493 // a call of preventDefault() by content needs to overwrite
494 // mDefaultPreventedByContent to true because in such case, defaultPrevented
495 // must be true when web apps check it after they call preventDefault().
496 if (!aCalledByDefaultHandler
) {
497 mEvent
->mFlags
.mDefaultPreventedByContent
= true;
504 WidgetDragEvent
* dragEvent
= mEvent
->AsDragEvent();
509 nsCOMPtr
<nsINode
> node
= do_QueryInterface(mEvent
->currentTarget
);
511 nsCOMPtr
<nsPIDOMWindow
> win
= do_QueryInterface(mEvent
->currentTarget
);
515 node
= win
->GetExtantDoc();
517 if (!nsContentUtils::IsChromeDoc(node
->OwnerDoc())) {
518 dragEvent
->mDefaultPreventedOnContent
= true;
523 Event::SetEventType(const nsAString
& aEventTypeArg
)
525 if (mIsMainThreadEvent
) {
527 nsContentUtils::GetEventIdAndAtom(aEventTypeArg
, mEvent
->eventStructType
,
530 mEvent
->userType
= nullptr;
531 mEvent
->message
= NS_USER_DEFINED_EVENT
;
532 mEvent
->typeString
= aEventTypeArg
;
537 Event::InitEvent(const nsAString
& aEventTypeArg
,
541 // Make sure this event isn't already being dispatched.
542 NS_ENSURE_TRUE(!mEvent
->mFlags
.mIsBeingDispatched
, NS_OK
);
545 // Ensure the caller is permitted to dispatch trusted DOM events.
546 if (!nsContentUtils::ThreadsafeIsCallerChrome()) {
551 SetEventType(aEventTypeArg
);
553 mEvent
->mFlags
.mBubbles
= aCanBubbleArg
;
554 mEvent
->mFlags
.mCancelable
= aCancelableArg
;
556 mEvent
->mFlags
.mDefaultPrevented
= false;
558 // Clearing the old targets, so that the event is targeted correctly when
559 // re-dispatching it.
560 mEvent
->target
= nullptr;
561 mEvent
->originalTarget
= nullptr;
566 Event::DuplicatePrivateData()
568 NS_ASSERTION(mEvent
, "No WidgetEvent for Event duplication!");
569 if (mEventIsInternal
) {
573 mEvent
= mEvent
->Duplicate();
574 mPresContext
= nullptr;
575 mEventIsInternal
= true;
576 mPrivateDataDuplicated
= true;
582 Event::SetTarget(nsIDOMEventTarget
* aTarget
)
586 nsCOMPtr
<nsPIDOMWindow
> win
= do_QueryInterface(aTarget
);
588 NS_ASSERTION(!win
|| !win
->IsInnerWindow(),
589 "Uh, inner window set as event target!");
593 mEvent
->target
= do_QueryInterface(aTarget
);
598 Event::IsDispatchStopped()
600 return mEvent
->mFlags
.mPropagationStopped
;
603 NS_IMETHODIMP_(WidgetEvent
*)
604 Event::GetInternalNSEvent()
609 NS_IMETHODIMP_(Event
*)
610 Event::InternalDOMEvent()
615 // return true if eventName is contained within events, delimited by
618 PopupAllowedForEvent(const char *eventName
)
620 if (!sPopupAllowedEvents
) {
621 Event::PopupAllowedEventsChanged();
623 if (!sPopupAllowedEvents
) {
628 nsDependentCString
events(sPopupAllowedEvents
);
630 nsAFlatCString::const_iterator start
, end
;
631 nsAFlatCString::const_iterator
startiter(events
.BeginReading(start
));
632 events
.EndReading(end
);
634 while (startiter
!= end
) {
635 nsAFlatCString::const_iterator
enditer(end
);
637 if (!FindInReadable(nsDependentCString(eventName
), startiter
, enditer
))
640 // the match is surrounded by spaces, or at a string boundary
641 if ((startiter
== start
|| *--startiter
== ' ') &&
642 (enditer
== end
|| *enditer
== ' ')) {
646 // Move on and see if there are other matches. (The delimitation
647 // requirement makes it pointless to begin the next search before
648 // the end of the invalid match just found.)
657 Event::GetEventPopupControlState(WidgetEvent
* aEvent
)
659 // generally if an event handler is running, new windows are disallowed.
660 // check for exceptions:
661 PopupControlState abuse
= openAbused
;
663 switch(aEvent
->eventStructType
) {
665 // For these following events only allow popups if they're
666 // triggered while handling user input. See
667 // nsPresShell::HandleEventInternal() for details.
668 if (EventStateManager::IsHandlingUserInput()) {
669 switch(aEvent
->message
) {
670 case NS_FORM_SELECTED
:
671 if (PopupAllowedForEvent("select")) {
672 abuse
= openControlled
;
675 case NS_FORM_CHANGE
:
676 if (PopupAllowedForEvent("change")) {
677 abuse
= openControlled
;
683 case NS_EDITOR_INPUT_EVENT
:
684 // For this following event only allow popups if it's triggered
685 // while handling user input. See
686 // nsPresShell::HandleEventInternal() for details.
687 if (EventStateManager::IsHandlingUserInput()) {
688 switch(aEvent
->message
) {
689 case NS_EDITOR_INPUT
:
690 if (PopupAllowedForEvent("input")) {
691 abuse
= openControlled
;
697 case NS_INPUT_EVENT
:
698 // For this following event only allow popups if it's triggered
699 // while handling user input. See
700 // nsPresShell::HandleEventInternal() for details.
701 if (EventStateManager::IsHandlingUserInput()) {
702 switch(aEvent
->message
) {
703 case NS_FORM_CHANGE
:
704 if (PopupAllowedForEvent("change")) {
705 abuse
= openControlled
;
709 abuse
= openControlled
;
715 if (aEvent
->mFlags
.mIsTrusted
) {
716 uint32_t key
= aEvent
->AsKeyboardEvent()->keyCode
;
717 switch(aEvent
->message
) {
719 // return key on focused button. see note at NS_MOUSE_CLICK.
720 if (key
== nsIDOMKeyEvent::DOM_VK_RETURN
) {
722 } else if (PopupAllowedForEvent("keypress")) {
723 abuse
= openControlled
;
727 // space key on focused button. see note at NS_MOUSE_CLICK.
728 if (key
== nsIDOMKeyEvent::DOM_VK_SPACE
) {
730 } else if (PopupAllowedForEvent("keyup")) {
731 abuse
= openControlled
;
735 if (PopupAllowedForEvent("keydown")) {
736 abuse
= openControlled
;
742 case NS_TOUCH_EVENT
:
743 if (aEvent
->mFlags
.mIsTrusted
) {
744 switch (aEvent
->message
) {
745 case NS_TOUCH_START
:
746 if (PopupAllowedForEvent("touchstart")) {
747 abuse
= openControlled
;
751 if (PopupAllowedForEvent("touchend")) {
752 abuse
= openControlled
;
758 case NS_MOUSE_EVENT
:
759 if (aEvent
->mFlags
.mIsTrusted
&&
760 aEvent
->AsMouseEvent()->button
== WidgetMouseEvent::eLeftButton
) {
761 switch(aEvent
->message
) {
762 case NS_MOUSE_BUTTON_UP
:
763 if (PopupAllowedForEvent("mouseup")) {
764 abuse
= openControlled
;
767 case NS_MOUSE_BUTTON_DOWN
:
768 if (PopupAllowedForEvent("mousedown")) {
769 abuse
= openControlled
;
772 case NS_MOUSE_CLICK
:
773 /* Click events get special treatment because of their
774 historical status as a more legitimate event handler. If
775 click popups are enabled in the prefs, clear the popup
776 status completely. */
777 if (PopupAllowedForEvent("click")) {
781 case NS_MOUSE_DOUBLECLICK
:
782 if (PopupAllowedForEvent("dblclick")) {
783 abuse
= openControlled
;
790 // For these following events only allow popups if they're
791 // triggered while handling user input. See
792 // nsPresShell::HandleEventInternal() for details.
793 if (EventStateManager::IsHandlingUserInput()) {
794 switch(aEvent
->message
) {
795 case NS_FORM_SUBMIT
:
796 if (PopupAllowedForEvent("submit")) {
797 abuse
= openControlled
;
801 if (PopupAllowedForEvent("reset")) {
802 abuse
= openControlled
;
817 Event::PopupAllowedEventsChanged()
819 if (sPopupAllowedEvents
) {
820 nsMemory::Free(sPopupAllowedEvents
);
823 nsAdoptingCString str
= Preferences::GetCString("dom.popup_allowed_events");
825 // We'll want to do this even if str is empty to avoid looking up
826 // this pref all the time if it's not set.
827 sPopupAllowedEvents
= ToNewCString(str
);
834 if (sPopupAllowedEvents
) {
835 nsMemory::Free(sPopupAllowedEvents
);
840 Event::GetScreenCoords(nsPresContext
* aPresContext
,
842 LayoutDeviceIntPoint aPoint
)
844 if (EventStateManager::sIsPointerLocked
) {
845 return EventStateManager::sLastScreenPoint
;
849 (aEvent
->eventStructType
!= NS_MOUSE_EVENT
&&
850 aEvent
->eventStructType
!= NS_MOUSE_SCROLL_EVENT
&&
851 aEvent
->eventStructType
!= NS_WHEEL_EVENT
&&
852 aEvent
->eventStructType
!= NS_POINTER_EVENT
&&
853 aEvent
->eventStructType
!= NS_TOUCH_EVENT
&&
854 aEvent
->eventStructType
!= NS_DRAG_EVENT
&&
855 aEvent
->eventStructType
!= NS_SIMPLE_GESTURE_EVENT
)) {
856 return nsIntPoint(0, 0);
859 WidgetGUIEvent
* guiEvent
= aEvent
->AsGUIEvent();
860 if (!guiEvent
->widget
) {
861 return LayoutDeviceIntPoint::ToUntyped(aPoint
);
864 LayoutDeviceIntPoint offset
= aPoint
+
865 LayoutDeviceIntPoint::FromUntyped(guiEvent
->widget
->WidgetToScreenOffset());
866 nscoord factor
= aPresContext
->DeviceContext()->UnscaledAppUnitsPerDevPixel();
867 return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(offset
.x
* factor
),
868 nsPresContext::AppUnitsToIntCSSPixels(offset
.y
* factor
));
873 Event::GetPageCoords(nsPresContext
* aPresContext
,
875 LayoutDeviceIntPoint aPoint
,
876 CSSIntPoint aDefaultPoint
)
878 CSSIntPoint pagePoint
=
879 Event::GetClientCoords(aPresContext
, aEvent
, aPoint
, aDefaultPoint
);
881 // If there is some scrolling, add scroll info to client point.
882 if (aPresContext
&& aPresContext
->GetPresShell()) {
883 nsIPresShell
* shell
= aPresContext
->GetPresShell();
884 nsIScrollableFrame
* scrollframe
= shell
->GetRootScrollFrameAsScrollable();
886 pagePoint
+= CSSIntPoint::FromAppUnitsRounded(scrollframe
->GetScrollPosition());
895 Event::GetClientCoords(nsPresContext
* aPresContext
,
897 LayoutDeviceIntPoint aPoint
,
898 CSSIntPoint aDefaultPoint
)
900 if (EventStateManager::sIsPointerLocked
) {
901 return EventStateManager::sLastClientPoint
;
905 (aEvent
->eventStructType
!= NS_MOUSE_EVENT
&&
906 aEvent
->eventStructType
!= NS_MOUSE_SCROLL_EVENT
&&
907 aEvent
->eventStructType
!= NS_WHEEL_EVENT
&&
908 aEvent
->eventStructType
!= NS_TOUCH_EVENT
&&
909 aEvent
->eventStructType
!= NS_DRAG_EVENT
&&
910 aEvent
->eventStructType
!= NS_POINTER_EVENT
&&
911 aEvent
->eventStructType
!= NS_SIMPLE_GESTURE_EVENT
) ||
913 !aEvent
->AsGUIEvent()->widget
) {
914 return aDefaultPoint
;
917 nsIPresShell
* shell
= aPresContext
->GetPresShell();
919 return CSSIntPoint(0, 0);
922 nsIFrame
* rootFrame
= shell
->GetRootFrame();
924 return CSSIntPoint(0, 0);
927 nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent
,
928 LayoutDeviceIntPoint::ToUntyped(aPoint
), rootFrame
);
930 return CSSIntPoint::FromAppUnitsRounded(pt
);
933 // To be called ONLY by Event::GetType (which has the additional
934 // logic for handling user-defined events).
937 Event::GetEventName(uint32_t aEventType
)
940 #define ID_TO_EVENT(name_, _id, _type, _struct) \
941 case _id: return #name_;
942 #include "mozilla/EventNameList.h"
947 // XXXldb We can hit this case for WidgetEvent objects that we didn't
948 // create and that are not user defined events since this function and
949 // SetEventType are incomplete. (But fixing that requires fixing the
950 // arrays in nsEventListenerManager too, since the events for which
951 // this is a problem generally *are* created by Event.)
956 Event::DefaultPrevented(JSContext
* aCx
) const
958 MOZ_ASSERT(aCx
, "JS context must be specified");
960 NS_ENSURE_TRUE(mEvent
, false);
962 // If preventDefault() has never been called, just return false.
963 if (!mEvent
->mFlags
.mDefaultPrevented
) {
967 // If preventDefault() has been called by content, return true. Otherwise,
968 // i.e., preventDefault() has been called by chrome, return true only when
969 // this is called by chrome.
970 return mEvent
->mFlags
.mDefaultPreventedByContent
|| IsChrome(aCx
);
974 Event::TimeStamp() const
976 if (!sReturnHighResTimeStamp
) {
977 return static_cast<double>(mEvent
->time
);
980 if (mEvent
->timeStamp
.IsNull()) {
984 if (mIsMainThreadEvent
) {
985 if (NS_WARN_IF(!mOwner
)) {
989 nsPerformance
* perf
= mOwner
->GetPerformance();
990 if (NS_WARN_IF(!perf
)) {
994 return perf
->GetDOMTiming()->TimeStampToDOMHighRes(mEvent
->timeStamp
);
997 // For dedicated workers, we should make times relative to the navigation
998 // start of the document that created the worker. We currently don't have
999 // that information handy so for now we treat shared workers and dedicated
1000 // workers alike and make times relative to the worker creation time. We can
1001 // fix this when we implement WorkerPerformance.
1002 workers::WorkerPrivate
* workerPrivate
=
1003 workers::GetCurrentThreadWorkerPrivate();
1004 MOZ_ASSERT(workerPrivate
);
1006 TimeDuration duration
=
1007 mEvent
->timeStamp
- workerPrivate
->CreationTimeStamp();
1008 return duration
.ToMilliseconds();
1012 Event::GetPreventDefault() const
1015 if (nsIDocument
* doc
= mOwner
->GetExtantDoc()) {
1016 doc
->WarnOnceAbout(nsIDocument::eGetPreventDefault
);
1019 // GetPreventDefault() is legacy and Gecko specific method. Although,
1020 // the result should be same as defaultPrevented, we don't need to break
1021 // backward compatibility of legacy method. Let's behave traditionally.
1022 return DefaultPrevented();
1026 Event::GetPreventDefault(bool* aReturn
)
1028 NS_ENSURE_ARG_POINTER(aReturn
);
1029 *aReturn
= GetPreventDefault();
1034 Event::GetDefaultPrevented(bool* aReturn
)
1036 NS_ENSURE_ARG_POINTER(aReturn
);
1037 // This method must be called by only event handlers implemented by C++.
1038 // Then, the handlers must handle default action. So, this method don't need
1039 // to check if preventDefault() has been called by content or chrome.
1040 *aReturn
= DefaultPrevented();
1044 NS_IMETHODIMP_(void)
1045 Event::Serialize(IPC::Message
* aMsg
, bool aSerializeInterfaceType
)
1047 if (aSerializeInterfaceType
) {
1048 IPC::WriteParam(aMsg
, NS_LITERAL_STRING("event"));
1053 IPC::WriteParam(aMsg
, type
);
1055 IPC::WriteParam(aMsg
, Bubbles());
1056 IPC::WriteParam(aMsg
, Cancelable());
1057 IPC::WriteParam(aMsg
, IsTrusted());
1059 // No timestamp serialization for now!
1062 NS_IMETHODIMP_(bool)
1063 Event::Deserialize(const IPC::Message
* aMsg
, void** aIter
)
1066 NS_ENSURE_TRUE(IPC::ReadParam(aMsg
, aIter
, &type
), false);
1068 bool bubbles
= false;
1069 NS_ENSURE_TRUE(IPC::ReadParam(aMsg
, aIter
, &bubbles
), false);
1071 bool cancelable
= false;
1072 NS_ENSURE_TRUE(IPC::ReadParam(aMsg
, aIter
, &cancelable
), false);
1074 bool trusted
= false;
1075 NS_ENSURE_TRUE(IPC::ReadParam(aMsg
, aIter
, &trusted
), false);
1077 nsresult rv
= InitEvent(type
, bubbles
, cancelable
);
1078 NS_ENSURE_SUCCESS(rv
, false);
1079 SetTrusted(trusted
);
1084 NS_IMETHODIMP_(void)
1085 Event::SetOwner(mozilla::dom::EventTarget
* aOwner
)
1093 nsCOMPtr
<nsINode
> n
= do_QueryInterface(aOwner
);
1095 mOwner
= do_QueryInterface(n
->OwnerDoc()->GetScopeObject());
1099 nsCOMPtr
<nsPIDOMWindow
> w
= do_QueryInterface(aOwner
);
1101 if (w
->IsOuterWindow()) {
1102 mOwner
= w
->GetCurrentInnerWindow();
1109 nsCOMPtr
<DOMEventTargetHelper
> eth
= do_QueryInterface(aOwner
);
1111 mOwner
= eth
->GetOwner();
1116 nsCOMPtr
<nsPIWindowRoot
> root
= do_QueryInterface(aOwner
);
1117 MOZ_ASSERT(root
, "Unexpected EventTarget!");
1122 } // namespace mozilla
1124 using namespace mozilla
;
1125 using namespace mozilla::dom
;
1128 NS_NewDOMEvent(nsIDOMEvent
** aInstancePtrResult
,
1129 EventTarget
* aOwner
,
1130 nsPresContext
* aPresContext
,
1131 WidgetEvent
* aEvent
)
1133 Event
* it
= new Event(aOwner
, aPresContext
, aEvent
);
1135 *aInstancePtrResult
= static_cast<Event
*>(it
);