Changeset 257840 in webkit


Ignore:
Timestamp:
Mar 4, 2020 6:53:01 AM (4 years ago)
Author:
Alan Bujtas
Message:

[First paint] Going from visually empty to non-empty should immediately trigger layer unfreezing
https://bugs.webkit.org/show_bug.cgi?id=208385
<rdar://problem/59895900>

Reviewed by Antti Koivisto.
Source/WebCore:

Now that VNE check and layout are decoupled, we should also decouple the VNE layout milestone and
layer unfreezing.
In many cases a style change does not initiate synchronous layout (see Document::updateStyleIfNeeded) which
potentially delays the first paint. This patch ensure that we unfreeze the layer tree and issue paint soon after
the style change produced a VNE content.

  • loader/EmptyFrameLoaderClient.h:
  • loader/FrameLoader.cpp:

(WebCore::FrameLoader::didReachVisuallyNonEmptyState):

  • loader/FrameLoader.h:
  • loader/FrameLoaderClient.h:
  • page/FrameView.cpp:

(WebCore::FrameView::styleAndRenderTreeDidChange):
(WebCore::FrameView::checkAndDispatchDidReachVisuallyNonEmptyState):
(WebCore::FrameView::fireLayoutRelatedMilestonesIfNeeded):
(WebCore::FrameView::qualifiesAsVisuallyNonEmpty const): Deleted.

  • page/FrameView.h:

Source/WebKit:

  • WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:

(WebKit::WebFrameLoaderClient::dispatchDidReachLayoutMilestone):
(WebKit::WebFrameLoaderClient::dispatchDidReachVisuallyNonEmptyState):

  • WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::didCompletePageTransition):

  • WebProcess/WebPage/ios/WebPageIOS.mm:

(WebKit::WebPage::resetIdempotentTextAutosizingIfNeeded): We don't have this case anymore.

  • WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:

(WebKit::TiledCoreAnimationDrawingArea::scheduleRenderingUpdate):

LayoutTests:

  • fast/scrolling/scroll-animator-overlay-scrollbars-clicked-expected.txt:
  • fast/scrolling/scroll-animator-overlay-scrollbars-clicked.html:
  • fast/scrolling/scroll-animator-overlay-scrollbars-hovered-expected.txt:
  • fast/scrolling/scroll-animator-overlay-scrollbars-hovered.html:
Location:
trunk
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r257839 r257840  
     12020-03-04  Zalan Bujtas  <zalan@apple.com>
     2
     3        [First paint] Going from visually empty to non-empty should immediately trigger layer unfreezing
     4        https://bugs.webkit.org/show_bug.cgi?id=208385
     5        <rdar://problem/59895900>
     6
     7        Reviewed by Antti Koivisto.
     8       
     9        * fast/scrolling/scroll-animator-overlay-scrollbars-clicked-expected.txt:
     10        * fast/scrolling/scroll-animator-overlay-scrollbars-clicked.html:
     11        * fast/scrolling/scroll-animator-overlay-scrollbars-hovered-expected.txt:
     12        * fast/scrolling/scroll-animator-overlay-scrollbars-hovered.html:
     13
    1142020-03-04  Antti Koivisto  <antti@apple.com>
    215
  • trunk/LayoutTests/fast/scrolling/scroll-animator-overlay-scrollbars-clicked-expected.txt

    r236564 r257840  
    1 CONSOLE MESSAGE: line 13: MainFrameView: didAddVerticalScrollbar
    2 CONSOLE MESSAGE: line 13: MainFrameView: didAddHorizontalScrollbar
    3 CONSOLE MESSAGE: line 13: FrameView: didAddVerticalScrollbar
    4 CONSOLE MESSAGE: line 13: FrameView: willRemoveVerticalScrollbar
    5 CONSOLE MESSAGE: line 16: MainFrameView: mouseEnteredContentArea
    6 CONSOLE MESSAGE: line 16: MainFrameView: mouseMovedInContentArea
    7 CONSOLE MESSAGE: line 18: MainFrameView: mouseEnteredVerticalScrollbar
    8 CONSOLE MESSAGE: line 18: FrameView: mouseEnteredContentArea
    9 CONSOLE MESSAGE: line 18: MainFrameView: mouseMovedInContentArea
    10 CONSOLE MESSAGE: line 19: MainFrameView: mouseIsDownInVerticalScrollbar
    11 CONSOLE MESSAGE: line 20: MainFrameView: mouseIsUpInVerticalScrollbar
    12 CONSOLE MESSAGE: line 21: MainFrameView: mouseExitedVerticalScrollbar
    13 CONSOLE MESSAGE: line 21: FrameView: mouseExitedContentArea
     1CONSOLE MESSAGE: MainFrameView: didAddVerticalScrollbar
     2CONSOLE MESSAGE: MainFrameView: didAddHorizontalScrollbar
     3CONSOLE MESSAGE: FrameView: didAddVerticalScrollbar
     4CONSOLE MESSAGE: FrameView: willRemoveVerticalScrollbar
     5CONSOLE MESSAGE: FrameView: didAddVerticalScrollbar
     6CONSOLE MESSAGE: FrameView: willRemoveVerticalScrollbar
     7CONSOLE MESSAGE: line 19: MainFrameView: mouseEnteredContentArea
     8CONSOLE MESSAGE: line 19: MainFrameView: mouseMovedInContentArea
     9CONSOLE MESSAGE: line 21: MainFrameView: mouseEnteredVerticalScrollbar
     10CONSOLE MESSAGE: line 21: FrameView: mouseEnteredContentArea
    1411CONSOLE MESSAGE: line 21: MainFrameView: mouseMovedInContentArea
     12CONSOLE MESSAGE: line 22: MainFrameView: mouseIsDownInVerticalScrollbar
     13CONSOLE MESSAGE: line 23: MainFrameView: mouseIsUpInVerticalScrollbar
     14CONSOLE MESSAGE: line 24: MainFrameView: mouseExitedVerticalScrollbar
     15CONSOLE MESSAGE: line 24: FrameView: mouseExitedContentArea
     16CONSOLE MESSAGE: line 24: MainFrameView: mouseMovedInContentArea
    1517PASS successfullyParsed is true
    1618
  • trunk/LayoutTests/fast/scrolling/scroll-animator-overlay-scrollbars-clicked.html

    r236564 r257840  
    22<script src="../../resources/js-test-pre.js"></script>
    33<script>
    4   if (window.internals) {
    5       window.internals.setUsesMockScrollAnimator(true);
    6       window.internals.setUsesOverlayScrollbars(true);
    7   }
    8   if (window.testRunner) {
    9       testRunner.waitUntilDone();
    10       testRunner.dumpAsText();
    11   }
    12   window.onload = function () {
    13       document.body.offsetTop; // force layout.
    14       setTimeout(() => {
    15       if (window.eventSender) {
    16           eventSender.mouseMoveTo(0, 0);
    17           // Move to a position that is over the vertical scrollbar and the iframe.
    18           eventSender.mouseMoveTo(window.innerWidth - 4, 100);
    19           eventSender.mouseDown();
    20           eventSender.mouseUp();
    21           eventSender.mouseMoveTo(0, 0);
    22       }
    23       if (window.testRunner)
    24           testRunner.notifyDone();
    25      }, 0);
    26   };
     4if (window.internals) {
     5    window.internals.setUsesMockScrollAnimator(true);
     6    window.internals.setUsesOverlayScrollbars(true);
     7}
     8
     9if (window.testRunner) {
     10    testRunner.waitUntilDone();
     11    testRunner.dumpAsText();
     12}
     13
     14function runTest() {
     15    setTimeout(() => {
     16        if (window.internals)
     17            internals.updateLayoutAndStyleForAllFrames();
     18        if (window.eventSender) {
     19            eventSender.mouseMoveTo(0, 0);
     20            // Move to a position that is over the vertical scrollbar and the iframe.
     21            eventSender.mouseMoveTo(window.innerWidth - 4, 100);
     22            eventSender.mouseDown();
     23            eventSender.mouseUp();
     24            eventSender.mouseMoveTo(0, 0);
     25        }
     26        if (window.testRunner)
     27            testRunner.notifyDone();
     28    }, 0);
     29};
    2730</script>
    2831<script src="../../resources/js-test-post.js"></script>
    2932<body>
    3033  <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=165056">https://bugs.webkit.org/show_bug.cgi?id=165056</a>.</p>
    31   <iframe width="1024" height="768" id="frame" src="data:text/html,<html></html>"></iframe>
     34  <iframe onload="runTest()" width="1024" height="768" id="frame" src="data:text/html,<html></html>"></iframe>
    3235  <pre id="console"></pre>
    3336</body>
  • trunk/LayoutTests/fast/scrolling/scroll-animator-overlay-scrollbars-hovered-expected.txt

    r196688 r257840  
    1 CONSOLE MESSAGE: line 15: MainFrameView: didAddVerticalScrollbar
    2 CONSOLE MESSAGE: line 15: FrameView: didAddVerticalScrollbar
    3 CONSOLE MESSAGE: line 15: FrameView: didAddHorizontalScrollbar
    4 CONSOLE MESSAGE: line 15: FrameView: willRemoveVerticalScrollbar
    5 CONSOLE MESSAGE: line 15: MainFrameView: mouseEnteredContentArea
    6 CONSOLE MESSAGE: line 15: MainFrameView: mouseMovedInContentArea
    7 CONSOLE MESSAGE: line 16: FrameView: mouseEnteredHorizontalScrollbar
    8 CONSOLE MESSAGE: line 16: FrameView: mouseEnteredContentArea
    9 CONSOLE MESSAGE: line 16: MainFrameView: mouseMovedInContentArea
    10 CONSOLE MESSAGE: line 17: FrameView: mouseExitedHorizontalScrollbar
    11 CONSOLE MESSAGE: line 17: FrameView: mouseExitedContentArea
     1CONSOLE MESSAGE: MainFrameView: didAddVerticalScrollbar
     2CONSOLE MESSAGE: FrameView: didAddVerticalScrollbar
     3CONSOLE MESSAGE: FrameView: willRemoveVerticalScrollbar
     4CONSOLE MESSAGE: line 14: FrameView: didAddVerticalScrollbar
     5CONSOLE MESSAGE: line 14: FrameView: didAddHorizontalScrollbar
     6CONSOLE MESSAGE: line 14: FrameView: willRemoveVerticalScrollbar
     7CONSOLE MESSAGE: line 17: MainFrameView: mouseEnteredContentArea
    128CONSOLE MESSAGE: line 17: MainFrameView: mouseMovedInContentArea
     9CONSOLE MESSAGE: line 18: FrameView: mouseEnteredHorizontalScrollbar
     10CONSOLE MESSAGE: line 18: FrameView: mouseEnteredContentArea
     11CONSOLE MESSAGE: line 18: MainFrameView: mouseMovedInContentArea
     12CONSOLE MESSAGE: line 19: FrameView: mouseExitedHorizontalScrollbar
     13CONSOLE MESSAGE: line 19: FrameView: mouseExitedContentArea
     14CONSOLE MESSAGE: line 19: MainFrameView: mouseMovedInContentArea
    1315PASS successfullyParsed is true
    1416
  • trunk/LayoutTests/fast/scrolling/scroll-animator-overlay-scrollbars-hovered.html

    r196688 r257840  
    22<script src="../../resources/js-test-pre.js"></script>
    33<script>
    4   if (window.internals) {
    5       window.internals.setUsesMockScrollAnimator(true);
    6       window.internals.setUsesOverlayScrollbars(true);
    7   }
    8   if (window.testRunner) {
    9       testRunner.waitUntilDone();
    10       testRunner.dumpAsText();
    11   }
    12   window.onload = function () {
    13       var frame = document.getElementById("frame");
    14       if (window.eventSender) {
    15           eventSender.mouseMoveTo(0, 0);
    16           eventSender.mouseMoveTo(frame.offsetLeft + 4, frame.offsetTop + frame.offsetHeight - 4);
    17           eventSender.mouseMoveTo(0, 0);
    18       }
    19       if (window.testRunner)
    20           testRunner.notifyDone();
    21   };
     4if (window.internals) {
     5    window.internals.setUsesMockScrollAnimator(true);
     6    window.internals.setUsesOverlayScrollbars(true);
     7}
     8if (window.testRunner) {
     9    testRunner.waitUntilDone();
     10    testRunner.dumpAsText();
     11}
     12function runTest() {
     13    if (window.internals)
     14        internals.updateLayoutAndStyleForAllFrames();
     15    document.body.offsetHeight;
     16    if (window.eventSender) {
     17        eventSender.mouseMoveTo(0, 0);
     18        eventSender.mouseMoveTo(frame.offsetLeft + 4, frame.offsetTop + frame.offsetHeight - 4);
     19        eventSender.mouseMoveTo(0, 0);
     20    }
     21    if (window.testRunner)
     22        testRunner.notifyDone();
     23};
    2224</script>
    2325<script src="../../resources/js-test-post.js"></script>
    2426<body>
    2527  <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=153304">https://bugs.webkit.org/show_bug.cgi?id=153304</a>.</p>
    26   <iframe width=120 scrolling=yes id="frame" src="data:text/html,
     28  <iframe onload="runTest()" width=120 scrolling=yes id="frame" src="data:text/html,
    2729      <p style='white-space: nowrap'>Scroll animator should be notified when overlay scrollbars in main frame are hovered</p>
    2830      ">
  • trunk/Source/WebCore/ChangeLog

    r257839 r257840  
     12020-03-04  Zalan Bujtas  <zalan@apple.com>
     2
     3        [First paint] Going from visually empty to non-empty should immediately trigger layer unfreezing
     4        https://bugs.webkit.org/show_bug.cgi?id=208385
     5        <rdar://problem/59895900>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Now that VNE check and layout are decoupled, we should also decouple the VNE layout milestone and
     10        layer unfreezing.
     11        In many cases a style change does not initiate synchronous layout (see Document::updateStyleIfNeeded) which
     12        potentially delays the first paint. This patch ensure that we unfreeze the layer tree and issue paint soon after
     13        the style change produced a VNE content.
     14
     15        * loader/EmptyFrameLoaderClient.h:
     16        * loader/FrameLoader.cpp:
     17        (WebCore::FrameLoader::didReachVisuallyNonEmptyState):
     18        * loader/FrameLoader.h:
     19        * loader/FrameLoaderClient.h:
     20        * page/FrameView.cpp:
     21        (WebCore::FrameView::styleAndRenderTreeDidChange):
     22        (WebCore::FrameView::checkAndDispatchDidReachVisuallyNonEmptyState):
     23        (WebCore::FrameView::fireLayoutRelatedMilestonesIfNeeded):
     24        (WebCore::FrameView::qualifiesAsVisuallyNonEmpty const): Deleted.
     25        * page/FrameView.h:
     26
    1272020-03-04  Antti Koivisto  <antti@apple.com>
    228
  • trunk/Source/WebCore/dom/Document.cpp

    r257839 r257840  
    13571357
    13581358    if (Frame* frame = this->frame())
    1359         frame->loader().forcePageTransitionIfNeeded();
     1359        frame->loader().completePageTransitionIfNeeded();
    13601360}
    13611361
  • trunk/Source/WebCore/loader/EmptyFrameLoaderClient.h

    r256073 r257840  
    9696    void dispatchDidFinishLoad() final { }
    9797    void dispatchDidReachLayoutMilestone(OptionSet<LayoutMilestone>) final { }
     98    void dispatchDidReachVisuallyNonEmptyState() final { }
    9899
    99100    Frame* dispatchCreatePage(const NavigationAction&) final { return nullptr; }
  • trunk/Source/WebCore/loader/FrameLoader.cpp

    r257707 r257840  
    26932693}
    26942694
     2695void FrameLoader::didReachVisuallyNonEmptyState()
     2696{
     2697    ASSERT(m_frame.isMainFrame());
     2698    m_client.dispatchDidReachVisuallyNonEmptyState();
     2699}
     2700
    26952701void FrameLoader::frameLoadCompleted()
    26962702{
     
    40744080}
    40754081
    4076 void FrameLoader::forcePageTransitionIfNeeded()
    4077 {
    4078     m_client.forcePageTransitionIfNeeded();
     4082void FrameLoader::completePageTransitionIfNeeded()
     4083{
     4084    m_client.completePageTransitionIfNeeded();
    40794085}
    40804086
  • trunk/Source/WebCore/loader/FrameLoader.h

    r257707 r257840  
    212212    void didReachLayoutMilestone(OptionSet<LayoutMilestone>);
    213213    void didFirstLayout();
     214    void didReachVisuallyNonEmptyState();
    214215
    215216    void loadedResourceFromMemoryCache(CachedResource&, ResourceRequest& newRequest, ResourceError&);
     
    312313    const URL& previousURL() const { return m_previousURL; }
    313314
    314     void forcePageTransitionIfNeeded();
     315    void completePageTransitionIfNeeded();
    315316
    316317    void setOverrideCachePolicyForTesting(ResourceRequestCachePolicy policy) { m_overrideCachePolicyForTesting = policy; }
  • trunk/Source/WebCore/loader/FrameLoaderClient.h

    r257780 r257840  
    188188    virtual void dispatchDidLayout() { }
    189189    virtual void dispatchDidReachLayoutMilestone(OptionSet<LayoutMilestone>) { }
     190    virtual void dispatchDidReachVisuallyNonEmptyState() { }
    190191
    191192    virtual Frame* dispatchCreatePage(const NavigationAction&) = 0;
     
    347348#endif
    348349
    349     virtual void forcePageTransitionIfNeeded() { }
     350    virtual void completePageTransitionIfNeeded() { }
    350351
    351352    // FIXME (bug 116233): We need to get rid of EmptyFrameLoaderClient completely, then this will no longer be needed.
  • trunk/Source/WebCore/page/FrameView.cpp

    r257648 r257840  
    810810        return;
    811811
    812     if (!m_contentQualifiesAsVisuallyNonEmpty) {
    813         // Let's check whether the newly constructed content qualifies as non-empty now.
    814         m_contentQualifiesAsVisuallyNonEmpty = qualifiesAsVisuallyNonEmpty();
    815     }
     812    checkAndDispatchDidReachVisuallyNonEmptyState();
    816813    auto* layerTreeMutationRoot = renderView->takeStyleChangeLayerTreeMutationRoot();
    817814    if (layerTreeMutationRoot && !needsLayout())
     
    43784375}
    43794376
    4380 bool FrameView::qualifiesAsVisuallyNonEmpty() const
    4381 {
    4382     // No content yet.
    4383     Element* documentElement = frame().document()->documentElement();
    4384     if (!documentElement || !documentElement->renderer())
    4385         return false;
    4386 
    4387     // FIXME: We should also ignore renderers with non-final style.
    4388     if (frame().document()->styleScope().hasPendingSheetsBeforeBody())
    4389         return false;
    4390 
    4391     auto finishedParsingMainDocument = frame().loader().stateMachine().committedFirstRealDocumentLoad() && (frame().document()->readyState() == Document::Interactive || frame().document()->readyState() == Document::Complete);
    4392     // Ensure that we always fire visually non-empty milestone eventually.
    4393     if (finishedParsingMainDocument && frame().loader().isComplete())
    4394         return true;
    4395 
    4396     auto isVisible = [](const Element* element) {
    4397         if (!element || !element->renderer())
     4377void FrameView::checkAndDispatchDidReachVisuallyNonEmptyState()
     4378{
     4379    auto qualifiesAsVisuallyNonEmpty = [&] {
     4380        // No content yet.
     4381        Element* documentElement = frame().document()->documentElement();
     4382        if (!documentElement || !documentElement->renderer())
    43984383            return false;
    4399         if (!element->renderer()->opacity())
     4384
     4385        // FIXME: We should also ignore renderers with non-final style.
     4386        if (frame().document()->styleScope().hasPendingSheetsBeforeBody())
    44004387            return false;
    4401         return element->renderer()->style().visibility() == Visibility::Visible;
    4402     };
    4403 
    4404     if (!isVisible(documentElement))
    4405         return false;
    4406 
    4407     if (!isVisible(frame().document()->body()))
    4408         return false;
    4409 
    4410     // The first few hundred characters rarely contain the interesting content of the page.
    4411     if (m_visuallyNonEmptyCharacterCount > visualCharacterThreshold)
    4412         return true;
    4413 
    4414     // Use a threshold value to prevent very small amounts of visible content from triggering didFirstVisuallyNonEmptyLayout
    4415     if (m_visuallyNonEmptyPixelCount > visualPixelThreshold)
    4416         return true;
    4417 
    4418     auto isMoreContentExpected = [&]() {
    4419         ASSERT(finishedParsingMainDocument);
    4420         // Pending css/font loading means we should wait a little longer. Classic non-async, non-defer scripts are all processed by now.
    4421         auto* documentLoader = frame().loader().documentLoader();
    4422         if (!documentLoader)
     4388
     4389        auto finishedParsingMainDocument = frame().loader().stateMachine().committedFirstRealDocumentLoad() && (frame().document()->readyState() == Document::Interactive || frame().document()->readyState() == Document::Complete);
     4390        // Ensure that we always fire visually non-empty milestone eventually.
     4391        if (finishedParsingMainDocument && frame().loader().isComplete())
     4392            return true;
     4393
     4394        auto isVisible = [](const Element* element) {
     4395            if (!element || !element->renderer())
     4396                return false;
     4397            if (!element->renderer()->opacity())
     4398                return false;
     4399            return element->renderer()->style().visibility() == Visibility::Visible;
     4400        };
     4401
     4402        if (!isVisible(documentElement))
    44234403            return false;
    44244404
    4425         auto& resourceLoader = documentLoader->cachedResourceLoader();
    4426         if (!resourceLoader.requestCount())
     4405        if (!isVisible(frame().document()->body()))
    44274406            return false;
    44284407
    4429         auto& resources = resourceLoader.allCachedResources();
    4430         for (auto& resource : resources) {
    4431             if (resource.value->isLoaded())
    4432                 continue;
    4433             if (resource.value->type() == CachedResource::Type::CSSStyleSheet || resource.value->type() == CachedResource::Type::FontResource)
    4434                 return true;
    4435         }
     4408        // The first few hundred characters rarely contain the interesting content of the page.
     4409        if (m_visuallyNonEmptyCharacterCount > visualCharacterThreshold)
     4410            return true;
     4411
     4412        // Use a threshold value to prevent very small amounts of visible content from triggering didFirstVisuallyNonEmptyLayout
     4413        if (m_visuallyNonEmptyPixelCount > visualPixelThreshold)
     4414            return true;
     4415
     4416        auto isMoreContentExpected = [&]() {
     4417            ASSERT(finishedParsingMainDocument);
     4418            // Pending css/font loading means we should wait a little longer. Classic non-async, non-defer scripts are all processed by now.
     4419            auto* documentLoader = frame().loader().documentLoader();
     4420            if (!documentLoader)
     4421                return false;
     4422
     4423            auto& resourceLoader = documentLoader->cachedResourceLoader();
     4424            if (!resourceLoader.requestCount())
     4425                return false;
     4426
     4427            auto& resources = resourceLoader.allCachedResources();
     4428            for (auto& resource : resources) {
     4429                if (resource.value->isLoaded())
     4430                    continue;
     4431                if (resource.value->type() == CachedResource::Type::CSSStyleSheet || resource.value->type() == CachedResource::Type::FontResource)
     4432                    return true;
     4433            }
     4434            return false;
     4435        };
     4436
     4437        // Finished parsing the main document and we still don't yet have enough content. Check if we might be getting some more.
     4438        if (finishedParsingMainDocument)
     4439            return !isMoreContentExpected();
     4440
    44364441        return false;
    44374442    };
    44384443
    4439     // Finished parsing the main document and we still don't yet have enough content. Check if we might be getting some more.
    4440     if (finishedParsingMainDocument)
    4441         return !isMoreContentExpected();
    4442 
    4443     return false;
     4444    if (m_contentQualifiesAsVisuallyNonEmpty)
     4445        return;
     4446
     4447    if (!qualifiesAsVisuallyNonEmpty())
     4448        return;
     4449
     4450    m_contentQualifiesAsVisuallyNonEmpty = true;
     4451    if (frame().isMainFrame())
     4452        frame().loader().didReachVisuallyNonEmptyState();
    44444453}
    44454454
     
    50915100
    50925101    if (m_firstVisuallyNonEmptyLayoutMilestoneIsPending) {
    5093         if (!m_contentQualifiesAsVisuallyNonEmpty)
    5094             m_contentQualifiesAsVisuallyNonEmpty = qualifiesAsVisuallyNonEmpty();
    5095 
     5102        checkAndDispatchDidReachVisuallyNonEmptyState();
    50965103        if (m_contentQualifiesAsVisuallyNonEmpty) {
    50975104            m_firstVisuallyNonEmptyLayoutMilestoneIsPending = false;
  • trunk/Source/WebCore/page/FrameView.h

    r257394 r257840  
    398398    void incrementVisuallyNonEmptyPixelCount(const IntSize&);
    399399    bool isVisuallyNonEmpty() const { return m_contentQualifiesAsVisuallyNonEmpty; }
    400     WEBCORE_EXPORT bool qualifiesAsVisuallyNonEmpty() const;
     400    void checkAndDispatchDidReachVisuallyNonEmptyState();
    401401
    402402    WEBCORE_EXPORT void enableAutoSizeMode(bool enable, const IntSize& minSize);
  • trunk/Source/WebKit/ChangeLog

    r257835 r257840  
     12020-03-04  Zalan Bujtas  <zalan@apple.com>
     2
     3        [First paint] Going from visually empty to non-empty should immediately trigger layer unfreezing
     4        https://bugs.webkit.org/show_bug.cgi?id=208385
     5        <rdar://problem/59895900>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
     10        (WebKit::WebFrameLoaderClient::dispatchDidReachLayoutMilestone):
     11        (WebKit::WebFrameLoaderClient::dispatchDidReachVisuallyNonEmptyState):
     12        * WebProcess/WebCoreSupport/WebFrameLoaderClient.h:
     13        * WebProcess/WebPage/WebPage.cpp:
     14        (WebKit::WebPage::didCompletePageTransition):
     15        * WebProcess/WebPage/ios/WebPageIOS.mm:
     16        (WebKit::WebPage::resetIdempotentTextAutosizingIfNeeded): We don't have this case anymore.
     17        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
     18        (WebKit::TiledCoreAnimationDrawingArea::scheduleRenderingUpdate):
     19
    1202020-03-03  Devin Rousso  <drousso@apple.com>
    221
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp

    r257780 r257840  
    681681}
    682682
    683 void WebFrameLoaderClient::forcePageTransitionIfNeeded()
     683void WebFrameLoaderClient::completePageTransitionIfNeeded()
    684684{
    685685    if (m_didCompletePageTransition)
    686686        return;
    687687
    688     WebPage* webPage = m_frame->page();
     688    auto* webPage = m_frame->page();
    689689    if (!webPage)
    690690        return;
     
    692692    webPage->didCompletePageTransition();
    693693    m_didCompletePageTransition = true;
     694    WEBFRAMELOADERCLIENT_RELEASE_LOG(Layout, "completePageTransitionIfNeeded: dispatching didCompletePageTransition");
    694695}
    695696
     
    743744
    744745    if (milestones & DidFirstVisuallyNonEmptyLayout) {
    745         if (m_frame->isMainFrame() && !m_didCompletePageTransition && !webPage->corePage()->settings().suppressesIncrementalRendering()) {
    746             WEBFRAMELOADERCLIENT_RELEASE_LOG(Layout, "dispatchDidReachLayoutMilestone: dispatching didCompletePageTransition");
    747             webPage->didCompletePageTransition();
    748             m_didCompletePageTransition = true;
    749         }
    750 
    751         // FIXME: We should consider removing the old didFirstVisuallyNonEmptyLayoutForFrame API since this is doing
    752         // double duty with the new didLayout API.
     746        ASSERT(!m_frame->isMainFrame() || webPage->corePage()->settings().suppressesIncrementalRendering() || m_didCompletePageTransition);
     747        // FIXME: We should consider removing the old didFirstVisuallyNonEmptyLayoutForFrame API since this is doing double duty with the new didLayout API.
    753748        WEBFRAMELOADERCLIENT_RELEASE_LOG(Layout, "dispatchDidReachLayoutMilestone: dispatching DidFirstVisuallyNonEmptyLayoutForFrame");
    754749        webPage->injectedBundleLoaderClient().didFirstVisuallyNonEmptyLayoutForFrame(*webPage, *m_frame, userData);
    755750        webPage->send(Messages::WebPageProxy::DidFirstVisuallyNonEmptyLayoutForFrame(m_frame->frameID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
    756751    }
     752}
     753
     754void WebFrameLoaderClient::dispatchDidReachVisuallyNonEmptyState()
     755{
     756    if (!m_frame->page() || m_frame->page()->corePage()->settings().suppressesIncrementalRendering())
     757        return;
     758    ASSERT(m_frame->isMainFrame());
     759    completePageTransitionIfNeeded();
    757760}
    758761
     
    13731376{
    13741377    // Note: Can be called multiple times.
    1375     WebPage* webPage = m_frame->page();
    1376     if (!webPage)
    1377         return;
    1378 
    1379     if (m_frame->isMainFrame() && !m_didCompletePageTransition) {
    1380         webPage->didCompletePageTransition();
    1381         m_didCompletePageTransition = true;
    1382     }
     1378    if (!m_frame->isMainFrame())
     1379        return;
     1380    completePageTransitionIfNeeded();
    13831381}
    13841382
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebFrameLoaderClient.h

    r257780 r257840  
    126126
    127127    void dispatchDidReachLayoutMilestone(OptionSet<WebCore::LayoutMilestone>) final;
     128    void dispatchDidReachVisuallyNonEmptyState() final;
    128129    void dispatchDidLayout() final;
    129130
     
    257258    Ref<WebCore::FrameNetworkingContext> createNetworkingContext() final;
    258259
    259     void forcePageTransitionIfNeeded() final;
     260    void completePageTransitionIfNeeded() final;
    260261
    261262#if USE(QUICK_LOOK)
  • trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm

    r257592 r257840  
    35013501    auto textAutoSizingDelay = [&] {
    35023502        auto& frameView = *m_page->mainFrame().view();
    3503         auto isVisaullyNonEmpty = frameView.isVisuallyNonEmpty();
    3504         auto willBeVisuallyNonEmptySoon = !isVisaullyNonEmpty && frameView.qualifiesAsVisuallyNonEmpty();
    3505         if (willBeVisuallyNonEmptySoon) {
    3506             // Be a bit more agressive on the first display.
    3507             const Seconds shortTextAutoSizingDelayOnViewportChange = 20_ms;
    3508             return shortTextAutoSizingDelayOnViewportChange;
    3509         }
    3510         if (!isVisaullyNonEmpty) {
    3511             // We don't anticipate any paining after the next upcoming layout.
     3503        if (!frameView.isVisuallyNonEmpty()) {
     3504            // We don't anticipate any painting after the next upcoming layout.
    35123505            const Seconds longTextAutoSizingDelayOnViewportChange = 100_ms;
    35133506            return longTextAutoSizingDelayOnViewportChange;
  • trunk/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm

    r257394 r257840  
    197197void TiledCoreAnimationDrawingArea::scheduleRenderingUpdate()
    198198{
    199     if (m_layerTreeStateIsFrozen) {
    200         return;
    201     }
    202 
     199    if (m_layerTreeStateIsFrozen)
     200        return;
    203201    scheduleRenderingUpdateRunLoopObserver();
    204202}
  • trunk/Source/WebKit/mac/WebKit2.order

    r253234 r257840  
    53305330__ZN6WebKit29TiledCoreAnimationDrawingArea14setExposedRectERKN7WebCore9FloatRectE
    53315331__ZN6WebKit29TiledCoreAnimationDrawingArea21setClipsToExposedRectEb
    5332 __ZN6WebKit20WebFrameLoaderClient27forcePageTransitionIfNeededEv
     5332__ZN6WebKit20WebFrameLoaderClient27completePageTransitionIfNeededEv
    53335333__ZN7WebCore5TimerIN6WebKit29TiledCoreAnimationDrawingAreaEE5firedEv
    53345334__ZN6WebKit29TiledCoreAnimationDrawingArea36updateIntrinsicContentSizeTimerFiredEPN7WebCore5TimerIS0_EE
Note: See TracChangeset for help on using the changeset viewer.