1 : /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is nsDOMTouchEvent.
16 : *
17 : * The Initial Developer of the Original Code is the Mozilla Foundation.
18 : * Portions created by the Initial Developer are Copyright (C) 2011
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Olli Pettay <Olli.Pettay@helsinki.fi> (Original Author)
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include "nsDOMTouchEvent.h"
39 : #include "nsGUIEvent.h"
40 : #include "nsDOMClassInfoID.h"
41 : #include "nsIClassInfo.h"
42 : #include "nsIXPCScriptable.h"
43 : #include "nsContentUtils.h"
44 : #include "mozilla/Preferences.h"
45 : #include "nsPresContext.h"
46 :
47 : using namespace mozilla;
48 :
49 : DOMCI_DATA(Touch, nsDOMTouch)
50 :
51 1464 : NS_IMPL_CYCLE_COLLECTION_1(nsDOMTouch, mTarget)
52 :
53 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMTouch)
54 0 : NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMTouch)
55 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMTouch)
56 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Touch)
57 0 : NS_INTERFACE_MAP_END
58 :
59 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMTouch)
60 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMTouch)
61 :
62 : NS_IMETHODIMP
63 0 : nsDOMTouch::GetIdentifier(PRInt32* aIdentifier)
64 : {
65 0 : *aIdentifier = mIdentifier;
66 0 : return NS_OK;
67 : }
68 :
69 : NS_IMETHODIMP
70 0 : nsDOMTouch::GetTarget(nsIDOMEventTarget** aTarget)
71 : {
72 0 : NS_IF_ADDREF(*aTarget = mTarget);
73 0 : return NS_OK;
74 : }
75 :
76 : NS_IMETHODIMP
77 0 : nsDOMTouch::GetScreenX(PRInt32* aScreenX)
78 : {
79 0 : *aScreenX = mScreenPoint.x;
80 0 : return NS_OK;
81 : }
82 :
83 : NS_IMETHODIMP
84 0 : nsDOMTouch::GetScreenY(PRInt32* aScreenY)
85 : {
86 0 : *aScreenY = mScreenPoint.y;
87 0 : return NS_OK;
88 : }
89 :
90 : NS_IMETHODIMP
91 0 : nsDOMTouch::GetClientX(PRInt32* aClientX)
92 : {
93 0 : *aClientX = mClientPoint.x;
94 0 : return NS_OK;
95 : }
96 :
97 : NS_IMETHODIMP
98 0 : nsDOMTouch::GetClientY(PRInt32* aClientY)
99 : {
100 0 : *aClientY = mClientPoint.y;
101 0 : return NS_OK;
102 : }
103 :
104 : NS_IMETHODIMP
105 0 : nsDOMTouch::GetPageX(PRInt32* aPageX)
106 : {
107 0 : *aPageX = mPagePoint.x;
108 0 : return NS_OK;
109 : }
110 :
111 : NS_IMETHODIMP
112 0 : nsDOMTouch::GetPageY(PRInt32* aPageY)
113 : {
114 0 : *aPageY = mPagePoint.y;
115 0 : return NS_OK;
116 : }
117 :
118 : NS_IMETHODIMP
119 0 : nsDOMTouch::GetRadiusX(PRInt32* aRadiusX)
120 : {
121 0 : *aRadiusX = mRadius.x;
122 0 : return NS_OK;
123 : }
124 :
125 : NS_IMETHODIMP
126 0 : nsDOMTouch::GetRadiusY(PRInt32* aRadiusY)
127 : {
128 0 : *aRadiusY = mRadius.y;
129 0 : return NS_OK;
130 : }
131 :
132 : NS_IMETHODIMP
133 0 : nsDOMTouch::GetRotationAngle(float* aRotationAngle)
134 : {
135 0 : *aRotationAngle = mRotationAngle;
136 0 : return NS_OK;
137 : }
138 :
139 : NS_IMETHODIMP
140 0 : nsDOMTouch::GetForce(float* aForce)
141 : {
142 0 : *aForce = mForce;
143 0 : return NS_OK;
144 : }
145 :
146 : bool
147 0 : nsDOMTouch::Equals(nsIDOMTouch* aTouch)
148 : {
149 : float force;
150 : float orientation;
151 : PRInt32 radiusX, radiusY;
152 0 : aTouch->GetForce(&force);
153 0 : aTouch->GetRotationAngle(&orientation);
154 0 : aTouch->GetRadiusX(&radiusX);
155 0 : aTouch->GetRadiusY(&radiusY);
156 0 : return mRefPoint != aTouch->mRefPoint ||
157 : (mForce != force) ||
158 : (mRotationAngle != orientation) ||
159 0 : (mRadius.x != radiusX) || (mRadius.y != radiusY);
160 : }
161 :
162 : // TouchList
163 0 : nsDOMTouchList::nsDOMTouchList(nsTArray<nsCOMPtr<nsIDOMTouch> > &aTouches)
164 : {
165 0 : mPoints.AppendElements(aTouches);
166 0 : }
167 :
168 : DOMCI_DATA(TouchList, nsDOMTouchList)
169 :
170 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTouchList)
171 :
172 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMTouchList)
173 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
174 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMTouchList)
175 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TouchList)
176 0 : NS_INTERFACE_MAP_END
177 :
178 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMTouchList)
179 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mPoints)
180 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
181 :
182 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMTouchList)
183 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mPoints)
184 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
185 :
186 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMTouchList)
187 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMTouchList)
188 :
189 : NS_IMETHODIMP
190 0 : nsDOMTouchList::GetLength(PRUint32* aLength)
191 : {
192 0 : *aLength = mPoints.Length();
193 0 : return NS_OK;
194 : }
195 :
196 : NS_IMETHODIMP
197 0 : nsDOMTouchList::Item(PRUint32 aIndex, nsIDOMTouch** aRetVal)
198 : {
199 0 : NS_IF_ADDREF(*aRetVal = mPoints.SafeElementAt(aIndex, nsnull));
200 0 : return NS_OK;
201 : }
202 :
203 : NS_IMETHODIMP
204 0 : nsDOMTouchList::IdentifiedTouch(PRInt32 aIdentifier, nsIDOMTouch** aRetVal)
205 : {
206 0 : *aRetVal = nsnull;
207 0 : for (PRUint32 i = 0; i < mPoints.Length(); ++i) {
208 0 : nsCOMPtr<nsIDOMTouch> point = mPoints[i];
209 : PRInt32 identifier;
210 0 : if (point && NS_SUCCEEDED(point->GetIdentifier(&identifier)) &&
211 : aIdentifier == identifier) {
212 0 : point.swap(*aRetVal);
213 : break;
214 : }
215 : }
216 0 : return NS_OK;
217 : }
218 :
219 : // TouchEvent
220 :
221 0 : nsDOMTouchEvent::nsDOMTouchEvent(nsPresContext* aPresContext,
222 : nsTouchEvent* aEvent)
223 : : nsDOMUIEvent(aPresContext, aEvent ? aEvent :
224 0 : new nsTouchEvent(false, 0, nsnull))
225 : {
226 0 : if (aEvent) {
227 0 : mEventIsInternal = false;
228 :
229 0 : for (PRUint32 i = 0; i < aEvent->touches.Length(); ++i) {
230 0 : nsIDOMTouch *touch = aEvent->touches[i];
231 0 : nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
232 0 : domtouch->InitializePoints(mPresContext, aEvent);
233 : }
234 : } else {
235 0 : mEventIsInternal = true;
236 0 : mEvent->time = PR_Now();
237 : }
238 0 : }
239 :
240 0 : nsDOMTouchEvent::~nsDOMTouchEvent()
241 : {
242 0 : if (mEventIsInternal && mEvent) {
243 0 : delete static_cast<nsTouchEvent*>(mEvent);
244 0 : mEvent = nsnull;
245 : }
246 0 : }
247 :
248 1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTouchEvent)
249 :
250 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
251 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTouches)
252 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTargetTouches)
253 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChangedTouches)
254 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
255 :
256 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
257 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTouches)
258 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTargetTouches)
259 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChangedTouches)
260 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
261 :
262 : DOMCI_DATA(TouchEvent, nsDOMTouchEvent)
263 :
264 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMTouchEvent)
265 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMTouchEvent)
266 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TouchEvent)
267 0 : NS_INTERFACE_MAP_END_INHERITING(nsDOMUIEvent)
268 :
269 0 : NS_IMPL_ADDREF_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
270 0 : NS_IMPL_RELEASE_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
271 :
272 :
273 : NS_IMETHODIMP
274 0 : nsDOMTouchEvent::InitTouchEvent(const nsAString& aType,
275 : bool aCanBubble,
276 : bool aCancelable,
277 : nsIDOMWindow* aView,
278 : PRInt32 aDetail,
279 : bool aCtrlKey,
280 : bool aAltKey,
281 : bool aShiftKey,
282 : bool aMetaKey,
283 : nsIDOMTouchList* aTouches,
284 : nsIDOMTouchList* aTargetTouches,
285 : nsIDOMTouchList* aChangedTouches)
286 : {
287 : nsresult rv = nsDOMUIEvent::InitUIEvent(aType,
288 : aCanBubble,
289 : aCancelable,
290 : aView,
291 0 : aDetail);
292 0 : NS_ENSURE_SUCCESS(rv, rv);
293 :
294 0 : static_cast<nsInputEvent*>(mEvent)->isControl = aCtrlKey;
295 0 : static_cast<nsInputEvent*>(mEvent)->isAlt = aAltKey;
296 0 : static_cast<nsInputEvent*>(mEvent)->isShift = aShiftKey;
297 0 : static_cast<nsInputEvent*>(mEvent)->isMeta = aMetaKey;
298 0 : mTouches = aTouches;
299 0 : mTargetTouches = aTargetTouches;
300 0 : mChangedTouches = aChangedTouches;
301 0 : return NS_OK;
302 : }
303 :
304 : NS_IMETHODIMP
305 0 : nsDOMTouchEvent::GetTouches(nsIDOMTouchList** aTouches)
306 : {
307 0 : NS_ENSURE_ARG_POINTER(aTouches);
308 0 : NS_ENSURE_STATE(mEvent);
309 0 : nsRefPtr<nsDOMTouchList> t;
310 :
311 0 : if (mTouches) {
312 0 : return CallQueryInterface(mTouches, aTouches);
313 : }
314 :
315 0 : nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
316 0 : if (mEvent->message == NS_TOUCH_END || mEvent->message == NS_TOUCH_CANCEL) {
317 : // for touchend events, remove any changed touches from the touches array
318 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > unchangedTouches;
319 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
320 0 : for (PRUint32 i = 0; i < touches.Length(); ++i) {
321 0 : if (!touches[i]->mChanged) {
322 0 : unchangedTouches.AppendElement(touches[i]);
323 : }
324 : }
325 0 : t = new nsDOMTouchList(unchangedTouches);
326 : } else {
327 0 : t = new nsDOMTouchList(touchEvent->touches);
328 : }
329 0 : mTouches = t;
330 0 : return CallQueryInterface(mTouches, aTouches);
331 : }
332 :
333 : NS_IMETHODIMP
334 0 : nsDOMTouchEvent::GetTargetTouches(nsIDOMTouchList** aTargetTouches)
335 : {
336 0 : NS_ENSURE_ARG_POINTER(aTargetTouches);
337 0 : NS_ENSURE_STATE(mEvent);
338 :
339 0 : if (mTargetTouches) {
340 0 : return CallQueryInterface(mTargetTouches, aTargetTouches);
341 : }
342 :
343 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > targetTouches;
344 0 : nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
345 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
346 0 : for (PRUint32 i = 0; i < touches.Length(); ++i) {
347 : // for touchend/cancel events, don't append to the target list if this is a
348 : // touch that is ending
349 0 : if ((mEvent->message != NS_TOUCH_END &&
350 0 : mEvent->message != NS_TOUCH_CANCEL) || !touches[i]->mChanged) {
351 0 : nsIDOMEventTarget* targetPtr = touches[i]->GetTarget();
352 0 : if (targetPtr == mEvent->target) {
353 0 : targetTouches.AppendElement(touches[i]);
354 : }
355 : }
356 : }
357 0 : mTargetTouches = new nsDOMTouchList(targetTouches);
358 0 : return CallQueryInterface(mTargetTouches, aTargetTouches);
359 : }
360 :
361 : NS_IMETHODIMP
362 0 : nsDOMTouchEvent::GetChangedTouches(nsIDOMTouchList** aChangedTouches)
363 : {
364 0 : NS_ENSURE_ARG_POINTER(aChangedTouches);
365 0 : NS_ENSURE_STATE(mEvent);
366 :
367 0 : if (mChangedTouches) {
368 0 : return CallQueryInterface(mChangedTouches, aChangedTouches);
369 : }
370 :
371 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > changedTouches;
372 0 : nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
373 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
374 0 : for (PRUint32 i = 0; i < touches.Length(); ++i) {
375 0 : if (touches[i]->mChanged) {
376 0 : changedTouches.AppendElement(touches[i]);
377 : }
378 : }
379 0 : mChangedTouches = new nsDOMTouchList(changedTouches);
380 0 : return CallQueryInterface(mChangedTouches, aChangedTouches);
381 : }
382 :
383 : NS_IMETHODIMP
384 0 : nsDOMTouchEvent::GetAltKey(bool* aAltKey)
385 : {
386 0 : *aAltKey = static_cast<nsInputEvent*>(mEvent)->isAlt;
387 0 : return NS_OK;
388 : }
389 :
390 : NS_IMETHODIMP
391 0 : nsDOMTouchEvent::GetMetaKey(bool* aMetaKey)
392 : {
393 0 : *aMetaKey = static_cast<nsInputEvent*>(mEvent)->isMeta;
394 0 : return NS_OK;
395 : }
396 :
397 : NS_IMETHODIMP
398 0 : nsDOMTouchEvent::GetCtrlKey(bool* aCtrlKey)
399 : {
400 0 : *aCtrlKey = static_cast<nsInputEvent*>(mEvent)->isControl;
401 0 : return NS_OK;
402 : }
403 :
404 : NS_IMETHODIMP
405 0 : nsDOMTouchEvent::GetShiftKey(bool* aShiftKey)
406 : {
407 0 : *aShiftKey = static_cast<nsInputEvent*>(mEvent)->isShift;
408 0 : return NS_OK;
409 : }
410 :
411 : bool
412 42534 : nsDOMTouchEvent::PrefEnabled()
413 : {
414 : static bool sDidCheckPref = false;
415 : static bool sPrefValue = false;
416 42534 : if (!sDidCheckPref) {
417 306 : sDidCheckPref = true;
418 306 : sPrefValue = Preferences::GetBool("dom.w3c_touch_events.enabled", false);
419 306 : if (sPrefValue) {
420 0 : nsContentUtils::InitializeTouchEventTable();
421 : }
422 : }
423 42534 : return sPrefValue;
424 : }
425 :
426 : nsresult
427 0 : NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult,
428 : nsPresContext* aPresContext,
429 : nsTouchEvent *aEvent)
430 : {
431 0 : nsDOMTouchEvent* it = new nsDOMTouchEvent(aPresContext, aEvent);
432 :
433 0 : return CallQueryInterface(it, aInstancePtrResult);
434 4392 : }
|