Repository: doukutsu-rs/doukutsu-rs (language: rust)

Issue:
SDL_GameControllerDB controllers are not detected until unplugged and replugged
When I start the game, any controllers recognized by SDL's GameController API work right away. However, controllers that SDL doesn't recognize but are in the gamecontrollerdb.txt file don't work unless I unplug them and plug them in again.

I tried patching in a loop over all plugged in joysticks and adding them if they are recognized as GameControllers. This made all my controllers work right away (though natively supported controllers were duplicated in the list of connected controllers). I don't see any loop like this right now. Does SDL fill the event queue with JoyDeviceAdded events for already connected controllers at startup? [The docs](https://wiki.libsdl.org/SDL2/SDL_JoyDeviceEvent) don't mention this as far as I can tell.

I think we need 2 things to make this work:

- After gamecontrollerdb.txt is loaded, loop over game controllers and add them.
- When receiving a JoyDeviceAdded event, check if we already have the controller first.


Discussion / hints:
> Does SDL fill the event queue with JoyDeviceAdded events for already connected controllers at startup? [The docs](https://wiki.libsdl.org/SDL2/SDL_JoyDeviceEvent) don't mention this as far as I can tell.

I'm not sure exactly how this works internally, but here's what I'm seeing. This code, which uses SDL_JOYSTICKADDED, works fine:

```c
#include "SDL.h"
#include "SDL_events.h"
#include "SDL_gamecontroller.h"
#include "SDL_joystick.h"

int main() {
	SDL_Event ev;

	SDL_Init(SDL_INIT_GAMECONTROLLER);

	printf("Detected %d joysticks.\n", SDL_NumJoysticks());

	SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");

	while (SDL_PollEvent(&ev)) {
		switch (ev.type) {
			case SDL_JOYDEVICEADDED:
				printf("Adding device %02d. Is controller? %d\n",
					ev.jdevice.which,
					SDL_IsGameController(ev.jdevice.which)
				);
				break;
		}
	}

	return 0;
}
```

When I plug in my weird controller that's only in SDL_GameControllerDB, this prints:

```
Detected 1 joysticks.
Adding device 00. Is controller? 1
```

But this behaves the same as doukutsu-rs:

```diff
	while (SDL_PollEvent(&ev)) {
		switch (ev.type) {
-			case SDL_JOYDEVICEADDED:
+			case SDL_CONTROLLERDEVICEADDED:
				printf("Adding device %02d. Is controller? %d\n",
					ev.jdevice.which,
-					SDL_IsGameController(ev.jdevice.which)
+					SDL_IsGameController(ev.cdevice.which)
				);
				break;
		}
```
Which prints:

```
Detected 1 joysticks.
```

I'll keep investigating how SDL works, but in the mean time, maybe d-rs should listen for SDL_JOYDEVICEADDED events and then check whether the added joystick is a GameController.
Some of my investigation continues at the SDL forums: https://discourse.libsdl.org/t/deviced-added-events-for-devices-plugged-in-at-game-start/55039

Fix patch:
diff --git a/src/framework/backend_sdl2.rs b/src/framework/backend_sdl2.rs
index a28e1237..fd91da30 100644
--- a/src/framework/backend_sdl2.rs
+++ b/src/framework/backend_sdl2.rs
@@ -332,7 +332,7 @@ impl BackendEventLoop for SDL2EventLoop {
                             ctx.keyboard_context.set_key(drs_scan, false);
                         }
                     }
-                    Event::ControllerDeviceAdded { which, .. } => {
+                    Event::JoyDeviceAdded { which, .. } => {
                         let game_controller = &self.refs.borrow().game_controller;
 
                         if game_controller.is_game_controller(which) {


Test patch: