diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index cb4eae1472..dd22ffe730 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -319,6 +319,19 @@ bool ControllerInterface::AddDevice(std::shared_ptr device NOTICE_LOG_FMT(CONTROLLERINTERFACE, "Added device: {}", device->GetQualifiedName()); m_devices.emplace_back(std::move(device)); + + // We can't (and don't want) to control the order in which devices are added, but we + // need their order to be consistent, and we need the same one to always be the first, where + // present (the keyboard and mouse device usually). This is because when defaulting a + // controller profile, it will automatically select the first device in the list as its default. + std::stable_sort(m_devices.begin(), m_devices.end(), + [](const std::shared_ptr& a, + const std::shared_ptr& b) { + // It would be nice to sort devices by Source then Name then ID but it's + // better to leave them sorted by the add order, which also avoids breaking + // the order on other platforms that are less tested. + return a->GetSortPriority() > b->GetSortPriority(); + }); } if (!m_populating_devices_counter) diff --git a/Source/Core/InputCommon/ControllerInterface/CoreDevice.h b/Source/Core/InputCommon/ControllerInterface/CoreDevice.h index 1994cb402c..e094d2477d 100644 --- a/Source/Core/InputCommon/ControllerInterface/CoreDevice.h +++ b/Source/Core/InputCommon/ControllerInterface/CoreDevice.h @@ -128,6 +128,11 @@ public: // (e.g. Xbox 360 controllers have controller number LEDs which should match the ID we use.) virtual std::optional GetPreferredId() const; + // Use this to change the order in which devices are sorted in their list. + // A higher priority means it will be one of the first ones (smaller index), making it more + // likely to be index 0, which is automatically set as the default device when there isn't one. + virtual int GetSortPriority() const { return 0; } + const std::vector& Inputs() const { return m_inputs; } const std::vector& Outputs() const { return m_outputs; } diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.cpp b/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.cpp index bc1820b8ad..0da09ad6e0 100644 --- a/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.cpp +++ b/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.cpp @@ -230,6 +230,12 @@ std::string KeyboardMouse::GetSource() const return DINPUT_SOURCE_NAME; } +// Give this device a higher priority to make sure it shows first +int KeyboardMouse::GetSortPriority() const +{ + return 5; +} + // names std::string KeyboardMouse::Key::GetName() const { diff --git a/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h b/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h index 3bd073a6f1..28c6407471 100644 --- a/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h +++ b/Source/Core/InputCommon/ControllerInterface/DInput/DInputKeyboardMouse.h @@ -102,6 +102,7 @@ public: std::string GetName() const override; std::string GetSource() const override; + int GetSortPriority() const override; private: void UpdateCursorInput(); diff --git a/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp b/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp index 6511af49c1..73eb0e515a 100644 --- a/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp +++ b/Source/Core/InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.cpp @@ -136,6 +136,8 @@ public: std::string GetName() const final override; std::string GetSource() const final override; std::optional GetPreferredId() const final override; + // Always add these at the end, given their hotplug nature + int GetSortPriority() const override { return -2; } private: void ResetPadData(); diff --git a/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.cpp b/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.cpp index dfd329f5e0..d68b0441a6 100644 --- a/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.cpp @@ -321,6 +321,12 @@ std::string Device::GetSource() const return SOURCE_NAME; } +// Always add these at the end, given their hotplug nature +int Device::GetSortPriority() const +{ + return -1; +} + void Device::RunTasks() { if (IsPerformingTask()) diff --git a/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.h b/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.h index 4864e0abb3..b6c96d0238 100644 --- a/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.h +++ b/Source/Core/InputCommon/ControllerInterface/Wiimote/WiimoteController.h @@ -33,6 +33,7 @@ public: std::string GetName() const override; std::string GetSource() const override; + int GetSortPriority() const override; void UpdateInput() override;