mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-04 23:22:48 +02:00
Fix JoyCon mappings on Android
This commit is contained in:
@@ -1478,14 +1478,16 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
// Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
|
||||
// SOURCE_JOYSTICK, while its key events arrive from the keyboard source
|
||||
// So, retrieve the device itself and check all of its sources
|
||||
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
|
||||
//
|
||||
// Echo events (event.getRepeatCount() > 0) should be ignored
|
||||
if (SDLControllerManager.isDeviceSDLJoystick(deviceId) && event.getRepeatCount() == 0) {
|
||||
// Note that we process events with specific key codes here
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||
if (SDLControllerManager.onNativePadDown(deviceId, keyCode)) {
|
||||
if (SDLControllerManager.onNativePadDown(deviceId, keyCode, event.getScanCode())) {
|
||||
return true;
|
||||
}
|
||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||
if (SDLControllerManager.onNativePadUp(deviceId, keyCode)) {
|
||||
if (SDLControllerManager.onNativePadUp(deviceId, keyCode, event.getScanCode())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ public class SDLControllerManager
|
||||
static native void nativeRemoveJoystick(int device_id);
|
||||
static native void nativeAddHaptic(int device_id, String name);
|
||||
static native void nativeRemoveHaptic(int device_id);
|
||||
static public native boolean onNativePadDown(int device_id, int keycode);
|
||||
static public native boolean onNativePadUp(int device_id, int keycode);
|
||||
static public native boolean onNativePadDown(int device_id, int keycode, int scancode);
|
||||
static public native boolean onNativePadUp(int device_id, int keycode, int scancode);
|
||||
static native void onNativeJoy(int device_id, int axis,
|
||||
float value);
|
||||
static native void onNativeHat(int device_id, int hat_id,
|
||||
|
||||
@@ -298,11 +298,11 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI)(
|
||||
|
||||
JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint keycode);
|
||||
jint device_id, jint keycode, jint scancode);
|
||||
|
||||
JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint keycode);
|
||||
jint device_id, jint keycode, jint scancode);
|
||||
|
||||
JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
@@ -336,8 +336,8 @@ JNIEXPORT void JNICALL SDL_JAVA_CONTROLLER_INTERFACE(nativeRemoveHaptic)(
|
||||
|
||||
static JNINativeMethod SDLControllerManager_tab[] = {
|
||||
{ "nativeSetupJNI", "()V", SDL_JAVA_CONTROLLER_INTERFACE(nativeSetupJNI) },
|
||||
{ "onNativePadDown", "(II)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown) },
|
||||
{ "onNativePadUp", "(II)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp) },
|
||||
{ "onNativePadDown", "(III)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown) },
|
||||
{ "onNativePadUp", "(III)Z", SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp) },
|
||||
{ "onNativeJoy", "(IIF)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoy) },
|
||||
{ "onNativeHat", "(IIII)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeHat) },
|
||||
{ "onNativeJoySensor", "(IIJFFF)V", SDL_JAVA_CONTROLLER_INTERFACE(onNativeJoySensor) },
|
||||
@@ -1159,10 +1159,10 @@ SDL_JAVA_AUDIO_INTERFACE(nativeRemoveAudioDevice)(JNIEnv *env, jclass jcls, jboo
|
||||
// Paddown
|
||||
JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint keycode)
|
||||
jint device_id, jint keycode, jint scancode)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_ANDROID
|
||||
return Android_OnPadDown(device_id, keycode);
|
||||
return Android_OnPadDown(device_id, keycode, scancode);
|
||||
#else
|
||||
return false;
|
||||
#endif // SDL_JOYSTICK_ANDROID
|
||||
@@ -1171,10 +1171,10 @@ JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadDown)(
|
||||
// Padup
|
||||
JNIEXPORT jboolean JNICALL SDL_JAVA_CONTROLLER_INTERFACE(onNativePadUp)(
|
||||
JNIEnv *env, jclass jcls,
|
||||
jint device_id, jint keycode)
|
||||
jint device_id, jint keycode, jint scancode)
|
||||
{
|
||||
#ifdef SDL_JOYSTICK_ANDROID
|
||||
return Android_OnPadUp(device_id, keycode);
|
||||
return Android_OnPadUp(device_id, keycode, scancode);
|
||||
#else
|
||||
return false;
|
||||
#endif // SDL_JOYSTICK_ANDROID
|
||||
|
||||
@@ -713,91 +713,116 @@ static GamepadMapping_t *SDL_CreateMappingForAndroidGamepad(SDL_GUID guid)
|
||||
char mapping_string[1024];
|
||||
int button_mask;
|
||||
int axis_mask;
|
||||
Uint16 vendor, product;
|
||||
|
||||
SDL_strlcpy(mapping_string, "none,", sizeof(mapping_string));
|
||||
|
||||
button_mask = SDL_Swap16LE(*(Uint16 *)(&guid.data[sizeof(guid.data) - 4]));
|
||||
axis_mask = SDL_Swap16LE(*(Uint16 *)(&guid.data[sizeof(guid.data) - 2]));
|
||||
if (!button_mask && !axis_mask) {
|
||||
// Accelerometer, shouldn't have a gamepad mapping
|
||||
return NULL;
|
||||
}
|
||||
if (!(button_mask & face_button_mask)) {
|
||||
// We don't know what buttons or axes are supported, don't make up a mapping
|
||||
return NULL;
|
||||
}
|
||||
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, NULL, NULL);
|
||||
if (vendor == USB_VENDOR_NINTENDO) {
|
||||
if (product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT || product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_RIGHT) {
|
||||
// FIXME: Should we have a separate hint for non-HIDAPI JoyCon handling?
|
||||
// Android doesn't report JoyCon SL/SR presses for some reason, so no horizontal triggers/vertical paddles
|
||||
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS, false)) {
|
||||
// Vertical mode
|
||||
if (product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) {
|
||||
SDL_strlcat(mapping_string, "Nintendo Switch Joy-Con (L),back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b15,leftx:a0,lefty:a1,misc1:b18,", sizeof(mapping_string));
|
||||
} else {
|
||||
SDL_strlcat(mapping_string, "Nintendo Switch Joy-Con (R),a:b0,b:b1,guide:b5,rightshoulder:b10,rightstick:b8,righttrigger:b16,rightx:a0,righty:a1,start:b6,x:b3,y:b2,", sizeof(mapping_string));
|
||||
}
|
||||
} else {
|
||||
// Mini gamepad mode
|
||||
if (product == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT) {
|
||||
SDL_strlcat(mapping_string, "Nintendo Switch Joy-Con (L),a:b13,b:b12,guide:b18,leftstick:b7,leftx:a1,lefty:a0~,start:b4,x:b11,y:b14,paddle2:b9,paddle4:b15,", sizeof(mapping_string));
|
||||
} else {
|
||||
SDL_strlcat(mapping_string, "Nintendo Switch Joy-Con (R),a:b1,b:b2,guide:b5,leftstick:b8,leftx:a1~,lefty:a0,start:b6,x:b0,y:b3,paddle1:b10,paddle3:b16,", sizeof(mapping_string));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
button_mask = SDL_Swap16LE(*(Uint16 *)(&guid.data[sizeof(guid.data) - 4]));
|
||||
axis_mask = SDL_Swap16LE(*(Uint16 *)(&guid.data[sizeof(guid.data) - 2]));
|
||||
if (!button_mask && !axis_mask) {
|
||||
// Accelerometer, shouldn't have a gamepad mapping
|
||||
return NULL;
|
||||
}
|
||||
if (!(button_mask & face_button_mask)) {
|
||||
// We don't know what buttons or axes are supported, don't make up a mapping
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_strlcpy(mapping_string, "none,*,", sizeof(mapping_string));
|
||||
SDL_strlcpy(mapping_string, "*,", sizeof(mapping_string));
|
||||
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_SOUTH)) {
|
||||
SDL_strlcat(mapping_string, "a:b0,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_EAST)) {
|
||||
SDL_strlcat(mapping_string, "b:b1,", sizeof(mapping_string));
|
||||
} else if (button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) {
|
||||
// Use the back button as "B" for easy UI navigation with TV remotes
|
||||
SDL_strlcat(mapping_string, "b:b4,", sizeof(mapping_string));
|
||||
button_mask &= ~(1 << SDL_GAMEPAD_BUTTON_BACK);
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_WEST)) {
|
||||
SDL_strlcat(mapping_string, "x:b2,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_NORTH)) {
|
||||
SDL_strlcat(mapping_string, "y:b3,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) {
|
||||
SDL_strlcat(mapping_string, "back:b4,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_GUIDE)) {
|
||||
// The guide button generally isn't functional (or acts as a home button) on most Android gamepads before Android 11
|
||||
if (SDL_GetAndroidSDKVersion() >= 30 /* Android 11 */) {
|
||||
SDL_strlcat(mapping_string, "guide:b5,", sizeof(mapping_string));
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_SOUTH)) {
|
||||
SDL_strlcat(mapping_string, "a:b0,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_EAST)) {
|
||||
SDL_strlcat(mapping_string, "b:b1,", sizeof(mapping_string));
|
||||
} else if (button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) {
|
||||
// Use the back button as "B" for easy UI navigation with TV remotes
|
||||
SDL_strlcat(mapping_string, "b:b4,", sizeof(mapping_string));
|
||||
button_mask &= ~(1 << SDL_GAMEPAD_BUTTON_BACK);
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_WEST)) {
|
||||
SDL_strlcat(mapping_string, "x:b2,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_NORTH)) {
|
||||
SDL_strlcat(mapping_string, "y:b3,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_BACK)) {
|
||||
SDL_strlcat(mapping_string, "back:b4,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_GUIDE)) {
|
||||
// The guide button generally isn't functional (or acts as a home button) on most Android gamepads before Android 11
|
||||
if (SDL_GetAndroidSDKVersion() >= 30 /* Android 11 */) {
|
||||
SDL_strlcat(mapping_string, "guide:b5,", sizeof(mapping_string));
|
||||
}
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) {
|
||||
SDL_strlcat(mapping_string, "start:b6,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_STICK)) {
|
||||
SDL_strlcat(mapping_string, "leftstick:b7,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_STICK)) {
|
||||
SDL_strlcat(mapping_string, "rightstick:b8,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_SHOULDER)) {
|
||||
SDL_strlcat(mapping_string, "leftshoulder:b9,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER)) {
|
||||
SDL_strlcat(mapping_string, "rightshoulder:b10,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_UP)) {
|
||||
SDL_strlcat(mapping_string, "dpup:b11,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_DOWN)) {
|
||||
SDL_strlcat(mapping_string, "dpdown:b12,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_LEFT)) {
|
||||
SDL_strlcat(mapping_string, "dpleft:b13,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_RIGHT)) {
|
||||
SDL_strlcat(mapping_string, "dpright:b14,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFTX)) {
|
||||
SDL_strlcat(mapping_string, "leftx:a0,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFTY)) {
|
||||
SDL_strlcat(mapping_string, "lefty:a1,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHTX)) {
|
||||
SDL_strlcat(mapping_string, "rightx:a2,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHTY)) {
|
||||
SDL_strlcat(mapping_string, "righty:a3,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFT_TRIGGER)) {
|
||||
SDL_strlcat(mapping_string, "lefttrigger:a4,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)) {
|
||||
SDL_strlcat(mapping_string, "righttrigger:a5,", sizeof(mapping_string));
|
||||
}
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_START)) {
|
||||
SDL_strlcat(mapping_string, "start:b6,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_STICK)) {
|
||||
SDL_strlcat(mapping_string, "leftstick:b7,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_STICK)) {
|
||||
SDL_strlcat(mapping_string, "rightstick:b8,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_LEFT_SHOULDER)) {
|
||||
SDL_strlcat(mapping_string, "leftshoulder:b9,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER)) {
|
||||
SDL_strlcat(mapping_string, "rightshoulder:b10,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_UP)) {
|
||||
SDL_strlcat(mapping_string, "dpup:b11,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_DOWN)) {
|
||||
SDL_strlcat(mapping_string, "dpdown:b12,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_LEFT)) {
|
||||
SDL_strlcat(mapping_string, "dpleft:b13,", sizeof(mapping_string));
|
||||
}
|
||||
if (button_mask & (1 << SDL_GAMEPAD_BUTTON_DPAD_RIGHT)) {
|
||||
SDL_strlcat(mapping_string, "dpright:b14,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFTX)) {
|
||||
SDL_strlcat(mapping_string, "leftx:a0,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFTY)) {
|
||||
SDL_strlcat(mapping_string, "lefty:a1,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHTX)) {
|
||||
SDL_strlcat(mapping_string, "rightx:a2,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHTY)) {
|
||||
SDL_strlcat(mapping_string, "righty:a3,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_LEFT_TRIGGER)) {
|
||||
SDL_strlcat(mapping_string, "lefttrigger:a4,", sizeof(mapping_string));
|
||||
}
|
||||
if (axis_mask & (1 << SDL_GAMEPAD_AXIS_RIGHT_TRIGGER)) {
|
||||
SDL_strlcat(mapping_string, "righttrigger:a5,", sizeof(mapping_string));
|
||||
}
|
||||
|
||||
return SDL_PrivateAddMappingForGUID(guid, mapping_string, &existing, SDL_GAMEPAD_MAPPING_PRIORITY_DEFAULT);
|
||||
}
|
||||
#endif // SDL_PLATFORM_ANDROID
|
||||
|
||||
@@ -29,8 +29,10 @@
|
||||
#include "../../events/SDL_keyboard_c.h"
|
||||
#include "../../core/android/SDL_android.h"
|
||||
#include "../hidapi/SDL_hidapijoystick_c.h"
|
||||
#include "../usb_ids.h"
|
||||
|
||||
#include "android/keycodes.h"
|
||||
#include <linux/input-event-codes.h>
|
||||
|
||||
// As of platform android-14, android/keycodes.h is missing these defines
|
||||
#ifndef AKEYCODE_BUTTON_1
|
||||
@@ -170,6 +172,31 @@ static int keycode_to_SDL(int keycode)
|
||||
return button;
|
||||
}
|
||||
|
||||
static int scancode_to_SDL(int scancode)
|
||||
{
|
||||
int button = 0;
|
||||
switch (scancode) {
|
||||
// D-Pad buttons on the left JoyCon
|
||||
case BTN_DPAD_UP:
|
||||
button = SDL_GAMEPAD_BUTTON_DPAD_UP;
|
||||
break;
|
||||
case BTN_DPAD_DOWN:
|
||||
button = SDL_GAMEPAD_BUTTON_DPAD_DOWN;
|
||||
break;
|
||||
case BTN_DPAD_LEFT:
|
||||
button = SDL_GAMEPAD_BUTTON_DPAD_LEFT;
|
||||
break;
|
||||
case BTN_DPAD_RIGHT:
|
||||
button = SDL_GAMEPAD_BUTTON_DPAD_RIGHT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
SDL_assert(button < ANDROID_MAX_NBUTTONS);
|
||||
return button;
|
||||
}
|
||||
|
||||
static SDL_Scancode button_to_scancode(int button)
|
||||
{
|
||||
switch (button) {
|
||||
@@ -195,11 +222,14 @@ static SDL_Scancode button_to_scancode(int button)
|
||||
return SDL_SCANCODE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool Android_OnPadDown(int device_id, int keycode)
|
||||
bool Android_OnPadDown(int device_id, int keycode, int scancode)
|
||||
{
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
SDL_joylist_item *item;
|
||||
int button = keycode_to_SDL(keycode);
|
||||
if (button < 0) {
|
||||
button = scancode_to_SDL(scancode);
|
||||
}
|
||||
if (button >= 0) {
|
||||
SDL_LockJoysticks();
|
||||
item = JoystickByDeviceId(device_id);
|
||||
@@ -215,11 +245,14 @@ bool Android_OnPadDown(int device_id, int keycode)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Android_OnPadUp(int device_id, int keycode)
|
||||
bool Android_OnPadUp(int device_id, int keycode, int scancode)
|
||||
{
|
||||
Uint64 timestamp = SDL_GetTicksNS();
|
||||
SDL_joylist_item *item;
|
||||
int button = keycode_to_SDL(keycode);
|
||||
if (button < 0) {
|
||||
button = scancode_to_SDL(scancode);
|
||||
}
|
||||
if (button >= 0) {
|
||||
SDL_LockJoysticks();
|
||||
item = JoystickByDeviceId(device_id);
|
||||
@@ -367,8 +400,9 @@ void Android_AddJoystick(int device_id, const char *name, const char *desc, int
|
||||
SDL_Log("Joystick: %s, descriptor %s, vendor = 0x%.4x, product = 0x%.4x, %d axes, %d hats", name, desc, vendor_id, product_id, naxes, nhats);
|
||||
#endif
|
||||
|
||||
if (nhats > 0) {
|
||||
if (nhats > 0 || (vendor_id == USB_VENDOR_NINTENDO && product_id == USB_PRODUCT_NINTENDO_SWITCH_JOYCON_LEFT)) {
|
||||
// Hat is translated into DPAD buttons
|
||||
// D-Pad on the left JoyCon is a special case, it's not recognized via keycodes or hats, only scancodes
|
||||
button_mask |= ((1 << SDL_GAMEPAD_BUTTON_DPAD_UP) |
|
||||
(1 << SDL_GAMEPAD_BUTTON_DPAD_DOWN) |
|
||||
(1 << SDL_GAMEPAD_BUTTON_DPAD_LEFT) |
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
|
||||
#include "../SDL_sysjoystick.h"
|
||||
|
||||
extern bool Android_OnPadDown(int device_id, int keycode);
|
||||
extern bool Android_OnPadUp(int device_id, int keycode);
|
||||
extern bool Android_OnPadDown(int device_id, int keycode, int scancode);
|
||||
extern bool Android_OnPadUp(int device_id, int keycode, int scancode);
|
||||
extern bool Android_OnJoy(int device_id, int axisnum, float value);
|
||||
extern bool Android_OnHat(int device_id, int hat_id, int x, int y);
|
||||
extern void Android_OnJoySensor(int device_id, int sensor_type, Uint64 sensor_timestamp, float x, float y, float z);
|
||||
|
||||
Reference in New Issue
Block a user