Chromium Code Reviews| 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() { |