blob: 70bf38e03e4232646b905a6836d8eeb153457a04 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/*
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 if (isAbs) {
79 int w = display.getWidth()-1;
80 int h = display.getHeight()-1;
81 if (orientation == Surface.ROTATION_90
82 || orientation == Surface.ROTATION_270) {
83 int tmp = w;
84 w = h;
85 h = tmp;
86 }
87 if (device.absX != null) {
88 scaledX = ((scaledX-device.absX.minValue)
89 / device.absX.range) * w;
90 }
91 if (device.absY != null) {
92 scaledY = ((scaledY-device.absY.minValue)
93 / device.absY.range) * h;
94 }
95 if (device.absPressure != null) {
96 scaledPressure =
97 ((pressure-device.absPressure.minValue)
98 / (float)device.absPressure.range);
99 }
100 if (device.absSize != null) {
101 scaledSize =
102 ((size-device.absSize.minValue)
103 / (float)device.absSize.range);
104 }
105 switch (orientation) {
106 case Surface.ROTATION_90:
107 temp = scaledX;
108 scaledX = scaledY;
109 scaledY = w-temp;
110 break;
111 case Surface.ROTATION_180:
112 scaledX = w-scaledX;
113 scaledY = h-scaledY;
114 break;
115 case Surface.ROTATION_270:
116 temp = scaledX;
117 scaledX = h-scaledY;
118 scaledY = temp;
119 break;
120 }
121 } else {
122 scaledX *= xMoveScale;
123 scaledY *= yMoveScale;
124 switch (orientation) {
125 case Surface.ROTATION_90:
126 temp = scaledX;
127 scaledX = scaledY;
128 scaledY = -temp;
129 break;
130 case Surface.ROTATION_180:
131 scaledX = -scaledX;
132 scaledY = -scaledY;
133 break;
134 case Surface.ROTATION_270:
135 temp = scaledX;
136 scaledX = -scaledY;
137 scaledY = temp;
138 break;
139 }
140 }
141
142 int edgeFlags = 0;
143 if (scaledX == 0) {
144 edgeFlags += MotionEvent.EDGE_LEFT;
145 } else if (scaledX == display.getWidth() - 1.0f) {
146 edgeFlags += MotionEvent.EDGE_RIGHT;
147 }
148
149 if (scaledY == 0) {
150 edgeFlags += MotionEvent.EDGE_TOP;
151 } else if (scaledY == display.getHeight() - 1.0f) {
152 edgeFlags += MotionEvent.EDGE_BOTTOM;
153 }
154
155 changed = false;
156 if (down != lastDown) {
157 int action;
158 lastDown = down;
159 if (down) {
160 action = MotionEvent.ACTION_DOWN;
161 downTime = curTime;
162 } else {
163 action = MotionEvent.ACTION_UP;
164 }
165 currentMove = null;
166 if (!isAbs) {
167 x = y = 0;
168 }
169 return MotionEvent.obtain(downTime, curTime, action,
170 scaledX, scaledY, scaledPressure, scaledSize, metaState,
171 xPrecision, yPrecision, device.id, edgeFlags);
172 } else {
173 if (currentMove != null) {
174 currentMove.addBatch(curTime, scaledX, scaledY,
175 scaledPressure, scaledSize, metaState);
176 if (WindowManagerPolicy.WATCH_POINTER) {
177 Log.i("KeyInputQueue", "Updating: " + currentMove);
178 }
179 return null;
180 }
181 MotionEvent me = MotionEvent.obtain(downTime, curTime,
182 MotionEvent.ACTION_MOVE, scaledX, scaledY,
183 scaledPressure, scaledSize, metaState,
184 xPrecision, yPrecision, device.id, edgeFlags);
185 currentMove = me;
186 return me;
187 }
188 }
189 }
190
191 static class AbsoluteInfo {
192 int minValue;
193 int maxValue;
194 int range;
195 int flat;
196 int fuzz;
197 };
198
199 InputDevice(int _id, int _classes, String _name,
200 AbsoluteInfo _absX, AbsoluteInfo _absY,
201 AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {
202 id = _id;
203 classes = _classes;
204 name = _name;
205 absX = _absX;
206 absY = _absY;
207 absPressure = _absPressure;
208 absSize = _absSize;
209 }
210};