blob: 7b8a2a47e5bf0283c422b785e2ca56bac6688e55 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import android.util.Log;
20import android.view.Display;
21import android.view.MotionEvent;
22import android.view.Surface;
23import android.view.WindowManagerPolicy;
24
25public class InputDevice {
26 /** Amount that trackball needs to move in order to generate a key event. */
27 static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
28
29 final int id;
30 final int classes;
31 final String name;
32 final AbsoluteInfo absX;
33 final AbsoluteInfo absY;
34 final AbsoluteInfo absPressure;
35 final AbsoluteInfo absSize;
36
37 long mDownTime = 0;
38 int mMetaKeysState = 0;
39
40 final MotionState mAbs = new MotionState(0, 0);
41 final MotionState mRel = new MotionState(TRACKBALL_MOVEMENT_THRESHOLD,
42 TRACKBALL_MOVEMENT_THRESHOLD);
43
44 static class MotionState {
45 int xPrecision;
46 int yPrecision;
47 float xMoveScale;
48 float yMoveScale;
49 MotionEvent currentMove = null;
50 boolean changed = false;
51 boolean down = false;
52 boolean lastDown = false;
53 long downTime = 0;
54 int x = 0;
55 int y = 0;
56 int pressure = 1;
57 int size = 0;
58
59 MotionState(int mx, int my) {
60 xPrecision = mx;
61 yPrecision = my;
62 xMoveScale = mx != 0 ? (1.0f/mx) : 1.0f;
63 yMoveScale = my != 0 ? (1.0f/my) : 1.0f;
64 }
65
66 MotionEvent generateMotion(InputDevice device, long curTime,
67 boolean isAbs, Display display, int orientation,
68 int metaState) {
69 if (!changed) {
70 return null;
71 }
72
73 float scaledX = x;
74 float scaledY = y;
75 float temp;
76 float scaledPressure = 1.0f;
77 float scaledSize = 0;
78 int edgeFlags = 0;
79 if (isAbs) {
80 int w = display.getWidth()-1;
81 int h = display.getHeight()-1;
82 if (orientation == Surface.ROTATION_90
83 || orientation == Surface.ROTATION_270) {
84 int tmp = w;
85 w = h;
86 h = tmp;
87 }
88 if (device.absX != null) {
89 scaledX = ((scaledX-device.absX.minValue)
90 / device.absX.range) * w;
91 }
92 if (device.absY != null) {
93 scaledY = ((scaledY-device.absY.minValue)
94 / device.absY.range) * h;
95 }
96 if (device.absPressure != null) {
97 scaledPressure =
98 ((pressure-device.absPressure.minValue)
99 / (float)device.absPressure.range);
100 }
101 if (device.absSize != null) {
102 scaledSize =
103 ((size-device.absSize.minValue)
104 / (float)device.absSize.range);
105 }
106 switch (orientation) {
107 case Surface.ROTATION_90:
108 temp = scaledX;
109 scaledX = scaledY;
110 scaledY = w-temp;
111 break;
112 case Surface.ROTATION_180:
113 scaledX = w-scaledX;
114 scaledY = h-scaledY;
115 break;
116 case Surface.ROTATION_270:
117 temp = scaledX;
118 scaledX = h-scaledY;
119 scaledY = temp;
120 break;
121 }
122
123 if (scaledX == 0) {
124 edgeFlags += MotionEvent.EDGE_LEFT;
125 } else if (scaledX == display.getWidth() - 1.0f) {
126 edgeFlags += MotionEvent.EDGE_RIGHT;
127 }
128
129 if (scaledY == 0) {
130 edgeFlags += MotionEvent.EDGE_TOP;
131 } else if (scaledY == display.getHeight() - 1.0f) {
132 edgeFlags += MotionEvent.EDGE_BOTTOM;
133 }
134
135 } else {
136 scaledX *= xMoveScale;
137 scaledY *= yMoveScale;
138 switch (orientation) {
139 case Surface.ROTATION_90:
140 temp = scaledX;
141 scaledX = scaledY;
142 scaledY = -temp;
143 break;
144 case Surface.ROTATION_180:
145 scaledX = -scaledX;
146 scaledY = -scaledY;
147 break;
148 case Surface.ROTATION_270:
149 temp = scaledX;
150 scaledX = -scaledY;
151 scaledY = temp;
152 break;
153 }
154 }
155
156 changed = false;
157 if (down != lastDown) {
158 int action;
159 lastDown = down;
160 if (down) {
161 action = MotionEvent.ACTION_DOWN;
162 downTime = curTime;
163 } else {
164 action = MotionEvent.ACTION_UP;
165 }
166 currentMove = null;
167 if (!isAbs) {
168 x = y = 0;
169 }
170 return MotionEvent.obtain(downTime, curTime, action,
171 scaledX, scaledY, scaledPressure, scaledSize, metaState,
172 xPrecision, yPrecision, device.id, edgeFlags);
173 } else {
174 if (currentMove != null) {
175 if (false) Log.i("InputDevice", "Adding batch x=" + scaledX
176 + " y=" + scaledY + " to " + currentMove);
177 currentMove.addBatch(curTime, scaledX, scaledY,
178 scaledPressure, scaledSize, metaState);
179 if (WindowManagerPolicy.WATCH_POINTER) {
180 Log.i("KeyInputQueue", "Updating: " + currentMove);
181 }
182 return null;
183 }
184 MotionEvent me = MotionEvent.obtain(downTime, curTime,
185 MotionEvent.ACTION_MOVE, scaledX, scaledY,
186 scaledPressure, scaledSize, metaState,
187 xPrecision, yPrecision, device.id, edgeFlags);
188 currentMove = me;
189 return me;
190 }
191 }
192 }
193
194 static class AbsoluteInfo {
195 int minValue;
196 int maxValue;
197 int range;
198 int flat;
199 int fuzz;
200 };
201
202 InputDevice(int _id, int _classes, String _name,
203 AbsoluteInfo _absX, AbsoluteInfo _absY,
204 AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {
205 id = _id;
206 classes = _classes;
207 name = _name;
208 absX = _absX;
209 absY = _absY;
210 absPressure = _absPressure;
211 absSize = _absSize;
212 }
213};