X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fcontent%2Fbrowser%2Fgamepad%2Fgamepad_provider.cc;h=8e7644ef46ec4c40fa1729c59a631a79bfb7f1c1;hb=004985e17e624662a4c85c76a7654039dc83f028;hp=1cc7aab73f5daba2e6984c3e626275c27fbf06b8;hpb=2f108dbacb161091e42a3479f4e171339b7e7623;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/content/browser/gamepad/gamepad_provider.cc b/src/content/browser/gamepad/gamepad_provider.cc index 1cc7aab..8e7644e 100644 --- a/src/content/browser/gamepad/gamepad_provider.cc +++ b/src/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()); } GamepadProvider::GamepadProvider(scoped_ptr 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 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);