Loading common/java/com/android/common/ui/PointerLocationView.java 0 → 100644 +333 −0 Original line number Diff line number Diff line package com.android.common.ui; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.FontMetricsInt; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import java.util.ArrayList; public class PointerLocationView extends View { public static class PointerState { private final ArrayList<Float> mXs = new ArrayList<Float>(); private final ArrayList<Float> mYs = new ArrayList<Float>(); private boolean mCurDown; private int mCurX; private int mCurY; private float mCurPressure; private float mCurSize; private int mCurWidth; private VelocityTracker mVelocity; } private final ViewConfiguration mVC; private final Paint mTextPaint; private final Paint mTextBackgroundPaint; private final Paint mTextLevelPaint; private final Paint mPaint; private final Paint mTargetPaint; private final Paint mPathPaint; private final FontMetricsInt mTextMetrics = new FontMetricsInt(); private int mHeaderBottom; private boolean mCurDown; private int mCurNumPointers; private int mMaxNumPointers; private final ArrayList<PointerState> mPointers = new ArrayList<PointerState>(); private boolean mPrintCoords = true; public PointerLocationView(Context c) { super(c); mVC = ViewConfiguration.get(c); mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize(10 * getResources().getDisplayMetrics().density); mTextPaint.setARGB(255, 0, 0, 0); mTextBackgroundPaint = new Paint(); mTextBackgroundPaint.setAntiAlias(false); mTextBackgroundPaint.setARGB(128, 255, 255, 255); mTextLevelPaint = new Paint(); mTextLevelPaint.setAntiAlias(false); mTextLevelPaint.setARGB(192, 255, 0, 0); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setARGB(255, 255, 255, 255); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(2); mTargetPaint = new Paint(); mTargetPaint.setAntiAlias(false); mTargetPaint.setARGB(255, 0, 0, 192); mPathPaint = new Paint(); mPathPaint.setAntiAlias(false); mPathPaint.setARGB(255, 0, 96, 255); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(1); PointerState ps = new PointerState(); ps.mVelocity = VelocityTracker.obtain(); mPointers.add(ps); } public void setPrintCoords(boolean state) { mPrintCoords = state; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mTextPaint.getFontMetricsInt(mTextMetrics); mHeaderBottom = -mTextMetrics.ascent+mTextMetrics.descent+2; if (false) { Log.i("foo", "Metrics: ascent=" + mTextMetrics.ascent + " descent=" + mTextMetrics.descent + " leading=" + mTextMetrics.leading + " top=" + mTextMetrics.top + " bottom=" + mTextMetrics.bottom); } } @Override protected void onDraw(Canvas canvas) { synchronized (mPointers) { final int w = getWidth(); final int itemW = w/7; final int base = -mTextMetrics.ascent+1; final int bottom = mHeaderBottom; final int NP = mPointers.size(); if (NP > 0) { final PointerState ps = mPointers.get(0); canvas.drawRect(0, 0, itemW-1, bottom,mTextBackgroundPaint); canvas.drawText("P: " + mCurNumPointers + " / " + mMaxNumPointers, 1, base, mTextPaint); final int N = ps.mXs.size(); if ((mCurDown && ps.mCurDown) || N == 0) { canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, mTextBackgroundPaint); canvas.drawText("X: " + ps.mCurX, 1 + itemW, base, mTextPaint); canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, mTextBackgroundPaint); canvas.drawText("Y: " + ps.mCurY, 1 + itemW * 2, base, mTextPaint); } else { float dx = ps.mXs.get(N-1) - ps.mXs.get(0); float dy = ps.mYs.get(N-1) - ps.mYs.get(0); canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, Math.abs(dx) < mVC.getScaledTouchSlop() ? mTextBackgroundPaint : mTextLevelPaint); canvas.drawText("dX: " + String.format("%.1f", dx), 1 + itemW, base, mTextPaint); canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, Math.abs(dy) < mVC.getScaledTouchSlop() ? mTextBackgroundPaint : mTextLevelPaint); canvas.drawText("dY: " + String.format("%.1f", dy), 1 + itemW * 2, base, mTextPaint); } canvas.drawRect(itemW * 3, 0, (itemW * 4) - 1, bottom, mTextBackgroundPaint); int velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getXVelocity() * 1000); canvas.drawText("Xv: " + velocity, 1 + itemW * 3, base, mTextPaint); canvas.drawRect(itemW * 4, 0, (itemW * 5) - 1, bottom, mTextBackgroundPaint); velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getYVelocity() * 1000); canvas.drawText("Yv: " + velocity, 1 + itemW * 4, base, mTextPaint); canvas.drawRect(itemW * 5, 0, (itemW * 6) - 1, bottom, mTextBackgroundPaint); canvas.drawRect(itemW * 5, 0, (itemW * 5) + (ps.mCurPressure * itemW) - 1, bottom, mTextLevelPaint); canvas.drawText("Prs: " + String.format("%.2f", ps.mCurPressure), 1 + itemW * 5, base, mTextPaint); canvas.drawRect(itemW * 6, 0, w, bottom, mTextBackgroundPaint); canvas.drawRect(itemW * 6, 0, (itemW * 6) + (ps.mCurSize * itemW) - 1, bottom, mTextLevelPaint); canvas.drawText("Size: " + String.format("%.2f", ps.mCurSize), 1 + itemW * 6, base, mTextPaint); } for (int p=0; p<NP; p++) { final PointerState ps = mPointers.get(p); if (mCurDown && ps.mCurDown) { canvas.drawLine(0, (int)ps.mCurY, getWidth(), (int)ps.mCurY, mTargetPaint); canvas.drawLine((int)ps.mCurX, 0, (int)ps.mCurX, getHeight(), mTargetPaint); int pressureLevel = (int)(ps.mCurPressure*255); mPaint.setARGB(255, pressureLevel, 128, 255-pressureLevel); canvas.drawPoint(ps.mCurX, ps.mCurY, mPaint); canvas.drawCircle(ps.mCurX, ps.mCurY, ps.mCurWidth, mPaint); } } for (int p=0; p<NP; p++) { final PointerState ps = mPointers.get(p); final int N = ps.mXs.size(); float lastX=0, lastY=0; boolean haveLast = false; boolean drawn = false; mPaint.setARGB(255, 128, 255, 255); for (int i=0; i<N; i++) { float x = ps.mXs.get(i); float y = ps.mYs.get(i); if (Float.isNaN(x)) { haveLast = false; continue; } if (haveLast) { canvas.drawLine(lastX, lastY, x, y, mPathPaint); canvas.drawPoint(lastX, lastY, mPaint); drawn = true; } lastX = x; lastY = y; haveLast = true; } if (drawn) { if (ps.mVelocity != null) { mPaint.setARGB(255, 255, 64, 128); float xVel = ps.mVelocity.getXVelocity() * (1000/60); float yVel = ps.mVelocity.getYVelocity() * (1000/60); canvas.drawLine(lastX, lastY, lastX+xVel, lastY+yVel, mPaint); } else { canvas.drawPoint(lastX, lastY, mPaint); } } } } } public void addTouchEvent(MotionEvent event) { synchronized (mPointers) { int action = event.getAction(); //Log.i("Pointer", "Motion: action=0x" + Integer.toHexString(action) // + " pointers=" + event.getPointerCount()); int NP = mPointers.size(); //mRect.set(0, 0, getWidth(), mHeaderBottom+1); //invalidate(mRect); //if (mCurDown) { // mRect.set(mCurX-mCurWidth-3, mCurY-mCurWidth-3, // mCurX+mCurWidth+3, mCurY+mCurWidth+3); //} else { // mRect.setEmpty(); //} if (action == MotionEvent.ACTION_DOWN) { for (int p=0; p<NP; p++) { final PointerState ps = mPointers.get(p); ps.mXs.clear(); ps.mYs.clear(); ps.mVelocity = VelocityTracker.obtain(); ps.mCurDown = false; } mPointers.get(0).mCurDown = true; mMaxNumPointers = 0; if (mPrintCoords) { Log.i("Pointer", "Pointer 1: DOWN"); } } if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) { final int id = (action&MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; while (NP <= id) { PointerState ps = new PointerState(); ps.mVelocity = VelocityTracker.obtain(); mPointers.add(ps); NP++; } final PointerState ps = mPointers.get(id); ps.mVelocity = VelocityTracker.obtain(); ps.mCurDown = true; if (mPrintCoords) { Log.i("Pointer", "Pointer " + (id+1) + ": DOWN"); } } final int NI = event.getPointerCount(); mCurDown = action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL; mCurNumPointers = mCurDown ? NI : 0; if (mMaxNumPointers < mCurNumPointers) { mMaxNumPointers = mCurNumPointers; } for (int i=0; i<NI; i++) { final PointerState ps = mPointers.get(event.getPointerId(i)); ps.mVelocity.addMovement(event); ps.mVelocity.computeCurrentVelocity(1); final int N = event.getHistorySize(); for (int j=0; j<N; j++) { if (mPrintCoords) { Log.i("Pointer", "Pointer " + (i+1) + ": (" + event.getHistoricalX(i, j) + ", " + event.getHistoricalY(i, j) + ")" + " Prs=" + event.getHistoricalPressure(i, j) + " Size=" + event.getHistoricalSize(i, j)); } ps.mXs.add(event.getHistoricalX(i, j)); ps.mYs.add(event.getHistoricalY(i, j)); } if (mPrintCoords) { Log.i("Pointer", "Pointer " + (i+1) + ": (" + event.getX(i) + ", " + event.getY(i) + ")" + " Prs=" + event.getPressure(i) + " Size=" + event.getSize(i)); } ps.mXs.add(event.getX(i)); ps.mYs.add(event.getY(i)); ps.mCurX = (int)event.getX(i); ps.mCurY = (int)event.getY(i); //Log.i("Pointer", "Pointer #" + p + ": (" + ps.mCurX // + "," + ps.mCurY + ")"); ps.mCurPressure = event.getPressure(i); ps.mCurSize = event.getSize(i); ps.mCurWidth = (int)(ps.mCurSize*(getWidth()/3)); } if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) { final int id = (action&MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; final PointerState ps = mPointers.get(id); ps.mXs.add(Float.NaN); ps.mYs.add(Float.NaN); ps.mCurDown = false; if (mPrintCoords) { Log.i("Pointer", "Pointer " + (id+1) + ": UP"); } } if (action == MotionEvent.ACTION_UP) { for (int i=0; i<NI; i++) { final PointerState ps = mPointers.get(event.getPointerId(i)); if (ps.mCurDown) { ps.mCurDown = false; if (mPrintCoords) { Log.i("Pointer", "Pointer " + (i+1) + ": UP"); } } } } //if (mCurDown) { // mRect.union(mCurX-mCurWidth-3, mCurY-mCurWidth-3, // mCurX+mCurWidth+3, mCurY+mCurWidth+3); //} //invalidate(mRect); postInvalidate(); } } @Override public boolean onTouchEvent(MotionEvent event) { addTouchEvent(event); return true; } } core/java/android/provider/Settings.java +8 −0 Original line number Diff line number Diff line Loading @@ -1488,6 +1488,14 @@ public final class Settings { */ public static final String DEFAULT_INSTALL_LOCATION = "default_install_location"; /** * Show pointer location on screen? * 0 = no * 1 = yes * @hide */ public static final String POINTER_LOCATION = "pointer_location"; /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. Loading core/java/android/view/WindowManagerPolicy.java +5 −0 Original line number Diff line number Diff line Loading @@ -851,6 +851,11 @@ public interface WindowManagerPolicy { */ public boolean isCheekPressedAgainstScreen(MotionEvent ev); /** * Called every time the window manager is dispatching a pointer event. */ public void dispatchedPointerEventLw(MotionEvent ev, int targetX, int targetY); public void setCurrentOrientationLw(int newOrientation); /** Loading services/java/com/android/server/WindowManagerService.java +31 −23 Original line number Diff line number Diff line Loading @@ -1773,6 +1773,32 @@ public class WindowManagerService extends IWindowManager.Stub } } void dispatchPointerElsewhereLocked(WindowState srcWin, WindowState relWin, MotionEvent pointer, long eventTime, boolean skipped) { if (relWin != null) { mPolicy.dispatchedPointerEventLw(pointer, relWin.mFrame.left, relWin.mFrame.top); } else { mPolicy.dispatchedPointerEventLw(pointer, 0, 0); } // If we sent an initial down to the wallpaper, then continue // sending events until the final up. if (mSendingPointersToWallpaper) { if (skipped) { Log.i(TAG, "Sending skipped pointer to wallpaper!"); } sendPointerToWallpaperLocked(relWin, pointer, eventTime); // If we are on top of the wallpaper, then the wallpaper also // gets to see this movement. } else if (srcWin != null && pointer.getAction() == MotionEvent.ACTION_DOWN && mWallpaperTarget == srcWin && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) { sendPointerToWallpaperLocked(relWin, pointer, eventTime); } } public int addWindow(Session session, IWindow client, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets) { Loading Loading @@ -4918,10 +4944,7 @@ public class WindowManagerService extends IWindowManager.Stub Log.w(TAG, "No window to dispatch pointer action " + ev.getAction()); } synchronized (mWindowMap) { if (mSendingPointersToWallpaper) { Log.i(TAG, "Sending skipped pointer to wallpaper!"); sendPointerToWallpaperLocked(null, ev, ev.getEventTime()); } dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true); } if (qev != null) { mQueue.recycleEvent(qev); Loading @@ -4931,10 +4954,7 @@ public class WindowManagerService extends IWindowManager.Stub } if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) { synchronized (mWindowMap) { if (mSendingPointersToWallpaper) { Log.i(TAG, "Sending skipped pointer to wallpaper!"); sendPointerToWallpaperLocked(null, ev, ev.getEventTime()); } dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true); } if (qev != null) { mQueue.recycleEvent(qev); Loading Loading @@ -5059,9 +5079,7 @@ public class WindowManagerService extends IWindowManager.Stub if (!target.isVisibleLw()) { // During this motion dispatch, the target window has become // invisible. if (mSendingPointersToWallpaper) { sendPointerToWallpaperLocked(null, ev, eventTime); } dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), false); if (qev != null) { mQueue.recycleEvent(qev); } Loading Loading @@ -5094,13 +5112,7 @@ public class WindowManagerService extends IWindowManager.Stub } } // If we are on top of the wallpaper, then the wallpaper also // gets to see this movement. if ((mWallpaperTarget == target && target.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) || mSendingPointersToWallpaper) { sendPointerToWallpaperLocked(null, ev, eventTime); } dispatchPointerElsewhereLocked(target, null, ev, ev.getEventTime(), false); final Rect frame = target.mFrame; ev.offsetLocation(-(float)frame.left, -(float)frame.top); Loading Loading @@ -6031,11 +6043,7 @@ public class WindowManagerService extends IWindowManager.Stub if (res != null && returnWhat == RETURN_PENDING_POINTER) { synchronized (mWindowMap) { if ((mWallpaperTarget == win && win.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) || mSendingPointersToWallpaper) { sendPointerToWallpaperLocked(win, res, res.getEventTime()); } dispatchPointerElsewhereLocked(win, win, res, res.getEventTime(), false); } } Loading Loading
common/java/com/android/common/ui/PointerLocationView.java 0 → 100644 +333 −0 Original line number Diff line number Diff line package com.android.common.ui; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.FontMetricsInt; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import java.util.ArrayList; public class PointerLocationView extends View { public static class PointerState { private final ArrayList<Float> mXs = new ArrayList<Float>(); private final ArrayList<Float> mYs = new ArrayList<Float>(); private boolean mCurDown; private int mCurX; private int mCurY; private float mCurPressure; private float mCurSize; private int mCurWidth; private VelocityTracker mVelocity; } private final ViewConfiguration mVC; private final Paint mTextPaint; private final Paint mTextBackgroundPaint; private final Paint mTextLevelPaint; private final Paint mPaint; private final Paint mTargetPaint; private final Paint mPathPaint; private final FontMetricsInt mTextMetrics = new FontMetricsInt(); private int mHeaderBottom; private boolean mCurDown; private int mCurNumPointers; private int mMaxNumPointers; private final ArrayList<PointerState> mPointers = new ArrayList<PointerState>(); private boolean mPrintCoords = true; public PointerLocationView(Context c) { super(c); mVC = ViewConfiguration.get(c); mTextPaint = new Paint(); mTextPaint.setAntiAlias(true); mTextPaint.setTextSize(10 * getResources().getDisplayMetrics().density); mTextPaint.setARGB(255, 0, 0, 0); mTextBackgroundPaint = new Paint(); mTextBackgroundPaint.setAntiAlias(false); mTextBackgroundPaint.setARGB(128, 255, 255, 255); mTextLevelPaint = new Paint(); mTextLevelPaint.setAntiAlias(false); mTextLevelPaint.setARGB(192, 255, 0, 0); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setARGB(255, 255, 255, 255); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(2); mTargetPaint = new Paint(); mTargetPaint.setAntiAlias(false); mTargetPaint.setARGB(255, 0, 0, 192); mPathPaint = new Paint(); mPathPaint.setAntiAlias(false); mPathPaint.setARGB(255, 0, 96, 255); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(1); PointerState ps = new PointerState(); ps.mVelocity = VelocityTracker.obtain(); mPointers.add(ps); } public void setPrintCoords(boolean state) { mPrintCoords = state; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mTextPaint.getFontMetricsInt(mTextMetrics); mHeaderBottom = -mTextMetrics.ascent+mTextMetrics.descent+2; if (false) { Log.i("foo", "Metrics: ascent=" + mTextMetrics.ascent + " descent=" + mTextMetrics.descent + " leading=" + mTextMetrics.leading + " top=" + mTextMetrics.top + " bottom=" + mTextMetrics.bottom); } } @Override protected void onDraw(Canvas canvas) { synchronized (mPointers) { final int w = getWidth(); final int itemW = w/7; final int base = -mTextMetrics.ascent+1; final int bottom = mHeaderBottom; final int NP = mPointers.size(); if (NP > 0) { final PointerState ps = mPointers.get(0); canvas.drawRect(0, 0, itemW-1, bottom,mTextBackgroundPaint); canvas.drawText("P: " + mCurNumPointers + " / " + mMaxNumPointers, 1, base, mTextPaint); final int N = ps.mXs.size(); if ((mCurDown && ps.mCurDown) || N == 0) { canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, mTextBackgroundPaint); canvas.drawText("X: " + ps.mCurX, 1 + itemW, base, mTextPaint); canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, mTextBackgroundPaint); canvas.drawText("Y: " + ps.mCurY, 1 + itemW * 2, base, mTextPaint); } else { float dx = ps.mXs.get(N-1) - ps.mXs.get(0); float dy = ps.mYs.get(N-1) - ps.mYs.get(0); canvas.drawRect(itemW, 0, (itemW * 2) - 1, bottom, Math.abs(dx) < mVC.getScaledTouchSlop() ? mTextBackgroundPaint : mTextLevelPaint); canvas.drawText("dX: " + String.format("%.1f", dx), 1 + itemW, base, mTextPaint); canvas.drawRect(itemW * 2, 0, (itemW * 3) - 1, bottom, Math.abs(dy) < mVC.getScaledTouchSlop() ? mTextBackgroundPaint : mTextLevelPaint); canvas.drawText("dY: " + String.format("%.1f", dy), 1 + itemW * 2, base, mTextPaint); } canvas.drawRect(itemW * 3, 0, (itemW * 4) - 1, bottom, mTextBackgroundPaint); int velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getXVelocity() * 1000); canvas.drawText("Xv: " + velocity, 1 + itemW * 3, base, mTextPaint); canvas.drawRect(itemW * 4, 0, (itemW * 5) - 1, bottom, mTextBackgroundPaint); velocity = ps.mVelocity == null ? 0 : (int) (ps.mVelocity.getYVelocity() * 1000); canvas.drawText("Yv: " + velocity, 1 + itemW * 4, base, mTextPaint); canvas.drawRect(itemW * 5, 0, (itemW * 6) - 1, bottom, mTextBackgroundPaint); canvas.drawRect(itemW * 5, 0, (itemW * 5) + (ps.mCurPressure * itemW) - 1, bottom, mTextLevelPaint); canvas.drawText("Prs: " + String.format("%.2f", ps.mCurPressure), 1 + itemW * 5, base, mTextPaint); canvas.drawRect(itemW * 6, 0, w, bottom, mTextBackgroundPaint); canvas.drawRect(itemW * 6, 0, (itemW * 6) + (ps.mCurSize * itemW) - 1, bottom, mTextLevelPaint); canvas.drawText("Size: " + String.format("%.2f", ps.mCurSize), 1 + itemW * 6, base, mTextPaint); } for (int p=0; p<NP; p++) { final PointerState ps = mPointers.get(p); if (mCurDown && ps.mCurDown) { canvas.drawLine(0, (int)ps.mCurY, getWidth(), (int)ps.mCurY, mTargetPaint); canvas.drawLine((int)ps.mCurX, 0, (int)ps.mCurX, getHeight(), mTargetPaint); int pressureLevel = (int)(ps.mCurPressure*255); mPaint.setARGB(255, pressureLevel, 128, 255-pressureLevel); canvas.drawPoint(ps.mCurX, ps.mCurY, mPaint); canvas.drawCircle(ps.mCurX, ps.mCurY, ps.mCurWidth, mPaint); } } for (int p=0; p<NP; p++) { final PointerState ps = mPointers.get(p); final int N = ps.mXs.size(); float lastX=0, lastY=0; boolean haveLast = false; boolean drawn = false; mPaint.setARGB(255, 128, 255, 255); for (int i=0; i<N; i++) { float x = ps.mXs.get(i); float y = ps.mYs.get(i); if (Float.isNaN(x)) { haveLast = false; continue; } if (haveLast) { canvas.drawLine(lastX, lastY, x, y, mPathPaint); canvas.drawPoint(lastX, lastY, mPaint); drawn = true; } lastX = x; lastY = y; haveLast = true; } if (drawn) { if (ps.mVelocity != null) { mPaint.setARGB(255, 255, 64, 128); float xVel = ps.mVelocity.getXVelocity() * (1000/60); float yVel = ps.mVelocity.getYVelocity() * (1000/60); canvas.drawLine(lastX, lastY, lastX+xVel, lastY+yVel, mPaint); } else { canvas.drawPoint(lastX, lastY, mPaint); } } } } } public void addTouchEvent(MotionEvent event) { synchronized (mPointers) { int action = event.getAction(); //Log.i("Pointer", "Motion: action=0x" + Integer.toHexString(action) // + " pointers=" + event.getPointerCount()); int NP = mPointers.size(); //mRect.set(0, 0, getWidth(), mHeaderBottom+1); //invalidate(mRect); //if (mCurDown) { // mRect.set(mCurX-mCurWidth-3, mCurY-mCurWidth-3, // mCurX+mCurWidth+3, mCurY+mCurWidth+3); //} else { // mRect.setEmpty(); //} if (action == MotionEvent.ACTION_DOWN) { for (int p=0; p<NP; p++) { final PointerState ps = mPointers.get(p); ps.mXs.clear(); ps.mYs.clear(); ps.mVelocity = VelocityTracker.obtain(); ps.mCurDown = false; } mPointers.get(0).mCurDown = true; mMaxNumPointers = 0; if (mPrintCoords) { Log.i("Pointer", "Pointer 1: DOWN"); } } if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) { final int id = (action&MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; while (NP <= id) { PointerState ps = new PointerState(); ps.mVelocity = VelocityTracker.obtain(); mPointers.add(ps); NP++; } final PointerState ps = mPointers.get(id); ps.mVelocity = VelocityTracker.obtain(); ps.mCurDown = true; if (mPrintCoords) { Log.i("Pointer", "Pointer " + (id+1) + ": DOWN"); } } final int NI = event.getPointerCount(); mCurDown = action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL; mCurNumPointers = mCurDown ? NI : 0; if (mMaxNumPointers < mCurNumPointers) { mMaxNumPointers = mCurNumPointers; } for (int i=0; i<NI; i++) { final PointerState ps = mPointers.get(event.getPointerId(i)); ps.mVelocity.addMovement(event); ps.mVelocity.computeCurrentVelocity(1); final int N = event.getHistorySize(); for (int j=0; j<N; j++) { if (mPrintCoords) { Log.i("Pointer", "Pointer " + (i+1) + ": (" + event.getHistoricalX(i, j) + ", " + event.getHistoricalY(i, j) + ")" + " Prs=" + event.getHistoricalPressure(i, j) + " Size=" + event.getHistoricalSize(i, j)); } ps.mXs.add(event.getHistoricalX(i, j)); ps.mYs.add(event.getHistoricalY(i, j)); } if (mPrintCoords) { Log.i("Pointer", "Pointer " + (i+1) + ": (" + event.getX(i) + ", " + event.getY(i) + ")" + " Prs=" + event.getPressure(i) + " Size=" + event.getSize(i)); } ps.mXs.add(event.getX(i)); ps.mYs.add(event.getY(i)); ps.mCurX = (int)event.getX(i); ps.mCurY = (int)event.getY(i); //Log.i("Pointer", "Pointer #" + p + ": (" + ps.mCurX // + "," + ps.mCurY + ")"); ps.mCurPressure = event.getPressure(i); ps.mCurSize = event.getSize(i); ps.mCurWidth = (int)(ps.mCurSize*(getWidth()/3)); } if ((action&MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP) { final int id = (action&MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; final PointerState ps = mPointers.get(id); ps.mXs.add(Float.NaN); ps.mYs.add(Float.NaN); ps.mCurDown = false; if (mPrintCoords) { Log.i("Pointer", "Pointer " + (id+1) + ": UP"); } } if (action == MotionEvent.ACTION_UP) { for (int i=0; i<NI; i++) { final PointerState ps = mPointers.get(event.getPointerId(i)); if (ps.mCurDown) { ps.mCurDown = false; if (mPrintCoords) { Log.i("Pointer", "Pointer " + (i+1) + ": UP"); } } } } //if (mCurDown) { // mRect.union(mCurX-mCurWidth-3, mCurY-mCurWidth-3, // mCurX+mCurWidth+3, mCurY+mCurWidth+3); //} //invalidate(mRect); postInvalidate(); } } @Override public boolean onTouchEvent(MotionEvent event) { addTouchEvent(event); return true; } }
core/java/android/provider/Settings.java +8 −0 Original line number Diff line number Diff line Loading @@ -1488,6 +1488,14 @@ public final class Settings { */ public static final String DEFAULT_INSTALL_LOCATION = "default_install_location"; /** * Show pointer location on screen? * 0 = no * 1 = yes * @hide */ public static final String POINTER_LOCATION = "pointer_location"; /** * Settings to backup. This is here so that it's in the same place as the settings * keys and easy to update. Loading
core/java/android/view/WindowManagerPolicy.java +5 −0 Original line number Diff line number Diff line Loading @@ -851,6 +851,11 @@ public interface WindowManagerPolicy { */ public boolean isCheekPressedAgainstScreen(MotionEvent ev); /** * Called every time the window manager is dispatching a pointer event. */ public void dispatchedPointerEventLw(MotionEvent ev, int targetX, int targetY); public void setCurrentOrientationLw(int newOrientation); /** Loading
services/java/com/android/server/WindowManagerService.java +31 −23 Original line number Diff line number Diff line Loading @@ -1773,6 +1773,32 @@ public class WindowManagerService extends IWindowManager.Stub } } void dispatchPointerElsewhereLocked(WindowState srcWin, WindowState relWin, MotionEvent pointer, long eventTime, boolean skipped) { if (relWin != null) { mPolicy.dispatchedPointerEventLw(pointer, relWin.mFrame.left, relWin.mFrame.top); } else { mPolicy.dispatchedPointerEventLw(pointer, 0, 0); } // If we sent an initial down to the wallpaper, then continue // sending events until the final up. if (mSendingPointersToWallpaper) { if (skipped) { Log.i(TAG, "Sending skipped pointer to wallpaper!"); } sendPointerToWallpaperLocked(relWin, pointer, eventTime); // If we are on top of the wallpaper, then the wallpaper also // gets to see this movement. } else if (srcWin != null && pointer.getAction() == MotionEvent.ACTION_DOWN && mWallpaperTarget == srcWin && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) { sendPointerToWallpaperLocked(relWin, pointer, eventTime); } } public int addWindow(Session session, IWindow client, WindowManager.LayoutParams attrs, int viewVisibility, Rect outContentInsets) { Loading Loading @@ -4918,10 +4944,7 @@ public class WindowManagerService extends IWindowManager.Stub Log.w(TAG, "No window to dispatch pointer action " + ev.getAction()); } synchronized (mWindowMap) { if (mSendingPointersToWallpaper) { Log.i(TAG, "Sending skipped pointer to wallpaper!"); sendPointerToWallpaperLocked(null, ev, ev.getEventTime()); } dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true); } if (qev != null) { mQueue.recycleEvent(qev); Loading @@ -4931,10 +4954,7 @@ public class WindowManagerService extends IWindowManager.Stub } if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) { synchronized (mWindowMap) { if (mSendingPointersToWallpaper) { Log.i(TAG, "Sending skipped pointer to wallpaper!"); sendPointerToWallpaperLocked(null, ev, ev.getEventTime()); } dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true); } if (qev != null) { mQueue.recycleEvent(qev); Loading Loading @@ -5059,9 +5079,7 @@ public class WindowManagerService extends IWindowManager.Stub if (!target.isVisibleLw()) { // During this motion dispatch, the target window has become // invisible. if (mSendingPointersToWallpaper) { sendPointerToWallpaperLocked(null, ev, eventTime); } dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), false); if (qev != null) { mQueue.recycleEvent(qev); } Loading Loading @@ -5094,13 +5112,7 @@ public class WindowManagerService extends IWindowManager.Stub } } // If we are on top of the wallpaper, then the wallpaper also // gets to see this movement. if ((mWallpaperTarget == target && target.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) || mSendingPointersToWallpaper) { sendPointerToWallpaperLocked(null, ev, eventTime); } dispatchPointerElsewhereLocked(target, null, ev, ev.getEventTime(), false); final Rect frame = target.mFrame; ev.offsetLocation(-(float)frame.left, -(float)frame.top); Loading Loading @@ -6031,11 +6043,7 @@ public class WindowManagerService extends IWindowManager.Stub if (res != null && returnWhat == RETURN_PENDING_POINTER) { synchronized (mWindowMap) { if ((mWallpaperTarget == win && win.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) || mSendingPointersToWallpaper) { sendPointerToWallpaperLocked(win, res, res.getEventTime()); } dispatchPointerElsewhereLocked(win, win, res, res.getEventTime(), false); } } Loading