Line data Source code
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 5 : MouseEvent::MouseEvent(EventTarget* aOwner,
17 : nsPresContext* aPresContext,
18 5 : WidgetMouseEventBase* aEvent)
19 : : UIEvent(aOwner, aPresContext,
20 : aEvent ? aEvent :
21 : new WidgetMouseEvent(false, eVoidEvent, nullptr,
22 5 : WidgetMouseEvent::eReal))
23 : {
24 : // There's no way to make this class' ctor allocate an WidgetMouseScrollEvent.
25 : // It's not that important, though, since a scroll event is not a real
26 : // DOM event.
27 :
28 5 : WidgetMouseEvent* mouseEvent = mEvent->AsMouseEvent();
29 5 : if (aEvent) {
30 5 : mEventIsInternal = false;
31 : }
32 : else {
33 0 : mEventIsInternal = true;
34 0 : mEvent->mTime = PR_Now();
35 0 : mEvent->mRefPoint = LayoutDeviceIntPoint(0, 0);
36 0 : mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
37 : }
38 :
39 5 : if (mouseEvent) {
40 5 : MOZ_ASSERT(mouseEvent->mReason != WidgetMouseEvent::eSynthesized,
41 : "Don't dispatch DOM events from synthesized mouse events");
42 5 : mDetail = mouseEvent->mClickCount;
43 : }
44 5 : }
45 :
46 13 : NS_IMPL_ADDREF_INHERITED(MouseEvent, UIEvent)
47 9 : NS_IMPL_RELEASE_INHERITED(MouseEvent, UIEvent)
48 :
49 59 : NS_INTERFACE_MAP_BEGIN(MouseEvent)
50 59 : NS_INTERFACE_MAP_ENTRY(nsIDOMMouseEvent)
51 55 : NS_INTERFACE_MAP_END_INHERITING(UIEvent)
52 :
53 : void
54 0 : MouseEvent::InitMouseEvent(const nsAString& aType,
55 : bool aCanBubble,
56 : bool aCancelable,
57 : nsGlobalWindow* aView,
58 : int32_t aDetail,
59 : int32_t aScreenX,
60 : int32_t aScreenY,
61 : int32_t aClientX,
62 : int32_t aClientY,
63 : bool aCtrlKey,
64 : bool aAltKey,
65 : bool aShiftKey,
66 : bool aMetaKey,
67 : uint16_t aButton,
68 : EventTarget* aRelatedTarget)
69 : {
70 0 : NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
71 :
72 0 : UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
73 :
74 0 : switch(mEvent->mClass) {
75 : case eMouseEventClass:
76 : case eMouseScrollEventClass:
77 : case eWheelEventClass:
78 : case eDragEventClass:
79 : case ePointerEventClass:
80 : case eSimpleGestureEventClass: {
81 0 : WidgetMouseEventBase* mouseEventBase = mEvent->AsMouseEventBase();
82 0 : mouseEventBase->relatedTarget = aRelatedTarget;
83 0 : mouseEventBase->button = aButton;
84 0 : mouseEventBase->InitBasicModifiers(aCtrlKey, aAltKey, aShiftKey, aMetaKey);
85 0 : mClientPoint.x = aClientX;
86 0 : mClientPoint.y = aClientY;
87 0 : mouseEventBase->mRefPoint.x = aScreenX;
88 0 : mouseEventBase->mRefPoint.y = aScreenY;
89 :
90 0 : WidgetMouseEvent* mouseEvent = mEvent->AsMouseEvent();
91 0 : if (mouseEvent) {
92 0 : mouseEvent->mClickCount = aDetail;
93 : }
94 0 : break;
95 : }
96 : default:
97 0 : break;
98 : }
99 : }
100 :
101 : NS_IMETHODIMP
102 0 : MouseEvent::InitMouseEvent(const nsAString& aType,
103 : bool aCanBubble,
104 : bool aCancelable,
105 : mozIDOMWindow* aView,
106 : int32_t aDetail,
107 : int32_t aScreenX,
108 : int32_t aScreenY,
109 : int32_t aClientX,
110 : int32_t aClientY,
111 : bool aCtrlKey,
112 : bool aAltKey,
113 : bool aShiftKey,
114 : bool aMetaKey,
115 : uint16_t aButton,
116 : nsIDOMEventTarget* aRelatedTarget)
117 : {
118 0 : MouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable,
119 : nsGlobalWindow::Cast(aView), aDetail,
120 : aScreenX, aScreenY,
121 : aClientX, aClientY,
122 : aCtrlKey, aAltKey, aShiftKey,
123 : aMetaKey, aButton,
124 0 : static_cast<EventTarget *>(aRelatedTarget));
125 :
126 0 : return NS_OK;
127 : }
128 :
129 : void
130 0 : MouseEvent::InitMouseEvent(const nsAString& aType,
131 : bool aCanBubble,
132 : bool aCancelable,
133 : nsGlobalWindow* aView,
134 : int32_t aDetail,
135 : int32_t aScreenX,
136 : int32_t aScreenY,
137 : int32_t aClientX,
138 : int32_t aClientY,
139 : int16_t aButton,
140 : EventTarget* aRelatedTarget,
141 : const nsAString& aModifiersList)
142 : {
143 0 : NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
144 :
145 0 : Modifiers modifiers = ComputeModifierState(aModifiersList);
146 :
147 0 : InitMouseEvent(aType, aCanBubble, aCancelable, aView, aDetail,
148 : aScreenX, aScreenY, aClientX, aClientY,
149 0 : (modifiers & MODIFIER_CONTROL) != 0,
150 0 : (modifiers & MODIFIER_ALT) != 0,
151 0 : (modifiers & MODIFIER_SHIFT) != 0,
152 0 : (modifiers & MODIFIER_META) != 0,
153 0 : aButton, aRelatedTarget);
154 :
155 0 : switch(mEvent->mClass) {
156 : case eMouseEventClass:
157 : case eMouseScrollEventClass:
158 : case eWheelEventClass:
159 : case eDragEventClass:
160 : case ePointerEventClass:
161 : case eSimpleGestureEventClass:
162 0 : mEvent->AsInputEvent()->mModifiers = modifiers;
163 0 : return;
164 : default:
165 0 : MOZ_CRASH("There is no space to store the modifiers");
166 : }
167 : }
168 :
169 : void
170 0 : MouseEvent::InitializeExtraMouseEventDictionaryMembers(const MouseEventInit& aParam)
171 : {
172 0 : InitModifiers(aParam);
173 0 : mEvent->AsMouseEventBase()->buttons = aParam.mButtons;
174 0 : mMovementPoint.x = aParam.mMovementX;
175 0 : mMovementPoint.y = aParam.mMovementY;
176 0 : }
177 :
178 : already_AddRefed<MouseEvent>
179 0 : MouseEvent::Constructor(const GlobalObject& aGlobal,
180 : const nsAString& aType,
181 : const MouseEventInit& aParam,
182 : ErrorResult& aRv)
183 : {
184 0 : nsCOMPtr<EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
185 0 : RefPtr<MouseEvent> e = new MouseEvent(t, nullptr, nullptr);
186 0 : bool trusted = e->Init(t);
187 0 : e->InitMouseEvent(aType, aParam.mBubbles, aParam.mCancelable,
188 0 : aParam.mView, aParam.mDetail, aParam.mScreenX,
189 0 : aParam.mScreenY, aParam.mClientX, aParam.mClientY,
190 0 : aParam.mCtrlKey, aParam.mAltKey, aParam.mShiftKey,
191 0 : aParam.mMetaKey, aParam.mButton, aParam.mRelatedTarget);
192 0 : e->InitializeExtraMouseEventDictionaryMembers(aParam);
193 0 : e->SetTrusted(trusted);
194 0 : e->SetComposed(aParam.mComposed);
195 0 : return e.forget();
196 : }
197 :
198 : void
199 0 : MouseEvent::InitNSMouseEvent(const nsAString& aType,
200 : bool aCanBubble,
201 : bool aCancelable,
202 : nsGlobalWindow* aView,
203 : int32_t aDetail,
204 : int32_t aScreenX,
205 : int32_t aScreenY,
206 : int32_t aClientX,
207 : int32_t aClientY,
208 : bool aCtrlKey,
209 : bool aAltKey,
210 : bool aShiftKey,
211 : bool aMetaKey,
212 : uint16_t aButton,
213 : EventTarget* aRelatedTarget,
214 : float aPressure,
215 : uint16_t aInputSource)
216 : {
217 0 : NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
218 :
219 0 : MouseEvent::InitMouseEvent(aType, aCanBubble, aCancelable,
220 : aView, aDetail, aScreenX, aScreenY,
221 : aClientX, aClientY,
222 : aCtrlKey, aAltKey, aShiftKey,
223 0 : aMetaKey, aButton, aRelatedTarget);
224 :
225 0 : WidgetMouseEventBase* mouseEventBase = mEvent->AsMouseEventBase();
226 0 : mouseEventBase->pressure = aPressure;
227 0 : mouseEventBase->inputSource = aInputSource;
228 : }
229 :
230 : NS_IMETHODIMP
231 0 : MouseEvent::GetButton(int16_t* aButton)
232 : {
233 0 : NS_ENSURE_ARG_POINTER(aButton);
234 0 : *aButton = Button();
235 0 : return NS_OK;
236 : }
237 :
238 : int16_t
239 0 : MouseEvent::Button()
240 : {
241 0 : switch(mEvent->mClass) {
242 : case eMouseEventClass:
243 : case eMouseScrollEventClass:
244 : case eWheelEventClass:
245 : case eDragEventClass:
246 : case ePointerEventClass:
247 : case eSimpleGestureEventClass:
248 0 : return mEvent->AsMouseEventBase()->button;
249 : default:
250 0 : NS_WARNING("Tried to get mouse button for non-mouse event!");
251 0 : return WidgetMouseEvent::eLeftButton;
252 : }
253 : }
254 :
255 : NS_IMETHODIMP
256 0 : MouseEvent::GetButtons(uint16_t* aButtons)
257 : {
258 0 : NS_ENSURE_ARG_POINTER(aButtons);
259 0 : *aButtons = Buttons();
260 0 : return NS_OK;
261 : }
262 :
263 : uint16_t
264 0 : MouseEvent::Buttons()
265 : {
266 0 : switch(mEvent->mClass) {
267 : case eMouseEventClass:
268 : case eMouseScrollEventClass:
269 : case eWheelEventClass:
270 : case eDragEventClass:
271 : case ePointerEventClass:
272 : case eSimpleGestureEventClass:
273 0 : return mEvent->AsMouseEventBase()->buttons;
274 : default:
275 0 : MOZ_CRASH("Tried to get mouse buttons for non-mouse event!");
276 : }
277 : }
278 :
279 : NS_IMETHODIMP
280 0 : MouseEvent::GetRelatedTarget(nsIDOMEventTarget** aRelatedTarget)
281 : {
282 0 : NS_ENSURE_ARG_POINTER(aRelatedTarget);
283 0 : *aRelatedTarget = GetRelatedTarget().take();
284 0 : return NS_OK;
285 : }
286 :
287 : already_AddRefed<EventTarget>
288 0 : MouseEvent::GetRelatedTarget()
289 : {
290 0 : nsCOMPtr<EventTarget> relatedTarget;
291 0 : switch(mEvent->mClass) {
292 : case eMouseEventClass:
293 : case eMouseScrollEventClass:
294 : case eWheelEventClass:
295 : case eDragEventClass:
296 : case ePointerEventClass:
297 : case eSimpleGestureEventClass:
298 : relatedTarget =
299 0 : do_QueryInterface(mEvent->AsMouseEventBase()->relatedTarget);
300 0 : break;
301 : default:
302 0 : break;
303 : }
304 :
305 0 : return EnsureWebAccessibleRelatedTarget(relatedTarget);
306 : }
307 :
308 : void
309 0 : MouseEvent::GetRegion(nsAString& aRegion)
310 : {
311 0 : SetDOMStringToNull(aRegion);
312 0 : WidgetMouseEventBase* mouseEventBase = mEvent->AsMouseEventBase();
313 0 : if (mouseEventBase) {
314 0 : aRegion = mouseEventBase->region;
315 : }
316 0 : }
317 :
318 : NS_IMETHODIMP
319 0 : MouseEvent::GetMozMovementX(int32_t* aMovementX)
320 : {
321 0 : NS_ENSURE_ARG_POINTER(aMovementX);
322 0 : *aMovementX = MovementX();
323 :
324 0 : return NS_OK;
325 : }
326 :
327 : NS_IMETHODIMP
328 0 : MouseEvent::GetMozMovementY(int32_t* aMovementY)
329 : {
330 0 : NS_ENSURE_ARG_POINTER(aMovementY);
331 0 : *aMovementY = MovementY();
332 :
333 0 : return NS_OK;
334 : }
335 :
336 : NS_IMETHODIMP
337 4 : MouseEvent::GetScreenX(int32_t* aScreenX)
338 : {
339 4 : NS_ENSURE_ARG_POINTER(aScreenX);
340 4 : *aScreenX = ScreenX(CallerType::System);
341 4 : return NS_OK;
342 : }
343 :
344 : int32_t
345 8 : MouseEvent::ScreenX(CallerType aCallerType)
346 : {
347 8 : if (mEvent->mFlags.mIsPositionless) {
348 0 : return 0;
349 : }
350 :
351 8 : if (nsContentUtils::ResistFingerprinting(aCallerType)) {
352 : // Sanitize to something sort of like client cooords, but not quite
353 : // (defaulting to (0,0) instead of our pre-specified client coords).
354 0 : return Event::GetClientCoords(mPresContext, mEvent, mEvent->mRefPoint,
355 0 : CSSIntPoint(0, 0)).x;
356 : }
357 :
358 8 : return Event::GetScreenCoords(mPresContext, mEvent, mEvent->mRefPoint).x;
359 : }
360 :
361 : NS_IMETHODIMP
362 4 : MouseEvent::GetScreenY(int32_t* aScreenY)
363 : {
364 4 : NS_ENSURE_ARG_POINTER(aScreenY);
365 4 : *aScreenY = ScreenY(CallerType::System);
366 4 : return NS_OK;
367 : }
368 :
369 : int32_t
370 8 : MouseEvent::ScreenY(CallerType aCallerType)
371 : {
372 8 : if (mEvent->mFlags.mIsPositionless) {
373 0 : return 0;
374 : }
375 :
376 8 : if (nsContentUtils::ResistFingerprinting(aCallerType)) {
377 : // Sanitize to something sort of like client cooords, but not quite
378 : // (defaulting to (0,0) instead of our pre-specified client coords).
379 0 : return Event::GetClientCoords(mPresContext, mEvent, mEvent->mRefPoint,
380 0 : CSSIntPoint(0, 0)).y;
381 : }
382 :
383 8 : return Event::GetScreenCoords(mPresContext, mEvent, mEvent->mRefPoint).y;
384 : }
385 :
386 :
387 : NS_IMETHODIMP
388 0 : MouseEvent::GetClientX(int32_t* aClientX)
389 : {
390 0 : NS_ENSURE_ARG_POINTER(aClientX);
391 0 : *aClientX = ClientX();
392 0 : return NS_OK;
393 : }
394 :
395 : int32_t
396 0 : MouseEvent::ClientX()
397 : {
398 0 : if (mEvent->mFlags.mIsPositionless) {
399 0 : return 0;
400 : }
401 :
402 0 : return Event::GetClientCoords(mPresContext, mEvent, mEvent->mRefPoint,
403 0 : mClientPoint).x;
404 : }
405 :
406 : NS_IMETHODIMP
407 0 : MouseEvent::GetClientY(int32_t* aClientY)
408 : {
409 0 : NS_ENSURE_ARG_POINTER(aClientY);
410 0 : *aClientY = ClientY();
411 0 : return NS_OK;
412 : }
413 :
414 : int32_t
415 0 : MouseEvent::ClientY()
416 : {
417 0 : if (mEvent->mFlags.mIsPositionless) {
418 0 : return 0;
419 : }
420 :
421 0 : return Event::GetClientCoords(mPresContext, mEvent, mEvent->mRefPoint,
422 0 : mClientPoint).y;
423 : }
424 :
425 : int32_t
426 0 : MouseEvent::OffsetX()
427 : {
428 0 : if (mEvent->mFlags.mIsPositionless) {
429 0 : return 0;
430 : }
431 0 : return Event::GetOffsetCoords(mPresContext, mEvent, mEvent->mRefPoint,
432 0 : mClientPoint).x;
433 : }
434 :
435 : int32_t
436 0 : MouseEvent::OffsetY()
437 : {
438 0 : if (mEvent->mFlags.mIsPositionless) {
439 0 : return 0;
440 : }
441 0 : return Event::GetOffsetCoords(mPresContext, mEvent, mEvent->mRefPoint,
442 0 : mClientPoint).y;
443 : }
444 :
445 : bool
446 0 : MouseEvent::AltKey()
447 : {
448 0 : return mEvent->AsInputEvent()->IsAlt();
449 : }
450 :
451 : NS_IMETHODIMP
452 0 : MouseEvent::GetAltKey(bool* aIsDown)
453 : {
454 0 : NS_ENSURE_ARG_POINTER(aIsDown);
455 0 : *aIsDown = AltKey();
456 0 : return NS_OK;
457 : }
458 :
459 : bool
460 0 : MouseEvent::CtrlKey()
461 : {
462 0 : return mEvent->AsInputEvent()->IsControl();
463 : }
464 :
465 : NS_IMETHODIMP
466 0 : MouseEvent::GetCtrlKey(bool* aIsDown)
467 : {
468 0 : NS_ENSURE_ARG_POINTER(aIsDown);
469 0 : *aIsDown = CtrlKey();
470 0 : return NS_OK;
471 : }
472 :
473 : bool
474 0 : MouseEvent::ShiftKey()
475 : {
476 0 : return mEvent->AsInputEvent()->IsShift();
477 : }
478 :
479 : NS_IMETHODIMP
480 0 : MouseEvent::GetShiftKey(bool* aIsDown)
481 : {
482 0 : NS_ENSURE_ARG_POINTER(aIsDown);
483 0 : *aIsDown = ShiftKey();
484 0 : return NS_OK;
485 : }
486 :
487 : bool
488 0 : MouseEvent::MetaKey()
489 : {
490 0 : return mEvent->AsInputEvent()->IsMeta();
491 : }
492 :
493 : NS_IMETHODIMP
494 0 : MouseEvent::GetMetaKey(bool* aIsDown)
495 : {
496 0 : NS_ENSURE_ARG_POINTER(aIsDown);
497 0 : *aIsDown = MetaKey();
498 0 : return NS_OK;
499 : }
500 :
501 : NS_IMETHODIMP
502 0 : MouseEvent::GetModifierState(const nsAString& aKey,
503 : bool* aState)
504 : {
505 0 : NS_ENSURE_ARG_POINTER(aState);
506 :
507 0 : *aState = GetModifierState(aKey);
508 0 : return NS_OK;
509 : }
510 :
511 : float
512 0 : MouseEvent::MozPressure() const
513 : {
514 0 : return mEvent->AsMouseEventBase()->pressure;
515 : }
516 :
517 : NS_IMETHODIMP
518 0 : MouseEvent::GetMozPressure(float* aPressure)
519 : {
520 0 : NS_ENSURE_ARG_POINTER(aPressure);
521 0 : *aPressure = MozPressure();
522 0 : return NS_OK;
523 : }
524 :
525 : bool
526 0 : MouseEvent::HitCluster() const
527 : {
528 0 : return mEvent->AsMouseEventBase()->hitCluster;
529 : }
530 :
531 : uint16_t
532 0 : MouseEvent::MozInputSource() const
533 : {
534 0 : return mEvent->AsMouseEventBase()->inputSource;
535 : }
536 :
537 : NS_IMETHODIMP
538 0 : MouseEvent::GetMozInputSource(uint16_t* aInputSource)
539 : {
540 0 : NS_ENSURE_ARG_POINTER(aInputSource);
541 0 : *aInputSource = MozInputSource();
542 0 : return NS_OK;
543 : }
544 :
545 : } // namespace dom
546 : } // namespace mozilla
547 :
548 : using namespace mozilla;
549 : using namespace mozilla::dom;
550 :
551 : already_AddRefed<MouseEvent>
552 5 : NS_NewDOMMouseEvent(EventTarget* aOwner,
553 : nsPresContext* aPresContext,
554 : WidgetMouseEvent* aEvent)
555 : {
556 10 : RefPtr<MouseEvent> it = new MouseEvent(aOwner, aPresContext, aEvent);
557 10 : return it.forget();
558 : }
|