mobile/android/base/util/GamepadUtils.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

michael@0 1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
michael@0 2 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 package org.mozilla.gecko.util;
michael@0 7
michael@0 8 import android.os.Build;
michael@0 9 import android.view.InputDevice;
michael@0 10 import android.view.KeyCharacterMap;
michael@0 11 import android.view.KeyEvent;
michael@0 12 import android.view.MotionEvent;
michael@0 13 import android.view.View;
michael@0 14 import android.widget.AdapterView;
michael@0 15 import android.widget.ListView;
michael@0 16
michael@0 17 public final class GamepadUtils {
michael@0 18 private static final int SONY_XPERIA_GAMEPAD_DEVICE_ID = 196611;
michael@0 19
michael@0 20 private static View.OnKeyListener sClickDispatcher;
michael@0 21 private static float sDeadZoneThresholdOverride = 1e-2f;
michael@0 22
michael@0 23 private GamepadUtils() {
michael@0 24 }
michael@0 25
michael@0 26 private static boolean isGamepadKey(KeyEvent event) {
michael@0 27 if (Build.VERSION.SDK_INT >= 9) {
michael@0 28 return (event.getSource() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD;
michael@0 29 }
michael@0 30 return false;
michael@0 31 }
michael@0 32
michael@0 33 public static boolean isActionKey(KeyEvent event) {
michael@0 34 return (isGamepadKey(event) && (event.getKeyCode() == KeyEvent.KEYCODE_BUTTON_A));
michael@0 35 }
michael@0 36
michael@0 37 public static boolean isActionKeyDown(KeyEvent event) {
michael@0 38 return isActionKey(event) && event.getAction() == KeyEvent.ACTION_DOWN;
michael@0 39 }
michael@0 40
michael@0 41 public static boolean isBackKey(KeyEvent event) {
michael@0 42 return (isGamepadKey(event) && (event.getKeyCode() == KeyEvent.KEYCODE_BUTTON_B));
michael@0 43 }
michael@0 44
michael@0 45 public static void overrideDeadZoneThreshold(float threshold) {
michael@0 46 sDeadZoneThresholdOverride = threshold;
michael@0 47 }
michael@0 48
michael@0 49 public static boolean isValueInDeadZone(MotionEvent event, int axis) {
michael@0 50 if (Build.VERSION.SDK_INT < 9) {
michael@0 51 return false;
michael@0 52 }
michael@0 53
michael@0 54 float threshold;
michael@0 55 if (sDeadZoneThresholdOverride >= 0) {
michael@0 56 threshold = sDeadZoneThresholdOverride;
michael@0 57 } else {
michael@0 58 InputDevice.MotionRange range = event.getDevice().getMotionRange(axis);
michael@0 59 threshold = range.getFlat() + range.getFuzz();
michael@0 60 }
michael@0 61 float value = event.getAxisValue(axis);
michael@0 62 return (Math.abs(value) < threshold);
michael@0 63 }
michael@0 64
michael@0 65 public static boolean isPanningControl(MotionEvent event) {
michael@0 66 if (Build.VERSION.SDK_INT < 12) {
michael@0 67 return false;
michael@0 68 }
michael@0 69 if ((event.getSource() & InputDevice.SOURCE_CLASS_MASK) != InputDevice.SOURCE_CLASS_JOYSTICK) {
michael@0 70 return false;
michael@0 71 }
michael@0 72 if (isValueInDeadZone(event, MotionEvent.AXIS_X)
michael@0 73 && isValueInDeadZone(event, MotionEvent.AXIS_Y)
michael@0 74 && isValueInDeadZone(event, MotionEvent.AXIS_Z)
michael@0 75 && isValueInDeadZone(event, MotionEvent.AXIS_RZ)) {
michael@0 76 return false;
michael@0 77 }
michael@0 78 return true;
michael@0 79 }
michael@0 80
michael@0 81 public static View.OnKeyListener getClickDispatcher() {
michael@0 82 if (sClickDispatcher == null) {
michael@0 83 sClickDispatcher = new View.OnKeyListener() {
michael@0 84 @Override
michael@0 85 public boolean onKey(View v, int keyCode, KeyEvent event) {
michael@0 86 if (isActionKeyDown(event)) {
michael@0 87 return v.performClick();
michael@0 88 }
michael@0 89 return false;
michael@0 90 }
michael@0 91 };
michael@0 92 }
michael@0 93 return sClickDispatcher;
michael@0 94 }
michael@0 95
michael@0 96 public static KeyEvent translateSonyXperiaGamepadKeys(int keyCode, KeyEvent event) {
michael@0 97 // The cross and circle button mappings may be swapped in the different regions so
michael@0 98 // determine if they are swapped so the proper key codes can be mapped to the keys
michael@0 99 boolean areKeysSwapped = areSonyXperiaGamepadKeysSwapped();
michael@0 100
michael@0 101 // If a Sony Xperia, remap the cross and circle buttons to buttons
michael@0 102 // A and B for the gamepad API
michael@0 103 switch (keyCode) {
michael@0 104 case KeyEvent.KEYCODE_BACK:
michael@0 105 keyCode = (areKeysSwapped ? KeyEvent.KEYCODE_BUTTON_A : KeyEvent.KEYCODE_BUTTON_B);
michael@0 106 break;
michael@0 107
michael@0 108 case KeyEvent.KEYCODE_DPAD_CENTER:
michael@0 109 keyCode = (areKeysSwapped ? KeyEvent.KEYCODE_BUTTON_B : KeyEvent.KEYCODE_BUTTON_A);
michael@0 110 break;
michael@0 111
michael@0 112 default:
michael@0 113 return event;
michael@0 114 }
michael@0 115
michael@0 116 return new KeyEvent(event.getAction(), keyCode);
michael@0 117 }
michael@0 118
michael@0 119 public static boolean isSonyXperiaGamepadKeyEvent(KeyEvent event) {
michael@0 120 return (event.getDeviceId() == SONY_XPERIA_GAMEPAD_DEVICE_ID &&
michael@0 121 "Sony Ericsson".equals(Build.MANUFACTURER) &&
michael@0 122 ("R800".equals(Build.MODEL) || "R800i".equals(Build.MODEL)));
michael@0 123 }
michael@0 124
michael@0 125 private static boolean areSonyXperiaGamepadKeysSwapped() {
michael@0 126 // The cross and circle buttons on Sony Xperia phones are swapped
michael@0 127 // in different regions
michael@0 128 // http://developer.sonymobile.com/2011/02/13/xperia-play-game-keys/
michael@0 129 final char DEFAULT_O_BUTTON_LABEL = 0x25CB;
michael@0 130
michael@0 131 boolean swapped = false;
michael@0 132 int[] deviceIds = InputDevice.getDeviceIds();
michael@0 133
michael@0 134 for (int i= 0; deviceIds != null && i < deviceIds.length; i++) {
michael@0 135 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(deviceIds[i]);
michael@0 136 if (keyCharacterMap != null && DEFAULT_O_BUTTON_LABEL ==
michael@0 137 keyCharacterMap.getDisplayLabel(KeyEvent.KEYCODE_DPAD_CENTER)) {
michael@0 138 swapped = true;
michael@0 139 break;
michael@0 140 }
michael@0 141 }
michael@0 142 return swapped;
michael@0 143 }
michael@0 144 }

mercurial