OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.content.browser.input; | |
6 | |
7 import android.content.Context; | |
8 import android.hardware.input.InputManager; | |
9 import android.hardware.input.InputManager.InputDeviceListener; | |
10 import android.view.InputDevice; | |
11 import android.view.InputEvent; | |
12 import android.view.KeyEvent; | |
13 import android.view.MotionEvent; | |
14 | |
15 import org.chromium.base.CalledByNative; | |
16 import org.chromium.base.JNINamespace; | |
17 import org.chromium.base.ThreadUtils; | |
18 | |
19 @JNINamespace("content") | |
Ted C
2014/04/16 23:36:53
the annotations usually go right above the class d
SaurabhK
2014/04/18 14:51:57
On 2014/04/16 23:36:53, Ted C wrote:
Done.
| |
20 | |
21 /** | |
22 * Class to manage connected gamepad devices list. | |
23 * | |
24 * It is a Java counterpart of GamepadPlatformDataFetcherAndroid and feeds Gamep ad API with input | |
25 * data. | |
26 */ | |
27 public class GamepadList implements InputDeviceListener { | |
28 private static final int MAX_GAMEPADS = 4; | |
29 | |
30 private static GamepadList sGamepadList = null; | |
31 | |
32 private final Object mLock = new Object(); | |
33 | |
34 private GamepadDevice[] mGamepadDevices = new GamepadDevice[MAX_GAMEPADS]; | |
35 private InputManager mInputManager; | |
36 private int mAttachedToWindowCounter; | |
37 private boolean mIsGamepadAccessed; | |
38 | |
39 private GamepadList() {} | |
40 | |
41 private void initializeDevices() { | |
42 // Get list of all the attached input devices. | |
43 int[] deviceIds = mInputManager.getInputDeviceIds(); | |
44 for (int i = 0; i < deviceIds.length; i++) { | |
45 InputDevice inputDevice = InputDevice.getDevice(deviceIds[i]); | |
46 // Check for gamepad device | |
47 if (isGamepadDevice(inputDevice)) { | |
48 // Register a new gamepad device. | |
49 registerGamepad(inputDevice); | |
50 } | |
51 } | |
52 } | |
53 | |
54 /** | |
55 * Notifies the GamepadList that a {@link ContentView} is attached to a wind ow and it should | |
56 * prepare itself for gamepad input. It must be called before {@link onGener icMotionEvent} and | |
57 * {@link dispatchKeyEvent}. | |
58 */ | |
59 public static void onAttachedToWindow(Context context) { | |
60 assert ThreadUtils.runningOnUiThread(); | |
61 createInstance(); | |
62 sGamepadList.attachedToWindow(context); | |
63 } | |
64 | |
65 private void attachedToWindow(Context context) { | |
66 if (mAttachedToWindowCounter++ == 0) { | |
67 mInputManager = (InputManager) context.getSystemService(Context.INP UT_SERVICE); | |
Ted C
2014/04/16 23:36:53
one too many spaces after the =
SaurabhK
2014/04/18 14:51:57
On 2014/04/16 23:36:53, Ted C wrote:
Done.
| |
68 synchronized (mLock) { | |
69 initializeDevices(); | |
70 } | |
71 // Register an input device listener. | |
72 mInputManager.registerInputDeviceListener(this, null); | |
73 } | |
74 } | |
75 | |
76 /** | |
77 * Notifies the GamepadList that a {@link ContentView} is detached from it's window. | |
78 */ | |
79 public static void onDetachedFromWindow() { | |
80 assert ThreadUtils.runningOnUiThread(); | |
81 sGamepadList.detachedFromWindow(); | |
82 } | |
83 | |
84 private void detachedFromWindow() { | |
85 if (--mAttachedToWindowCounter == 0) { | |
86 synchronized (mLock) { | |
87 for (int i = 0; i < MAX_GAMEPADS; ++i) { | |
88 mGamepadDevices[i] = null; | |
89 } | |
90 } | |
91 mInputManager.unregisterInputDeviceListener(this); | |
92 mInputManager = null; | |
93 } | |
94 } | |
95 | |
96 // ------------------------------------------------------------ | |
97 | |
98 // Override InputDeviceListener methods | |
99 @Override | |
100 public void onInputDeviceChanged(int deviceId) { | |
101 } | |
102 | |
103 @Override | |
104 public void onInputDeviceRemoved(int deviceId) { | |
105 synchronized (mLock) { | |
106 unregisterGamepad(deviceId); | |
107 } | |
108 } | |
109 | |
110 @Override | |
111 public void onInputDeviceAdded(int deviceId) { | |
112 InputDevice inputDevice = InputDevice.getDevice(deviceId); | |
113 if (!isGamepadDevice(inputDevice)) return; | |
114 synchronized (mLock) { | |
115 registerGamepad(inputDevice); | |
116 } | |
117 } | |
118 | |
119 // ------------------------------------------------------------ | |
120 | |
121 private static void createInstance() { | |
122 if (sGamepadList == null) { | |
123 sGamepadList = new GamepadList(); | |
124 } | |
125 } | |
126 | |
127 private int getDeviceCount() { | |
128 int count = 0; | |
129 for (int i = 0; i < MAX_GAMEPADS; i++) { | |
130 if (getDevice(i) != null) { | |
131 count++; | |
132 } | |
133 } | |
134 return count; | |
135 } | |
136 | |
137 private boolean isDeviceConnected(int index) { | |
138 if (index < MAX_GAMEPADS && getDevice(index) != null) { | |
139 return true; | |
140 } | |
141 return false; | |
142 } | |
143 | |
144 private GamepadDevice getDeviceById(int deviceId) { | |
145 for (int i = 0; i < MAX_GAMEPADS; i++) { | |
146 GamepadDevice gamepad = mGamepadDevices[i]; | |
147 if (gamepad != null && gamepad.getId() == deviceId) { | |
148 return gamepad; | |
149 } | |
150 } | |
151 return null; | |
152 } | |
153 | |
154 private GamepadDevice getDevice(int index) { | |
155 // Maximum 4 Gamepads can be connected at a time starting at index zero. | |
156 assert index >= 0 && index < MAX_GAMEPADS; | |
157 return mGamepadDevices[index]; | |
158 } | |
159 | |
160 /** | |
161 * Handles key events from the gamepad devices. | |
162 * @return True if the event has been consumed. | |
163 */ | |
164 public static boolean dispatchKeyEvent(KeyEvent event) { | |
165 if (!isGamepadEvent(event)) return false; | |
166 return sGamepadList.handleKeyEvent(event); | |
167 } | |
168 | |
169 private boolean handleKeyEvent(KeyEvent event) { | |
170 synchronized (mLock) { | |
171 if (!mIsGamepadAccessed) return false; | |
172 GamepadDevice gamepad = getGamepadForEvent(event); | |
173 if (gamepad == null) return false; | |
174 return gamepad.handleKeyEvent(event); | |
175 } | |
176 } | |
177 | |
178 /** | |
179 * Handles motion events from the gamepad devices. | |
180 * @return True if the event has been consumed. | |
181 */ | |
182 public static boolean onGenericMotionEvent(MotionEvent event) { | |
183 if (!isGamepadEvent(event)) return false; | |
184 return sGamepadList.handleMotionEvent(event); | |
185 } | |
186 | |
187 private boolean handleMotionEvent(MotionEvent event) { | |
188 synchronized (mLock) { | |
189 if (!mIsGamepadAccessed) return false; | |
190 GamepadDevice gamepad = getGamepadForEvent(event); | |
191 if (gamepad == null) return false; | |
192 return gamepad.handleMotionEvent(event); | |
193 } | |
194 } | |
195 | |
196 private int getNextAvailableIndex() { | |
197 // When multiple gamepads are connected to a user agent, indices must be assigned on a | |
198 // first-come first-serve basis, starting at zero. If a gamepad is disco nnected, previously | |
199 // assigned indices must not be reassigned to gamepads that continue to be connected. | |
200 // However, if a gamepad is disconnected, and subsequently the same or a different | |
201 // gamepad is then connected, index entries must be reused. | |
202 | |
203 for (int i = 0; i < MAX_GAMEPADS; ++i) { | |
204 if (getDevice(i) == null) { | |
205 return i; | |
206 } | |
207 } | |
208 // Reached maximum gamepads limit. | |
209 return -1; | |
210 } | |
211 | |
212 private boolean registerGamepad(InputDevice inputDevice) { | |
213 int index = getNextAvailableIndex(); | |
214 if (index == -1) return false; // invalid index | |
215 | |
216 GamepadDevice gamepad = new GamepadDevice(index, inputDevice); | |
217 mGamepadDevices[index] = gamepad; | |
218 return true; | |
219 } | |
220 | |
221 private void unregisterGamepad(int deviceId) { | |
222 GamepadDevice gamepadDevice = getDeviceById(deviceId); | |
223 if (gamepadDevice == null) return; // Not a registered device. | |
224 int index = gamepadDevice.getIndex(); | |
225 mGamepadDevices[index] = null; | |
226 } | |
227 | |
228 private static boolean isGamepadDevice(InputDevice inputDevice) { | |
229 return ((inputDevice.getSources() & InputDevice.SOURCE_JOYSTICK) == | |
230 InputDevice.SOURCE_JOYSTICK); | |
231 } | |
232 | |
233 private GamepadDevice getGamepadForEvent(InputEvent event) { | |
234 int deviceId = event.getDeviceId(); | |
235 GamepadDevice gamepad = getDeviceById(deviceId); | |
236 return gamepad; | |
Ted C
2014/04/16 23:36:53
I think this is fine just as:
return getDeviceByI
SaurabhK
2014/04/18 14:51:57
On 2014/04/16 23:36:53, Ted C wrote:
Done.
| |
237 } | |
238 | |
239 /** | |
240 * @return True if the motion event corresponds to a gamepad event. | |
241 */ | |
242 public static boolean isGamepadEvent(MotionEvent event) { | |
243 return ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice .SOURCE_JOYSTICK); | |
244 } | |
245 | |
246 /** | |
247 * @return True if event's keycode corresponds to a gamepad key. | |
248 * Specific handling for dpad keys is required because | |
Ted C
2014/04/16 23:36:53
these two lines are implementation specific. They
SaurabhK
2014/04/18 14:51:57
On 2014/04/16 23:36:53, Ted C wrote:
Moved to swi
| |
249 * KeyEvent.isGamepadButton doesn't consider dpad keys. | |
250 */ | |
251 public static boolean isGamepadEvent(KeyEvent event) { | |
252 int keyCode = event.getKeyCode(); | |
253 switch (keyCode) { | |
254 case KeyEvent.KEYCODE_DPAD_UP: | |
255 case KeyEvent.KEYCODE_DPAD_DOWN: | |
256 case KeyEvent.KEYCODE_DPAD_LEFT: | |
257 case KeyEvent.KEYCODE_DPAD_RIGHT: | |
258 return true; | |
259 default: | |
260 return KeyEvent.isGamepadButton(keyCode); | |
261 } | |
262 } | |
263 | |
264 @CalledByNative | |
265 static void getGamepadData(long gamepads) { | |
Ted C
2014/04/16 23:36:53
I would call this updateGamepadData because it doe
SaurabhK
2014/04/18 14:51:57
On 2014/04/16 23:36:53, Ted C wrote:
Using webGam
| |
266 assert sGamepadList != null; | |
267 sGamepadList.grabGamepadData(gamepads); | |
268 } | |
269 | |
270 private void grabGamepadData(long gamepads) { | |
271 synchronized (mLock) { | |
272 for (int i = 0; i < MAX_GAMEPADS; i++) { | |
273 final GamepadDevice device = getDevice(i); | |
274 if (device != null) { | |
275 device.mapButtonsAndAxes(); | |
Ted C
2014/04/16 23:36:53
maybe updateButtonsAndAxesMapping
The verb "map"
SaurabhK
2014/04/18 14:51:57
On 2014/04/16 23:36:53, Ted C wrote:
Using update
| |
276 nativeSetGamepadData(gamepads, i, device.getMapping(), true, device.getName(), | |
277 device.getTimestamp(), device.getAxes(), device.getB uttons()); | |
278 } | |
279 else | |
Ted C
2014/04/16 23:36:53
the else needs to be on the line with the } from t
SaurabhK
2014/04/18 14:51:57
On 2014/04/16 23:36:53, Ted C wrote:
THanks for t
| |
280 nativeSetGamepadData(gamepads, i, false, false, null, 0, nul l, null); | |
281 } | |
282 } | |
283 } | |
284 | |
285 @CalledByNative | |
286 static void notifyForGamepadsAccess(boolean isAccessPaused) { | |
287 assert sGamepadList != null; | |
288 sGamepadList.setIsGamepadAccessed(!isAccessPaused); | |
289 } | |
290 | |
291 private void setIsGamepadAccessed(boolean isGamepadAccessed) { | |
292 synchronized (mLock) { | |
293 mIsGamepadAccessed = isGamepadAccessed; | |
294 if (isGamepadAccessed) { | |
295 for (int i = 0; i < MAX_GAMEPADS; i++) { | |
296 GamepadDevice gamepadDevice = getDevice(i); | |
297 if (gamepadDevice == null) continue; | |
298 gamepadDevice.clearData(); | |
299 } | |
300 } | |
301 } | |
302 } | |
303 | |
304 private native void nativeSetGamepadData(long gamepads, int index, boolean m apping, | |
305 boolean connected, String devicename, long timestamp, float[] axes, float[] buttons); | |
306 | |
307 } | |
OLD | NEW |