blob: e1bce731d076f4e732932b94b180c51b4598e866 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import android.util.Log;
20import android.view.Display;
21import android.view.MotionEvent;
22import android.view.Surface;
23import android.view.WindowManagerPolicy;
24
25public class InputDevice {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070026 static final boolean DEBUG_POINTERS = false;
27
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028 /** Amount that trackball needs to move in order to generate a key event. */
29 static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
30
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070031 /** Maximum number of pointers we will track and report. */
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070032 static final int MAX_POINTERS = 10;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034 final int id;
35 final int classes;
36 final String name;
37 final AbsoluteInfo absX;
38 final AbsoluteInfo absY;
39 final AbsoluteInfo absPressure;
40 final AbsoluteInfo absSize;
41
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070042 long mKeyDownTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043 int mMetaKeysState = 0;
44
Dianne Hackborn2a2b34432009-08-12 17:13:55 -070045 // For use by KeyInputQueue for keeping track of the current touch
46 // data in the old non-multi-touch protocol.
47 final int[] curTouchVals = new int[MotionEvent.NUM_SAMPLE_DATA * 2];
48
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 final MotionState mAbs = new MotionState(0, 0);
50 final MotionState mRel = new MotionState(TRACKBALL_MOVEMENT_THRESHOLD,
51 TRACKBALL_MOVEMENT_THRESHOLD);
52
53 static class MotionState {
54 int xPrecision;
55 int yPrecision;
56 float xMoveScale;
57 float yMoveScale;
58 MotionEvent currentMove = null;
59 boolean changed = false;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070060 long mDownTime = 0;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070061
62 // The currently assigned pointer IDs, corresponding to the last data.
63 int[] mPointerIds = new int[MAX_POINTERS];
64
65 // This is the last generated pointer data, ordered to match
66 // mPointerIds.
67 int mLastNumPointers = 0;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070068 final int[] mLastData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070069
70 // This is the next set of pointer data being generated. It is not
71 // in any known order, and will be propagated in to mLastData
72 // as part of mapping it to the appropriate pointer IDs.
73 // Note that we have one extra sample of data here, to help clients
74 // avoid doing bounds checking.
75 int mNextNumPointers = 0;
76 final int[] mNextData = new int[(MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS)
77 + MotionEvent.NUM_SAMPLE_DATA];
78
79 // Temporary data structures for doing the pointer ID mapping.
80 final int[] mLast2Next = new int[MAX_POINTERS];
81 final int[] mNext2Last = new int[MAX_POINTERS];
82 final long[] mNext2LastDistance = new long[MAX_POINTERS];
83
84 // Temporary data structure for generating the final motion data.
Dianne Hackborn9822d2b2009-07-20 17:33:15 -070085 final float[] mReportData = new float[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070087 // This is not used here, but can be used by callers for state tracking.
88 int mAddingPointerOffset = 0;
89 final boolean[] mDown = new boolean[MAX_POINTERS];
90
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 MotionState(int mx, int my) {
92 xPrecision = mx;
93 yPrecision = my;
94 xMoveScale = mx != 0 ? (1.0f/mx) : 1.0f;
95 yMoveScale = my != 0 ? (1.0f/my) : 1.0f;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -070096 for (int i=0; i<MAX_POINTERS; i++) {
97 mPointerIds[i] = i;
98 }
99 }
100
101 private boolean assignPointer(int nextIndex, boolean allowOverlap) {
102 final int lastNumPointers = mLastNumPointers;
103 final int[] next2Last = mNext2Last;
104 final long[] next2LastDistance = mNext2LastDistance;
105 final int[] last2Next = mLast2Next;
106 final int[] lastData = mLastData;
107 final int[] nextData = mNextData;
108 final int id = nextIndex * MotionEvent.NUM_SAMPLE_DATA;
109
110 if (DEBUG_POINTERS) Log.v("InputDevice", "assignPointer: nextIndex="
111 + nextIndex + " dataOff=" + id);
112 final int x1 = nextData[id + MotionEvent.SAMPLE_X];
113 final int y1 = nextData[id + MotionEvent.SAMPLE_Y];
114
115 long bestDistance = -1;
116 int bestIndex = -1;
117 for (int j=0; j<lastNumPointers; j++) {
118 if (!allowOverlap && last2Next[j] < 0) {
119 continue;
120 }
121 final int jd = j * MotionEvent.NUM_SAMPLE_DATA;
122 final int xd = lastData[jd + MotionEvent.SAMPLE_X] - x1;
123 final int yd = lastData[jd + MotionEvent.SAMPLE_Y] - y1;
124 final long distance = xd*(long)xd + yd*(long)yd;
125 if (j == 0 || distance < bestDistance) {
126 bestDistance = distance;
127 bestIndex = j;
128 }
129 }
130
131 if (DEBUG_POINTERS) Log.v("InputDevice", "New index " + nextIndex
132 + " best old index=" + bestIndex + " (distance="
133 + bestDistance + ")");
134 next2Last[nextIndex] = bestIndex;
135 next2LastDistance[nextIndex] = bestDistance;
136
137 if (bestIndex < 0) {
138 return true;
139 }
140
141 if (last2Next[bestIndex] == -1) {
142 last2Next[bestIndex] = nextIndex;
143 return false;
144 }
145
146 if (DEBUG_POINTERS) Log.v("InputDevice", "Old index " + bestIndex
147 + " has multiple best new pointers!");
148
149 last2Next[bestIndex] = -2;
150 return true;
151 }
152
153 private int updatePointerIdentifiers() {
154 final int[] lastData = mLastData;
155 final int[] nextData = mNextData;
156 final int nextNumPointers = mNextNumPointers;
157 final int lastNumPointers = mLastNumPointers;
158
159 if (nextNumPointers == 1 && lastNumPointers == 1) {
160 System.arraycopy(nextData, 0, lastData, 0,
161 MotionEvent.NUM_SAMPLE_DATA);
162 return -1;
163 }
164
165 // Clear our old state.
166 final int[] last2Next = mLast2Next;
167 for (int i=0; i<lastNumPointers; i++) {
168 last2Next[i] = -1;
169 }
170
171 if (DEBUG_POINTERS) Log.v("InputDevice",
172 "Update pointers: lastNumPointers=" + lastNumPointers
173 + " nextNumPointers=" + nextNumPointers);
174
175 // Figure out the closes new points to the previous points.
176 final int[] next2Last = mNext2Last;
177 final long[] next2LastDistance = mNext2LastDistance;
178 boolean conflicts = false;
179 for (int i=0; i<nextNumPointers; i++) {
180 conflicts |= assignPointer(i, true);
181 }
182
183 // Resolve ambiguities in pointer mappings, when two or more
184 // new pointer locations find their best previous location is
185 // the same.
186 if (conflicts) {
187 if (DEBUG_POINTERS) Log.v("InputDevice", "Resolving conflicts");
188
189 for (int i=0; i<lastNumPointers; i++) {
190 if (last2Next[i] != -2) {
191 continue;
192 }
193
194 // Note that this algorithm is far from perfect. Ideally
195 // we should do something like the one described at
196 // http://portal.acm.org/citation.cfm?id=997856
197
198 if (DEBUG_POINTERS) Log.v("InputDevice",
199 "Resolving last index #" + i);
200
201 int numFound;
202 do {
203 numFound = 0;
204 long worstDistance = 0;
205 int worstJ = -1;
206 for (int j=0; j<nextNumPointers; j++) {
207 if (next2Last[j] != i) {
208 continue;
209 }
210 numFound++;
211 if (worstDistance < next2LastDistance[j]) {
212 worstDistance = next2LastDistance[j];
213 worstJ = j;
214 }
215 }
216
217 if (worstJ >= 0) {
218 if (DEBUG_POINTERS) Log.v("InputDevice",
219 "Worst new pointer: " + worstJ
220 + " (distance=" + worstDistance + ")");
221 if (assignPointer(worstJ, false)) {
222 // In this case there is no last pointer
223 // remaining for this new one!
224 next2Last[worstJ] = -1;
225 }
226 }
227 } while (numFound > 2);
228 }
229 }
230
231 int retIndex = -1;
232
233 if (lastNumPointers < nextNumPointers) {
234 // We have one or more new pointers that are down. Create a
235 // new pointer identifier for one of them.
236 if (DEBUG_POINTERS) Log.v("InputDevice", "Adding new pointer");
237 int nextId = 0;
238 int i=0;
239 while (i < lastNumPointers) {
240 if (mPointerIds[i] > nextId) {
241 // Found a hole, insert the pointer here.
242 if (DEBUG_POINTERS) Log.v("InputDevice",
243 "Inserting new pointer at hole " + i);
244 System.arraycopy(mPointerIds, i, mPointerIds,
245 i+1, lastNumPointers-i);
246 System.arraycopy(lastData, i*MotionEvent.NUM_SAMPLE_DATA,
247 lastData, (i+1)*MotionEvent.NUM_SAMPLE_DATA,
248 (lastNumPointers-i)*MotionEvent.NUM_SAMPLE_DATA);
249 break;
250 }
251 i++;
252 nextId++;
253 }
254
255 if (DEBUG_POINTERS) Log.v("InputDevice",
256 "New pointer id " + nextId + " at index " + i);
257
258 mLastNumPointers++;
259 retIndex = i;
260 mPointerIds[i] = nextId;
261
262 // And assign this identifier to the first new pointer.
263 for (int j=0; j<nextNumPointers; j++) {
264 if (next2Last[j] < 0) {
265 if (DEBUG_POINTERS) Log.v("InputDevice",
266 "Assigning new id to new pointer index " + j);
267 next2Last[j] = i;
268 break;
269 }
270 }
271 }
272
273 // Propagate all of the current data into the appropriate
274 // location in the old data to match the pointer ID that was
275 // assigned to it.
276 for (int i=0; i<nextNumPointers; i++) {
277 int lastIndex = next2Last[i];
278 if (lastIndex >= 0) {
279 if (DEBUG_POINTERS) Log.v("InputDevice",
280 "Copying next pointer index " + i
281 + " to last index " + lastIndex);
282 System.arraycopy(nextData, i*MotionEvent.NUM_SAMPLE_DATA,
283 lastData, lastIndex*MotionEvent.NUM_SAMPLE_DATA,
284 MotionEvent.NUM_SAMPLE_DATA);
285 }
286 }
287
288 if (lastNumPointers > nextNumPointers) {
289 // One or more pointers has gone up. Find the first one,
290 // and adjust accordingly.
291 if (DEBUG_POINTERS) Log.v("InputDevice", "Removing old pointer");
292 for (int i=0; i<lastNumPointers; i++) {
293 if (last2Next[i] == -1) {
294 if (DEBUG_POINTERS) Log.v("InputDevice",
295 "Removing old pointer at index " + i);
296 retIndex = i;
297 break;
298 }
299 }
300 }
301
302 return retIndex;
303 }
304
305 void removeOldPointer(int index) {
306 final int lastNumPointers = mLastNumPointers;
307 if (index >= 0 && index < lastNumPointers) {
308 System.arraycopy(mPointerIds, index+1, mPointerIds,
309 index, lastNumPointers-index-1);
310 System.arraycopy(mLastData, (index+1)*MotionEvent.NUM_SAMPLE_DATA,
311 mLastData, (index)*MotionEvent.NUM_SAMPLE_DATA,
312 (lastNumPointers-index-1)*MotionEvent.NUM_SAMPLE_DATA);
313 mLastNumPointers--;
314 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 }
316
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700317 MotionEvent generateAbsMotion(InputDevice device, long curTime,
318 long curTimeNano, Display display, int orientation,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 int metaState) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700320
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700321 if (mNextNumPointers <= 0 && mLastNumPointers <= 0) {
322 return null;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700323 }
324
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700325 final int lastNumPointers = mLastNumPointers;
326 final int nextNumPointers = mNextNumPointers;
327 if (mNextNumPointers > MAX_POINTERS) {
328 Log.w("InputDevice", "Number of pointers " + mNextNumPointers
329 + " exceeded maximum of " + MAX_POINTERS);
330 mNextNumPointers = MAX_POINTERS;
331 }
332
333 int upOrDownPointer = updatePointerIdentifiers();
334
335 final float[] reportData = mReportData;
336 final int[] rawData = mLastData;
337
338 final int numPointers = mLastNumPointers;
339
340 if (DEBUG_POINTERS) Log.v("InputDevice", "Processing "
341 + numPointers + " pointers (going from " + lastNumPointers
342 + " to " + nextNumPointers + ")");
343
344 for (int i=0; i<numPointers; i++) {
345 final int pos = i * MotionEvent.NUM_SAMPLE_DATA;
346 reportData[pos + MotionEvent.SAMPLE_X] = rawData[pos + MotionEvent.SAMPLE_X];
347 reportData[pos + MotionEvent.SAMPLE_Y] = rawData[pos + MotionEvent.SAMPLE_Y];
348 reportData[pos + MotionEvent.SAMPLE_PRESSURE] = rawData[pos + MotionEvent.SAMPLE_PRESSURE];
349 reportData[pos + MotionEvent.SAMPLE_SIZE] = rawData[pos + MotionEvent.SAMPLE_SIZE];
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700350 }
351
352 int action;
353 int edgeFlags = 0;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700354 if (nextNumPointers != lastNumPointers) {
355 if (nextNumPointers > lastNumPointers) {
356 if (lastNumPointers == 0) {
357 action = MotionEvent.ACTION_DOWN;
358 mDownTime = curTime;
359 } else {
360 action = MotionEvent.ACTION_POINTER_DOWN
361 | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700362 }
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700363 } else {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700364 if (numPointers == 1) {
365 action = MotionEvent.ACTION_UP;
366 } else {
367 action = MotionEvent.ACTION_POINTER_UP
368 | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
369 }
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700370 }
371 currentMove = null;
372 } else {
373 action = MotionEvent.ACTION_MOVE;
374 }
375
376 final int dispW = display.getWidth()-1;
377 final int dispH = display.getHeight()-1;
378 int w = dispW;
379 int h = dispH;
380 if (orientation == Surface.ROTATION_90
381 || orientation == Surface.ROTATION_270) {
382 int tmp = w;
383 w = h;
384 h = tmp;
385 }
386
387 final AbsoluteInfo absX = device.absX;
388 final AbsoluteInfo absY = device.absY;
389 final AbsoluteInfo absPressure = device.absPressure;
390 final AbsoluteInfo absSize = device.absSize;
391 for (int i=0; i<numPointers; i++) {
392 final int j = i * MotionEvent.NUM_SAMPLE_DATA;
393
394 if (absX != null) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700395 reportData[j + MotionEvent.SAMPLE_X] =
396 ((reportData[j + MotionEvent.SAMPLE_X]-absX.minValue)
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700397 / absX.range) * w;
398 }
399 if (absY != null) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700400 reportData[j + MotionEvent.SAMPLE_Y] =
401 ((reportData[j + MotionEvent.SAMPLE_Y]-absY.minValue)
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700402 / absY.range) * h;
403 }
404 if (absPressure != null) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700405 reportData[j + MotionEvent.SAMPLE_PRESSURE] =
406 ((reportData[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue)
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700407 / (float)absPressure.range);
408 }
409 if (absSize != null) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700410 reportData[j + MotionEvent.SAMPLE_SIZE] =
411 ((reportData[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue)
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700412 / (float)absSize.range);
413 }
414
415 switch (orientation) {
416 case Surface.ROTATION_90: {
Dianne Hackborn2a2b34432009-08-12 17:13:55 -0700417 final float temp = reportData[j + MotionEvent.SAMPLE_X];
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700418 reportData[j + MotionEvent.SAMPLE_X] = reportData[j + MotionEvent.SAMPLE_Y];
419 reportData[j + MotionEvent.SAMPLE_Y] = w-temp;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700420 break;
421 }
422 case Surface.ROTATION_180: {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700423 reportData[j + MotionEvent.SAMPLE_X] = w-reportData[j + MotionEvent.SAMPLE_X];
424 reportData[j + MotionEvent.SAMPLE_Y] = h-reportData[j + MotionEvent.SAMPLE_Y];
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700425 break;
426 }
427 case Surface.ROTATION_270: {
Dianne Hackborn2a2b34432009-08-12 17:13:55 -0700428 final float temp = reportData[j + MotionEvent.SAMPLE_X];
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700429 reportData[j + MotionEvent.SAMPLE_X] = h-reportData[j + MotionEvent.SAMPLE_Y];
430 reportData[j + MotionEvent.SAMPLE_Y] = temp;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700431 break;
432 }
433 }
434 }
435
436 // We only consider the first pointer when computing the edge
437 // flags, since they are global to the event.
Dianne Hackbornddca3ee2009-07-23 19:01:31 -0700438 if (action == MotionEvent.ACTION_DOWN) {
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700439 if (reportData[MotionEvent.SAMPLE_X] <= 0) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700440 edgeFlags |= MotionEvent.EDGE_LEFT;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700441 } else if (reportData[MotionEvent.SAMPLE_X] >= dispW) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700442 edgeFlags |= MotionEvent.EDGE_RIGHT;
443 }
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700444 if (reportData[MotionEvent.SAMPLE_Y] <= 0) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700445 edgeFlags |= MotionEvent.EDGE_TOP;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700446 } else if (reportData[MotionEvent.SAMPLE_Y] >= dispH) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700447 edgeFlags |= MotionEvent.EDGE_BOTTOM;
448 }
449 }
450
451 if (currentMove != null) {
452 if (false) Log.i("InputDevice", "Adding batch x="
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700453 + reportData[MotionEvent.SAMPLE_X]
454 + " y=" + reportData[MotionEvent.SAMPLE_Y]
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700455 + " to " + currentMove);
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700456 currentMove.addBatch(curTime, reportData, metaState);
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700457 if (WindowManagerPolicy.WATCH_POINTER) {
458 Log.i("KeyInputQueue", "Updating: " + currentMove);
459 }
460 return null;
461 }
462
463 MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700464 curTimeNano, action, numPointers, mPointerIds, reportData,
465 metaState, xPrecision, yPrecision, device.id, edgeFlags);
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700466 if (action == MotionEvent.ACTION_MOVE) {
467 currentMove = me;
468 }
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700469
470 if (nextNumPointers < lastNumPointers) {
471 removeOldPointer(upOrDownPointer);
472 }
473
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700474 return me;
475 }
476
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700477 boolean hasMore() {
478 return mLastNumPointers != mNextNumPointers;
479 }
480
481 void finish() {
482 mNextNumPointers = mAddingPointerOffset = 0;
483 mNextData[MotionEvent.SAMPLE_PRESSURE] = 0;
484 }
485
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700486 MotionEvent generateRelMotion(InputDevice device, long curTime,
487 long curTimeNano, int orientation, int metaState) {
488
489 final float[] scaled = mReportData;
490
491 // For now we only support 1 pointer with relative motions.
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700492 scaled[MotionEvent.SAMPLE_X] = mNextData[MotionEvent.SAMPLE_X];
493 scaled[MotionEvent.SAMPLE_Y] = mNextData[MotionEvent.SAMPLE_Y];
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700494 scaled[MotionEvent.SAMPLE_PRESSURE] = 1.0f;
495 scaled[MotionEvent.SAMPLE_SIZE] = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496 int edgeFlags = 0;
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700497
498 int action;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700499 if (mNextNumPointers != mLastNumPointers) {
500 mNextData[MotionEvent.SAMPLE_X] =
501 mNextData[MotionEvent.SAMPLE_Y] = 0;
502 if (mNextNumPointers > 0 && mLastNumPointers == 0) {
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700503 action = MotionEvent.ACTION_DOWN;
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700504 mDownTime = curTime;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700505 } else if (mNextNumPointers == 0) {
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700506 action = MotionEvent.ACTION_UP;
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700507 } else {
508 action = MotionEvent.ACTION_MOVE;
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700509 }
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700510 mLastNumPointers = mNextNumPointers;
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700511 currentMove = null;
512 } else {
513 action = MotionEvent.ACTION_MOVE;
514 }
515
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700516 scaled[MotionEvent.SAMPLE_X] *= xMoveScale;
517 scaled[MotionEvent.SAMPLE_Y] *= yMoveScale;
518 switch (orientation) {
519 case Surface.ROTATION_90: {
520 final float temp = scaled[MotionEvent.SAMPLE_X];
521 scaled[MotionEvent.SAMPLE_X] = scaled[MotionEvent.SAMPLE_Y];
522 scaled[MotionEvent.SAMPLE_Y] = -temp;
523 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 }
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700525 case Surface.ROTATION_180: {
526 scaled[MotionEvent.SAMPLE_X] = -scaled[MotionEvent.SAMPLE_X];
527 scaled[MotionEvent.SAMPLE_Y] = -scaled[MotionEvent.SAMPLE_Y];
528 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 }
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700530 case Surface.ROTATION_270: {
531 final float temp = scaled[MotionEvent.SAMPLE_X];
532 scaled[MotionEvent.SAMPLE_X] = -scaled[MotionEvent.SAMPLE_Y];
533 scaled[MotionEvent.SAMPLE_Y] = temp;
534 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 }
536 }
537
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700538 if (currentMove != null) {
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700539 if (false) Log.i("InputDevice", "Adding batch x="
540 + scaled[MotionEvent.SAMPLE_X]
541 + " y=" + scaled[MotionEvent.SAMPLE_Y]
542 + " to " + currentMove);
543 currentMove.addBatch(curTime, scaled, metaState);
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700544 if (WindowManagerPolicy.WATCH_POINTER) {
545 Log.i("KeyInputQueue", "Updating: " + currentMove);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 }
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700547 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 }
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700549
Dianne Hackborn9822d2b2009-07-20 17:33:15 -0700550 MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
Dianne Hackborn0dd7cb42009-08-04 05:49:43 -0700551 curTimeNano, action, 1, mPointerIds, scaled, metaState,
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700552 xPrecision, yPrecision, device.id, edgeFlags);
553 if (action == MotionEvent.ACTION_MOVE) {
554 currentMove = me;
555 }
556 return me;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 }
558 }
559
560 static class AbsoluteInfo {
561 int minValue;
562 int maxValue;
563 int range;
564 int flat;
565 int fuzz;
566 };
567
568 InputDevice(int _id, int _classes, String _name,
569 AbsoluteInfo _absX, AbsoluteInfo _absY,
570 AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {
571 id = _id;
572 classes = _classes;
573 name = _name;
574 absX = _absX;
575 absY = _absY;
576 absPressure = _absPressure;
577 absSize = _absSize;
578 }
579};