/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server; import android.util.Log; import android.view.Display; import android.view.MotionEvent; import android.view.Surface; import android.view.WindowManagerPolicy; public class InputDevice { /** Amount that trackball needs to move in order to generate a key event. */ static final int TRACKBALL_MOVEMENT_THRESHOLD = 6; final int id; final int classes; final String name; final AbsoluteInfo absX; final AbsoluteInfo absY; final AbsoluteInfo absPressure; final AbsoluteInfo absSize; long mDownTime = 0; int mMetaKeysState = 0; final MotionState mAbs = new MotionState(0, 0); final MotionState mRel = new MotionState(TRACKBALL_MOVEMENT_THRESHOLD, TRACKBALL_MOVEMENT_THRESHOLD); static class MotionState { int xPrecision; int yPrecision; float xMoveScale; float yMoveScale; MotionEvent currentMove = null; boolean changed = false; boolean down = false; boolean lastDown = false; long downTime = 0; int x = 0; int y = 0; int pressure = 1; int size = 0; MotionState(int mx, int my) { xPrecision = mx; yPrecision = my; xMoveScale = mx != 0 ? (1.0f/mx) : 1.0f; yMoveScale = my != 0 ? (1.0f/my) : 1.0f; } MotionEvent generateMotion(InputDevice device, long curTime, boolean isAbs, Display display, int orientation, int metaState) { if (!changed) { return null; } float scaledX = x; float scaledY = y; float temp; float scaledPressure = 1.0f; float scaledSize = 0; int edgeFlags = 0; if (isAbs) { int w = display.getWidth()-1; int h = display.getHeight()-1; if (orientation == Surface.ROTATION_90 || orientation == Surface.ROTATION_270) { int tmp = w; w = h; h = tmp; } if (device.absX != null) { scaledX = ((scaledX-device.absX.minValue) / device.absX.range) * w; } if (device.absY != null) { scaledY = ((scaledY-device.absY.minValue) / device.absY.range) * h; } if (device.absPressure != null) { scaledPressure = ((pressure-device.absPressure.minValue) / (float)device.absPressure.range); } if (device.absSize != null) { scaledSize = ((size-device.absSize.minValue) / (float)device.absSize.range); } switch (orientation) { case Surface.ROTATION_90: temp = scaledX; scaledX = scaledY; scaledY = w-temp; break; case Surface.ROTATION_180: scaledX = w-scaledX; scaledY = h-scaledY; break; case Surface.ROTATION_270: temp = scaledX; scaledX = h-scaledY; scaledY = temp; break; } if (scaledX == 0) { edgeFlags += MotionEvent.EDGE_LEFT; } else if (scaledX == display.getWidth() - 1.0f) { edgeFlags += MotionEvent.EDGE_RIGHT; } if (scaledY == 0) { edgeFlags += MotionEvent.EDGE_TOP; } else if (scaledY == display.getHeight() - 1.0f) { edgeFlags += MotionEvent.EDGE_BOTTOM; } } else { scaledX *= xMoveScale; scaledY *= yMoveScale; switch (orientation) { case Surface.ROTATION_90: temp = scaledX; scaledX = scaledY; scaledY = -temp; break; case Surface.ROTATION_180: scaledX = -scaledX; scaledY = -scaledY; break; case Surface.ROTATION_270: temp = scaledX; scaledX = -scaledY; scaledY = temp; break; } } changed = false; if (down != lastDown) { int action; lastDown = down; if (down) { action = MotionEvent.ACTION_DOWN; downTime = curTime; } else { action = MotionEvent.ACTION_UP; } currentMove = null; if (!isAbs) { x = y = 0; } return MotionEvent.obtain(downTime, curTime, action, scaledX, scaledY, scaledPressure, scaledSize, metaState, xPrecision, yPrecision, device.id, edgeFlags); } else { if (currentMove != null) { if (false) Log.i("InputDevice", "Adding batch x=" + scaledX + " y=" + scaledY + " to " + currentMove); currentMove.addBatch(curTime, scaledX, scaledY, scaledPressure, scaledSize, metaState); if (WindowManagerPolicy.WATCH_POINTER) { Log.i("KeyInputQueue", "Updating: " + currentMove); } return null; } MotionEvent me = MotionEvent.obtain(downTime, curTime, MotionEvent.ACTION_MOVE, scaledX, scaledY, scaledPressure, scaledSize, metaState, xPrecision, yPrecision, device.id, edgeFlags); currentMove = me; return me; } } } static class AbsoluteInfo { int minValue; int maxValue; int range; int flat; int fuzz; }; InputDevice(int _id, int _classes, String _name, AbsoluteInfo _absX, AbsoluteInfo _absY, AbsoluteInfo _absPressure, AbsoluteInfo _absSize) { id = _id; classes = _classes; name = _name; absX = _absX; absY = _absY; absPressure = _absPressure; absSize = _absSize; } };