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

Side by Side Diff: content/browser/gamepad/gamepad_platform_data_fetcher_win.cc

Issue 12260011: Support DirectInput gamepads on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 10 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/gamepad/gamepad_platform_data_fetcher_win.h" 5 #include "content/browser/gamepad/gamepad_platform_data_fetcher_win.h"
6 6
7 #include <dinput.h>
8 #include <dinputd.h>
9
7 #include "base/debug/trace_event.h" 10 #include "base/debug/trace_event.h"
11 #include "base/stringprintf.h"
8 #include "content/common/gamepad_messages.h" 12 #include "content/common/gamepad_messages.h"
9 #include "content/common/gamepad_hardware_buffer.h" 13 #include "content/common/gamepad_hardware_buffer.h"
10 14
11 namespace content { 15 namespace content {
12 16
13 using namespace WebKit; 17 using namespace WebKit;
14 18
15 namespace { 19 namespace {
16 20
17 // See http://goo.gl/5VSJR. These are not available in all versions of the 21 // See http://goo.gl/5VSJR. These are not available in all versions of the
18 // header, but they can be returned from the driver, so we define our own 22 // header, but they can be returned from the driver, so we define our own
19 // versions here. 23 // versions here.
20 static const BYTE kDeviceSubTypeGamepad = 1; 24 static const BYTE kDeviceSubTypeGamepad = 1;
21 static const BYTE kDeviceSubTypeWheel = 2; 25 static const BYTE kDeviceSubTypeWheel = 2;
22 static const BYTE kDeviceSubTypeArcadeStick = 3; 26 static const BYTE kDeviceSubTypeArcadeStick = 3;
23 static const BYTE kDeviceSubTypeFlightStick = 4; 27 static const BYTE kDeviceSubTypeFlightStick = 4;
24 static const BYTE kDeviceSubTypeDancePad = 5; 28 static const BYTE kDeviceSubTypeDancePad = 5;
25 static const BYTE kDeviceSubTypeGuitar = 6; 29 static const BYTE kDeviceSubTypeGuitar = 6;
26 static const BYTE kDeviceSubTypeGuitarAlternate = 7; 30 static const BYTE kDeviceSubTypeGuitarAlternate = 7;
27 static const BYTE kDeviceSubTypeDrumKit = 8; 31 static const BYTE kDeviceSubTypeDrumKit = 8;
28 static const BYTE kDeviceSubTypeGuitarBass = 11; 32 static const BYTE kDeviceSubTypeGuitarBass = 11;
29 static const BYTE kDeviceSubTypeArcadePad = 19; 33 static const BYTE kDeviceSubTypeArcadePad = 19;
30 34
31 float NormalizeAxis(SHORT value) { 35 float NormalizeXInputAxis(SHORT value) {
32 return ((value + 32768.f) / 32767.5f) - 1.f; 36 return ((value + 32768.f) / 32767.5f) - 1.f;
33 } 37 }
34 38
35 const WebUChar* const GamepadSubTypeName(BYTE sub_type) { 39 const WebUChar* const GamepadSubTypeName(BYTE sub_type) {
36 switch (sub_type) { 40 switch (sub_type) {
37 case kDeviceSubTypeGamepad: return L"GAMEPAD"; 41 case kDeviceSubTypeGamepad: return L"GAMEPAD";
38 case kDeviceSubTypeWheel: return L"WHEEL"; 42 case kDeviceSubTypeWheel: return L"WHEEL";
39 case kDeviceSubTypeArcadeStick: return L"ARCADE_STICK"; 43 case kDeviceSubTypeArcadeStick: return L"ARCADE_STICK";
40 case kDeviceSubTypeFlightStick: return L"FLIGHT_STICK"; 44 case kDeviceSubTypeFlightStick: return L"FLIGHT_STICK";
41 case kDeviceSubTypeDancePad: return L"DANCE_PAD"; 45 case kDeviceSubTypeDancePad: return L"DANCE_PAD";
42 case kDeviceSubTypeGuitar: return L"GUITAR"; 46 case kDeviceSubTypeGuitar: return L"GUITAR";
43 case kDeviceSubTypeGuitarAlternate: return L"GUITAR_ALTERNATE"; 47 case kDeviceSubTypeGuitarAlternate: return L"GUITAR_ALTERNATE";
44 case kDeviceSubTypeDrumKit: return L"DRUM_KIT"; 48 case kDeviceSubTypeDrumKit: return L"DRUM_KIT";
45 case kDeviceSubTypeGuitarBass: return L"GUITAR_BASS"; 49 case kDeviceSubTypeGuitarBass: return L"GUITAR_BASS";
46 case kDeviceSubTypeArcadePad: return L"ARCADE_PAD"; 50 case kDeviceSubTypeArcadePad: return L"ARCADE_PAD";
47 default: return L"<UNKNOWN>"; 51 default: return L"<UNKNOWN>";
48 } 52 }
49 } 53 }
50 54
55 bool GetDirectInputVendorProduct(IDirectInputDevice8* gamepad,
56 std::string* vendor,
57 std::string* product) {
58 DIPROPDWORD prop;
59 prop.diph.dwSize = sizeof(DIPROPDWORD);
60 prop.diph.dwHeaderSize = sizeof(DIPROPHEADER);
61 prop.diph.dwObj = 0;
62 prop.diph.dwHow = DIPH_DEVICE;
63
64 if (FAILED(gamepad->GetProperty(DIPROP_VIDPID, &prop.diph)))
65 return false;
66 *vendor = base::StringPrintf("%04x", LOWORD(prop.dwData));
67 *product = base::StringPrintf("%04x", HIWORD(prop.dwData));
68 return true;
69 }
70
71 // Sets the deadzone value for all axes of a gamepad.
72 // deadzone values range from 0 (no deadzone) to 10,000 (entire range
73 // is dead).
74 bool SetDirectInputDeadZone(IDirectInputDevice8* gamepad,
75 int deadzone) {
76 DIPROPDWORD prop;
77 prop.diph.dwSize = sizeof(DIPROPDWORD);
78 prop.diph.dwHeaderSize = sizeof(DIPROPHEADER);
79 prop.diph.dwObj = 0;
80 prop.diph.dwHow = DIPH_DEVICE;
81 prop.dwData = deadzone;
82 return SUCCEEDED(gamepad->SetProperty(DIPROP_DEADZONE, &prop.diph));
83 }
84
85 struct InternalDirectInputDevice {
86 IDirectInputDevice8* gamepad;
87 GamepadStandardMappingFunction mapper;
88 wchar_t id[WebGamepad::idLengthCap];
89 };
90
91 struct EnumDevicesContext {
92 IDirectInput8* directinput_interface;
93 std::vector<InternalDirectInputDevice>* directinput_devices;
94 };
95
96 // We define our own data format structure to attempt to get as many
97 // axes as possible.
98 struct JoyData {
99 long axes[10];
100 char buttons[24];
101 DWORD pov; // Often used for D-pads.
102 };
103
104 BOOL CALLBACK DirectInputEnumDevicesCallback(const DIDEVICEINSTANCE* instance,
105 void* context) {
106 EnumDevicesContext* ctxt = (EnumDevicesContext*) context;
107 IDirectInputDevice8* gamepad;
108 if (FAILED(ctxt->directinput_interface->CreateDevice(instance->guidInstance,
109 &gamepad,
110 NULL)))
111 return DIENUM_CONTINUE;
112
113 gamepad->Acquire();
114
115 #define MAKE_AXIS(i) \
116 {0, FIELD_OFFSET(JoyData, axes) + 4 * i, \
117 DIDFT_AXIS | DIDFT_MAKEINSTANCE(i) | DIDFT_OPTIONAL, 0}
118 #define MAKE_BUTTON(i) \
119 {&GUID_Button, FIELD_OFFSET(JoyData, buttons) + i, \
120 DIDFT_BUTTON | DIDFT_MAKEINSTANCE(i) | DIDFT_OPTIONAL, 0}
121 #define MAKE_POV() \
122 {&GUID_POV, FIELD_OFFSET(JoyData, pov), DIDFT_POV | DIDFT_OPTIONAL, 0}
123 DIOBJECTDATAFORMAT rgodf[] = {
124 MAKE_AXIS(0),
125 MAKE_AXIS(1),
126 MAKE_AXIS(2),
127 MAKE_AXIS(3),
128 MAKE_AXIS(4),
129 MAKE_AXIS(5),
130 MAKE_AXIS(6),
131 MAKE_AXIS(7),
132 MAKE_AXIS(8),
133 MAKE_AXIS(9),
134 MAKE_BUTTON(0),
135 MAKE_BUTTON(1),
136 MAKE_BUTTON(2),
137 MAKE_BUTTON(3),
138 MAKE_BUTTON(4),
139 MAKE_BUTTON(5),
140 MAKE_BUTTON(6),
141 MAKE_BUTTON(7),
142 MAKE_BUTTON(8),
143 MAKE_BUTTON(9),
144 MAKE_BUTTON(10),
145 MAKE_BUTTON(11),
146 MAKE_BUTTON(12),
147 MAKE_BUTTON(13),
148 MAKE_BUTTON(14),
149 MAKE_BUTTON(15),
150 MAKE_BUTTON(16),
151 MAKE_POV(),
152 };
153 #undef MAKE_AXIS
154 #undef MAKE_BUTTON
155 #undef MAKE_POV
156
157 DIDATAFORMAT df = {
158 sizeof (DIDATAFORMAT),
159 sizeof (DIOBJECTDATAFORMAT),
160 DIDF_ABSAXIS,
161 sizeof (JoyData),
162 sizeof (rgodf) / sizeof (rgodf[0]),
163 rgodf
164 };
165
166 // If we can't set the data format on the device, don't add it to our
167 // list, since we won't know how to read data from it.
168 if (FAILED(gamepad->SetDataFormat(&df))) {
169 gamepad->Release();
170 return DIENUM_CONTINUE;
171 }
172
173 InternalDirectInputDevice device;
174 device.gamepad = gamepad;
175 std::string vendor;
176 std::string product;
177 if (!GetDirectInputVendorProduct(gamepad, &vendor, &product)) {
178 gamepad->Release();
179 return DIENUM_CONTINUE;
180 }
181
182 // Set the dead zone to 10% of the axis length for all axes. This
183 // gives us a larger space for what's "neutral" so the controls don't
184 // slowly drift.
185 SetDirectInputDeadZone(gamepad, 1000);
186 device.mapper = GetGamepadStandardMappingFunction(vendor, product);
187 if (device.mapper) {
188 base::swprintf(device.id,
189 WebGamepad::idLengthCap,
190 L"STANDARD GAMEPAD (%ls)",
191 instance->tszProductName);
192 ctxt->directinput_devices->push_back(device);
193 } else {
194 gamepad->Release();
195 }
196 return DIENUM_CONTINUE;
197 }
198
51 } // namespace 199 } // namespace
52 200
53 GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin() 201 GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin()
54 : xinput_dll_(FilePath(FILE_PATH_LITERAL("xinput1_3.dll"))), 202 : xinput_dll_(FilePath(FILE_PATH_LITERAL("xinput1_3.dll"))),
55 xinput_available_(GetXinputDllFunctions()) { 203 xinput_available_(GetXInputDllFunctions()) {
204 directinput_available_ =
205 SUCCEEDED(DirectInput8Create(GetModuleHandle(NULL),
206 DIRECTINPUT_VERSION,
scottmg 2013/02/14 18:44:34 nit, parameter alignment
207 IID_IDirectInput8,
208 (void **)&directinput_interface_,
209 NULL));
56 } 210 }
57 211
58 GamepadPlatformDataFetcherWin::~GamepadPlatformDataFetcherWin() { 212 GamepadPlatformDataFetcherWin::~GamepadPlatformDataFetcherWin() {
59 } 213 }
60 214
215 void GamepadPlatformDataFetcherWin::EnumerateDevices(
216 WebGamepads* pads) {
217 TRACE_EVENT0("GAMEPAD", "EnumerateDevices");
218 pad_state_.clear();
219 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
220 PadState s;
221 s.status = DISCONNECTED;
222 pad_state_.push_back(s);
223 }
224
225 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
226 WebGamepad &pad = pads->items[i];
227 if (xinput_available_ && GetXInputPadConnectivity(i, &pad)) {
228 pad_state_[i].status = XINPUT_CONNECTED;
229 continue;
230 }
231 }
232
233 if (directinput_available_) {
234 struct EnumDevicesContext context;
235 std::vector<InternalDirectInputDevice> directinput_gamepads;
236 context.directinput_interface = directinput_interface_;
237 context.directinput_devices = &directinput_gamepads;
238
239 directinput_interface_->EnumDevices(
240 DI8DEVCLASS_GAMECTRL,
241 &DirectInputEnumDevicesCallback,
242 &context,
243 DIEDFL_ATTACHEDONLY);
244
245 // Fill the "disconnected" pad state entries with our DirectInput
246 // gamepads.
247 unsigned pad_state_index = 0;
248 unsigned directinput_index = 0;
249 while (pad_state_index < WebGamepads::itemsLengthCap &&
250 directinput_index < directinput_gamepads.size()) {
251 if (pad_state_[pad_state_index].status != DISCONNECTED) {
252 ++pad_state_index;
253 continue;
254 }
255 WebGamepad &pad = pads->items[pad_state_index];
256 pad.connected = true;
257 wcscpy_s(pad.id, WebGamepad::idLengthCap,
258 directinput_gamepads[directinput_index].id);
259 PadState &state = pad_state_[pad_state_index];
260 state.status = DIRECTINPUT_CONNECTED;
261 state.directinput_gamepad =
262 directinput_gamepads[directinput_index].gamepad;
263 state.mapper = directinput_gamepads[directinput_index].mapper;
264 ++directinput_index;
265 ++pad_state_index;
266 }
267 }
268 }
269
270
61 void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads, 271 void GamepadPlatformDataFetcherWin::GetGamepadData(WebGamepads* pads,
62 bool devices_changed_hint) { 272 bool devices_changed_hint) {
63 TRACE_EVENT0("GAMEPAD", "GetGamepadData"); 273 TRACE_EVENT0("GAMEPAD", "GetGamepadData");
64 274
65 // If there's no XInput DLL on the system, early out so that we don't 275 if (!xinput_available_ && !directinput_available_) {
66 // call any other XInput functions.
67 if (!xinput_available_) {
68 pads->length = 0; 276 pads->length = 0;
69 return; 277 return;
70 } 278 }
71 279
72 pads->length = WebGamepads::itemsLengthCap; 280 // A note on XInput devices:
73
74 // If we got notification that system devices have been updated, then 281 // If we got notification that system devices have been updated, then
75 // run GetCapabilities to update the connected status and the device 282 // run GetCapabilities to update the connected status and the device
76 // identifier. It can be slow to do to both GetCapabilities and 283 // identifier. It can be slow to do to both GetCapabilities and
77 // GetState on unconnected devices, so we want to avoid a 2-5ms pause 284 // GetState on unconnected devices, so we want to avoid a 2-5ms pause
78 // here by only doing this when the devices are updated (despite 285 // here by only doing this when the devices are updated (despite
79 // documentation claiming it's OK to call it any time). 286 // documentation claiming it's OK to call it any time).
80 if (devices_changed_hint) { 287 if (devices_changed_hint)
81 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) { 288 EnumerateDevices(pads);
82 WebGamepad& pad = pads->items[i]; 289
83 TRACE_EVENT1("GAMEPAD", "GetCapabilities", "id", i);
84 XINPUT_CAPABILITIES caps;
85 DWORD res = xinput_get_capabilities_(i, XINPUT_FLAG_GAMEPAD, &caps);
86 if (res == ERROR_DEVICE_NOT_CONNECTED) {
87 pad.connected = false;
88 } else {
89 pad.connected = true;
90 base::swprintf(pad.id,
91 WebGamepad::idLengthCap,
92 L"Xbox 360 Controller (XInput STANDARD %ls)",
93 GamepadSubTypeName(caps.SubType));
94 }
95 }
96 }
97
98 // We've updated the connection state if necessary, now update the actual
99 // data for the devices that are connected.
100 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) { 290 for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
101 WebGamepad& pad = pads->items[i]; 291 WebGamepad& pad = pads->items[i];
102 292 if (pad_state_[i].status == XINPUT_CONNECTED)
103 // We rely on device_changed and GetCapabilities to tell us that 293 GetXInputPadData(i, &pad);
104 // something's been connected, but we will mark as disconnected if 294 else if (pad_state_[i].status == DIRECTINPUT_CONNECTED)
105 // GetState returns that we've lost the pad. 295 GetDirectInputPadData(i, &pad);
106 if (!pad.connected) 296 }
107 continue; 297 pads->length = WebGamepads::itemsLengthCap;
108 298 }
109 XINPUT_STATE state; 299
110 memset(&state, 0, sizeof(XINPUT_STATE)); 300 bool GamepadPlatformDataFetcherWin::GetXInputPadConnectivity(
111 TRACE_EVENT_BEGIN1("GAMEPAD", "XInputGetState", "id", i); 301 int i,
112 DWORD dwResult = xinput_get_state_(i, &state); 302 WebGamepad* pad) const {
113 TRACE_EVENT_END1("GAMEPAD", "XInputGetState", "id", i); 303 DCHECK(pad);
114 304 TRACE_EVENT1("GAMEPAD", "GetXInputPadConnectivity", "id", i);
115 if (dwResult == ERROR_SUCCESS) { 305 XINPUT_CAPABILITIES caps;
116 pad.timestamp = state.dwPacketNumber; 306 DWORD res = xinput_get_capabilities_(i, XINPUT_FLAG_GAMEPAD, &caps);
117 pad.buttonsLength = 0; 307 if (res == ERROR_DEVICE_NOT_CONNECTED) {
118 #define ADD(b) pad.buttons[pad.buttonsLength++] = \ 308 pad->connected = false;
119 ((state.Gamepad.wButtons & (b)) ? 1.0 : 0.0); 309 return false;
120 ADD(XINPUT_GAMEPAD_A); 310 } else {
121 ADD(XINPUT_GAMEPAD_B); 311 pad->connected = true;
122 ADD(XINPUT_GAMEPAD_X); 312 base::swprintf(pad->id,
123 ADD(XINPUT_GAMEPAD_Y); 313 WebGamepad::idLengthCap,
124 ADD(XINPUT_GAMEPAD_LEFT_SHOULDER); 314 L"Xbox 360 Controller (XInput STANDARD %ls)",
125 ADD(XINPUT_GAMEPAD_RIGHT_SHOULDER); 315 GamepadSubTypeName(caps.SubType));
126 pad.buttons[pad.buttonsLength++] = state.Gamepad.bLeftTrigger / 255.0; 316 return true;
127 pad.buttons[pad.buttonsLength++] = state.Gamepad.bRightTrigger / 255.0; 317 }
128 ADD(XINPUT_GAMEPAD_BACK); 318 }
129 ADD(XINPUT_GAMEPAD_START); 319
130 ADD(XINPUT_GAMEPAD_LEFT_THUMB); 320 void GamepadPlatformDataFetcherWin::GetXInputPadData(
131 ADD(XINPUT_GAMEPAD_RIGHT_THUMB); 321 int i,
132 ADD(XINPUT_GAMEPAD_DPAD_UP); 322 WebGamepad* pad) {
133 ADD(XINPUT_GAMEPAD_DPAD_DOWN); 323 // We rely on device_changed and GetCapabilities to tell us that
134 ADD(XINPUT_GAMEPAD_DPAD_LEFT); 324 // something's been connected, but we will mark as disconnected if
135 ADD(XINPUT_GAMEPAD_DPAD_RIGHT); 325 // GetState returns that we've lost the pad.
326 if (!pad->connected)
327 return;
328
329 XINPUT_STATE state;
330 memset(&state, 0, sizeof(XINPUT_STATE));
331 TRACE_EVENT_BEGIN1("GAMEPAD", "XInputGetState", "id", i);
332 DWORD dwResult = xinput_get_state_(i, &state);
333 TRACE_EVENT_END1("GAMEPAD", "XInputGetState", "id", i);
334
335 if (dwResult == ERROR_SUCCESS) {
336 pad->timestamp = state.dwPacketNumber;
337 pad->buttonsLength = 0;
338 #define ADD(b) pad->buttons[pad->buttonsLength++] = \
339 ((state.Gamepad.wButtons & (b)) ? 1.0 : 0.0);
340 ADD(XINPUT_GAMEPAD_A);
341 ADD(XINPUT_GAMEPAD_B);
342 ADD(XINPUT_GAMEPAD_X);
343 ADD(XINPUT_GAMEPAD_Y);
344 ADD(XINPUT_GAMEPAD_LEFT_SHOULDER);
345 ADD(XINPUT_GAMEPAD_RIGHT_SHOULDER);
346 pad->buttons[pad->buttonsLength++] = state.Gamepad.bLeftTrigger / 255.0;
347 pad->buttons[pad->buttonsLength++] = state.Gamepad.bRightTrigger / 255.0;
348 ADD(XINPUT_GAMEPAD_BACK);
349 ADD(XINPUT_GAMEPAD_START);
350 ADD(XINPUT_GAMEPAD_LEFT_THUMB);
351 ADD(XINPUT_GAMEPAD_RIGHT_THUMB);
352 ADD(XINPUT_GAMEPAD_DPAD_UP);
353 ADD(XINPUT_GAMEPAD_DPAD_DOWN);
354 ADD(XINPUT_GAMEPAD_DPAD_LEFT);
355 ADD(XINPUT_GAMEPAD_DPAD_RIGHT);
136 #undef ADD 356 #undef ADD
137 pad.axesLength = 0; 357 pad->axesLength = 0;
138 // XInput are +up/+right, -down/-left, we want -up/-left. 358 // XInput are +up/+right, -down/-left, we want -up/-left.
139 pad.axes[pad.axesLength++] = NormalizeAxis(state.Gamepad.sThumbLX); 359 pad->axes[pad->axesLength++] = NormalizeXInputAxis(state.Gamepad.sThumbLX);
140 pad.axes[pad.axesLength++] = -NormalizeAxis(state.Gamepad.sThumbLY); 360 pad->axes[pad->axesLength++] = -NormalizeXInputAxis(state.Gamepad.sThumbLY);
141 pad.axes[pad.axesLength++] = NormalizeAxis(state.Gamepad.sThumbRX); 361 pad->axes[pad->axesLength++] = NormalizeXInputAxis(state.Gamepad.sThumbRX);
142 pad.axes[pad.axesLength++] = -NormalizeAxis(state.Gamepad.sThumbRY); 362 pad->axes[pad->axesLength++] = -NormalizeXInputAxis(state.Gamepad.sThumbRY);
143 } else { 363 } else {
144 pad.connected = false; 364 pad->connected = false;
145 } 365 }
146 } 366 }
147 } 367
148 368 void GamepadPlatformDataFetcherWin::GetDirectInputPadData(
149 bool GamepadPlatformDataFetcherWin::GetXinputDllFunctions() { 369 int index,
370 WebGamepad* pad) {
371 if (!pad->connected)
372 return;
373
374 IDirectInputDevice8* gamepad = pad_state_[index].directinput_gamepad;
375 if (FAILED(gamepad->Poll())) {
376 // Polling didn't work, try acquiring the gamepad.
377 if (FAILED(gamepad->Acquire()))
378 return;
scottmg 2013/02/14 18:44:34 i think these failures need to set pad->connected
teravest 2013/02/19 17:17:24 Done.
379 // Try polling again.
380 if (FAILED(gamepad->Poll()))
381 return;
382 }
383 JoyData state;
384 if (FAILED(gamepad->GetDeviceState(sizeof(JoyData), &state))) {
385 pad->connected = false;
386 return;
387 }
388
389 WebGamepad raw;
390 raw.connected = true;
391 for (int i = 0; i < 16; i++)
392 raw.buttons[i] = (state.buttons[i] & 0x80) ? 1.0 : 0.0;
393
394 // We map the POV (often a D-pad) into the buttons 16-19.
395 // DirectInput gives pov measurements in hundredths of degrees,
396 // clockwise from "North".
397 // We use 22.5 degree slices so we can handle diagonal D-raw presses.
398 static const int arc_segment = 2250; // 22.5 degrees = 1/16 circle
399 if (state.pov > arc_segment && state.pov < 7 * arc_segment)
400 raw.buttons[19] = 1.0;
401 else
402 raw.buttons[19] = 0.0;
403
404 if (state.pov > 5 * arc_segment && state.pov < 11 * arc_segment)
405 raw.buttons[17] = 1.0;
406 else
407 raw.buttons[17] = 0.0;
408
409 if (state.pov > 9 * arc_segment && state.pov < 15 * arc_segment)
410 raw.buttons[18] = 1.0;
411 else
412 raw.buttons[18] = 0.0;
413
414 if (state.pov < 3 * arc_segment ||
415 (state.pov > 13 * arc_segment && state.pov < 36000))
416 raw.buttons[16] = 1.0;
417 else
418 raw.buttons[16] = 0.0;
419
420 for (int i = 0; i < 10; i++)
421 raw.axes[i] = state.axes[i];
422 pad_state_[index].mapper(raw, pad);
423 }
424
425 bool GamepadPlatformDataFetcherWin::GetXInputDllFunctions() {
150 xinput_get_capabilities_ = NULL; 426 xinput_get_capabilities_ = NULL;
151 xinput_get_state_ = NULL; 427 xinput_get_state_ = NULL;
152 xinput_enable_ = static_cast<XInputEnableFunc>( 428 xinput_enable_ = static_cast<XInputEnableFunc>(
153 xinput_dll_.GetFunctionPointer("XInputEnable")); 429 xinput_dll_.GetFunctionPointer("XInputEnable"));
154 if (!xinput_enable_) 430 if (!xinput_enable_)
155 return false; 431 return false;
156 xinput_get_capabilities_ = static_cast<XInputGetCapabilitiesFunc>( 432 xinput_get_capabilities_ = static_cast<XInputGetCapabilitiesFunc>(
157 xinput_dll_.GetFunctionPointer("XInputGetCapabilities")); 433 xinput_dll_.GetFunctionPointer("XInputGetCapabilities"));
158 if (!xinput_get_capabilities_) 434 if (!xinput_get_capabilities_)
159 return false; 435 return false;
160 xinput_get_state_ = static_cast<XInputGetStateFunc>( 436 xinput_get_state_ = static_cast<XInputGetStateFunc>(
161 xinput_dll_.GetFunctionPointer("XInputGetState")); 437 xinput_dll_.GetFunctionPointer("XInputGetState"));
162 if (!xinput_get_state_) 438 if (!xinput_get_state_)
163 return false; 439 return false;
164 xinput_enable_(true); 440 xinput_enable_(true);
165 return true; 441 return true;
166 } 442 }
167 443
168 } // namespace content 444 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/gamepad/gamepad_platform_data_fetcher_win.h ('k') | content/browser/gamepad/gamepad_standard_mappings_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698