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