diff options
| author | Shawn Hoffman <godisgovernment@gmail.com> | 2022-08-07 17:28:41 -0700 |
|---|---|---|
| committer | Shawn Hoffman <godisgovernment@gmail.com> | 2022-08-26 21:59:56 -0700 |
| commit | 76d2e47444636210a188ac57d2c962049947ec20 (patch) | |
| tree | a41555fe0d1fccc90ccbfed16664cec411a7d7e9 /Source/Core/InputCommon/ControllerInterface | |
| parent | b6ac63dc4767512aa53183fae3fa310883302260 (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.cpp | 174 |
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(¬ify_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(); |
