Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(619)

Unified Diff: device/gamepad/raw_input_data_fetcher_win.cc

Issue 2129003002: Refactored gamepad polling to support dynamic sources (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed unit test issue and Mac XBoxDataFetcher constructor Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: device/gamepad/raw_input_data_fetcher_win.cc
diff --git a/device/gamepad/raw_input_data_fetcher_win.cc b/device/gamepad/raw_input_data_fetcher_win.cc
index 1379dc75a702a6f72bb51f26307f63c439d1fc8c..ec7d6cbf40fe93886d5a04b43174e1c22b508d6e 100644
--- a/device/gamepad/raw_input_data_fetcher_win.cc
+++ b/device/gamepad/raw_input_data_fetcher_win.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include "base/macros.h"
+#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
namespace device {
@@ -41,10 +42,11 @@ RawGamepadInfo::RawGamepadInfo() {}
RawGamepadInfo::~RawGamepadInfo() {}
RawInputDataFetcher::RawInputDataFetcher()
- : hid_dll_(base::FilePath(FILE_PATH_LITERAL("hid.dll"))),
- rawinput_available_(GetHidDllFunctions()),
+ : rawinput_available_(false),
filter_xinput_(true),
- events_monitored_(false) {}
+ events_monitored_(false),
+ last_source_id_(0),
+ last_enumeration_id_(0) {}
RawInputDataFetcher::~RawInputDataFetcher() {
ClearControllers();
@@ -52,10 +54,20 @@ RawInputDataFetcher::~RawInputDataFetcher() {
DCHECK(!events_monitored_);
}
+GamepadSource RawInputDataFetcher::source() {
+ return Factory::static_source();
+}
+
void RawInputDataFetcher::WillDestroyCurrentMessageLoop() {
StopMonitor();
}
+void RawInputDataFetcher::OnAddedToProvider() {
+ hid_dll_.Reset(base::LoadNativeLibrary(
+ base::FilePath(FILE_PATH_LITERAL("hid.dll")), nullptr));
+ rawinput_available_ = GetHidDllFunctions();
+}
+
RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) {
size_t usage_count = arraysize(DeviceUsages);
std::unique_ptr<RAWINPUTDEVICE[]> devices(new RAWINPUTDEVICE[usage_count]);
@@ -68,6 +80,13 @@ RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) {
return devices.release();
}
+void RawInputDataFetcher::PauseHint(bool pause) {
+ if (pause)
+ StopMonitor();
+ else
+ StartMonitor();
+}
+
void RawInputDataFetcher::StartMonitor() {
if (!rawinput_available_ || events_monitored_)
return;
@@ -128,16 +147,43 @@ void RawInputDataFetcher::ClearControllers() {
}
}
-std::vector<RawGamepadInfo*> RawInputDataFetcher::EnumerateDevices() {
- std::vector<RawGamepadInfo*> valid_controllers;
+void RawInputDataFetcher::GetGamepadData(bool devices_changed_hint) {
+ if (!rawinput_available_)
+ return;
- ClearControllers();
+ if (devices_changed_hint)
+ EnumerateDevices();
+
+ for (const auto& controller : controllers_) {
+ RawGamepadInfo* gamepad = controller.second;
+ PadState* state = GetPadState(gamepad->source_id);
+ if (!state)
+ continue;
+
+ WebGamepad& pad = state->data;
+
+ pad.timestamp = gamepad->report_id;
+ pad.buttonsLength = gamepad->buttons_length;
+ pad.axesLength = gamepad->axes_length;
+
+ for (unsigned int i = 0; i < pad.buttonsLength; i++) {
+ pad.buttons[i].pressed = gamepad->buttons[i];
+ pad.buttons[i].value = gamepad->buttons[i] ? 1.0 : 0.0;
+ }
+
+ for (unsigned int i = 0; i < pad.axesLength; i++)
+ pad.axes[i] = gamepad->axes[i].value;
+ }
+}
+
+void RawInputDataFetcher::EnumerateDevices() {
+ last_enumeration_id_++;
UINT count = 0;
UINT result = GetRawInputDeviceList(NULL, &count, sizeof(RAWINPUTDEVICELIST));
if (result == static_cast<UINT>(-1)) {
PLOG(ERROR) << "GetRawInputDeviceList() failed";
- return valid_controllers;
+ return;
}
DCHECK_EQ(0u, result);
@@ -147,38 +193,66 @@ std::vector<RawGamepadInfo*> RawInputDataFetcher::EnumerateDevices() {
sizeof(RAWINPUTDEVICELIST));
if (result == static_cast<UINT>(-1)) {
PLOG(ERROR) << "GetRawInputDeviceList() failed";
- return valid_controllers;
+ return;
}
DCHECK_EQ(count, result);
for (UINT i = 0; i < count; ++i) {
if (device_list[i].dwType == RIM_TYPEHID) {
HANDLE device_handle = device_list[i].hDevice;
- RawGamepadInfo* gamepad_info = ParseGamepadInfo(device_handle);
- if (gamepad_info) {
- controllers_[device_handle] = gamepad_info;
- valid_controllers.push_back(gamepad_info);
+ ControllerMap::iterator controller = controllers_.find(device_handle);
+
+ RawGamepadInfo* gamepad;
+ if (controller != controllers_.end()) {
+ gamepad = controller->second;
+ } else {
+ gamepad = ParseGamepadInfo(device_handle);
+ if (!gamepad)
+ continue;
+
+ PadState* state = GetPadState(gamepad->source_id);
+ if (!state)
+ continue; // No slot available for this gamepad.
+
+ controllers_[device_handle] = gamepad;
+
+ WebGamepad& pad = state->data;
+ pad.connected = true;
+
+ std::string vendor = base::StringPrintf("%04x", gamepad->vendor_id);
+ std::string product = base::StringPrintf("%04x", gamepad->product_id);
+ state->mapper = GetGamepadStandardMappingFunction(vendor, product);
+ state->axis_mask = 0;
+ state->button_mask = 0;
+
+ swprintf(pad.id, WebGamepad::idLengthCap,
+ L"%ls (%lsVendor: %04x Product: %04x)", gamepad->id,
+ state->mapper ? L"STANDARD GAMEPAD " : L"", gamepad->vendor_id,
+ gamepad->product_id);
+
+ if (state->mapper)
+ swprintf(pad.mapping, WebGamepad::mappingLengthCap, L"standard");
+ else
+ pad.mapping[0] = 0;
}
+
+ gamepad->enumeration_id = last_enumeration_id_;
}
}
- return valid_controllers;
-}
-
-RawGamepadInfo* RawInputDataFetcher::GetGamepadInfo(HANDLE handle) {
- std::map<HANDLE, RawGamepadInfo*>::iterator it = controllers_.find(handle);
- if (it != controllers_.end())
- return it->second;
- return NULL;
+ // Clear out old controllers that weren't part of this enumeration pass.
+ for (const auto& controller : controllers_) {
+ RawGamepadInfo* gamepad = controller.second;
+ if (gamepad->enumeration_id != last_enumeration_id_) {
+ controllers_.erase(gamepad->handle);
+ delete gamepad;
+ }
+ }
}
RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
UINT size = 0;
- // Do we already have this device in the map?
- if (GetGamepadInfo(hDevice))
- return NULL;
-
// Query basic device info.
UINT result = GetRawInputDeviceInfo(hDevice, RIDI_DEVICEINFO, NULL, &size);
if (result == static_cast<UINT>(-1)) {
@@ -207,10 +281,17 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
}
}
+ // This is terrible, but the Oculus Rift seems to think it's a gamepad.
+ // Filter out any Oculus devices. (We'll handle Oculus Touch elsewhere.)
+ if (device_info->hid.dwVendorId == 0x2833) {
+ valid_type = false;
+ }
+
if (!valid_type)
return NULL;
std::unique_ptr<RawGamepadInfo> gamepad_info(new RawGamepadInfo);
+ gamepad_info->source_id = ++last_source_id_;
gamepad_info->handle = hDevice;
gamepad_info->report_id = 0;
gamepad_info->vendor_id = device_info->hid.dwVendorId;
@@ -350,6 +431,10 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
}
}
+ // Sometimes devices show up with no buttons or axes. Don't return these.
+ if (gamepad_info->buttons_length == 0 && gamepad_info->axes_length == 0)
+ return nullptr;
+
return gamepad_info.release();
}
@@ -448,9 +533,9 @@ LRESULT RawInputDataFetcher::OnInput(HRAWINPUT input_handle) {
// Notify the observer about events generated locally.
if (input->header.dwType == RIM_TYPEHID && input->header.hDevice != NULL) {
- RawGamepadInfo* gamepad = GetGamepadInfo(input->header.hDevice);
- if (gamepad)
- UpdateGamepad(input, gamepad);
+ ControllerMap::iterator it = controllers_.find(input->header.hDevice);
+ if (it != controllers_.end())
+ UpdateGamepad(input, it->second);
}
return DefRawInputProc(&input, 1, sizeof(RAWINPUTHEADER));

Powered by Google App Engine
This is Rietveld 408576698