mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-21 13:20:27 -06:00
ControllerInterface: Implement ChangeWindow on DInput without recreating the devices
Also polished DInput code in general to try and mitigate issue 11702. Added a lot of logging and comments.
This commit is contained in:
@ -11,6 +11,7 @@
|
||||
#include <thread>
|
||||
|
||||
#include "Common/Event.h"
|
||||
#include "Common/Flag.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/ScopeGuard.h"
|
||||
#include "Common/Thread.h"
|
||||
@ -19,20 +20,30 @@
|
||||
|
||||
constexpr UINT WM_DOLPHIN_STOP = WM_USER;
|
||||
|
||||
static Common::Event s_done_populating;
|
||||
static std::atomic<HWND> s_hwnd;
|
||||
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 Common::Flag s_first_populate_devices_asked;
|
||||
|
||||
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
if (message == WM_INPUT_DEVICE_CHANGE)
|
||||
{
|
||||
g_controller_interface.PlatformPopulateDevices([] {
|
||||
ciface::DInput::PopulateDevices(s_hwnd);
|
||||
ciface::XInput::PopulateDevices();
|
||||
});
|
||||
s_done_populating.Set();
|
||||
// Windows automatically sends this message before we ask for it and before we are "ready" to
|
||||
// listen for it.
|
||||
if (s_first_populate_devices_asked.IsSet())
|
||||
{
|
||||
s_received_device_change_event.Set();
|
||||
// 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([] {
|
||||
ciface::DInput::PopulateDevices(s_hwnd);
|
||||
ciface::XInput::PopulateDevices();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return DefWindowProc(hwnd, message, wparam, lparam);
|
||||
@ -125,10 +136,14 @@ void ciface::Win32::PopulateDevices(void* hwnd)
|
||||
if (s_thread.joinable())
|
||||
{
|
||||
s_hwnd = static_cast<HWND>(hwnd);
|
||||
s_done_populating.Reset();
|
||||
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);
|
||||
if (!s_done_populating.WaitFor(std::chrono::seconds(10)))
|
||||
ERROR_LOG_FMT(CONTROLLERINTERFACE, "win32 timed out when trying to populate devices");
|
||||
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();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -137,6 +152,15 @@ void ciface::Win32::PopulateDevices(void* hwnd)
|
||||
}
|
||||
}
|
||||
|
||||
void ciface::Win32::ChangeWindow(void* hwnd)
|
||||
{
|
||||
if (s_thread.joinable()) // "Has init?"
|
||||
{
|
||||
s_hwnd = static_cast<HWND>(hwnd);
|
||||
ciface::DInput::ChangeWindow(s_hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
void ciface::Win32::DeInit()
|
||||
{
|
||||
NOTICE_LOG_FMT(CONTROLLERINTERFACE, "win32 DeInit");
|
||||
@ -145,7 +169,11 @@ 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();
|
||||
}
|
||||
s_hwnd = nullptr;
|
||||
|
||||
XInput::DeInit();
|
||||
}
|
||||
|
@ -8,5 +8,6 @@ namespace ciface::Win32
|
||||
{
|
||||
void Init(void* hwnd);
|
||||
void PopulateDevices(void* hwnd);
|
||||
void ChangeWindow(void* hwnd);
|
||||
void DeInit();
|
||||
} // namespace ciface::Win32
|
||||
|
Reference in New Issue
Block a user