Generalized the handling of instantaneous guide button presses so there's a minimum of 100 ms between guide button press and release. This happens with at least the following controllers: All Apple MFI controllers, ASUS Gamepad, XiaoMi Bluetooth Controller
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c
index 3326c46..cdf97e4 100644
--- a/src/joystick/SDL_gamecontroller.c
+++ b/src/joystick/SDL_gamecontroller.c
@@ -25,6 +25,7 @@
#include "SDL_events.h"
#include "SDL_assert.h"
#include "SDL_hints.h"
+#include "SDL_timer.h"
#include "SDL_sysjoystick.h"
#include "SDL_joystick_c.h"
#include "SDL_gamecontrollerdb.h"
@@ -38,6 +39,9 @@
#endif
+/* Many controllers turn the center button into an instantaneous button press */
+#define SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS 100
+
#define SDL_CONTROLLER_PLATFORM_FIELD "platform:"
/* a list of currently opened game controllers */
@@ -112,6 +116,7 @@ struct _SDL_GameController
SDL_ExtendedGameControllerBind *bindings;
SDL_ExtendedGameControllerBind **last_match_axis;
Uint8 *last_hat_mask;
+ Uint32 guide_button_down;
struct _SDL_GameController *next; /* pointer to next game controller we have allocated */
};
@@ -1964,6 +1969,24 @@ SDL_PrivateGameControllerButton(SDL_GameController * gamecontroller, SDL_GameCon
}
#endif /* !SDL_EVENTS_DISABLED */
+ if (button == SDL_CONTROLLER_BUTTON_GUIDE) {
+ Uint32 now = SDL_GetTicks();
+ if (state == SDL_PRESSED) {
+ gamecontroller->guide_button_down = now;
+
+ if (gamecontroller->joystick->delayed_guide_button) {
+ /* Skip duplicate press */
+ return;
+ }
+ } else {
+ if (!SDL_TICKS_PASSED(now, gamecontroller->guide_button_down+SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS) && !gamecontroller->joystick->force_recentering) {
+ gamecontroller->joystick->delayed_guide_button = SDL_TRUE;
+ return;
+ }
+ gamecontroller->joystick->delayed_guide_button = SDL_FALSE;
+ }
+ }
+
/* translate the event, if desired */
posted = 0;
#if !SDL_EVENTS_DISABLED
@@ -2012,4 +2035,17 @@ SDL_GameControllerEventState(int state)
#endif /* SDL_EVENTS_DISABLED */
}
+void
+SDL_GameControllerHandleDelayedGuideButton(SDL_Joystick *joystick)
+{
+ SDL_GameController *controllerlist = SDL_gamecontrollers;
+ while (controllerlist) {
+ if (controllerlist->joystick == joystick) {
+ SDL_PrivateGameControllerButton(controllerlist, SDL_CONTROLLER_BUTTON_GUIDE, SDL_RELEASED);
+ break;
+ }
+ controllerlist = controllerlist->next;
+ }
+}
+
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/src/joystick/SDL_gamecontrollerdb.h b/src/joystick/SDL_gamecontrollerdb.h
index 6f75be6..5c8e768 100644
--- a/src/joystick/SDL_gamecontrollerdb.h
+++ b/src/joystick/SDL_gamecontrollerdb.h
@@ -208,7 +208,6 @@ static const char *s_ControllerMappings [] =
"03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,",
#endif
#if defined(__ANDROID__)
- "05000000050b000000450000bf7f3f00,ASUS Gamepad,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,",
"050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,",
"050000004c050000cc090000fffe3f00,PS4 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,",
"05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,",
diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c
index 38eef7c..ebbd2bf 100644
--- a/src/joystick/SDL_joystick.c
+++ b/src/joystick/SDL_joystick.c
@@ -874,6 +874,10 @@ SDL_JoystickUpdate(void)
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
SDL_SYS_JoystickUpdate(joystick);
+ if (joystick->delayed_guide_button) {
+ SDL_GameControllerHandleDelayedGuideButton(joystick);
+ }
+
if (joystick->force_recentering) {
int i;
diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h
index 0a8fdb4..2ce622e 100644
--- a/src/joystick/SDL_joystick_c.h
+++ b/src/joystick/SDL_joystick_c.h
@@ -42,6 +42,9 @@ extern SDL_bool SDL_IsGameControllerNameAndGUID(const char *name, SDL_JoystickGU
/* Function to return whether a game controller should be ignored */
extern SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid);
+/* Handle delayed guide button on a game controller */
+extern void SDL_GameControllerHandleDelayedGuideButton(SDL_Joystick *joystick);
+
/* Internal event queueing functions */
extern void SDL_PrivateJoystickAdded(int device_index);
extern void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance);
diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h
index 0ce3115..efcc2d7 100644
--- a/src/joystick/SDL_sysjoystick.h
+++ b/src/joystick/SDL_sysjoystick.h
@@ -63,6 +63,7 @@ struct _SDL_Joystick
int ref_count; /* Reference count for multiple opens */
SDL_bool is_game_controller;
+ SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */
SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */
SDL_JoystickPowerLevel epowerlevel; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */
struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */
diff --git a/src/joystick/iphoneos/SDL_sysjoystick.m b/src/joystick/iphoneos/SDL_sysjoystick.m
index 71b81d3..2da1e6c 100644
--- a/src/joystick/iphoneos/SDL_sysjoystick.m
+++ b/src/joystick/iphoneos/SDL_sysjoystick.m
@@ -31,7 +31,6 @@
#include "SDL_joystick.h"
#include "SDL_hints.h"
#include "SDL_stdinc.h"
-#include "SDL_timer.h"
#include "../SDL_sysjoystick.h"
#include "../SDL_joystick_c.h"
#include "../steam/SDL_steamcontroller.h"
@@ -560,8 +559,6 @@ SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
Uint8 hatstate = SDL_HAT_CENTERED;
int i;
int updateplayerindex = 0;
- const Uint8 pausebutton = joystick->nbuttons - 1; /* The pause button is always last. */
- const Uint32 PAUSE_RELEASE_DELAY_MS = 100;
if (controller.extendedGamepad) {
GCExtendedGamepad *gamepad = controller.extendedGamepad;
@@ -650,21 +647,13 @@ SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
}
for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
+ const Uint8 pausebutton = joystick->nbuttons - 1; /* The pause button is always last. */
SDL_PrivateJoystickButton(joystick, pausebutton, SDL_PRESSED);
- joystick->hwdata->pause_button_down_time = SDL_GetTicks();
- if (!joystick->hwdata->pause_button_down_time) {
- joystick->hwdata->pause_button_down_time = 1;
- }
+ SDL_PrivateJoystickButton(joystick, pausebutton, SDL_RELEASED);
updateplayerindex = YES;
}
joystick->hwdata->num_pause_presses = 0;
- if (joystick->hwdata->pause_button_down_time &&
- SDL_TICKS_PASSED(SDL_GetTicks(), joystick->hwdata->pause_button_down_time + PAUSE_RELEASE_DELAY_MS)) {
- SDL_PrivateJoystickButton(joystick, pausebutton, SDL_RELEASED);
- joystick->hwdata->pause_button_down_time = 0;
- }
-
if (updateplayerindex && controller.playerIndex == -1) {
BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO};