The user pressing a button on a gamepad should cause gamepads to become visible to...
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jun 2014 21:11:24 +0000 (21:11 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Jun 2014 21:11:24 +0000 (21:11 +0000)
https://bugs.webkit.org/show_bug.cgi?id=134375

Reviewed by Darin Adler.

No new tests (Not yet a tested config)

* Modules/gamepad/GamepadManager.cpp:
(WebCore::GamepadManager::platformGamepadConnected): Also call to makeGamepadsVisibileToBlindNavigators.
(WebCore::GamepadManager::platformGamepadDisconnected):
(WebCore::GamepadManager::platformGamepadInputActivity): Call makeGamepadsVisibileToBlindNavigators.
(WebCore::GamepadManager::makeGamepadsVisibileToBlindNavigators): Walk through each blind navigator
  notifying it of each connected Gamepad.
(WebCore::GamepadManager::registerNavigator): Also add to the blind navigator set.
(WebCore::GamepadManager::unregisterNavigator): Also remove from the blind navigator set.
* Modules/gamepad/GamepadManager.h:

* platform/GamepadProviderClient.h: Added platformGamepadInputActivity.

* platform/mac/HIDGamepadProvider.cpp:
(WebCore::HIDGamepadProvider::HIDGamepadProvider):
(WebCore::HIDGamepadProvider::valuesChanged): Set the input notification timer which will notify the clients
  that a button was pressed.
(WebCore::HIDGamepadProvider::inputNotificationTimerFired): Perform that notification.
* platform/mac/HIDGamepadProvider.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@170553 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/Modules/gamepad/GamepadManager.cpp
Source/WebCore/Modules/gamepad/GamepadManager.h
Source/WebCore/platform/GamepadProviderClient.h
Source/WebCore/platform/mac/HIDGamepadProvider.cpp
Source/WebCore/platform/mac/HIDGamepadProvider.h

index 48f03e8..a7bbe70 100644 (file)
@@ -1,5 +1,33 @@
 2014-06-27  Brady Eidson  <beidson@apple.com>
 
+        The user pressing a button on a gamepad should cause gamepads to become visible to all NavigatorGamepads.
+        https://bugs.webkit.org/show_bug.cgi?id=134375
+
+        Reviewed by Darin Adler.
+
+        No new tests (Not yet a tested config)
+
+        * Modules/gamepad/GamepadManager.cpp:
+        (WebCore::GamepadManager::platformGamepadConnected): Also call to makeGamepadsVisibileToBlindNavigators.
+        (WebCore::GamepadManager::platformGamepadDisconnected):
+        (WebCore::GamepadManager::platformGamepadInputActivity): Call makeGamepadsVisibileToBlindNavigators.
+        (WebCore::GamepadManager::makeGamepadsVisibileToBlindNavigators): Walk through each blind navigator
+          notifying it of each connected Gamepad.
+        (WebCore::GamepadManager::registerNavigator): Also add to the blind navigator set.
+        (WebCore::GamepadManager::unregisterNavigator): Also remove from the blind navigator set.
+        * Modules/gamepad/GamepadManager.h:
+
+        * platform/GamepadProviderClient.h: Added platformGamepadInputActivity.
+
+        * platform/mac/HIDGamepadProvider.cpp:
+        (WebCore::HIDGamepadProvider::HIDGamepadProvider):
+        (WebCore::HIDGamepadProvider::valuesChanged): Set the input notification timer which will notify the clients
+          that a button was pressed.
+        (WebCore::HIDGamepadProvider::inputNotificationTimerFired): Perform that notification.
+        * platform/mac/HIDGamepadProvider.h:
+
+2014-06-27  Brady Eidson  <beidson@apple.com>
+
         HIDGamepads should populate themselves with initial input values
         https://bugs.webkit.org/show_bug.cgi?id=134381
 
index 299296b..a41292b 100644 (file)
@@ -48,18 +48,45 @@ GamepadManager::GamepadManager()
 
 void GamepadManager::platformGamepadConnected(unsigned index)
 {
-    for (auto& navigator : m_navigators)
-        navigator->gamepadConnected(index);
+    for (auto& navigator : m_navigators) {
+        if (!m_gamepadBlindNavigators.contains(navigator))
+            navigator->gamepadConnected(index);
 
-    // FIXME: Fire connected event to all pages with listeners.
+        // FIXME: Fire connected event to all pages with listeners.
+    }
+
+    makeGamepadsVisibileToBlindNavigators();
 }
 
 void GamepadManager::platformGamepadDisconnected(unsigned index)
 {
-    // FIXME: Fire disconnected event to all pages with listeners.
+    for (auto& navigator : m_navigators) {
+        if (!m_gamepadBlindNavigators.contains(navigator))
+            navigator->gamepadDisconnected(index);
+
+        // FIXME: Fire disconnected event to all pages with listeners.
+    }
+}
+
+void GamepadManager::platformGamepadInputActivity()
+{
+    makeGamepadsVisibileToBlindNavigators();
+}
+
+void GamepadManager::makeGamepadsVisibileToBlindNavigators()
+{
+    for (auto& navigator : m_gamepadBlindNavigators) {
+        // FIXME: Here we notify a blind Navigator of each existing gamepad.
+        // But we also need to fire the connected event to its corresponding DOMWindow objects.
+        auto& platformGamepads = GamepadProvider::shared().platformGamepads();
+        unsigned size = platformGamepads.size();
+        for (unsigned i = 0; i < size; ++i) {
+            if (platformGamepads[i])
+                navigator->gamepadConnected(i);
+        }
+    }
 
-    for (auto& navigator : m_navigators)
-        navigator->gamepadDisconnected(index);
+    m_gamepadBlindNavigators.clear();
 }
 
 void GamepadManager::registerNavigator(NavigatorGamepad* navigator)
@@ -68,6 +95,7 @@ void GamepadManager::registerNavigator(NavigatorGamepad* navigator)
 
     ASSERT(!m_navigators.contains(navigator));
     m_navigators.add(navigator);
+    m_gamepadBlindNavigators.add(navigator);
 
     // FIXME: Monitoring gamepads will also be reliant on whether or not there are any
     // connected/disconnected event listeners.
@@ -84,6 +112,7 @@ void GamepadManager::unregisterNavigator(NavigatorGamepad* navigator)
 
     ASSERT(m_navigators.contains(navigator));
     m_navigators.remove(navigator);
+    m_gamepadBlindNavigators.remove(navigator);
 
     // FIXME: Monitoring gamepads will also be reliant on whether or not there are any
     // connected/disconnected event listeners.
index bbfc7b7..ce2fd4e 100644 (file)
@@ -46,6 +46,7 @@ public:
 
     virtual void platformGamepadConnected(unsigned index) override final;
     virtual void platformGamepadDisconnected(unsigned index) override final;
+    virtual void platformGamepadInputActivity() override final;
 
     void registerNavigator(NavigatorGamepad*);
     void unregisterNavigator(NavigatorGamepad*);
@@ -53,7 +54,10 @@ public:
 private:
     GamepadManager();
 
+    void makeGamepadsVisibileToBlindNavigators();
+
     HashSet<NavigatorGamepad*> m_navigators;
+    HashSet<NavigatorGamepad*> m_gamepadBlindNavigators;
 };
 
 } // namespace WebCore
index 5c79d30..0810a2d 100644 (file)
@@ -36,6 +36,7 @@ public:
 
     virtual void platformGamepadConnected(unsigned index) = 0;
     virtual void platformGamepadDisconnected(unsigned index) = 0;
+    virtual void platformGamepadInputActivity() = 0;
 };
 
 } // namespace WebCore
index c4eb9bf..7a304ce 100644 (file)
@@ -35,6 +35,7 @@
 namespace WebCore {
 
 static const double ConnectionDelayInterval = 0.5;
+static const double InputNotificationDelay = 0.05;
 
 static RetainPtr<CFDictionaryRef> deviceMatchingDictionary(uint32_t usagePage, uint32_t usage)
 {
@@ -81,6 +82,7 @@ HIDGamepadProvider& HIDGamepadProvider::shared()
 HIDGamepadProvider::HIDGamepadProvider()
     : m_shouldDispatchCallbacks(false)
     , m_connectionDelayTimer(this, &HIDGamepadProvider::connectionDelayTimerFired)
+    , m_inputNotificationTimer(this, &HIDGamepadProvider::inputNotificationTimerFired)
 {
     m_manager = adoptCF(IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone));
 
@@ -219,6 +221,20 @@ void HIDGamepadProvider::valuesChanged(IOHIDValueRef value)
         return;
 
     gamepad->valueChanged(value);
+
+    // This isActive check is necessary as we want to delay input notifications from the time of the first input,
+    // and not push the notification out on every subsequent input.
+    if (!m_inputNotificationTimer.isActive())
+        m_inputNotificationTimer.startOneShot(InputNotificationDelay);
+}
+
+void HIDGamepadProvider::inputNotificationTimerFired(Timer<HIDGamepadProvider>&)
+{
+    if (!m_shouldDispatchCallbacks)
+        return;
+
+    for (auto& client : m_clients)
+        client->platformGamepadInputActivity();
 }
 
 std::pair<std::unique_ptr<HIDGamepad>, unsigned>  HIDGamepadProvider::removeGamepadForDevice(IOHIDDeviceRef device)
index 724eece..4c3d162 100644 (file)
@@ -65,6 +65,7 @@ private:
     void closeAndUnscheduleManager();
 
     void connectionDelayTimerFired(Timer<HIDGamepadProvider>&);
+    void inputNotificationTimerFired(Timer<HIDGamepadProvider>&);
 
     unsigned indexForNewlyConnectedDevice();
 
@@ -77,6 +78,7 @@ private:
     bool m_shouldDispatchCallbacks;
 
     Timer<HIDGamepadProvider> m_connectionDelayTimer;
+    Timer<HIDGamepadProvider> m_inputNotificationTimer;
 };
 
 } // namespace WebCore