mirror of
https://github.com/Ryujinx/SDL.git
synced 2024-12-23 14:25:34 +00:00
Added the hint SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS to control whether Nintendo Switch controllers use their button labels or button positions for game controller button reporting.
This commit is contained in:
parent
e6ac16ef2f
commit
b3470f04b1
|
@ -488,6 +488,29 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT"
|
#define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief If set, game controller face buttons report their values according to their labels instead of their positional layout.
|
||||||
|
*
|
||||||
|
* For example, on Nintendo Switch controllers, normally you'd get:
|
||||||
|
*
|
||||||
|
* (Y)
|
||||||
|
* (X) (B)
|
||||||
|
* (A)
|
||||||
|
*
|
||||||
|
* but if this hint is set, you'll get:
|
||||||
|
*
|
||||||
|
* (X)
|
||||||
|
* (Y) (A)
|
||||||
|
* (B)
|
||||||
|
*
|
||||||
|
* The variable can be set to the following values:
|
||||||
|
* "0" - Report the face buttons by position, as though they were on an Xbox controller.
|
||||||
|
* "1" - Report the face buttons by label instead of position
|
||||||
|
*
|
||||||
|
* The default value is "0". This hint may be set at any time.
|
||||||
|
*/
|
||||||
|
#define SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS "SDL_GAMECONTROLLER_USE_BUTTON_LABELS"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background.
|
* \brief A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background.
|
||||||
*
|
*
|
||||||
|
|
|
@ -192,8 +192,9 @@ typedef struct
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
hid_device *dev;
|
hid_device *dev;
|
||||||
SDL_bool m_bIsInputOnly;
|
SDL_bool m_bInputOnly;
|
||||||
SDL_bool m_bIsUsingBluetooth;
|
SDL_bool m_bUsingBluetooth;
|
||||||
|
SDL_bool m_bUseButtonLabels;
|
||||||
Uint8 m_nCommandNumber;
|
Uint8 m_nCommandNumber;
|
||||||
SwitchCommonOutputPacket_t m_RumblePacket;
|
SwitchCommonOutputPacket_t m_RumblePacket;
|
||||||
Uint32 m_nRumbleExpiration;
|
Uint32 m_nRumbleExpiration;
|
||||||
|
@ -313,7 +314,7 @@ static void ConstructSubcommand(SDL_DriverSwitch_Context *ctx, ESwitchSubcommand
|
||||||
static SDL_bool WritePacket(SDL_DriverSwitch_Context *ctx, void *pBuf, Uint8 ucLen)
|
static SDL_bool WritePacket(SDL_DriverSwitch_Context *ctx, void *pBuf, Uint8 ucLen)
|
||||||
{
|
{
|
||||||
Uint8 rgucBuf[k_unSwitchMaxOutputPacketLength];
|
Uint8 rgucBuf[k_unSwitchMaxOutputPacketLength];
|
||||||
const size_t unWriteSize = ctx->m_bIsUsingBluetooth ? k_unSwitchBluetoothPacketLength : k_unSwitchUSBPacketLength;
|
const size_t unWriteSize = ctx->m_bUsingBluetooth ? k_unSwitchBluetoothPacketLength : k_unSwitchUSBPacketLength;
|
||||||
|
|
||||||
if (ucLen > k_unSwitchOutputPacketDataLength) {
|
if (ucLen > k_unSwitchOutputPacketDataLength) {
|
||||||
return SDL_FALSE;
|
return SDL_FALSE;
|
||||||
|
@ -526,7 +527,7 @@ static SDL_bool LoadStickCalibration(SDL_DriverSwitch_Context *ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->m_bIsUsingBluetooth) {
|
if (ctx->m_bUsingBluetooth) {
|
||||||
for (stick = 0; stick < 2; ++stick) {
|
for (stick = 0; stick < 2; ++stick) {
|
||||||
for(axis = 0; axis < 2; ++axis) {
|
for(axis = 0; axis < 2; ++axis) {
|
||||||
ctx->m_StickExtents[stick].axis[axis].sMin = (Sint16)(SDL_MIN_SINT16 * 0.5f);
|
ctx->m_StickExtents[stick].axis[axis].sMin = (Sint16)(SDL_MIN_SINT16 * 0.5f);
|
||||||
|
@ -580,6 +581,31 @@ static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, i
|
||||||
return ApplyStickCalibrationCentered(ctx, nStick, nAxis, sRawValue, ctx->m_StickCalData[nStick].axis[nAxis].sCenter);
|
return ApplyStickCalibrationCentered(ctx, nStick, nAxis, sRawValue, ctx->m_StickCalData[nStick].axis[nAxis].sCenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SDLCALL SDL_GameControllerButtonReportingHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||||
|
{
|
||||||
|
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)userdata;
|
||||||
|
ctx->m_bUseButtonLabels = (hint && *hint != '0' && SDL_strcasecmp(hint, "false") != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Uint8 RemapButton(SDL_DriverSwitch_Context *ctx, Uint8 button)
|
||||||
|
{
|
||||||
|
if (ctx->m_bUseButtonLabels) {
|
||||||
|
switch (button) {
|
||||||
|
case SDL_CONTROLLER_BUTTON_A:
|
||||||
|
return SDL_CONTROLLER_BUTTON_B;
|
||||||
|
case SDL_CONTROLLER_BUTTON_B:
|
||||||
|
return SDL_CONTROLLER_BUTTON_A;
|
||||||
|
case SDL_CONTROLLER_BUTTON_X:
|
||||||
|
return SDL_CONTROLLER_BUTTON_Y;
|
||||||
|
case SDL_CONTROLLER_BUTTON_Y:
|
||||||
|
return SDL_CONTROLLER_BUTTON_X;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
static SDL_bool
|
static SDL_bool
|
||||||
HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
|
HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_id, Uint16 product_id, void **context)
|
||||||
{
|
{
|
||||||
|
@ -596,15 +622,15 @@ HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_
|
||||||
*context = ctx;
|
*context = ctx;
|
||||||
|
|
||||||
/* Find out whether or not we can send output reports */
|
/* Find out whether or not we can send output reports */
|
||||||
ctx->m_bIsInputOnly = SDL_IsJoystickNintendoSwitchProInputOnly(vendor_id, product_id);
|
ctx->m_bInputOnly = SDL_IsJoystickNintendoSwitchProInputOnly(vendor_id, product_id);
|
||||||
if (!ctx->m_bIsInputOnly) {
|
if (!ctx->m_bInputOnly) {
|
||||||
/* Initialize rumble data */
|
/* Initialize rumble data */
|
||||||
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[0]);
|
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[0]);
|
||||||
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]);
|
SetNeutralRumble(&ctx->m_RumblePacket.rumbleData[1]);
|
||||||
|
|
||||||
/* Try setting up USB mode, and if that fails we're using Bluetooth */
|
/* Try setting up USB mode, and if that fails we're using Bluetooth */
|
||||||
if (!BTrySetupUSB(ctx)) {
|
if (!BTrySetupUSB(ctx)) {
|
||||||
ctx->m_bIsUsingBluetooth = SDL_TRUE;
|
ctx->m_bUsingBluetooth = SDL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LoadStickCalibration(ctx)) {
|
if (!LoadStickCalibration(ctx)) {
|
||||||
|
@ -620,7 +646,7 @@ HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the desired input mode */
|
/* Set the desired input mode */
|
||||||
if (ctx->m_bIsUsingBluetooth) {
|
if (ctx->m_bUsingBluetooth) {
|
||||||
input_mode = k_eSwitchInputReportIDs_SimpleControllerState;
|
input_mode = k_eSwitchInputReportIDs_SimpleControllerState;
|
||||||
} else {
|
} else {
|
||||||
input_mode = k_eSwitchInputReportIDs_FullControllerState;
|
input_mode = k_eSwitchInputReportIDs_FullControllerState;
|
||||||
|
@ -632,7 +658,7 @@ HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start sending USB reports */
|
/* Start sending USB reports */
|
||||||
if (!ctx->m_bIsUsingBluetooth) {
|
if (!ctx->m_bUsingBluetooth) {
|
||||||
/* ForceUSB doesn't generate an ACK, so don't wait for a reply */
|
/* ForceUSB doesn't generate an ACK, so don't wait for a reply */
|
||||||
if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, SDL_FALSE)) {
|
if (!WriteProprietary(ctx, k_eSwitchProprietaryCommandIDs_ForceUSB, NULL, 0, SDL_FALSE)) {
|
||||||
SDL_SetError("Couldn't start USB reports");
|
SDL_SetError("Couldn't start USB reports");
|
||||||
|
@ -646,6 +672,14 @@ HIDAPI_DriverSwitch_Init(SDL_Joystick *joystick, hid_device *dev, Uint16 vendor_
|
||||||
SetSlotLED(ctx, (joystick->instance_id % 4));
|
SetSlotLED(ctx, (joystick->instance_id % 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vendor_id == 0x0e6f && product_id == 0x0185) {
|
||||||
|
/* This is a controller shaped like a GameCube controller, with a large central A button */
|
||||||
|
ctx->m_bUseButtonLabels = SDL_TRUE;
|
||||||
|
} else {
|
||||||
|
SDL_AddHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
|
||||||
|
SDL_GameControllerButtonReportingHintChanged, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize the joystick capabilities */
|
/* Initialize the joystick capabilities */
|
||||||
joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
|
joystick->nbuttons = SDL_CONTROLLER_BUTTON_MAX;
|
||||||
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
|
joystick->naxes = SDL_CONTROLLER_AXIS_MAX;
|
||||||
|
@ -701,10 +735,10 @@ static void HandleInputOnlyControllerState(SDL_Joystick *joystick, SDL_DriverSwi
|
||||||
|
|
||||||
if (packet->rgucButtons[0] != ctx->m_lastInputOnlyState.rgucButtons[0]) {
|
if (packet->rgucButtons[0] != ctx->m_lastInputOnlyState.rgucButtons[0]) {
|
||||||
Uint8 data = packet->rgucButtons[0];
|
Uint8 data = packet->rgucButtons[0];
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
|
||||||
|
@ -799,10 +833,10 @@ static void HandleSimpleControllerState(SDL_Joystick *joystick, SDL_DriverSwitch
|
||||||
|
|
||||||
if (packet->rgucButtons[0] != ctx->m_lastSimpleState.rgucButtons[0]) {
|
if (packet->rgucButtons[0] != ctx->m_lastSimpleState.rgucButtons[0]) {
|
||||||
Uint8 data = packet->rgucButtons[0];
|
Uint8 data = packet->rgucButtons[0];
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, (data & 0x10) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x20) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
|
|
||||||
|
@ -887,10 +921,10 @@ static void HandleFullControllerState(SDL_Joystick *joystick, SDL_DriverSwitch_C
|
||||||
|
|
||||||
if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
|
if (packet->controllerState.rgucButtons[0] != ctx->m_lastFullState.controllerState.rgucButtons[0]) {
|
||||||
Uint8 data = packet->controllerState.rgucButtons[0];
|
Uint8 data = packet->controllerState.rgucButtons[0];
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_X, (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_X), (data & 0x01) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_Y, (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_Y), (data & 0x02) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_A, (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_A), (data & 0x04) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_B, (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, RemapButton(ctx, SDL_CONTROLLER_BUTTON_B), (data & 0x08) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
SDL_PrivateJoystickButton(joystick, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, (data & 0x40) ? SDL_PRESSED : SDL_RELEASED);
|
||||||
axis = (data & 0x80) ? 32767 : -32768;
|
axis = (data & 0x80) ? 32767 : -32768;
|
||||||
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
|
SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_TRIGGERRIGHT, axis);
|
||||||
|
@ -964,7 +998,7 @@ HIDAPI_DriverSwitch_Update(SDL_Joystick *joystick, hid_device *dev, void *contex
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
while ((size = ReadInput(ctx)) > 0) {
|
while ((size = ReadInput(ctx)) > 0) {
|
||||||
if (ctx->m_bIsInputOnly) {
|
if (ctx->m_bInputOnly) {
|
||||||
HandleInputOnlyControllerState(joystick, ctx, (SwitchInputOnlyControllerStatePacket_t *)&ctx->m_rgucReadBuffer[0]);
|
HandleInputOnlyControllerState(joystick, ctx, (SwitchInputOnlyControllerStatePacket_t *)&ctx->m_rgucReadBuffer[0]);
|
||||||
} else {
|
} else {
|
||||||
switch (ctx->m_rgucReadBuffer[0]) {
|
switch (ctx->m_rgucReadBuffer[0]) {
|
||||||
|
@ -995,8 +1029,13 @@ HIDAPI_DriverSwitch_Quit(SDL_Joystick *joystick, hid_device *dev, void *context)
|
||||||
{
|
{
|
||||||
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context;
|
SDL_DriverSwitch_Context *ctx = (SDL_DriverSwitch_Context *)context;
|
||||||
|
|
||||||
|
if (!ctx->m_bInputOnly) {
|
||||||
/* Restore simple input mode for other applications */
|
/* Restore simple input mode for other applications */
|
||||||
SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState);
|
SetInputMode(ctx, k_eSwitchInputReportIDs_SimpleControllerState);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_DelHintCallback(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS,
|
||||||
|
SDL_GameControllerButtonReportingHintChanged, ctx);
|
||||||
|
|
||||||
SDL_free(context);
|
SDL_free(context);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue