summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorbajones <bajones@chromium.org>2015-11-12 11:38:37 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-12 19:40:12 +0000
commit7d5976b00cf431b8dc1243533043b6bae682a401 (patch)
treeeff2fe6f3156c59e6ad9988edd0843054118438c /content
parent5788cd432cc28372aa85a57cd7a66e6b6699db74 (diff)
downloadchromium_src-7d5976b00cf431b8dc1243533043b6bae682a401.zip
chromium_src-7d5976b00cf431b8dc1243533043b6bae682a401.tar.gz
chromium_src-7d5976b00cf431b8dc1243533043b6bae682a401.tar.bz2
Refactoring gamepad support to have more shared code between platforms
BUG=529668 Review URL: https://codereview.chromium.org/1405233011 Cr-Commit-Position: refs/heads/master@{#359358}
Diffstat (limited to 'content')
-rw-r--r--content/browser/gamepad/gamepad_data_fetcher.cc81
-rw-r--r--content/browser/gamepad/gamepad_data_fetcher.h41
-rw-r--r--content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc60
-rw-r--r--content/browser/gamepad/gamepad_platform_data_fetcher_linux.h20
-rw-r--r--content/browser/gamepad/gamepad_platform_data_fetcher_mac.h9
-rw-r--r--content/browser/gamepad/gamepad_platform_data_fetcher_mac.mm126
-rw-r--r--content/browser/gamepad/gamepad_platform_data_fetcher_win.cc130
-rw-r--r--content/browser/gamepad/gamepad_platform_data_fetcher_win.h11
-rw-r--r--content/content_browser.gypi1
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',