rawinput: use UTF-8 for device descriptor (#422)

## Link to GitHub Issue, if one exists
n/a

## Description of change
For HID device descriptor, use the "W" version of Windows API, and make
sure UTF-8 is being used throughout since that's the only format IMGUI
supports.

Before this change, non-Latin characters would have shown up as `HID ???
?????` for a mouse, for example.

Due to the way ImGui loads fonts, only the following languages are
supported:

* Simplified Chinese
* Cyrillic
* Japanese
* Korean
* Thai
* Vietnamese

## Testing
Tested various combination of Windows UI language and non-Unicode
language.
This commit is contained in:
bicarus-dev
2025-11-16 00:08:30 -08:00
committed by GitHub
parent 9e2b04d5db
commit 052698afa3
2 changed files with 21 additions and 13 deletions
+11 -13
View File
@@ -347,40 +347,38 @@ void rawinput::RawInputManager::devices_scan_rawinput(RAWINPUTDEVICELIST *device
if (hid_handle != INVALID_HANDLE_VALUE) { if (hid_handle != INVALID_HANDLE_VALUE) {
// check manufacturer string // check manufacturer string
std::wstring man_ws; std::string man_ws;
wchar_t man_str_buffer[256] {}; wchar_t man_str_buffer[256] {};
if (HidD_GetManufacturerString(hid_handle, man_str_buffer, sizeof(man_str_buffer))) { if (HidD_GetManufacturerString(hid_handle, man_str_buffer, sizeof(man_str_buffer))) {
man_ws = std::wstring(man_str_buffer); man_ws = wchar_to_u8(man_str_buffer);
} }
// get product string // get product string
std::wstring prod_ws; std::string prod_ws;
wchar_t prod_str_buffer[256] {}; wchar_t prod_str_buffer[256] {};
if (HidD_GetProductString(hid_handle, prod_str_buffer, sizeof(prod_str_buffer))) { if (HidD_GetProductString(hid_handle, prod_str_buffer, sizeof(prod_str_buffer))) {
prod_ws = std::wstring(prod_str_buffer); prod_ws = wchar_to_u8(prod_str_buffer);
} }
// For Bluetooth LE HID devices (e.g., newer Xbox controllers) HidD_GetProductString // For Bluetooth LE HID devices (e.g., newer Xbox controllers) HidD_GetProductString
// and HidD_GetManufacturerString will return blank strings. // and HidD_GetManufacturerString will return blank strings.
// https://docs.microsoft.com/en-us/answers/questions/401236/hidd-getproductstring-with-ble-hid-device.html // https://docs.microsoft.com/en-us/answers/questions/401236/hidd-getproductstring-with-ble-hid-device.html
if (man_ws.empty() && prod_ws.empty()) { if (man_ws.empty() && prod_ws.empty()) {
prod_ws = s2ws(device_description); prod_ws = device_description;
} }
// build desc string // build desc string
std::wstring desc_ws; std::string desc_ws;
if (string_begins_with(prod_ws, man_ws)) { if (string_begins_with(prod_ws, man_ws)) {
desc_ws = prod_ws; desc_ws = prod_ws;
} else { } else {
desc_ws = man_ws; desc_ws = man_ws;
if (!man_ws.empty() && !prod_ws.empty()) { if (!man_ws.empty() && !prod_ws.empty()) {
desc_ws += L" "; desc_ws += " ";
} }
desc_ws += prod_ws; desc_ws += prod_ws;
} }
new_device.desc = desc_ws;
// convert to normal string
new_device.desc = ws2s(desc_ws);
// get attributes // get attributes
if (!HidD_GetAttributes(hid_handle, &hid_attributes)) { if (!HidD_GetAttributes(hid_handle, &hid_attributes)) {
@@ -1148,7 +1146,7 @@ std::string rawinput::RawInputManager::rawinput_get_device_description(const raw
// get property // get property
DWORD desc_size = 0; DWORD desc_size = 0;
if (SetupDiGetDeviceRegistryProperty( if (SetupDiGetDeviceRegistryPropertyW(
devinfo, &devinfo_data, SPDRP_DEVICEDESC, nullptr, nullptr, 0, &desc_size)) devinfo, &devinfo_data, SPDRP_DEVICEDESC, nullptr, nullptr, 0, &desc_size))
{ {
continue; continue;
@@ -1160,14 +1158,14 @@ std::string rawinput::RawInputManager::rawinput_get_device_description(const raw
// allocate buffer // allocate buffer
auto desc_data = std::make_unique<BYTE[]>(desc_size); auto desc_data = std::make_unique<BYTE[]>(desc_size);
if (!SetupDiGetDeviceRegistryProperty( if (!SetupDiGetDeviceRegistryPropertyW(
devinfo, &devinfo_data, SPDRP_DEVICEDESC, nullptr, desc_data.get(), desc_size, nullptr)) devinfo, &devinfo_data, SPDRP_DEVICEDESC, nullptr, desc_data.get(), desc_size, nullptr))
{ {
continue; continue;
} }
// kthxbye // kthxbye
device_description = std::string(reinterpret_cast<char *>(desc_data.get())); device_description = wchar_to_u8(reinterpret_cast<PWCHAR>(desc_data.get()));
} }
} }
} }
+10
View File
@@ -340,3 +340,13 @@ static inline bool parse_width_height(const std::string wh, std::pair<uint32_t,
return false; return false;
} }
} }
static inline std::string wchar_to_u8(const wchar_t* wstr) {
int size = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr);
if (size <= 1) {
return "";
}
std::string out(size - 1, 0);
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, out.data(), size - 1, nullptr, nullptr);
return out;
}