diff --git a/Core/KeyMap.cpp b/Core/KeyMap.cpp index ba74591e0e..e3f0de9dc7 100644 --- a/Core/KeyMap.cpp +++ b/Core/KeyMap.cpp @@ -812,43 +812,52 @@ void ClearAllMappings() { g_controllerMapGeneration++; } -bool IsNvidiaShield(const std::string &name) { +bool IsNvidiaShield(std::string_view name) { return name == "NVIDIA:SHIELD"; } -bool IsRetroid(const std::string &name) { +bool IsRetroid(std::string_view name) { // TODO: Not sure if there are differences between different Retroid devices. // The one I have is a "Retroid Pocket 2+". return startsWith(name, "Retroid:"); } -bool IsNvidiaShieldTV(const std::string &name) { +bool IsNvidiaShieldTV(std::string_view name) { return name == "NVIDIA:SHIELD Android TV"; } -bool IsXperiaPlay(const std::string &name) { +bool IsXperiaPlay(std::string_view name) { return name == "Sony Ericsson:R800a" || name == "Sony Ericsson:R800i" || name == "Sony Ericsson:R800x" || name == "Sony Ericsson:R800at" || name == "Sony Ericsson:SO-01D" || name == "Sony Ericsson:zeus"; } -bool IsMOQII7S(const std::string &name) { +bool IsMOQII7S(std::string_view name) { return name == "MOQI:I7S"; } -bool HasBuiltinController(const std::string &name) { +bool HasBuiltinController(std::string_view name) { return IsXperiaPlay(name) || IsNvidiaShield(name) || IsMOQII7S(name) || IsRetroid(name); } -void NotifyPadConnected(InputDeviceID deviceId, const std::string &name) { +void NotifyPadConnected(InputDeviceID deviceId, std::string_view name) { std::lock_guard guard(g_controllerMapLock); - g_seenPads.insert(name); + g_seenPads.insert(std::string(name)); g_padNames[deviceId] = name; } -void AutoConfForPad(const std::string &name) { +void NotifyPadDisconnected(InputDeviceID deviceId) { + std::lock_guard guard(g_controllerMapLock); + auto iter = g_padNames.find(deviceId); + if (iter != g_padNames.end()) { + g_seenPads.erase(iter->second); + } + g_padNames.erase(deviceId); +} + +void AutoConfForPad(std::string_view name) { std::lock_guard guard(g_controllerMapLock); g_controllerMap.clear(); - INFO_LOG(Log::System, "Autoconfiguring pad for '%s'", name.c_str()); + INFO_LOG(Log::System, "Autoconfiguring pad for '%.*s'", STR_VIEW(name)); #if PPSSPP_PLATFORM(ANDROID) if (name.find("Xbox") != std::string::npos) { diff --git a/Core/KeyMap.h b/Core/KeyMap.h index b2f2da888e..9c6660bb2c 100644 --- a/Core/KeyMap.h +++ b/Core/KeyMap.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include #include #include @@ -209,17 +210,19 @@ namespace KeyMap { void UpdateNativeMenuKeys(); - void NotifyPadConnected(InputDeviceID deviceId, const std::string &name); - bool IsNvidiaShield(const std::string &name); - bool IsNvidiaShieldTV(const std::string &name); - bool IsXperiaPlay(const std::string &name); - bool IsMOQII7S(const std::string &name); - bool IsRetroid(const std::string &name); - bool HasBuiltinController(const std::string &name); + void NotifyPadConnected(InputDeviceID deviceId, std::string_view name); + void NotifyPadDisconnected(InputDeviceID deviceId); + + bool IsNvidiaShield(std::string_view name); + bool IsNvidiaShieldTV(std::string_view name); + bool IsXperiaPlay(std::string_view name); + bool IsMOQII7S(std::string_view name); + bool IsRetroid(std::string_view name); + bool HasBuiltinController(std::string_view name); const std::set &GetSeenPads(); std::string PadName(InputDeviceID deviceId); - void AutoConfForPad(const std::string &name); + void AutoConfForPad(std::string_view name); bool IsKeyMapped(InputDeviceID device, int key); diff --git a/Windows/DinputDevice.cpp b/Windows/DinputDevice.cpp index ac5715f27f..2405af0fae 100644 --- a/Windows/DinputDevice.cpp +++ b/Windows/DinputDevice.cpp @@ -173,6 +173,8 @@ DinputDevice::DinputDevice(int devnum) { } DinputDevice::~DinputDevice() { + KeyMap::NotifyPadDisconnected(DEVICE_ID_PAD_0 + pDevNum); + if (pJoystick) { pJoystick = nullptr; } diff --git a/Windows/XinputDevice.cpp b/Windows/XinputDevice.cpp index 9c32f07d81..38c75dc0a6 100644 --- a/Windows/XinputDevice.cpp +++ b/Windows/XinputDevice.cpp @@ -173,20 +173,18 @@ int XinputDevice::UpdateState() { continue; DWORD dwResult = PPSSPP_XInputGetState(i, &state); if (dwResult == ERROR_SUCCESS) { - padData_[i].connected = true; - if (!padData_[i].notified) { - padData_[i].notified = true; + if (!padData_[i].connected) { + padData_[i].connected = true; + padData_[i].vendorId = 0; + padData_[i].productId = 0; #if !PPSSPP_PLATFORM(UWP) XINPUT_CAPABILITIES_EX caps{}; if (PPSSPP_XInputGetCapabilitiesEx != nullptr && PPSSPP_XInputGetCapabilitiesEx(1, i, 0, &caps) == ERROR_SUCCESS) { - - KeyMap::NotifyPadConnected(DEVICE_ID_XINPUT_0 + i, StringFromFormat("Xbox pad %d: %d/%d", (i + 1), caps.VendorId, caps.ProductId)); - } else { -#else - { -#endif - KeyMap::NotifyPadConnected(DEVICE_ID_XINPUT_0 + i, StringFromFormat("Xbox pad %d", (i + 1))); + padData_[i].vendorId = caps.VendorId; + padData_[i].productId = caps.ProductId; } +#endif + KeyMap::NotifyPadConnected(DEVICE_ID_XINPUT_0 + i, StringFromFormat("Xbox pad %d: %d/%d", (i + 1), padData_[i].vendorId, padData_[i].productId)); } XINPUT_VIBRATION vibration{}; UpdatePad(i, state, vibration); @@ -194,6 +192,7 @@ int XinputDevice::UpdateState() { } else if (dwResult == ERROR_DEVICE_NOT_CONNECTED) { if (padData_[i].connected) { ReleaseAllKeys(i); + KeyMap::NotifyPadDisconnected(DEVICE_ID_XINPUT_0 + i); padData_[i].connected = false; } padData_[i].checkDelayUpdates = 30; diff --git a/Windows/XinputDevice.h b/Windows/XinputDevice.h index 3581ef053a..13c489451f 100644 --- a/Windows/XinputDevice.h +++ b/Windows/XinputDevice.h @@ -17,7 +17,6 @@ private: void ApplyVibration(int pad, XINPUT_VIBRATION &vibration); struct PadData { - bool notified = false; bool connected = false; int checkDelayUpdates = 0; XINPUT_STATE prevState{};