replaced obsolete joystick calibration with game controller configuration
authorHolger Schemel <info@artsoft.org>
Tue, 25 Jul 2017 19:07:16 +0000 (21:07 +0200)
committerHolger Schemel <info@artsoft.org>
Tue, 25 Jul 2017 19:09:03 +0000 (21:09 +0200)
graphics/gfx_classic/joystick/axis_x.png [new file with mode: 0644]
graphics/gfx_classic/joystick/axis_y.png [new file with mode: 0644]
graphics/gfx_classic/joystick/button.png [new file with mode: 0644]
graphics/gfx_classic/joystick/controller.png [new file with mode: 0644]
src/files.c
src/files.h
src/libgame/joystick.h
src/libgame/sdl.c
src/libgame/sdl.h
src/screens.c
src/tools.c

diff --git a/graphics/gfx_classic/joystick/axis_x.png b/graphics/gfx_classic/joystick/axis_x.png
new file mode 100644 (file)
index 0000000..ff3fa94
Binary files /dev/null and b/graphics/gfx_classic/joystick/axis_x.png differ
diff --git a/graphics/gfx_classic/joystick/axis_y.png b/graphics/gfx_classic/joystick/axis_y.png
new file mode 100644 (file)
index 0000000..6942de5
Binary files /dev/null and b/graphics/gfx_classic/joystick/axis_y.png differ
diff --git a/graphics/gfx_classic/joystick/button.png b/graphics/gfx_classic/joystick/button.png
new file mode 100644 (file)
index 0000000..490e8bc
Binary files /dev/null and b/graphics/gfx_classic/joystick/button.png differ
diff --git a/graphics/gfx_classic/joystick/controller.png b/graphics/gfx_classic/joystick/controller.png
new file mode 100644 (file)
index 0000000..d1d7d4b
Binary files /dev/null and b/graphics/gfx_classic/joystick/controller.png differ
index 4370cba412ca3492d03ab7644f1111fd2cb12ed9..b3d18ba2d74fc7aacb116d508da1d5ee3f148125 100644 (file)
@@ -8690,6 +8690,55 @@ void LoadSetup_EditorCascade()
   free(filename);
 }
 
+static void addGameControllerMappingToHash(SetupFileHash *mappings_hash,
+                                          char *mapping_line)
+{
+  char mapping_guid[MAX_LINE_LEN];
+  char *mapping_start, *mapping_end;
+
+  // get GUID from game controller mapping line: copy complete line
+  strncpy(mapping_guid, mapping_line, MAX_LINE_LEN - 1);
+  mapping_guid[MAX_LINE_LEN - 1] = '\0';
+
+  // get GUID from game controller mapping line: cut after GUID part
+  mapping_start = strchr(mapping_guid, ',');
+  if (mapping_start != NULL)
+    *mapping_start = '\0';
+
+  // cut newline from game controller mapping line
+  mapping_end = strchr(mapping_line, '\n');
+  if (mapping_end != NULL)
+    *mapping_end = '\0';
+
+  // add mapping entry to game controller mappings hash
+  setHashEntry(mappings_hash, mapping_guid, mapping_line);
+}
+
+static void LoadSetup_ReadGameControllerMappings(SetupFileHash *mappings_hash,
+                                                char *filename)
+{
+  FILE *file;
+
+  if (!(file = fopen(filename, MODE_READ)))
+  {
+    Error(ERR_WARN, "cannot read game controller mappings file '%s'", filename);
+
+    return;
+  }
+
+  while (!feof(file))
+  {
+    char line[MAX_LINE_LEN];
+
+    if (!fgets(line, MAX_LINE_LEN, file))
+      break;
+
+    addGameControllerMappingToHash(mappings_hash, line);
+  }
+
+  fclose(file);
+}
+
 void SaveSetup()
 {
   char *filename = getSetupFilename();
@@ -8799,6 +8848,47 @@ void SaveSetup_EditorCascade()
   free(filename);
 }
 
+static void SaveSetup_WriteGameControllerMappings(SetupFileHash *mappings_hash,
+                                                 char *filename)
+{
+  FILE *file;
+
+  if (!(file = fopen(filename, MODE_WRITE)))
+  {
+    Error(ERR_WARN, "cannot write game controller mappings file '%s'",filename);
+
+    return;
+  }
+
+  BEGIN_HASH_ITERATION(mappings_hash, itr)
+  {
+    fprintf(file, "%s\n", HASH_ITERATION_VALUE(itr));
+  }
+  END_HASH_ITERATION(mappings_hash, itr)
+
+  fclose(file);
+}
+
+void SaveSetup_AddGameControllerMapping(char *mapping)
+{
+  char *filename = getPath2(getSetupDir(), GAMECONTROLLER_BASENAME);
+  SetupFileHash *mappings_hash = newSetupFileHash();
+
+  InitUserDataDirectory();
+
+  // load existing personal game controller mappings
+  LoadSetup_ReadGameControllerMappings(mappings_hash, filename);
+
+  // add new mapping to personal game controller mappings
+  addGameControllerMappingToHash(mappings_hash, mapping);
+
+  // save updated personal game controller mappings
+  SaveSetup_WriteGameControllerMappings(mappings_hash, filename);
+
+  freeSetupFileHash(mappings_hash);
+  free(filename);
+}
+
 void LoadCustomElementDescriptions()
 {
   char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
index 46dcae9c9aa4f588c59c0e8cf11b3ff65129489b..1db4988681039db4743b9af83bd57add191209c2 100644 (file)
@@ -63,6 +63,8 @@ void SaveSetup();
 void LoadSetup_EditorCascade();
 void SaveSetup_EditorCascade();
 
+void SaveSetup_AddGameControllerMapping(char *);
+
 void LoadCustomElementDescriptions();
 void InitMenuDesignSettings_Static();
 void LoadMenuDesignSettings();
index f3be29545672d5e2b636ba5b2ec17ab4d3f1c7db..74dbad76c1b44a4bab313cd0c5387ceb0ce79b71 100644 (file)
@@ -17,6 +17,8 @@
 #define JOYSTICK_NOT_AVAILABLE 0
 #define        JOYSTICK_AVAILABLE      (1 << 0)
 #define        JOYSTICK_ACTIVE         (1 << 1)
+#define JOYSTICK_CONFIGURED    (1 << 2)
+#define JOYSTICK_NOT_CONFIGURED        (1 << 3)
 #define JOYSTICK_ACTIVATED     (JOYSTICK_AVAILABLE | JOYSTICK_ACTIVE)
 
 #if defined(PLATFORM_FREEBSD)
index f94193127f5eafb7cf5127d9bd00809c6ce6bc26..c473b2652b4724b0176a2bef87b2605b97fe2e34 100644 (file)
@@ -2616,7 +2616,7 @@ void SDLClearJoystickState()
   }
 }
 
-static boolean SDLOpenJoystick(int nr)
+boolean SDLOpenJoystick(int nr)
 {
   if (nr < 0 || nr >= MAX_PLAYERS)
     return FALSE;
@@ -2644,7 +2644,7 @@ static boolean SDLOpenJoystick(int nr)
   return (sdl_joystick[nr] != NULL);
 }
 
-static void SDLCloseJoystick(int nr)
+void SDLCloseJoystick(int nr)
 {
   if (nr < 0 || nr >= MAX_PLAYERS)
     return;
index 5391b683d5cbec0da588b93a968e780c048cb484..14872400f7051788b34cfa28172e3e1d26b91879 100644 (file)
@@ -492,6 +492,8 @@ void SDLInitJoysticks(void);
 boolean SDLReadJoystick(int, int *, int *, boolean *, boolean *);
 boolean SDLCheckJoystickOpened(int);
 void SDLClearJoystickState();
+boolean SDLOpenJoystick(int);
+void SDLCloseJoystick(int);
 
 void PrepareFadeBitmap(int);
 
index b3d9111d7bd8359997ebdfa2d433fe78ebf37bf6..265c9e2f45d1a7e0456031e680df77035eb7af5b 100644 (file)
@@ -163,7 +163,7 @@ static void HandleScreenGadgets(struct GadgetInfo *);
 static void HandleSetupScreen_Generic(int, int, int, int, int);
 static void HandleSetupScreen_Input(int, int, int, int, int);
 static void CustomizeKeyboard(int);
-static void CalibrateJoystick(int);
+static void ConfigureJoystick(int);
 static void execSetupGame(void);
 static void execSetupGraphics(void);
 static void execSetupSound(void);
@@ -6007,8 +6007,8 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active)
     { &custom_key.right, "Joystick Right" },
     { &custom_key.up,    "Joystick Up"    },
     { &custom_key.down,  "Joystick Down"  },
-    { &custom_key.snap,  "Button 1"       },
-    { &custom_key.drop,  "Button 2"       }
+    { &custom_key.snap,  "Button 1/A/X"   },
+    { &custom_key.drop,  "Button 2/B/Y"   }
   };
   static char *joystick_name[MAX_PLAYERS] =
   {
@@ -6038,7 +6038,7 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active)
     int font_nr = (joystick_active ? FONT_VALUE_1 : FONT_VALUE_OLD);
 
     DrawText(mSX + 8 * 32, mSY + 3 * 32, text, font_nr);
-    DrawText(mSX + 32, mSY + 4 * 32, "Calibrate", text_font_nr);
+    DrawText(mSX + 32, mSY + 4 * 32, "Configure", text_font_nr);
   }
   else
   {
@@ -6189,7 +6189,7 @@ void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button)
       else if (y == 2)
       {
        if (setup.input[input_player_nr].use_joystick)
-         CalibrateJoystick(input_player_nr);
+         ConfigureJoystick(input_player_nr);
        else
          CustomizeKeyboard(input_player_nr);
       }
@@ -6336,7 +6336,8 @@ void CustomizeKeyboard(int player_nr)
   DrawSetupScreen_Input();
 }
 
-static boolean CalibrateJoystickMain(int player_nr)
+#if 0
+static boolean OLD_CalibrateJoystickMain(int player_nr)
 {
   int new_joystick_xleft = JOYSTICK_XMIDDLE;
   int new_joystick_xright = JOYSTICK_XMIDDLE;
@@ -6507,23 +6508,398 @@ static boolean CalibrateJoystickMain(int player_nr)
 
   return TRUE;
 }
+#endif
+
+/* game controller mapping generator by Gabriel Jacobo <gabomdq@gmail.com> */
+
+#define MARKER_BUTTON          1
+#define MARKER_AXIS_X          2
+#define MARKER_AXIS_Y          3
+
+static boolean ConfigureJoystickMapButtonsAndAxes(SDL_Joystick *joystick)
+{
+#if defined(TARGET_SDL2)
+  static Bitmap *controller, *button, *axis_x, *axis_y;
+  Bitmap *marker;
+  boolean bitmaps_initialized = FALSE;
+  boolean screen_initialized = FALSE;
+  const char *name = NULL;
+  boolean success = TRUE;
+  boolean done = FALSE, next = FALSE;
+  Event event;
+  int alpha = 200, alpha_step = -1;
+  int alpha_ticks = 0;
+  char mapping[4096], temp[4096];
+  int i, j;
+
+  struct
+  {
+    int x, y;
+    int marker;
+    char *field;
+    int axis, button, hat, hat_value;
+    char mapping[4096];
+  }
+  *step, *prev_step, steps[] =
+  {
+    { 370, 175, MARKER_BUTTON, "a",            },
+    { 410, 142, MARKER_BUTTON, "b",            },
+    { 334, 145, MARKER_BUTTON, "x",            },
+    { 372, 115, MARKER_BUTTON, "y",            },
+    { 176, 145, MARKER_BUTTON, "back",         },
+    { 230, 145, MARKER_BUTTON, "guide",                },
+    { 285, 145, MARKER_BUTTON, "start",                },
+    { 124, 220, MARKER_BUTTON, "dpleft",       },
+    { 160, 248, MARKER_BUTTON, "dpdown",       },
+    { 192, 220, MARKER_BUTTON, "dpright",      },
+    { 160, 192, MARKER_BUTTON, "dpup",         },
+    {  64,  60, MARKER_BUTTON, "leftshoulder", },
+    { 102,  10, MARKER_AXIS_Y, "lefttrigger",  },
+    { 396,  60, MARKER_BUTTON, "rightshoulder",        },
+    { 360,  10, MARKER_AXIS_Y, "righttrigger", },
+    {  87, 161, MARKER_BUTTON, "leftstick",    },
+    { 296, 230, MARKER_BUTTON, "rightstick",   },
+    {  87, 161, MARKER_AXIS_X, "leftx",                },
+    {  87, 161, MARKER_AXIS_Y, "lefty",                },
+    { 296, 230, MARKER_AXIS_X, "rightx",       },
+    { 296, 230, MARKER_AXIS_Y, "righty",       },
+  };
+
+  unsigned int event_frame_delay = 0;
+  unsigned int event_frame_delay_value = GAME_FRAME_DELAY;
+
+  ResetDelayCounter(&event_frame_delay);
+
+  if (!bitmaps_initialized)
+  {
+    controller = LoadCustomImage("joystick/controller.png");
+    button     = LoadCustomImage("joystick/button.png");
+    axis_x     = LoadCustomImage("joystick/axis_x.png");
+    axis_y     = LoadCustomImage("joystick/axis_y.png");
+
+    bitmaps_initialized = TRUE;
+  }
+
+  /* print info about the joystick we are watching */
+  name = SDL_JoystickName(joystick);
+  Error(ERR_DEBUG, "Watching joystick %d: (%s)\n",
+       SDL_JoystickInstanceID(joystick),
+       (name ? name : "(unknown joystick)"));
+  Error(ERR_DEBUG, "Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
+       SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
+       SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
+
+  /* initialize mapping with GUID and name */
+  SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), temp, sizeof(temp));
+
+  snprintf(mapping, sizeof(mapping), "%s,%s,platform:%s,",
+          temp, name ? name : "Unknown Joystick", SDL_GetPlatform());
+
+  /* loop through all steps (buttons and axes), getting joystick events */
+  for (i = 0; i < SDL_arraysize(steps) && !done;)
+  {
+    step = &steps[i];
+    strcpy(step->mapping, mapping);
+    step->axis = -1;
+    step->button = -1;
+    step->hat = -1;
+    step->hat_value = -1;
+
+    marker = (step->marker == MARKER_BUTTON ? button :
+             step->marker == MARKER_AXIS_X ? axis_x :
+             step->marker == MARKER_AXIS_Y ? axis_y : marker);
+
+    next = FALSE;
+
+    while (!done && !next)
+    {
+      alpha += alpha_step * (int)(SDL_GetTicks() - alpha_ticks) / 5;
+      alpha_ticks = SDL_GetTicks();
+
+      if (alpha >= 255)
+      {
+       alpha = 255;
+       alpha_step = -1;
+      }
+      else if (alpha < 128)
+      {
+       alpha = 127;
+       alpha_step = 1;
+      }
+
+      ClearField();
+
+      DrawTextSCentered(mSY - SY + 22 * 16, FONT_REQUEST,
+                       "Press buttons and move axes on");
+      DrawTextSCentered(mSY - SY + 23 * 16, FONT_REQUEST,
+                       "your controller when indicated.");
+      DrawTextSCentered(mSY - SY + 24 * 16, FONT_REQUEST,
+                       "(Your controller may look different.)");
+
+#if defined(PLATFORM_ANDROID)
+      DrawTextSCentered(mSY - SY + 26 * 16, FONT_REQUEST,
+                       "To correct a mistake,");
+      DrawTextSCentered(mSY - SY + 27 * 16, FONT_REQUEST,
+                       "press the 'back' button.");
+      DrawTextSCentered(mSY - SY + 28 * 16, FONT_REQUEST,
+                       "To skip a button or axis,");
+      DrawTextSCentered(mSY - SY + 29 * 16, FONT_REQUEST,
+                       "press the 'menu' button.");
+#else
+      DrawTextSCentered(mSY - SY + 26 * 16, FONT_REQUEST,
+                       "To correct a mistake,");
+      DrawTextSCentered(mSY - SY + 27 * 16, FONT_REQUEST,
+                       "press the 'backspace' key.");
+      DrawTextSCentered(mSY - SY + 28 * 16, FONT_REQUEST,
+                       "To skip a button or axis,");
+      DrawTextSCentered(mSY - SY + 29 * 16, FONT_REQUEST,
+                       "press the 'return' key.");
+      DrawTextSCentered(mSY - SY + 30 * 16, FONT_REQUEST,
+                       "To exit, press the 'escape' key.");
+#endif
+
+      int controller_x = gfx.sx + (gfx.sxsize - controller->width) / 2;
+      int controller_y = gfx.sy;
+
+      int marker_x = controller_x + step->x;
+      int marker_y = controller_y + step->y;
+
+      BlitBitmapMasked(controller, drawto, 0, 0,
+                      controller->width, controller->height,
+                      controller_x, controller_y);
+
+      SDL_SetSurfaceAlphaMod(marker->surface_masked, alpha);
+
+      BlitBitmapMasked(marker, drawto, 0, 0,
+                      marker->width, marker->height,
+                      marker_x, marker_y);
+
+      if (!screen_initialized)
+       FadeIn(REDRAW_FIELD);
+      else
+       BackToFront();
+
+      screen_initialized = TRUE;
+
+      while (NextValidEvent(&event))
+      {
+       switch (event.type)
+       {
+         case SDL_JOYAXISMOTION:
+           if (event.jaxis.value > 20000 ||
+               event.jaxis.value < -20000)
+           {
+             for (j = 0; j < i; j++)
+               if (steps[j].axis == event.jaxis.axis)
+                 break;
+
+             if (j == i)
+             {
+               if (step->marker != MARKER_AXIS_X &&
+                   step->marker != MARKER_AXIS_Y)
+                 break;
+
+               step->axis = event.jaxis.axis;
+               strcat(mapping, step->field);
+               snprintf(temp, sizeof(temp), ":a%u,", event.jaxis.axis);
+               strcat(mapping, temp);
+               i++;
+               next = TRUE;
+             }
+           }
+
+           break;
+
+         case SDL_JOYHATMOTION:
+           /* ignore centering; we're probably just coming back
+              to the center from the previous item we set */
+           if (event.jhat.value == SDL_HAT_CENTERED)
+             break;
+
+           for (j = 0; j < i; j++)
+             if (steps[j].hat == event.jhat.hat &&
+                 steps[j].hat_value == event.jhat.value)
+               break;
+
+           if (j == i)
+           {
+             step->hat = event.jhat.hat;
+             step->hat_value = event.jhat.value;
+             strcat(mapping, step->field);
+             snprintf(temp, sizeof(temp), ":h%u.%u,",
+                      event.jhat.hat, event.jhat.value );
+             strcat(mapping, temp);
+             i++;
+             next = TRUE;
+           }
+
+           break;
+
+         case SDL_JOYBALLMOTION:
+           break;
+
+         case SDL_JOYBUTTONUP:
+           for (j = 0; j < i; j++)
+             if (steps[j].button == event.jbutton.button)
+               break;
+
+           if (j == i)
+           {
+             step->button = event.jbutton.button;
+             strcat(mapping, step->field);
+             snprintf(temp, sizeof(temp), ":b%u,", event.jbutton.button);
+             strcat(mapping, temp);
+             i++;
+             next = TRUE;
+           }
+
+           break;
+
+         case SDL_FINGERDOWN:
+         case SDL_MOUSEBUTTONDOWN:
+           /* skip this step */
+           i++;
+           next = TRUE;
+
+           break;
+
+         case SDL_KEYDOWN:
+           if (event.key.keysym.sym == KSYM_BackSpace ||
+               event.key.keysym.sym == KSYM_Back)
+           {
+             /* undo this step */
+             if (i > 0)
+             {
+               prev_step = &steps[--i];
+               strcpy(mapping, prev_step->mapping);
+               next = TRUE;
+             }
+
+             break;
+           }
+
+           if (event.key.keysym.sym == KSYM_space ||
+               event.key.keysym.sym == KSYM_Return ||
+               event.key.keysym.sym == KSYM_Menu)
+           {
+             /* skip this step */
+             i++;
+             next = TRUE;
+
+             break;
+           }
+
+           if (event.key.keysym.sym == KSYM_Escape)
+           {
+             success = FALSE;
+             done = TRUE;
+           }
+
+           break;
+
+         case SDL_QUIT:
+           program.exit_function(0);
+           break;
+
+         default:
+           break;
+       }
+
+       // do not handle events for longer than standard frame delay period
+       if (DelayReached(&event_frame_delay, event_frame_delay_value))
+         break;
+      }
+    }
+  }
+
+  if (success)
+  {
+    Error(ERR_DEBUG, "New game controller mapping:\n\n%s\n\n", mapping);
+
+    // activate mapping for this game
+    SDL_GameControllerAddMapping(mapping);
+
+    // save mapping to personal mappings
+    SaveSetup_AddGameControllerMapping(mapping);
+  }
+
+  /* wait until the last pending event was removed from event queue */
+  while (NextValidEvent(&event));
+
+  return success;
+#else
+  return TRUE;
+#endif
+}
 
-void CalibrateJoystick(int player_nr)
+static int ConfigureJoystickMain(int player_nr)
 {
-  if (!CalibrateJoystickMain(player_nr))
+  char *device_name = setup.input[player_nr].joy.device_name;
+  int joystick_nr = getJoystickNrFromDeviceName(device_name);
+  boolean joystick_active = CheckJoystickOpened(joystick_nr);
+  int success = FALSE;
+  int i;
+
+  if (joystick.status == JOYSTICK_NOT_AVAILABLE)
+    return JOYSTICK_NOT_AVAILABLE;
+
+  if (!joystick_active || !setup.input[player_nr].use_joystick)
+    return JOYSTICK_NOT_AVAILABLE;
+
+  FadeSetEnterMenu();
+  FadeOut(REDRAW_FIELD);
+
+  // close all joystick devices (potentially opened as game controllers)
+  for (i = 0; i < SDL_NumJoysticks(); i++)
+    SDLCloseJoystick(i);
+
+  // open joystick device as plain joystick to configure as game controller
+  SDL_Joystick *joystick = SDL_JoystickOpen(joystick_nr);
+
+  // as the joystick was successfully opened before, this should not happen
+  if (joystick == NULL)
+    return FALSE;
+
+  // create new game controller mapping (buttons and axes) for joystick device
+  success = ConfigureJoystickMapButtonsAndAxes(joystick);
+
+  // close joystick (and maybe re-open as configured game controller later)
+  SDL_JoystickClose(joystick);
+
+  // re-open all joystick devices (potentially as game controllers)
+  for (i = 0; i < SDL_NumJoysticks(); i++)
+    SDLOpenJoystick(i);
+
+  // clear all joystick input actions for all joystick devices
+  SDLClearJoystickState();
+
+  return (success ? JOYSTICK_CONFIGURED : JOYSTICK_NOT_CONFIGURED);
+}
+
+void ConfigureJoystick(int player_nr)
+{
+  boolean state = ConfigureJoystickMain(player_nr);
+
+  if (state != JOYSTICK_NOT_CONFIGURED)
   {
+    boolean success = (state == JOYSTICK_CONFIGURED);
+    char *message = (success ? " IS CONFIGURED! " : " NOT AVAILABLE! ");
     char *device_name = setup.input[player_nr].joy.device_name;
     int nr = getJoystickNrFromDeviceName(device_name) + 1;
     int xpos = mSX - SX;
     int ypos = mSY - SY;
+    unsigned int wait_frame_delay = 0;
+    unsigned int wait_frame_delay_value = 2000;
+
+    ResetDelayCounter(&wait_frame_delay);
 
     ClearField();
 
     DrawTextF(xpos + 16, ypos + 6 * 32, FONT_TITLE_1, "   JOYSTICK %d   ", nr);
-    DrawTextF(xpos + 16, ypos + 7 * 32, FONT_TITLE_1, " NOT AVAILABLE! ");
-    BackToFront();
+    DrawTextF(xpos + 16, ypos + 7 * 32, FONT_TITLE_1, message);
 
-    Delay(2000);               /* show error message for a short time */
+    while (!DelayReached(&wait_frame_delay, wait_frame_delay_value))
+      BackToFront();
 
     ClearEventQueue();
   }
index 1ea116bab181f892eb1280285b3203743873a9c7..31ae317a3104eb985dbc59e773b0a819acdbda25 100644 (file)
@@ -3759,6 +3759,10 @@ void WaitForEventToContinue()
       {
        case EVENT_BUTTONPRESS:
        case EVENT_KEYPRESS:
+#if defined(TARGET_SDL2)
+        case SDL_CONTROLLERBUTTONDOWN:
+#endif
+        case SDL_JOYBUTTONDOWN:
          still_wait = FALSE;
          break;