⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 253360 in webkit


Ignore:
Timestamp:
Dec 10, 2019, 6:16:19 PM (7 years ago)
Author:
Chris Dumez
Message:

[macOS] Issue load sooner on swipe back/forward navigation
https://bugs.webkit.org/show_bug.cgi?id=205087

Reviewed by Tim Horton.

Issue load sooner on swipe back/forward navigation on macOS. We were waiting until the end of
the swipe animation to issue the load. We now issue the load as soon as the user lifts the finger
off the screen and thus commits to navigating. This results in improved perceived performance
when swiping back/forward to navigate.

This patch does not take care of iOS because the ViewGestureController logic is different on that
platform. There is no reason we shouldn't be able to do the same optimization on iOS too though.

To achieve the behavior change on macOS, the following was done:

  • Issue the load in ViewGestureController::willEndSwipeGesture() instead of ViewGestureController::endSwipeGesture().
  • Add a new SnapshotRemovalTracker::Event::SwipeAnimationEnd event and wait for this event before taking away the snapshot. This makes sure we do not take away the swipe snapshot until the swipe animation is actually over (now that we start the navigation during the animation, instead of after).
  • To make sure that layer being swiped away stays the same until the end of the animation, I added a new SwipeAnimation reason for freezing the layer tree. At the beginning of the animation, the UIProcess sends a FreezeLayerTreeDueToSwipeAnimation IPC to the WebProcess to add this layer tree freeze reason. At the end of the animation, the UIProcess sends the UnfreezeLayerTreeDueToSwipeAnimation IPC to remove this freeze reason. Without this change, the layer being swiped away would sometimes start showing the destination site being loaded before the end of the animation. On cross-process navigation, not freezing the layer tree would cause the swipe animation to get interrupted when we have something to paint in the new process before the end of the swipe animation.
  • UIProcess/ProvisionalPageProxy.cpp:

(WebKit::ProvisionalPageProxy::initializeWebPage):

  • UIProcess/ViewGestureController.cpp:

(WebKit::ViewGestureController::SnapshotRemovalTracker::eventsDescription):
(WebKit::ViewGestureController::willEndSwipeGesture):
(WebKit::ViewGestureController::endSwipeGesture):

  • UIProcess/ViewGestureController.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::commitProvisionalPage):

  • UIProcess/WebPageProxy.h:

(WebKit::WebPageProxy::isLayerTreeFrozenDueToSwipeAnimation const):

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::freezeLayerTreeDueToSwipeAnimation):
(WebKit::WebPage::unfreezeLayerTreeDueToSwipeAnimation):

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:
Location:
trunk/Source/WebKit
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r253359 r253360  
     12019-12-10  Chris Dumez  <cdumez@apple.com>
     2
     3        [macOS] Issue load sooner on swipe back/forward navigation
     4        https://bugs.webkit.org/show_bug.cgi?id=205087
     5
     6        Reviewed by Tim Horton.
     7
     8        Issue load sooner on swipe back/forward navigation on macOS. We were waiting until the end of
     9        the swipe animation to issue the load. We now issue the load as soon as the user lifts the finger
     10        off the screen and thus commits to navigating. This results in improved perceived performance
     11        when swiping back/forward to navigate.
     12
     13        This patch does not take care of iOS because the ViewGestureController logic is different on that
     14        platform. There is no reason we shouldn't be able to do the same optimization on iOS too though.
     15
     16        To achieve the behavior change on macOS, the following was done:
     17        - Issue the load in ViewGestureController::willEndSwipeGesture() instead of
     18          ViewGestureController::endSwipeGesture().
     19        - Add a new SnapshotRemovalTracker::Event::SwipeAnimationEnd event and wait for this event before
     20          taking away the snapshot. This makes sure we do not take away the swipe snapshot until the swipe
     21          animation is actually over (now that we start the navigation during the animation, instead of
     22          after).
     23        - To make sure that layer being swiped away stays the same until the end of the animation, I added
     24          a new SwipeAnimation reason for freezing the layer tree. At the beginning of the animation, the
     25          UIProcess sends a FreezeLayerTreeDueToSwipeAnimation IPC to the WebProcess to add this layer tree
     26          freeze reason. At the end of the animation, the UIProcess sends the UnfreezeLayerTreeDueToSwipeAnimation
     27          IPC to remove this freeze reason. Without this change, the layer being swiped away would sometimes
     28          start showing the destination site being loaded before the end of the animation. On cross-process
     29          navigation, not freezing the layer tree would cause the swipe animation to get interrupted when
     30          we have something to paint in the new process before the end of the swipe animation.
     31
     32        * UIProcess/ProvisionalPageProxy.cpp:
     33        (WebKit::ProvisionalPageProxy::initializeWebPage):
     34        * UIProcess/ViewGestureController.cpp:
     35        (WebKit::ViewGestureController::SnapshotRemovalTracker::eventsDescription):
     36        (WebKit::ViewGestureController::willEndSwipeGesture):
     37        (WebKit::ViewGestureController::endSwipeGesture):
     38        * UIProcess/ViewGestureController.h:
     39        * UIProcess/WebPageProxy.cpp:
     40        (WebKit::WebPageProxy::commitProvisionalPage):
     41        * UIProcess/WebPageProxy.h:
     42        (WebKit::WebPageProxy::isLayerTreeFrozenDueToSwipeAnimation const):
     43        * WebProcess/WebPage/WebPage.cpp:
     44        (WebKit::WebPage::freezeLayerTreeDueToSwipeAnimation):
     45        (WebKit::WebPage::unfreezeLayerTreeDueToSwipeAnimation):
     46        * WebProcess/WebPage/WebPage.h:
     47        * WebProcess/WebPage/WebPage.messages.in:
     48
    1492019-12-10  Fujii Hironori  <Hironori.Fujii@sony.com>
    250
  • trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp

    r253346 r253360  
    144144    m_process->send(Messages::WebProcess::CreateWebPage(m_webPageID, parameters), 0);
    145145    m_process->addVisitedLinkStoreUser(m_page.visitedLinkStore(), m_page.identifier());
     146
     147    if (m_page.isLayerTreeFrozenDueToSwipeAnimation())
     148        send(Messages::WebPage::FreezeLayerTreeDueToSwipeAnimation());
    146149}
    147150
  • trunk/Source/WebKit/UIProcess/ViewGestureController.cpp

    r253304 r253360  
    279279        description.append("ScrollPositionRestoration ");
    280280
     281    if (event & ViewGestureController::SnapshotRemovalTracker::SwipeAnimationEnd)
     282        description.append("SwipeAnimationEnd ");
     283
    281284    return description.toString();
    282285}
     
    554557{
    555558    m_webPageProxy.navigationGestureWillEnd(!cancelled, targetItem);
     559
     560    if (cancelled)
     561        return;
     562
     563    uint64_t renderTreeSize = 0;
     564    if (ViewSnapshot* snapshot = targetItem.snapshot())
     565        renderTreeSize = snapshot->renderTreeSize();
     566    auto renderTreeSizeThreshold = renderTreeSize * swipeSnapshotRemovalRenderTreeSizeTargetFraction;
     567
     568    m_webPageProxy.goToBackForwardItem(targetItem);
     569
     570    auto* currentItem = m_webPageProxy.backForwardList().currentItem();
     571    // The main frame will not be navigated so hide the snapshot right away.
     572    if (currentItem && currentItem->itemIsClone(targetItem)) {
     573        removeSwipeSnapshot();
     574        return;
     575    }
     576
     577    SnapshotRemovalTracker::Events desiredEvents = SnapshotRemovalTracker::VisuallyNonEmptyLayout
     578        | SnapshotRemovalTracker::MainFrameLoad
     579        | SnapshotRemovalTracker::SubresourceLoads
     580        | SnapshotRemovalTracker::ScrollPositionRestoration
     581        | SnapshotRemovalTracker::SwipeAnimationEnd;
     582
     583    if (renderTreeSizeThreshold) {
     584        desiredEvents |= SnapshotRemovalTracker::RenderTreeSizeThreshold;
     585        m_snapshotRemovalTracker.setRenderTreeSizeThreshold(renderTreeSizeThreshold);
     586    }
     587
     588    m_snapshotRemovalTracker.start(desiredEvents, [this] { this->forceRepaintIfNeeded(); });
     589
     590    // FIXME: Like on iOS, we should ensure that even if one of the timeouts fires,
     591    // we never show the old page content, instead showing the snapshot background color.
     592
     593    if (ViewSnapshot* snapshot = targetItem.snapshot())
     594        m_backgroundColorForCurrentSnapshot = snapshot->backgroundColor();
    556595}
    557596
     
    571610    }
    572611
    573     uint64_t renderTreeSize = 0;
    574     if (ViewSnapshot* snapshot = targetItem->snapshot())
    575         renderTreeSize = snapshot->renderTreeSize();
    576     auto renderTreeSizeThreshold = renderTreeSize * swipeSnapshotRemovalRenderTreeSizeTargetFraction;
    577 
    578612    m_webPageProxy.navigationGestureDidEnd(true, *targetItem);
    579     m_webPageProxy.goToBackForwardItem(*targetItem);
    580 
    581     auto* currentItem = m_webPageProxy.backForwardList().currentItem();
    582     // The main frame will not be navigated so hide the snapshot right away.
    583     if (currentItem && currentItem->itemIsClone(*targetItem)) {
    584         removeSwipeSnapshot();
    585         return;
    586     }
    587 
    588     SnapshotRemovalTracker::Events desiredEvents = SnapshotRemovalTracker::VisuallyNonEmptyLayout
    589         | SnapshotRemovalTracker::MainFrameLoad
    590         | SnapshotRemovalTracker::SubresourceLoads
    591         | SnapshotRemovalTracker::ScrollPositionRestoration;
    592 
    593     if (renderTreeSizeThreshold) {
    594         desiredEvents |= SnapshotRemovalTracker::RenderTreeSizeThreshold;
    595         m_snapshotRemovalTracker.setRenderTreeSizeThreshold(renderTreeSizeThreshold);
    596     }
    597 
    598     m_snapshotRemovalTracker.start(desiredEvents, [this] { this->forceRepaintIfNeeded(); });
    599 
    600     // FIXME: Like on iOS, we should ensure that even if one of the timeouts fires,
    601     // we never show the old page content, instead showing the snapshot background color.
    602 
    603     if (ViewSnapshot* snapshot = targetItem->snapshot())
    604         m_backgroundColorForCurrentSnapshot = snapshot->backgroundColor();
     613
     614    m_snapshotRemovalTracker.eventOccurred(SnapshotRemovalTracker::SwipeAnimationEnd);
    605615}
    606616
  • trunk/Source/WebKit/UIProcess/ViewGestureController.h

    r252155 r253360  
    195195            MainFrameLoad = 1 << 3,
    196196            SubresourceLoads = 1 << 4,
    197             ScrollPositionRestoration = 1 << 5
     197            ScrollPositionRestoration = 1 << 5,
     198            SwipeAnimationEnd = 1 << 6
    198199        };
    199200        typedef uint8_t Events;
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r253346 r253360  
    31233123#endif
    31243124
     3125    if (m_isLayerTreeFrozenDueToSwipeAnimation)
     3126        send(Messages::WebPage::UnfreezeLayerTreeDueToSwipeAnimation());
     3127
    31253128    processDidTerminate(ProcessTerminationReason::NavigationSwap);
    31263129
     
    84188421{
    84198422    PageClientProtector protector(pageClient());
     8423    if (willNavigate) {
     8424        m_isLayerTreeFrozenDueToSwipeAnimation = true;
     8425        send(Messages::WebPage::FreezeLayerTreeDueToSwipeAnimation());
     8426    }
    84208427
    84218428    pageClient().navigationGestureWillEnd(willNavigate, item);
     
    84318438
    84328439    m_navigationClient->didEndNavigationGesture(*this, willNavigate, item);
     8440
     8441    if (m_isLayerTreeFrozenDueToSwipeAnimation) {
     8442        m_isLayerTreeFrozenDueToSwipeAnimation = false;
     8443        send(Messages::WebPage::UnfreezeLayerTreeDueToSwipeAnimation());
     8444    }
    84338445}
    84348446
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r253346 r253360  
    12911291#endif
    12921292
     1293    bool isLayerTreeFrozenDueToSwipeAnimation() const { return m_isLayerTreeFrozenDueToSwipeAnimation; }
     1294
    12931295    WebCore::IntSize minimumSizeForAutoLayout() const { return m_minimumSizeForAutoLayout; }
    12941296    void setMinimumSizeForAutoLayout(const WebCore::IntSize&);
     
    26402642#endif
    26412643    bool m_isQuotaIncreaseDenied { false };
     2644    bool m_isLayerTreeFrozenDueToSwipeAnimation { false };
    26422645   
    26432646    String m_overriddenMediaType;
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r253327 r253360  
    46664666#endif
    46674667
     4668void WebPage::freezeLayerTreeDueToSwipeAnimation()
     4669{
     4670    freezeLayerTree(LayerTreeFreezeReason::SwipeAnimation);
     4671}
     4672
     4673void WebPage::unfreezeLayerTreeDueToSwipeAnimation()
     4674{
     4675    unfreezeLayerTree(LayerTreeFreezeReason::SwipeAnimation);
     4676}
     4677
    46684678void WebPage::beginPrinting(FrameIdentifier frameID, const PrintInfo& printInfo)
    46694679{
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r253267 r253360  
    730730        Printing                = 1 << 4,
    731731        ProcessSwap             = 1 << 5,
     732        SwipeAnimation          = 1 << 6,
    732733    };
    733734    void freezeLayerTree(LayerTreeFreezeReason);
     
    736737    void markLayersVolatile(Function<void(bool)>&& completionHandler = { });
    737738    void cancelMarkLayersVolatile();
     739
     740    void freezeLayerTreeDueToSwipeAnimation();
     741    void unfreezeLayerTreeDueToSwipeAnimation();
    738742
    739743    NotificationPermissionRequestManager* notificationPermissionRequestManager();
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in

    r253187 r253360  
    381381    DidReceiveNotificationPermissionDecision(uint64_t notificationID, bool allowed)
    382382
     383    FreezeLayerTreeDueToSwipeAnimation()
     384    UnfreezeLayerTreeDueToSwipeAnimation()
     385
    383386    # Printing.
    384387    BeginPrinting(WebCore::FrameIdentifier frameID, struct WebKit::PrintInfo printInfo)
Note: See TracChangeset for help on using the changeset viewer.