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

Unified Diff: content/browser/gamepad/gamepad_provider.cc

Issue 200873002: Gamepad API: add support for connection events (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/browser/gamepad/gamepad_provider.h ('k') | content/browser/gamepad/gamepad_service.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/gamepad/gamepad_provider.cc
diff --git a/content/browser/gamepad/gamepad_provider.cc b/content/browser/gamepad/gamepad_provider.cc
index 1cc7aab73f5daba2e6984c3e626275c27fbf06b8..0d84452b1d1859a0385ac788653df09789265036 100644
--- a/content/browser/gamepad/gamepad_provider.cc
+++ b/content/browser/gamepad/gamepad_provider.cc
@@ -15,9 +15,14 @@
#include "content/browser/gamepad/gamepad_data_fetcher.h"
#include "content/browser/gamepad/gamepad_platform_data_fetcher.h"
#include "content/browser/gamepad/gamepad_provider.h"
+#include "content/browser/gamepad/gamepad_service.h"
#include "content/common/gamepad_hardware_buffer.h"
#include "content/common/gamepad_messages.h"
#include "content/common/gamepad_user_gesture.h"
+#include "content/public/browser/browser_thread.h"
+
+using blink::WebGamepad;
+using blink::WebGamepads;
namespace content {
@@ -34,14 +39,16 @@ GamepadProvider::ClosureAndThread::~ClosureAndThread() {
GamepadProvider::GamepadProvider()
: is_paused_(true),
have_scheduled_do_poll_(false),
- devices_changed_(true) {
+ devices_changed_(true),
+ ever_had_user_gesture_(false) {
Initialize(scoped_ptr<GamepadDataFetcher>());
}
GamepadProvider::GamepadProvider(scoped_ptr<GamepadDataFetcher> fetcher)
: is_paused_(true),
have_scheduled_do_poll_(false),
- devices_changed_(true) {
+ devices_changed_(true),
+ ever_had_user_gesture_(false) {
Initialize(fetcher.Pass());
}
@@ -63,6 +70,12 @@ base::SharedMemoryHandle GamepadProvider::GetSharedMemoryHandleForProcess(
return renderer_handle;
}
+void GamepadProvider::GetCurrentGamepadData(WebGamepads* data) {
+ const WebGamepads& pads = SharedMemoryAsHardwareBuffer()->buffer;
+ base::AutoLock lock(shared_memory_lock_);
+ *data = pads;
+}
+
void GamepadProvider::Pause() {
{
base::AutoLock lock(is_paused_lock_);
@@ -111,6 +124,7 @@ void GamepadProvider::Initialize(scoped_ptr<GamepadDataFetcher> fetcher) {
CHECK(res);
GamepadHardwareBuffer* hwbuf = SharedMemoryAsHardwareBuffer();
memset(hwbuf, 0, sizeof(GamepadHardwareBuffer));
+ pad_states_.reset(new PadState[WebGamepads::itemsLengthCap]);
polling_thread_.reset(new base::Thread("Gamepad polling thread"));
#if defined(OS_LINUX)
@@ -148,6 +162,39 @@ void GamepadProvider::SendPauseHint(bool paused) {
data_fetcher_->PauseHint(paused);
}
+bool GamepadProvider::PadState::Match(const WebGamepad& pad) const {
+ return connected == pad.connected &&
+ axes_length == pad.axesLength &&
+ buttons_length == pad.buttonsLength &&
+ memcmp(id, pad.id, arraysize(id)) == 0 &&
+ memcmp(mapping, pad.mapping, arraysize(mapping)) == 0;
+}
+
+void GamepadProvider::PadState::SetPad(const WebGamepad& pad) {
+ DCHECK(pad.connected);
+ connected = true;
+ axes_length = pad.axesLength;
+ buttons_length = pad.buttonsLength;
+ memcpy(id, pad.id, arraysize(id));
+ memcpy(mapping, pad.mapping, arraysize(mapping));
+}
+
+void GamepadProvider::PadState::SetDisconnected() {
+ connected = false;
+ axes_length = 0;
+ buttons_length = 0;
+ memset(id, 0, arraysize(id));
+ memset(mapping, 0, arraysize(mapping));
+}
+
+void GamepadProvider::PadState::AsWebGamepad(WebGamepad* pad) {
+ pad->connected = connected;
+ pad->axesLength = axes_length;
+ pad->buttonsLength = buttons_length;
+ memcpy(pad->id, id, arraysize(id));
+ memcpy(pad->mapping, mapping, arraysize(mapping));
+}
+
void GamepadProvider::DoPoll() {
DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
DCHECK(have_scheduled_do_poll_);
@@ -158,7 +205,7 @@ void GamepadProvider::DoPoll() {
ANNOTATE_BENIGN_RACE_SIZED(
&hwbuf->buffer,
- sizeof(blink::WebGamepads),
+ sizeof(WebGamepads),
"Racey reads are discarded");
{
@@ -167,14 +214,35 @@ void GamepadProvider::DoPoll() {
devices_changed_ = false;
}
- // Acquire the SeqLock. There is only ever one writer to this data.
- // See gamepad_hardware_buffer.h.
- hwbuf->sequence.WriteBegin();
- data_fetcher_->GetGamepadData(&hwbuf->buffer, changed);
- hwbuf->sequence.WriteEnd();
+ {
+ base::AutoLock lock(shared_memory_lock_);
+
+ // Acquire the SeqLock. There is only ever one writer to this data.
+ // See gamepad_hardware_buffer.h.
+ hwbuf->sequence.WriteBegin();
+ data_fetcher_->GetGamepadData(&hwbuf->buffer, changed);
+ hwbuf->sequence.WriteEnd();
+ }
CheckForUserGesture();
+ if (ever_had_user_gesture_) {
+ for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
+ WebGamepad& pad = hwbuf->buffer.items[i];
+ PadState& state = pad_states_.get()[i];
+ if (pad.connected && !state.connected) {
+ OnGamepadConnectionChange(true, i, pad);
+ } else if (!pad.connected && state.connected) {
+ OnGamepadConnectionChange(false, i, pad);
+ } else if (pad.connected && state.connected && !state.Match(pad)) {
+ WebGamepad old_pad;
+ state.AsWebGamepad(&old_pad);
+ OnGamepadConnectionChange(false, i, old_pad);
+ OnGamepadConnectionChange(true, i, pad);
+ }
+ }
+ }
+
// Schedule our next interval of polling.
ScheduleDoPoll();
}
@@ -197,6 +265,32 @@ void GamepadProvider::ScheduleDoPoll() {
have_scheduled_do_poll_ = true;
}
+void GamepadProvider::OnGamepadConnectionChange(
+ bool connected, int index, const WebGamepad& pad) {
+ PadState& state = pad_states_.get()[index];
+ if (connected)
+ state.SetPad(pad);
+ else
+ state.SetDisconnected();
+
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&GamepadProvider::DispatchGamepadConnectionChange,
+ base::Unretained(this),
+ connected,
+ index,
+ pad));
+}
+
+void GamepadProvider::DispatchGamepadConnectionChange(
+ bool connected, int index, const WebGamepad& pad) {
+ if (connected)
+ GamepadService::GetInstance()->OnGamepadConnected(index, pad);
+ else
+ GamepadService::GetInstance()->OnGamepadDisconnected(index, pad);
+}
+
GamepadHardwareBuffer* GamepadProvider::SharedMemoryAsHardwareBuffer() {
void* mem = gamepad_shared_memory_.memory();
CHECK(mem);
@@ -205,10 +299,11 @@ GamepadHardwareBuffer* GamepadProvider::SharedMemoryAsHardwareBuffer() {
void GamepadProvider::CheckForUserGesture() {
base::AutoLock lock(user_gesture_lock_);
- if (user_gesture_observers_.empty())
- return; // Don't need to check if nobody is listening.
+ if (user_gesture_observers_.empty() && ever_had_user_gesture_)
+ return;
if (GamepadsHaveUserGesture(SharedMemoryAsHardwareBuffer()->buffer)) {
+ ever_had_user_gesture_ = true;
for (size_t i = 0; i < user_gesture_observers_.size(); i++) {
user_gesture_observers_[i].message_loop->PostTask(FROM_HERE,
user_gesture_observers_[i].closure);
« no previous file with comments | « content/browser/gamepad/gamepad_provider.h ('k') | content/browser/gamepad/gamepad_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698