[WK2] Don't monitor gamepads at all unless an interested WebPageProxy is in the activ...
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Aug 2016 01:29:52 +0000 (01:29 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Aug 2016 01:29:52 +0000 (01:29 +0000)
https://bugs.webkit.org/show_bug.cgi?id=160760

Reviewed by Tim Horton.

This patch makes it such that the UIProcess will only listen to the platform gamepad mechanism
if a WebPageProxy that is interested in gamepads is in the active window.

* UIProcess/Cocoa/WebViewImpl.mm:
(WebKit::WebViewImpl::windowDidBecomeKey):
(WebKit::WebViewImpl::windowDidResignKey):

* UIProcess/Gamepad/UIGamepadProvider.cpp:
(WebKit::UIGamepadProvider::UIGamepadProvider):
(WebKit::UIGamepadProvider::gamepadSyncTimerFired):
(WebKit::UIGamepadProvider::scheduleGamepadStateSync):
(WebKit::UIGamepadProvider::platformGamepadConnected):
(WebKit::UIGamepadProvider::platformGamepadDisconnected):
(WebKit::UIGamepadProvider::platformGamepadInputActivity):
(WebKit::UIGamepadProvider::processPoolStartedUsingGamepads):
(WebKit::UIGamepadProvider::processPoolStoppedUsingGamepads):
(WebKit::UIGamepadProvider::viewBecameActive):
(WebKit::UIGamepadProvider::viewBecameInactive):
(WebKit::UIGamepadProvider::scheduleDisableGamepadMonitoring):
(WebKit::UIGamepadProvider::disableMonitoringTimerFired):
(WebKit::UIGamepadProvider::startMonitoringGamepads):
(WebKit::UIGamepadProvider::stopMonitoringGamepads):
(WebKit::UIGamepadProvider::updateTimerFired): Deleted.
(WebKit::UIGamepadProvider::startOrStopSynchingGamepadState): Deleted.
* UIProcess/Gamepad/UIGamepadProvider.h:

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

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/Cocoa/WebViewImpl.mm
Source/WebKit2/UIProcess/Gamepad/UIGamepadProvider.cpp
Source/WebKit2/UIProcess/Gamepad/UIGamepadProvider.h

index a2d55a9..394cbcf 100644 (file)
@@ -1,5 +1,38 @@
 2016-08-11  Brady Eidson  <beidson@apple.com>
 
+        [WK2] Don't monitor gamepads at all unless an interested WebPageProxy is in the active window.
+        https://bugs.webkit.org/show_bug.cgi?id=160760
+
+        Reviewed by Tim Horton.
+        
+        This patch makes it such that the UIProcess will only listen to the platform gamepad mechanism
+        if a WebPageProxy that is interested in gamepads is in the active window.
+
+        * UIProcess/Cocoa/WebViewImpl.mm:
+        (WebKit::WebViewImpl::windowDidBecomeKey):
+        (WebKit::WebViewImpl::windowDidResignKey):
+
+        * UIProcess/Gamepad/UIGamepadProvider.cpp:
+        (WebKit::UIGamepadProvider::UIGamepadProvider):
+        (WebKit::UIGamepadProvider::gamepadSyncTimerFired):
+        (WebKit::UIGamepadProvider::scheduleGamepadStateSync):
+        (WebKit::UIGamepadProvider::platformGamepadConnected):
+        (WebKit::UIGamepadProvider::platformGamepadDisconnected):
+        (WebKit::UIGamepadProvider::platformGamepadInputActivity):
+        (WebKit::UIGamepadProvider::processPoolStartedUsingGamepads):
+        (WebKit::UIGamepadProvider::processPoolStoppedUsingGamepads):
+        (WebKit::UIGamepadProvider::viewBecameActive):
+        (WebKit::UIGamepadProvider::viewBecameInactive):
+        (WebKit::UIGamepadProvider::scheduleDisableGamepadMonitoring):
+        (WebKit::UIGamepadProvider::disableMonitoringTimerFired):
+        (WebKit::UIGamepadProvider::startMonitoringGamepads):
+        (WebKit::UIGamepadProvider::stopMonitoringGamepads):
+        (WebKit::UIGamepadProvider::updateTimerFired): Deleted.
+        (WebKit::UIGamepadProvider::startOrStopSynchingGamepadState): Deleted.
+        * UIProcess/Gamepad/UIGamepadProvider.h:
+
+2016-08-11  Brady Eidson  <beidson@apple.com>
+
         Make Gamepads be a WK2 ExperimentalFeature.
         https://bugs.webkit.org/show_bug.cgi?id=160788
 
index 4093390..65169ed 100644 (file)
@@ -46,6 +46,7 @@
 #import "TextChecker.h"
 #import "TextCheckerState.h"
 #import "TiledCoreAnimationDrawingAreaProxy.h"
+#import "UIGamepadProvider.h"
 #import "ViewGestureController.h"
 #import "WKBrowsingContextControllerInternal.h"
 #import "WKFullScreenWindowController.h"
@@ -1056,6 +1057,9 @@ void WebViewImpl::windowDidOrderOnScreen()
 void WebViewImpl::windowDidBecomeKey(NSWindow *keyWindow)
 {
     if (keyWindow == m_view.window || keyWindow == m_view.window.attachedSheet) {
+#if ENABLE(GAMEPAD)
+        UIGamepadProvider::singleton().viewBecameActive(m_page.get());
+#endif
         updateSecureInputState();
         m_page->viewStateDidChange(WebCore::ViewState::WindowIsActive);
     }
@@ -1064,6 +1068,9 @@ void WebViewImpl::windowDidBecomeKey(NSWindow *keyWindow)
 void WebViewImpl::windowDidResignKey(NSWindow *formerKeyWindow)
 {
     if (formerKeyWindow == m_view.window || formerKeyWindow == m_view.window.attachedSheet) {
+#if ENABLE(GAMEPAD)
+        UIGamepadProvider::singleton().viewBecameInactive(m_page.get());
+#endif
         updateSecureInputState();
         m_page->viewStateDidChange(WebCore::ViewState::WindowIsActive);
     }
index 645d350..750eaef 100644 (file)
@@ -38,7 +38,7 @@ using namespace WebCore;
 
 namespace WebKit {
 
-static const double gamepadUpdateInterval = 1 / 60.0;
+static const double maximumGamepadUpdateInterval = 1 / 120.0;
 
 UIGamepadProvider& UIGamepadProvider::singleton()
 {
@@ -47,7 +47,8 @@ UIGamepadProvider& UIGamepadProvider::singleton()
 }
 
 UIGamepadProvider::UIGamepadProvider()
-    : m_timer(*this, &UIGamepadProvider::updateTimerFired)
+    : m_gamepadSyncTimer(RunLoop::main(), this, &UIGamepadProvider::gamepadSyncTimerFired)
+    , m_disableMonitoringTimer(RunLoop::main(), this, &UIGamepadProvider::disableMonitoringTimerFired)
 {
 }
 
@@ -57,9 +58,10 @@ UIGamepadProvider::~UIGamepadProvider()
         platformStopMonitoringGamepads();
 }
 
-void UIGamepadProvider::updateTimerFired()
+void UIGamepadProvider::gamepadSyncTimerFired()
 {
-    if (!m_hadActivitySinceLastSynch)
+    auto webPageProxy = platformWebPageProxyForGamepadInput();
+    if (!webPageProxy || !m_processPoolsUsingGamepads.contains(&webPageProxy->process().processPool()))
         return;
 
     Vector<GamepadData> gamepadDatas;
@@ -72,24 +74,20 @@ void UIGamepadProvider::updateTimerFired()
             gamepadDatas.uncheckedAppend({ });
     }
 
-    auto webPageProxy = platformWebPageProxyForGamepadInput();
-    if (webPageProxy && m_processPoolsUsingGamepads.contains(&webPageProxy->process().processPool()))
-        webPageProxy->gamepadActivity(gamepadDatas);
-
-    m_hadActivitySinceLastSynch = false;
+    webPageProxy->gamepadActivity(gamepadDatas);
 }
 
-void UIGamepadProvider::startOrStopSynchingGamepadState()
+void UIGamepadProvider::scheduleGamepadStateSync()
 {
-    // FIXME (https://bugs.webkit.org/show_bug.cgi?id=160699)
-    // Only start synching updates if the currently focused WKWebView is also listening for gamepads.
+    if (!m_isMonitoringGamepads || m_gamepadSyncTimer.isActive())
+        return;
 
-    // FIXME (https://bugs.webkit.org/show_bug.cgi?id=160673)
-    // Instead of refreshing gamepad data on a 60hz timer, actually sync with the display.
-    if (m_gamepads.isEmpty() || m_processPoolsUsingGamepads.isEmpty())
-        m_timer.stop();
-    else
-        m_timer.startRepeating(gamepadUpdateInterval);
+    if (m_gamepads.isEmpty() || m_processPoolsUsingGamepads.isEmpty()) {
+        m_gamepadSyncTimer.stop();
+        return;
+    }
+
+    m_gamepadSyncTimer.startOneShot(maximumGamepadUpdateInterval);
 }
 
 void UIGamepadProvider::platformGamepadConnected(PlatformGamepad& gamepad)
@@ -100,8 +98,7 @@ void UIGamepadProvider::platformGamepadConnected(PlatformGamepad& gamepad)
     ASSERT(!m_gamepads[gamepad.index()]);
     m_gamepads[gamepad.index()] = std::make_unique<UIGamepad>(gamepad);
 
-    m_hadActivitySinceLastSynch = true;
-    startOrStopSynchingGamepadState();
+    scheduleGamepadStateSync();
 
     for (auto& pool : m_processPoolsUsingGamepads)
         pool->gamepadConnected(*m_gamepads[gamepad.index()]);
@@ -114,7 +111,7 @@ void UIGamepadProvider::platformGamepadDisconnected(PlatformGamepad& gamepad)
 
     std::unique_ptr<UIGamepad> disconnectedGamepad = WTFMove(m_gamepads[gamepad.index()]);
 
-    startOrStopSynchingGamepadState();
+    scheduleGamepadStateSync();
 
     for (auto& pool : m_processPoolsUsingGamepads)
         pool->gamepadDisconnected(*disconnectedGamepad);
@@ -135,33 +132,74 @@ void UIGamepadProvider::platformGamepadInputActivity()
         m_gamepads[i]->updateFromPlatformGamepad(*platformGamepads[i]);
     }
 
-    m_hadActivitySinceLastSynch = true;
+    scheduleGamepadStateSync();
 }
 
 void UIGamepadProvider::processPoolStartedUsingGamepads(WebProcessPool& pool)
 {
-    bool wereAnyProcessPoolsUsingGamepads = !m_processPoolsUsingGamepads.isEmpty();
-
     ASSERT(!m_processPoolsUsingGamepads.contains(&pool));
     m_processPoolsUsingGamepads.add(&pool);
 
-    if (!wereAnyProcessPoolsUsingGamepads)
-        platformStartMonitoringGamepads();
+    if (!m_isMonitoringGamepads && platformWebPageProxyForGamepadInput())
+        startMonitoringGamepads();
 
-    startOrStopSynchingGamepadState();
+    scheduleGamepadStateSync();
 }
 
 void UIGamepadProvider::processPoolStoppedUsingGamepads(WebProcessPool& pool)
 {
-    bool wereAnyProcessPoolsUsingGamepads = !m_processPoolsUsingGamepads.isEmpty();
-
     ASSERT(m_processPoolsUsingGamepads.contains(&pool));
     m_processPoolsUsingGamepads.remove(&pool);
 
-    if (wereAnyProcessPoolsUsingGamepads && m_processPoolsUsingGamepads.isEmpty())
-        platformStopMonitoringGamepads();
+    if (m_isMonitoringGamepads && !platformWebPageProxyForGamepadInput())
+        scheduleDisableGamepadMonitoring();
+
+    scheduleGamepadStateSync();
+}
+
+void UIGamepadProvider::viewBecameActive(WebPageProxy& page)
+{
+    if (!m_processPoolsUsingGamepads.contains(&page.process().processPool()))
+        return;
+
+    m_disableMonitoringTimer.stop();
+    startMonitoringGamepads();
+}
+
+void UIGamepadProvider::viewBecameInactive(WebPageProxy& page)
+{
+    auto pageForGamepadInput = platformWebPageProxyForGamepadInput();
+    if (pageForGamepadInput == &page)
+        scheduleDisableGamepadMonitoring();
+}
+
+void UIGamepadProvider::scheduleDisableGamepadMonitoring()
+{
+    if (!m_disableMonitoringTimer.isActive())
+        m_disableMonitoringTimer.startOneShot(0);
+}
+
+void UIGamepadProvider::disableMonitoringTimerFired()
+{
+    stopMonitoringGamepads();
+}
+
+void UIGamepadProvider::startMonitoringGamepads()
+{
+    if (m_isMonitoringGamepads)
+        return;
+
+    m_isMonitoringGamepads = true;
+    platformStartMonitoringGamepads();
+}
+
+void UIGamepadProvider::stopMonitoringGamepads()
+{
+    if (!m_isMonitoringGamepads)
+        return;
 
-    startOrStopSynchingGamepadState();
+    m_isMonitoringGamepads = false;
+    platformStopMonitoringGamepads();
 }
 
 #if !PLATFORM(MAC)
index 5b04068..70dc842 100644 (file)
@@ -28,9 +28,9 @@
 #if ENABLE(GAMEPAD)
 
 #include <WebCore/GamepadProviderClient.h>
-#include <WebCore/Timer.h>
 #include <wtf/HashSet.h>
 #include <wtf/NeverDestroyed.h>
+#include <wtf/RunLoop.h>
 #include <wtf/Vector.h>
 
 namespace WebKit {
@@ -47,6 +47,9 @@ public:
     void processPoolStartedUsingGamepads(WebProcessPool&);
     void processPoolStoppedUsingGamepads(WebProcessPool&);
 
+    void viewBecameActive(WebPageProxy&);
+    void viewBecameInactive(WebPageProxy&);
+
     Vector<GamepadData> gamepadStates() const;
 
 private:
@@ -54,6 +57,9 @@ private:
     UIGamepadProvider();
     ~UIGamepadProvider() final;
 
+    void startMonitoringGamepads();
+    void stopMonitoringGamepads();
+
     void platformStartMonitoringGamepads();
     void platformStopMonitoringGamepads();
     const Vector<WebCore::PlatformGamepad*>& platformGamepads();
@@ -63,15 +69,20 @@ private:
     void platformGamepadDisconnected(WebCore::PlatformGamepad&) final;
     void platformGamepadInputActivity() final;
 
-    void startOrStopSynchingGamepadState();
-    void updateTimerFired();
+    void scheduleGamepadStateSync();
+    void gamepadSyncTimerFired();
+
+    void scheduleDisableGamepadMonitoring();
+    void disableMonitoringTimerFired();
 
     HashSet<WebProcessPool*> m_processPoolsUsingGamepads;
 
     Vector<std::unique_ptr<UIGamepad>> m_gamepads;
 
-    WebCore::Timer m_timer;
-    bool m_hadActivitySinceLastSynch { false };
+    RunLoop::Timer<UIGamepadProvider> m_gamepadSyncTimer;
+    RunLoop::Timer<UIGamepadProvider> m_disableMonitoringTimer;
+
+    bool m_isMonitoringGamepads { false };
 };
 
 }