Index: content/browser/gamepad/gamepad_platform_data_fetcher_win.cc |
diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc b/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc |
index f8f3dafb04a2277f80018f96218888f706e686a3..1424b6d1df955da315139f8034ece7832a4fe9ca 100644 |
--- a/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc |
+++ b/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc |
@@ -217,6 +217,9 @@ GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin() |
directinput_available_ = false; |
for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) |
pad_state_[i].status = DISCONNECTED; |
+ |
+ raw_input_fetcher_.reset(new RawInputDataFetcher()); |
+ raw_input_fetcher_->StartMonitor(); |
} |
GamepadPlatformDataFetcherWin::~GamepadPlatformDataFetcherWin() { |
@@ -224,6 +227,8 @@ GamepadPlatformDataFetcherWin::~GamepadPlatformDataFetcherWin() { |
if (pad_state_[i].status == DIRECTINPUT_CONNECTED) |
pad_state_[i].directinput_gamepad->Release(); |
} |
+ |
+ raw_input_fetcher_->StopMonitor(); |
} |
int GamepadPlatformDataFetcherWin::FirstAvailableGamepadId() const { |
@@ -253,6 +258,16 @@ bool GamepadPlatformDataFetcherWin::HasDirectInputGamepad( |
return false; |
} |
+bool GamepadPlatformDataFetcherWin::HasRawInputGamepad( |
+ const HANDLE handle) const { |
+ for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { |
+ if (pad_state_[i].status == RAWINPUT_CONNECTED && |
+ pad_state_[i].handle == handle) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
void GamepadPlatformDataFetcherWin::EnumerateDevices( |
WebGamepads* pads) { |
TRACE_EVENT0("GAMEPAD", "EnumerateDevices"); |
@@ -273,6 +288,8 @@ void GamepadPlatformDataFetcherWin::EnumerateDevices( |
if (xinput_available_ && GetXInputPadConnectivity(i, &pad)) { |
pad_state_[pad_index].status = XINPUT_CONNECTED; |
pad_state_[pad_index].xinput_index = i; |
+ pad_state_[pad_index].mapper = NULL; |
+ pads->length++; |
} |
} |
@@ -303,6 +320,35 @@ void GamepadPlatformDataFetcherWin::EnumerateDevices( |
state.guid = directinput_gamepads[i].guid; |
state.directinput_gamepad = directinput_gamepads[i].gamepad; |
state.mapper = directinput_gamepads[i].mapper; |
+ pads->length++; |
+ } |
+ } |
+ |
+ if (raw_input_fetcher_->Available()) { |
+ std::vector<RawJoystickInfo*> raw_inputs = |
+ raw_input_fetcher_->EnumerateDevices(); |
+ for (size_t i = 0; i < raw_inputs.size(); ++i) { |
+ RawJoystickInfo* joystick = raw_inputs[i]; |
+ if (HasRawInputGamepad(joystick->handle)) |
+ continue; |
+ int pad_index = FirstAvailableGamepadId(); |
+ if (pad_index == -1) |
+ return; |
+ WebGamepad& pad = pads->items[pad_index]; |
+ pad.connected = true; |
+ PadState& state = pad_state_[pad_index]; |
+ state.status = RAWINPUT_CONNECTED; |
+ state.handle = joystick->handle; |
+ |
+ std::string vendor = base::StringPrintf("%04x", joystick->vendor_id); |
+ std::string product = base::StringPrintf("%04x", joystick->product_id); |
+ state.mapper = GetGamepadStandardMappingFunction(vendor, product); |
+ |
+ swprintf(pad.id, WebGamepad::idLengthCap, |
+ L"%ls (%lsVendor: %04x Product: %04x)", |
+ joystick->id, state.mapper ? L"STANDARD GAMEPAD " : L"", |
+ joystick->vendor_id, joystick->product_id); |
+ pads->length++; |
} |
} |
} |
@@ -312,7 +358,9 @@ void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads, |
bool devices_changed_hint) { |
TRACE_EVENT0("GAMEPAD", "GetGamepadData"); |
- if (!xinput_available_ && !directinput_available_) { |
+ if (!xinput_available_ && |
+ !directinput_available_ && |
+ !raw_input_fetcher_->Available()) { |
pads->length = 0; |
return; |
} |
@@ -325,16 +373,37 @@ void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads, |
// here by only doing this when the devices are updated (despite |
// documentation claiming it's OK to call it any time). |
if (devices_changed_hint) |
- EnumerateDevices(pads); |
+ EnumerateDevices(&data_); |
+ pads->length = data_.length; |
for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { |
- WebGamepad& pad = pads->items[i]; |
+ // We rely on device_changed and GetCapabilities to tell us that |
+ // something's been connected, but we will mark as disconnected if |
+ // Get___PadState returns that we've lost the pad. |
+ if (!data_.items[i].connected) |
+ continue; |
+ |
if (pad_state_[i].status == XINPUT_CONNECTED) |
- GetXInputPadData(i, &pad); |
+ GetXInputPadData(i, &data_.items[i]); |
else if (pad_state_[i].status == DIRECTINPUT_CONNECTED) |
- GetDirectInputPadData(i, &pad); |
+ GetDirectInputPadData(i, &data_.items[i]); |
+ else if (pad_state_[i].status == RAWINPUT_CONNECTED) |
+ GetRawInputPadData(i, &data_.items[i]); |
+ |
+ // Copy to the current state to the output buffer, using the mapping |
+ // function, if there is one available. |
+ if (pad_state_[i].mapper) |
+ pad_state_[i].mapper(data_.items[i], &pads->items[i]); |
+ else |
+ pads->items[i] = data_.items[i]; |
scottmg
2014/01/31 20:51:10
this seems kind of silly for xinput
|
} |
- pads->length = WebGamepads::itemsLengthCap; |
+} |
+ |
+void GamepadPlatformDataFetcherWin::PauseHint(bool pause) { |
+ if (pause) |
+ raw_input_fetcher_->StopMonitor(); |
+ else |
+ raw_input_fetcher_->StartMonitor(); |
} |
bool GamepadPlatformDataFetcherWin::GetXInputPadConnectivity( |
@@ -360,12 +429,6 @@ bool GamepadPlatformDataFetcherWin::GetXInputPadConnectivity( |
void GamepadPlatformDataFetcherWin::GetXInputPadData( |
int i, |
WebGamepad* pad) { |
- // We rely on device_changed and GetCapabilities to tell us that |
- // something's been connected, but we will mark as disconnected if |
- // GetState returns that we've lost the pad. |
- if (!pad->connected) |
- return; |
- |
XINPUT_STATE state; |
memset(&state, 0, sizeof(XINPUT_STATE)); |
TRACE_EVENT_BEGIN1("GAMEPAD", "XInputGetState", "id", i); |
@@ -408,9 +471,6 @@ void GamepadPlatformDataFetcherWin::GetXInputPadData( |
void GamepadPlatformDataFetcherWin::GetDirectInputPadData( |
int index, |
WebGamepad* pad) { |
- if (!pad->connected) |
- return; |
- |
IDirectInputDevice8* gamepad = pad_state_[index].directinput_gamepad; |
if (FAILED(gamepad->Poll())) { |
// Polling didn't work, try acquiring the gamepad. |
@@ -432,10 +492,9 @@ void GamepadPlatformDataFetcherWin::GetDirectInputPadData( |
return; |
} |
- WebGamepad raw; |
- raw.connected = true; |
+ pad->connected = true; |
for (int i = 0; i < 16; i++) |
- raw.buttons[i] = (state.buttons[i] & 0x80) ? 1.0 : 0.0; |
+ pad->buttons[i] = (state.buttons[i] & 0x80) ? 1.0 : 0.0; |
// We map the POV (often a D-pad) into the buttons 16-19. |
// DirectInput gives pov measurements in hundredths of degrees, |
@@ -443,29 +502,49 @@ void GamepadPlatformDataFetcherWin::GetDirectInputPadData( |
// We use 22.5 degree slices so we can handle diagonal D-raw presses. |
static const int arc_segment = 2250; // 22.5 degrees = 1/16 circle |
if (state.pov > arc_segment && state.pov < 7 * arc_segment) |
- raw.buttons[19] = 1.0; |
+ pad->buttons[19] = 1.0; |
else |
- raw.buttons[19] = 0.0; |
+ pad->buttons[19] = 0.0; |
if (state.pov > 5 * arc_segment && state.pov < 11 * arc_segment) |
- raw.buttons[17] = 1.0; |
+ pad->buttons[17] = 1.0; |
else |
- raw.buttons[17] = 0.0; |
+ pad->buttons[17] = 0.0; |
if (state.pov > 9 * arc_segment && state.pov < 15 * arc_segment) |
- raw.buttons[18] = 1.0; |
+ pad->buttons[18] = 1.0; |
else |
- raw.buttons[18] = 0.0; |
+ pad->buttons[18] = 0.0; |
if (state.pov < 3 * arc_segment || |
(state.pov > 13 * arc_segment && state.pov < 36000)) |
- raw.buttons[16] = 1.0; |
+ pad->buttons[16] = 1.0; |
else |
- raw.buttons[16] = 0.0; |
+ pad->buttons[16] = 0.0; |
for (int i = 0; i < 10; i++) |
- raw.axes[i] = state.axes[i]; |
- pad_state_[index].mapper(raw, pad); |
+ pad->axes[i] = state.axes[i]; |
+} |
+ |
+void GamepadPlatformDataFetcherWin::GetRawInputPadData( |
+ int index, |
+ WebGamepad* pad) { |
+ RawJoystickInfo* joystick = raw_input_fetcher_->GetJoystickInfo( |
+ pad_state_[index].handle); |
+ if (!joystick) { |
+ pad->connected = false; |
+ return; |
+ } |
+ |
+ pad->timestamp = joystick->report_id; |
+ pad->buttonsLength = joystick->buttons_length; |
+ pad->axesLength = joystick->axes_length; |
+ |
+ for (unsigned int i = 0; i < pad->buttonsLength; i++) |
+ pad->buttons[i] = joystick->buttons[i] ? 1.0 : 0.0; |
+ |
+ for (unsigned int i = 0; i < pad->axesLength; i++) |
+ pad->axes[i] = joystick->axes[i].value; |
} |
bool GamepadPlatformDataFetcherWin::GetXInputDllFunctions() { |