Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/input/GamepadList.java

Issue 133943002: Gamepad API support for chrome on android (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698