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 1396 : 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 :
164 : DOMCI_DATA(TouchList, nsDOMTouchList)
165 :
166 1396 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTouchList)
167 :
168 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMTouchList)
169 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
170 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
171 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMTouchList)
172 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TouchList)
173 0 : NS_INTERFACE_MAP_END
174 :
175 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMTouchList)
176 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_OF_NSCOMPTR(mPoints)
177 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParent)
178 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
179 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
180 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMTouchList)
181 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
182 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
183 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMTouchList)
184 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mPoints)
185 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
186 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
187 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
188 :
189 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMTouchList)
190 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMTouchList)
191 :
192 : NS_IMETHODIMP
193 0 : nsDOMTouchList::GetLength(PRUint32* aLength)
194 : {
195 0 : *aLength = mPoints.Length();
196 0 : return NS_OK;
197 : }
198 :
199 : NS_IMETHODIMP
200 0 : nsDOMTouchList::Item(PRUint32 aIndex, nsIDOMTouch** aRetVal)
201 : {
202 0 : NS_IF_ADDREF(*aRetVal = nsDOMTouchList::GetItemAt(aIndex));
203 0 : return NS_OK;
204 : }
205 :
206 : NS_IMETHODIMP
207 0 : nsDOMTouchList::IdentifiedTouch(PRInt32 aIdentifier, nsIDOMTouch** aRetVal)
208 : {
209 0 : *aRetVal = nsnull;
210 0 : for (PRUint32 i = 0; i < mPoints.Length(); ++i) {
211 0 : nsCOMPtr<nsIDOMTouch> point = mPoints[i];
212 : PRInt32 identifier;
213 0 : if (point && NS_SUCCEEDED(point->GetIdentifier(&identifier)) &&
214 : aIdentifier == identifier) {
215 0 : point.swap(*aRetVal);
216 : break;
217 : }
218 : }
219 0 : return NS_OK;
220 : }
221 :
222 : nsIDOMTouch*
223 0 : nsDOMTouchList::GetItemAt(PRUint32 aIndex)
224 : {
225 0 : return mPoints.SafeElementAt(aIndex, nsnull);
226 : }
227 :
228 : // TouchEvent
229 :
230 0 : nsDOMTouchEvent::nsDOMTouchEvent(nsPresContext* aPresContext,
231 : nsTouchEvent* aEvent)
232 : : nsDOMUIEvent(aPresContext, aEvent ? aEvent :
233 0 : new nsTouchEvent(false, 0, nsnull))
234 : {
235 0 : if (aEvent) {
236 0 : mEventIsInternal = false;
237 :
238 0 : for (PRUint32 i = 0; i < aEvent->touches.Length(); ++i) {
239 0 : nsIDOMTouch *touch = aEvent->touches[i];
240 0 : nsDOMTouch *domtouch = static_cast<nsDOMTouch*>(touch);
241 0 : domtouch->InitializePoints(mPresContext, aEvent);
242 : }
243 : } else {
244 0 : mEventIsInternal = true;
245 0 : mEvent->time = PR_Now();
246 : }
247 0 : }
248 :
249 0 : nsDOMTouchEvent::~nsDOMTouchEvent()
250 : {
251 0 : if (mEventIsInternal && mEvent) {
252 0 : delete static_cast<nsTouchEvent*>(mEvent);
253 0 : mEvent = nsnull;
254 : }
255 0 : }
256 :
257 1396 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMTouchEvent)
258 :
259 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
260 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTouches)
261 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTargetTouches)
262 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChangedTouches)
263 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
264 :
265 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
266 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTouches)
267 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTargetTouches)
268 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChangedTouches)
269 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
270 :
271 : DOMCI_DATA(TouchEvent, nsDOMTouchEvent)
272 :
273 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsDOMTouchEvent)
274 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMTouchEvent)
275 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TouchEvent)
276 0 : NS_INTERFACE_MAP_END_INHERITING(nsDOMUIEvent)
277 :
278 0 : NS_IMPL_ADDREF_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
279 0 : NS_IMPL_RELEASE_INHERITED(nsDOMTouchEvent, nsDOMUIEvent)
280 :
281 :
282 : NS_IMETHODIMP
283 0 : nsDOMTouchEvent::InitTouchEvent(const nsAString& aType,
284 : bool aCanBubble,
285 : bool aCancelable,
286 : nsIDOMWindow* aView,
287 : PRInt32 aDetail,
288 : bool aCtrlKey,
289 : bool aAltKey,
290 : bool aShiftKey,
291 : bool aMetaKey,
292 : nsIDOMTouchList* aTouches,
293 : nsIDOMTouchList* aTargetTouches,
294 : nsIDOMTouchList* aChangedTouches)
295 : {
296 : nsresult rv = nsDOMUIEvent::InitUIEvent(aType,
297 : aCanBubble,
298 : aCancelable,
299 : aView,
300 0 : aDetail);
301 0 : NS_ENSURE_SUCCESS(rv, rv);
302 :
303 0 : static_cast<nsInputEvent*>(mEvent)->isControl = aCtrlKey;
304 0 : static_cast<nsInputEvent*>(mEvent)->isAlt = aAltKey;
305 0 : static_cast<nsInputEvent*>(mEvent)->isShift = aShiftKey;
306 0 : static_cast<nsInputEvent*>(mEvent)->isMeta = aMetaKey;
307 0 : mTouches = aTouches;
308 0 : mTargetTouches = aTargetTouches;
309 0 : mChangedTouches = aChangedTouches;
310 0 : return NS_OK;
311 : }
312 :
313 : NS_IMETHODIMP
314 0 : nsDOMTouchEvent::GetTouches(nsIDOMTouchList** aTouches)
315 : {
316 0 : NS_ENSURE_ARG_POINTER(aTouches);
317 0 : NS_ENSURE_STATE(mEvent);
318 0 : nsRefPtr<nsDOMTouchList> t;
319 :
320 0 : if (mTouches) {
321 0 : return CallQueryInterface(mTouches, aTouches);
322 : }
323 :
324 0 : nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
325 0 : if (mEvent->message == NS_TOUCH_END || mEvent->message == NS_TOUCH_CANCEL) {
326 : // for touchend events, remove any changed touches from the touches array
327 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > unchangedTouches;
328 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
329 0 : for (PRUint32 i = 0; i < touches.Length(); ++i) {
330 0 : if (!touches[i]->mChanged) {
331 0 : unchangedTouches.AppendElement(touches[i]);
332 : }
333 : }
334 : t = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
335 0 : unchangedTouches);
336 : } else {
337 : t = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
338 0 : touchEvent->touches);
339 : }
340 0 : mTouches = t;
341 0 : return CallQueryInterface(mTouches, aTouches);
342 : }
343 :
344 : NS_IMETHODIMP
345 0 : nsDOMTouchEvent::GetTargetTouches(nsIDOMTouchList** aTargetTouches)
346 : {
347 0 : NS_ENSURE_ARG_POINTER(aTargetTouches);
348 0 : NS_ENSURE_STATE(mEvent);
349 :
350 0 : if (mTargetTouches) {
351 0 : return CallQueryInterface(mTargetTouches, aTargetTouches);
352 : }
353 :
354 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > targetTouches;
355 0 : nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
356 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
357 0 : for (PRUint32 i = 0; i < touches.Length(); ++i) {
358 : // for touchend/cancel events, don't append to the target list if this is a
359 : // touch that is ending
360 0 : if ((mEvent->message != NS_TOUCH_END &&
361 0 : mEvent->message != NS_TOUCH_CANCEL) || !touches[i]->mChanged) {
362 0 : nsIDOMEventTarget* targetPtr = touches[i]->GetTarget();
363 0 : if (targetPtr == mEvent->target) {
364 0 : targetTouches.AppendElement(touches[i]);
365 : }
366 : }
367 : }
368 : mTargetTouches = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
369 0 : targetTouches);
370 0 : return CallQueryInterface(mTargetTouches, aTargetTouches);
371 : }
372 :
373 : NS_IMETHODIMP
374 0 : nsDOMTouchEvent::GetChangedTouches(nsIDOMTouchList** aChangedTouches)
375 : {
376 0 : NS_ENSURE_ARG_POINTER(aChangedTouches);
377 0 : NS_ENSURE_STATE(mEvent);
378 :
379 0 : if (mChangedTouches) {
380 0 : return CallQueryInterface(mChangedTouches, aChangedTouches);
381 : }
382 :
383 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > changedTouches;
384 0 : nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(mEvent);
385 0 : nsTArray<nsCOMPtr<nsIDOMTouch> > touches = touchEvent->touches;
386 0 : for (PRUint32 i = 0; i < touches.Length(); ++i) {
387 0 : if (touches[i]->mChanged) {
388 0 : changedTouches.AppendElement(touches[i]);
389 : }
390 : }
391 : mChangedTouches = new nsDOMTouchList(static_cast<nsIDOMTouchEvent*>(this),
392 0 : changedTouches);
393 0 : return CallQueryInterface(mChangedTouches, aChangedTouches);
394 : }
395 :
396 : NS_IMETHODIMP
397 0 : nsDOMTouchEvent::GetAltKey(bool* aAltKey)
398 : {
399 0 : *aAltKey = static_cast<nsInputEvent*>(mEvent)->isAlt;
400 0 : return NS_OK;
401 : }
402 :
403 : NS_IMETHODIMP
404 0 : nsDOMTouchEvent::GetMetaKey(bool* aMetaKey)
405 : {
406 0 : *aMetaKey = static_cast<nsInputEvent*>(mEvent)->isMeta;
407 0 : return NS_OK;
408 : }
409 :
410 : NS_IMETHODIMP
411 0 : nsDOMTouchEvent::GetCtrlKey(bool* aCtrlKey)
412 : {
413 0 : *aCtrlKey = static_cast<nsInputEvent*>(mEvent)->isControl;
414 0 : return NS_OK;
415 : }
416 :
417 : NS_IMETHODIMP
418 0 : nsDOMTouchEvent::GetShiftKey(bool* aShiftKey)
419 : {
420 0 : *aShiftKey = static_cast<nsInputEvent*>(mEvent)->isShift;
421 0 : return NS_OK;
422 : }
423 :
424 : bool
425 42395 : nsDOMTouchEvent::PrefEnabled()
426 : {
427 : static bool sDidCheckPref = false;
428 : static bool sPrefValue = false;
429 42395 : if (!sDidCheckPref) {
430 305 : sDidCheckPref = true;
431 305 : sPrefValue = Preferences::GetBool("dom.w3c_touch_events.enabled", false);
432 305 : if (sPrefValue) {
433 0 : nsContentUtils::InitializeTouchEventTable();
434 : }
435 : }
436 42395 : return sPrefValue;
437 : }
438 :
439 : nsresult
440 0 : NS_NewDOMTouchEvent(nsIDOMEvent** aInstancePtrResult,
441 : nsPresContext* aPresContext,
442 : nsTouchEvent *aEvent)
443 : {
444 0 : nsDOMTouchEvent* it = new nsDOMTouchEvent(aPresContext, aEvent);
445 :
446 0 : return CallQueryInterface(it, aInstancePtrResult);
447 4188 : }
|