/src/mozilla-central/dom/events/MouseEvent.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
6 | | |
7 | | #include "mozilla/dom/MouseEvent.h" |
8 | | #include "mozilla/MouseEvents.h" |
9 | | #include "nsContentUtils.h" |
10 | | #include "nsIContent.h" |
11 | | #include "prtime.h" |
12 | | |
13 | | namespace mozilla { |
14 | | namespace dom { |
15 | | |
16 | | MouseEvent::MouseEvent(EventTarget* aOwner, |
17 | | nsPresContext* aPresContext, |
18 | | WidgetMouseEventBase* aEvent) |
19 | | : UIEvent(aOwner, aPresContext, |
20 | | aEvent ? aEvent : |
21 | | new WidgetMouseEvent(false, eVoidEvent, nullptr, |
22 | | WidgetMouseEvent::eReal)) |
23 | 0 | { |
24 | 0 | // There's no way to make this class' ctor allocate an WidgetMouseScrollEvent. |
25 | 0 | // It's not that important, though, since a scroll event is not a real |
26 | 0 | // DOM event. |
27 | 0 |
|
28 | 0 | WidgetMouseEvent* mouseEvent = mEvent->AsMouseEvent(); |
29 | 0 | if (aEvent) { |
30 | 0 | mEventIsInternal = false; |
31 | 0 | } |
32 | 0 | else { |
33 | 0 | mEventIsInternal = true; |
34 | 0 | mEvent->mTime = PR_Now(); |
35 | 0 | mEvent->mRefPoint = LayoutDeviceIntPoint(0, 0); |
36 | 0 | mouseEvent->inputSource = MouseEvent_Binding::MOZ_SOURCE_UNKNOWN; |
37 | 0 | } |
38 | 0 |
|
39 | 0 | if (mouseEvent) { |
40 | 0 | MOZ_ASSERT(mouseEvent->mReason != WidgetMouseEvent::eSynthesized, |
41 | 0 | "Don't dispatch DOM events from synthesized mouse events"); |
42 | 0 | mDetail = mouseEvent->mClickCount; |
43 | 0 | } |
44 | 0 | } |
45 | | |
46 | | void |
47 | | MouseEvent::InitMouseEvent(const nsAString& aType, |
48 | | bool aCanBubble, |
49 | | bool aCancelable, |
50 | | nsGlobalWindowInner* aView, |
51 | | int32_t aDetail, |
52 | | int32_t aScreenX, |
53 | | int32_t aScreenY, |
54 | | int32_t aClientX, |
55 | | int32_t aClientY, |
56 | | bool aCtrlKey, |
57 | | bool aAltKey, |
58 | | bool aShiftKey, |
59 | | bool aMetaKey, |
60 | | uint16_t aButton, |
61 | | EventTarget* aRelatedTarget) |
62 | 0 | { |
63 | 0 | NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched); |
64 | 0 |
|
65 | 0 | UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail); |
66 | 0 |
|
67 | 0 | switch(mEvent->mClass) { |
68 | 0 | case eMouseEventClass: |
69 | 0 | case eMouseScrollEventClass: |
70 | 0 | case eWheelEventClass: |
71 | 0 | case eDragEventClass: |
72 | 0 | case ePointerEventClass: |
73 | 0 | case eSimpleGestureEventClass: { |
74 | 0 | WidgetMouseEventBase* mouseEventBase = mEvent->AsMouseEventBase(); |
75 | 0 | mouseEventBase->mRelatedTarget = aRelatedTarget; |
76 | 0 | mouseEventBase->button = aButton; |
77 | 0 | mouseEventBase->InitBasicModifiers(aCtrlKey, aAltKey, aShiftKey, aMetaKey); |
78 | 0 | mClientPoint.x = aClientX; |
79 | 0 | mClientPoint.y = aClientY; |
80 | 0 | mouseEventBase->mRefPoint.x = aScreenX; |
81 | 0 | mouseEventBase->mRefPoint.y = aScreenY; |
82 | 0 |
|
83 | 0 | WidgetMouseEvent* mouseEvent = mEvent->AsMouseEvent(); |
84 | 0 | if (mouseEvent) { |
85 | 0 | mouseEvent->mClickCount = aDetail; |
86 | 0 | } |
87 | 0 | break; |
88 | 0 | } |
89 | 0 | default: |
90 | 0 | break; |
91 | 0 | } |
92 | 0 | } |
93 | | |
94 | | void |
95 | | MouseEvent::InitMouseEvent(const nsAString& aType, |
96 | | bool aCanBubble, |
97 | | bool aCancelable, |
98 | | nsGlobalWindowInner* aView, |
99 | | int32_t aDetail, |
100 | | int32_t aScreenX, |
101 | | int32_t aScreenY, |
102 | | int32_t aClientX, |
103 | | int32_t aClientY, |
104 | | int16_t aButton, |
105 | | EventTarget* aRelatedTarget, |
106 | | const nsAString& aModifiersList) |
107 | 0 | { |
108 | 0 | NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched); |
109 | 0 |
|
110 | 0 | Modifiers modifiers = ComputeModifierState(aModifiersList); |
111 | 0 |
|
112 | 0 | InitMouseEvent(aType, aCanBubble, aCancelable, aView, aDetail, |
113 | 0 | aScreenX, aScreenY, aClientX, aClientY, |
114 | 0 | (modifiers & MODIFIER_CONTROL) != 0, |
115 | 0 | (modifiers & MODIFIER_ALT) != 0, |
116 | 0 | (modifiers & MODIFIER_SHIFT) != 0, |
117 | 0 | (modifiers & MODIFIER_META) != 0, |
118 | 0 | aButton, aRelatedTarget); |
119 | 0 |
|
120 | 0 | switch(mEvent->mClass) { |
121 | 0 | case eMouseEventClass: |
122 | 0 | case eMouseScrollEventClass: |
123 | 0 | case eWheelEventClass: |
124 | 0 | case eDragEventClass: |
125 | 0 | case ePointerEventClass: |
126 | 0 | case eSimpleGestureEventClass: |
127 | 0 | mEvent->AsInputEvent()->mModifiers = modifiers; |
128 | 0 | return; |
129 | 0 | default: |
130 | 0 | MOZ_CRASH("There is no space to store the modifiers"); |
131 | 0 | } |
132 | 0 | } |
133 | | |
134 | | void |
135 | | MouseEvent::InitializeExtraMouseEventDictionaryMembers(const MouseEventInit& aParam) |
136 | 0 | { |
137 | 0 | InitModifiers(aParam); |
138 | 0 | mEvent->AsMouseEventBase()->buttons = aParam.mButtons; |
139 | 0 | mMovementPoint.x = aParam.mMovementX; |
140 | 0 | mMovementPoint.y = aParam.mMovementY; |
141 | 0 | } |
142 | | |
143 | | already_AddRefed<MouseEvent> |
144 | | MouseEvent::Constructor(const GlobalObject& aGlobal, |
145 | | const nsAString& aType, |
146 | | const MouseEventInit& aParam, |
147 | | ErrorResult& aRv) |
148 | 0 | { |
149 | 0 | nsCOMPtr<EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports()); |
150 | 0 | RefPtr<MouseEvent> e = new MouseEvent(t, nullptr, nullptr); |
151 | 0 | bool trusted = e->Init(t); |
152 | 0 | e->InitMouseEvent(aType, aParam.mBubbles, aParam.mCancelable, |
153 | 0 | aParam.mView, aParam.mDetail, aParam.mScreenX, |
154 | 0 | aParam.mScreenY, aParam.mClientX, aParam.mClientY, |
155 | 0 | aParam.mCtrlKey, aParam.mAltKey, aParam.mShiftKey, |
156 | 0 | aParam.mMetaKey, aParam.mButton, aParam.mRelatedTarget); |
157 | 0 | e->InitializeExtraMouseEventDictionaryMembers(aParam); |
158 | 0 | e->SetTrusted(trusted); |
159 | 0 | e->SetComposed(aParam.mComposed); |
160 | 0 | return e.forget(); |
161 | 0 | } |
162 | | |
163 | | void |
164 | | MouseEvent::InitNSMouseEvent(const nsAString& aType, |
165 | | bool aCanBubble, |
166 | | bool aCancelable, |
167 | | nsGlobalWindowInner* aView, |
168 | | int32_t aDetail, |
169 | | int32_t aScreenX, |
170 | | int32_t aScreenY, |
171 | | int32_t aClientX, |
172 | | int32_t aClientY, |
173 | | bool aCtrlKey, |
174 | | bool aAltKey, |
175 | | bool aShiftKey, |
176 | | bool aMetaKey, |
177 | | uint16_t aButton, |
178 | | EventTarget* aRelatedTarget, |
179 | | float aPressure, |
180 | | uint16_t aInputSource) |
181 | 0 | { |
182 | 0 | NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched); |
183 | 0 |
|
184 | 0 | MouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable, |
185 | 0 | aView, aDetail, aScreenX, aScreenY, |
186 | 0 | aClientX, aClientY, |
187 | 0 | aCtrlKey, aAltKey, aShiftKey, |
188 | 0 | aMetaKey, aButton, aRelatedTarget); |
189 | 0 |
|
190 | 0 | WidgetMouseEventBase* mouseEventBase = mEvent->AsMouseEventBase(); |
191 | 0 | mouseEventBase->pressure = aPressure; |
192 | 0 | mouseEventBase->inputSource = aInputSource; |
193 | 0 | } |
194 | | |
195 | | int16_t |
196 | | MouseEvent::Button() |
197 | 0 | { |
198 | 0 | switch(mEvent->mClass) { |
199 | 0 | case eMouseEventClass: |
200 | 0 | case eMouseScrollEventClass: |
201 | 0 | case eWheelEventClass: |
202 | 0 | case eDragEventClass: |
203 | 0 | case ePointerEventClass: |
204 | 0 | case eSimpleGestureEventClass: |
205 | 0 | return mEvent->AsMouseEventBase()->button; |
206 | 0 | default: |
207 | 0 | NS_WARNING("Tried to get mouse button for non-mouse event!"); |
208 | 0 | return WidgetMouseEvent::eLeftButton; |
209 | 0 | } |
210 | 0 | } |
211 | | |
212 | | uint16_t |
213 | | MouseEvent::Buttons() |
214 | 0 | { |
215 | 0 | switch(mEvent->mClass) { |
216 | 0 | case eMouseEventClass: |
217 | 0 | case eMouseScrollEventClass: |
218 | 0 | case eWheelEventClass: |
219 | 0 | case eDragEventClass: |
220 | 0 | case ePointerEventClass: |
221 | 0 | case eSimpleGestureEventClass: |
222 | 0 | return mEvent->AsMouseEventBase()->buttons; |
223 | 0 | default: |
224 | 0 | MOZ_CRASH("Tried to get mouse buttons for non-mouse event!"); |
225 | 0 | } |
226 | 0 | } |
227 | | |
228 | | already_AddRefed<EventTarget> |
229 | | MouseEvent::GetRelatedTarget() |
230 | 0 | { |
231 | 0 | nsCOMPtr<EventTarget> relatedTarget; |
232 | 0 | switch(mEvent->mClass) { |
233 | 0 | case eMouseEventClass: |
234 | 0 | case eMouseScrollEventClass: |
235 | 0 | case eWheelEventClass: |
236 | 0 | case eDragEventClass: |
237 | 0 | case ePointerEventClass: |
238 | 0 | case eSimpleGestureEventClass: |
239 | 0 | relatedTarget = mEvent->AsMouseEventBase()->mRelatedTarget; |
240 | 0 | break; |
241 | 0 | default: |
242 | 0 | break; |
243 | 0 | } |
244 | 0 | |
245 | 0 | return EnsureWebAccessibleRelatedTarget(relatedTarget); |
246 | 0 | } |
247 | | |
248 | | void |
249 | | MouseEvent::GetRegion(nsAString& aRegion) |
250 | 0 | { |
251 | 0 | SetDOMStringToNull(aRegion); |
252 | 0 | WidgetMouseEventBase* mouseEventBase = mEvent->AsMouseEventBase(); |
253 | 0 | if (mouseEventBase) { |
254 | 0 | aRegion = mouseEventBase->region; |
255 | 0 | } |
256 | 0 | } |
257 | | |
258 | | int32_t |
259 | | MouseEvent::ScreenX(CallerType aCallerType) |
260 | 0 | { |
261 | 0 | if (mEvent->mFlags.mIsPositionless) { |
262 | 0 | return 0; |
263 | 0 | } |
264 | 0 | |
265 | 0 | if (nsContentUtils::ResistFingerprinting(aCallerType)) { |
266 | 0 | // Sanitize to something sort of like client cooords, but not quite |
267 | 0 | // (defaulting to (0,0) instead of our pre-specified client coords). |
268 | 0 | return Event::GetClientCoords(mPresContext, mEvent, mEvent->mRefPoint, |
269 | 0 | CSSIntPoint(0, 0)).x; |
270 | 0 | } |
271 | 0 | |
272 | 0 | return Event::GetScreenCoords(mPresContext, mEvent, mEvent->mRefPoint).x; |
273 | 0 | } |
274 | | |
275 | | int32_t |
276 | | MouseEvent::ScreenY(CallerType aCallerType) |
277 | 0 | { |
278 | 0 | if (mEvent->mFlags.mIsPositionless) { |
279 | 0 | return 0; |
280 | 0 | } |
281 | 0 | |
282 | 0 | if (nsContentUtils::ResistFingerprinting(aCallerType)) { |
283 | 0 | // Sanitize to something sort of like client cooords, but not quite |
284 | 0 | // (defaulting to (0,0) instead of our pre-specified client coords). |
285 | 0 | return Event::GetClientCoords(mPresContext, mEvent, mEvent->mRefPoint, |
286 | 0 | CSSIntPoint(0, 0)).y; |
287 | 0 | } |
288 | 0 | |
289 | 0 | return Event::GetScreenCoords(mPresContext, mEvent, mEvent->mRefPoint).y; |
290 | 0 | } |
291 | | |
292 | | int32_t |
293 | | MouseEvent::ClientX() |
294 | 0 | { |
295 | 0 | if (mEvent->mFlags.mIsPositionless) { |
296 | 0 | return 0; |
297 | 0 | } |
298 | 0 | |
299 | 0 | return Event::GetClientCoords(mPresContext, mEvent, mEvent->mRefPoint, |
300 | 0 | mClientPoint).x; |
301 | 0 | } |
302 | | |
303 | | int32_t |
304 | | MouseEvent::ClientY() |
305 | 0 | { |
306 | 0 | if (mEvent->mFlags.mIsPositionless) { |
307 | 0 | return 0; |
308 | 0 | } |
309 | 0 | |
310 | 0 | return Event::GetClientCoords(mPresContext, mEvent, mEvent->mRefPoint, |
311 | 0 | mClientPoint).y; |
312 | 0 | } |
313 | | |
314 | | int32_t |
315 | | MouseEvent::OffsetX() |
316 | 0 | { |
317 | 0 | if (mEvent->mFlags.mIsPositionless) { |
318 | 0 | return 0; |
319 | 0 | } |
320 | 0 | return Event::GetOffsetCoords(mPresContext, mEvent, mEvent->mRefPoint, |
321 | 0 | mClientPoint).x; |
322 | 0 | } |
323 | | |
324 | | int32_t |
325 | | MouseEvent::OffsetY() |
326 | 0 | { |
327 | 0 | if (mEvent->mFlags.mIsPositionless) { |
328 | 0 | return 0; |
329 | 0 | } |
330 | 0 | return Event::GetOffsetCoords(mPresContext, mEvent, mEvent->mRefPoint, |
331 | 0 | mClientPoint).y; |
332 | 0 | } |
333 | | |
334 | | bool |
335 | | MouseEvent::AltKey() |
336 | 0 | { |
337 | 0 | return mEvent->AsInputEvent()->IsAlt(); |
338 | 0 | } |
339 | | |
340 | | bool |
341 | | MouseEvent::CtrlKey() |
342 | 0 | { |
343 | 0 | return mEvent->AsInputEvent()->IsControl(); |
344 | 0 | } |
345 | | |
346 | | bool |
347 | | MouseEvent::ShiftKey() |
348 | 0 | { |
349 | 0 | return mEvent->AsInputEvent()->IsShift(); |
350 | 0 | } |
351 | | |
352 | | bool |
353 | | MouseEvent::MetaKey() |
354 | 0 | { |
355 | 0 | return mEvent->AsInputEvent()->IsMeta(); |
356 | 0 | } |
357 | | |
358 | | float |
359 | | MouseEvent::MozPressure() const |
360 | 0 | { |
361 | 0 | return mEvent->AsMouseEventBase()->pressure; |
362 | 0 | } |
363 | | |
364 | | bool |
365 | | MouseEvent::HitCluster() const |
366 | 0 | { |
367 | 0 | return mEvent->AsMouseEventBase()->hitCluster; |
368 | 0 | } |
369 | | |
370 | | uint16_t |
371 | | MouseEvent::MozInputSource() const |
372 | 0 | { |
373 | 0 | return mEvent->AsMouseEventBase()->inputSource; |
374 | 0 | } |
375 | | |
376 | | } // namespace dom |
377 | | } // namespace mozilla |
378 | | |
379 | | using namespace mozilla; |
380 | | using namespace mozilla::dom; |
381 | | |
382 | | already_AddRefed<MouseEvent> |
383 | | NS_NewDOMMouseEvent(EventTarget* aOwner, |
384 | | nsPresContext* aPresContext, |
385 | | WidgetMouseEvent* aEvent) |
386 | 0 | { |
387 | 0 | RefPtr<MouseEvent> it = new MouseEvent(aOwner, aPresContext, aEvent); |
388 | 0 | return it.forget(); |
389 | 0 | } |