Generalized the handling of instantaneous guide button presses so there's a minimum of 100 ms between guide button press and release.
authorSam Lantinga <slouken@libsdl.org>
Mon, 19 Mar 2018 14:42:51 -0700
changeset 11934a7061d1f4ee4
parent 11933 ea7df1e9a723
child 11935 331397505b6c
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
src/joystick/SDL_gamecontroller.c
src/joystick/SDL_gamecontrollerdb.h
src/joystick/SDL_joystick.c
src/joystick/SDL_joystick_c.h
src/joystick/SDL_sysjoystick.h
src/joystick/iphoneos/SDL_sysjoystick.m
     1.1 --- a/src/joystick/SDL_gamecontroller.c	Mon Mar 19 13:16:11 2018 -0700
     1.2 +++ b/src/joystick/SDL_gamecontroller.c	Mon Mar 19 14:42:51 2018 -0700
     1.3 @@ -25,6 +25,7 @@
     1.4  #include "SDL_events.h"
     1.5  #include "SDL_assert.h"
     1.6  #include "SDL_hints.h"
     1.7 +#include "SDL_timer.h"
     1.8  #include "SDL_sysjoystick.h"
     1.9  #include "SDL_joystick_c.h"
    1.10  #include "SDL_gamecontrollerdb.h"
    1.11 @@ -38,6 +39,9 @@
    1.12  #endif
    1.13  
    1.14  
    1.15 +/* Many controllers turn the center button into an instantaneous button press */
    1.16 +#define SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS   100
    1.17 +
    1.18  #define SDL_CONTROLLER_PLATFORM_FIELD "platform:"
    1.19  
    1.20  /* a list of currently opened game controllers */
    1.21 @@ -112,6 +116,7 @@
    1.22      SDL_ExtendedGameControllerBind *bindings;
    1.23      SDL_ExtendedGameControllerBind **last_match_axis;
    1.24      Uint8 *last_hat_mask;
    1.25 +    Uint32 guide_button_down;
    1.26  
    1.27      struct _SDL_GameController *next; /* pointer to next game controller we have allocated */
    1.28  };
    1.29 @@ -1964,6 +1969,24 @@
    1.30      }
    1.31  #endif /* !SDL_EVENTS_DISABLED */
    1.32  
    1.33 +    if (button == SDL_CONTROLLER_BUTTON_GUIDE) {
    1.34 +        Uint32 now = SDL_GetTicks();
    1.35 +        if (state == SDL_PRESSED) {
    1.36 +            gamecontroller->guide_button_down = now;
    1.37 +
    1.38 +            if (gamecontroller->joystick->delayed_guide_button) {
    1.39 +                /* Skip duplicate press */
    1.40 +                return;
    1.41 +            }
    1.42 +        } else {
    1.43 +            if (!SDL_TICKS_PASSED(now, gamecontroller->guide_button_down+SDL_MINIMUM_GUIDE_BUTTON_DELAY_MS) && !gamecontroller->joystick->force_recentering) {
    1.44 +                gamecontroller->joystick->delayed_guide_button = SDL_TRUE;
    1.45 +                return;
    1.46 +            }
    1.47 +            gamecontroller->joystick->delayed_guide_button = SDL_FALSE;
    1.48 +        }
    1.49 +    }
    1.50 +
    1.51      /* translate the event, if desired */
    1.52      posted = 0;
    1.53  #if !SDL_EVENTS_DISABLED
    1.54 @@ -2012,4 +2035,17 @@
    1.55  #endif /* SDL_EVENTS_DISABLED */
    1.56  }
    1.57  
    1.58 +void
    1.59 +SDL_GameControllerHandleDelayedGuideButton(SDL_Joystick *joystick)
    1.60 +{
    1.61 +    SDL_GameController *controllerlist = SDL_gamecontrollers;
    1.62 +    while (controllerlist) {
    1.63 +        if (controllerlist->joystick == joystick) {
    1.64 +            SDL_PrivateGameControllerButton(controllerlist, SDL_CONTROLLER_BUTTON_GUIDE, SDL_RELEASED);
    1.65 +            break;
    1.66 +        }
    1.67 +        controllerlist = controllerlist->next;
    1.68 +    }
    1.69 +}
    1.70 +
    1.71  /* vi: set ts=4 sw=4 expandtab: */
     2.1 --- a/src/joystick/SDL_gamecontrollerdb.h	Mon Mar 19 13:16:11 2018 -0700
     2.2 +++ b/src/joystick/SDL_gamecontrollerdb.h	Mon Mar 19 14:42:51 2018 -0700
     2.3 @@ -208,7 +208,6 @@
     2.4      "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,",
     2.5  #endif
     2.6  #if defined(__ANDROID__)
     2.7 -    "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,",
     2.8      "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,",
     2.9      "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,",
    2.10      "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,",
     3.1 --- a/src/joystick/SDL_joystick.c	Mon Mar 19 13:16:11 2018 -0700
     3.2 +++ b/src/joystick/SDL_joystick.c	Mon Mar 19 14:42:51 2018 -0700
     3.3 @@ -874,6 +874,10 @@
     3.4      for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
     3.5          SDL_SYS_JoystickUpdate(joystick);
     3.6  
     3.7 +        if (joystick->delayed_guide_button) {
     3.8 +            SDL_GameControllerHandleDelayedGuideButton(joystick);
     3.9 +        }
    3.10 +
    3.11          if (joystick->force_recentering) {
    3.12              int i;
    3.13  
     4.1 --- a/src/joystick/SDL_joystick_c.h	Mon Mar 19 13:16:11 2018 -0700
     4.2 +++ b/src/joystick/SDL_joystick_c.h	Mon Mar 19 14:42:51 2018 -0700
     4.3 @@ -42,6 +42,9 @@
     4.4  /* Function to return whether a game controller should be ignored */
     4.5  extern SDL_bool SDL_ShouldIgnoreGameController(const char *name, SDL_JoystickGUID guid);
     4.6  
     4.7 +/* Handle delayed guide button on a game controller */
     4.8 +extern void SDL_GameControllerHandleDelayedGuideButton(SDL_Joystick *joystick);
     4.9 +
    4.10  /* Internal event queueing functions */
    4.11  extern void SDL_PrivateJoystickAdded(int device_index);
    4.12  extern void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance);
     5.1 --- a/src/joystick/SDL_sysjoystick.h	Mon Mar 19 13:16:11 2018 -0700
     5.2 +++ b/src/joystick/SDL_sysjoystick.h	Mon Mar 19 14:42:51 2018 -0700
     5.3 @@ -63,6 +63,7 @@
     5.4      int ref_count;              /* Reference count for multiple opens */
     5.5  
     5.6      SDL_bool is_game_controller;
     5.7 +    SDL_bool delayed_guide_button; /* SDL_TRUE if this device has the guide button event delayed */
     5.8      SDL_bool force_recentering; /* SDL_TRUE if this device needs to have its state reset to 0 */
     5.9      SDL_JoystickPowerLevel epowerlevel; /* power level of this joystick, SDL_JOYSTICK_POWER_UNKNOWN if not supported */
    5.10      struct _SDL_Joystick *next; /* pointer to next joystick we have allocated */
     6.1 --- a/src/joystick/iphoneos/SDL_sysjoystick.m	Mon Mar 19 13:16:11 2018 -0700
     6.2 +++ b/src/joystick/iphoneos/SDL_sysjoystick.m	Mon Mar 19 14:42:51 2018 -0700
     6.3 @@ -31,7 +31,6 @@
     6.4  #include "SDL_joystick.h"
     6.5  #include "SDL_hints.h"
     6.6  #include "SDL_stdinc.h"
     6.7 -#include "SDL_timer.h"
     6.8  #include "../SDL_sysjoystick.h"
     6.9  #include "../SDL_joystick_c.h"
    6.10  #include "../steam/SDL_steamcontroller.h"
    6.11 @@ -560,8 +559,6 @@
    6.12          Uint8 hatstate = SDL_HAT_CENTERED;
    6.13          int i;
    6.14          int updateplayerindex = 0;
    6.15 -        const Uint8 pausebutton = joystick->nbuttons - 1; /* The pause button is always last. */
    6.16 -        const Uint32 PAUSE_RELEASE_DELAY_MS = 100;
    6.17  
    6.18          if (controller.extendedGamepad) {
    6.19              GCExtendedGamepad *gamepad = controller.extendedGamepad;
    6.20 @@ -650,21 +647,13 @@
    6.21          }
    6.22  
    6.23          for (i = 0; i < joystick->hwdata->num_pause_presses; i++) {
    6.24 +            const Uint8 pausebutton = joystick->nbuttons - 1; /* The pause button is always last. */
    6.25              SDL_PrivateJoystickButton(joystick, pausebutton, SDL_PRESSED);
    6.26 -            joystick->hwdata->pause_button_down_time = SDL_GetTicks();
    6.27 -            if (!joystick->hwdata->pause_button_down_time) {
    6.28 -                joystick->hwdata->pause_button_down_time = 1;
    6.29 -            }
    6.30 +            SDL_PrivateJoystickButton(joystick, pausebutton, SDL_RELEASED);
    6.31              updateplayerindex = YES;
    6.32          }
    6.33          joystick->hwdata->num_pause_presses = 0;
    6.34  
    6.35 -        if (joystick->hwdata->pause_button_down_time &&
    6.36 -            SDL_TICKS_PASSED(SDL_GetTicks(), joystick->hwdata->pause_button_down_time + PAUSE_RELEASE_DELAY_MS)) {
    6.37 -            SDL_PrivateJoystickButton(joystick, pausebutton, SDL_RELEASED);
    6.38 -            joystick->hwdata->pause_button_down_time = 0;
    6.39 -        }
    6.40 -
    6.41          if (updateplayerindex && controller.playerIndex == -1) {
    6.42              BOOL usedPlayerIndexSlots[4] = {NO, NO, NO, NO};
    6.43