Index: Source/modules/gamepad/NavigatorGamepad.cpp |
diff --git a/Source/modules/gamepad/NavigatorGamepad.cpp b/Source/modules/gamepad/NavigatorGamepad.cpp |
index 27c1e53322ceece8349fc24a3b5d8f530ab8e7e2..514fe4d600418e83cb066ee74baa339821053f7d 100644 |
--- a/Source/modules/gamepad/NavigatorGamepad.cpp |
+++ b/Source/modules/gamepad/NavigatorGamepad.cpp |
@@ -26,14 +26,67 @@ |
#include "config.h" |
#include "modules/gamepad/NavigatorGamepad.h" |
+#include "core/frame/DOMWindow.h" |
+#include "core/frame/LocalFrame.h" |
#include "core/frame/Navigator.h" |
+#include "modules/gamepad/GamepadEvent.h" |
#include "modules/gamepad/GamepadList.h" |
#include "modules/gamepad/WebKitGamepadList.h" |
#include "public/platform/Platform.h" |
+#include "public/platform/WebGamepadListener.h" |
+#include "wtf/HashSet.h" |
#include "wtf/PassOwnPtr.h" |
namespace WebCore { |
+class GlobalGamepadListener : public blink::WebGamepadListener { |
abarth-chromium
2014/03/19 18:00:33
Can you put this class in its own file? For consi
|
+public: |
+ GlobalGamepadListener(); |
+ |
+ void addClient(NavigatorGamepad* observer); |
+ void removeClient(NavigatorGamepad* observer); |
+ |
+private: |
+ virtual void didConnectGamepad(unsigned index, const blink::WebGamepad&) OVERRIDE; |
+ virtual void didDisconnectGamepad(unsigned index, const blink::WebGamepad&) OVERRIDE; |
+ |
+ typedef WTF::HashSet<NavigatorGamepad*> ClientSet; |
+ ClientSet m_clients; |
+}; |
+ |
+GlobalGamepadListener::GlobalGamepadListener() |
+{ |
+ blink::Platform::current()->setGamepadListener(this); |
abarth-chromium
2014/03/19 18:00:33
If you look at how DeviceOrientationDispatcher, yo
kbalazs
2014/03/20 18:57:21
Good point. After looking at orientation and motio
|
+} |
+ |
+void GlobalGamepadListener::addClient(NavigatorGamepad* observer) |
+{ |
+ m_clients.add(observer); |
+} |
+ |
+void GlobalGamepadListener::removeClient(NavigatorGamepad* observer) |
+{ |
+ m_clients.remove(observer); |
+} |
+ |
+void GlobalGamepadListener::didConnectGamepad(unsigned index, const blink::WebGamepad& gamepad) |
+{ |
+ for (ClientSet::iterator it = m_clients.begin(), end = m_clients.end(); it != end; ++it) |
+ (*it)->didConnectGamepad(index, gamepad); |
abarth-chromium
2014/03/19 18:00:33
What stops m_clients from being mutated during thi
kbalazs
2014/03/20 18:57:21
Solved by using DeviceSensorDispatcher and DeviceS
|
+} |
+ |
+void GlobalGamepadListener::didDisconnectGamepad(unsigned index, const blink::WebGamepad& gamepad) |
+{ |
+ for (ClientSet::iterator it = m_clients.begin(), end = m_clients.end(); it != end; ++it) |
+ (*it)->didDisconnectGamepad(index, gamepad); |
+} |
+ |
+static GlobalGamepadListener& globalListener() |
+{ |
+ DEFINE_STATIC_LOCAL(GlobalGamepadListener, listener, ()); |
+ return listener; |
+} |
+ |
template<typename T> |
static void sampleGamepad(unsigned index, T& gamepad, const blink::WebGamepad& webGamepad) |
{ |
@@ -67,12 +120,14 @@ static void sampleGamepads(ListType* into) |
} |
} |
-NavigatorGamepad::NavigatorGamepad() |
+NavigatorGamepad::NavigatorGamepad(LocalFrame* frame) |
+ : DOMWindowLifecycleObserver(frame ? frame->domWindow() : 0) |
{ |
} |
NavigatorGamepad::~NavigatorGamepad() |
{ |
+ globalListener().removeClient(this); |
abarth-chromium
2014/03/19 18:00:33
The problem with only calling removeClient in the
kbalazs
2014/03/20 18:57:21
Orientation and motion unregisters when the event
|
} |
const char* NavigatorGamepad::supplementName() |
@@ -84,7 +139,7 @@ NavigatorGamepad& NavigatorGamepad::from(Navigator& navigator) |
{ |
NavigatorGamepad* supplement = static_cast<NavigatorGamepad*>(Supplement<Navigator>::from(navigator, supplementName())); |
if (!supplement) { |
- supplement = new NavigatorGamepad(); |
+ supplement = new NavigatorGamepad(navigator.frame()); |
provideTo(navigator, supplementName(), adoptPtr(supplement)); |
} |
return *supplement; |
@@ -116,4 +171,49 @@ GamepadList* NavigatorGamepad::gamepads() |
return m_gamepads.get(); |
} |
+void NavigatorGamepad::didConnectGamepad(unsigned index, const blink::WebGamepad& webGamepad) |
+{ |
+ if (index >= blink::WebGamepads::itemsLengthCap || !webGamepad.connected) |
+ return; |
abarth-chromium
2014/03/19 18:00:33
How could index >= blink::WebGamepads::itemsLength
kbalazs
2014/03/20 18:57:21
Done.
|
+ |
+ if (!m_gamepads) |
+ m_gamepads = GamepadList::create(); |
+ |
+ RefPtrWillBeRawPtr<Gamepad> gamepad = m_gamepads->item(index); |
+ if (!gamepad) |
+ gamepad = Gamepad::create(); |
+ sampleGamepad(index, *gamepad, webGamepad); |
+ m_gamepads->set(index, gamepad); |
+ |
+ if (window()) { |
abarth-chromium
2014/03/19 18:00:33
Do we want to do the work above if we don't have a
kbalazs
2014/03/20 18:57:21
Done.
|
+ RefPtr<GamepadEvent> event = GamepadEvent::create(EventTypeNames::gamepadconnected, false, true, gamepad.get()); |
+ window()->dispatchEvent(event); |
+ } |
+} |
+ |
+void NavigatorGamepad::didDisconnectGamepad(unsigned index, const blink::WebGamepad& webGamepad) |
+{ |
+ if (index >= blink::WebGamepads::itemsLengthCap) |
+ return; |
+ |
+ if (!m_gamepads) |
+ m_gamepads = GamepadList::create(); |
+ |
+ RefPtrWillBeRawPtr<Gamepad> gamepad = m_gamepads->item(index); |
+ if (!gamepad) |
+ gamepad = Gamepad::create(); |
+ sampleGamepad(index, *gamepad, webGamepad); |
+ |
+ if (window()) { |
+ RefPtr<GamepadEvent> event = GamepadEvent::create(EventTypeNames::gamepaddisconnected, false, true, gamepad.get()); |
+ window()->dispatchEvent(event); |
+ } |
+} |
+ |
+void NavigatorGamepad::didAddEventListener(DOMWindow*, const AtomicString& eventType) |
+{ |
+ if (eventType == EventTypeNames::gamepadconnected || eventType == EventTypeNames::gamepaddisconnected) |
+ globalListener() |
+} |
+ |
} // namespace WebCore |