MotionEvent generateAbsMotion( InputDevice device, long curTime, long curTimeNano, Display display, int orientation, int metaState) { boolean isMouse = ((device.classes & RawInputEvent.CLASS_MOUSE) == RawInputEvent.CLASS_MOUSE); if (mSkipLastPointers) { mSkipLastPointers = false; mLastNumPointers = 0; } if (!isMouse && (mNextNumPointers <= 0 && mLastNumPointers <= 0)) { return null; } final int lastNumPointers = mLastNumPointers; final int nextNumPointers = mNextNumPointers; if (mNextNumPointers > MAX_POINTERS) { Slog.w( "InputDevice", "Number of pointers " + mNextNumPointers + " exceeded maximum of " + MAX_POINTERS); mNextNumPointers = MAX_POINTERS; } /* * This is not used for mouse */ int upOrDownPointer = isMouse ? 0 : updatePointerIdentifiers(); final float[] reportData = mReportData; final int[] rawData; if (!isMouse && KeyInputQueue.BAD_TOUCH_HACK) { rawData = generateAveragedData(upOrDownPointer, lastNumPointers, nextNumPointers); } else { rawData = isMouse ? mNextData : mLastData; } final int numPointers = isMouse ? 1 : mLastNumPointers; if (DEBUG_POINTERS) Slog.v( "InputDevice", "Processing " + numPointers + " pointers (going from " + lastNumPointers + " to " + nextNumPointers + ")"); for (int i = 0; i < numPointers; i++) { final int pos = i * MotionEvent.NUM_SAMPLE_DATA; reportData[pos + MotionEvent.SAMPLE_X] = rawData[pos + MotionEvent.SAMPLE_X]; reportData[pos + MotionEvent.SAMPLE_Y] = rawData[pos + MotionEvent.SAMPLE_Y]; reportData[pos + MotionEvent.SAMPLE_PRESSURE] = rawData[pos + MotionEvent.SAMPLE_PRESSURE]; reportData[pos + MotionEvent.SAMPLE_SIZE] = rawData[pos + MotionEvent.SAMPLE_SIZE]; } int action; int edgeFlags = 0; if (!isMouse) { if (nextNumPointers != lastNumPointers) { if (nextNumPointers > lastNumPointers) { if (lastNumPointers == 0) { action = MotionEvent.ACTION_DOWN; mDownTime = curTime; } else { action = MotionEvent.ACTION_POINTER_DOWN | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT); } } else { if (numPointers == 1) { action = MotionEvent.ACTION_UP; } else { action = MotionEvent.ACTION_POINTER_UP | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT); } } currentMove = null; } else { action = MotionEvent.ACTION_MOVE; } } else { if (mNextNumPointers != mLastNumPointers) { if (mNextNumPointers == 1) { action = MotionEvent.ACTION_DOWN; mDownTime = curTime; } else if (mNextNumPointers == 2) { action = MotionEvent.ACTION_UP; } else { action = MotionEvent.ACTION_MOVE; } mLastNumPointers = mNextNumPointers; currentMove = null; } else { action = MotionEvent.ACTION_MOVE; } } final int dispW = display.getWidth() - 1; final int dispH = display.getHeight() - 1; int w = dispW; int h = dispH; if (orientation == Surface.ROTATION_90 || orientation == Surface.ROTATION_270) { int tmp = w; w = h; h = tmp; } final AbsoluteInfo absX = device.absX; final AbsoluteInfo absY = device.absY; final AbsoluteInfo absPressure = device.absPressure; final AbsoluteInfo absSize = device.absSize; for (int i = 0; i < numPointers; i++) { final int j = i * MotionEvent.NUM_SAMPLE_DATA; if (absX != null) { reportData[j + MotionEvent.SAMPLE_X] = ((reportData[j + MotionEvent.SAMPLE_X] - absX.minValue) / absX.range) * w; } if (absY != null) { reportData[j + MotionEvent.SAMPLE_Y] = ((reportData[j + MotionEvent.SAMPLE_Y] - absY.minValue) / absY.range) * h; } if (absPressure != null) { reportData[j + MotionEvent.SAMPLE_PRESSURE] = ((reportData[j + MotionEvent.SAMPLE_PRESSURE] - absPressure.minValue) / (float) absPressure.range); } if (absSize != null) { reportData[j + MotionEvent.SAMPLE_SIZE] = ((reportData[j + MotionEvent.SAMPLE_SIZE] - absSize.minValue) / (float) absSize.range); } switch (orientation) { case Surface.ROTATION_90: { final float temp = reportData[j + MotionEvent.SAMPLE_X]; reportData[j + MotionEvent.SAMPLE_X] = reportData[j + MotionEvent.SAMPLE_Y]; reportData[j + MotionEvent.SAMPLE_Y] = w - temp; break; } case Surface.ROTATION_180: { reportData[j + MotionEvent.SAMPLE_X] = w - reportData[j + MotionEvent.SAMPLE_X]; reportData[j + MotionEvent.SAMPLE_Y] = h - reportData[j + MotionEvent.SAMPLE_Y]; break; } case Surface.ROTATION_270: { final float temp = reportData[j + MotionEvent.SAMPLE_X]; reportData[j + MotionEvent.SAMPLE_X] = h - reportData[j + MotionEvent.SAMPLE_Y]; reportData[j + MotionEvent.SAMPLE_Y] = temp; break; } } } // We only consider the first pointer when computing the edge // flags, since they are global to the event. if (action == MotionEvent.ACTION_DOWN) { if (reportData[MotionEvent.SAMPLE_X] <= 0) { edgeFlags |= MotionEvent.EDGE_LEFT; } else if (reportData[MotionEvent.SAMPLE_X] >= dispW) { edgeFlags |= MotionEvent.EDGE_RIGHT; } if (reportData[MotionEvent.SAMPLE_Y] <= 0) { edgeFlags |= MotionEvent.EDGE_TOP; } else if (reportData[MotionEvent.SAMPLE_Y] >= dispH) { edgeFlags |= MotionEvent.EDGE_BOTTOM; } } if (currentMove != null) { if (false) Slog.i( "InputDevice", "Adding batch x=" + reportData[MotionEvent.SAMPLE_X] + " y=" + reportData[MotionEvent.SAMPLE_Y] + " to " + currentMove); currentMove.addBatch(curTime, reportData, metaState); if (WindowManagerPolicy.WATCH_POINTER) { Slog.i("KeyInputQueue", "Updating: " + currentMove); } return null; } MotionEvent me = MotionEvent.obtainNano( mDownTime, curTime, curTimeNano, action, numPointers, mPointerIds, reportData, metaState, xPrecision, yPrecision, device.id, edgeFlags); if (action == MotionEvent.ACTION_MOVE) { currentMove = me; } if (nextNumPointers < lastNumPointers) { removeOldPointer(upOrDownPointer); } return me; }
MotionEvent generateRelMotion( InputDevice device, long curTime, long curTimeNano, int orientation, int metaState) { final float[] scaled = mReportData; // For now we only support 1 pointer with relative motions. scaled[MotionEvent.SAMPLE_X] = mNextData[MotionEvent.SAMPLE_X]; scaled[MotionEvent.SAMPLE_Y] = mNextData[MotionEvent.SAMPLE_Y]; scaled[MotionEvent.SAMPLE_PRESSURE] = 1.0f; scaled[MotionEvent.SAMPLE_SIZE] = 0; int edgeFlags = 0; int action; if (mNextNumPointers != mLastNumPointers) { mNextData[MotionEvent.SAMPLE_X] = mNextData[MotionEvent.SAMPLE_Y] = 0; if (mNextNumPointers > 0 && mLastNumPointers == 0) { action = MotionEvent.ACTION_DOWN; mDownTime = curTime; } else if (mNextNumPointers == 0) { action = MotionEvent.ACTION_UP; } else { action = MotionEvent.ACTION_MOVE; } mLastNumPointers = mNextNumPointers; currentMove = null; } else { action = MotionEvent.ACTION_MOVE; } scaled[MotionEvent.SAMPLE_X] *= xMoveScale; scaled[MotionEvent.SAMPLE_Y] *= yMoveScale; switch (orientation) { case Surface.ROTATION_90: { final float temp = scaled[MotionEvent.SAMPLE_X]; scaled[MotionEvent.SAMPLE_X] = scaled[MotionEvent.SAMPLE_Y]; scaled[MotionEvent.SAMPLE_Y] = -temp; break; } case Surface.ROTATION_180: { scaled[MotionEvent.SAMPLE_X] = -scaled[MotionEvent.SAMPLE_X]; scaled[MotionEvent.SAMPLE_Y] = -scaled[MotionEvent.SAMPLE_Y]; break; } case Surface.ROTATION_270: { final float temp = scaled[MotionEvent.SAMPLE_X]; scaled[MotionEvent.SAMPLE_X] = -scaled[MotionEvent.SAMPLE_Y]; scaled[MotionEvent.SAMPLE_Y] = temp; break; } } if (currentMove != null) { if (false) Slog.i( "InputDevice", "Adding batch x=" + scaled[MotionEvent.SAMPLE_X] + " y=" + scaled[MotionEvent.SAMPLE_Y] + " to " + currentMove); currentMove.addBatch(curTime, scaled, metaState); if (WindowManagerPolicy.WATCH_POINTER) { Slog.i("KeyInputQueue", "Updating: " + currentMove); } return null; } MotionEvent me = MotionEvent.obtainNano( mDownTime, curTime, curTimeNano, action, 1, mPointerIds, scaled, metaState, xPrecision, yPrecision, device.id, edgeFlags); if (action == MotionEvent.ACTION_MOVE) { currentMove = me; } return me; }