1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org
.chromium
.chromoting
;
7 import android
.graphics
.PointF
;
8 import android
.os
.SystemClock
;
9 import android
.util
.SparseArray
;
10 import android
.view
.InputDevice
;
11 import android
.view
.MotionEvent
;
14 * Utility for creating MotionEvents for multi-touch event simulation. The events are created by
15 * calling MotionEvent.obtain(...) with suitable parameters.
17 public class TouchEventGenerator
{
19 * Stores the current set of held-down fingers. This is a sparse array since the indices of the
20 * fingers are not contiguous. For example, if fingers 0, 1, 2 are pressed then finger 1 is
21 * lifted, the device ids 0, 2 would correspond to the indexes 0, 1.
23 private SparseArray
<PointF
> mFingerPositions
= new SparseArray
<PointF
>();
26 * The event's DownTime. This is set to the system's current time when the first finger is
29 private long mDownTime
;
32 * Creates a fake event with the given action and device id. The event is generated using the
33 * information in |mFingerPositions|.
35 * @param actionMasked The (masked) action to generate, for example, ACTION_POINTER_DOWN.
36 * @param id The device id of the event. There must already be an entry for |id| in
37 * |mFingerPositions|, so that |id| can be converted to an index and combined with
38 * |actionMasked| to set the new event's |action| property.
40 private MotionEvent
obtainEvent(int actionMasked
, int id
) {
41 int actionIndex
= mFingerPositions
.indexOfKey(id
);
42 assert actionIndex
>= 0;
43 int action
= (actionIndex
<< MotionEvent
.ACTION_POINTER_INDEX_SHIFT
) | actionMasked
;
45 long eventTime
= SystemClock
.uptimeMillis();
46 int size
= mFingerPositions
.size();
48 // Generate the arrays of pointers and positions for the event.
49 MotionEvent
.PointerProperties
[] pointers
= new MotionEvent
.PointerProperties
[size
];
50 MotionEvent
.PointerCoords
[] positions
= new MotionEvent
.PointerCoords
[size
];
51 for (int i
= 0; i
< size
; i
++) {
52 int key
= mFingerPositions
.keyAt(i
);
53 PointF position
= mFingerPositions
.valueAt(i
);
55 pointers
[i
] = new MotionEvent
.PointerProperties();
58 positions
[i
] = new MotionEvent
.PointerCoords();
59 positions
[i
].x
= position
.x
;
60 positions
[i
].y
= position
.y
;
63 return MotionEvent
.obtain(mDownTime
, eventTime
, action
, size
, pointers
, positions
,
64 0, 0, 1, 1, id
, 0, InputDevice
.SOURCE_TOUCHSCREEN
, 0);
68 * Obtains a finger-down event.
70 * @param id The device id of the new finger that is pressed. The caller must ensure this is
71 * a finger not currently held down.
72 * @param x The x-coordinate of the new finger position.
73 * @param y The y-coordinate of the new finger position.
75 public MotionEvent
obtainDownEvent(int id
, float x
, float y
) {
76 assert mFingerPositions
.get(id
) == null;
77 mFingerPositions
.put(id
, new PointF(x
, y
));
79 if (mFingerPositions
.size() == 1) {
80 mDownTime
= SystemClock
.uptimeMillis();
81 actionMasked
= MotionEvent
.ACTION_DOWN
;
83 actionMasked
= MotionEvent
.ACTION_POINTER_DOWN
;
85 return obtainEvent(actionMasked
, id
);
89 * Obtains a finger-up event.
91 * @param id The device id of the finger to be lifted. The caller must ensure this is a
92 * finger previously held down.
94 public MotionEvent
obtainUpEvent(int id
) {
95 assert mFingerPositions
.get(id
) != null;
97 int actionMasked
= mFingerPositions
.size() == 1
98 ? MotionEvent
.ACTION_UP
: MotionEvent
.ACTION_POINTER_UP
;
100 MotionEvent event
= obtainEvent(actionMasked
, id
);
101 mFingerPositions
.remove(id
);
106 * Obtains a finger-move event. This moves a single finger, keeping any others in the same
109 * @param id The device id of the finger being moved. The caller must ensure this is a
110 * finger previously held down.
111 * @param x The x-coordinate of the new finger position.
112 * @param y The y-coordinate of the new finger position.
114 public MotionEvent
obtainMoveEvent(int id
, float x
, float y
) {
115 PointF position
= mFingerPositions
.get(id
);
116 assert position
!= null;
119 return obtainEvent(MotionEvent
.ACTION_MOVE
, id
);