mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
rawinput: fix hotplug for keyboard and mouse (#810)
## Link to GitHub Issue or related Pull Request, if one exists n/a ## Description of change Fix a long-standing issue of hotplug not working for keyboards and mice. The code only registered for HID notifications; we also need to do it for the keyboard GUID and mouse GUID. ## Testing Confirmed that keyboards and mice can be hot unplugged and plugged.
This commit is contained in:
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
#include <dbt.h>
|
#include <dbt.h>
|
||||||
#include <devguid.h>
|
#include <devguid.h>
|
||||||
|
#include <hidclass.h>
|
||||||
|
#include <ntddkbd.h>
|
||||||
|
#include <ntddmou.h>
|
||||||
|
#include <objbase.h>
|
||||||
|
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "rawinput.h"
|
#include "rawinput.h"
|
||||||
@@ -12,31 +16,42 @@
|
|||||||
|
|
||||||
namespace rawinput {
|
namespace rawinput {
|
||||||
|
|
||||||
DEFINE_GUID(GUID_HID, 0x4D1E55B2L, 0xF16F, 0x11CF, 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30);
|
static bool is_rawinput_interface(const GUID &guid) {
|
||||||
|
return IsEqualGUID(guid, GUID_DEVINTERFACE_HID)
|
||||||
|
|| IsEqualGUID(guid, GUID_DEVINTERFACE_KEYBOARD)
|
||||||
|
|| IsEqualGUID(guid, GUID_DEVINTERFACE_MOUSE);
|
||||||
|
}
|
||||||
|
|
||||||
HotplugManager::HotplugManager(RawInputManager *ri_mgr, HWND hWnd) : ri_mgr(ri_mgr) {
|
HotplugManager::HotplugManager(RawInputManager *ri_mgr, HWND hWnd) : ri_mgr(ri_mgr) {
|
||||||
|
auto register_notification = [hWnd](const GUID &guid, const char *name) -> HANDLE {
|
||||||
|
DEV_BROADCAST_DEVICEINTERFACE settings {
|
||||||
|
.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE),
|
||||||
|
.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE,
|
||||||
|
.dbcc_reserved = 0,
|
||||||
|
.dbcc_classguid = guid,
|
||||||
|
.dbcc_name = {0},
|
||||||
|
};
|
||||||
|
|
||||||
// init settings
|
auto notification = RegisterDeviceNotification(hWnd, &settings, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||||
DEV_BROADCAST_DEVICEINTERFACE settings_hid {
|
if (notification == nullptr) {
|
||||||
.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE),
|
log_warning("hotplug", "failed to register {} notifications: {}", name, GetLastError());
|
||||||
.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE,
|
}
|
||||||
.dbcc_reserved = 0,
|
return notification;
|
||||||
.dbcc_classguid = GUID_HID,
|
|
||||||
.dbcc_name = {0},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// register notifications
|
// register notifications
|
||||||
this->hotplug_hid = RegisterDeviceNotification(hWnd, &settings_hid, DEVICE_NOTIFY_WINDOW_HANDLE);
|
this->hotplug_hid = register_notification(GUID_DEVINTERFACE_HID, "HID");
|
||||||
if (this->hotplug_hid == nullptr) {
|
this->hotplug_keyboard = register_notification(GUID_DEVINTERFACE_KEYBOARD, "keyboard");
|
||||||
log_warning("hotplug", "failed to register HID notifications: {}", GetLastError());
|
this->hotplug_mouse = register_notification(GUID_DEVINTERFACE_MOUSE, "mouse");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HotplugManager::~HotplugManager() {
|
HotplugManager::~HotplugManager() {
|
||||||
|
|
||||||
// unregister notifications
|
// unregister notifications
|
||||||
if (this->hotplug_hid != nullptr) {
|
for (auto notification : {this->hotplug_hid, this->hotplug_keyboard, this->hotplug_mouse}) {
|
||||||
UnregisterDeviceNotification(this->hotplug_hid);
|
if (notification != nullptr) {
|
||||||
|
UnregisterDeviceNotification(notification);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +69,16 @@ namespace rawinput {
|
|||||||
switch (hdr->dbch_devicetype) {
|
switch (hdr->dbch_devicetype) {
|
||||||
case DBT_DEVTYP_DEVICEINTERFACE: {
|
case DBT_DEVTYP_DEVICEINTERFACE: {
|
||||||
auto dev = (const DEV_BROADCAST_DEVICEINTERFACE *) hdr;
|
auto dev = (const DEV_BROADCAST_DEVICEINTERFACE *) hdr;
|
||||||
this->ri_mgr->midi_scan_start();
|
|
||||||
|
|
||||||
// check if class is not HID
|
// check if this is one of the registered RawInput interfaces
|
||||||
if (memcmp(&dev->dbcc_classguid, &GUID_HID, sizeof(GUID_HID)) != 0)
|
if (!is_rawinput_interface(dev->dbcc_classguid)) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// keyboard and mouse class events accompany the HID event, so scan MIDI only once
|
||||||
|
if (IsEqualGUID(dev->dbcc_classguid, GUID_DEVINTERFACE_HID)) {
|
||||||
|
this->ri_mgr->midi_scan_start();
|
||||||
|
}
|
||||||
|
|
||||||
// hotplug
|
// hotplug
|
||||||
std::string name(dev->dbcc_name);
|
std::string name(dev->dbcc_name);
|
||||||
@@ -109,6 +129,9 @@ namespace rawinput {
|
|||||||
switch (hdr->dbch_devicetype) {
|
switch (hdr->dbch_devicetype) {
|
||||||
case DBT_DEVTYP_DEVICEINTERFACE: {
|
case DBT_DEVTYP_DEVICEINTERFACE: {
|
||||||
auto dev = (DEV_BROADCAST_DEVICEINTERFACE*) hdr;
|
auto dev = (DEV_BROADCAST_DEVICEINTERFACE*) hdr;
|
||||||
|
if (!is_rawinput_interface(dev->dbcc_classguid)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
std::string name(dev->dbcc_name);
|
std::string name(dev->dbcc_name);
|
||||||
|
|
||||||
// destruct device
|
// destruct device
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ namespace rawinput {
|
|||||||
class HotplugManager {
|
class HotplugManager {
|
||||||
private:
|
private:
|
||||||
RawInputManager *ri_mgr;
|
RawInputManager *ri_mgr;
|
||||||
HANDLE hotplug_hid;
|
HANDLE hotplug_hid = nullptr;
|
||||||
|
HANDLE hotplug_keyboard = nullptr;
|
||||||
|
HANDLE hotplug_mouse = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HotplugManager(RawInputManager *ri_mgr, HWND hwnd);
|
HotplugManager(RawInputManager *ri_mgr, HWND hwnd);
|
||||||
|
|||||||
@@ -246,7 +246,8 @@ void rawinput::RawInputManager::devices_scan_rawinput(const std::string &device_
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// iterate devices
|
// hotplug gives us an interface path rather than a RawInput handle, so find its
|
||||||
|
// matching entry; an empty path means this is a full device scan
|
||||||
for (UINT device_cur_index = 0; device_cur_index < device_no; device_cur_index++) {
|
for (UINT device_cur_index = 0; device_cur_index < device_no; device_cur_index++) {
|
||||||
auto device = &device_list.get()[device_cur_index];
|
auto device = &device_list.get()[device_cur_index];
|
||||||
if (device_name.length() == 0) {
|
if (device_name.length() == 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user