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 "mozilla/dom/MouseEvent.h"
8 #include "mozilla/MouseEvents.h"
9 #include "mozilla/BasePrincipal.h"
10 #include "nsContentUtils.h"
11 #include "nsIContent.h"
12 #include "nsIScreenManager.h"
15 namespace mozilla::dom
{
17 MouseEvent::MouseEvent(EventTarget
* aOwner
, nsPresContext
* aPresContext
,
18 WidgetMouseEventBase
* aEvent
)
19 : UIEvent(aOwner
, aPresContext
,
21 : new WidgetMouseEvent(false, eVoidEvent
, nullptr,
22 WidgetMouseEvent::eReal
)) {
23 // There's no way to make this class' ctor allocate an WidgetMouseScrollEvent.
24 // It's not that important, though, since a scroll event is not a real
27 WidgetMouseEvent
* mouseEvent
= mEvent
->AsMouseEvent();
29 mEventIsInternal
= false;
31 mEventIsInternal
= true;
32 mEvent
->mRefPoint
= LayoutDeviceIntPoint(0, 0);
33 mouseEvent
->mInputSource
= MouseEvent_Binding::MOZ_SOURCE_UNKNOWN
;
37 MOZ_ASSERT(mouseEvent
->mReason
!= WidgetMouseEvent::eSynthesized
,
38 "Don't dispatch DOM events from synthesized mouse events");
39 mDetail
= mouseEvent
->mClickCount
;
43 void MouseEvent::InitMouseEvent(const nsAString
& aType
, bool aCanBubble
,
44 bool aCancelable
, nsGlobalWindowInner
* aView
,
45 int32_t aDetail
, int32_t aScreenX
,
46 int32_t aScreenY
, int32_t aClientX
,
47 int32_t aClientY
, bool aCtrlKey
, bool aAltKey
,
48 bool aShiftKey
, bool aMetaKey
, uint16_t aButton
,
49 EventTarget
* aRelatedTarget
) {
50 NS_ENSURE_TRUE_VOID(!mEvent
->mFlags
.mIsBeingDispatched
);
52 UIEvent::InitUIEvent(aType
, aCanBubble
, aCancelable
, aView
, aDetail
);
54 switch (mEvent
->mClass
) {
55 case eMouseEventClass
:
56 case eMouseScrollEventClass
:
57 case eWheelEventClass
:
59 case ePointerEventClass
:
60 case eSimpleGestureEventClass
: {
61 WidgetMouseEventBase
* mouseEventBase
= mEvent
->AsMouseEventBase();
62 mouseEventBase
->mRelatedTarget
= aRelatedTarget
;
63 mouseEventBase
->mButton
= aButton
;
64 mouseEventBase
->InitBasicModifiers(aCtrlKey
, aAltKey
, aShiftKey
,
66 mDefaultClientPoint
.x
= aClientX
;
67 mDefaultClientPoint
.y
= aClientY
;
68 mouseEventBase
->mRefPoint
.x
= aScreenX
;
69 mouseEventBase
->mRefPoint
.y
= aScreenY
;
71 WidgetMouseEvent
* mouseEvent
= mEvent
->AsMouseEvent();
73 mouseEvent
->mClickCount
= aDetail
;
82 void MouseEvent::InitMouseEvent(const nsAString
& aType
, bool aCanBubble
,
83 bool aCancelable
, nsGlobalWindowInner
* aView
,
84 int32_t aDetail
, int32_t aScreenX
,
85 int32_t aScreenY
, int32_t aClientX
,
86 int32_t aClientY
, int16_t aButton
,
87 EventTarget
* aRelatedTarget
,
88 const nsAString
& aModifiersList
) {
89 NS_ENSURE_TRUE_VOID(!mEvent
->mFlags
.mIsBeingDispatched
);
91 Modifiers modifiers
= ComputeModifierState(aModifiersList
);
94 aType
, aCanBubble
, aCancelable
, aView
, aDetail
, aScreenX
, aScreenY
,
95 aClientX
, aClientY
, (modifiers
& MODIFIER_CONTROL
) != 0,
96 (modifiers
& MODIFIER_ALT
) != 0, (modifiers
& MODIFIER_SHIFT
) != 0,
97 (modifiers
& MODIFIER_META
) != 0, aButton
, aRelatedTarget
);
99 switch (mEvent
->mClass
) {
100 case eMouseEventClass
:
101 case eMouseScrollEventClass
:
102 case eWheelEventClass
:
103 case eDragEventClass
:
104 case ePointerEventClass
:
105 case eSimpleGestureEventClass
:
106 mEvent
->AsInputEvent()->mModifiers
= modifiers
;
109 MOZ_CRASH("There is no space to store the modifiers");
113 void MouseEvent::InitializeExtraMouseEventDictionaryMembers(
114 const MouseEventInit
& aParam
) {
115 InitModifiers(aParam
);
116 mEvent
->AsMouseEventBase()->mButtons
= aParam
.mButtons
;
117 mMovementPoint
.x
= aParam
.mMovementX
;
118 mMovementPoint
.y
= aParam
.mMovementY
;
121 already_AddRefed
<MouseEvent
> MouseEvent::Constructor(
122 const GlobalObject
& aGlobal
, const nsAString
& aType
,
123 const MouseEventInit
& aParam
) {
124 nsCOMPtr
<EventTarget
> t
= do_QueryInterface(aGlobal
.GetAsSupports());
125 RefPtr
<MouseEvent
> e
= new MouseEvent(t
, nullptr, nullptr);
126 bool trusted
= e
->Init(t
);
127 e
->InitMouseEvent(aType
, aParam
.mBubbles
, aParam
.mCancelable
, aParam
.mView
,
128 aParam
.mDetail
, aParam
.mScreenX
, aParam
.mScreenY
,
129 aParam
.mClientX
, aParam
.mClientY
, aParam
.mCtrlKey
,
130 aParam
.mAltKey
, aParam
.mShiftKey
, aParam
.mMetaKey
,
131 aParam
.mButton
, aParam
.mRelatedTarget
);
132 e
->InitializeExtraMouseEventDictionaryMembers(aParam
);
133 e
->SetTrusted(trusted
);
134 e
->SetComposed(aParam
.mComposed
);
138 void MouseEvent::InitNSMouseEvent(const nsAString
& aType
, bool aCanBubble
,
139 bool aCancelable
, nsGlobalWindowInner
* aView
,
140 int32_t aDetail
, int32_t aScreenX
,
141 int32_t aScreenY
, int32_t aClientX
,
142 int32_t aClientY
, bool aCtrlKey
, bool aAltKey
,
143 bool aShiftKey
, bool aMetaKey
,
144 uint16_t aButton
, EventTarget
* aRelatedTarget
,
145 float aPressure
, uint16_t aInputSource
) {
146 NS_ENSURE_TRUE_VOID(!mEvent
->mFlags
.mIsBeingDispatched
);
148 MouseEvent::InitMouseEvent(aType
, aCanBubble
, aCancelable
, aView
, aDetail
,
149 aScreenX
, aScreenY
, aClientX
, aClientY
, aCtrlKey
,
150 aAltKey
, aShiftKey
, aMetaKey
, aButton
,
153 WidgetMouseEventBase
* mouseEventBase
= mEvent
->AsMouseEventBase();
154 mouseEventBase
->mPressure
= aPressure
;
155 mouseEventBase
->mInputSource
= aInputSource
;
158 void MouseEvent::PreventClickEvent() {
159 if (WidgetMouseEvent
* mouseEvent
= mEvent
->AsMouseEvent()) {
160 mouseEvent
->mClickEventPrevented
= true;
164 bool MouseEvent::ClickEventPrevented() {
165 if (WidgetMouseEvent
* mouseEvent
= mEvent
->AsMouseEvent()) {
166 return mouseEvent
->mClickEventPrevented
;
171 int16_t MouseEvent::Button() {
172 switch (mEvent
->mClass
) {
173 case eMouseEventClass
:
174 case eMouseScrollEventClass
:
175 case eWheelEventClass
:
176 case eDragEventClass
:
177 case ePointerEventClass
:
178 case eSimpleGestureEventClass
:
179 return mEvent
->AsMouseEventBase()->mButton
;
181 NS_WARNING("Tried to get mouse mButton for non-mouse event!");
182 return MouseButton::ePrimary
;
186 uint16_t MouseEvent::Buttons() {
187 switch (mEvent
->mClass
) {
188 case eMouseEventClass
:
189 case eMouseScrollEventClass
:
190 case eWheelEventClass
:
191 case eDragEventClass
:
192 case ePointerEventClass
:
193 case eSimpleGestureEventClass
:
194 return mEvent
->AsMouseEventBase()->mButtons
;
196 MOZ_CRASH("Tried to get mouse buttons for non-mouse event!");
200 already_AddRefed
<EventTarget
> MouseEvent::GetRelatedTarget() {
201 nsCOMPtr
<EventTarget
> relatedTarget
;
202 switch (mEvent
->mClass
) {
203 case eMouseEventClass
:
204 case eMouseScrollEventClass
:
205 case eWheelEventClass
:
206 case eDragEventClass
:
207 case ePointerEventClass
:
208 case eSimpleGestureEventClass
:
209 relatedTarget
= mEvent
->AsMouseEventBase()->mRelatedTarget
;
215 return EnsureWebAccessibleRelatedTarget(relatedTarget
);
218 void MouseEvent::GetRegion(nsAString
& aRegion
) { SetDOMStringToNull(aRegion
); }
220 CSSIntPoint
MouseEvent::ScreenPoint(CallerType aCallerType
) const {
221 if (mEvent
->mFlags
.mIsPositionless
) {
225 if (nsContentUtils::ShouldResistFingerprinting(
226 aCallerType
, GetParentObject(), RFPTarget::MouseEventScreenPoint
)) {
227 // Sanitize to something sort of like client cooords, but not quite
228 // (defaulting to (0,0) instead of our pre-specified client coords).
229 return Event::GetClientCoords(mPresContext
, mEvent
, mEvent
->mRefPoint
,
233 return Event::GetScreenCoords(mPresContext
, mEvent
, mEvent
->mRefPoint
)
237 LayoutDeviceIntPoint
MouseEvent::ScreenPointLayoutDevicePix() const {
238 const CSSIntPoint point
= ScreenPoint(CallerType::System
);
239 auto scale
= mPresContext
? mPresContext
->CSSToDevPixelScale()
240 : CSSToLayoutDeviceScale();
241 return LayoutDeviceIntPoint::Round(point
* scale
);
244 DesktopIntPoint
MouseEvent::ScreenPointDesktopPix() const {
245 const CSSIntPoint point
= ScreenPoint(CallerType::System
);
248 ? mPresContext
->CSSToDevPixelScale() /
249 mPresContext
->DeviceContext()->GetDesktopToDeviceScale()
250 : CSSToDesktopScale();
251 return DesktopIntPoint::Round(point
* scale
);
254 already_AddRefed
<nsIScreen
> MouseEvent::GetScreen() {
255 nsCOMPtr
<nsIScreenManager
> screenMgr
=
256 do_GetService("@mozilla.org/gfx/screenmanager;1");
260 return screenMgr
->ScreenForRect(
261 DesktopIntRect(ScreenPointDesktopPix(), DesktopIntSize(1, 1)));
264 CSSIntPoint
MouseEvent::PagePoint() const {
265 if (mEvent
->mFlags
.mIsPositionless
) {
269 if (mPrivateDataDuplicated
) {
273 return Event::GetPageCoords(mPresContext
, mEvent
, mEvent
->mRefPoint
,
274 mDefaultClientPoint
);
277 CSSIntPoint
MouseEvent::ClientPoint() const {
278 if (mEvent
->mFlags
.mIsPositionless
) {
282 return Event::GetClientCoords(mPresContext
, mEvent
, mEvent
->mRefPoint
,
283 mDefaultClientPoint
);
286 CSSIntPoint
MouseEvent::OffsetPoint() const {
287 if (mEvent
->mFlags
.mIsPositionless
) {
291 return Event::GetOffsetCoords(mPresContext
, mEvent
, mEvent
->mRefPoint
,
292 mDefaultClientPoint
);
295 bool MouseEvent::AltKey() { return mEvent
->AsInputEvent()->IsAlt(); }
297 bool MouseEvent::CtrlKey() { return mEvent
->AsInputEvent()->IsControl(); }
299 bool MouseEvent::ShiftKey() { return mEvent
->AsInputEvent()->IsShift(); }
301 bool MouseEvent::MetaKey() { return mEvent
->AsInputEvent()->IsMeta(); }
303 float MouseEvent::MozPressure() const {
304 return mEvent
->AsMouseEventBase()->mPressure
;
307 uint16_t MouseEvent::MozInputSource() const {
308 return mEvent
->AsMouseEventBase()->mInputSource
;
311 } // namespace mozilla::dom
313 using namespace mozilla
;
315 void WidgetDragEvent::UpdateDefaultPreventedOnContent(
316 dom::EventTarget
* aTarget
) {
317 MOZ_ASSERT(DefaultPrevented());
318 nsIPrincipal
* principal
= nullptr;
319 nsINode
* node
= nsINode::FromEventTargetOrNull(aTarget
);
321 principal
= node
->NodePrincipal();
323 nsCOMPtr
<nsIScriptObjectPrincipal
> sop
= do_QueryInterface(aTarget
);
325 principal
= sop
->GetPrincipal();
328 if (principal
&& !principal
->IsSystemPrincipal()) {
329 mDefaultPreventedOnContent
= true;
333 using namespace mozilla::dom
;
335 already_AddRefed
<MouseEvent
> NS_NewDOMMouseEvent(EventTarget
* aOwner
,
336 nsPresContext
* aPresContext
,
337 WidgetMouseEvent
* aEvent
) {
338 RefPtr
<MouseEvent
> it
= new MouseEvent(aOwner
, aPresContext
, aEvent
);