mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 20:47:44 +00:00
145 lines
5.2 KiB
Java
145 lines
5.2 KiB
Java
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
package org.mozilla.gecko.util;
|
|
|
|
import android.os.Build;
|
|
import android.view.InputDevice;
|
|
import android.view.KeyCharacterMap;
|
|
import android.view.KeyEvent;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
import android.widget.AdapterView;
|
|
import android.widget.ListView;
|
|
|
|
public final class GamepadUtils {
|
|
private static final int SONY_XPERIA_GAMEPAD_DEVICE_ID = 196611;
|
|
|
|
private static View.OnKeyListener sClickDispatcher;
|
|
private static float sDeadZoneThresholdOverride = 1e-2f;
|
|
|
|
private GamepadUtils() {
|
|
}
|
|
|
|
private static boolean isGamepadKey(KeyEvent event) {
|
|
if (Build.VERSION.SDK_INT >= 9) {
|
|
return (event.getSource() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static boolean isActionKey(KeyEvent event) {
|
|
return (isGamepadKey(event) && (event.getKeyCode() == KeyEvent.KEYCODE_BUTTON_A));
|
|
}
|
|
|
|
public static boolean isActionKeyDown(KeyEvent event) {
|
|
return isActionKey(event) && event.getAction() == KeyEvent.ACTION_DOWN;
|
|
}
|
|
|
|
public static boolean isBackKey(KeyEvent event) {
|
|
return (isGamepadKey(event) && (event.getKeyCode() == KeyEvent.KEYCODE_BUTTON_B));
|
|
}
|
|
|
|
public static void overrideDeadZoneThreshold(float threshold) {
|
|
sDeadZoneThresholdOverride = threshold;
|
|
}
|
|
|
|
public static boolean isValueInDeadZone(MotionEvent event, int axis) {
|
|
if (Build.VERSION.SDK_INT < 9) {
|
|
return false;
|
|
}
|
|
|
|
float threshold;
|
|
if (sDeadZoneThresholdOverride >= 0) {
|
|
threshold = sDeadZoneThresholdOverride;
|
|
} else {
|
|
InputDevice.MotionRange range = event.getDevice().getMotionRange(axis);
|
|
threshold = range.getFlat() + range.getFuzz();
|
|
}
|
|
float value = event.getAxisValue(axis);
|
|
return (Math.abs(value) < threshold);
|
|
}
|
|
|
|
public static boolean isPanningControl(MotionEvent event) {
|
|
if (Build.VERSION.SDK_INT < 12) {
|
|
return false;
|
|
}
|
|
if ((event.getSource() & InputDevice.SOURCE_CLASS_MASK) != InputDevice.SOURCE_CLASS_JOYSTICK) {
|
|
return false;
|
|
}
|
|
if (isValueInDeadZone(event, MotionEvent.AXIS_X)
|
|
&& isValueInDeadZone(event, MotionEvent.AXIS_Y)
|
|
&& isValueInDeadZone(event, MotionEvent.AXIS_Z)
|
|
&& isValueInDeadZone(event, MotionEvent.AXIS_RZ)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public static View.OnKeyListener getClickDispatcher() {
|
|
if (sClickDispatcher == null) {
|
|
sClickDispatcher = new View.OnKeyListener() {
|
|
@Override
|
|
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
|
if (isActionKeyDown(event)) {
|
|
return v.performClick();
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
}
|
|
return sClickDispatcher;
|
|
}
|
|
|
|
public static KeyEvent translateSonyXperiaGamepadKeys(int keyCode, KeyEvent event) {
|
|
// The cross and circle button mappings may be swapped in the different regions so
|
|
// determine if they are swapped so the proper key codes can be mapped to the keys
|
|
boolean areKeysSwapped = areSonyXperiaGamepadKeysSwapped();
|
|
|
|
// If a Sony Xperia, remap the cross and circle buttons to buttons
|
|
// A and B for the gamepad API
|
|
switch (keyCode) {
|
|
case KeyEvent.KEYCODE_BACK:
|
|
keyCode = (areKeysSwapped ? KeyEvent.KEYCODE_BUTTON_A : KeyEvent.KEYCODE_BUTTON_B);
|
|
break;
|
|
|
|
case KeyEvent.KEYCODE_DPAD_CENTER:
|
|
keyCode = (areKeysSwapped ? KeyEvent.KEYCODE_BUTTON_B : KeyEvent.KEYCODE_BUTTON_A);
|
|
break;
|
|
|
|
default:
|
|
return event;
|
|
}
|
|
|
|
return new KeyEvent(event.getAction(), keyCode);
|
|
}
|
|
|
|
public static boolean isSonyXperiaGamepadKeyEvent(KeyEvent event) {
|
|
return (event.getDeviceId() == SONY_XPERIA_GAMEPAD_DEVICE_ID &&
|
|
"Sony Ericsson".equals(Build.MANUFACTURER) &&
|
|
("R800".equals(Build.MODEL) || "R800i".equals(Build.MODEL)));
|
|
}
|
|
|
|
private static boolean areSonyXperiaGamepadKeysSwapped() {
|
|
// The cross and circle buttons on Sony Xperia phones are swapped
|
|
// in different regions
|
|
// http://developer.sonymobile.com/2011/02/13/xperia-play-game-keys/
|
|
final char DEFAULT_O_BUTTON_LABEL = 0x25CB;
|
|
|
|
boolean swapped = false;
|
|
int[] deviceIds = InputDevice.getDeviceIds();
|
|
|
|
for (int i= 0; deviceIds != null && i < deviceIds.length; i++) {
|
|
KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(deviceIds[i]);
|
|
if (keyCharacterMap != null && DEFAULT_O_BUTTON_LABEL ==
|
|
keyCharacterMap.getDisplayLabel(KeyEvent.KEYCODE_DPAD_CENTER)) {
|
|
swapped = true;
|
|
break;
|
|
}
|
|
}
|
|
return swapped;
|
|
}
|
|
}
|