summaryrefslogtreecommitdiff
path: root/Source/Core/InputCommon/ControllerInterface
diff options
context:
space:
mode:
authorShawn Hoffman <godisgovernment@gmail.com>2022-08-07 17:28:41 -0700
committerShawn Hoffman <godisgovernment@gmail.com>2022-08-26 21:59:56 -0700
commit76d2e47444636210a188ac57d2c962049947ec20 (patch)
treea41555fe0d1fccc90ccbfed16664cec411a7d7e9 /Source/Core/InputCommon/ControllerInterface
parentb6ac63dc4767512aa53183fae3fa310883302260 (diff)
ciface/win32: use CM_Register_Notification instead of wnd msgs
Diffstat (limited to 'Source/Core/InputCommon/ControllerInterface')
-rw-r--r--Source/Core/InputCommon/ControllerInterface/Win32/Win32.cpp174
1 files changed, 47 insertions, 127 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/Win32/Win32.cpp b/Source/Core/InputCommon/ControllerInterface/Win32/Win32.cpp
index 42aa12a141..793e66dbf2 100644
--- a/Source/Core/InputCommon/ControllerInterface/Win32/Win32.cpp
+++ b/Source/Core/InputCommon/ControllerInterface/Win32/Win32.cpp
@@ -3,35 +3,38 @@
#include "InputCommon/ControllerInterface/Win32/Win32.h"
-#include <windows.h>
+#include <Windows.h>
+#include <cfgmgr32.h>
+// must be before hidclass
+#include <initguid.h>
+
+#include <hidclass.h>
-#include <array>
-#include <future>
#include <mutex>
-#include <thread>
#include "Common/Flag.h"
-#include "Common/HRWrap.h"
#include "Common/Logging/Log.h"
-#include "Common/ScopeGuard.h"
-#include "Common/Thread.h"
#include "InputCommon/ControllerInterface/DInput/DInput.h"
#include "InputCommon/ControllerInterface/WGInput/WGInput.h"
#include "InputCommon/ControllerInterface/XInput/XInput.h"
-constexpr UINT WM_DOLPHIN_STOP = WM_USER;
+#pragma comment(lib, "OneCoreUAP.Lib")
// 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;
+// TODO is this really needed?
static Common::Flag s_first_populate_devices_asked;
+static HCMNOTIFICATION s_notify_handle;
-static LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
+_Pre_satisfies_(EventDataSize >= sizeof(CM_NOTIFY_EVENT_DATA)) static DWORD CALLBACK
+ OnDevicesChanged(_In_ HCMNOTIFICATION hNotify, _In_opt_ PVOID Context,
+ _In_ CM_NOTIFY_ACTION Action,
+ _In_reads_bytes_(EventDataSize) PCM_NOTIFY_EVENT_DATA EventData,
+ _In_ DWORD EventDataSize)
{
- if (message == WM_INPUT_DEVICE_CHANGE)
+ if (Action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL ||
+ Action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL)
{
// Windows automatically sends this message before we ask for it and before we are "ready" to
// listen for it.
@@ -47,142 +50,59 @@ static LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARA
});
}
}
-
- return DefWindowProc(hwnd, message, wparam, lparam);
+ return ERROR_SUCCESS;
}
void ciface::Win32::Init(void* hwnd)
{
s_hwnd = static_cast<HWND>(hwnd);
+
XInput::Init();
WGInput::Init();
- std::promise<HWND> message_window_promise;
-
- s_thread = std::thread([&message_window_promise] {
- Common::SetCurrentThreadName("ciface::Win32 Message Loop");
-
- HWND message_window = nullptr;
- Common::ScopeGuard promise_guard([&] { message_window_promise.set_value(message_window); });
-
- HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
- if (FAILED(hr))
- {
- ERROR_LOG_FMT(CONTROLLERINTERFACE, "CoInitializeEx failed: {}", Common::HRWrap(hr));
- return;
- }
- Common::ScopeGuard uninit([] { CoUninitialize(); });
-
- const auto window_name = TEXT("DolphinWin32ControllerInterface");
-
- WNDCLASSEX window_class_info{};
- window_class_info.cbSize = sizeof(window_class_info);
- window_class_info.lpfnWndProc = WindowProc;
- window_class_info.hInstance = GetModuleHandle(nullptr);
- window_class_info.lpszClassName = window_name;
-
- ATOM window_class = RegisterClassEx(&window_class_info);
- if (!window_class)
- {
- NOTICE_LOG_FMT(CONTROLLERINTERFACE, "RegisterClassEx failed: {}",
- Common::HRWrap(GetLastError()));
- return;
- }
- Common::ScopeGuard unregister([&window_class] {
- if (!UnregisterClass(MAKEINTATOM(window_class), GetModuleHandle(nullptr)))
- ERROR_LOG_FMT(CONTROLLERINTERFACE, "UnregisterClass failed: {}",
- Common::HRWrap(GetLastError()));
- });
-
- message_window = CreateWindowEx(0, window_name, nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr,
- nullptr, nullptr);
- promise_guard.Exit();
- if (!message_window)
- {
- ERROR_LOG_FMT(CONTROLLERINTERFACE, "CreateWindowEx failed: {}",
- Common::HRWrap(GetLastError()));
- return;
- }
- Common::ScopeGuard destroy([&] {
- if (!DestroyWindow(message_window))
- ERROR_LOG_FMT(CONTROLLERINTERFACE, "DestroyWindow failed: {}",
- Common::HRWrap(GetLastError()));
- });
-
- std::array<RAWINPUTDEVICE, 2> devices;
- // game pad devices
- devices[0].usUsagePage = 0x01;
- devices[0].usUsage = 0x05;
- devices[0].dwFlags = RIDEV_DEVNOTIFY;
- devices[0].hwndTarget = message_window;
- // joystick devices
- devices[1].usUsagePage = 0x01;
- devices[1].usUsage = 0x04;
- devices[1].dwFlags = RIDEV_DEVNOTIFY;
- devices[1].hwndTarget = message_window;
-
- if (!RegisterRawInputDevices(devices.data(), static_cast<UINT>(devices.size()),
- static_cast<UINT>(sizeof(decltype(devices)::value_type))))
- {
- ERROR_LOG_FMT(CONTROLLERINTERFACE, "RegisterRawInputDevices failed: {}", GetLastError());
- return;
- }
-
- MSG msg;
- while (GetMessage(&msg, nullptr, 0, 0) > 0)
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- if (msg.message == WM_DOLPHIN_STOP)
- break;
- }
- });
-
- s_message_window = message_window_promise.get_future().get();
+ CM_NOTIFY_FILTER notify_filter{.cbSize = sizeof(notify_filter),
+ .FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE,
+ .u{.DeviceInterface{.ClassGuid = GUID_DEVINTERFACE_HID}}};
+ const CONFIGRET cfg_rv =
+ CM_Register_Notification(&notify_filter, nullptr, OnDevicesChanged, &s_notify_handle);
+ if (cfg_rv != CR_SUCCESS)
+ {
+ ERROR_LOG_FMT(CONTROLLERINTERFACE, "CM_Register_Notification failed: {:x}", cfg_rv);
+ }
}
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();
- ciface::DInput::PopulateDevices(s_hwnd);
- ciface::XInput::PopulateDevices();
- ciface::WGInput::PopulateDevices();
- }
- else
- {
- ERROR_LOG_FMT(CONTROLLERINTERFACE,
- "win32 asked to populate devices, but device thread isn't running");
- }
+ s_hwnd = static_cast<HWND>(hwnd);
+ std::lock_guard lk_population(s_populate_mutex);
+ s_first_populate_devices_asked.Set();
+ ciface::DInput::PopulateDevices(s_hwnd);
+ ciface::XInput::PopulateDevices();
+ ciface::WGInput::PopulateDevices();
}
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);
- }
+ s_hwnd = static_cast<HWND>(hwnd);
+ std::lock_guard lk_population(s_populate_mutex);
+ ciface::DInput::ChangeWindow(s_hwnd);
}
void ciface::Win32::DeInit()
{
- NOTICE_LOG_FMT(CONTROLLERINTERFACE, "win32 DeInit");
- if (s_thread.joinable())
+ s_first_populate_devices_asked.Clear();
+ DInput::DeInit();
+ s_hwnd = nullptr;
+
+ if (s_notify_handle)
{
- PostMessage(s_message_window, WM_DOLPHIN_STOP, 0, 0);
- s_thread.join();
- s_message_window = nullptr;
- s_first_populate_devices_asked.Clear();
- DInput::DeInit();
+ const CONFIGRET cfg_rv = CM_Unregister_Notification(s_notify_handle);
+ if (cfg_rv != CR_SUCCESS)
+ {
+ ERROR_LOG_FMT(CONTROLLERINTERFACE, "CM_Unregister_Notification failed: {:x}", cfg_rv);
+ }
+ s_notify_handle = nullptr;
}
- s_hwnd = nullptr;
XInput::DeInit();
WGInput::DeInit();