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

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

Issue 195873019: Gamepad API: add support for connection events (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: and a missing override Created 6 years, 7 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..8e7644ef46ec4c40fa1729c59a631a79bfb7f1c1 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,41 @@ 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_));
+ memset(pad->axes, 0, arraysize(pad->axes));
+ memset(pad->buttons, 0, arraysize(pad->buttons));
+}
+
void GamepadProvider::DoPoll() {
DCHECK(base::MessageLoop::current() == polling_thread_->message_loop());
DCHECK(have_scheduled_do_poll_);
@@ -158,7 +207,7 @@ void GamepadProvider::DoPoll() {
ANNOTATE_BENIGN_RACE_SIZED(
&hwbuf->buffer,
- sizeof(blink::WebGamepads),
+ sizeof(WebGamepads),
"Racey reads are discarded");
{
@@ -167,14 +216,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 +267,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 +301,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