blob: 7b34f22c40587842e2458baf2fbdb3eacdd0184a [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2014 The Chromium Authors
[email protected]cf786002014-02-11 02:05:542// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Nasko Oskovee48dfb42024-06-08 05:13:065#ifdef UNSAFE_BUFFERS_BUILD
6// TODO(crbug.com/342213636): Remove this and spanify to fix the errors.
7#pragma allow_unsafe_buffers
8#endif
9
danakj89f47082020-09-02 17:53:4310#include "content/web_test/renderer/gamepad_controller.h"
[email protected]cf786002014-02-11 02:05:5411
Henrique Ferreirof464d9f12019-11-04 20:47:1712#include <string>
13#include <utility>
avi5dd91f82015-12-25 22:30:4614
Avi Drissmanadac21992023-01-11 23:46:3915#include "base/functional/bind.h"
Oksana Zhuravlova11651852018-07-16 20:07:5016#include "content/public/renderer/render_frame.h"
[email protected]cf786002014-02-11 02:05:5417#include "gin/arguments.h"
18#include "gin/handle.h"
19#include "gin/object_template_builder.h"
20#include "gin/wrappable.h"
Alexandr Ilin1ce671502018-07-19 20:59:3521#include "mojo/public/cpp/system/platform_handle.h"
Lukasz Anforowicz9bc03e72024-07-14 20:25:0222#include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
Dave Tapuskad1aaf8a2023-09-12 14:50:3423#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
Blink Reformata30d4232018-04-07 15:31:0624#include "third_party/blink/public/web/web_local_frame.h"
[email protected]cf786002014-02-11 02:05:5425#include "v8/include/v8.h"
26
juncai2f298a82017-04-18 03:51:3927using device::Gamepad;
28using device::Gamepads;
[email protected]cf786002014-02-11 02:05:5429
danakj741848a2020-04-07 22:48:0630namespace content {
[email protected]cf786002014-02-11 02:05:5431
Matt Reynolds99e2f5ef2019-01-18 23:40:5532namespace {
33
34// Set button.pressed if the button value is above a threshold. The threshold is
35// chosen to match XInput's trigger deadzone.
36constexpr float kButtonPressedThreshold = 30.f / 255.f;
37
38int64_t CurrentTimeInMicroseconds() {
39 return base::TimeTicks::Now().since_origin().InMicroseconds();
40}
41
42} // namespace
43
[email protected]cf786002014-02-11 02:05:5444class GamepadControllerBindings
45 : public gin::Wrappable<GamepadControllerBindings> {
46 public:
47 static gin::WrapperInfo kWrapperInfo;
48
Peter Boström9b036532021-10-28 23:37:2849 GamepadControllerBindings(const GamepadControllerBindings&) = delete;
50 GamepadControllerBindings& operator=(const GamepadControllerBindings&) =
51 delete;
52
[email protected]cf786002014-02-11 02:05:5453 static void Install(base::WeakPtr<GamepadController> controller,
lukaszadf18ba762017-06-09 22:24:3054 blink::WebLocalFrame* frame);
[email protected]cf786002014-02-11 02:05:5455
56 private:
57 explicit GamepadControllerBindings(
58 base::WeakPtr<GamepadController> controller);
dchenge933b3e2014-10-21 11:44:0959 ~GamepadControllerBindings() override;
[email protected]cf786002014-02-11 02:05:5460
61 // gin::Wrappable.
dchenge933b3e2014-10-21 11:44:0962 gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
anand.ratn449f39a42014-10-06 13:45:5763 v8::Isolate* isolate) override;
[email protected]cf786002014-02-11 02:05:5464
65 void Connect(int index);
[email protected]85603cbb2014-03-25 02:20:0166 void DispatchConnected(int index);
[email protected]cf786002014-02-11 02:05:5467 void Disconnect(int index);
68 void SetId(int index, const std::string& src);
69 void SetButtonCount(int index, int buttons);
70 void SetButtonData(int index, int button, double data);
71 void SetAxisCount(int index, int axes);
72 void SetAxisData(int index, int axis, double data);
Matt Reynolds6e9187e2017-10-23 18:32:0173 void SetDualRumbleVibrationActuator(int index, bool enabled);
Gabriel Britod5667f02022-07-05 01:29:2974 void SetTriggerRumbleVibrationActuator(int index, bool enabled);
Bradley Needham835f0f492023-04-04 23:00:5475 void SetTouchCount(int index, int touches);
76 void SetTouchData(int index,
77 int touch,
78 unsigned int touch_id,
79 float position_x,
80 float position_y);
[email protected]cf786002014-02-11 02:05:5481
82 base::WeakPtr<GamepadController> controller_;
[email protected]cf786002014-02-11 02:05:5483};
84
85gin::WrapperInfo GamepadControllerBindings::kWrapperInfo = {
86 gin::kEmbedderNativeGin};
87
88// static
89void GamepadControllerBindings::Install(
90 base::WeakPtr<GamepadController> controller,
lukaszadf18ba762017-06-09 22:24:3091 blink::WebLocalFrame* frame) {
Dave Tapuskad1aaf8a2023-09-12 14:50:3492 v8::Isolate* isolate = frame->GetAgentGroupScheduler()->Isolate();
[email protected]cf786002014-02-11 02:05:5493 v8::HandleScope handle_scope(isolate);
Blink Reformat1c4d759e2017-04-09 16:34:5494 v8::Local<v8::Context> context = frame->MainWorldScriptContext();
[email protected]cf786002014-02-11 02:05:5495 if (context.IsEmpty())
96 return;
97
98 v8::Context::Scope context_scope(context);
99
100 gin::Handle<GamepadControllerBindings> bindings =
101 gin::CreateHandle(isolate, new GamepadControllerBindings(controller));
[email protected]ad4d2032014-04-28 13:50:59102 if (bindings.IsEmpty())
103 return;
deepak.s750d68f2015-04-30 07:32:41104 v8::Local<v8::Object> global = context->Global();
Dan Elphicka83be512019-02-05 15:57:23105 global
106 ->Set(context, gin::StringToV8(isolate, "gamepadController"),
107 bindings.ToV8())
108 .Check();
[email protected]cf786002014-02-11 02:05:54109}
110
111GamepadControllerBindings::GamepadControllerBindings(
112 base::WeakPtr<GamepadController> controller)
113 : controller_(controller) {}
114
115GamepadControllerBindings::~GamepadControllerBindings() {}
116
117gin::ObjectTemplateBuilder GamepadControllerBindings::GetObjectTemplateBuilder(
118 v8::Isolate* isolate) {
119 return gin::Wrappable<GamepadControllerBindings>::GetObjectTemplateBuilder(
120 isolate)
121 .SetMethod("connect", &GamepadControllerBindings::Connect)
jochen73e711c2015-06-03 10:01:46122 .SetMethod("dispatchConnected",
123 &GamepadControllerBindings::DispatchConnected)
[email protected]cf786002014-02-11 02:05:54124 .SetMethod("disconnect", &GamepadControllerBindings::Disconnect)
125 .SetMethod("setId", &GamepadControllerBindings::SetId)
126 .SetMethod("setButtonCount", &GamepadControllerBindings::SetButtonCount)
127 .SetMethod("setButtonData", &GamepadControllerBindings::SetButtonData)
128 .SetMethod("setAxisCount", &GamepadControllerBindings::SetAxisCount)
Matt Reynolds6e9187e2017-10-23 18:32:01129 .SetMethod("setAxisData", &GamepadControllerBindings::SetAxisData)
130 .SetMethod("setDualRumbleVibrationActuator",
Gabriel Britod5667f02022-07-05 01:29:29131 &GamepadControllerBindings::SetDualRumbleVibrationActuator)
132 .SetMethod("setTriggerRumbleVibrationActuator",
Bradley Needham835f0f492023-04-04 23:00:54133 &GamepadControllerBindings::SetTriggerRumbleVibrationActuator)
134 .SetMethod("setTouchCount", &GamepadControllerBindings::SetTouchCount)
135 .SetMethod("setTouchData", &GamepadControllerBindings::SetTouchData);
[email protected]cf786002014-02-11 02:05:54136}
137
138void GamepadControllerBindings::Connect(int index) {
139 if (controller_)
140 controller_->Connect(index);
141}
142
[email protected]85603cbb2014-03-25 02:20:01143void GamepadControllerBindings::DispatchConnected(int index) {
144 if (controller_)
145 controller_->DispatchConnected(index);
146}
147
[email protected]cf786002014-02-11 02:05:54148void GamepadControllerBindings::Disconnect(int index) {
149 if (controller_)
150 controller_->Disconnect(index);
151}
152
153void GamepadControllerBindings::SetId(int index, const std::string& src) {
154 if (controller_)
155 controller_->SetId(index, src);
156}
157
158void GamepadControllerBindings::SetButtonCount(int index, int buttons) {
159 if (controller_)
160 controller_->SetButtonCount(index, buttons);
161}
162
163void GamepadControllerBindings::SetButtonData(int index,
164 int button,
165 double data) {
166 if (controller_)
167 controller_->SetButtonData(index, button, data);
168}
169
170void GamepadControllerBindings::SetAxisCount(int index, int axes) {
171 if (controller_)
172 controller_->SetAxisCount(index, axes);
173}
174
175void GamepadControllerBindings::SetAxisData(int index, int axis, double data) {
176 if (controller_)
177 controller_->SetAxisData(index, axis, data);
178}
179
Matt Reynolds6e9187e2017-10-23 18:32:01180void GamepadControllerBindings::SetDualRumbleVibrationActuator(int index,
181 bool enabled) {
182 if (controller_)
183 controller_->SetDualRumbleVibrationActuator(index, enabled);
184}
185
Gabriel Britod5667f02022-07-05 01:29:29186void GamepadControllerBindings::SetTriggerRumbleVibrationActuator(
187 int index,
188 bool enabled) {
189 if (controller_)
190 controller_->SetTriggerRumbleVibrationActuator(index, enabled);
191}
192
Bradley Needham835f0f492023-04-04 23:00:54193void GamepadControllerBindings::SetTouchData(int index,
194 int touch,
195 unsigned int touch_id,
196 float position_x,
197 float position_y) {
198 if (controller_) {
199 controller_->SetTouchData(index, touch, touch_id, position_x, position_y);
200 }
201}
202
203void GamepadControllerBindings::SetTouchCount(int index, int touches) {
204 if (controller_) {
205 controller_->SetTouchCount(index, touches);
206 }
207}
208
Matt Reynolds093c89f2019-05-03 00:58:59209GamepadController::MonitorImpl::MonitorImpl(
210 GamepadController* controller,
Gyuyoung Kim7959faf2019-08-15 12:10:20211 mojo::PendingReceiver<device::mojom::GamepadMonitor> receiver)
212 : controller_(controller) {
213 receiver_.Bind(std::move(receiver));
Matt Reynolds093c89f2019-05-03 00:58:59214}
215
216GamepadController::MonitorImpl::~MonitorImpl() = default;
217
218bool GamepadController::MonitorImpl::HasPendingConnect(int index) {
219 return missed_dispatches_.test(index);
220}
221
222void GamepadController::MonitorImpl::GamepadStartPolling(
223 GamepadStartPollingCallback callback) {
224 std::move(callback).Run(controller_->GetSharedMemoryRegion());
225}
226
227void GamepadController::MonitorImpl::GamepadStopPolling(
228 GamepadStopPollingCallback callback) {
229 std::move(callback).Run();
230}
231
232void GamepadController::MonitorImpl::SetObserver(
Gyuyoung Kim7959faf2019-08-15 12:10:20233 mojo::PendingRemote<device::mojom::GamepadObserver> observer) {
234 observer_remote_.Bind(std::move(observer));
235 observer_remote_.set_disconnect_handler(
Matt Reynolds093c89f2019-05-03 00:58:59236 base::BindOnce(&GamepadController::OnConnectionError,
237 base::Unretained(controller_), base::Unretained(this)));
238
239 // Notify the new observer of any GamepadConnected RPCs that it missed because
240 // the SetObserver RPC wasn't processed in time. This happens during layout
241 // tests because SetObserver is async, so the test can continue to the
242 // DispatchConnected call before the SetObserver RPC was processed. This isn't
243 // an issue in the real implementation because the 'gamepadconnected' event
244 // doesn't fire until user input is detected, so even if a GamepadConnected
245 // event is missed, another will be picked up after the next user input.
246 controller_->NotifyForMissedDispatches(this);
247 missed_dispatches_.reset();
248}
249
250void GamepadController::MonitorImpl::DispatchConnected(
251 int index,
252 const device::Gamepad& pad) {
Gyuyoung Kim7959faf2019-08-15 12:10:20253 if (observer_remote_) {
254 observer_remote_->GamepadConnected(index, pad);
Matt Reynolds093c89f2019-05-03 00:58:59255 } else {
256 // Record that there wasn't an observer to get the GamepadConnected RPC so
257 // we can send it when SetObserver gets called.
258 missed_dispatches_.set(index);
259 }
260}
261
262void GamepadController::MonitorImpl::DispatchDisconnected(
263 int index,
264 const device::Gamepad& pad) {
Gyuyoung Kim7959faf2019-08-15 12:10:20265 if (observer_remote_)
266 observer_remote_->GamepadDisconnected(index, pad);
Matt Reynolds093c89f2019-05-03 00:58:59267}
268
269void GamepadController::MonitorImpl::Reset() {
270 missed_dispatches_.reset();
271}
272
273GamepadController::GamepadController() {
Robbie McElrathf7b2d1172018-06-11 22:35:45274 size_t buffer_size = sizeof(device::GamepadHardwareBuffer);
Alexandr Ilin1ce671502018-07-19 20:59:35275 // Use mojo to delegate the creation of shared memory to the broker process.
276 mojo::ScopedSharedBufferHandle mojo_buffer =
277 mojo::SharedBufferHandle::Create(buffer_size);
278 base::WritableSharedMemoryRegion writable_region =
279 mojo::UnwrapWritableSharedMemoryRegion(std::move(mojo_buffer));
280 shared_memory_mapping_ = writable_region.Map();
281 shared_memory_region_ = base::WritableSharedMemoryRegion::ConvertToReadOnly(
282 std::move(writable_region));
danakja0c51ca2020-08-26 20:54:59283 if (!shared_memory_region_.IsValid()) {
284 // Log an error instead of crashing, as this can flakily happen in
285 // clusterfuzz. If it happened in the wild, the test would be retried.
286 LOG(ERROR) << "GamepadController shared memory region is not valid";
287 } else if (!shared_memory_mapping_.IsValid()) {
288 // Log an error instead of crashing, as this can flakily happen in
289 // clusterfuzz. If it happened in the wild, the test would be retried.
290 LOG(ERROR) << "GamepadController shared memory mapping is not valid";
291 } else {
292 gamepads_ =
293 new (shared_memory_mapping_.memory()) device::GamepadHardwareBuffer();
294 }
Robbie McElrathf7b2d1172018-06-11 22:35:45295
[email protected]cf786002014-02-11 02:05:54296 Reset();
297}
298
danakjc989ac72020-04-15 20:31:23299GamepadController::~GamepadController() = default;
[email protected]cf786002014-02-11 02:05:54300
301void GamepadController::Reset() {
danakja0c51ca2020-08-26 20:54:59302 if (!gamepads_)
303 return; // Shared memory failed.
304
Robbie McElrathf7b2d1172018-06-11 22:35:45305 memset(gamepads_, 0, sizeof(*gamepads_));
Matt Reynolds093c89f2019-05-03 00:58:59306 for (auto& monitor : monitors_)
307 monitor->Reset();
[email protected]cf786002014-02-11 02:05:54308}
309
danakja0c51ca2020-08-26 20:54:59310void GamepadController::Install(RenderFrame* frame) {
311 if (!gamepads_)
312 return; // Shared memory failed.
Oksana Zhuravlova11651852018-07-16 20:07:50313
Lukasz Anforowicz21b928482024-06-26 17:02:51314 frame->GetBrowserInterfaceBroker().SetBinderForTesting(
Robbie McElrathf7b2d1172018-06-11 22:35:45315 device::mojom::GamepadMonitor::Name_,
316 base::BindRepeating(&GamepadController::OnInterfaceRequest,
317 base::Unretained(this)));
danakja0c51ca2020-08-26 20:54:59318 GamepadControllerBindings::Install(weak_factory_.GetWeakPtr(),
319 frame->GetWebFrame());
[email protected]cf786002014-02-11 02:05:54320}
321
Robbie McElrathf7b2d1172018-06-11 22:35:45322void GamepadController::OnInterfaceRequest(
323 mojo::ScopedMessagePipeHandle handle) {
Matt Reynolds093c89f2019-05-03 00:58:59324 monitors_.insert(std::make_unique<MonitorImpl>(
Miyoung Shinc9f4dac2019-09-26 15:14:10325 this,
326 mojo::PendingReceiver<device::mojom::GamepadMonitor>(std::move(handle))));
[email protected]078780b2014-06-20 16:57:06327}
328
Matt Reynolds093c89f2019-05-03 00:58:59329base::ReadOnlySharedMemoryRegion GamepadController::GetSharedMemoryRegion()
330 const {
331 return shared_memory_region_.Duplicate();
Robbie McElrathf7b2d1172018-06-11 22:35:45332}
333
Matt Reynolds093c89f2019-05-03 00:58:59334void GamepadController::OnConnectionError(
335 GamepadController::MonitorImpl* monitor) {
336 monitors_.erase(monitors_.find(monitor));
Robbie McElrathf7b2d1172018-06-11 22:35:45337}
338
Matt Reynolds093c89f2019-05-03 00:58:59339void GamepadController::NotifyForMissedDispatches(
340 GamepadController::MonitorImpl* monitor) {
Robbie McElrathf7b2d1172018-06-11 22:35:45341 gamepads_->seqlock.WriteBegin();
342 for (size_t index = 0; index < Gamepads::kItemsLengthCap; index++) {
Matt Reynolds093c89f2019-05-03 00:58:59343 if (monitor->HasPendingConnect(index))
344 monitor->DispatchConnected(index, gamepads_->data.items[index]);
Robbie McElrathf7b2d1172018-06-11 22:35:45345 }
Robbie McElrathf7b2d1172018-06-11 22:35:45346 gamepads_->seqlock.WriteEnd();
[email protected]cf786002014-02-11 02:05:54347}
348
349void GamepadController::Connect(int index) {
juncai2f298a82017-04-18 03:51:39350 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap))
[email protected]cf786002014-02-11 02:05:54351 return;
Matt Reynolds99e2f5ef2019-01-18 23:40:55352 const int64_t now = CurrentTimeInMicroseconds();
Robbie McElrathf7b2d1172018-06-11 22:35:45353 gamepads_->seqlock.WriteBegin();
Matt Reynolds99e2f5ef2019-01-18 23:40:55354 Gamepad& pad = gamepads_->data.items[index];
355 pad.connected = true;
356 pad.timestamp = now;
Robbie McElrathf7b2d1172018-06-11 22:35:45357 gamepads_->seqlock.WriteEnd();
[email protected]cf786002014-02-11 02:05:54358}
359
[email protected]85603cbb2014-03-25 02:20:01360void GamepadController::DispatchConnected(int index) {
Matt Reynolds093c89f2019-05-03 00:58:59361 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap))
362 return;
363 const Gamepad& pad = gamepads_->data.items[index];
364 if (!pad.connected)
[email protected]85603cbb2014-03-25 02:20:01365 return;
Robbie McElrathf7b2d1172018-06-11 22:35:45366 gamepads_->seqlock.WriteBegin();
Matt Reynolds093c89f2019-05-03 00:58:59367 for (auto& monitor : monitors_)
368 monitor->DispatchConnected(index, pad);
Robbie McElrathf7b2d1172018-06-11 22:35:45369 gamepads_->seqlock.WriteEnd();
[email protected]85603cbb2014-03-25 02:20:01370}
371
[email protected]cf786002014-02-11 02:05:54372void GamepadController::Disconnect(int index) {
juncai2f298a82017-04-18 03:51:39373 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap))
[email protected]cf786002014-02-11 02:05:54374 return;
Matt Reynolds99e2f5ef2019-01-18 23:40:55375 const int64_t now = CurrentTimeInMicroseconds();
Robbie McElrathf7b2d1172018-06-11 22:35:45376 gamepads_->seqlock.WriteBegin();
377 Gamepad& pad = gamepads_->data.items[index];
[email protected]85603cbb2014-03-25 02:20:01378 pad.connected = false;
Matt Reynolds99e2f5ef2019-01-18 23:40:55379 pad.timestamp = now;
Matt Reynolds093c89f2019-05-03 00:58:59380 for (auto& monitor : monitors_)
381 monitor->DispatchDisconnected(index, pad);
Robbie McElrathf7b2d1172018-06-11 22:35:45382 gamepads_->seqlock.WriteEnd();
[email protected]cf786002014-02-11 02:05:54383}
384
385void GamepadController::SetId(int index, const std::string& src) {
juncai2f298a82017-04-18 03:51:39386 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap))
[email protected]cf786002014-02-11 02:05:54387 return;
388 const char* p = src.c_str();
Matt Reynolds99e2f5ef2019-01-18 23:40:55389 const int64_t now = CurrentTimeInMicroseconds();
Robbie McElrathf7b2d1172018-06-11 22:35:45390 gamepads_->seqlock.WriteBegin();
Matt Reynolds99e2f5ef2019-01-18 23:40:55391 Gamepad& pad = gamepads_->data.items[index];
392 memset(pad.id, 0, sizeof(pad.id));
juncai2f298a82017-04-18 03:51:39393 for (unsigned i = 0; *p && i < Gamepad::kIdLengthCap - 1; ++i)
Matt Reynolds99e2f5ef2019-01-18 23:40:55394 pad.id[i] = *p++;
395 pad.timestamp = now;
Robbie McElrathf7b2d1172018-06-11 22:35:45396 gamepads_->seqlock.WriteEnd();
[email protected]cf786002014-02-11 02:05:54397}
398
399void GamepadController::SetButtonCount(int index, int buttons) {
juncai2f298a82017-04-18 03:51:39400 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap))
[email protected]cf786002014-02-11 02:05:54401 return;
juncai2f298a82017-04-18 03:51:39402 if (buttons < 0 || buttons >= static_cast<int>(Gamepad::kButtonsLengthCap))
[email protected]cf786002014-02-11 02:05:54403 return;
Matt Reynolds99e2f5ef2019-01-18 23:40:55404 const int64_t now = CurrentTimeInMicroseconds();
Robbie McElrathf7b2d1172018-06-11 22:35:45405 gamepads_->seqlock.WriteBegin();
Matt Reynolds99e2f5ef2019-01-18 23:40:55406 Gamepad& pad = gamepads_->data.items[index];
407 pad.buttons_length = buttons;
408 pad.timestamp = now;
Robbie McElrathf7b2d1172018-06-11 22:35:45409 gamepads_->seqlock.WriteEnd();
[email protected]cf786002014-02-11 02:05:54410}
411
412void GamepadController::SetButtonData(int index, int button, double data) {
juncai2f298a82017-04-18 03:51:39413 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap))
[email protected]cf786002014-02-11 02:05:54414 return;
juncai2f298a82017-04-18 03:51:39415 if (button < 0 || button >= static_cast<int>(Gamepad::kButtonsLengthCap))
[email protected]cf786002014-02-11 02:05:54416 return;
Matt Reynolds99e2f5ef2019-01-18 23:40:55417 const int64_t now = CurrentTimeInMicroseconds();
Robbie McElrathf7b2d1172018-06-11 22:35:45418 gamepads_->seqlock.WriteBegin();
Matt Reynolds99e2f5ef2019-01-18 23:40:55419 Gamepad& pad = gamepads_->data.items[index];
420 pad.buttons[button].value = data;
421 pad.buttons[button].pressed = data > kButtonPressedThreshold;
422 pad.timestamp = now;
Robbie McElrathf7b2d1172018-06-11 22:35:45423 gamepads_->seqlock.WriteEnd();
[email protected]cf786002014-02-11 02:05:54424}
425
426void GamepadController::SetAxisCount(int index, int axes) {
juncai2f298a82017-04-18 03:51:39427 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap))
[email protected]cf786002014-02-11 02:05:54428 return;
juncai2f298a82017-04-18 03:51:39429 if (axes < 0 || axes >= static_cast<int>(Gamepad::kAxesLengthCap))
[email protected]cf786002014-02-11 02:05:54430 return;
Matt Reynolds99e2f5ef2019-01-18 23:40:55431 const int64_t now = CurrentTimeInMicroseconds();
Robbie McElrathf7b2d1172018-06-11 22:35:45432 gamepads_->seqlock.WriteBegin();
Matt Reynolds99e2f5ef2019-01-18 23:40:55433 Gamepad& pad = gamepads_->data.items[index];
434 pad.axes_length = axes;
435 pad.timestamp = now;
Robbie McElrathf7b2d1172018-06-11 22:35:45436 gamepads_->seqlock.WriteEnd();
[email protected]cf786002014-02-11 02:05:54437}
438
439void GamepadController::SetAxisData(int index, int axis, double data) {
juncai2f298a82017-04-18 03:51:39440 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap))
[email protected]cf786002014-02-11 02:05:54441 return;
juncai2f298a82017-04-18 03:51:39442 if (axis < 0 || axis >= static_cast<int>(Gamepad::kAxesLengthCap))
[email protected]cf786002014-02-11 02:05:54443 return;
Matt Reynolds99e2f5ef2019-01-18 23:40:55444 const int64_t now = CurrentTimeInMicroseconds();
Robbie McElrathf7b2d1172018-06-11 22:35:45445 gamepads_->seqlock.WriteBegin();
Matt Reynolds99e2f5ef2019-01-18 23:40:55446 Gamepad& pad = gamepads_->data.items[index];
447 pad.axes[axis] = data;
448 pad.timestamp = now;
Robbie McElrathf7b2d1172018-06-11 22:35:45449 gamepads_->seqlock.WriteEnd();
[email protected]cf786002014-02-11 02:05:54450}
451
Matt Reynolds6e9187e2017-10-23 18:32:01452void GamepadController::SetDualRumbleVibrationActuator(int index,
453 bool enabled) {
454 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap))
455 return;
Matt Reynolds99e2f5ef2019-01-18 23:40:55456 const int64_t now = CurrentTimeInMicroseconds();
Robbie McElrathf7b2d1172018-06-11 22:35:45457 gamepads_->seqlock.WriteBegin();
Matt Reynolds99e2f5ef2019-01-18 23:40:55458 Gamepad& pad = gamepads_->data.items[index];
459 pad.vibration_actuator.type = device::GamepadHapticActuatorType::kDualRumble;
460 pad.vibration_actuator.not_null = enabled;
461 pad.timestamp = now;
Robbie McElrathf7b2d1172018-06-11 22:35:45462 gamepads_->seqlock.WriteEnd();
Matt Reynolds6e9187e2017-10-23 18:32:01463}
464
Gabriel Britod5667f02022-07-05 01:29:29465void GamepadController::SetTriggerRumbleVibrationActuator(int index,
466 bool enabled) {
467 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap))
468 return;
469 const int64_t now = CurrentTimeInMicroseconds();
470 gamepads_->seqlock.WriteBegin();
471 Gamepad& pad = gamepads_->data.items[index];
472 pad.vibration_actuator.type =
473 device::GamepadHapticActuatorType::kTriggerRumble;
474 pad.vibration_actuator.not_null = enabled;
475 pad.timestamp = now;
476 gamepads_->seqlock.WriteEnd();
477}
478
Bradley Needham835f0f492023-04-04 23:00:54479void GamepadController::SetTouchCount(int index, int touches) {
480 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap)) {
481 return;
482 }
483 if (touches < 0 ||
484 touches >= static_cast<int>(Gamepad::kTouchEventsLengthCap)) {
485 return;
486 }
487 const int64_t now = CurrentTimeInMicroseconds();
488 gamepads_->seqlock.WriteBegin();
489 Gamepad& pad = gamepads_->data.items[index];
490 pad.supports_touch_events_ = true;
491 pad.touch_events_length = touches;
492 pad.timestamp = now;
493 gamepads_->seqlock.WriteEnd();
494}
495
496void GamepadController::SetTouchData(int index,
497 int touch,
498 unsigned int touch_id,
499 float position_x,
500 float position_y) {
501 if (index < 0 || index >= static_cast<int>(Gamepads::kItemsLengthCap)) {
502 return;
503 }
504 if (touch < 0 || touch >= static_cast<int>(Gamepad::kTouchEventsLengthCap)) {
505 return;
506 }
507 const int64_t now = CurrentTimeInMicroseconds();
508 gamepads_->seqlock.WriteBegin();
509 Gamepad& pad = gamepads_->data.items[index];
510 pad.supports_touch_events_ = true;
511 pad.touch_events[touch].touch_id = touch_id;
512 pad.touch_events[touch].x = position_x;
513 pad.touch_events[touch].y = position_y;
514 pad.timestamp = now;
515 gamepads_->seqlock.WriteEnd();
516}
517
danakj741848a2020-04-07 22:48:06518} // namespace content