Title: [148713] trunk/Source/WebKit2
Revision
148713
Author
timothy_hor...@apple.com
Date
2013-04-18 16:40:20 -0700 (Thu, 18 Apr 2013)

Log Message

Add a synchronous version of WKView endDeferringViewInWindowChanges
https://bugs.webkit.org/show_bug.cgi?id=114780
<rdar://problem/12821901>

Reviewed by Simon Fraser.

Add new WKView SPI, endDeferringViewInWindowChangesSync, which synchronously
(though with a 250 ms timeout) does the work required to reparent a WKView
without flashing white.

* UIProcess/API/mac/WKView.mm:
(-[WKView beginDeferringViewInWindowChanges]):
(-[WKView endDeferringViewInWindowChanges]):
Make begin/endDeferringViewInWindowChanges not allow nested deferrals,
as we don't need them, and they complicate synchronous-end a lot.

(-[WKView endDeferringViewInWindowChangesSync]):
Add a sync version of endDeferringViewInWindowChanges which waits
for DidUpdateInWindowState.

(-[WKView isDeferringViewInWindowChanges]):

* UIProcess/API/mac/WKViewPrivate.h: Add endDeferringViewInWindowChangesSync.

* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::waitForDidUpdateInWindowState):
Add waitForDidUpdateInWindowState(), which blocks for
250ms or until the WebProcess reparents all of its layers and spins
the runloop once, to prevent flashing when parenting a WKView.
If we've already timed out waiting for the WebProcess, don't block, as
it's probably quite busy and is likely to time out again.

* UIProcess/WebPageProxy.h:
(WebKit::WebPageProxy::isInWindow): Added.
(WebKit::WebPageProxy::waitForDidUpdateInWindowState): Added.
(WebKit::WebPageProxy::didUpdateInWindowState): Added.

* UIProcess/WebPageProxy.messages.in: Add DidUpdateInWindowState()

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::didUpdateInWindowStateTimerFired): Send DidUpdateInWindowState to WebPageProxy.
(WebKit::WebPage::setIsInWindow): When setIsInWindow completes, TileController
tiles have been reparented, and the TiledCoreAnimationDrawingArea has
reconnected the layer tree to the context, start a 0-delay runloop timer
to allow painting and layer flushing to finish; when the timer fires,
we'll send the UIProcess a DidUpdateInWindowState so it can stop blocking.

* WebProcess/WebPage/WebPage.h:
(WebPage): Add didUpdateInWindowStateTimerFired and m_sendDidUpdateInWindowStateTimer.

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (148712 => 148713)


--- trunk/Source/WebKit2/ChangeLog	2013-04-18 23:32:20 UTC (rev 148712)
+++ trunk/Source/WebKit2/ChangeLog	2013-04-18 23:40:20 UTC (rev 148713)
@@ -1,3 +1,55 @@
+2013-04-18  Tim Horton  <timothy_hor...@apple.com>
+
+        Add a synchronous version of WKView endDeferringViewInWindowChanges
+        https://bugs.webkit.org/show_bug.cgi?id=114780
+        <rdar://problem/12821901>
+
+        Reviewed by Simon Fraser.
+
+        Add new WKView SPI, endDeferringViewInWindowChangesSync, which synchronously
+        (though with a 250 ms timeout) does the work required to reparent a WKView
+        without flashing white.
+
+        * UIProcess/API/mac/WKView.mm:
+        (-[WKView beginDeferringViewInWindowChanges]):
+        (-[WKView endDeferringViewInWindowChanges]):
+        Make begin/endDeferringViewInWindowChanges not allow nested deferrals,
+        as we don't need them, and they complicate synchronous-end a lot.
+
+        (-[WKView endDeferringViewInWindowChangesSync]):
+        Add a sync version of endDeferringViewInWindowChanges which waits
+        for DidUpdateInWindowState.
+
+        (-[WKView isDeferringViewInWindowChanges]):
+
+        * UIProcess/API/mac/WKViewPrivate.h: Add endDeferringViewInWindowChangesSync.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::waitForDidUpdateInWindowState):
+        Add waitForDidUpdateInWindowState(), which blocks for
+        250ms or until the WebProcess reparents all of its layers and spins
+        the runloop once, to prevent flashing when parenting a WKView.
+        If we've already timed out waiting for the WebProcess, don't block, as
+        it's probably quite busy and is likely to time out again.
+
+        * UIProcess/WebPageProxy.h:
+        (WebKit::WebPageProxy::isInWindow): Added.
+        (WebKit::WebPageProxy::waitForDidUpdateInWindowState): Added.
+        (WebKit::WebPageProxy::didUpdateInWindowState): Added.
+
+        * UIProcess/WebPageProxy.messages.in: Add DidUpdateInWindowState()
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::didUpdateInWindowStateTimerFired): Send DidUpdateInWindowState to WebPageProxy.
+        (WebKit::WebPage::setIsInWindow): When setIsInWindow completes, TileController
+        tiles have been reparented, and the TiledCoreAnimationDrawingArea has
+        reconnected the layer tree to the context, start a 0-delay runloop timer
+        to allow painting and layer flushing to finish; when the timer fires,
+        we'll send the UIProcess a DidUpdateInWindowState so it can stop blocking.
+
+        * WebProcess/WebPage/WebPage.h:
+        (WebPage): Add didUpdateInWindowStateTimerFired and m_sendDidUpdateInWindowStateTimer.
+
 2013-04-18  Anders Carlsson  <ander...@apple.com>
 
         StorageManager should keep track of local storage namespaces

Modified: trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm (148712 => 148713)


--- trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm	2013-04-18 23:32:20 UTC (rev 148712)
+++ trunk/Source/WebKit2/UIProcess/API/mac/WKView.mm	2013-04-18 23:40:20 UTC (rev 148713)
@@ -218,7 +218,7 @@
     NSRect _windowBottomCornerIntersectionRect;
     
     unsigned _frameSizeUpdatesDisabledCount;
-    unsigned _viewInWindowChangesDeferredCount;
+    BOOL _shouldDeferViewInWindowChanges;
 
     BOOL _viewInWindowChangeWasDeferred;
 
@@ -3392,27 +3392,48 @@
 
 - (void)beginDeferringViewInWindowChanges
 {
-    _data->_viewInWindowChangesDeferredCount++;
+    if (_data->_shouldDeferViewInWindowChanges) {
+        NSLog(@"beginDeferringViewInWindowChanges was called while already deferring view-in-window changes!");
+        return;
+    }
+
+    _data->_shouldDeferViewInWindowChanges = YES;
 }
 
 - (void)endDeferringViewInWindowChanges
 {
-    if (!_data->_viewInWindowChangesDeferredCount) {
-        NSLog(@"endDeferringViewInWindowChanges was called without a matching beginDeferringViewInWindowChanges!");
+    if (!_data->_shouldDeferViewInWindowChanges) {
+        NSLog(@"endDeferringViewInWindowChanges was called without beginDeferringViewInWindowChanges!");
         return;
     }
 
-    --_data->_viewInWindowChangesDeferredCount;
+    _data->_shouldDeferViewInWindowChanges = NO;
 
-    if (!_data->_viewInWindowChangesDeferredCount && _data->_viewInWindowChangeWasDeferred) {
+    if (_data->_viewInWindowChangeWasDeferred) {
         _data->_page->viewStateDidChange(WebPageProxy::ViewIsInWindow);
         _data->_viewInWindowChangeWasDeferred = NO;
     }
 }
 
+- (void)endDeferringViewInWindowChangesSync
+{
+    if (!_data->_shouldDeferViewInWindowChanges) {
+        NSLog(@"endDeferringViewInWindowChangesSync was called without beginDeferringViewInWindowChanges!");
+        return;
+    }
+
+    PageClient* pageClient = _data->_pageClient.get();
+    bool hasPendingViewInWindowChange = _data->_viewInWindowChangeWasDeferred && _data->_page->isInWindow() != pageClient->isViewInWindow();
+
+    [self endDeferringViewInWindowChanges];
+
+    if (hasPendingViewInWindowChange)
+        _data->_page->waitForDidUpdateInWindowState();
+}
+
 - (BOOL)isDeferringViewInWindowChanges
 {
-    return _data->_viewInWindowChangesDeferredCount;
+    return _data->_shouldDeferViewInWindowChanges;
 }
 
 - (BOOL)windowOcclusionDetectionEnabled

Modified: trunk/Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h (148712 => 148713)


--- trunk/Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h	2013-04-18 23:32:20 UTC (rev 148712)
+++ trunk/Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h	2013-04-18 23:40:20 UTC (rev 148713)
@@ -67,6 +67,7 @@
 
 - (void)beginDeferringViewInWindowChanges;
 - (void)endDeferringViewInWindowChanges;
+- (void)endDeferringViewInWindowChangesSync;
 - (BOOL)isDeferringViewInWindowChanges;
 
 - (BOOL)windowOcclusionDetectionEnabled;

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (148712 => 148713)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2013-04-18 23:32:20 UTC (rev 148712)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp	2013-04-18 23:40:20 UTC (rev 148713)
@@ -308,6 +308,7 @@
     , m_minimumLayoutWidth(0)
     , m_mediaVolume(1)
     , m_mayStartMediaWhenInWindow(true)
+    , m_waitingForDidUpdateInWindowState(false)
 #if ENABLE(PAGE_VISIBILITY_API)
     , m_visibilityState(PageVisibilityStateVisible)
 #endif
@@ -1040,6 +1041,20 @@
     updateBackingStoreDiscardableState();
 }
 
+void WebPageProxy::waitForDidUpdateInWindowState()
+{
+    // If we have previously timed out with no response from the WebProcess, don't block the UIProcess again until it starts responding.
+    if (m_waitingForDidUpdateInWindowState)
+        return;
+
+    m_waitingForDidUpdateInWindowState = true;
+
+    if (!m_process->isLaunching()) {
+        const double inWindowStateUpdateTimeout = 0.25;
+        m_process->connection()->waitForAndDispatchImmediately<Messages::WebPageProxy::DidUpdateInWindowState>(m_pageID, inWindowStateUpdateTimeout);
+    }
+}
+
 IntSize WebPageProxy::viewSize() const
 {
     return m_pageClient->viewSize();

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (148712 => 148713)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2013-04-18 23:32:20 UTC (rev 148712)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2013-04-18 23:40:20 UTC (rev 148713)
@@ -341,6 +341,8 @@
     };
     typedef unsigned ViewStateFlags;
     void viewStateDidChange(ViewStateFlags flags);
+    bool isInWindow() const { return m_isInWindow; }
+    void waitForDidUpdateInWindowState();
 
     WebCore::IntSize viewSize() const;
     bool isViewVisible() const { return m_isVisible; }
@@ -492,6 +494,7 @@
     void listenForLayoutMilestones(WebCore::LayoutMilestones);
 
     void setVisibilityState(WebCore::PageVisibilityState, bool isInitialState);
+    void didUpdateInWindowState() { m_waitingForDidUpdateInWindowState = false; }
 
     bool hasHorizontalScrollbar() const { return m_mainFrameHasHorizontalScrollbar; }
     bool hasVerticalScrollbar() const { return m_mainFrameHasVerticalScrollbar; }
@@ -1260,6 +1263,8 @@
     float m_mediaVolume;
     bool m_mayStartMediaWhenInWindow;
 
+    bool m_waitingForDidUpdateInWindowState;
+
 #if PLATFORM(QT)
     WTF::HashSet<RefPtr<QtRefCountedNetworkRequestData> > m_applicationSchemeRequests;
 #endif

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in (148712 => 148713)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in	2013-04-18 23:32:20 UTC (rev 148712)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in	2013-04-18 23:40:20 UTC (rev 148713)
@@ -318,4 +318,5 @@
     GetPluginPath(WTF::String mimeType, WTF::String urlString, WTF::String frameURLString, WTF::String pageURLString) -> (WTF::String pluginPath, uint32_t pluginLoadPolicy)
 #endif
 
+    DidUpdateInWindowState()
 }

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (148712 => 148713)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp	2013-04-18 23:32:20 UTC (rev 148712)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp	2013-04-18 23:40:20 UTC (rev 148713)
@@ -253,6 +253,7 @@
     , m_accessibilityObject(0)
 #endif
     , m_setCanStartMediaTimer(RunLoop::main(), this, &WebPage::setCanStartMediaTimerFired)
+    , m_sendDidUpdateInWindowStateTimer(RunLoop::main(), this, &WebPage::didUpdateInWindowStateTimerFired)
     , m_findController(this)
 #if ENABLE(TOUCH_EVENTS)
 #if PLATFORM(QT)
@@ -1977,6 +1978,11 @@
         m_page->setCanStartMedia(true);
 }
 
+void WebPage::didUpdateInWindowStateTimerFired()
+{
+    send(Messages::WebPageProxy::DidUpdateInWindowState());
+}
+
 inline bool WebPage::canHandleUserEvents() const
 {
 #if USE(TILED_BACKING_STORE)
@@ -2011,6 +2017,7 @@
     }
 
     m_page->setIsInWindow(isInWindow);
+    m_sendDidUpdateInWindowStateTimer.startOneShot(0);
 }
 
 void WebPage::didReceivePolicyDecision(uint64_t frameID, uint64_t listenerID, uint32_t policyAction, uint64_t downloadID)

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h (148712 => 148713)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h	2013-04-18 23:32:20 UTC (rev 148712)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.h	2013-04-18 23:40:20 UTC (rev 148713)
@@ -819,6 +819,7 @@
 
     void changeSelectedIndex(int32_t index);
     void setCanStartMediaTimerFired();
+    void didUpdateInWindowStateTimerFired();
 
     bool canHandleUserEvents() const;
 
@@ -915,6 +916,7 @@
 #endif
     
     WebCore::RunLoop::Timer<WebPage> m_setCanStartMediaTimer;
+    WebCore::RunLoop::Timer<WebPage> m_sendDidUpdateInWindowStateTimer;
     bool m_mayStartMediaWhenInWindow;
 
     HashMap<uint64_t, RefPtr<WebUndoStep> > m_undoStepMap;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to