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