1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "AccessCheck.h"
8 #include "base/basictypes.h"
9 #include "ipc/IPCMessageUtils.h"
10 #include "ipc/IPCMessageUtilsSpecializations.h"
11 #include "mozilla/EventDispatcher.h"
12 #include "mozilla/BasePrincipal.h"
13 #include "mozilla/ContentEvents.h"
14 #include "mozilla/DOMEventTargetHelper.h"
15 #include "mozilla/EventStateManager.h"
16 #include "mozilla/InternalMutationEvent.h"
17 #include "mozilla/dom/Performance.h"
18 #include "mozilla/dom/WorkerPrivate.h"
19 #include "mozilla/MiscEvents.h"
20 #include "mozilla/MouseEvents.h"
21 #include "mozilla/PointerLockManager.h"
22 #include "mozilla/Preferences.h"
23 #include "mozilla/PresShell.h"
24 #include "mozilla/TextEvents.h"
25 #include "mozilla/TouchEvents.h"
26 #include "mozilla/ViewportUtils.h"
27 #include "mozilla/dom/Document.h"
28 #include "mozilla/dom/DocumentInlines.h"
29 #include "mozilla/dom/Event.h"
30 #include "mozilla/dom/ShadowRoot.h"
31 #include "mozilla/dom/WorkerScope.h"
32 #include "mozilla/StaticPrefs_dom.h"
33 #include "mozilla/SVGUtils.h"
34 #include "mozilla/SVGOuterSVGFrame.h"
35 #include "nsContentUtils.h"
37 #include "nsDeviceContext.h"
39 #include "nsGlobalWindow.h"
41 #include "nsIContent.h"
42 #include "nsIContentInlines.h"
43 #include "nsIScrollableFrame.h"
44 #include "nsJSEnvironment.h"
45 #include "nsLayoutUtils.h"
46 #include "nsPIWindowRoot.h"
47 #include "nsRFPService.h"
49 namespace mozilla::dom
{
51 Event::Event(EventTarget
* aOwner
, nsPresContext
* aPresContext
,
52 WidgetEvent
* aEvent
) {
53 ConstructorInit(aOwner
, aPresContext
, aEvent
);
56 Event::Event(nsPIDOMWindowInner
* aParent
) {
57 ConstructorInit(nsGlobalWindowInner::Cast(aParent
), nullptr, nullptr);
60 void Event::ConstructorInit(EventTarget
* aOwner
, nsPresContext
* aPresContext
,
61 WidgetEvent
* aEvent
) {
63 mIsMainThreadEvent
= NS_IsMainThread();
65 mPrivateDataDuplicated
= false;
66 mWantsPopupControlCheck
= false;
70 mEventIsInternal
= false;
72 mEventIsInternal
= true;
74 A derived class might want to allocate its own type of aEvent
75 (derived from WidgetEvent). To do this, it should take care to pass
76 a non-nullptr aEvent to this ctor, e.g.:
78 FooEvent::FooEvent(..., WidgetEvent* aEvent)
79 : Event(..., aEvent ? aEvent : new WidgetEvent())
81 Then, to override the mEventIsInternal assignments done by the
82 base ctor, it should do this in its own ctor:
84 FooEvent::FooEvent(..., WidgetEvent* aEvent)
89 mEventIsInternal = false;
92 mEventIsInternal = true;
97 mEvent
= new WidgetEvent(false, eVoidEvent
);
100 InitPresContextData(aPresContext
);
103 void Event::InitPresContextData(nsPresContext
* aPresContext
) {
104 mPresContext
= aPresContext
;
105 // Get the explicit original target (if it's anonymous make it null)
107 nsCOMPtr
<nsIContent
> content
= GetTargetFromFrame();
108 if (content
&& !content
->IsInNativeAnonymousSubtree()) {
109 mExplicitOriginalTarget
= std::move(content
);
111 mExplicitOriginalTarget
= nullptr;
117 NS_ASSERT_OWNINGTHREAD(Event
);
119 if (mEventIsInternal
&& mEvent
) {
124 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Event
)
125 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
126 NS_INTERFACE_MAP_ENTRY(nsISupports
)
127 NS_INTERFACE_MAP_ENTRY(Event
)
130 NS_IMPL_CYCLE_COLLECTING_ADDREF(Event
)
131 NS_IMPL_CYCLE_COLLECTING_RELEASE(Event
)
133 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(Event
)
135 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Event
)
136 if (tmp
->mEventIsInternal
) {
137 tmp
->mEvent
->mTarget
= nullptr;
138 tmp
->mEvent
->mCurrentTarget
= nullptr;
139 tmp
->mEvent
->mOriginalTarget
= nullptr;
140 tmp
->mEvent
->mRelatedTarget
= nullptr;
141 tmp
->mEvent
->mOriginalRelatedTarget
= nullptr;
142 switch (tmp
->mEvent
->mClass
) {
143 case eDragEventClass
: {
144 WidgetDragEvent
* dragEvent
= tmp
->mEvent
->AsDragEvent();
145 dragEvent
->mDataTransfer
= nullptr;
148 case eClipboardEventClass
:
149 tmp
->mEvent
->AsClipboardEvent()->mClipboardData
= nullptr;
151 case eEditorInputEventClass
: {
152 InternalEditorInputEvent
* inputEvent
=
153 tmp
->mEvent
->AsEditorInputEvent();
154 inputEvent
->mDataTransfer
= nullptr;
155 inputEvent
->mTargetRanges
.Clear();
158 case eMutationEventClass
:
159 tmp
->mEvent
->AsMutationEvent()->mRelatedNode
= nullptr;
165 if (WidgetMouseEvent
* mouseEvent
= tmp
->mEvent
->AsMouseEvent()) {
166 mouseEvent
->mClickTarget
= nullptr;
169 NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext
);
170 NS_IMPL_CYCLE_COLLECTION_UNLINK(mExplicitOriginalTarget
);
171 NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner
);
172 NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
173 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
175 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Event
)
176 if (tmp
->mEventIsInternal
) {
177 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent
->mTarget
)
178 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent
->mCurrentTarget
)
179 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent
->mOriginalTarget
)
180 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent
->mRelatedTarget
)
181 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvent
->mOriginalRelatedTarget
);
182 switch (tmp
->mEvent
->mClass
) {
183 case eDragEventClass
: {
184 WidgetDragEvent
* dragEvent
= tmp
->mEvent
->AsDragEvent();
185 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->mDataTransfer");
186 cb
.NoteXPCOMChild(dragEvent
->mDataTransfer
);
189 case eClipboardEventClass
:
190 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->mClipboardData");
191 cb
.NoteXPCOMChild(tmp
->mEvent
->AsClipboardEvent()->mClipboardData
);
193 case eEditorInputEventClass
:
194 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->mDataTransfer");
195 cb
.NoteXPCOMChild(tmp
->mEvent
->AsEditorInputEvent()->mDataTransfer
);
196 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(
197 mEvent
->AsEditorInputEvent()->mTargetRanges
);
199 case eMutationEventClass
:
200 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->mRelatedNode");
201 cb
.NoteXPCOMChild(tmp
->mEvent
->AsMutationEvent()->mRelatedNode
);
207 if (WidgetMouseEvent
* mouseEvent
= tmp
->mEvent
->AsMouseEvent()) {
208 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb
, "mEvent->mClickTarget");
209 cb
.NoteXPCOMChild(mouseEvent
->mClickTarget
);
212 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext
)
213 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExplicitOriginalTarget
)
214 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner
)
215 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
217 JSObject
* Event::WrapObject(JSContext
* aCx
, JS::Handle
<JSObject
*> aGivenProto
) {
218 return WrapObjectInternal(aCx
, aGivenProto
);
221 JSObject
* Event::WrapObjectInternal(JSContext
* aCx
,
222 JS::Handle
<JSObject
*> aGivenProto
) {
223 return Event_Binding::Wrap(aCx
, this, aGivenProto
);
226 void Event::GetType(nsAString
& aType
) const {
227 GetWidgetEventType(mEvent
, aType
);
230 EventTarget
* Event::GetTarget() const { return mEvent
->GetDOMEventTarget(); }
232 already_AddRefed
<Document
> Event::GetDocument() const {
233 nsCOMPtr
<EventTarget
> eventTarget
= GetTarget();
239 nsCOMPtr
<nsPIDOMWindowInner
> win
=
240 do_QueryInterface(eventTarget
->GetOwnerGlobal());
246 nsCOMPtr
<Document
> doc
;
247 doc
= win
->GetExtantDoc();
252 EventTarget
* Event::GetCurrentTarget() const {
253 return mEvent
->GetCurrentDOMEventTarget();
256 void Event::ComposedPath(nsTArray
<RefPtr
<EventTarget
>>& aPath
) {
257 EventDispatcher::GetComposedPathFor(mEvent
, aPath
);
261 // Get the actual event target node (may have been retargeted for mouse events)
263 already_AddRefed
<nsIContent
> Event::GetTargetFromFrame() {
268 // Get the mTarget frame (have to get the ESM first)
269 nsIFrame
* targetFrame
= mPresContext
->EventStateManager()->GetEventTarget();
274 // get the real content
275 nsCOMPtr
<nsIContent
> realEventContent
;
276 targetFrame
->GetContentForEvent(mEvent
, getter_AddRefs(realEventContent
));
277 return realEventContent
.forget();
280 EventTarget
* Event::GetExplicitOriginalTarget() const {
281 if (mExplicitOriginalTarget
) {
282 return mExplicitOriginalTarget
;
287 EventTarget
* Event::GetOriginalTarget() const {
288 return mEvent
->GetOriginalDOMEventTarget();
291 EventTarget
* Event::GetComposedTarget() const {
292 EventTarget
* et
= GetOriginalTarget();
293 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(et
);
297 nsIContent
* nonChrome
= content
->FindFirstNonChromeOnlyAccessContent();
298 return nonChrome
? static_cast<EventTarget
*>(nonChrome
)
299 : static_cast<EventTarget
*>(content
->GetComposedDoc());
302 void Event::SetTrusted(bool aTrusted
) { mEvent
->mFlags
.mIsTrusted
= aTrusted
; }
304 bool Event::ShouldIgnoreChromeEventTargetListener() const {
305 MOZ_ASSERT(NS_IsMainThread());
306 if (!XRE_IsParentProcess()) {
309 if (EventTarget
* currentTarget
= GetCurrentTarget();
310 NS_WARN_IF(!currentTarget
) || !currentTarget
->IsRootWindow()) {
313 EventTarget
* et
= GetOriginalTarget();
314 if (NS_WARN_IF(!et
)) {
317 nsIGlobalObject
* global
= et
->GetOwnerGlobal();
318 if (NS_WARN_IF(!global
)) {
321 nsPIDOMWindowInner
* win
= global
->AsInnerWindow();
322 if (NS_WARN_IF(!win
)) {
325 BrowsingContext
* bc
= win
->GetBrowsingContext();
326 if (NS_WARN_IF(!bc
)) {
329 // If this is a content event on an nsWindowRoot, then we also handle this in
330 // InProcessBrowserChildMessageManager, so we can ignore this event.
331 return bc
->IsContent();
334 bool Event::Init(mozilla::dom::EventTarget
* aGlobal
) {
335 if (!mIsMainThreadEvent
) {
336 return IsCurrentThreadRunningChromeWorker();
338 bool trusted
= false;
339 nsCOMPtr
<nsPIDOMWindowInner
> w
= do_QueryInterface(aGlobal
);
341 nsCOMPtr
<Document
> d
= w
->GetExtantDoc();
343 trusted
= nsContentUtils::IsChromeDoc(d
);
344 nsPresContext
* presContext
= d
->GetPresContext();
346 InitPresContextData(presContext
);
354 already_AddRefed
<Event
> Event::Constructor(const GlobalObject
& aGlobal
,
355 const nsAString
& aType
,
356 const EventInit
& aParam
) {
357 nsCOMPtr
<mozilla::dom::EventTarget
> t
=
358 do_QueryInterface(aGlobal
.GetAsSupports());
359 return Constructor(t
, aType
, aParam
);
363 already_AddRefed
<Event
> Event::Constructor(EventTarget
* aEventTarget
,
364 const nsAString
& aType
,
365 const EventInit
& aParam
) {
366 RefPtr
<Event
> e
= new Event(aEventTarget
, nullptr, nullptr);
367 bool trusted
= e
->Init(aEventTarget
);
368 e
->InitEvent(aType
, aParam
.mBubbles
, aParam
.mCancelable
);
369 e
->SetTrusted(trusted
);
370 e
->SetComposed(aParam
.mComposed
);
374 uint16_t Event::EventPhase() const {
375 if ((mEvent
->mCurrentTarget
&& mEvent
->mCurrentTarget
== mEvent
->mTarget
) ||
376 mEvent
->mFlags
.mInTargetPhase
) {
377 return Event_Binding::AT_TARGET
;
379 if (mEvent
->mFlags
.mInCapturePhase
) {
380 return Event_Binding::CAPTURING_PHASE
;
382 if (mEvent
->mFlags
.mInBubblingPhase
) {
383 return Event_Binding::BUBBLING_PHASE
;
385 return Event_Binding::NONE
;
388 void Event::StopPropagation() { mEvent
->StopPropagation(); }
390 void Event::StopImmediatePropagation() { mEvent
->StopImmediatePropagation(); }
392 void Event::StopCrossProcessForwarding() {
393 mEvent
->StopCrossProcessForwarding();
396 void Event::PreventDefault() {
397 // This method is called only from C++ code which must handle default action
398 // of this event. So, pass true always.
399 PreventDefaultInternal(true);
402 void Event::PreventDefault(JSContext
* aCx
, CallerType aCallerType
) {
403 // Note that at handling default action, another event may be dispatched.
404 // Then, JS in content mey be call preventDefault()
405 // even in the event is in system event group. Therefore, don't refer
406 // mInSystemGroup here.
407 nsIPrincipal
* principal
=
408 mIsMainThreadEvent
? nsContentUtils::SubjectPrincipal(aCx
) : nullptr;
410 PreventDefaultInternal(aCallerType
== CallerType::System
, principal
);
413 void Event::PreventDefaultInternal(bool aCalledByDefaultHandler
,
414 nsIPrincipal
* aPrincipal
) {
415 if (!mEvent
->mFlags
.mCancelable
) {
418 if (mEvent
->mFlags
.mInPassiveListener
) {
419 nsCOMPtr
<nsPIDOMWindowInner
> win(do_QueryInterface(mOwner
));
421 if (Document
* doc
= win
->GetExtantDoc()) {
422 if (!doc
->HasWarnedAbout(
423 Document::ePreventDefaultFromPassiveListener
)) {
424 AutoTArray
<nsString
, 1> params
;
425 GetType(*params
.AppendElement());
426 doc
->WarnOnceAbout(Document::ePreventDefaultFromPassiveListener
,
434 mEvent
->PreventDefault(aCalledByDefaultHandler
, aPrincipal
);
440 // If this is called by default handlers, the caller will call
441 // UpdateDefaultPreventedOnContentFor when necessary.
442 if (!aCalledByDefaultHandler
) {
443 if (WidgetDragEvent
* dragEvent
= mEvent
->AsDragEvent()) {
444 dragEvent
->UpdateDefaultPreventedOnContent(dragEvent
->mCurrentTarget
);
449 void Event::SetEventType(const nsAString
& aEventTypeArg
) {
450 mEvent
->mSpecifiedEventTypeString
.Truncate();
451 if (mIsMainThreadEvent
) {
452 mEvent
->mSpecifiedEventType
= nsContentUtils::GetEventMessageAndAtom(
453 aEventTypeArg
, mEvent
->mClass
, &(mEvent
->mMessage
));
454 mEvent
->SetDefaultComposed();
456 mEvent
->mSpecifiedEventType
= NS_Atomize(u
"on"_ns
+ aEventTypeArg
);
457 mEvent
->mMessage
= eUnidentifiedEvent
;
458 mEvent
->SetComposed(aEventTypeArg
);
460 mEvent
->SetDefaultComposedInNativeAnonymousContent();
463 already_AddRefed
<EventTarget
> Event::EnsureWebAccessibleRelatedTarget(
464 EventTarget
* aRelatedTarget
) {
465 nsCOMPtr
<EventTarget
> relatedTarget
= aRelatedTarget
;
467 nsIContent
* content
= nsIContent::FromEventTarget(relatedTarget
);
468 if (content
&& content
->ChromeOnlyAccess() &&
469 !nsContentUtils::CanAccessNativeAnon()) {
470 content
= content
->FindFirstNonChromeOnlyAccessContent();
471 relatedTarget
= content
;
475 relatedTarget
= relatedTarget
->GetTargetForDOMEvent();
478 return relatedTarget
.forget();
481 void Event::InitEvent(const nsAString
& aEventTypeArg
,
482 mozilla::CanBubble aCanBubbleArg
,
483 mozilla::Cancelable aCancelableArg
,
484 mozilla::Composed aComposedArg
) {
485 // Make sure this event isn't already being dispatched.
486 NS_ENSURE_TRUE_VOID(!mEvent
->mFlags
.mIsBeingDispatched
);
489 // Ensure the caller is permitted to dispatch trusted DOM events.
490 if (!nsContentUtils::ThreadsafeIsCallerChrome()) {
495 SetEventType(aEventTypeArg
);
497 mEvent
->mFlags
.mBubbles
= aCanBubbleArg
== CanBubble::eYes
;
498 mEvent
->mFlags
.mCancelable
= aCancelableArg
== Cancelable::eYes
;
499 if (aComposedArg
!= Composed::eDefault
) {
500 mEvent
->mFlags
.mComposed
= aComposedArg
== Composed::eYes
;
503 mEvent
->mFlags
.mDefaultPrevented
= false;
504 mEvent
->mFlags
.mDefaultPreventedByContent
= false;
505 mEvent
->mFlags
.mDefaultPreventedByChrome
= false;
506 mEvent
->mFlags
.mPropagationStopped
= false;
507 mEvent
->mFlags
.mImmediatePropagationStopped
= false;
509 // Clearing the old targets, so that the event is targeted correctly when
510 // re-dispatching it.
511 mEvent
->mTarget
= nullptr;
512 mEvent
->mOriginalTarget
= nullptr;
515 void Event::DuplicatePrivateData() {
516 NS_ASSERTION(mEvent
, "No WidgetEvent for Event duplication!");
517 if (mEventIsInternal
) {
521 mEvent
= mEvent
->Duplicate();
522 mPresContext
= nullptr;
523 mEventIsInternal
= true;
524 mPrivateDataDuplicated
= true;
527 void Event::SetTarget(EventTarget
* aTarget
) { mEvent
->mTarget
= aTarget
; }
529 bool Event::IsDispatchStopped() { return mEvent
->PropagationStopped(); }
531 WidgetEvent
* Event::WidgetEventPtr() { return mEvent
; }
534 Maybe
<CSSIntPoint
> Event::GetScreenCoords(nsPresContext
* aPresContext
,
536 LayoutDeviceIntPoint aPoint
) {
537 if (PointerLockManager::IsLocked()) {
538 return Some(EventStateManager::sLastScreenPoint
);
541 if (!aEvent
|| (aEvent
->mClass
!= eMouseEventClass
&&
542 aEvent
->mClass
!= eMouseScrollEventClass
&&
543 aEvent
->mClass
!= eWheelEventClass
&&
544 aEvent
->mClass
!= ePointerEventClass
&&
545 aEvent
->mClass
!= eTouchEventClass
&&
546 aEvent
->mClass
!= eDragEventClass
&&
547 aEvent
->mClass
!= eSimpleGestureEventClass
)) {
551 // Doing a straight conversion from LayoutDeviceIntPoint to CSSIntPoint
552 // seem incorrect, but it is needed to maintain legacy functionality.
553 WidgetGUIEvent
* guiEvent
= aEvent
->AsGUIEvent();
554 if (!aPresContext
|| !(guiEvent
&& guiEvent
->mWidget
)) {
555 return Some(CSSIntPoint(aPoint
.x
, aPoint
.y
));
558 // (Potentially) transform the point from the coordinate space of an
559 // out-of-process iframe to the coordinate space of the native
560 // window. The transform can only be applied to a point whose components
561 // are floating-point values, so convert the integer point first, then
562 // transform, and then round the result back to an integer point.
563 LayoutDevicePoint
floatPoint(aPoint
);
564 LayoutDevicePoint topLevelPoint
=
565 guiEvent
->mWidget
->WidgetToTopLevelWidgetTransform().TransformPoint(
567 LayoutDeviceIntPoint rounded
= RoundedToInt(topLevelPoint
);
569 nsPoint pt
= LayoutDevicePixel::ToAppUnits(
570 rounded
, aPresContext
->DeviceContext()->AppUnitsPerDevPixel());
572 pt
+= LayoutDevicePixel::ToAppUnits(
573 guiEvent
->mWidget
->TopLevelWidgetToScreenOffset(),
574 aPresContext
->DeviceContext()->AppUnitsPerDevPixel());
576 return Some(CSSPixel::FromAppUnitsRounded(pt
));
580 CSSIntPoint
Event::GetPageCoords(nsPresContext
* aPresContext
,
582 LayoutDeviceIntPoint aPoint
,
583 CSSIntPoint aDefaultPoint
) {
584 CSSIntPoint pagePoint
=
585 Event::GetClientCoords(aPresContext
, aEvent
, aPoint
, aDefaultPoint
);
587 // If there is some scrolling, add scroll info to client point.
588 if (aPresContext
&& aPresContext
->GetPresShell()) {
589 PresShell
* presShell
= aPresContext
->PresShell();
590 nsIScrollableFrame
* scrollframe
=
591 presShell
->GetRootScrollFrameAsScrollable();
594 CSSIntPoint::FromAppUnitsRounded(scrollframe
->GetScrollPosition());
602 CSSIntPoint
Event::GetClientCoords(nsPresContext
* aPresContext
,
604 LayoutDeviceIntPoint aPoint
,
605 CSSIntPoint aDefaultPoint
) {
606 if (PointerLockManager::IsLocked()) {
607 return EventStateManager::sLastClientPoint
;
611 (aEvent
->mClass
!= eMouseEventClass
&&
612 aEvent
->mClass
!= eMouseScrollEventClass
&&
613 aEvent
->mClass
!= eWheelEventClass
&&
614 aEvent
->mClass
!= eTouchEventClass
&&
615 aEvent
->mClass
!= eDragEventClass
&&
616 aEvent
->mClass
!= ePointerEventClass
&&
617 aEvent
->mClass
!= eSimpleGestureEventClass
) ||
618 !aPresContext
|| !aEvent
->AsGUIEvent()->mWidget
) {
619 return aDefaultPoint
;
622 PresShell
* presShell
= aPresContext
->GetPresShell();
624 return CSSIntPoint(0, 0);
626 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
628 return CSSIntPoint(0, 0);
630 nsPoint pt
= nsLayoutUtils::GetEventCoordinatesRelativeTo(
631 aEvent
, aPoint
, RelativeTo
{rootFrame
});
633 return CSSIntPoint::FromAppUnitsRounded(pt
);
637 CSSIntPoint
Event::GetOffsetCoords(nsPresContext
* aPresContext
,
639 LayoutDeviceIntPoint aPoint
,
640 CSSIntPoint aDefaultPoint
) {
641 if (!aEvent
->mTarget
) {
642 return GetPageCoords(aPresContext
, aEvent
, aPoint
, aDefaultPoint
);
644 nsCOMPtr
<nsIContent
> content
= nsIContent::FromEventTarget(aEvent
->mTarget
);
645 if (!content
|| !aPresContext
) {
646 return CSSIntPoint();
648 RefPtr
<PresShell
> presShell
= aPresContext
->GetPresShell();
650 return CSSIntPoint();
652 presShell
->FlushPendingNotifications(FlushType::Layout
);
653 nsIFrame
* frame
= content
->GetPrimaryFrame();
655 return CSSIntPoint();
657 // For compat, see https://github.com/w3c/csswg-drafts/issues/1508. In SVG we
658 // just return the coordinates of the outer SVG box. This is all kinda
660 if (frame
->HasAnyStateBits(NS_FRAME_SVG_LAYOUT
) &&
661 StaticPrefs::dom_events_offset_in_svg_relative_to_svg_root()) {
662 frame
= SVGUtils::GetOuterSVGFrame(frame
);
664 return CSSIntPoint();
667 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
669 return CSSIntPoint();
671 CSSIntPoint clientCoords
=
672 GetClientCoords(aPresContext
, aEvent
, aPoint
, aDefaultPoint
);
673 nsPoint pt
= CSSPixel::ToAppUnits(clientCoords
);
674 if (nsLayoutUtils::TransformPoint(RelativeTo
{rootFrame
}, RelativeTo
{frame
},
675 pt
) == nsLayoutUtils::TRANSFORM_SUCCEEDED
) {
676 pt
-= frame
->GetPaddingRectRelativeToSelf().TopLeft();
677 return CSSPixel::FromAppUnitsRounded(pt
);
679 return CSSIntPoint();
682 // To be called ONLY by Event::GetType (which has the additional
683 // logic for handling user-defined events).
685 const char16_t
* Event::GetEventName(EventMessage aEventType
) {
686 switch (aEventType
) {
687 #define MESSAGE_TO_EVENT(name_, _message, _type, _struct) \
690 #include "mozilla/EventNameList.h"
691 #undef MESSAGE_TO_EVENT
695 // XXXldb We can hit this case for WidgetEvent objects that we didn't
696 // create and that are not user defined events since this function and
697 // SetEventType are incomplete. (But fixing that requires fixing the
698 // arrays in nsEventListenerManager too, since the events for which
699 // this is a problem generally *are* created by Event.)
703 bool Event::DefaultPrevented(CallerType aCallerType
) const {
704 NS_ENSURE_TRUE(mEvent
, false);
706 // If preventDefault() has never been called, just return false.
707 if (!mEvent
->DefaultPrevented()) {
711 // If preventDefault() has been called by content, return true. Otherwise,
712 // i.e., preventDefault() has been called by chrome, return true only when
713 // this is called by chrome.
714 return mEvent
->DefaultPreventedByContent() ||
715 aCallerType
== CallerType::System
;
718 bool Event::ReturnValue(CallerType aCallerType
) const {
719 return !DefaultPrevented(aCallerType
);
722 void Event::SetReturnValue(bool aReturnValue
, CallerType aCallerType
) {
724 PreventDefaultInternal(aCallerType
== CallerType::System
);
728 double Event::TimeStamp() {
729 if (mEvent
->mTimeStamp
.IsNull()) {
733 if (mIsMainThreadEvent
) {
734 if (NS_WARN_IF(!mOwner
)) {
738 nsCOMPtr
<nsPIDOMWindowInner
> win
= do_QueryInterface(mOwner
);
739 if (NS_WARN_IF(!win
)) {
743 Performance
* perf
= win
->GetPerformance();
744 if (NS_WARN_IF(!perf
)) {
749 perf
->GetDOMTiming()->TimeStampToDOMHighRes(mEvent
->mTimeStamp
);
750 MOZ_ASSERT(mOwner
->PrincipalOrNull());
752 return nsRFPService::ReduceTimePrecisionAsMSecs(
753 ret
, perf
->GetRandomTimelineSeed(), perf
->GetRTPCallerType());
756 WorkerPrivate
* workerPrivate
= GetCurrentThreadWorkerPrivate();
757 MOZ_ASSERT(workerPrivate
);
759 double ret
= workerPrivate
->TimeStampToDOMHighRes(mEvent
->mTimeStamp
);
761 return nsRFPService::ReduceTimePrecisionAsMSecs(
762 ret
, workerPrivate
->GetRandomTimelineSeed(),
763 workerPrivate
->GlobalScope()->GetRTPCallerType());
766 void Event::Serialize(IPC::MessageWriter
* aWriter
,
767 bool aSerializeInterfaceType
) {
768 if (aSerializeInterfaceType
) {
769 IPC::WriteParam(aWriter
, u
"event"_ns
);
774 IPC::WriteParam(aWriter
, type
);
776 IPC::WriteParam(aWriter
, Bubbles());
777 IPC::WriteParam(aWriter
, Cancelable());
778 IPC::WriteParam(aWriter
, IsTrusted());
779 IPC::WriteParam(aWriter
, Composed());
781 // No timestamp serialization for now!
784 bool Event::Deserialize(IPC::MessageReader
* aReader
) {
786 NS_ENSURE_TRUE(IPC::ReadParam(aReader
, &type
), false);
788 bool bubbles
= false;
789 NS_ENSURE_TRUE(IPC::ReadParam(aReader
, &bubbles
), false);
791 bool cancelable
= false;
792 NS_ENSURE_TRUE(IPC::ReadParam(aReader
, &cancelable
), false);
794 bool trusted
= false;
795 NS_ENSURE_TRUE(IPC::ReadParam(aReader
, &trusted
), false);
797 bool composed
= false;
798 NS_ENSURE_TRUE(IPC::ReadParam(aReader
, &composed
), false);
800 InitEvent(type
, bubbles
, cancelable
);
802 SetComposed(composed
);
807 void Event::SetOwner(EventTarget
* aOwner
) {
814 if (nsINode
* n
= aOwner
->GetAsNode()) {
815 mOwner
= n
->OwnerDoc()->GetScopeObject();
819 if (nsPIDOMWindowInner
* w
= aOwner
->GetAsWindowInner()) {
820 mOwner
= w
->AsGlobal();
824 nsCOMPtr
<DOMEventTargetHelper
> eth
= do_QueryInterface(aOwner
);
826 mOwner
= eth
->GetParentObject();
831 nsCOMPtr
<nsPIWindowRoot
> root
= do_QueryInterface(aOwner
);
832 MOZ_ASSERT(root
, "Unexpected EventTarget!");
836 void Event::GetWidgetEventType(WidgetEvent
* aEvent
, nsAString
& aType
) {
837 if (!aEvent
->mSpecifiedEventTypeString
.IsEmpty()) {
838 aType
= aEvent
->mSpecifiedEventTypeString
;
842 const char16_t
* name
= GetEventName(aEvent
->mMessage
);
845 aType
.AssignLiteral(name
, nsString::char_traits::length(name
));
847 } else if (aEvent
->mMessage
== eUnidentifiedEvent
&&
848 aEvent
->mSpecifiedEventType
) {
850 aType
= Substring(nsDependentAtomString(aEvent
->mSpecifiedEventType
), 2);
851 aEvent
->mSpecifiedEventTypeString
= aType
;
858 bool Event::IsDragExitEnabled(JSContext
* aCx
, JSObject
* aGlobal
) {
859 return StaticPrefs::dom_event_dragexit_enabled() ||
860 nsContentUtils::IsSystemCaller(aCx
);
863 } // namespace mozilla::dom
865 using namespace mozilla
;
866 using namespace mozilla::dom
;
868 already_AddRefed
<Event
> NS_NewDOMEvent(EventTarget
* aOwner
,
869 nsPresContext
* aPresContext
,
870 WidgetEvent
* aEvent
) {
871 RefPtr
<Event
> it
= new Event(aOwner
, aPresContext
, aEvent
);