PointerLocationView.java revision 70825161b5bf51ed48319e142751a9c88b104994
1f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root/* 2f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * Copyright (C) 2010 The Android Open Source Project 3f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * 4f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 5f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * you may not use this file except in compliance with the License. 6f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * You may obtain a copy of the License at 7f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * 8f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * http://www.apache.org/licenses/LICENSE-2.0 9f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * 10f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * Unless required by applicable law or agreed to in writing, software 11f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 12f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * See the License for the specific language governing permissions and 14f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root * limitations under the License. 15f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root */ 16f8d0f095e34f8d661ca5b7d555d8610272099bffKenny Root 17829778843cf459384841f9f4ecafe862b6228d6eDianne Hackbornpackage com.android.internal.widget; 1890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 1990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.content.Context; 2090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.graphics.Canvas; 2190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.graphics.Paint; 228d60866e2100db70ecf0502c14768a384514d7e9Jeff Brownimport android.graphics.RectF; 2390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.graphics.Paint.FontMetricsInt; 2490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.util.Log; 258d60866e2100db70ecf0502c14768a384514d7e9Jeff Brownimport android.view.InputDevice; 26c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brownimport android.view.KeyEvent; 2790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.MotionEvent; 2890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.VelocityTracker; 2990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.View; 3090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport android.view.ViewConfiguration; 31cc0c159e9b3dd4e0f48da0ce3e33d2c68a651413Jeff Brownimport android.view.MotionEvent.PointerCoords; 3290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 3390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornimport java.util.ArrayList; 3490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 3590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackbornpublic class PointerLocationView extends View { 368d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private static final String TAG = "Pointer"; 378d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 3890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public static class PointerState { 398d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown // Trace of previous points. 408d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private float[] mTraceX = new float[32]; 418d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private float[] mTraceY = new float[32]; 428d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private int mTraceCount; 438d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 448d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown // True if the pointer is down. 4590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private boolean mCurDown; 468d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 478d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown // Most recent coordinates. 48cc0c159e9b3dd4e0f48da0ce3e33d2c68a651413Jeff Brown private PointerCoords mCoords = new PointerCoords(); 4965fd251c3913fc921468a3dad190810db19eb9dfJeff Brown private int mToolType; 508d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 518d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown // Most recent velocity. 529e2ad36be87f2703b3d737189944d82f93bd4f27Jeff Brown private float mXVelocity; 539e2ad36be87f2703b3d737189944d82f93bd4f27Jeff Brown private float mYVelocity; 54b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown 55b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown // Position estimator. 56b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown private VelocityTracker.Estimator mEstimator = new VelocityTracker.Estimator(); 57b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown 588d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown public void clearTrace() { 598d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mTraceCount = 0; 608d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 618d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 628d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown public void addTrace(float x, float y) { 638d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown int traceCapacity = mTraceX.length; 648d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown if (mTraceCount == traceCapacity) { 658d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown traceCapacity *= 2; 668d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown float[] newTraceX = new float[traceCapacity]; 678d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown System.arraycopy(mTraceX, 0, newTraceX, 0, mTraceCount); 688d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mTraceX = newTraceX; 698d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 708d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown float[] newTraceY = new float[traceCapacity]; 718d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown System.arraycopy(mTraceY, 0, newTraceY, 0, mTraceCount); 728d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mTraceY = newTraceY; 738d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 748d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 758d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mTraceX[mTraceCount] = x; 768d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mTraceY[mTraceCount] = y; 778d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mTraceCount += 1; 788d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 7990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 8090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 81b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown private final int ESTIMATE_PAST_POINTS = 4; 82b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown private final int ESTIMATE_FUTURE_POINTS = 2; 83b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown private final float ESTIMATE_INTERVAL = 0.02f; 84b59ab9f41faafb358afb4f951de96f34a656e0b4Jeff Brown 8590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final ViewConfiguration mVC; 8690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTextPaint; 8790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTextBackgroundPaint; 8890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTextLevelPaint; 8990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mPaint; 9090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mTargetPaint; 9190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final Paint mPathPaint; 9290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private final FontMetricsInt mTextMetrics = new FontMetricsInt(); 9390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mHeaderBottom; 9490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private boolean mCurDown; 9590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mCurNumPointers; 9690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private int mMaxNumPointers; 97d1e0c371a651f024b3de62a686c56e369e3f361eJeff Brown private int mActivePointerId; 988d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private final ArrayList<PointerState> mPointers = new ArrayList<PointerState>(); 9965fd251c3913fc921468a3dad190810db19eb9dfJeff Brown private final PointerCoords mTempCoords = new PointerCoords(); 10090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 1019e2ad36be87f2703b3d737189944d82f93bd4f27Jeff Brown private final VelocityTracker mVelocity; 1029e2ad36be87f2703b3d737189944d82f93bd4f27Jeff Brown 1038d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private final FasterStringBuilder mText = new FasterStringBuilder(); 1048d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 10590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn private boolean mPrintCoords = true; 10690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 10790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public PointerLocationView(Context c) { 10890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn super(c); 109c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown setFocusableInTouchMode(true); 110c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown 11190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mVC = ViewConfiguration.get(c); 11290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint = new Paint(); 11390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.setAntiAlias(true); 11490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.setTextSize(10 11590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn * getResources().getDisplayMetrics().density); 11690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.setARGB(255, 0, 0, 0); 11790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextBackgroundPaint = new Paint(); 11890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextBackgroundPaint.setAntiAlias(false); 11990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextBackgroundPaint.setARGB(128, 255, 255, 255); 12090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextLevelPaint = new Paint(); 12190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextLevelPaint.setAntiAlias(false); 12290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextLevelPaint.setARGB(192, 255, 0, 0); 12390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint = new Paint(); 12490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setAntiAlias(true); 12590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setARGB(255, 255, 255, 255); 12690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStyle(Paint.Style.STROKE); 12790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStrokeWidth(2); 12890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTargetPaint = new Paint(); 12990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTargetPaint.setAntiAlias(false); 13090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTargetPaint.setARGB(255, 0, 0, 192); 13190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPathPaint = new Paint(); 13290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPathPaint.setAntiAlias(false); 13390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPathPaint.setARGB(255, 0, 96, 255); 13490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStyle(Paint.Style.STROKE); 13590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPaint.setStrokeWidth(1); 13690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 13790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn PointerState ps = new PointerState(); 13890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPointers.add(ps); 139d1e0c371a651f024b3de62a686c56e369e3f361eJeff Brown mActivePointerId = 0; 1409e2ad36be87f2703b3d737189944d82f93bd4f27Jeff Brown 1419e2ad36be87f2703b3d737189944d82f93bd4f27Jeff Brown mVelocity = VelocityTracker.obtain(); 1428d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 1438d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown logInputDeviceCapabilities(); 1448d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 1458d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 1468d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private void logInputDeviceCapabilities() { 1478d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown int[] deviceIds = InputDevice.getDeviceIds(); 1488d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown for (int i = 0; i < deviceIds.length; i++) { 1498d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown InputDevice device = InputDevice.getDevice(deviceIds[i]); 1508d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown if (device != null) { 1518d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown Log.i(TAG, device.toString()); 1528d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 1538d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 15490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 15590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 15690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public void setPrintCoords(boolean state) { 15790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mPrintCoords = state; 15890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 15990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 16090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn @Override 16190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 16290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn super.onMeasure(widthMeasureSpec, heightMeasureSpec); 16390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mTextPaint.getFontMetricsInt(mTextMetrics); 16490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn mHeaderBottom = -mTextMetrics.ascent+mTextMetrics.descent+2; 16590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (false) { 16690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn Log.i("foo", "Metrics: ascent=" + mTextMetrics.ascent 16790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " descent=" + mTextMetrics.descent 16890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " leading=" + mTextMetrics.leading 16990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " top=" + mTextMetrics.top 17090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn + " bottom=" + mTextMetrics.bottom); 17190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 17290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 1738d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 1748d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown // Draw an oval. When angle is 0 radians, orients the major axis vertically, 1758d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown // angles less than or greater than 0 radians rotate the major axis left or right. 1768d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private RectF mReusableOvalRect = new RectF(); 1778d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private void drawOval(Canvas canvas, float x, float y, float major, float minor, 1788d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown float angle, Paint paint) { 1798d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown canvas.save(Canvas.MATRIX_SAVE_FLAG); 1805068ad8d2396d6d7bfbdb1c2c3fe57104744f1f9Jeff Brown canvas.rotate((float) (angle * 180 / Math.PI), x, y); 1818d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mReusableOvalRect.left = x - minor / 2; 1828d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mReusableOvalRect.right = x + minor / 2; 1838d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mReusableOvalRect.top = y - major / 2; 1848d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mReusableOvalRect.bottom = y + major / 2; 1858d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown canvas.drawOval(mReusableOvalRect, paint); 1868d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown canvas.restore(); 1878d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 18890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 18990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn @Override 19090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn protected void onDraw(Canvas canvas) { 19170825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int w = getWidth(); 19270825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int itemW = w/7; 19370825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int base = -mTextMetrics.ascent+1; 19470825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int bottom = mHeaderBottom; 19570825161b5bf51ed48319e142751a9c88b104994Jeff Brown 19670825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int NP = mPointers.size(); 19770825161b5bf51ed48319e142751a9c88b104994Jeff Brown 19870825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Labels 19970825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (mActivePointerId >= 0) { 20070825161b5bf51ed48319e142751a9c88b104994Jeff Brown final PointerState ps = mPointers.get(mActivePointerId); 20190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 20270825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(0, 0, itemW-1, bottom,mTextBackgroundPaint); 20370825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawText(mText.clear() 20470825161b5bf51ed48319e142751a9c88b104994Jeff Brown .append("P: ").append(mCurNumPointers) 20570825161b5bf51ed48319e142751a9c88b104994Jeff Brown .append(" / ").append(mMaxNumPointers) 20670825161b5bf51ed48319e142751a9c88b104994Jeff Brown .toString(), 1, base, mTextPaint); 20770825161b5bf51ed48319e142751a9c88b104994Jeff Brown 20870825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int N = ps.mTraceCount; 20970825161b5bf51ed48319e142751a9c88b104994Jeff Brown if ((mCurDown && ps.mCurDown) || N == 0) { 21070825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, mTextBackgroundPaint); 2118d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown canvas.drawText(mText.clear() 21270825161b5bf51ed48319e142751a9c88b104994Jeff Brown .append("X: ").append(ps.mCoords.x, 1) 21370825161b5bf51ed48319e142751a9c88b104994Jeff Brown .toString(), 1 + itemW, base, mTextPaint); 21470825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, mTextBackgroundPaint); 2158d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown canvas.drawText(mText.clear() 21670825161b5bf51ed48319e142751a9c88b104994Jeff Brown .append("Y: ").append(ps.mCoords.y, 1) 21770825161b5bf51ed48319e142751a9c88b104994Jeff Brown .toString(), 1 + itemW * 2, base, mTextPaint); 21870825161b5bf51ed48319e142751a9c88b104994Jeff Brown } else { 21970825161b5bf51ed48319e142751a9c88b104994Jeff Brown float dx = ps.mTraceX[N - 1] - ps.mTraceX[0]; 22070825161b5bf51ed48319e142751a9c88b104994Jeff Brown float dy = ps.mTraceY[N - 1] - ps.mTraceY[0]; 22170825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, 22270825161b5bf51ed48319e142751a9c88b104994Jeff Brown Math.abs(dx) < mVC.getScaledTouchSlop() 22370825161b5bf51ed48319e142751a9c88b104994Jeff Brown ? mTextBackgroundPaint : mTextLevelPaint); 2248d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown canvas.drawText(mText.clear() 22570825161b5bf51ed48319e142751a9c88b104994Jeff Brown .append("dX: ").append(dx, 1) 22670825161b5bf51ed48319e142751a9c88b104994Jeff Brown .toString(), 1 + itemW, base, mTextPaint); 22770825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, 22870825161b5bf51ed48319e142751a9c88b104994Jeff Brown Math.abs(dy) < mVC.getScaledTouchSlop() 22970825161b5bf51ed48319e142751a9c88b104994Jeff Brown ? mTextBackgroundPaint : mTextLevelPaint); 2308d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown canvas.drawText(mText.clear() 23170825161b5bf51ed48319e142751a9c88b104994Jeff Brown .append("dY: ").append(dy, 1) 23270825161b5bf51ed48319e142751a9c88b104994Jeff Brown .toString(), 1 + itemW * 2, base, mTextPaint); 23390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 23470825161b5bf51ed48319e142751a9c88b104994Jeff Brown 23570825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(itemW * 3, 0, (itemW * 4) - 1, bottom, mTextBackgroundPaint); 23670825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawText(mText.clear() 23770825161b5bf51ed48319e142751a9c88b104994Jeff Brown .append("Xv: ").append(ps.mXVelocity, 3) 23870825161b5bf51ed48319e142751a9c88b104994Jeff Brown .toString(), 1 + itemW * 3, base, mTextPaint); 23970825161b5bf51ed48319e142751a9c88b104994Jeff Brown 24070825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(itemW * 4, 0, (itemW * 5) - 1, bottom, mTextBackgroundPaint); 24170825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawText(mText.clear() 24270825161b5bf51ed48319e142751a9c88b104994Jeff Brown .append("Yv: ").append(ps.mYVelocity, 3) 24370825161b5bf51ed48319e142751a9c88b104994Jeff Brown .toString(), 1 + itemW * 4, base, mTextPaint); 24470825161b5bf51ed48319e142751a9c88b104994Jeff Brown 24570825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(itemW * 5, 0, (itemW * 6) - 1, bottom, mTextBackgroundPaint); 24670825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(itemW * 5, 0, (itemW * 5) + (ps.mCoords.pressure * itemW) - 1, 24770825161b5bf51ed48319e142751a9c88b104994Jeff Brown bottom, mTextLevelPaint); 24870825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawText(mText.clear() 24970825161b5bf51ed48319e142751a9c88b104994Jeff Brown .append("Prs: ").append(ps.mCoords.pressure, 2) 25070825161b5bf51ed48319e142751a9c88b104994Jeff Brown .toString(), 1 + itemW * 5, base, mTextPaint); 25170825161b5bf51ed48319e142751a9c88b104994Jeff Brown 25270825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(itemW * 6, 0, w, bottom, mTextBackgroundPaint); 25370825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawRect(itemW * 6, 0, (itemW * 6) + (ps.mCoords.size * itemW) - 1, 25470825161b5bf51ed48319e142751a9c88b104994Jeff Brown bottom, mTextLevelPaint); 25570825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawText(mText.clear() 25670825161b5bf51ed48319e142751a9c88b104994Jeff Brown .append("Size: ").append(ps.mCoords.size, 2) 25770825161b5bf51ed48319e142751a9c88b104994Jeff Brown .toString(), 1 + itemW * 6, base, mTextPaint); 25870825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 25970825161b5bf51ed48319e142751a9c88b104994Jeff Brown 26070825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Pointer trace. 26170825161b5bf51ed48319e142751a9c88b104994Jeff Brown for (int p = 0; p < NP; p++) { 26270825161b5bf51ed48319e142751a9c88b104994Jeff Brown final PointerState ps = mPointers.get(p); 26370825161b5bf51ed48319e142751a9c88b104994Jeff Brown 26470825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Draw path. 26570825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int N = ps.mTraceCount; 26670825161b5bf51ed48319e142751a9c88b104994Jeff Brown float lastX = 0, lastY = 0; 26770825161b5bf51ed48319e142751a9c88b104994Jeff Brown boolean haveLast = false; 26870825161b5bf51ed48319e142751a9c88b104994Jeff Brown boolean drawn = false; 26970825161b5bf51ed48319e142751a9c88b104994Jeff Brown mPaint.setARGB(255, 128, 255, 255); 27070825161b5bf51ed48319e142751a9c88b104994Jeff Brown for (int i=0; i < N; i++) { 27170825161b5bf51ed48319e142751a9c88b104994Jeff Brown float x = ps.mTraceX[i]; 27270825161b5bf51ed48319e142751a9c88b104994Jeff Brown float y = ps.mTraceY[i]; 27370825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (Float.isNaN(x)) { 27470825161b5bf51ed48319e142751a9c88b104994Jeff Brown haveLast = false; 27570825161b5bf51ed48319e142751a9c88b104994Jeff Brown continue; 27690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 27770825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (haveLast) { 27870825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawLine(lastX, lastY, x, y, mPathPaint); 27970825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawPoint(lastX, lastY, mPaint); 28070825161b5bf51ed48319e142751a9c88b104994Jeff Brown drawn = true; 2818d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 28270825161b5bf51ed48319e142751a9c88b104994Jeff Brown lastX = x; 28370825161b5bf51ed48319e142751a9c88b104994Jeff Brown lastY = y; 28470825161b5bf51ed48319e142751a9c88b104994Jeff Brown haveLast = true; 28570825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 28670825161b5bf51ed48319e142751a9c88b104994Jeff Brown 28770825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (drawn) { 28870825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Draw movement estimate curve. 28970825161b5bf51ed48319e142751a9c88b104994Jeff Brown mPaint.setARGB(128, 128, 0, 128); 29070825161b5bf51ed48319e142751a9c88b104994Jeff Brown float lx = ps.mEstimator.estimateX(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL); 29170825161b5bf51ed48319e142751a9c88b104994Jeff Brown float ly = ps.mEstimator.estimateY(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL); 29270825161b5bf51ed48319e142751a9c88b104994Jeff Brown for (int i = -ESTIMATE_PAST_POINTS + 1; i <= ESTIMATE_FUTURE_POINTS; i++) { 29370825161b5bf51ed48319e142751a9c88b104994Jeff Brown float x = ps.mEstimator.estimateX(i * ESTIMATE_INTERVAL); 29470825161b5bf51ed48319e142751a9c88b104994Jeff Brown float y = ps.mEstimator.estimateY(i * ESTIMATE_INTERVAL); 29570825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawLine(lx, ly, x, y, mPaint); 29670825161b5bf51ed48319e142751a9c88b104994Jeff Brown lx = x; 29770825161b5bf51ed48319e142751a9c88b104994Jeff Brown ly = y; 29870825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 29970825161b5bf51ed48319e142751a9c88b104994Jeff Brown 30070825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Draw velocity vector. 30170825161b5bf51ed48319e142751a9c88b104994Jeff Brown mPaint.setARGB(255, 255, 64, 128); 30270825161b5bf51ed48319e142751a9c88b104994Jeff Brown float xVel = ps.mXVelocity * (1000 / 60); 30370825161b5bf51ed48319e142751a9c88b104994Jeff Brown float yVel = ps.mYVelocity * (1000 / 60); 30470825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawLine(lastX, lastY, lastX + xVel, lastY + yVel, mPaint); 30570825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 30670825161b5bf51ed48319e142751a9c88b104994Jeff Brown 30770825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (mCurDown && ps.mCurDown) { 30870825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Draw crosshairs. 30970825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawLine(0, ps.mCoords.y, getWidth(), ps.mCoords.y, mTargetPaint); 31070825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawLine(ps.mCoords.x, 0, ps.mCoords.x, getHeight(), mTargetPaint); 31170825161b5bf51ed48319e142751a9c88b104994Jeff Brown 31270825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Draw current point. 31370825161b5bf51ed48319e142751a9c88b104994Jeff Brown int pressureLevel = (int)(ps.mCoords.pressure * 255); 31470825161b5bf51ed48319e142751a9c88b104994Jeff Brown mPaint.setARGB(255, pressureLevel, 255, 255 - pressureLevel); 31570825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawPoint(ps.mCoords.x, ps.mCoords.y, mPaint); 31670825161b5bf51ed48319e142751a9c88b104994Jeff Brown 31770825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Draw current touch ellipse. 31870825161b5bf51ed48319e142751a9c88b104994Jeff Brown mPaint.setARGB(255, pressureLevel, 255 - pressureLevel, 128); 31970825161b5bf51ed48319e142751a9c88b104994Jeff Brown drawOval(canvas, ps.mCoords.x, ps.mCoords.y, ps.mCoords.touchMajor, 32070825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.touchMinor, ps.mCoords.orientation, mPaint); 32170825161b5bf51ed48319e142751a9c88b104994Jeff Brown 32270825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Draw current tool ellipse. 32370825161b5bf51ed48319e142751a9c88b104994Jeff Brown mPaint.setARGB(255, pressureLevel, 128, 255 - pressureLevel); 32470825161b5bf51ed48319e142751a9c88b104994Jeff Brown drawOval(canvas, ps.mCoords.x, ps.mCoords.y, ps.mCoords.toolMajor, 32570825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.toolMinor, ps.mCoords.orientation, mPaint); 32670825161b5bf51ed48319e142751a9c88b104994Jeff Brown 32770825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Draw the orientation arrow. 32870825161b5bf51ed48319e142751a9c88b104994Jeff Brown float arrowSize = ps.mCoords.toolMajor * 0.7f; 32970825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (arrowSize < 20) { 33070825161b5bf51ed48319e142751a9c88b104994Jeff Brown arrowSize = 20; 33170825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 33270825161b5bf51ed48319e142751a9c88b104994Jeff Brown mPaint.setARGB(255, pressureLevel, 255, 0); 33370825161b5bf51ed48319e142751a9c88b104994Jeff Brown float orientationVectorX = (float) (Math.sin(ps.mCoords.orientation) 33470825161b5bf51ed48319e142751a9c88b104994Jeff Brown * arrowSize); 33570825161b5bf51ed48319e142751a9c88b104994Jeff Brown float orientationVectorY = (float) (-Math.cos(ps.mCoords.orientation) 33670825161b5bf51ed48319e142751a9c88b104994Jeff Brown * arrowSize); 33770825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (ps.mToolType == MotionEvent.TOOL_TYPE_STYLUS 33870825161b5bf51ed48319e142751a9c88b104994Jeff Brown || ps.mToolType == MotionEvent.TOOL_TYPE_ERASER) { 33970825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Show full circle orientation. 34070825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawLine(ps.mCoords.x, ps.mCoords.y, 34170825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.x + orientationVectorX, 34270825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.y + orientationVectorY, 34370825161b5bf51ed48319e142751a9c88b104994Jeff Brown mPaint); 34470825161b5bf51ed48319e142751a9c88b104994Jeff Brown } else { 34570825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Show half circle orientation. 34670825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawLine( 34770825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.x - orientationVectorX, 34870825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.y - orientationVectorY, 34970825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.x + orientationVectorX, 35070825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.y + orientationVectorY, 35170825161b5bf51ed48319e142751a9c88b104994Jeff Brown mPaint); 35290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 35370825161b5bf51ed48319e142751a9c88b104994Jeff Brown 35470825161b5bf51ed48319e142751a9c88b104994Jeff Brown // Draw the tilt point along the orientation arrow. 35570825161b5bf51ed48319e142751a9c88b104994Jeff Brown float tiltScale = (float) Math.sin( 35670825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.getAxisValue(MotionEvent.AXIS_TILT)); 35770825161b5bf51ed48319e142751a9c88b104994Jeff Brown canvas.drawCircle( 35870825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.x + orientationVectorX * tiltScale, 35970825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCoords.y + orientationVectorY * tiltScale, 36070825161b5bf51ed48319e142751a9c88b104994Jeff Brown 3.0f, mPaint); 36190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 36290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 36390d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 36465fd251c3913fc921468a3dad190810db19eb9dfJeff Brown 36565fd251c3913fc921468a3dad190810db19eb9dfJeff Brown private void logMotionEvent(String type, MotionEvent event) { 36665fd251c3913fc921468a3dad190810db19eb9dfJeff Brown final int action = event.getAction(); 36765fd251c3913fc921468a3dad190810db19eb9dfJeff Brown final int N = event.getHistorySize(); 36865fd251c3913fc921468a3dad190810db19eb9dfJeff Brown final int NI = event.getPointerCount(); 36965fd251c3913fc921468a3dad190810db19eb9dfJeff Brown for (int historyPos = 0; historyPos < N; historyPos++) { 37065fd251c3913fc921468a3dad190810db19eb9dfJeff Brown for (int i = 0; i < NI; i++) { 37165fd251c3913fc921468a3dad190810db19eb9dfJeff Brown final int id = event.getPointerId(i); 37265fd251c3913fc921468a3dad190810db19eb9dfJeff Brown event.getHistoricalPointerCoords(i, historyPos, mTempCoords); 37365fd251c3913fc921468a3dad190810db19eb9dfJeff Brown logCoords(type, action, i, mTempCoords, id, 37465fd251c3913fc921468a3dad190810db19eb9dfJeff Brown event.getToolType(i), event.getButtonState()); 37565fd251c3913fc921468a3dad190810db19eb9dfJeff Brown } 37665fd251c3913fc921468a3dad190810db19eb9dfJeff Brown } 37765fd251c3913fc921468a3dad190810db19eb9dfJeff Brown for (int i = 0; i < NI; i++) { 37865fd251c3913fc921468a3dad190810db19eb9dfJeff Brown final int id = event.getPointerId(i); 37965fd251c3913fc921468a3dad190810db19eb9dfJeff Brown event.getPointerCoords(i, mTempCoords); 38065fd251c3913fc921468a3dad190810db19eb9dfJeff Brown logCoords(type, action, i, mTempCoords, id, 38165fd251c3913fc921468a3dad190810db19eb9dfJeff Brown event.getToolType(i), event.getButtonState()); 38265fd251c3913fc921468a3dad190810db19eb9dfJeff Brown } 38365fd251c3913fc921468a3dad190810db19eb9dfJeff Brown } 38465fd251c3913fc921468a3dad190810db19eb9dfJeff Brown 38565fd251c3913fc921468a3dad190810db19eb9dfJeff Brown private void logCoords(String type, int action, int index, 38665fd251c3913fc921468a3dad190810db19eb9dfJeff Brown MotionEvent.PointerCoords coords, int id, int toolType, int buttonState) { 38733bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown final String prefix; 38833bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown switch (action & MotionEvent.ACTION_MASK) { 38933bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown case MotionEvent.ACTION_DOWN: 39033bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "DOWN"; 39133bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown break; 39233bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown case MotionEvent.ACTION_UP: 39333bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "UP"; 39433bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown break; 39533bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown case MotionEvent.ACTION_MOVE: 39633bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "MOVE"; 39733bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown break; 39833bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown case MotionEvent.ACTION_CANCEL: 39933bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "CANCEL"; 40033bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown break; 40133bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown case MotionEvent.ACTION_OUTSIDE: 40233bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "OUTSIDE"; 40333bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown break; 40433bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown case MotionEvent.ACTION_POINTER_DOWN: 40533bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown if (index == ((action & MotionEvent.ACTION_POINTER_INDEX_MASK) 40633bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown >> MotionEvent.ACTION_POINTER_INDEX_SHIFT)) { 40733bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "DOWN"; 40833bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown } else { 40933bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "MOVE"; 41033bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown } 41133bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown break; 41233bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown case MotionEvent.ACTION_POINTER_UP: 41333bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown if (index == ((action & MotionEvent.ACTION_POINTER_INDEX_MASK) 41433bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown >> MotionEvent.ACTION_POINTER_INDEX_SHIFT)) { 41533bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "UP"; 41633bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown } else { 41733bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "MOVE"; 41833bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown } 41933bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown break; 42033bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown case MotionEvent.ACTION_HOVER_MOVE: 42133bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "HOVER MOVE"; 42233bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown break; 423a032cc008618b83ecbbede537517d1e7998e3264Jeff Brown case MotionEvent.ACTION_HOVER_ENTER: 424a032cc008618b83ecbbede537517d1e7998e3264Jeff Brown prefix = "HOVER ENTER"; 425a032cc008618b83ecbbede537517d1e7998e3264Jeff Brown break; 426a032cc008618b83ecbbede537517d1e7998e3264Jeff Brown case MotionEvent.ACTION_HOVER_EXIT: 427a032cc008618b83ecbbede537517d1e7998e3264Jeff Brown prefix = "HOVER EXIT"; 428a032cc008618b83ecbbede537517d1e7998e3264Jeff Brown break; 42933bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown case MotionEvent.ACTION_SCROLL: 43033bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = "SCROLL"; 43133bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown break; 43233bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown default: 43333bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown prefix = Integer.toString(action); 43433bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown break; 43533bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown } 43633bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown 4378d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown Log.i(TAG, mText.clear() 43865fd251c3913fc921468a3dad190810db19eb9dfJeff Brown .append(type).append(" id ").append(id + 1) 43933bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown .append(": ") 44033bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown .append(prefix) 44133bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown .append(" (").append(coords.x, 3).append(", ").append(coords.y, 3) 4428d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown .append(") Pressure=").append(coords.pressure, 3) 4438d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown .append(" Size=").append(coords.size, 3) 4448d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown .append(" TouchMajor=").append(coords.touchMajor, 3) 4458d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown .append(" TouchMinor=").append(coords.touchMinor, 3) 4468d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown .append(" ToolMajor=").append(coords.toolMajor, 3) 4478d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown .append(" ToolMinor=").append(coords.toolMinor, 3) 4488d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown .append(" Orientation=").append((float)(coords.orientation * 180 / Math.PI), 1) 4496f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown .append("deg") 45065fd251c3913fc921468a3dad190810db19eb9dfJeff Brown .append(" Tilt=").append((float)( 45165fd251c3913fc921468a3dad190810db19eb9dfJeff Brown coords.getAxisValue(MotionEvent.AXIS_TILT) * 180 / Math.PI), 1) 45265fd251c3913fc921468a3dad190810db19eb9dfJeff Brown .append("deg") 45380fd47ce75253dcdc2cfa85d7a3f42634b923a47Jeff Brown .append(" Distance=").append(coords.getAxisValue(MotionEvent.AXIS_DISTANCE), 1) 4546f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown .append(" VScroll=").append(coords.getAxisValue(MotionEvent.AXIS_VSCROLL), 1) 4556f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown .append(" HScroll=").append(coords.getAxisValue(MotionEvent.AXIS_HSCROLL), 1) 456fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown .append(" ToolType=").append(MotionEvent.toolTypeToString(toolType)) 457fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown .append(" ButtonState=").append(MotionEvent.buttonStateToString(buttonState)) 4586f2fba428ca5e77a26d991ad728e346cc47609eeJeff Brown .toString()); 4598d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 46090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 46133bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown public void addPointerEvent(MotionEvent event) { 46270825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int action = event.getAction(); 46370825161b5bf51ed48319e142751a9c88b104994Jeff Brown int NP = mPointers.size(); 46433bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown 46570825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (action == MotionEvent.ACTION_DOWN 46670825161b5bf51ed48319e142751a9c88b104994Jeff Brown || (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) { 46770825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) 46870825161b5bf51ed48319e142751a9c88b104994Jeff Brown >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; // will be 0 for down 46970825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (action == MotionEvent.ACTION_DOWN) { 47070825161b5bf51ed48319e142751a9c88b104994Jeff Brown for (int p=0; p<NP; p++) { 47170825161b5bf51ed48319e142751a9c88b104994Jeff Brown final PointerState ps = mPointers.get(p); 47270825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.clearTrace(); 47370825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCurDown = false; 47433bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown } 47570825161b5bf51ed48319e142751a9c88b104994Jeff Brown mCurDown = true; 47670825161b5bf51ed48319e142751a9c88b104994Jeff Brown mCurNumPointers = 0; 47770825161b5bf51ed48319e142751a9c88b104994Jeff Brown mMaxNumPointers = 0; 47870825161b5bf51ed48319e142751a9c88b104994Jeff Brown mVelocity.clear(); 47970825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 48033bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown 48170825161b5bf51ed48319e142751a9c88b104994Jeff Brown mCurNumPointers += 1; 48270825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (mMaxNumPointers < mCurNumPointers) { 48370825161b5bf51ed48319e142751a9c88b104994Jeff Brown mMaxNumPointers = mCurNumPointers; 48490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 485cc0c159e9b3dd4e0f48da0ce3e33d2c68a651413Jeff Brown 48670825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int id = event.getPointerId(index); 48770825161b5bf51ed48319e142751a9c88b104994Jeff Brown while (NP <= id) { 48870825161b5bf51ed48319e142751a9c88b104994Jeff Brown PointerState ps = new PointerState(); 48970825161b5bf51ed48319e142751a9c88b104994Jeff Brown mPointers.add(ps); 49070825161b5bf51ed48319e142751a9c88b104994Jeff Brown NP++; 49170825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 49270825161b5bf51ed48319e142751a9c88b104994Jeff Brown 49370825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (mActivePointerId < 0 || 49470825161b5bf51ed48319e142751a9c88b104994Jeff Brown !mPointers.get(mActivePointerId).mCurDown) { 49570825161b5bf51ed48319e142751a9c88b104994Jeff Brown mActivePointerId = id; 49633bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown } 49770825161b5bf51ed48319e142751a9c88b104994Jeff Brown 49870825161b5bf51ed48319e142751a9c88b104994Jeff Brown final PointerState ps = mPointers.get(id); 49970825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCurDown = true; 50070825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 50170825161b5bf51ed48319e142751a9c88b104994Jeff Brown 50270825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int NI = event.getPointerCount(); 50370825161b5bf51ed48319e142751a9c88b104994Jeff Brown 50470825161b5bf51ed48319e142751a9c88b104994Jeff Brown mVelocity.addMovement(event); 50570825161b5bf51ed48319e142751a9c88b104994Jeff Brown mVelocity.computeCurrentVelocity(1); 50670825161b5bf51ed48319e142751a9c88b104994Jeff Brown 50770825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int N = event.getHistorySize(); 50870825161b5bf51ed48319e142751a9c88b104994Jeff Brown for (int historyPos = 0; historyPos < N; historyPos++) { 50933bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown for (int i = 0; i < NI; i++) { 51033bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown final int id = event.getPointerId(i); 51133bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown final PointerState ps = mCurDown ? mPointers.get(id) : null; 51265fd251c3913fc921468a3dad190810db19eb9dfJeff Brown final PointerCoords coords = ps != null ? ps.mCoords : mTempCoords; 51370825161b5bf51ed48319e142751a9c88b104994Jeff Brown event.getHistoricalPointerCoords(i, historyPos, coords); 51490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn if (mPrintCoords) { 51565fd251c3913fc921468a3dad190810db19eb9dfJeff Brown logCoords("Pointer", action, i, coords, id, 516fe9f8ab03a63b1037f07dd85799fbea80ec6adaaJeff Brown event.getToolType(i), event.getButtonState()); 517cc0c159e9b3dd4e0f48da0ce3e33d2c68a651413Jeff Brown } 518cc0c159e9b3dd4e0f48da0ce3e33d2c68a651413Jeff Brown if (ps != null) { 519cc0c159e9b3dd4e0f48da0ce3e33d2c68a651413Jeff Brown ps.addTrace(coords.x, coords.y); 52090d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 52190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 52270825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 52370825161b5bf51ed48319e142751a9c88b104994Jeff Brown for (int i = 0; i < NI; i++) { 52470825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int id = event.getPointerId(i); 52570825161b5bf51ed48319e142751a9c88b104994Jeff Brown final PointerState ps = mCurDown ? mPointers.get(id) : null; 52670825161b5bf51ed48319e142751a9c88b104994Jeff Brown final PointerCoords coords = ps != null ? ps.mCoords : mTempCoords; 52770825161b5bf51ed48319e142751a9c88b104994Jeff Brown event.getPointerCoords(i, coords); 52870825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (mPrintCoords) { 52970825161b5bf51ed48319e142751a9c88b104994Jeff Brown logCoords("Pointer", action, i, coords, id, 53070825161b5bf51ed48319e142751a9c88b104994Jeff Brown event.getToolType(i), event.getButtonState()); 53170825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 53270825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (ps != null) { 53370825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.addTrace(coords.x, coords.y); 53470825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mXVelocity = mVelocity.getXVelocity(id); 53570825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mYVelocity = mVelocity.getYVelocity(id); 53670825161b5bf51ed48319e142751a9c88b104994Jeff Brown mVelocity.getEstimator(id, -1, -1, ps.mEstimator); 53770825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mToolType = event.getToolType(i); 53870825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 53970825161b5bf51ed48319e142751a9c88b104994Jeff Brown } 54070825161b5bf51ed48319e142751a9c88b104994Jeff Brown 54170825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (action == MotionEvent.ACTION_UP 54270825161b5bf51ed48319e142751a9c88b104994Jeff Brown || action == MotionEvent.ACTION_CANCEL 54370825161b5bf51ed48319e142751a9c88b104994Jeff Brown || (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) { 54470825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int index = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) 54570825161b5bf51ed48319e142751a9c88b104994Jeff Brown >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; // will be 0 for UP 54670825161b5bf51ed48319e142751a9c88b104994Jeff Brown 54770825161b5bf51ed48319e142751a9c88b104994Jeff Brown final int id = event.getPointerId(index); 54870825161b5bf51ed48319e142751a9c88b104994Jeff Brown final PointerState ps = mPointers.get(id); 54970825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.mCurDown = false; 55033bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown 5518d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown if (action == MotionEvent.ACTION_UP 55270825161b5bf51ed48319e142751a9c88b104994Jeff Brown || action == MotionEvent.ACTION_CANCEL) { 55370825161b5bf51ed48319e142751a9c88b104994Jeff Brown mCurDown = false; 55470825161b5bf51ed48319e142751a9c88b104994Jeff Brown mCurNumPointers = 0; 55570825161b5bf51ed48319e142751a9c88b104994Jeff Brown } else { 55670825161b5bf51ed48319e142751a9c88b104994Jeff Brown mCurNumPointers -= 1; 55770825161b5bf51ed48319e142751a9c88b104994Jeff Brown if (mActivePointerId == id) { 55870825161b5bf51ed48319e142751a9c88b104994Jeff Brown mActivePointerId = event.getPointerId(index == 0 ? 1 : 0); 55990d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 56070825161b5bf51ed48319e142751a9c88b104994Jeff Brown ps.addTrace(Float.NaN, Float.NaN); 56190d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 56290d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 56370825161b5bf51ed48319e142751a9c88b104994Jeff Brown 56470825161b5bf51ed48319e142751a9c88b104994Jeff Brown invalidate(); 56590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 56690d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn 56790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn @Override 56890d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn public boolean onTouchEvent(MotionEvent event) { 56933bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown addPointerEvent(event); 570c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown 571c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown if (event.getAction() == MotionEvent.ACTION_DOWN && !isFocused()) { 572c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown requestFocus(); 573c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } 57490d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn return true; 57590d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn } 5767d9af5ae762c59e879a86e77dcb330856774bc09Dianne Hackborn 5777d9af5ae762c59e879a86e77dcb330856774bc09Dianne Hackborn @Override 57833bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown public boolean onGenericMotionEvent(MotionEvent event) { 579c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown final int source = event.getSource(); 580c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) { 58133bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown addPointerEvent(event); 582c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } else if ((source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { 58365fd251c3913fc921468a3dad190810db19eb9dfJeff Brown logMotionEvent("Joystick", event); 584c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } else if ((source & InputDevice.SOURCE_CLASS_POSITION) != 0) { 58565fd251c3913fc921468a3dad190810db19eb9dfJeff Brown logMotionEvent("Position", event); 586c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } else { 58765fd251c3913fc921468a3dad190810db19eb9dfJeff Brown logMotionEvent("Generic", event); 588c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } 589c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown return true; 590c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } 591c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown 592c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown @Override 593c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown public boolean onKeyDown(int keyCode, KeyEvent event) { 594c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown if (shouldLogKey(keyCode)) { 595c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown final int repeatCount = event.getRepeatCount(); 596c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown if (repeatCount == 0) { 597c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown Log.i(TAG, "Key Down: " + event); 598c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } else { 599c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown Log.i(TAG, "Key Repeat #" + repeatCount + ": " + event); 600c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } 60133bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown return true; 60233bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown } 603c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown return super.onKeyDown(keyCode, event); 604c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } 605c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown 606c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown @Override 607c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown public boolean onKeyUp(int keyCode, KeyEvent event) { 608c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown if (shouldLogKey(keyCode)) { 609c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown Log.i(TAG, "Key Up: " + event); 610c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown return true; 611c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } 612c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown return super.onKeyUp(keyCode, event); 613c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } 614c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown 615c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown private static boolean shouldLogKey(int keyCode) { 616c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown switch (keyCode) { 617c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown case KeyEvent.KEYCODE_DPAD_UP: 618c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown case KeyEvent.KEYCODE_DPAD_DOWN: 619c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown case KeyEvent.KEYCODE_DPAD_LEFT: 620c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown case KeyEvent.KEYCODE_DPAD_RIGHT: 621c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown case KeyEvent.KEYCODE_DPAD_CENTER: 622c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown return true; 623c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown default: 624c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown return KeyEvent.isGamepadButton(keyCode) 625c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown || KeyEvent.isModifierKey(keyCode); 626c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown } 62733bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown } 62833bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown 62933bbfd2232ea9eaae9a9d87a05a95a430f09bd83Jeff Brown @Override 6307d9af5ae762c59e879a86e77dcb330856774bc09Dianne Hackborn public boolean onTrackballEvent(MotionEvent event) { 63165fd251c3913fc921468a3dad190810db19eb9dfJeff Brown logMotionEvent("Trackball", event); 632c3fe7669d6276b43e82c802743a7e8974bae52a5Jeff Brown return true; 6337d9af5ae762c59e879a86e77dcb330856774bc09Dianne Hackborn } 6347d9af5ae762c59e879a86e77dcb330856774bc09Dianne Hackborn 6358d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown // HACK 6368d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown // A quick and dirty string builder implementation optimized for GC. 637d1e0c371a651f024b3de62a686c56e369e3f361eJeff Brown // Using String.format causes the application grind to a halt when 638d1e0c371a651f024b3de62a686c56e369e3f361eJeff Brown // more than a couple of pointers are down due to the number of 639d1e0c371a651f024b3de62a686c56e369e3f361eJeff Brown // temporary objects allocated while formatting strings for drawing or logging. 6408d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private static final class FasterStringBuilder { 6418d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private char[] mChars; 6428d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private int mLength; 6438d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 6448d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown public FasterStringBuilder() { 6458d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mChars = new char[64]; 6468d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 6478d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 6488d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown public FasterStringBuilder clear() { 6498d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mLength = 0; 6508d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown return this; 6518d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 6528d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 6538d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown public FasterStringBuilder append(String value) { 6548d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown final int valueLength = value.length(); 6558d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown final int index = reserve(valueLength); 6568d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown value.getChars(0, valueLength, mChars, index); 6578d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mLength += valueLength; 6588d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown return this; 6598d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 6608d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 6618d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown public FasterStringBuilder append(int value) { 6628d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown return append(value, 0); 6638d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 6648d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 6658d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown public FasterStringBuilder append(int value, int zeroPadWidth) { 6668d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown final boolean negative = value < 0; 6678d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown if (negative) { 6688d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown value = - value; 6698d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown if (value < 0) { 6708d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown append("-2147483648"); 6718d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown return this; 6728d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 6738d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 6748d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 6758d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown int index = reserve(11); 6768d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown final char[] chars = mChars; 6778d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 6788d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown if (value == 0) { 6798d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown chars[index++] = '0'; 6808d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mLength += 1; 6818d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown return this; 6828d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 6838d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 6848d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown if (negative) { 6858d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown chars[index++] = '-'; 6868d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 6878d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 6888d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown int divisor = 1000000000; 6898d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown int numberWidth = 10; 6908d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown while (value < divisor) { 6918d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown divisor /= 10; 6928d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown numberWidth -= 1; 6938d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown if (numberWidth < zeroPadWidth) { 6948d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown chars[index++] = '0'; 6958d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 6968d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 6978d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 6988d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown do { 6998d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown int digit = value / divisor; 7008d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown value -= digit * divisor; 7018d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown divisor /= 10; 7028d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown chars[index++] = (char) (digit + '0'); 7038d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } while (divisor != 0); 7048d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 7058d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mLength = index; 7068d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown return this; 7078d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 7088d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 7098d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown public FasterStringBuilder append(float value, int precision) { 7108d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown int scale = 1; 7118d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown for (int i = 0; i < precision; i++) { 7128d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown scale *= 10; 7138d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 7148d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown value = (float) (Math.rint(value * scale) / scale); 7158d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 7168d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown append((int) value); 7178d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 7188d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown if (precision != 0) { 7198d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown append("."); 7208d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown value = Math.abs(value); 7218d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown value -= Math.floor(value); 7228d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown append((int) (value * scale), precision); 7238d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 7248d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 7258d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown return this; 7268d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 7278d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 7288d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown @Override 7298d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown public String toString() { 7308d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown return new String(mChars, 0, mLength); 7318d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 7328d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown 7338d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown private int reserve(int length) { 7348d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown final int oldLength = mLength; 7358d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown final int newLength = mLength + length; 7368d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown final char[] oldChars = mChars; 7378d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown final int oldCapacity = oldChars.length; 7388d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown if (newLength > oldCapacity) { 7398d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown final int newCapacity = oldCapacity * 2; 7408d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown final char[] newChars = new char[newCapacity]; 7418d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown System.arraycopy(oldChars, 0, newChars, 0, oldLength); 7428d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown mChars = newChars; 7438d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 7448d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown return oldLength; 7458d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 7468d60866e2100db70ecf0502c14768a384514d7e9Jeff Brown } 74790d2db3d21d07c2a4b4cbbc558f5ec59d20098c3Dianne Hackborn} 748