Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/events/PointerEvent.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
 * Portions Copyright 2013 Microsoft Open Technologies, Inc. */
8
9
#include "mozilla/dom/MouseEventBinding.h"
10
#include "mozilla/dom/PointerEvent.h"
11
#include "mozilla/dom/PointerEventBinding.h"
12
#include "mozilla/MouseEvents.h"
13
#include "prtime.h"
14
15
namespace mozilla {
16
namespace dom {
17
18
PointerEvent::PointerEvent(EventTarget* aOwner,
19
                           nsPresContext* aPresContext,
20
                           WidgetPointerEvent* aEvent)
21
  : MouseEvent(aOwner, aPresContext,
22
               aEvent ? aEvent :
23
                        new WidgetPointerEvent(false, eVoidEvent, nullptr))
24
0
{
25
0
  NS_ASSERTION(mEvent->mClass == ePointerEventClass,
26
0
               "event type mismatch ePointerEventClass");
27
0
28
0
  WidgetMouseEvent* mouseEvent = mEvent->AsMouseEvent();
29
0
  if (aEvent) {
30
0
    mEventIsInternal = false;
31
0
  } else {
32
0
    mEventIsInternal = true;
33
0
    mEvent->mTime = PR_Now();
34
0
    mEvent->mRefPoint = LayoutDeviceIntPoint(0, 0);
35
0
    mouseEvent->inputSource = MouseEvent_Binding::MOZ_SOURCE_UNKNOWN;
36
0
  }
37
0
  // 5.2 Pointer Event types, for all pointer events, |detail| attribute SHOULD
38
0
  // be 0.
39
0
  mDetail = 0;
40
0
}
41
42
JSObject*
43
PointerEvent::WrapObjectInternal(JSContext* aCx,
44
                                 JS::Handle<JSObject*> aGivenProto)
45
0
{
46
0
  return PointerEvent_Binding::Wrap(aCx, this, aGivenProto);
47
0
}
48
49
static uint16_t
50
ConvertStringToPointerType(const nsAString& aPointerTypeArg)
51
0
{
52
0
  if (aPointerTypeArg.EqualsLiteral("mouse")) {
53
0
    return MouseEvent_Binding::MOZ_SOURCE_MOUSE;
54
0
  }
55
0
  if (aPointerTypeArg.EqualsLiteral("pen")) {
56
0
    return MouseEvent_Binding::MOZ_SOURCE_PEN;
57
0
  }
58
0
  if (aPointerTypeArg.EqualsLiteral("touch")) {
59
0
    return MouseEvent_Binding::MOZ_SOURCE_TOUCH;
60
0
  }
61
0
62
0
  return MouseEvent_Binding::MOZ_SOURCE_UNKNOWN;
63
0
}
64
65
void
66
ConvertPointerTypeToString(uint16_t aPointerTypeSrc, nsAString& aPointerTypeDest)
67
{
68
  switch (aPointerTypeSrc) {
69
    case MouseEvent_Binding::MOZ_SOURCE_MOUSE:
70
      aPointerTypeDest.AssignLiteral("mouse");
71
      break;
72
    case MouseEvent_Binding::MOZ_SOURCE_PEN:
73
      aPointerTypeDest.AssignLiteral("pen");
74
      break;
75
    case MouseEvent_Binding::MOZ_SOURCE_TOUCH:
76
      aPointerTypeDest.AssignLiteral("touch");
77
      break;
78
    default:
79
      aPointerTypeDest.Truncate();
80
      break;
81
  }
82
}
83
84
// static
85
already_AddRefed<PointerEvent>
86
PointerEvent::Constructor(EventTarget* aOwner,
87
                          const nsAString& aType,
88
                          const PointerEventInit& aParam)
89
0
{
90
0
  RefPtr<PointerEvent> e = new PointerEvent(aOwner, nullptr, nullptr);
91
0
  bool trusted = e->Init(aOwner);
92
0
93
0
  e->InitMouseEvent(aType, aParam.mBubbles, aParam.mCancelable,
94
0
                    aParam.mView, aParam.mDetail, aParam.mScreenX,
95
0
                    aParam.mScreenY, aParam.mClientX, aParam.mClientY,
96
0
                    false, false, false, false, aParam.mButton,
97
0
                    aParam.mRelatedTarget);
98
0
  e->InitializeExtraMouseEventDictionaryMembers(aParam);
99
0
100
0
  WidgetPointerEvent* widgetEvent = e->mEvent->AsPointerEvent();
101
0
  widgetEvent->pointerId = aParam.mPointerId;
102
0
  widgetEvent->mWidth = aParam.mWidth;
103
0
  widgetEvent->mHeight = aParam.mHeight;
104
0
  widgetEvent->pressure = aParam.mPressure;
105
0
  widgetEvent->tangentialPressure = aParam.mTangentialPressure;
106
0
  widgetEvent->tiltX = aParam.mTiltX;
107
0
  widgetEvent->tiltY = aParam.mTiltY;
108
0
  widgetEvent->twist = aParam.mTwist;
109
0
  widgetEvent->inputSource = ConvertStringToPointerType(aParam.mPointerType);
110
0
  widgetEvent->mIsPrimary = aParam.mIsPrimary;
111
0
  widgetEvent->buttons = aParam.mButtons;
112
0
113
0
  if (!aParam.mCoalescedEvents.IsEmpty()) {
114
0
    e->mCoalescedEvents.AppendElements(aParam.mCoalescedEvents);
115
0
  }
116
0
  e->SetTrusted(trusted);
117
0
  e->SetComposed(aParam.mComposed);
118
0
  return e.forget();
119
0
}
120
121
// static
122
already_AddRefed<PointerEvent>
123
PointerEvent::Constructor(const GlobalObject& aGlobal,
124
                          const nsAString& aType,
125
                          const PointerEventInit& aParam,
126
                          ErrorResult& aRv)
127
0
{
128
0
  nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
129
0
  return Constructor(owner, aType, aParam);
130
0
}
131
132
NS_IMPL_CYCLE_COLLECTION_CLASS(PointerEvent)
133
134
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(PointerEvent, MouseEvent)
135
0
  NS_IMPL_CYCLE_COLLECTION_UNLINK(mCoalescedEvents)
136
0
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
137
138
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(PointerEvent, MouseEvent)
139
0
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCoalescedEvents)
140
0
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
141
142
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PointerEvent)
143
0
NS_INTERFACE_MAP_END_INHERITING(MouseEvent)
144
145
NS_IMPL_ADDREF_INHERITED(PointerEvent, MouseEvent)
146
NS_IMPL_RELEASE_INHERITED(PointerEvent, MouseEvent)
147
148
void
149
PointerEvent::GetPointerType(nsAString& aPointerType)
150
0
{
151
0
  ConvertPointerTypeToString(mEvent->AsPointerEvent()->inputSource, aPointerType);
152
0
}
153
154
int32_t
155
PointerEvent::PointerId()
156
0
{
157
0
  return mEvent->AsPointerEvent()->pointerId;
158
0
}
159
160
int32_t
161
PointerEvent::Width()
162
0
{
163
0
  return mEvent->AsPointerEvent()->mWidth;
164
0
}
165
166
int32_t
167
PointerEvent::Height()
168
0
{
169
0
  return mEvent->AsPointerEvent()->mHeight;
170
0
}
171
172
float
173
PointerEvent::Pressure()
174
0
{
175
0
  return mEvent->AsPointerEvent()->pressure;
176
0
}
177
178
float
179
PointerEvent::TangentialPressure()
180
0
{
181
0
  return mEvent->AsPointerEvent()->tangentialPressure;
182
0
}
183
184
int32_t
185
PointerEvent::TiltX()
186
0
{
187
0
  return mEvent->AsPointerEvent()->tiltX;
188
0
}
189
190
int32_t
191
PointerEvent::TiltY()
192
0
{
193
0
  return mEvent->AsPointerEvent()->tiltY;
194
0
}
195
196
int32_t
197
PointerEvent::Twist()
198
0
{
199
0
  return mEvent->AsPointerEvent()->twist;
200
0
}
201
202
bool
203
PointerEvent::IsPrimary()
204
0
{
205
0
  return mEvent->AsPointerEvent()->mIsPrimary;
206
0
}
207
208
void
209
PointerEvent::GetCoalescedEvents(nsTArray<RefPtr<PointerEvent>>& aPointerEvents)
210
0
{
211
0
  WidgetPointerEvent* widgetEvent = mEvent->AsPointerEvent();
212
0
  if (mCoalescedEvents.IsEmpty() && widgetEvent &&
213
0
      widgetEvent->mCoalescedWidgetEvents &&
214
0
      !widgetEvent->mCoalescedWidgetEvents->mEvents.IsEmpty()) {
215
0
    for (WidgetPointerEvent& event :
216
0
         widgetEvent->mCoalescedWidgetEvents->mEvents) {
217
0
      RefPtr<PointerEvent> domEvent =
218
0
        NS_NewDOMPointerEvent(nullptr, nullptr, &event);
219
0
220
0
      // The dom event is derived from an OS generated widget event. Setup
221
0
      // mWidget and mPresContext since they are necessary to calculate
222
0
      // offsetX / offsetY.
223
0
      domEvent->mEvent->AsGUIEvent()->mWidget = widgetEvent->mWidget;
224
0
      domEvent->mPresContext = mPresContext;
225
0
226
0
      // The coalesced widget mouse events shouldn't have been dispatched.
227
0
      MOZ_ASSERT(!domEvent->mEvent->mTarget);
228
0
      // The event target should be the same as the dispatched event's target.
229
0
      domEvent->mEvent->mTarget = mEvent->mTarget;
230
0
231
0
      // JS could hold reference to dom events. We have to ask dom event to
232
0
      // duplicate its private data to avoid the widget event is destroyed.
233
0
      domEvent->DuplicatePrivateData();
234
0
235
0
      // Setup mPresContext again after DuplicatePrivateData since it clears
236
0
      // mPresContext.
237
0
      domEvent->mPresContext = mPresContext;
238
0
      mCoalescedEvents.AppendElement(domEvent);
239
0
    }
240
0
  }
241
0
  if (mEvent->mTarget) {
242
0
    for (RefPtr<PointerEvent>& pointerEvent : mCoalescedEvents) {
243
0
      // Only set event target when it's null.
244
0
      if (!pointerEvent->mEvent->mTarget) {
245
0
        pointerEvent->mEvent->mTarget = mEvent->mTarget;
246
0
      }
247
0
    }
248
0
  }
249
0
  aPointerEvents.AppendElements(mCoalescedEvents);
250
0
}
251
252
} // namespace dom
253
} // namespace mozilla
254
255
using namespace mozilla;
256
using namespace mozilla::dom;
257
258
already_AddRefed<PointerEvent>
259
NS_NewDOMPointerEvent(EventTarget* aOwner,
260
                      nsPresContext* aPresContext,
261
                      WidgetPointerEvent *aEvent)
262
0
{
263
0
  RefPtr<PointerEvent> it = new PointerEvent(aOwner, aPresContext, aEvent);
264
0
  return it.forget();
265
0
}