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

Unified Diff: content/public/android/java/src/org/chromium/content/browser/input/GamepadDataMapper.java

Issue 165483003: Gamepad API for Android (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: updated Created 6 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/src/org/chromium/content/browser/input/GamepadDataMapper.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/GamepadDataMapper.java b/content/public/android/java/src/org/chromium/content/browser/input/GamepadDataMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd3a863e7aff531249f716362569ad9660469f71
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/input/GamepadDataMapper.java
@@ -0,0 +1,234 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.content.browser.input;
+
+import android.util.SparseArray;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import org.chromium.base.JNINamespace;
+
+/**
+ * Device specific input data converter for Gamepad API.
+ * Implemented per device by subclasses.
+ */
+@JNINamespace("content")
+abstract class GamepadDataMapper {
+ protected static final String PS3_SIXAXIS_DEVICE_NAME = "Sony PLAYSTATION(R)3 Controller";
+
+ public abstract WebGamepadData map(SparseArray<Float> axes, SparseArray<Boolean> buttons);
+
+ // Factory method.
+ public static GamepadDataMapper createDataMapper(String deviceName) {
+ if (deviceName.equals(PS3_SIXAXIS_DEVICE_NAME))
+ return new PS3SixAxisGamepadDataMapper();
+
+ return new GenericGamepadDataMapper(deviceName);
+ }
+
+ // CanonicalButtonIndex and CanonicalAxisIndex mirror the same enums
+ // from C++ (in gamepad_standard_mappings.h).
+
+ protected enum CanonicalButtonIndex {
bulach 2014/03/05 12:34:39 enums are a no-go in android :( http://developer.a
kbalazs 2014/03/05 19:56:11 Should I keep the naming scheme kButtonWhatever? I
+ BUTTON_PRIMARY,
+ BUTTON_SECONDARY,
+ BUTTON_TERTIARY,
+ BUTTON_QUATERNARY,
+ BUTTON_LEFT_SHOULDER,
+ BUTTON_RIGHT_SHOULDER,
+ BUTTON_LEFT_TRIGGER,
+ BUTTON_RIGHT_TRIGGER,
+ BUTTON_BACK_SELECT,
+ BUTTON_START,
+ BUTTON_LEFT_THUMBSTICK,
+ BUTTON_RIGHT_THUMBSTICK,
+ BUTTON_DPAD_UP,
+ BUTTON_DPAD_DOWN,
+ BUTTON_DPAD_LEFT,
+ BUTTON_DPAD_RIGHT,
+ BUTTON_META,
+ NUM_BUTTONS;
+ };
+
+ protected static final int NumberOfCanonicalButtons =
+ CanonicalButtonIndex.NUM_BUTTONS.ordinal();
+
+ protected enum CanonicalAxisIndex {
+ AXIS_LEFT_STICK_X,
+ AXIS_LEFT_STICK_Y,
+ AXIS_RIGHT_STICK_X,
+ AXIS_RIGHT_STICK_Y,
+ NUM_AXES
+ };
+
+ protected static final int NumberOfCanonicalAxes =
+ CanonicalAxisIndex.NUM_AXES.ordinal();
+
+ protected static float axisValue(Float f) { return f == null ? 0 : f.floatValue(); }
+ protected static float buttonValue(Boolean b) { return (b == null || !b) ? 0 : 1; }
+
+ protected static WebGamepadData createWebGamepadData() {
+ WebGamepadData data = new WebGamepadData();
+ data.axes = new float[NumberOfCanonicalAxes];
+ data.buttons = new float[NumberOfCanonicalButtons];
+ return data;
+ }
+
+ protected static void mapCommonXYAxes(WebGamepadData data, SparseArray<Float> axes) {
+ Float x = (Float) axes.get(MotionEvent.AXIS_X);
+ Float y = (Float) axes.get(MotionEvent.AXIS_Y);
+ data.axes[CanonicalAxisIndex.AXIS_LEFT_STICK_X.ordinal()] = axisValue(x);
+ data.axes[CanonicalAxisIndex.AXIS_LEFT_STICK_Y.ordinal()] = axisValue(y);
+ }
+
+ protected static void mapCommonTriggerAxes(WebGamepadData data, SparseArray<Float> axes) {
+ Float lTrigger = (Float) axes.get(MotionEvent.AXIS_LTRIGGER);
+ Float rTrigger = (Float) axes.get(MotionEvent.AXIS_RTRIGGER);
+ data.buttons[CanonicalButtonIndex.BUTTON_LEFT_SHOULDER.ordinal()] = axisValue(lTrigger);
+ data.buttons[CanonicalButtonIndex.BUTTON_RIGHT_SHOULDER.ordinal()] = axisValue(rTrigger);
+ }
+
+ protected static void mapCommonTriggerButtons(
+ WebGamepadData data, SparseArray<Boolean> buttons) {
+ Boolean l1 = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_L1);
+ Boolean r1 = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_R1);
+ data.buttons[CanonicalButtonIndex.BUTTON_LEFT_TRIGGER.ordinal()] = buttonValue(l1);
+ data.buttons[CanonicalButtonIndex.BUTTON_RIGHT_TRIGGER.ordinal()] = buttonValue(r1);
+ }
+
+ protected static void mapCommonThumbstickButtons(
+ WebGamepadData data, SparseArray<Boolean> buttons) {
+ Boolean thumbL = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_THUMBL);
+ Boolean thumbR = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_THUMBR);
+ data.buttons[CanonicalButtonIndex.BUTTON_LEFT_THUMBSTICK.ordinal()] = buttonValue(thumbL);
+ data.buttons[CanonicalButtonIndex.BUTTON_RIGHT_THUMBSTICK.ordinal()] = buttonValue(thumbR);
+ }
+
+ protected static void mapCommonStartSelectButtons(
+ WebGamepadData data, SparseArray<Boolean> buttons) {
+ Boolean select = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_SELECT);
+ Boolean start = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_START);
+ data.buttons[CanonicalButtonIndex.BUTTON_BACK_SELECT.ordinal()] = buttonValue(select);
+ data.buttons[CanonicalButtonIndex.BUTTON_START.ordinal()] = buttonValue(start);
+ }
+
+ protected static void mapCommonDpadButtons(
+ WebGamepadData data, SparseArray<Boolean> buttons) {
+ Boolean dpadDown = (Boolean) buttons.get(KeyEvent.KEYCODE_DPAD_DOWN);
+ Boolean dpadUp = (Boolean) buttons.get(KeyEvent.KEYCODE_DPAD_UP);
+ Boolean dpadLeft = (Boolean) buttons.get(KeyEvent.KEYCODE_DPAD_LEFT);
+ Boolean dpadRight = (Boolean) buttons.get(KeyEvent.KEYCODE_DPAD_RIGHT);
+ data.buttons[CanonicalButtonIndex.BUTTON_DPAD_DOWN.ordinal()] = buttonValue(dpadDown);
+ data.buttons[CanonicalButtonIndex.BUTTON_DPAD_UP.ordinal()] = buttonValue(dpadUp);
+ data.buttons[CanonicalButtonIndex.BUTTON_DPAD_LEFT.ordinal()] = buttonValue(dpadLeft);
+ data.buttons[CanonicalButtonIndex.BUTTON_DPAD_RIGHT.ordinal()] = buttonValue(dpadRight);
+ }
+
+ protected static void mapCommonXYABButtons(
+ WebGamepadData data, SparseArray<Boolean> buttons) {
+ Boolean bA = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_A);
+ Boolean bB = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_B);
+ Boolean bX = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_X);
+ Boolean bY = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_Y);
+ data.buttons[CanonicalButtonIndex.BUTTON_PRIMARY.ordinal()] = buttonValue(bA);
+ data.buttons[CanonicalButtonIndex.BUTTON_SECONDARY.ordinal()] = buttonValue(bB);
+ data.buttons[CanonicalButtonIndex.BUTTON_TERTIARY.ordinal()] = buttonValue(bX);
+ data.buttons[CanonicalButtonIndex.BUTTON_QUATERNARY.ordinal()] = buttonValue(bY);
+ }
+}
+
+// This is a last resort if we find a device that we don't know about.
+// The Android API is general enough that this can be better than nothing
+// but we should not really rely on this.
+class GenericGamepadDataMapper extends GamepadDataMapper {
+ private final String mDeviceName;
+
+ GenericGamepadDataMapper(String deviceName) {
+ mDeviceName = deviceName;
+ }
+
+ // Find something for right stick x and y. If there is even more axes, map them to
+ // non-canonical positions.
+ private static void mapRightAndExtraSticks(WebGamepadData data, SparseArray<Float> axes) {
+ int position = CanonicalAxisIndex.AXIS_RIGHT_STICK_X.ordinal();
+ // position + 1 is AXIS_RIGHT_STICK_Y.
+ Float x = (Float) axes.get(MotionEvent.AXIS_RX);
+ Float y = (Float) axes.get(MotionEvent.AXIS_RY);
+ if (x != null || y != null) {
+ data.axes[position++] = axisValue(x);
+ data.axes[position++] = axisValue(y);
+ }
+ x = (Float) axes.get(MotionEvent.AXIS_Z);
+ y = (Float) axes.get(MotionEvent.AXIS_RZ);
+ if (x != null || y != null) {
+ data.axes[position++] = axisValue(x);
+ data.axes[position++] = axisValue(y);
+ }
+ x = (Float) axes.get(MotionEvent.AXIS_HAT_X);
+ y = (Float) axes.get(MotionEvent.AXIS_HAT_Y);
+ if (x != null || y != null) {
+ data.axes[position++] = axisValue(x);
+ data.axes[position++] = axisValue(y);
+ }
+ }
+
+ public WebGamepadData map(SparseArray<Float> axes, SparseArray<Boolean> buttons) {
+ WebGamepadData data = createWebGamepadData();
+ data.id = mDeviceName + " (STANDARD_GAMEPAD)";
+ data.mapping = "standard";
+ mapCommonXYAxes(data, axes);
+ mapRightAndExtraSticks(data, axes);
+ mapCommonTriggerAxes(data, axes);
+ mapCommonXYABButtons(data, buttons);
+ mapCommonTriggerButtons(data, buttons);
+ mapCommonThumbstickButtons(data, buttons);
+ mapCommonStartSelectButtons(data, buttons);
+ mapCommonDpadButtons(data, buttons);
+
+ // TODO(b.kelemen): meta is missing.
+
+ return data;
+ }
+}
+
+class PS3SixAxisGamepadDataMapper extends GamepadDataMapper {
+ public WebGamepadData map(SparseArray<Float> axes, SparseArray<Boolean> buttons) {
+ WebGamepadData data = createWebGamepadData();
+ data.id = PS3_SIXAXIS_DEVICE_NAME + " (STANDARD_GAMEPAD)";
+ data.mapping = "standard";
+
+ mapCommonXYAxes(data, axes);
+
+ Float z = (Float) axes.get(MotionEvent.AXIS_Z);
+ Float rz = (Float) axes.get(MotionEvent.AXIS_RZ);
+ data.axes[CanonicalAxisIndex.AXIS_RIGHT_STICK_X.ordinal()] = axisValue(z);
+ data.axes[CanonicalAxisIndex.AXIS_RIGHT_STICK_Y.ordinal()] = axisValue(rz);
+
+ mapCommonTriggerAxes(data, axes);
+
+ Boolean bA = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_A);
+ Boolean bB = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_B);
+ Boolean bX = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_X);
+ Boolean bY = (Boolean) buttons.get(KeyEvent.KEYCODE_BUTTON_Y);
+ data.buttons[CanonicalButtonIndex.BUTTON_PRIMARY.ordinal()] = buttonValue(bX);
+ data.buttons[CanonicalButtonIndex.BUTTON_SECONDARY.ordinal()] = buttonValue(bY);
+ data.buttons[CanonicalButtonIndex.BUTTON_TERTIARY.ordinal()] = buttonValue(bA);
+ data.buttons[CanonicalButtonIndex.BUTTON_QUATERNARY.ordinal()] = buttonValue(bB);
+
+ mapCommonTriggerButtons(data, buttons);
+ mapCommonThumbstickButtons(data, buttons);
+ mapCommonStartSelectButtons(data, buttons);
+ mapCommonDpadButtons(data, buttons);
+
+ // TODO(b.kelemen): PS button is missing. Looks like it is swallowed by Android
+ // but probably there is a way to configure otherwise and in this case we should
+ // handle it.
+
+ return data;
+ }
+}
+
+// TODO(b.kelemen): add more implementations. It would be nice to support at least those that are
+// supported on Linux.

Powered by Google App Engine
This is Rietveld 408576698