Merge pull request #10248 from Filoppi/fix_input_config_default_device_load

Fix default input config default device not being loaded/found
This commit is contained in:
JosJuice 2021-12-09 22:20:55 +01:00 committed by GitHub
commit e0a61ed9a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 35 additions and 14 deletions

View File

@ -319,6 +319,13 @@ void MainWindow::InitControllers()
return;
g_controller_interface.Initialize(GetWindowSystemInfo(windowHandle()));
if (!g_controller_interface.HasDefaultDevice())
{
// Note that the CI default device could be still temporarily removed at any time
WARN_LOG(CONTROLLERINTERFACE,
"No default device has been added in time. EmulatedController(s) defaulting adds"
" input mappings made for a specific default device depending on the platform");
}
Pad::Initialize();
Pad::InitializeGBA();
Keyboard::Initialize();

View File

@ -159,6 +159,10 @@ void ControllerInterface::RefreshDevices(RefreshReason reason)
// with their own PlatformPopulateDevices().
// This means that devices might end up in different order, unless we override their priority.
// It also means they might appear as "disconnected" in the Qt UI for a tiny bit of time.
// This helps the emulation and host thread to not stall when repopulating devices for any reason.
// Every platform that adds a device that is meant to be used as default device should try to not
// do it async, to not risk the emulated controllers default config loading not finding a default
// device.
#ifdef CIFACE_USE_WIN32
ciface::Win32::PopulateDevices(m_wsi.render_window);

View File

@ -258,10 +258,18 @@ std::vector<std::string> DeviceContainer::GetAllDeviceStrings() const
return device_strings;
}
bool DeviceContainer::HasDefaultDevice() const
{
std::lock_guard lk(m_devices_mutex);
// Devices are already sorted by priority
return !m_devices.empty() && m_devices[0]->GetSortPriority() >= 0;
}
std::string DeviceContainer::GetDefaultDeviceString() const
{
std::lock_guard lk(m_devices_mutex);
if (m_devices.empty())
// Devices are already sorted by priority
if (m_devices.empty() || m_devices[0]->GetSortPriority() < 0)
return "";
DeviceQualifier device_qualifier;

View File

@ -136,6 +136,7 @@ public:
// 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.
// Every platform should have at least one device with priority >= 0.
virtual int GetSortPriority() const { return 0; }
const std::vector<Input*>& Inputs() const { return m_inputs; }
@ -226,6 +227,7 @@ public:
Device::Output* FindOutput(std::string_view name, const Device* def_dev) const;
std::vector<std::string> GetAllDeviceStrings() const;
bool HasDefaultDevice() const;
std::string GetDefaultDeviceString() const;
std::shared_ptr<Device> FindDevice(const DeviceQualifier& devq) const;

View File

@ -64,6 +64,7 @@ public:
std::string GetName() const override;
std::string GetSource() const override;
int GetSortPriority() const override { return -2; }
bool IsValid() const final override;

View File

@ -136,7 +136,7 @@ public:
std::string GetSource() const final override;
std::optional<int> GetPreferredId() const final override;
// Always add these at the end, given their hotplug nature
int GetSortPriority() const override { return -2; }
int GetSortPriority() const override { return -4; }
private:
void ResetPadData();

View File

@ -323,7 +323,7 @@ std::string Device::GetSource() const
// Always add these at the end, given their hotplug nature
int Device::GetSortPriority() const
{
return -1;
return -3;
}
void Device::RunTasks()

View File

@ -7,9 +7,9 @@
#include <array>
#include <future>
#include <mutex>
#include <thread>
#include "Common/Event.h"
#include "Common/Flag.h"
#include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h"
@ -19,12 +19,12 @@
constexpr UINT WM_DOLPHIN_STOP = WM_USER;
static Common::Event s_received_device_change_event;
// Dolphin's render window
static HWND s_hwnd;
// Windows messaging window (hidden)
static HWND s_message_window;
static std::thread s_thread;
static std::mutex s_populate_mutex;
static Common::Flag s_first_populate_devices_asked;
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
@ -35,7 +35,7 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARA
// listen for it.
if (s_first_populate_devices_asked.IsSet())
{
s_received_device_change_event.Set();
std::lock_guard lk_population(s_populate_mutex);
// TODO: we could easily use the message passed alongside this event, which tells
// whether a device was added or removed, to avoid removing old, still connected, devices
g_controller_interface.PlatformPopulateDevices([] {
@ -135,14 +135,12 @@ void ciface::Win32::PopulateDevices(void* hwnd)
if (s_thread.joinable())
{
s_hwnd = static_cast<HWND>(hwnd);
// To avoid blocking this thread until the async population has finished, directly do it here
// (we need the DInput Keyboard and Mouse "default" device to always be added without any wait).
std::lock_guard lk_population(s_populate_mutex);
s_first_populate_devices_asked.Set();
s_received_device_change_event.Reset();
// Do this forced devices refresh in the messaging thread so it won't cause any race conditions
PostMessage(s_message_window, WM_INPUT_DEVICE_CHANGE, 0, 0);
std::thread([] {
if (!s_received_device_change_event.WaitFor(std::chrono::seconds(5)))
ERROR_LOG_FMT(CONTROLLERINTERFACE, "win32 timed out when trying to populate devices");
}).detach();
ciface::DInput::PopulateDevices(s_hwnd);
ciface::XInput::PopulateDevices();
}
else
{
@ -156,6 +154,7 @@ void ciface::Win32::ChangeWindow(void* hwnd)
if (s_thread.joinable()) // "Has init?"
{
s_hwnd = static_cast<HWND>(hwnd);
std::lock_guard lk_population(s_populate_mutex);
ciface::DInput::ChangeWindow(s_hwnd);
}
}
@ -168,7 +167,6 @@ void ciface::Win32::DeInit()
PostMessage(s_message_window, WM_DOLPHIN_STOP, 0, 0);
s_thread.join();
s_message_window = nullptr;
s_received_device_change_event.Reset();
s_first_populate_devices_asked.Clear();
DInput::DeInit();
}

View File

@ -31,6 +31,7 @@ public:
std::string GetName() const override;
std::string GetSource() const override;
std::optional<int> GetPreferredId() const override;
int GetSortPriority() const override { return -1; }
void UpdateInput() override;