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

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

Issue 2081583002: Migrating majority of gamepad from content/browser/ to device/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Final tweaks Created 4 years, 5 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.annotation.SuppressLint;
8 import android.content.Context;
9 import android.hardware.input.InputManager;
10 import android.hardware.input.InputManager.InputDeviceListener;
11 import android.view.InputDevice;
12 import android.view.InputEvent;
13 import android.view.KeyEvent;
14 import android.view.MotionEvent;
15
16 import org.chromium.base.ThreadUtils;
17 import org.chromium.base.annotations.CalledByNative;
18 import org.chromium.base.annotations.JNINamespace;
19 import org.chromium.content.browser.ContentView;
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 @JNINamespace("content")
28 public class GamepadList {
29 private static final int MAX_GAMEPADS = 4;
30
31 private final Object mLock = new Object();
32
33 private final GamepadDevice[] mGamepadDevices = new GamepadDevice[MAX_GAMEPA DS];
34 private InputManager mInputManager;
35 private int mAttachedToWindowCounter;
36 private boolean mIsGamepadAPIActive;
37 private InputDeviceListener mInputDeviceListener;
38
39 private GamepadList() {
40 mInputDeviceListener = new InputDeviceListener() {
41 // Override InputDeviceListener methods
42 @Override
43 public void onInputDeviceChanged(int deviceId) {
44 onInputDeviceChangedImpl(deviceId);
45 }
46
47 @Override
48 public void onInputDeviceRemoved(int deviceId) {
49 onInputDeviceRemovedImpl(deviceId);
50 }
51
52 @Override
53 public void onInputDeviceAdded(int deviceId) {
54 onInputDeviceAddedImpl(deviceId);
55 }
56 };
57 }
58
59 private void initializeDevices() {
60 // Get list of all the attached input devices.
61 int[] deviceIds = mInputManager.getInputDeviceIds();
62 for (int i = 0; i < deviceIds.length; i++) {
63 InputDevice inputDevice = InputDevice.getDevice(deviceIds[i]);
64 // Check for gamepad device
65 if (isGamepadDevice(inputDevice)) {
66 // Register a new gamepad device.
67 registerGamepad(inputDevice);
68 }
69 }
70 }
71
72 /**
73 * Notifies the GamepadList that a {@link ContentView} is attached to a wind ow and it should
74 * prepare itself for gamepad input. It must be called before {@link onGener icMotionEvent} and
75 * {@link dispatchKeyEvent}.
76 */
77 public static void onAttachedToWindow(Context context) {
78 assert ThreadUtils.runningOnUiThread();
79 getInstance().attachedToWindow(context);
80 }
81
82 private void attachedToWindow(Context context) {
83 if (mAttachedToWindowCounter++ == 0) {
84 mInputManager = (InputManager) context.getSystemService(Context.INPU T_SERVICE);
85 synchronized (mLock) {
86 initializeDevices();
87 }
88 // Register an input device listener.
89 mInputManager.registerInputDeviceListener(mInputDeviceListener, null );
90 }
91 }
92
93 /**
94 * Notifies the GamepadList that a {@link ContentView} is detached from it's window.
95 */
96 @SuppressLint("MissingSuperCall")
97 public static void onDetachedFromWindow() {
98 assert ThreadUtils.runningOnUiThread();
99 getInstance().detachedFromWindow();
100 }
101
102 private void detachedFromWindow() {
103 if (--mAttachedToWindowCounter == 0) {
104 synchronized (mLock) {
105 for (int i = 0; i < MAX_GAMEPADS; ++i) {
106 mGamepadDevices[i] = null;
107 }
108 }
109 mInputManager.unregisterInputDeviceListener(mInputDeviceListener);
110 mInputManager = null;
111 }
112 }
113
114 // ------------------------------------------------------------
115
116 private void onInputDeviceChangedImpl(int deviceId) {}
117
118 private void onInputDeviceRemovedImpl(int deviceId) {
119 synchronized (mLock) {
120 unregisterGamepad(deviceId);
121 }
122 }
123
124 private void onInputDeviceAddedImpl(int deviceId) {
125 InputDevice inputDevice = InputDevice.getDevice(deviceId);
126 if (!isGamepadDevice(inputDevice)) return;
127 synchronized (mLock) {
128 registerGamepad(inputDevice);
129 }
130 }
131
132 // ------------------------------------------------------------
133
134 private static GamepadList getInstance() {
135 return LazyHolder.INSTANCE;
136 }
137
138 private int getDeviceCount() {
139 int count = 0;
140 for (int i = 0; i < MAX_GAMEPADS; i++) {
141 if (getDevice(i) != null) {
142 count++;
143 }
144 }
145 return count;
146 }
147
148 private boolean isDeviceConnected(int index) {
149 if (index < MAX_GAMEPADS && getDevice(index) != null) {
150 return true;
151 }
152 return false;
153 }
154
155 private GamepadDevice getDeviceById(int deviceId) {
156 for (int i = 0; i < MAX_GAMEPADS; i++) {
157 GamepadDevice gamepad = mGamepadDevices[i];
158 if (gamepad != null && gamepad.getId() == deviceId) {
159 return gamepad;
160 }
161 }
162 return null;
163 }
164
165 private GamepadDevice getDevice(int index) {
166 // Maximum 4 Gamepads can be connected at a time starting at index zero.
167 assert index >= 0 && index < MAX_GAMEPADS;
168 return mGamepadDevices[index];
169 }
170
171 /**
172 * Handles key events from the gamepad devices.
173 * @return True if the event has been consumed.
174 */
175 public static boolean dispatchKeyEvent(KeyEvent event) {
176 if (!isGamepadEvent(event)) return false;
177 return getInstance().handleKeyEvent(event);
178 }
179
180 private boolean handleKeyEvent(KeyEvent event) {
181 synchronized (mLock) {
182 if (!mIsGamepadAPIActive) return false;
183 GamepadDevice gamepad = getGamepadForEvent(event);
184 if (gamepad == null) return false;
185 return gamepad.handleKeyEvent(event);
186 }
187 }
188
189 /**
190 * Handles motion events from the gamepad devices.
191 * @return True if the event has been consumed.
192 */
193 public static boolean onGenericMotionEvent(MotionEvent event) {
194 if (!isGamepadEvent(event)) return false;
195 return getInstance().handleMotionEvent(event);
196 }
197
198 private boolean handleMotionEvent(MotionEvent event) {
199 synchronized (mLock) {
200 if (!mIsGamepadAPIActive) return false;
201 GamepadDevice gamepad = getGamepadForEvent(event);
202 if (gamepad == null) return false;
203 return gamepad.handleMotionEvent(event);
204 }
205 }
206
207 private int getNextAvailableIndex() {
208 // When multiple gamepads are connected to a user agent, indices must be assigned on a
209 // first-come first-serve basis, starting at zero. If a gamepad is disco nnected, previously
210 // assigned indices must not be reassigned to gamepads that continue to be connected.
211 // However, if a gamepad is disconnected, and subsequently the same or a different
212 // gamepad is then connected, index entries must be reused.
213
214 for (int i = 0; i < MAX_GAMEPADS; ++i) {
215 if (getDevice(i) == null) {
216 return i;
217 }
218 }
219 // Reached maximum gamepads limit.
220 return -1;
221 }
222
223 private boolean registerGamepad(InputDevice inputDevice) {
224 int index = getNextAvailableIndex();
225 if (index == -1) return false; // invalid index
226
227 GamepadDevice gamepad = new GamepadDevice(index, inputDevice);
228 mGamepadDevices[index] = gamepad;
229 return true;
230 }
231
232 private void unregisterGamepad(int deviceId) {
233 GamepadDevice gamepadDevice = getDeviceById(deviceId);
234 if (gamepadDevice == null) return; // Not a registered device.
235 int index = gamepadDevice.getIndex();
236 mGamepadDevices[index] = null;
237 }
238
239 private static boolean isGamepadDevice(InputDevice inputDevice) {
240 if (inputDevice == null) return false;
241 return ((inputDevice.getSources()
242 & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK);
243 }
244
245 private GamepadDevice getGamepadForEvent(InputEvent event) {
246 return getDeviceById(event.getDeviceId());
247 }
248
249 /**
250 * @return True if HTML5 gamepad API is active.
251 */
252 public static boolean isGamepadAPIActive() {
253 return getInstance().mIsGamepadAPIActive;
254 }
255
256 /**
257 * @return True if the motion event corresponds to a gamepad event.
258 */
259 public static boolean isGamepadEvent(MotionEvent event) {
260 return ((event.getSource() & InputDevice.SOURCE_JOYSTICK) == InputDevice .SOURCE_JOYSTICK);
261 }
262
263 /**
264 * @return True if event's keycode corresponds to a gamepad key.
265 */
266 public static boolean isGamepadEvent(KeyEvent event) {
267 int keyCode = event.getKeyCode();
268 switch (keyCode) {
269 // Specific handling for dpad keys is required because
270 // KeyEvent.isGamepadButton doesn't consider dpad keys.
271 case KeyEvent.KEYCODE_DPAD_UP:
272 case KeyEvent.KEYCODE_DPAD_DOWN:
273 case KeyEvent.KEYCODE_DPAD_LEFT:
274 case KeyEvent.KEYCODE_DPAD_RIGHT:
275 return true;
276 default:
277 return KeyEvent.isGamepadButton(keyCode);
278 }
279 }
280
281 @CalledByNative
282 static void updateGamepadData(long webGamepadsPtr) {
283 getInstance().grabGamepadData(webGamepadsPtr);
284 }
285
286 private void grabGamepadData(long webGamepadsPtr) {
287 synchronized (mLock) {
288 for (int i = 0; i < MAX_GAMEPADS; i++) {
289 final GamepadDevice device = getDevice(i);
290 if (device != null) {
291 device.updateButtonsAndAxesMapping();
292 nativeSetGamepadData(webGamepadsPtr, i, device.isStandardGam epad(), true,
293 device.getName(), device.getTimestamp(), device.getA xes(),
294 device.getButtons());
295 } else {
296 nativeSetGamepadData(webGamepadsPtr, i, false, false, null, 0, null, null);
297 }
298 }
299 }
300 }
301
302 @CalledByNative
303 static void setGamepadAPIActive(boolean isActive) {
304 getInstance().setIsGamepadActive(isActive);
305 }
306
307 private void setIsGamepadActive(boolean isGamepadActive) {
308 synchronized (mLock) {
309 mIsGamepadAPIActive = isGamepadActive;
310 if (isGamepadActive) {
311 for (int i = 0; i < MAX_GAMEPADS; i++) {
312 GamepadDevice gamepadDevice = getDevice(i);
313 if (gamepadDevice == null) continue;
314 gamepadDevice.clearData();
315 }
316 }
317 }
318 }
319
320 private native void nativeSetGamepadData(long webGamepadsPtr, int index, boo lean mapping,
321 boolean connected, String devicename, long timestamp, float[] axes, float[] buttons);
322
323 private static class LazyHolder {
324 private static final GamepadList INSTANCE = new GamepadList();
325 }
326
327 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698