blob: a71c39a0b3b5c5421f15b1df0af7912e33bf07d3 [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
Michael Chan53071d62009-05-13 17:29:48 -070066 MotionEvent generateMotion(InputDevice device, long curTime, long curTimeNano,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067 boolean isAbs, Display display, int orientation,
68 int metaState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 float scaledX = x;
70 float scaledY = y;
71 float temp;
72 float scaledPressure = 1.0f;
73 float scaledSize = 0;
74 int edgeFlags = 0;
Dianne Hackborne3dd8842009-07-14 12:06:54 -070075
76 int action;
77 if (down != lastDown) {
78 if (isAbs) {
79 final AbsoluteInfo absX = device.absX;
80 final AbsoluteInfo absY = device.absY;
81 if (down && absX != null && absY != null) {
82 // We don't let downs start unless we are
83 // inside of the screen. There are two reasons for
84 // this: to avoid spurious touches when holding
85 // the edges of the device near the touchscreen,
86 // and to avoid reporting events if there are virtual
87 // keys on the touchscreen outside of the display
88 // area.
89 if (scaledX < absX.minValue || scaledX > absX.maxValue
90 || scaledY < absY.minValue || scaledY > absY.maxValue) {
91 if (false) Log.v("InputDevice", "Rejecting (" + scaledX + ","
92 + scaledY + "): outside of ("
93 + absX.minValue + "," + absY.minValue
94 + ")-(" + absX.maxValue + ","
95 + absY.maxValue + ")");
96 return null;
97 }
98 }
99 } else {
100 x = y = 0;
101 }
102 lastDown = down;
103 if (down) {
104 action = MotionEvent.ACTION_DOWN;
105 downTime = curTime;
106 } else {
107 action = MotionEvent.ACTION_UP;
108 }
109 currentMove = null;
110 } else {
111 action = MotionEvent.ACTION_MOVE;
112 }
113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 if (isAbs) {
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700115 final int dispW = display.getWidth()-1;
116 final int dispH = display.getHeight()-1;
117 int w = dispW;
118 int h = dispH;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 if (orientation == Surface.ROTATION_90
120 || orientation == Surface.ROTATION_270) {
121 int tmp = w;
122 w = h;
123 h = tmp;
124 }
125 if (device.absX != null) {
126 scaledX = ((scaledX-device.absX.minValue)
127 / device.absX.range) * w;
128 }
129 if (device.absY != null) {
130 scaledY = ((scaledY-device.absY.minValue)
131 / device.absY.range) * h;
132 }
133 if (device.absPressure != null) {
134 scaledPressure =
135 ((pressure-device.absPressure.minValue)
136 / (float)device.absPressure.range);
137 }
138 if (device.absSize != null) {
139 scaledSize =
140 ((size-device.absSize.minValue)
141 / (float)device.absSize.range);
142 }
143 switch (orientation) {
144 case Surface.ROTATION_90:
145 temp = scaledX;
146 scaledX = scaledY;
147 scaledY = w-temp;
148 break;
149 case Surface.ROTATION_180:
150 scaledX = w-scaledX;
151 scaledY = h-scaledY;
152 break;
153 case Surface.ROTATION_270:
154 temp = scaledX;
155 scaledX = h-scaledY;
156 scaledY = temp;
157 break;
158 }
159
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700160 if (action != MotionEvent.ACTION_DOWN) {
161 if (scaledX <= 0) {
162 edgeFlags += MotionEvent.EDGE_LEFT;
163 } else if (scaledX >= dispW) {
164 edgeFlags += MotionEvent.EDGE_RIGHT;
165 }
166 if (scaledY <= 0) {
167 edgeFlags += MotionEvent.EDGE_TOP;
168 } else if (scaledY >= dispH) {
169 edgeFlags += MotionEvent.EDGE_BOTTOM;
170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 }
172
173 } else {
174 scaledX *= xMoveScale;
175 scaledY *= yMoveScale;
176 switch (orientation) {
177 case Surface.ROTATION_90:
178 temp = scaledX;
179 scaledX = scaledY;
180 scaledY = -temp;
181 break;
182 case Surface.ROTATION_180:
183 scaledX = -scaledX;
184 scaledY = -scaledY;
185 break;
186 case Surface.ROTATION_270:
187 temp = scaledX;
188 scaledX = -scaledY;
189 scaledY = temp;
190 break;
191 }
192 }
193
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700194 if (currentMove != null) {
195 if (false) Log.i("InputDevice", "Adding batch x=" + scaledX
196 + " y=" + scaledY + " to " + currentMove);
197 currentMove.addBatch(curTime, scaledX, scaledY,
198 scaledPressure, scaledSize, metaState);
199 if (WindowManagerPolicy.WATCH_POINTER) {
200 Log.i("KeyInputQueue", "Updating: " + currentMove);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 }
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700202 return null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 }
Dianne Hackborne3dd8842009-07-14 12:06:54 -0700204
205 MotionEvent me = MotionEvent.obtainNano(downTime, curTime,
206 curTimeNano, action, scaledX, scaledY,
207 scaledPressure, scaledSize, metaState,
208 xPrecision, yPrecision, device.id, edgeFlags);
209 if (action == MotionEvent.ACTION_MOVE) {
210 currentMove = me;
211 }
212 return me;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 }
214 }
215
216 static class AbsoluteInfo {
217 int minValue;
218 int maxValue;
219 int range;
220 int flat;
221 int fuzz;
222 };
223
224 InputDevice(int _id, int _classes, String _name,
225 AbsoluteInfo _absX, AbsoluteInfo _absY,
226 AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {
227 id = _id;
228 classes = _classes;
229 name = _name;
230 absX = _absX;
231 absY = _absY;
232 absPressure = _absPressure;
233 absSize = _absSize;
234 }
235};