From 733a7fadda04185e66750feecfe9ccc75524d292 Mon Sep 17 00:00:00 2001
From: David Salvisberg <dave@portablegaming.de>
Date: Fri, 27 Feb 2015 01:48:55 +0100
Subject: [PATCH] Improved handling of multiple connected joysticks, prefer
 SDL_GameControllers.

---
 src/eventthread.cpp | 41 +++++++++++++++++++++++++++++++++++++----
 src/eventthread.h   |  1 +
 src/main.cpp        | 13 +++++++++++--
 3 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/src/eventthread.cpp b/src/eventthread.cpp
index e52bc30..b32c527 100644
--- a/src/eventthread.cpp
+++ b/src/eventthread.cpp
@@ -286,11 +286,14 @@ void EventThread::process(RGSSThreadData &rtData)
 			break;
 
 		case SDL_JOYDEVICEADDED :
-			if (event.jdevice.which > 0)
+			if (SDL_JoystickGetAttached(js))
 				break;
 
-			if (SDL_IsGameController(0))
-				rtData.gamecontroller = SDL_GameControllerOpen(0);
+			if (SDL_IsGameController(event.jdevice.which))
+			{
+				rtData.gamecontroller = SDL_GameControllerOpen(event.jdevice.which);
+				rtData.gamecontrollerIndex = event.jdevice.which;
+			}
 			if (rtData.gamecontroller != NULL)
 			{
 				js = SDL_GameControllerGetJoystick(rtData.gamecontroller);
@@ -298,14 +301,44 @@ void EventThread::process(RGSSThreadData &rtData)
 				 * the user hasn't set a custom set of keybinds yet */
 				rtData.bindingUpdateMsg.post(loadBindings(rtData.config, rtData.gamecontroller));
 			}
-			else
+			else if (event.jdevice.which == 0)
 			{
 				js = SDL_JoystickOpen(0);
+				rtData.gamecontrollerIndex = 0;
 			}
 			break;
 
 		case SDL_JOYDEVICEREMOVED :
+			if (SDL_JoystickInstanceID(js) != event.jdevice.which)
+				break;
+
+			/* clean up the connected controller and joy device if it was the one we were tracking */
+			if (rtData.gamecontroller != NULL && SDL_GameControllerGetAttached(rtData.gamecontroller))
+				SDL_GameControllerClose(rtData.gamecontroller);
+			else if (SDL_JoystickGetAttached(js))
+				SDL_JoystickClose(js);
 			resetInputStates();
+
+			/* If there are still joysticks/gamepads around make sure to connect them */
+			js = NULL;
+			rtData.gamecontroller = NULL;
+			rtData.gamecontrollerIndex = 0;
+			for (int i = 0; i < SDL_NumJoysticks(); i++)
+			{
+				if (SDL_IsGameController(i))
+				{
+					rtData.gamecontroller = SDL_GameControllerOpen(i);
+					rtData.gamecontrollerIndex = i;
+					break;
+				}
+			}
+			if (rtData.gamecontroller != NULL)
+			{
+				js = SDL_GameControllerGetJoystick(rtData.gamecontroller);
+				rtData.bindingUpdateMsg.post(loadBindings(rtData.config, rtData.gamecontroller));
+			}
+			else if (SDL_NumJoysticks() > 0)
+				js = SDL_JoystickOpen(0);
 			break;
 
 		case SDL_MOUSEBUTTONDOWN :
diff --git a/src/eventthread.h b/src/eventthread.h
index 6f73e5a..9b2f7fb 100644
--- a/src/eventthread.h
+++ b/src/eventthread.h
@@ -233,6 +233,7 @@ struct RGSSThreadData
 	Config config;
 
 	SDL_GameController *gamecontroller;
+	int gamecontrollerIndex;
 
 	std::string rgssErrorMsg;
 
diff --git a/src/main.cpp b/src/main.cpp
index 919753a..177deb2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -284,8 +284,17 @@ int main(int argc, char *argv[])
 	SDL_GameControllerAddMappingsFromRW(controllerDB, 1);
 
 	rtData.gamecontroller = NULL;
-	if (SDL_NumJoysticks() > 0 && SDL_IsGameController(0))
-		rtData.gamecontroller = SDL_GameControllerOpen(0);
+	rtData.gamecontrollerIndex = 0;
+	/* Add the first index which is a valid GameController if there is one */
+	for (int i = 0; i < SDL_NumJoysticks(); i++)
+	{
+		if (SDL_IsGameController(i))
+		{
+			rtData.gamecontroller = SDL_GameControllerOpen(i);
+			rtData.gamecontrollerIndex = i;
+			break;
+		}
+	} 
 
 	/* Load and post key bindings */
 	rtData.bindingUpdateMsg.post(loadBindings(conf, rtData.gamecontroller));