Index: Source/modules/gamepad/NavigatorGamepad.cpp |
diff --git a/Source/modules/gamepad/NavigatorGamepad.cpp b/Source/modules/gamepad/NavigatorGamepad.cpp |
index 6333946be8a506ee5138fe2e9e63869afac7b3f6..e9766a01037ce55991c53371e601805cd09177c0 100644 |
--- a/Source/modules/gamepad/NavigatorGamepad.cpp |
+++ b/Source/modules/gamepad/NavigatorGamepad.cpp |
@@ -126,6 +126,7 @@ void NavigatorGamepad::trace(Visitor* visitor) |
{ |
visitor->trace(m_gamepads); |
visitor->trace(m_webkitGamepads); |
+ visitor->trace(m_pendingEvents); |
WillBeHeapSupplement<Navigator>::trace(visitor); |
} |
@@ -152,14 +153,28 @@ void NavigatorGamepad::didUpdateData() |
sampleGamepad(change.index, *gamepad, change.pad); |
m_gamepads->set(change.index, gamepad); |
- const AtomicString& eventName = change.pad.connected ? EventTypeNames::gamepadconnected : EventTypeNames::gamepaddisconnected; |
+ m_pendingEvents.append(gamepad); |
+ m_dispatchOneEventRunner.runAsync(); |
+} |
+ |
+void NavigatorGamepad::dispatchOneEvent() |
+{ |
+ ASSERT(window()); |
+ ASSERT(!m_pendingEvents.isEmpty()); |
+ |
+ Gamepad* gamepad = m_pendingEvents.takeFirst(); |
+ const AtomicString& eventName = gamepad->connected() ? EventTypeNames::gamepadconnected : EventTypeNames::gamepaddisconnected; |
window()->dispatchEvent(GamepadEvent::create(eventName, false, true, gamepad)); |
+ |
+ if (!m_pendingEvents.isEmpty()) |
+ m_dispatchOneEventRunner.runAsync(); |
} |
NavigatorGamepad::NavigatorGamepad(LocalFrame* frame) |
: DOMWindowProperty(frame) |
, DeviceEventControllerBase(frame ? frame->page() : 0) |
, DOMWindowLifecycleObserver(frame ? frame->domWindow() : 0) |
+ , m_dispatchOneEventRunner(this, &NavigatorGamepad::dispatchOneEvent) |
{ |
} |
@@ -187,10 +202,12 @@ void NavigatorGamepad::willDetachGlobalObjectFromFrame() |
void NavigatorGamepad::registerWithDispatcher() |
{ |
GamepadDispatcher::instance().addController(this); |
+ m_dispatchOneEventRunner.resume(); |
} |
void NavigatorGamepad::unregisterWithDispatcher() |
{ |
+ m_dispatchOneEventRunner.suspend(); |
GamepadDispatcher::instance().removeController(this); |
} |
@@ -219,22 +236,58 @@ void NavigatorGamepad::didRemoveEventListener(LocalDOMWindow* window, const Atom |
if (isGamepadEvent(eventType) |
&& !window->hasEventListeners(EventTypeNames::gamepadconnected) |
&& !window->hasEventListeners(EventTypeNames::gamepaddisconnected)) { |
- m_hasEventListener = false; |
+ didRemoveGamepadEventListeners(); |
} |
} |
void NavigatorGamepad::didRemoveAllEventListeners(LocalDOMWindow*) |
{ |
+ didRemoveGamepadEventListeners(); |
+} |
+ |
+void NavigatorGamepad::didRemoveGamepadEventListeners() |
+{ |
m_hasEventListener = false; |
+ m_dispatchOneEventRunner.stop(); |
+ m_pendingEvents.clear(); |
} |
void NavigatorGamepad::pageVisibilityChanged() |
{ |
// Inform the embedder whether it needs to provide gamepad data for us. |
- if (page()->visibilityState() == PageVisibilityStateVisible && (m_hasEventListener || m_gamepads || m_webkitGamepads)) |
+ bool visible = page()->visibilityState() == PageVisibilityStateVisible; |
+ if (visible && (m_hasEventListener || m_gamepads || m_webkitGamepads)) |
startUpdating(); |
else |
stopUpdating(); |
+ |
+ if (!visible || !m_hasEventListener) |
+ return; |
+ |
+ // Tell the page what has changed. m_gamepads contains the state before we became hidden. |
+ // We create a new snapshot and compare them. |
+ GamepadList* oldGamepads = m_gamepads.release(); |
+ gamepads(); |
+ GamepadList* newGamepads = m_gamepads.get(); |
+ ASSERT(newGamepads); |
+ |
+ for (unsigned i = 0; i < blink::WebGamepads::itemsLengthCap; ++i) { |
+ Gamepad* oldGamepad = oldGamepads ? oldGamepads->item(i) : 0; |
+ Gamepad* newGamepad = newGamepads->item(i); |
+ bool oldWasConnected = oldGamepad && oldGamepad->connected(); |
+ bool newIsConnected = newGamepad && newGamepad->connected(); |
+ bool connectedGamepadChanged = oldWasConnected && newIsConnected && oldGamepad->id() != newGamepad->id(); |
+ if (connectedGamepadChanged || (oldWasConnected && !newIsConnected)) { |
+ oldGamepad->setConnected(false); |
+ m_pendingEvents.append(oldGamepad); |
+ } |
+ if (connectedGamepadChanged || (!oldWasConnected && newIsConnected)) { |
+ m_pendingEvents.append(newGamepad); |
+ } |
+ } |
+ |
+ if (!m_pendingEvents.isEmpty()) |
+ m_dispatchOneEventRunner.runAsync(); |
} |
} // namespace WebCore |