|
1 /* |
|
2 * Copyright (C) 2010 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 |
|
17 #define LOG_TAG "Input" |
|
18 //#define LOG_NDEBUG 0 |
|
19 #include "cutils_log.h" |
|
20 |
|
21 #include <math.h> |
|
22 #include <limits.h> |
|
23 |
|
24 #include "Input.h" |
|
25 |
|
26 #ifdef HAVE_ANDROID_OS |
|
27 #include <binder/Parcel.h> |
|
28 |
|
29 #include "SkPoint.h" |
|
30 #include "SkMatrix.h" |
|
31 #include "SkScalar.h" |
|
32 #endif |
|
33 |
|
34 namespace android { |
|
35 |
|
36 // --- InputEvent --- |
|
37 |
|
38 void InputEvent::initialize(int32_t deviceId, int32_t source) { |
|
39 mDeviceId = deviceId; |
|
40 mSource = source; |
|
41 } |
|
42 |
|
43 void InputEvent::initialize(const InputEvent& from) { |
|
44 mDeviceId = from.mDeviceId; |
|
45 mSource = from.mSource; |
|
46 } |
|
47 |
|
48 // --- KeyEvent --- |
|
49 |
|
50 bool KeyEvent::hasDefaultAction(int32_t keyCode) { |
|
51 switch (keyCode) { |
|
52 case AKEYCODE_HOME: |
|
53 case AKEYCODE_BACK: |
|
54 case AKEYCODE_CALL: |
|
55 case AKEYCODE_ENDCALL: |
|
56 case AKEYCODE_VOLUME_UP: |
|
57 case AKEYCODE_VOLUME_DOWN: |
|
58 case AKEYCODE_VOLUME_MUTE: |
|
59 case AKEYCODE_POWER: |
|
60 case AKEYCODE_CAMERA: |
|
61 case AKEYCODE_HEADSETHOOK: |
|
62 case AKEYCODE_MENU: |
|
63 case AKEYCODE_NOTIFICATION: |
|
64 case AKEYCODE_FOCUS: |
|
65 case AKEYCODE_SEARCH: |
|
66 case AKEYCODE_MEDIA_PLAY: |
|
67 case AKEYCODE_MEDIA_PAUSE: |
|
68 case AKEYCODE_MEDIA_PLAY_PAUSE: |
|
69 case AKEYCODE_MEDIA_STOP: |
|
70 case AKEYCODE_MEDIA_NEXT: |
|
71 case AKEYCODE_MEDIA_PREVIOUS: |
|
72 case AKEYCODE_MEDIA_REWIND: |
|
73 case AKEYCODE_MEDIA_RECORD: |
|
74 case AKEYCODE_MEDIA_FAST_FORWARD: |
|
75 case AKEYCODE_MUTE: |
|
76 case AKEYCODE_BRIGHTNESS_DOWN: |
|
77 case AKEYCODE_BRIGHTNESS_UP: |
|
78 return true; |
|
79 } |
|
80 |
|
81 return false; |
|
82 } |
|
83 |
|
84 bool KeyEvent::hasDefaultAction() const { |
|
85 return hasDefaultAction(getKeyCode()); |
|
86 } |
|
87 |
|
88 bool KeyEvent::isSystemKey(int32_t keyCode) { |
|
89 switch (keyCode) { |
|
90 case AKEYCODE_MENU: |
|
91 case AKEYCODE_SOFT_RIGHT: |
|
92 case AKEYCODE_HOME: |
|
93 case AKEYCODE_BACK: |
|
94 case AKEYCODE_CALL: |
|
95 case AKEYCODE_ENDCALL: |
|
96 case AKEYCODE_VOLUME_UP: |
|
97 case AKEYCODE_VOLUME_DOWN: |
|
98 case AKEYCODE_VOLUME_MUTE: |
|
99 case AKEYCODE_MUTE: |
|
100 case AKEYCODE_POWER: |
|
101 case AKEYCODE_HEADSETHOOK: |
|
102 case AKEYCODE_MEDIA_PLAY: |
|
103 case AKEYCODE_MEDIA_PAUSE: |
|
104 case AKEYCODE_MEDIA_PLAY_PAUSE: |
|
105 case AKEYCODE_MEDIA_STOP: |
|
106 case AKEYCODE_MEDIA_NEXT: |
|
107 case AKEYCODE_MEDIA_PREVIOUS: |
|
108 case AKEYCODE_MEDIA_REWIND: |
|
109 case AKEYCODE_MEDIA_RECORD: |
|
110 case AKEYCODE_MEDIA_FAST_FORWARD: |
|
111 case AKEYCODE_CAMERA: |
|
112 case AKEYCODE_FOCUS: |
|
113 case AKEYCODE_SEARCH: |
|
114 case AKEYCODE_BRIGHTNESS_DOWN: |
|
115 case AKEYCODE_BRIGHTNESS_UP: |
|
116 return true; |
|
117 } |
|
118 |
|
119 return false; |
|
120 } |
|
121 |
|
122 bool KeyEvent::isSystemKey() const { |
|
123 return isSystemKey(getKeyCode()); |
|
124 } |
|
125 |
|
126 void KeyEvent::initialize( |
|
127 int32_t deviceId, |
|
128 int32_t source, |
|
129 int32_t action, |
|
130 int32_t flags, |
|
131 int32_t keyCode, |
|
132 int32_t scanCode, |
|
133 int32_t metaState, |
|
134 int32_t repeatCount, |
|
135 nsecs_t downTime, |
|
136 nsecs_t eventTime) { |
|
137 InputEvent::initialize(deviceId, source); |
|
138 mAction = action; |
|
139 mFlags = flags; |
|
140 mKeyCode = keyCode; |
|
141 mScanCode = scanCode; |
|
142 mMetaState = metaState; |
|
143 mRepeatCount = repeatCount; |
|
144 mDownTime = downTime; |
|
145 mEventTime = eventTime; |
|
146 } |
|
147 |
|
148 void KeyEvent::initialize(const KeyEvent& from) { |
|
149 InputEvent::initialize(from); |
|
150 mAction = from.mAction; |
|
151 mFlags = from.mFlags; |
|
152 mKeyCode = from.mKeyCode; |
|
153 mScanCode = from.mScanCode; |
|
154 mMetaState = from.mMetaState; |
|
155 mRepeatCount = from.mRepeatCount; |
|
156 mDownTime = from.mDownTime; |
|
157 mEventTime = from.mEventTime; |
|
158 } |
|
159 |
|
160 |
|
161 // --- PointerCoords --- |
|
162 |
|
163 float PointerCoords::getAxisValue(int32_t axis) const { |
|
164 if (axis < 0 || axis > 63) { |
|
165 return 0; |
|
166 } |
|
167 |
|
168 uint64_t axisBit = 1LL << axis; |
|
169 if (!(bits & axisBit)) { |
|
170 return 0; |
|
171 } |
|
172 uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); |
|
173 return values[index]; |
|
174 } |
|
175 |
|
176 status_t PointerCoords::setAxisValue(int32_t axis, float value) { |
|
177 if (axis < 0 || axis > 63) { |
|
178 return NAME_NOT_FOUND; |
|
179 } |
|
180 |
|
181 uint64_t axisBit = 1LL << axis; |
|
182 uint32_t index = __builtin_popcountll(bits & (axisBit - 1LL)); |
|
183 if (!(bits & axisBit)) { |
|
184 if (value == 0) { |
|
185 return OK; // axes with value 0 do not need to be stored |
|
186 } |
|
187 uint32_t count = __builtin_popcountll(bits); |
|
188 if (count >= MAX_AXES) { |
|
189 tooManyAxes(axis); |
|
190 return NO_MEMORY; |
|
191 } |
|
192 bits |= axisBit; |
|
193 for (uint32_t i = count; i > index; i--) { |
|
194 values[i] = values[i - 1]; |
|
195 } |
|
196 } |
|
197 values[index] = value; |
|
198 return OK; |
|
199 } |
|
200 |
|
201 static inline void scaleAxisValue(PointerCoords& c, int axis, float scaleFactor) { |
|
202 float value = c.getAxisValue(axis); |
|
203 if (value != 0) { |
|
204 c.setAxisValue(axis, value * scaleFactor); |
|
205 } |
|
206 } |
|
207 |
|
208 void PointerCoords::scale(float scaleFactor) { |
|
209 // No need to scale pressure or size since they are normalized. |
|
210 // No need to scale orientation since it is meaningless to do so. |
|
211 scaleAxisValue(*this, AMOTION_EVENT_AXIS_X, scaleFactor); |
|
212 scaleAxisValue(*this, AMOTION_EVENT_AXIS_Y, scaleFactor); |
|
213 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MAJOR, scaleFactor); |
|
214 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOUCH_MINOR, scaleFactor); |
|
215 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MAJOR, scaleFactor); |
|
216 scaleAxisValue(*this, AMOTION_EVENT_AXIS_TOOL_MINOR, scaleFactor); |
|
217 } |
|
218 |
|
219 #ifdef HAVE_ANDROID_OS |
|
220 status_t PointerCoords::readFromParcel(Parcel* parcel) { |
|
221 bits = parcel->readInt64(); |
|
222 |
|
223 uint32_t count = __builtin_popcountll(bits); |
|
224 if (count > MAX_AXES) { |
|
225 return BAD_VALUE; |
|
226 } |
|
227 |
|
228 for (uint32_t i = 0; i < count; i++) { |
|
229 values[i] = parcel->readFloat(); |
|
230 } |
|
231 return OK; |
|
232 } |
|
233 |
|
234 status_t PointerCoords::writeToParcel(Parcel* parcel) const { |
|
235 parcel->writeInt64(bits); |
|
236 |
|
237 uint32_t count = __builtin_popcountll(bits); |
|
238 for (uint32_t i = 0; i < count; i++) { |
|
239 parcel->writeFloat(values[i]); |
|
240 } |
|
241 return OK; |
|
242 } |
|
243 #endif |
|
244 |
|
245 void PointerCoords::tooManyAxes(int axis) { |
|
246 ALOGW("Could not set value for axis %d because the PointerCoords structure is full and " |
|
247 "cannot contain more than %d axis values.", axis, int(MAX_AXES)); |
|
248 } |
|
249 |
|
250 bool PointerCoords::operator==(const PointerCoords& other) const { |
|
251 if (bits != other.bits) { |
|
252 return false; |
|
253 } |
|
254 uint32_t count = __builtin_popcountll(bits); |
|
255 for (uint32_t i = 0; i < count; i++) { |
|
256 if (values[i] != other.values[i]) { |
|
257 return false; |
|
258 } |
|
259 } |
|
260 return true; |
|
261 } |
|
262 |
|
263 void PointerCoords::copyFrom(const PointerCoords& other) { |
|
264 bits = other.bits; |
|
265 uint32_t count = __builtin_popcountll(bits); |
|
266 for (uint32_t i = 0; i < count; i++) { |
|
267 values[i] = other.values[i]; |
|
268 } |
|
269 } |
|
270 |
|
271 |
|
272 // --- PointerProperties --- |
|
273 |
|
274 bool PointerProperties::operator==(const PointerProperties& other) const { |
|
275 return id == other.id |
|
276 && toolType == other.toolType; |
|
277 } |
|
278 |
|
279 void PointerProperties::copyFrom(const PointerProperties& other) { |
|
280 id = other.id; |
|
281 toolType = other.toolType; |
|
282 } |
|
283 |
|
284 |
|
285 // --- MotionEvent --- |
|
286 |
|
287 void MotionEvent::initialize( |
|
288 int32_t deviceId, |
|
289 int32_t source, |
|
290 int32_t action, |
|
291 int32_t flags, |
|
292 int32_t edgeFlags, |
|
293 int32_t metaState, |
|
294 int32_t buttonState, |
|
295 float xOffset, |
|
296 float yOffset, |
|
297 float xPrecision, |
|
298 float yPrecision, |
|
299 nsecs_t downTime, |
|
300 nsecs_t eventTime, |
|
301 size_t pointerCount, |
|
302 const PointerProperties* pointerProperties, |
|
303 const PointerCoords* pointerCoords) { |
|
304 InputEvent::initialize(deviceId, source); |
|
305 mAction = action; |
|
306 mFlags = flags; |
|
307 mEdgeFlags = edgeFlags; |
|
308 mMetaState = metaState; |
|
309 mButtonState = buttonState; |
|
310 mXOffset = xOffset; |
|
311 mYOffset = yOffset; |
|
312 mXPrecision = xPrecision; |
|
313 mYPrecision = yPrecision; |
|
314 mDownTime = downTime; |
|
315 mPointerProperties.clear(); |
|
316 mPointerProperties.appendArray(pointerProperties, pointerCount); |
|
317 mSampleEventTimes.clear(); |
|
318 mSamplePointerCoords.clear(); |
|
319 addSample(eventTime, pointerCoords); |
|
320 } |
|
321 |
|
322 void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) { |
|
323 InputEvent::initialize(other->mDeviceId, other->mSource); |
|
324 mAction = other->mAction; |
|
325 mFlags = other->mFlags; |
|
326 mEdgeFlags = other->mEdgeFlags; |
|
327 mMetaState = other->mMetaState; |
|
328 mButtonState = other->mButtonState; |
|
329 mXOffset = other->mXOffset; |
|
330 mYOffset = other->mYOffset; |
|
331 mXPrecision = other->mXPrecision; |
|
332 mYPrecision = other->mYPrecision; |
|
333 mDownTime = other->mDownTime; |
|
334 mPointerProperties = other->mPointerProperties; |
|
335 |
|
336 if (keepHistory) { |
|
337 mSampleEventTimes = other->mSampleEventTimes; |
|
338 mSamplePointerCoords = other->mSamplePointerCoords; |
|
339 } else { |
|
340 mSampleEventTimes.clear(); |
|
341 mSampleEventTimes.push(other->getEventTime()); |
|
342 mSamplePointerCoords.clear(); |
|
343 size_t pointerCount = other->getPointerCount(); |
|
344 size_t historySize = other->getHistorySize(); |
|
345 mSamplePointerCoords.appendArray(other->mSamplePointerCoords.array() |
|
346 + (historySize * pointerCount), pointerCount); |
|
347 } |
|
348 } |
|
349 |
|
350 void MotionEvent::addSample( |
|
351 int64_t eventTime, |
|
352 const PointerCoords* pointerCoords) { |
|
353 mSampleEventTimes.push(eventTime); |
|
354 mSamplePointerCoords.appendArray(pointerCoords, getPointerCount()); |
|
355 } |
|
356 |
|
357 const PointerCoords* MotionEvent::getRawPointerCoords(size_t pointerIndex) const { |
|
358 return &mSamplePointerCoords[getHistorySize() * getPointerCount() + pointerIndex]; |
|
359 } |
|
360 |
|
361 float MotionEvent::getRawAxisValue(int32_t axis, size_t pointerIndex) const { |
|
362 return getRawPointerCoords(pointerIndex)->getAxisValue(axis); |
|
363 } |
|
364 |
|
365 float MotionEvent::getAxisValue(int32_t axis, size_t pointerIndex) const { |
|
366 float value = getRawPointerCoords(pointerIndex)->getAxisValue(axis); |
|
367 switch (axis) { |
|
368 case AMOTION_EVENT_AXIS_X: |
|
369 return value + mXOffset; |
|
370 case AMOTION_EVENT_AXIS_Y: |
|
371 return value + mYOffset; |
|
372 } |
|
373 return value; |
|
374 } |
|
375 |
|
376 const PointerCoords* MotionEvent::getHistoricalRawPointerCoords( |
|
377 size_t pointerIndex, size_t historicalIndex) const { |
|
378 return &mSamplePointerCoords[historicalIndex * getPointerCount() + pointerIndex]; |
|
379 } |
|
380 |
|
381 float MotionEvent::getHistoricalRawAxisValue(int32_t axis, size_t pointerIndex, |
|
382 size_t historicalIndex) const { |
|
383 return getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); |
|
384 } |
|
385 |
|
386 float MotionEvent::getHistoricalAxisValue(int32_t axis, size_t pointerIndex, |
|
387 size_t historicalIndex) const { |
|
388 float value = getHistoricalRawPointerCoords(pointerIndex, historicalIndex)->getAxisValue(axis); |
|
389 switch (axis) { |
|
390 case AMOTION_EVENT_AXIS_X: |
|
391 return value + mXOffset; |
|
392 case AMOTION_EVENT_AXIS_Y: |
|
393 return value + mYOffset; |
|
394 } |
|
395 return value; |
|
396 } |
|
397 |
|
398 ssize_t MotionEvent::findPointerIndex(int32_t pointerId) const { |
|
399 size_t pointerCount = mPointerProperties.size(); |
|
400 for (size_t i = 0; i < pointerCount; i++) { |
|
401 if (mPointerProperties.itemAt(i).id == pointerId) { |
|
402 return i; |
|
403 } |
|
404 } |
|
405 return -1; |
|
406 } |
|
407 |
|
408 void MotionEvent::offsetLocation(float xOffset, float yOffset) { |
|
409 mXOffset += xOffset; |
|
410 mYOffset += yOffset; |
|
411 } |
|
412 |
|
413 void MotionEvent::scale(float scaleFactor) { |
|
414 mXOffset *= scaleFactor; |
|
415 mYOffset *= scaleFactor; |
|
416 mXPrecision *= scaleFactor; |
|
417 mYPrecision *= scaleFactor; |
|
418 |
|
419 size_t numSamples = mSamplePointerCoords.size(); |
|
420 for (size_t i = 0; i < numSamples; i++) { |
|
421 mSamplePointerCoords.editItemAt(i).scale(scaleFactor); |
|
422 } |
|
423 } |
|
424 |
|
425 #ifdef HAVE_ANDROID_OS |
|
426 static inline float transformAngle(const SkMatrix* matrix, float angleRadians) { |
|
427 // Construct and transform a vector oriented at the specified clockwise angle from vertical. |
|
428 // Coordinate system: down is increasing Y, right is increasing X. |
|
429 SkPoint vector; |
|
430 vector.fX = SkFloatToScalar(sinf(angleRadians)); |
|
431 vector.fY = SkFloatToScalar(-cosf(angleRadians)); |
|
432 matrix->mapVectors(& vector, 1); |
|
433 |
|
434 // Derive the transformed vector's clockwise angle from vertical. |
|
435 float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY)); |
|
436 if (result < - M_PI_2) { |
|
437 result += M_PI; |
|
438 } else if (result > M_PI_2) { |
|
439 result -= M_PI; |
|
440 } |
|
441 return result; |
|
442 } |
|
443 |
|
444 void MotionEvent::transform(const SkMatrix* matrix) { |
|
445 float oldXOffset = mXOffset; |
|
446 float oldYOffset = mYOffset; |
|
447 |
|
448 // The tricky part of this implementation is to preserve the value of |
|
449 // rawX and rawY. So we apply the transformation to the first point |
|
450 // then derive an appropriate new X/Y offset that will preserve rawX and rawY. |
|
451 SkPoint point; |
|
452 float rawX = getRawX(0); |
|
453 float rawY = getRawY(0); |
|
454 matrix->mapXY(SkFloatToScalar(rawX + oldXOffset), SkFloatToScalar(rawY + oldYOffset), |
|
455 & point); |
|
456 float newX = SkScalarToFloat(point.fX); |
|
457 float newY = SkScalarToFloat(point.fY); |
|
458 float newXOffset = newX - rawX; |
|
459 float newYOffset = newY - rawY; |
|
460 |
|
461 mXOffset = newXOffset; |
|
462 mYOffset = newYOffset; |
|
463 |
|
464 // Apply the transformation to all samples. |
|
465 size_t numSamples = mSamplePointerCoords.size(); |
|
466 for (size_t i = 0; i < numSamples; i++) { |
|
467 PointerCoords& c = mSamplePointerCoords.editItemAt(i); |
|
468 float x = c.getAxisValue(AMOTION_EVENT_AXIS_X) + oldXOffset; |
|
469 float y = c.getAxisValue(AMOTION_EVENT_AXIS_Y) + oldYOffset; |
|
470 matrix->mapXY(SkFloatToScalar(x), SkFloatToScalar(y), &point); |
|
471 c.setAxisValue(AMOTION_EVENT_AXIS_X, SkScalarToFloat(point.fX) - newXOffset); |
|
472 c.setAxisValue(AMOTION_EVENT_AXIS_Y, SkScalarToFloat(point.fY) - newYOffset); |
|
473 |
|
474 float orientation = c.getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION); |
|
475 c.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, transformAngle(matrix, orientation)); |
|
476 } |
|
477 } |
|
478 |
|
479 status_t MotionEvent::readFromParcel(Parcel* parcel) { |
|
480 size_t pointerCount = parcel->readInt32(); |
|
481 size_t sampleCount = parcel->readInt32(); |
|
482 if (pointerCount == 0 || pointerCount > MAX_POINTERS || sampleCount == 0) { |
|
483 return BAD_VALUE; |
|
484 } |
|
485 |
|
486 mDeviceId = parcel->readInt32(); |
|
487 mSource = parcel->readInt32(); |
|
488 mAction = parcel->readInt32(); |
|
489 mFlags = parcel->readInt32(); |
|
490 mEdgeFlags = parcel->readInt32(); |
|
491 mMetaState = parcel->readInt32(); |
|
492 mButtonState = parcel->readInt32(); |
|
493 mXOffset = parcel->readFloat(); |
|
494 mYOffset = parcel->readFloat(); |
|
495 mXPrecision = parcel->readFloat(); |
|
496 mYPrecision = parcel->readFloat(); |
|
497 mDownTime = parcel->readInt64(); |
|
498 |
|
499 mPointerProperties.clear(); |
|
500 mPointerProperties.setCapacity(pointerCount); |
|
501 mSampleEventTimes.clear(); |
|
502 mSampleEventTimes.setCapacity(sampleCount); |
|
503 mSamplePointerCoords.clear(); |
|
504 mSamplePointerCoords.setCapacity(sampleCount * pointerCount); |
|
505 |
|
506 for (size_t i = 0; i < pointerCount; i++) { |
|
507 mPointerProperties.push(); |
|
508 PointerProperties& properties = mPointerProperties.editTop(); |
|
509 properties.id = parcel->readInt32(); |
|
510 properties.toolType = parcel->readInt32(); |
|
511 } |
|
512 |
|
513 while (sampleCount-- > 0) { |
|
514 mSampleEventTimes.push(parcel->readInt64()); |
|
515 for (size_t i = 0; i < pointerCount; i++) { |
|
516 mSamplePointerCoords.push(); |
|
517 status_t status = mSamplePointerCoords.editTop().readFromParcel(parcel); |
|
518 if (status) { |
|
519 return status; |
|
520 } |
|
521 } |
|
522 } |
|
523 return OK; |
|
524 } |
|
525 |
|
526 status_t MotionEvent::writeToParcel(Parcel* parcel) const { |
|
527 size_t pointerCount = mPointerProperties.size(); |
|
528 size_t sampleCount = mSampleEventTimes.size(); |
|
529 |
|
530 parcel->writeInt32(pointerCount); |
|
531 parcel->writeInt32(sampleCount); |
|
532 |
|
533 parcel->writeInt32(mDeviceId); |
|
534 parcel->writeInt32(mSource); |
|
535 parcel->writeInt32(mAction); |
|
536 parcel->writeInt32(mFlags); |
|
537 parcel->writeInt32(mEdgeFlags); |
|
538 parcel->writeInt32(mMetaState); |
|
539 parcel->writeInt32(mButtonState); |
|
540 parcel->writeFloat(mXOffset); |
|
541 parcel->writeFloat(mYOffset); |
|
542 parcel->writeFloat(mXPrecision); |
|
543 parcel->writeFloat(mYPrecision); |
|
544 parcel->writeInt64(mDownTime); |
|
545 |
|
546 for (size_t i = 0; i < pointerCount; i++) { |
|
547 const PointerProperties& properties = mPointerProperties.itemAt(i); |
|
548 parcel->writeInt32(properties.id); |
|
549 parcel->writeInt32(properties.toolType); |
|
550 } |
|
551 |
|
552 const PointerCoords* pc = mSamplePointerCoords.array(); |
|
553 for (size_t h = 0; h < sampleCount; h++) { |
|
554 parcel->writeInt64(mSampleEventTimes.itemAt(h)); |
|
555 for (size_t i = 0; i < pointerCount; i++) { |
|
556 status_t status = (pc++)->writeToParcel(parcel); |
|
557 if (status) { |
|
558 return status; |
|
559 } |
|
560 } |
|
561 } |
|
562 return OK; |
|
563 } |
|
564 #endif |
|
565 |
|
566 bool MotionEvent::isTouchEvent(int32_t source, int32_t action) { |
|
567 if (source & AINPUT_SOURCE_CLASS_POINTER) { |
|
568 // Specifically excludes HOVER_MOVE and SCROLL. |
|
569 switch (action & AMOTION_EVENT_ACTION_MASK) { |
|
570 case AMOTION_EVENT_ACTION_DOWN: |
|
571 case AMOTION_EVENT_ACTION_MOVE: |
|
572 case AMOTION_EVENT_ACTION_UP: |
|
573 case AMOTION_EVENT_ACTION_POINTER_DOWN: |
|
574 case AMOTION_EVENT_ACTION_POINTER_UP: |
|
575 case AMOTION_EVENT_ACTION_CANCEL: |
|
576 case AMOTION_EVENT_ACTION_OUTSIDE: |
|
577 return true; |
|
578 } |
|
579 } |
|
580 return false; |
|
581 } |
|
582 |
|
583 |
|
584 // --- PooledInputEventFactory --- |
|
585 |
|
586 PooledInputEventFactory::PooledInputEventFactory(size_t maxPoolSize) : |
|
587 mMaxPoolSize(maxPoolSize) { |
|
588 } |
|
589 |
|
590 PooledInputEventFactory::~PooledInputEventFactory() { |
|
591 for (size_t i = 0; i < mKeyEventPool.size(); i++) { |
|
592 delete mKeyEventPool.itemAt(i); |
|
593 } |
|
594 for (size_t i = 0; i < mMotionEventPool.size(); i++) { |
|
595 delete mMotionEventPool.itemAt(i); |
|
596 } |
|
597 } |
|
598 |
|
599 KeyEvent* PooledInputEventFactory::createKeyEvent() { |
|
600 if (!mKeyEventPool.isEmpty()) { |
|
601 KeyEvent* event = mKeyEventPool.top(); |
|
602 mKeyEventPool.pop(); |
|
603 return event; |
|
604 } |
|
605 return new KeyEvent(); |
|
606 } |
|
607 |
|
608 MotionEvent* PooledInputEventFactory::createMotionEvent() { |
|
609 if (!mMotionEventPool.isEmpty()) { |
|
610 MotionEvent* event = mMotionEventPool.top(); |
|
611 mMotionEventPool.pop(); |
|
612 return event; |
|
613 } |
|
614 return new MotionEvent(); |
|
615 } |
|
616 |
|
617 void PooledInputEventFactory::recycle(InputEvent* event) { |
|
618 switch (event->getType()) { |
|
619 case AINPUT_EVENT_TYPE_KEY: |
|
620 if (mKeyEventPool.size() < mMaxPoolSize) { |
|
621 mKeyEventPool.push(static_cast<KeyEvent*>(event)); |
|
622 return; |
|
623 } |
|
624 break; |
|
625 case AINPUT_EVENT_TYPE_MOTION: |
|
626 if (mMotionEventPool.size() < mMaxPoolSize) { |
|
627 mMotionEventPool.push(static_cast<MotionEvent*>(event)); |
|
628 return; |
|
629 } |
|
630 break; |
|
631 } |
|
632 delete event; |
|
633 } |
|
634 |
|
635 } // namespace android |