Improve joystick connection/disconnection.

Followup on 02520fb6.

Add ConnectController() and DisconnectController() protected methods in
wxSDLJoy, use them to open or close and clear the device pointer
properly.

For controller add/remap events, call DisconnectController() first
before ConnectController() to make sure the right device is associated.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
This commit is contained in:
Rafael Kitover 2019-12-05 16:55:02 +00:00
parent d395e05d97
commit 1ccc377978
No known key found for this signature in database
GPG Key ID: 08AB596679D86240
2 changed files with 26 additions and 11 deletions

View File

@ -100,7 +100,8 @@ void wxSDLJoy::Poll()
auto joy = e.cdevice.which; auto joy = e.cdevice.which;
if (add_all || contains(joystate, joy)) { if (add_all || contains(joystate, joy)) {
joystate[joy].dev = SDL_GameControllerOpen(joy); DisconnectController(joy);
ConnectController(joy);
systemScreenMessage(wxString::Format(_("Connected game controller %d"), joy + 1)); systemScreenMessage(wxString::Format(_("Connected game controller %d"), joy + 1));
} }
@ -111,7 +112,7 @@ void wxSDLJoy::Poll()
auto joy = e.cdevice.which; auto joy = e.cdevice.which;
if (contains(joystate, joy)) { if (contains(joystate, joy)) {
joystate[joy].dev = nullptr; DisconnectController(joy);
systemScreenMessage(wxString::Format(_("Disconnected game controller %d"), joy + 1)); systemScreenMessage(wxString::Format(_("Disconnected game controller %d"), joy + 1));
} }
@ -121,6 +122,22 @@ void wxSDLJoy::Poll()
} }
} }
void wxSDLJoy::ConnectController(uint8_t joy)
{
if (!(joystate[joy].dev = SDL_GameControllerOpen(joy)))
wxLogDebug("SDL_GameControllerOpen(%d) failed: %s", joy, SDL_GetError());
}
void wxSDLJoy::DisconnectController(uint8_t joy)
{
if (auto& dev = joystate[joy].dev) {
if (SDL_GameControllerGetAttached(dev))
SDL_GameControllerClose(dev);
dev = nullptr;
}
}
wxEvtHandler* wxSDLJoy::Attach(wxEvtHandler* handler) wxEvtHandler* wxSDLJoy::Attach(wxEvtHandler* handler)
{ {
wxEvtHandler* prev = evthandler; wxEvtHandler* prev = evthandler;
@ -132,14 +149,14 @@ void wxSDLJoy::Add(int8_t joy_n)
{ {
if (joy_n < 0) { if (joy_n < 0) {
for (uint8_t joy : range(0, SDL_NumJoysticks())) for (uint8_t joy : range(0, SDL_NumJoysticks()))
joystate[joy].dev = SDL_GameControllerOpen(joy); ConnectController(joy);
add_all = true; add_all = true;
return; return;
} }
joystate[joy_n].dev = SDL_GameControllerOpen(joy_n); ConnectController(joy_n);
} }
void wxSDLJoy::Remove(int8_t joy_n) void wxSDLJoy::Remove(int8_t joy_n)
@ -147,19 +164,15 @@ void wxSDLJoy::Remove(int8_t joy_n)
add_all = false; add_all = false;
if (joy_n < 0) { if (joy_n < 0) {
for (auto joy : joystate) { for (auto joy : joystate)
if (auto dev = std::get<1>(joy).dev) DisconnectController(std::get<0>(joy));
SDL_GameControllerClose(dev);
}
joystate.clear(); joystate.clear();
return; return;
} }
if (auto dev = joystate[joy_n].dev) DisconnectController(joy_n);
SDL_GameControllerClose(dev);
joystate.erase(joy_n); joystate.erase(joy_n);
} }

View File

@ -50,6 +50,8 @@ public:
protected: protected:
// used to continue rumbling on a timer // used to continue rumbling on a timer
void Notify(); void Notify();
void ConnectController(uint8_t joy);
void DisconnectController(uint8_t joy);
private: private:
std::unordered_map<uint8_t, wxSDLJoyState> joystate; std::unordered_map<uint8_t, wxSDLJoyState> joystate;
wxEvtHandler* evthandler; wxEvtHandler* evthandler;