Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #10248 from Filoppi/fix_input_config_default_devic…
…e_load

Fix default input config default device not being loaded/found
  • Loading branch information
JosJuice committed Dec 9, 2021
2 parents d5d21c6 + 125971d commit e0a61ed
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 14 deletions.
7 changes: 7 additions & 0 deletions Source/Core/DolphinQt/MainWindow.cpp
Expand Up @@ -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();
Expand Down
Expand Up @@ -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);
Expand Down
10 changes: 9 additions & 1 deletion Source/Core/InputCommon/ControllerInterface/CoreDevice.cpp
Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions Source/Core/InputCommon/ControllerInterface/CoreDevice.h
Expand Up @@ -136,6 +136,7 @@ class Device
// 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; }
Expand Down Expand Up @@ -226,6 +227,7 @@ class DeviceContainer
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;

Expand Down
Expand Up @@ -64,6 +64,7 @@ class Joystick : public ForceFeedback::ForceFeedbackDevice

std::string GetName() const override;
std::string GetSource() const override;
int GetSortPriority() const override { return -2; }

bool IsValid() const final override;

Expand Down
Expand Up @@ -136,7 +136,7 @@ class Device final : public Core::Device
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();
Expand Down
Expand Up @@ -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()
Expand Down
20 changes: 9 additions & 11 deletions Source/Core/InputCommon/ControllerInterface/Win32/Win32.cpp
Expand Up @@ -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"
Expand All @@ -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)
Expand All @@ -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([] {
Expand Down Expand Up @@ -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
{
Expand All @@ -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);
}
}
Expand All @@ -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();
}
Expand Down
Expand Up @@ -31,6 +31,7 @@ class Device final : public Core::Device
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;

Expand Down

0 comments on commit e0a61ed

Please sign in to comment.