diff options
Diffstat (limited to 'content')
9 files changed, 217 insertions, 262 deletions
diff --git a/content/browser/gamepad/gamepad_data_fetcher.cc b/content/browser/gamepad/gamepad_data_fetcher.cc new file mode 100644 index 0000000..2a654a8 --- /dev/null +++ b/content/browser/gamepad/gamepad_data_fetcher.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/gamepad/gamepad_data_fetcher.h" + +#include "base/logging.h" + +namespace { + +#if !defined(OS_ANDROID) +const float kMinAxisResetValue = 0.1f; +#endif + +} // namespace + +namespace content { + +using blink::WebGamepad; +using blink::WebGamepads; + +#if !defined(OS_ANDROID) +void GamepadDataFetcher::MapAndSanitizeGamepadData( + PadState* pad_state, WebGamepad* pad) { + DCHECK(pad_state); + DCHECK(pad); + + if (!pad_state->data.connected) { + memset(pad, 0, sizeof(WebGamepad)); + return; + } + + // Copy the current state to the output buffer, using the mapping + // function, if there is one available. + if (pad_state->mapper) + pad_state->mapper(pad_state->data, pad); + else + *pad = pad_state->data; + + // About sanitization: Gamepads may report input event if the user is not + // interacting with it, due to hardware problems or environmental ones (pad + // has something heavy leaning against an axis.) This may cause user gestures + // to be detected erroniously, exposing gamepad information when the user had + // no intention of doing so. To avoid this we require that each button or axis + // report being at rest (zero) at least once before exposing its value to the + // Gamepad API. This state is tracked by the axis_mask and button_mask + // bitfields. If the bit for an axis or button is 0 it means the axis has + // never reported being at rest, and the value will be forced to zero. + + // We can skip axis sanitation if all available axes have been masked. + uint32_t full_axis_mask = (1 << pad->axesLength) - 1; + if (pad_state->axis_mask != full_axis_mask) { + for (size_t axis = 0; axis < pad->axesLength; ++axis) { + if (!(pad_state->axis_mask & 1 << axis)) { + if (fabs(pad->axes[axis]) < kMinAxisResetValue) { + pad_state->axis_mask |= 1 << axis; + } else { + pad->axes[axis] = 0.0f; + } + } + } + } + + // We can skip button sanitation if all available buttons have been masked. + uint32_t full_button_mask = (1 << pad->buttonsLength) - 1; + if (pad_state->button_mask != full_button_mask) { + for (size_t button = 0; button < pad->buttonsLength; ++button) { + if (!(pad_state->button_mask & 1 << button)) { + if (!pad->buttons[button].pressed) { + pad_state->button_mask |= 1 << button; + } else { + pad->buttons[button].pressed = false; + pad->buttons[button].value = 0.0f; + } + } + } + } +} +#endif + +} // namespace content diff --git a/content/browser/gamepad/gamepad_data_fetcher.h b/content/browser/gamepad/gamepad_data_fetcher.h index 17887d5..a395fd9 100644 --- a/content/browser/gamepad/gamepad_data_fetcher.h +++ b/content/browser/gamepad/gamepad_data_fetcher.h @@ -5,9 +5,11 @@ #ifndef CONTENT_BROWSER_GAMEPAD_GAMEPAD_DATA_FETCHER_H_ #define CONTENT_BROWSER_GAMEPAD_GAMEPAD_DATA_FETCHER_H_ -namespace blink { -class WebGamepads; -} +#include <stdint.h> + +#include "build/build_config.h" +#include "content/browser/gamepad/gamepad_standard_mappings.h" +#include "third_party/WebKit/public/platform/WebGamepads.h" namespace content { @@ -19,6 +21,39 @@ class GamepadDataFetcher { virtual void GetGamepadData(blink::WebGamepads* pads, bool devices_changed_hint) = 0; virtual void PauseHint(bool paused) {} + +#if !defined(OS_ANDROID) + struct PadState { + // Gamepad data, unmapped. + blink::WebGamepad data; + + // Functions to map from device data to standard layout, if available. May + // be null if no mapping is available. + GamepadStandardMappingFunction mapper; + + // Sanitization masks + // axis_mask and button_mask are bitfields that represent the reset state of + // each input. If a button or axis has ever reported 0 in the past the + // corresponding bit will be set to 1. + + // If we ever increase the max axis count this will need to be updated. + static_assert(blink::WebGamepad::axesLengthCap <= + std::numeric_limits<uint32_t>::digits, + "axis_mask is not large enough"); + uint32_t axis_mask; + + // If we ever increase the max button count this will need to be updated. + static_assert(blink::WebGamepad::buttonsLengthCap <= + std::numeric_limits<uint32_t>::digits, + "button_mask is not large enough"); + uint32_t button_mask; + }; + + void MapAndSanitizeGamepadData(PadState* pad_state, blink::WebGamepad* pad); + + protected: + PadState pad_state_[blink::WebGamepads::itemsLengthCap]; +#endif }; } // namespace content diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc b/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc index 5196674..7b74c05 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc @@ -27,7 +27,6 @@ const char kInputSubsystem[] = "input"; const char kUsbSubsystem[] = "usb"; const char kUsbDeviceType[] = "usb_device"; const float kMaxLinuxAxisValue = 32767.0; -const float kMinAxisResetValue = 0.1; void CloseFileDescriptorIfValid(int fd) { if (fd >= 0) @@ -71,12 +70,10 @@ using blink::WebGamepads; GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { for (size_t i = 0; i < arraysize(pad_state_); ++i) { - pad_state_[i].device_fd = -1; + device_fd_[i] = -1; pad_state_[i].mapper = 0; - for (size_t j = 0; j < arraysize(pad_state_[i].is_axes_ever_reset); ++j) - pad_state_[i].is_axes_ever_reset[j] = false; - for (size_t j = 0; j < arraysize(pad_state_[i].is_buttons_ever_reset); ++j) - pad_state_[i].is_buttons_ever_reset[j] = false; + pad_state_[i].axis_mask = 0; + pad_state_[i].button_mask = 0; } std::vector<UdevLinux::UdevMonitorFilter> filters; @@ -91,34 +88,7 @@ GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() { GamepadPlatformDataFetcherLinux::~GamepadPlatformDataFetcherLinux() { for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) - CloseFileDescriptorIfValid(pad_state_[i].device_fd); -} - -void GamepadPlatformDataFetcherLinux::SanitizeGamepadData(size_t index, - WebGamepad* pad) { - bool* axes_reset = pad_state_[index].is_axes_ever_reset; - bool* buttons_reset = pad_state_[index].is_buttons_ever_reset; - - for (size_t axis = 0; axis < pad->axesLength; ++axis) { - if (!axes_reset[axis]) { - if (fabs(pad->axes[axis]) < kMinAxisResetValue) { - axes_reset[axis] = true; - } else { - pad->axes[axis] = 0.0f; - } - } - } - - for (size_t button = 0; button < pad->buttonsLength; ++button) { - if (!buttons_reset[button]) { - if (!pad->buttons[button].pressed) { - buttons_reset[button] = true; - } else { - pad->buttons[button].pressed = false; - pad->buttons[button].value = 0.0f; - } - } - } + CloseFileDescriptorIfValid(device_fd_[i]); } void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) { @@ -126,20 +96,14 @@ void GamepadPlatformDataFetcherLinux::GetGamepadData(WebGamepads* pads, bool) { // Update our internal state. for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { - if (pad_state_[i].device_fd >= 0) { + if (device_fd_[i] >= 0) { ReadDeviceData(i); } } - // Copy to the current state to the output buffer, using the mapping - // function, if there is one available. pads->length = WebGamepads::itemsLengthCap; for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { - if (pad_state_[i].mapper) - pad_state_[i].mapper(pad_state_[i].data, &pads->items[i]); - else - pads->items[i] = pad_state_[i].data; - SanitizeGamepadData(i, &pads->items[i]); + MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]); } } @@ -148,11 +112,9 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { int index; std::string node_path; if (IsGamepad(dev, &index, &node_path)) { - int& device_fd = pad_state_[index].device_fd; + int& device_fd = device_fd_[index]; WebGamepad& pad = pad_state_[index].data; GamepadStandardMappingFunction& mapper = pad_state_[index].mapper; - bool* axes_reset = pad_state_[index].is_axes_ever_reset; - bool* buttons_reset = pad_state_[index].is_buttons_ever_reset; CloseFileDescriptorIfValid(device_fd); @@ -237,10 +199,8 @@ void GamepadPlatformDataFetcherLinux::RefreshDevice(udev_device* dev) { pad.mapping[0] = 0; } - for (size_t j = 0; j < blink::WebGamepad::axesLengthCap; ++j) - axes_reset[j] = false; - for (size_t j = 0; j < blink::WebGamepad::buttonsLengthCap; ++j) - buttons_reset[j] = false; + pad_state_[index].axis_mask = 0; + pad_state_[index].button_mask = 0; pad.connected = true; } @@ -281,7 +241,7 @@ void GamepadPlatformDataFetcherLinux::ReadDeviceData(size_t index) { return; } - const int& fd = pad_state_[index].device_fd; + const int& fd = device_fd_[index]; WebGamepad& pad = pad_state_[index].data; DCHECK_GE(fd, 0); diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h b/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h index 251b3a1..0878546 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h @@ -11,8 +11,6 @@ #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "content/browser/gamepad/gamepad_data_fetcher.h" -#include "content/browser/gamepad/gamepad_standard_mappings.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" extern "C" { struct udev_device; @@ -35,23 +33,9 @@ class GamepadPlatformDataFetcherLinux : public GamepadDataFetcher { void RefreshDevice(udev_device* dev); void EnumerateDevices(); void ReadDeviceData(size_t index); - void SanitizeGamepadData(size_t index, blink::WebGamepad* pad); - struct PadState { - // File descriptor for the /dev/input/js* devices. -1 if not in use. - int device_fd; - - // Functions to map from device data to standard layout, if available. May - // be null if no mapping is available. - GamepadStandardMappingFunction mapper; - - bool is_axes_ever_reset[blink::WebGamepad::axesLengthCap]; - bool is_buttons_ever_reset[blink::WebGamepad::buttonsLengthCap]; - - // Data that's returned to the consumer. - blink::WebGamepad data; - }; - PadState pad_state_[blink::WebGamepads::itemsLengthCap]; + // File descriptor for the /dev/input/js* devices. -1 if not in use. + int device_fd_[blink::WebGamepads::itemsLengthCap]; scoped_ptr<UdevLinux> udev_; diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h b/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h index 302a6c1..af2ad0d 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_mac.h @@ -11,10 +11,8 @@ #include "base/memory/scoped_ptr.h" #include "build/build_config.h" #include "content/browser/gamepad/gamepad_data_fetcher.h" -#include "content/browser/gamepad/gamepad_standard_mappings.h" #include "content/browser/gamepad/xbox_data_fetcher_mac.h" #include "content/common/gamepad_hardware_buffer.h" -#include "third_party/WebKit/public/platform/WebGamepads.h" #include <CoreFoundation/CoreFoundation.h> #include <IOKit/hid/IOHIDManager.h> @@ -76,8 +74,6 @@ class GamepadPlatformDataFetcherMac : public GamepadDataFetcher, scoped_ptr<XboxDataFetcher> xbox_fetcher_; - blink::WebGamepads data_; - // Side-band data that's not passed to the consumer, but we need to maintain // to update data_. struct AssociatedData { @@ -89,17 +85,12 @@ class GamepadPlatformDataFetcherMac : public GamepadDataFetcher, IOHIDElementRef axis_elements[blink::WebGamepad::axesLengthCap]; CFIndex axis_minimums[blink::WebGamepad::axesLengthCap]; CFIndex axis_maximums[blink::WebGamepad::axesLengthCap]; - // Function to map from device data to standard layout, if available. - // May be null if no mapping is available. - GamepadStandardMappingFunction mapper; } hid; struct { XboxController* device; UInt32 location_id; } xbox; }; - bool is_axes_ever_reset[blink::WebGamepad::axesLengthCap]; - bool is_buttons_ever_reset[blink::WebGamepad::buttonsLengthCap]; }; AssociatedData associated_[blink::WebGamepads::itemsLengthCap]; diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm b/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm index 5c27631..e18caf5 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm @@ -50,8 +50,6 @@ const uint32_t kGameUsageNumber = 0x05; const uint32_t kMultiAxisUsageNumber = 0x08; const uint32_t kAxisMinimumUsageNumber = 0x30; -const float kMinAxisResetValue = 0.1; - } // namespace GamepadPlatformDataFetcherMac::GamepadPlatformDataFetcherMac() @@ -156,7 +154,7 @@ void GamepadPlatformDataFetcherMac::ValueChangedCallback(void* context, bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, size_t slot) { - WebGamepad& pad = data_.items[slot]; + WebGamepad& pad = pad_state_[slot].data; AssociatedData& associated = associated_[slot]; CHECK(!associated.is_xbox); @@ -230,7 +228,7 @@ bool GamepadPlatformDataFetcherMac::AddButtonsAndAxes(NSArray* elements, size_t GamepadPlatformDataFetcherMac::GetEmptySlot() { // Find a free slot for this device. for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { - if (!data_.items[slot].connected) + if (!pad_state_[slot].data.connected) return slot; } return WebGamepads::itemsLengthCap; @@ -240,7 +238,7 @@ size_t GamepadPlatformDataFetcherMac::GetSlotForDevice(IOHIDDeviceRef device) { for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { // If we already have this device, and it's already connected, don't do // anything now. - if (data_.items[slot].connected && + if (pad_state_[slot].data.connected && !associated_[slot].is_xbox && associated_[slot].hid.device_ref == device) return WebGamepads::itemsLengthCap; @@ -253,7 +251,7 @@ size_t GamepadPlatformDataFetcherMac::GetSlotForXboxDevice( for (size_t slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { if (associated_[slot].is_xbox && associated_[slot].xbox.location_id == device->location_id()) { - if (data_.items[slot].connected) { + if (pad_state_[slot].data.connected) { // The device is already connected. No idea why we got a second "device // added" call, but let's not add it twice. DCHECK_EQ(associated_[slot].xbox.device, device); @@ -297,27 +295,27 @@ void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) { char vendor_as_str[5], product_as_str[5]; snprintf(vendor_as_str, sizeof(vendor_as_str), "%04x", vendor_int); snprintf(product_as_str, sizeof(product_as_str), "%04x", product_int); - associated_[slot].hid.mapper = + pad_state_[slot].mapper = GetGamepadStandardMappingFunction(vendor_as_str, product_as_str); NSString* ident = [NSString stringWithFormat: @"%@ (%sVendor: %04x Product: %04x)", product, - associated_[slot].hid.mapper ? "STANDARD GAMEPAD " : "", + pad_state_[slot].mapper ? "STANDARD GAMEPAD " : "", vendor_int, product_int]; CopyNSStringAsUTF16LittleEndian( ident, - data_.items[slot].id, - sizeof(data_.items[slot].id)); + pad_state_[slot].data.id, + sizeof(pad_state_[slot].data.id)); - if (associated_[slot].hid.mapper) { + if (pad_state_[slot].mapper) { CopyNSStringAsUTF16LittleEndian( @"standard", - data_.items[slot].mapping, - sizeof(data_.items[slot].mapping)); + pad_state_[slot].data.mapping, + sizeof(pad_state_[slot].data.mapping)); } else { - data_.items[slot].mapping[0] = 0; + pad_state_[slot].data.mapping[0] = 0; } base::ScopedCFTypeRef<CFArrayRef> elements( @@ -327,14 +325,9 @@ void GamepadPlatformDataFetcherMac::DeviceAdd(IOHIDDeviceRef device) { return; associated_[slot].hid.device_ref = device; - data_.items[slot].connected = true; - if (slot >= data_.length) - data_.length = slot + 1; - - for (size_t j = 0; j < blink::WebGamepad::axesLengthCap; ++j) - associated_[slot].is_axes_ever_reset[j] = false; - for (size_t j = 0; j < blink::WebGamepad::buttonsLengthCap; ++j) - associated_[slot].is_buttons_ever_reset[j] = false; + pad_state_[slot].data.connected = true; + pad_state_[slot].axis_mask = 0; + pad_state_[slot].button_mask = 0; } void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) { @@ -344,7 +337,7 @@ void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) { // Find the index for this device. size_t slot; for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { - if (data_.items[slot].connected && + if (pad_state_[slot].data.connected && !associated_[slot].is_xbox && associated_[slot].hid.device_ref == device) break; @@ -352,7 +345,7 @@ void GamepadPlatformDataFetcherMac::DeviceRemove(IOHIDDeviceRef device) { DCHECK(slot < WebGamepads::itemsLengthCap); // Leave associated device_ref so that it will be reconnected in the same // location. Simply mark it as disconnected. - data_.items[slot].connected = false; + pad_state_[slot].data.connected = false; } void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) { @@ -364,16 +357,16 @@ void GamepadPlatformDataFetcherMac::ValueChanged(IOHIDValueRef value) { // Find device slot. size_t slot; - for (slot = 0; slot < data_.length; ++slot) { - if (data_.items[slot].connected && + for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { + if (pad_state_[slot].data.connected && !associated_[slot].is_xbox && associated_[slot].hid.device_ref == device) break; } - if (slot == data_.length) + if (slot == WebGamepads::itemsLengthCap) return; - WebGamepad& pad = data_.items[slot]; + WebGamepad& pad = pad_state_[slot].data; AssociatedData& associated = associated_[slot]; uint32_t value_length = IOHIDValueGetLength(value); @@ -427,28 +420,24 @@ void GamepadPlatformDataFetcherMac::XboxDeviceAdd(XboxController* device) { device->GetProductId(), device->GetVendorId()]; CopyNSStringAsUTF16LittleEndian( ident, - data_.items[slot].id, - sizeof(data_.items[slot].id)); + pad_state_[slot].data.id, + sizeof(pad_state_[slot].data.id)); CopyNSStringAsUTF16LittleEndian( @"standard", - data_.items[slot].mapping, - sizeof(data_.items[slot].mapping)); + pad_state_[slot].data.mapping, + sizeof(pad_state_[slot].data.mapping)); associated_[slot].is_xbox = true; associated_[slot].xbox.device = device; associated_[slot].xbox.location_id = device->location_id(); - data_.items[slot].connected = true; - data_.items[slot].axesLength = 4; - data_.items[slot].buttonsLength = 17; - data_.items[slot].timestamp = 0; - if (slot >= data_.length) - data_.length = slot + 1; - - for (size_t j = 0; j < blink::WebGamepad::axesLengthCap; ++j) - associated_[slot].is_axes_ever_reset[j] = false; - for (size_t j = 0; j < blink::WebGamepad::buttonsLengthCap; ++j) - associated_[slot].is_buttons_ever_reset[j] = false; + pad_state_[slot].data.connected = true; + pad_state_[slot].data.axesLength = 4; + pad_state_[slot].data.buttonsLength = 17; + pad_state_[slot].data.timestamp = 0; + pad_state_[slot].mapper = 0; + pad_state_[slot].axis_mask = 0; + pad_state_[slot].button_mask = 0; } void GamepadPlatformDataFetcherMac::XboxDeviceRemove(XboxController* device) { @@ -458,7 +447,7 @@ void GamepadPlatformDataFetcherMac::XboxDeviceRemove(XboxController* device) { // Find the index for this device. size_t slot; for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { - if (data_.items[slot].connected && + if (pad_state_[slot].data.connected && associated_[slot].is_xbox && associated_[slot].xbox.device == device) break; @@ -466,23 +455,23 @@ void GamepadPlatformDataFetcherMac::XboxDeviceRemove(XboxController* device) { DCHECK(slot < WebGamepads::itemsLengthCap); // Leave associated location id so that the controller will be reconnected in // the same slot if it is plugged in again. Simply mark it as disconnected. - data_.items[slot].connected = false; + pad_state_[slot].data.connected = false; } void GamepadPlatformDataFetcherMac::XboxValueChanged( XboxController* device, const XboxController::Data& data) { // Find device slot. size_t slot; - for (slot = 0; slot < data_.length; ++slot) { - if (data_.items[slot].connected && + for (slot = 0; slot < WebGamepads::itemsLengthCap; ++slot) { + if (pad_state_[slot].data.connected && associated_[slot].is_xbox && associated_[slot].xbox.device == device) break; } - if (slot == data_.length) + if (slot == WebGamepads::itemsLengthCap) return; - WebGamepad& pad = data_.items[slot]; + WebGamepad& pad = pad_state_[slot].data; for (size_t i = 0; i < 6; i++) { pad.buttons[i].pressed = data.buttons[i]; @@ -503,50 +492,15 @@ void GamepadPlatformDataFetcherMac::XboxValueChanged( pad.timestamp = base::TimeTicks::Now().ToInternalValue(); } -void GamepadPlatformDataFetcherMac::SanitizeGamepadData(size_t index, - WebGamepad* pad) { - bool* axes_reset = associated_[index].is_axes_ever_reset; - bool* buttons_reset = associated_[index].is_buttons_ever_reset; - - for (size_t axis = 0; axis < pad->axesLength; ++axis) { - if (!axes_reset[axis]) { - if (fabs(pad->axes[axis]) < kMinAxisResetValue) { - axes_reset[axis] = true; - } else { - pad->axes[axis] = 0.0f; - } - } - } - - for (size_t button = 0; button < pad->buttonsLength; ++button) { - if (!buttons_reset[button]) { - if (!pad->buttons[button].pressed) { - buttons_reset[button] = true; - } else { - pad->buttons[button].pressed = false; - pad->buttons[button].value = 0.0f; - } - } - } -} - void GamepadPlatformDataFetcherMac::GetGamepadData(WebGamepads* pads, bool) { if (!enabled_ && !xbox_fetcher_) { pads->length = 0; return; } - // Copy to the current state to the output buffer, using the mapping - // function, if there is one available. pads->length = WebGamepads::itemsLengthCap; - for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { - if (!associated_[i].is_xbox && associated_[i].hid.mapper) - associated_[i].hid.mapper(data_.items[i], &pads->items[i]); - else - pads->items[i] = data_.items[i]; - - SanitizeGamepadData(i, &pads->items[i]); - } + for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) + MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]); } } // namespace content diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc b/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc index 7372126..3945489 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc @@ -58,11 +58,10 @@ GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin() : xinput_dll_(base::FilePath(FILE_PATH_LITERAL("xinput1_3.dll"))), xinput_available_(GetXInputDllFunctions()) { for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { - pad_state_[i].status = DISCONNECTED; - for (size_t j = 0; j < arraysize(pad_state_[i].is_axes_ever_reset); ++j) - pad_state_[i].is_axes_ever_reset[j] = false; - for (size_t j = 0; j < arraysize(pad_state_[i].is_buttons_ever_reset); ++j) - pad_state_[i].is_buttons_ever_reset[j] = false; + platform_pad_state_[i].status = DISCONNECTED; + pad_state_[i].mapper = NULL; + pad_state_[i].axis_mask = 0; + pad_state_[i].button_mask = 0; } raw_input_fetcher_.reset(new RawInputDataFetcher()); @@ -75,7 +74,7 @@ GamepadPlatformDataFetcherWin::~GamepadPlatformDataFetcherWin() { int GamepadPlatformDataFetcherWin::FirstAvailableGamepadId() const { for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { - if (pad_state_[i].status == DISCONNECTED) + if (platform_pad_state_[i].status == DISCONNECTED) return i; } return -1; @@ -83,8 +82,8 @@ int GamepadPlatformDataFetcherWin::FirstAvailableGamepadId() const { bool GamepadPlatformDataFetcherWin::HasXInputGamepad(int index) const { for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { - if (pad_state_[i].status == XINPUT_CONNECTED && - pad_state_[i].xinput_index == index) + if (platform_pad_state_[i].status == XINPUT_CONNECTED && + platform_pad_state_[i].xinput_index == index) return true; } return false; @@ -93,21 +92,20 @@ bool GamepadPlatformDataFetcherWin::HasXInputGamepad(int index) const { 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].raw_input_handle == handle) + if (platform_pad_state_[i].status == RAWINPUT_CONNECTED && + platform_pad_state_[i].raw_input_handle == handle) return true; } return false; } -void GamepadPlatformDataFetcherWin::EnumerateDevices( - WebGamepads* pads) { +void GamepadPlatformDataFetcherWin::EnumerateDevices() { TRACE_EVENT0("GAMEPAD", "EnumerateDevices"); // Mark all disconnected pads DISCONNECTED. for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) { - if (!pads->items[i].connected) - pad_state_[i].status = DISCONNECTED; + if (!pad_state_[i].data.connected) + platform_pad_state_[i].status = DISCONNECTED; } for (size_t i = 0; i < XUSER_MAX_COUNT; ++i) { @@ -116,18 +114,14 @@ void GamepadPlatformDataFetcherWin::EnumerateDevices( int pad_index = FirstAvailableGamepadId(); if (pad_index == -1) return; // We can't add any more gamepads. - WebGamepad& pad = pads->items[pad_index]; + WebGamepad& pad = pad_state_[pad_index].data; if (xinput_available_ && GetXInputPadConnectivity(i, &pad)) { - pad_state_[pad_index].status = XINPUT_CONNECTED; - pad_state_[pad_index].xinput_index = i; + platform_pad_state_[pad_index].status = XINPUT_CONNECTED; + platform_pad_state_[pad_index].xinput_index = i; pad_state_[pad_index].mapper = NULL; + pad_state_[pad_index].axis_mask = 0; + pad_state_[pad_index].button_mask = 0; } - bool* axes_reset = pad_state_[pad_index].is_axes_ever_reset; - bool* buttons_reset = pad_state_[pad_index].is_buttons_ever_reset; - for (size_t j = 0; j < blink::WebGamepad::axesLengthCap; ++j) - axes_reset[j] = false; - for (size_t j = 0; j < blink::WebGamepad::buttonsLengthCap; ++j) - buttons_reset[j] = false; } if (raw_input_fetcher_->Available()) { @@ -142,15 +136,18 @@ void GamepadPlatformDataFetcherWin::EnumerateDevices( int pad_index = FirstAvailableGamepadId(); if (pad_index == -1) return; - WebGamepad& pad = pads->items[pad_index]; + WebGamepad& pad = pad_state_[pad_index].data; pad.connected = true; PadState& state = pad_state_[pad_index]; - state.status = RAWINPUT_CONNECTED; - state.raw_input_handle = gamepad->handle; + PlatformPadState& platform_state = platform_pad_state_[pad_index]; + platform_state.status = RAWINPUT_CONNECTED; + platform_state.raw_input_handle = gamepad->handle; 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)", @@ -161,40 +158,6 @@ void GamepadPlatformDataFetcherWin::EnumerateDevices( swprintf(pad.mapping, WebGamepad::mappingLengthCap, L"standard"); else pad.mapping[0] = 0; - - bool* axes_reset = pad_state_[pad_index].is_axes_ever_reset; - bool* buttons_reset = pad_state_[pad_index].is_buttons_ever_reset; - for (size_t j = 0; j < blink::WebGamepad::axesLengthCap; ++j) - axes_reset[j] = false; - for (size_t j = 0; j < blink::WebGamepad::buttonsLengthCap; ++j) - buttons_reset[j] = false; - } - } -} - -void GamepadPlatformDataFetcherWin::SanitizeGamepadData(size_t index, - WebGamepad* pad) { - bool* axes_reset = pad_state_[index].is_axes_ever_reset; - bool* buttons_reset = pad_state_[index].is_buttons_ever_reset; - - for (size_t axis = 0; axis < pad->axesLength; ++axis) { - if (!axes_reset[axis]) { - if (fabs(pad->axes[axis]) < kMinAxisResetValue) { - axes_reset[axis] = true; - } else { - pad->axes[axis] = 0.0f; - } - } - } - - for (size_t button = 0; button < pad->buttonsLength; ++button) { - if (!buttons_reset[button]) { - if (!pad->buttons[button].pressed) { - buttons_reset[button] = true; - } else { - pad->buttons[button].pressed = false; - pad->buttons[button].value = 0.0f; - } } } } @@ -217,7 +180,7 @@ 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(); pads->length = 0; @@ -225,15 +188,15 @@ void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads, // 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 (!pads->items[i].connected) + if (!pad_state_[i].data.connected) continue; - if (pad_state_[i].status == XINPUT_CONNECTED) - GetXInputPadData(i, &pads->items[i]); - else if (pad_state_[i].status == RAWINPUT_CONNECTED) - GetRawInputPadData(i, &pads->items[i]); + if (platform_pad_state_[i].status == XINPUT_CONNECTED) + GetXInputPadData(i, &pad_state_[i].data); + else if (platform_pad_state_[i].status == RAWINPUT_CONNECTED) + GetRawInputPadData(i, &pad_state_[i].data); - SanitizeGamepadData(i, &pads->items[i]); + MapAndSanitizeGamepadData(&pad_state_[i], &pads->items[i]); if (pads->items[i].connected) pads->length++; @@ -274,15 +237,15 @@ void GamepadPlatformDataFetcherWin::GetXInputPadData( XINPUT_STATE state; memset(&state, 0, sizeof(XINPUT_STATE)); TRACE_EVENT_BEGIN1("GAMEPAD", "XInputGetState", "id", i); - DWORD dwResult = xinput_get_state_(pad_state_[i].xinput_index, &state); + DWORD dwResult = xinput_get_state_(platform_pad_state_[i].xinput_index, + &state); TRACE_EVENT_END1("GAMEPAD", "XInputGetState", "id", i); if (dwResult == ERROR_SUCCESS) { pad->timestamp = state.dwPacketNumber; pad->buttonsLength = 0; WORD val = state.Gamepad.wButtons; -#define ADD(b) if (!val) \ - pad->buttons[pad->buttonsLength].pressed = (val & (b)) != 0; \ +#define ADD(b) pad->buttons[pad->buttonsLength].pressed = (val & (b)) != 0; \ pad->buttons[pad->buttonsLength++].value = ((val & (b)) ? 1.f : 0.f); ADD(XINPUT_GAMEPAD_A); ADD(XINPUT_GAMEPAD_B); @@ -331,32 +294,23 @@ void GamepadPlatformDataFetcherWin::GetRawInputPadData( int index, WebGamepad* pad) { RawGamepadInfo* gamepad = raw_input_fetcher_->GetGamepadInfo( - pad_state_[index].raw_input_handle); + platform_pad_state_[index].raw_input_handle); if (!gamepad) { pad->connected = false; return; } - WebGamepad raw_pad = *pad; - - raw_pad.timestamp = gamepad->report_id; - raw_pad.buttonsLength = gamepad->buttons_length; - raw_pad.axesLength = gamepad->axes_length; + pad->timestamp = gamepad->report_id; + pad->buttonsLength = gamepad->buttons_length; + pad->axesLength = gamepad->axes_length; - for (unsigned int i = 0; i < raw_pad.buttonsLength; i++) { - raw_pad.buttons[i].pressed = gamepad->buttons[i]; - raw_pad.buttons[i].value = gamepad->buttons[i] ? 1.0 : 0.0; + 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 < raw_pad.axesLength; i++) - raw_pad.axes[i] = gamepad->axes[i].value; - - // Copy to the current state to the output buffer, using the mapping - // function, if there is one available. - if (pad_state_[index].mapper) - pad_state_[index].mapper(raw_pad, pad); - else - *pad = raw_pad; + for (unsigned int i = 0; i < pad->axesLength; i++) + pad->axes[i] = gamepad->axes[i].value; } bool GamepadPlatformDataFetcherWin::GetXInputDllFunctions() { diff --git a/content/browser/gamepad/gamepad_platform_data_fetcher_win.h b/content/browser/gamepad/gamepad_platform_data_fetcher_win.h index a668366..6680f99 100644 --- a/content/browser/gamepad/gamepad_platform_data_fetcher_win.h +++ b/content/browser/gamepad/gamepad_platform_data_fetcher_win.h @@ -56,7 +56,7 @@ class GamepadPlatformDataFetcherWin : public GamepadDataFetcher { bool GetXInputDllFunctions(); // Scan for connected XInput and DirectInput gamepads. - void EnumerateDevices(blink::WebGamepads* pads); + void EnumerateDevices(); bool GetXInputPadConnectivity(int i, blink::WebGamepad* pad) const; void GetXInputPadData(int i, blink::WebGamepad* pad); @@ -65,7 +65,6 @@ class GamepadPlatformDataFetcherWin : public GamepadDataFetcher { int FirstAvailableGamepadId() const; bool HasXInputGamepad(int index) const; bool HasRawInputGamepad(const HANDLE handle) const; - void SanitizeGamepadData(size_t index, blink::WebGamepad* pad); base::ScopedNativeLibrary xinput_dll_; bool xinput_available_; @@ -82,17 +81,13 @@ class GamepadPlatformDataFetcherWin : public GamepadDataFetcher { RAWINPUT_CONNECTED }; - struct PadState { + struct PlatformPadState { PadConnectionStatus status; - GamepadStandardMappingFunction mapper; - - bool is_axes_ever_reset[blink::WebGamepad::axesLengthCap]; - bool is_buttons_ever_reset[blink::WebGamepad::buttonsLengthCap]; int xinput_index; // XInput-only HANDLE raw_input_handle; // RawInput-only fields. }; - PadState pad_state_[blink::WebGamepads::itemsLengthCap]; + PlatformPadState platform_pad_state_[blink::WebGamepads::itemsLengthCap]; scoped_ptr<RawInputDataFetcher> raw_input_fetcher_; diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 79c893d..383ba9b 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -735,6 +735,7 @@ 'browser/frame_host/render_widget_host_view_guest.h', 'browser/gamepad/gamepad_consumer.h', 'browser/gamepad/gamepad_data_fetcher.h', + 'browser/gamepad/gamepad_data_fetcher.cc', 'browser/gamepad/gamepad_platform_data_fetcher.h', 'browser/gamepad/gamepad_platform_data_fetcher_android.cc', 'browser/gamepad/gamepad_platform_data_fetcher_android.h', |