Coverage Report

Created: 2018-09-25 14:53

/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
}