Skip to content

Commit

Permalink
joystick: On disconnect, recenter all game controller inputs.
Browse files Browse the repository at this point in the history
The joystick layer can't necessarily give us perfect centering, but we know
that the game controller level has logical absolute idle positions that have
nothing to do with the physical device.

So send game controller events to make it look like the device is completely
untouched before sending the final removal event.
  • Loading branch information
icculus committed Apr 20, 2020
1 parent 116b8c1 commit c5f2a1c
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions src/joystick/SDL_gamecontroller.c
Expand Up @@ -344,6 +344,28 @@ static void HandleJoystickHat(SDL_GameController *gamecontroller, int hat, Uint8
gamecontroller->last_hat_mask[hat] = value;
}


/* The joystick layer will _also_ send events to recenter before disconnect,
but it has to make (sometimes incorrect) guesses at what being "centered"
is. The game controller layer, however, can set a definite logical idle
position, so set them all here. If we happened to already be at the
center thanks to the joystick layer or idle hands, this won't generate
duplicate events. */
static void RecenterGameController(SDL_GameController *gamecontroller)
{
SDL_GameControllerButton button;
SDL_GameControllerAxis axis;

for (button = (SDL_GameControllerButton) 0; button < SDL_CONTROLLER_BUTTON_MAX; button++) {
SDL_PrivateGameControllerButton(gamecontroller, button, SDL_RELEASED);
}

for (axis = (SDL_GameControllerAxis) 0; axis < SDL_CONTROLLER_AXIS_MAX; axis++) {
SDL_PrivateGameControllerAxis(gamecontroller, axis, 0);
}
}


/*
* Event filter to fire controller events from joystick ones
*/
Expand Down Expand Up @@ -404,6 +426,8 @@ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event * ev
if (controllerlist->joystick->instance_id == event->jdevice.which) {
SDL_Event deviceevent;

RecenterGameController(controllerlist);

deviceevent.type = SDL_CONTROLLERDEVICEREMOVED;
deviceevent.cdevice.which = event->jdevice.which;
SDL_PushEvent(&deviceevent);
Expand Down

0 comments on commit c5f2a1c

Please sign in to comment.