Skip to content

Commit

Permalink
Refactor caret animation handling logic when scrolling/zooming
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=249511
rdar://102938633

Reviewed by Simon Fraser.

* Source/WebCore/loader/EmptyClients.cpp:
* Source/WebCore/page/EditorClient.h:
* Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp:
(WebCore::AsyncScrollingCoordinator::AsyncScrollingCoordinator):
(WebCore::AsyncScrollingCoordinator::hysterisisTimerFired):
(WebCore::AsyncScrollingCoordinator::applyScrollPositionUpdate):
(WebCore::AsyncScrollingCoordinator::animatedScrollWillStartForNode):
(WebCore::AsyncScrollingCoordinator::animatedScrollDidEndForNode):
(WebCore::AsyncScrollingCoordinator::wheelEventScrollWillStartForNode):
(WebCore::AsyncScrollingCoordinator::wheelEventScrollDidEndForNode):
* Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h:
* Source/WebCore/page/scrolling/ScrollingCoordinatorTypes.h:
* Source/WebCore/page/scrolling/ScrollingTree.h:
(WebCore::ScrollingTree::scrollingTreeNodeWillStartAnimatedScroll):
(WebCore::ScrollingTree::scrollingTreeNodeWillStartWheelEventScroll):
(WebCore::ScrollingTree::scrollingTreeNodeDidStopWheelEventScroll):
* Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp:
(WebCore::ScrollingTreeScrollingNode::willStartAnimatedScroll):
(WebCore::ScrollingTreeScrollingNode::willStartWheelEventScroll):
(WebCore::ScrollingTreeScrollingNode::didStopWheelEventScroll):
* Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h:
* Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp:
(WebCore::ThreadedScrollingTree::scrollingTreeNodeScrollUpdated):
(WebCore::ThreadedScrollingTree::scrollingTreeNodeWillStartAnimatedScroll):
(WebCore::ThreadedScrollingTree::scrollingTreeNodeDidStopAnimatedScroll):
(WebCore::ThreadedScrollingTree::scrollingTreeNodeWillStartWheelEventScroll):
(WebCore::ThreadedScrollingTree::scrollingTreeNodeDidStopWheelEventScroll):
* Source/WebCore/page/scrolling/ThreadedScrollingTree.h:
* Source/WebCore/page/scrolling/ThreadedScrollingTreeScrollingNodeDelegate.cpp:
(WebCore::ThreadedScrollingTreeScrollingNodeDelegate::willStartAnimatedScroll):
(WebCore::ThreadedScrollingTreeScrollingNodeDelegate::willStartWheelEventScroll):
(WebCore::ThreadedScrollingTreeScrollingNodeDelegate::didStopWheelEventScroll):
* Source/WebCore/page/scrolling/ThreadedScrollingTreeScrollingNodeDelegate.h:
* Source/WebCore/platform/ScrollingEffectsController.cpp:
(WebCore::ScrollingEffectsController::scrollAnimationWillStart):
* Source/WebCore/platform/ScrollingEffectsController.h:
(WebCore::ScrollingEffectsControllerClient::willStartWheelEventScroll):
(WebCore::ScrollingEffectsControllerClient::didStopWheelEventScroll):
* Source/WebCore/platform/mac/ScrollingEffectsController.mm:
(WebCore::ScrollingEffectsController::handleWheelEvent):
* Source/WebKit/UIProcess/PageClient.h:
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::setCaretDecorationVisibility):
* Source/WebKit/UIProcess/WebPageProxy.h:
* Source/WebKit/UIProcess/WebPageProxy.messages.in:
* Source/WebKit/UIProcess/mac/PageClientImplMac.h:
* Source/WebKit/UIProcess/mac/PageClientImplMac.mm:
(WebKit::PageClientImpl::setCaretDecorationVisibility):
* Source/WebKit/UIProcess/mac/ViewGestureControllerMac.mm:
(WebKit::ViewGestureController::handleMagnificationGestureEvent):
* Source/WebKit/UIProcess/mac/WebViewImpl.h:
* Source/WebKit/UIProcess/mac/WebViewImpl.mm:
(WebKit::WebViewImpl::setCaretDecorationVisibility):
* Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.cpp:
(WebKit::WebEditorClient::setCaretDecorationVisibility):
* Source/WebKit/WebProcess/WebCoreSupport/WebEditorClient.h:
* Source/WebKitLegacy/mac/WebCoreSupport/WebEditorClient.h:

Canonical link: https://commits.webkit.org/258201@main
  • Loading branch information
rr-codes committed Dec 21, 2022
1 parent 94b13da commit f7697e1
Show file tree
Hide file tree
Showing 30 changed files with 238 additions and 6 deletions.
2 changes: 2 additions & 0 deletions Source/WebCore/loader/EmptyClients.cpp
Expand Up @@ -333,6 +333,8 @@ class EmptyEditorClient final : public EditorClient {
void uppercaseWord() final { }
void lowercaseWord() final { }
void capitalizeWord() final { }

void setCaretDecorationVisibility(bool) final { }
#endif

#if USE(AUTOMATIC_TEXT_REPLACEMENT)
Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/page/EditorClient.h
Expand Up @@ -154,6 +154,8 @@ class EditorClient {
virtual void uppercaseWord() = 0;
virtual void lowercaseWord() = 0;
virtual void capitalizeWord() = 0;

virtual void setCaretDecorationVisibility(bool) = 0;
#endif

#if USE(AUTOMATIC_TEXT_REPLACEMENT)
Expand Down
14 changes: 14 additions & 0 deletions Source/WebCore/page/Page.cpp
Expand Up @@ -4126,4 +4126,18 @@ String Page::sanitizeLookalikeCharacters(const String& urlString) const
return urlString;
}

void Page::willBeginScrolling()
{
#if USE(APPKIT)
editorClient().setCaretDecorationVisibility(false);
#endif
}

void Page::didFinishScrolling()
{
#if USE(APPKIT)
editorClient().setCaretDecorationVisibility(true);
#endif
}

} // namespace WebCore
3 changes: 3 additions & 0 deletions Source/WebCore/page/Page.h
Expand Up @@ -998,6 +998,9 @@ class Page : public Supplementable<Page>, public CanMakeWeakPtr<Page> {

BadgeClient& badgeClient() { return m_badgeClient.get(); }

void willBeginScrolling();
void didFinishScrolling();

private:
struct Navigation {
RegistrableDomain domain;
Expand Down
73 changes: 71 additions & 2 deletions Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp
Expand Up @@ -51,6 +51,7 @@
#include "ScrollingStateTree.h"
#include "Settings.h"
#include "WheelEventTestMonitor.h"
#include "pal/HysteresisActivity.h"
#include <wtf/ProcessID.h>
#include <wtf/text/TextStream.h>

Expand All @@ -59,9 +60,16 @@ namespace WebCore {
AsyncScrollingCoordinator::AsyncScrollingCoordinator(Page* page)
: ScrollingCoordinator(page)
, m_scrollingStateTree(makeUnique<ScrollingStateTree>(this))
, m_hysterisisActivity([this](auto state) { hysterisisTimerFired(state); }, 200_ms)
{
}

void AsyncScrollingCoordinator::hysterisisTimerFired(PAL::HysteresisState state)
{
if (state == PAL::HysteresisState::Stopped)
m_page->didFinishScrolling();
}

AsyncScrollingCoordinator::~AsyncScrollingCoordinator() = default;

void AsyncScrollingCoordinator::scrollingStateTreePropertiesChanged()
Expand Down Expand Up @@ -456,12 +464,42 @@ void AsyncScrollingCoordinator::applyScrollUpdate(ScrollUpdate&& update, ScrollT

void AsyncScrollingCoordinator::applyScrollPositionUpdate(ScrollUpdate&& update, ScrollType scrollType)
{
if (update.updateType == ScrollUpdateType::AnimatedScrollDidEnd) {
switch (update.updateType) {
case ScrollUpdateType::AnimatedScrollWillStart:
animatedScrollWillStartForNode(update.nodeID);
return;

case ScrollUpdateType::AnimatedScrollDidEnd:
animatedScrollDidEndForNode(update.nodeID);
return;

case ScrollUpdateType::WheelEventScrollWillStart:
wheelEventScrollWillStartForNode(update.nodeID);
return;

case ScrollUpdateType::WheelEventScrollDidEnd:
wheelEventScrollDidEndForNode(update.nodeID);
return;

case ScrollUpdateType::PositionUpdate:
updateScrollPositionAfterAsyncScroll(update.nodeID, update.scrollPosition, update.layoutViewportOrigin, update.updateLayerPositionAction, scrollType);
return;
}
}

updateScrollPositionAfterAsyncScroll(update.nodeID, update.scrollPosition, update.layoutViewportOrigin, update.updateLayerPositionAction, scrollType);
void AsyncScrollingCoordinator::animatedScrollWillStartForNode(ScrollingNodeID scrollingNodeID)
{
ASSERT(isMainThread());

if (!m_page)
return;

auto* frameView = frameViewForScrollingNode(scrollingNodeID);
if (!frameView)
return;

m_hysterisisActivity.start();
m_page->willBeginScrolling();
}

void AsyncScrollingCoordinator::animatedScrollDidEndForNode(ScrollingNodeID scrollingNodeID)
Expand All @@ -477,6 +515,8 @@ void AsyncScrollingCoordinator::animatedScrollDidEndForNode(ScrollingNodeID scro

LOG_WITH_STREAM(Scrolling, stream << "AsyncScrollingCoordinator::animatedScrollDidEndForNode node " << scrollingNodeID);

m_hysterisisActivity.stop();

if (scrollingNodeID == frameView->scrollingNodeID()) {
frameView->setScrollAnimationStatus(ScrollAnimationStatus::NotAnimating);
return;
Expand All @@ -488,6 +528,35 @@ void AsyncScrollingCoordinator::animatedScrollDidEndForNode(ScrollingNodeID scro
}
}

void AsyncScrollingCoordinator::wheelEventScrollWillStartForNode(ScrollingNodeID scrollingNodeID)
{
ASSERT(isMainThread());

if (!m_page)
return;

auto* frameView = frameViewForScrollingNode(scrollingNodeID);
if (!frameView)
return;

m_hysterisisActivity.start();
m_page->willBeginScrolling();
}

void AsyncScrollingCoordinator::wheelEventScrollDidEndForNode(ScrollingNodeID scrollingNodeID)
{
ASSERT(isMainThread());

if (!m_page)
return;

auto* frameView = frameViewForScrollingNode(scrollingNodeID);
if (!frameView)
return;

m_hysterisisActivity.stop();
}

void AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll(ScrollingNodeID scrollingNodeID, const FloatPoint& scrollPosition, std::optional<FloatPoint> layoutViewportOrigin, ScrollingLayerPositionAction scrollingLayerPositionAction, ScrollType scrollType)
{
ASSERT(isMainThread());
Expand Down
8 changes: 8 additions & 0 deletions Source/WebCore/page/scrolling/AsyncScrollingCoordinator.h
Expand Up @@ -25,6 +25,7 @@

#pragma once

#include "pal/HysteresisActivity.h"
#if ENABLE(ASYNC_SCROLLING)

#include "ScrollingCoordinator.h"
Expand Down Expand Up @@ -160,14 +161,21 @@ class AsyncScrollingCoordinator : public ScrollingCoordinator {

void applyScrollPositionUpdate(ScrollUpdate&&, ScrollType);
void updateScrollPositionAfterAsyncScroll(ScrollingNodeID, const FloatPoint&, std::optional<FloatPoint> layoutViewportOrigin, ScrollingLayerPositionAction, ScrollType);
void animatedScrollWillStartForNode(ScrollingNodeID);
void animatedScrollDidEndForNode(ScrollingNodeID);
void wheelEventScrollWillStartForNode(ScrollingNodeID);
void wheelEventScrollDidEndForNode(ScrollingNodeID);

FrameView* frameViewForScrollingNode(ScrollingNodeID) const;

void hysterisisTimerFired(PAL::HysteresisState);

std::unique_ptr<ScrollingStateTree> m_scrollingStateTree;
RefPtr<ScrollingTree> m_scrollingTree;

bool m_eventTrackingRegionsDirty { false };

PAL::HysteresisActivity m_hysterisisActivity;
};

#if ENABLE(SCROLLING_THREAD)
Expand Down
12 changes: 12 additions & 0 deletions Source/WebCore/page/scrolling/ScrollingCoordinatorTypes.cpp
Expand Up @@ -136,4 +136,16 @@ TextStream& operator<<(TextStream& ts, WheelEventProcessingSteps steps)
return ts;
}

TextStream& operator<<(TextStream& ts, ScrollUpdateType type)
{
switch (type) {
case ScrollUpdateType::PositionUpdate: ts << "position update"; break;
case ScrollUpdateType::AnimatedScrollWillStart: ts << "animated scroll will start"; break;
case ScrollUpdateType::AnimatedScrollDidEnd: ts << "animated scroll did end"; break;
case ScrollUpdateType::WheelEventScrollWillStart: ts << "wheel event scroll will start"; break;
case ScrollUpdateType::WheelEventScrollDidEnd: ts << "wheel event scroll did end"; break;
}
return ts;
}

} // namespace WebCore
6 changes: 5 additions & 1 deletion Source/WebCore/page/scrolling/ScrollingCoordinatorTypes.h
Expand Up @@ -151,7 +151,10 @@ struct RequestedKeyboardScrollData {

enum class ScrollUpdateType : uint8_t {
PositionUpdate,
AnimatedScrollDidEnd
AnimatedScrollWillStart,
AnimatedScrollDidEnd,
WheelEventScrollWillStart,
WheelEventScrollDidEnd,
};

struct ScrollUpdate {
Expand Down Expand Up @@ -205,6 +208,7 @@ WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollingLayerPosit
WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollableAreaParameters);
WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ViewportRectStability);
WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, WheelEventProcessingSteps);
WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, ScrollUpdateType);

} // namespace WebCore

Expand Down
3 changes: 3 additions & 0 deletions Source/WebCore/page/scrolling/ScrollingTree.h
Expand Up @@ -117,7 +117,10 @@ class ScrollingTree : public ThreadSafeRefCounted<ScrollingTree> {
// Called after a scrolling tree node has handled a scroll and updated its layers.
// Updates FrameView/RenderLayer scrolling state and GraphicsLayers.
virtual void scrollingTreeNodeDidScroll(ScrollingTreeScrollingNode&, ScrollingLayerPositionAction = ScrollingLayerPositionAction::Sync) = 0;
virtual void scrollingTreeNodeWillStartAnimatedScroll(ScrollingTreeScrollingNode&) { }
virtual void scrollingTreeNodeDidStopAnimatedScroll(ScrollingTreeScrollingNode&) { }
virtual void scrollingTreeNodeWillStartWheelEventScroll(ScrollingTreeScrollingNode&) { }
virtual void scrollingTreeNodeDidStopWheelEventScroll(ScrollingTreeScrollingNode&) { }

// Called for requested scroll position updates. Returns true if handled.
virtual bool scrollingTreeNodeRequestsScroll(ScrollingNodeID, const RequestedScrollData&) { return false; }
Expand Down
15 changes: 15 additions & 0 deletions Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp
Expand Up @@ -236,12 +236,27 @@ void ScrollingTreeScrollingNode::setScrollSnapInProgress(bool isSnapping)
scrollingTree().setNodeScrollSnapInProgress(scrollingNodeID(), isSnapping);
}

void ScrollingTreeScrollingNode::willStartAnimatedScroll()
{
scrollingTree().scrollingTreeNodeWillStartAnimatedScroll(*this);
}

void ScrollingTreeScrollingNode::didStopAnimatedScroll()
{
LOG_WITH_STREAM(Scrolling, stream << "ScrollingTreeScrollingNode " << scrollingNodeID() << " didStopAnimatedScroll");
scrollingTree().scrollingTreeNodeDidStopAnimatedScroll(*this);
}

void ScrollingTreeScrollingNode::willStartWheelEventScroll()
{
scrollingTree().scrollingTreeNodeWillStartWheelEventScroll(*this);
}

void ScrollingTreeScrollingNode::didStopWheelEventScroll()
{
scrollingTree().scrollingTreeNodeDidStopWheelEventScroll(*this);
}

bool ScrollingTreeScrollingNode::startAnimatedScrollToPosition(FloatPoint destinationPosition)
{
return m_delegate ? m_delegate->startAnimatedScrollToPosition(destinationPosition) : false;
Expand Down
3 changes: 3 additions & 0 deletions Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h
Expand Up @@ -141,7 +141,10 @@ class WEBCORE_EXPORT ScrollingTreeScrollingNode : public ScrollingTreeNode {
virtual bool startAnimatedScrollToPosition(FloatPoint);
virtual void stopAnimatedScroll();

void willStartAnimatedScroll();
void didStopAnimatedScroll();
void willStartWheelEventScroll();
void didStopWheelEventScroll();

void setScrollAnimationInProgress(bool);

Expand Down
26 changes: 23 additions & 3 deletions Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp
Expand Up @@ -259,14 +259,14 @@ void ThreadedScrollingTree::scrollingTreeNodeDidScroll(ScrollingTreeScrollingNod
});
}

void ThreadedScrollingTree::scrollingTreeNodeDidStopAnimatedScroll(ScrollingTreeScrollingNode& node)
void ThreadedScrollingTree::scrollingTreeNodeScrollUpdated(ScrollingTreeScrollingNode& node, const ScrollUpdateType& scrollUpdateType)
{
if (!m_scrollingCoordinator)
return;

LOG_WITH_STREAM(Scrolling, stream << "ThreadedScrollingTree::scrollingTreeNodeDidStopAnimatedScroll " << node.scrollingNodeID());
LOG_WITH_STREAM(Scrolling, stream << "ThreadedScrollingTree::scrollingTreeNodeScrollUpdated " << node.scrollingNodeID() << " update type " << scrollUpdateType);

auto scrollUpdate = ScrollUpdate { node.scrollingNodeID(), { }, { }, ScrollUpdateType::AnimatedScrollDidEnd };
auto scrollUpdate = ScrollUpdate { node.scrollingNodeID(), { }, { }, scrollUpdateType };

if (RunLoop::isMain()) {
m_scrollingCoordinator->applyScrollUpdate(WTFMove(scrollUpdate));
Expand All @@ -281,6 +281,26 @@ void ThreadedScrollingTree::scrollingTreeNodeDidStopAnimatedScroll(ScrollingTree
});
}

void ThreadedScrollingTree::scrollingTreeNodeWillStartAnimatedScroll(ScrollingTreeScrollingNode& node)
{
scrollingTreeNodeScrollUpdated(node, ScrollUpdateType::AnimatedScrollWillStart);
}

void ThreadedScrollingTree::scrollingTreeNodeDidStopAnimatedScroll(ScrollingTreeScrollingNode& node)
{
scrollingTreeNodeScrollUpdated(node, ScrollUpdateType::AnimatedScrollDidEnd);
}

void ThreadedScrollingTree::scrollingTreeNodeWillStartWheelEventScroll(ScrollingTreeScrollingNode& node)
{
scrollingTreeNodeScrollUpdated(node, ScrollUpdateType::WheelEventScrollWillStart);
}

void ThreadedScrollingTree::scrollingTreeNodeDidStopWheelEventScroll(ScrollingTreeScrollingNode& node)
{
scrollingTreeNodeScrollUpdated(node, ScrollUpdateType::WheelEventScrollDidEnd);
}

void ThreadedScrollingTree::reportSynchronousScrollingReasonsChanged(MonotonicTime timestamp, OptionSet<SynchronousScrollingReason> reasons)
{
auto scrollingCoordinator = m_scrollingCoordinator;
Expand Down
5 changes: 5 additions & 0 deletions Source/WebCore/page/scrolling/ThreadedScrollingTree.h
Expand Up @@ -71,7 +71,10 @@ class ThreadedScrollingTree : public ScrollingTree {
explicit ThreadedScrollingTree(AsyncScrollingCoordinator&);

void scrollingTreeNodeDidScroll(ScrollingTreeScrollingNode&, ScrollingLayerPositionAction = ScrollingLayerPositionAction::Sync) override;
void scrollingTreeNodeWillStartAnimatedScroll(ScrollingTreeScrollingNode&) override;
void scrollingTreeNodeDidStopAnimatedScroll(ScrollingTreeScrollingNode&) override;
void scrollingTreeNodeWillStartWheelEventScroll(ScrollingTreeScrollingNode&) override;
void scrollingTreeNodeDidStopWheelEventScroll(ScrollingTreeScrollingNode&) override;
bool scrollingTreeNodeRequestsScroll(ScrollingNodeID, const RequestedScrollData&) override WTF_REQUIRES_LOCK(m_treeLock);

#if PLATFORM(MAC)
Expand Down Expand Up @@ -123,6 +126,8 @@ class ThreadedScrollingTree : public ScrollingTree {
void lockLayersForHitTesting() final WTF_ACQUIRES_LOCK(m_layerHitTestMutex);
void unlockLayersForHitTesting() final WTF_RELEASES_LOCK(m_layerHitTestMutex);

void scrollingTreeNodeScrollUpdated(ScrollingTreeScrollingNode&, const ScrollUpdateType&);

enum class SynchronizationState : uint8_t {
Idle,
WaitingForRenderingUpdate,
Expand Down
Expand Up @@ -146,11 +146,26 @@ float ThreadedScrollingTreeScrollingNodeDelegate::pageScaleFactor() const
return 1;
}

void ThreadedScrollingTreeScrollingNodeDelegate::willStartAnimatedScroll()
{
scrollingNode().willStartAnimatedScroll();
}

void ThreadedScrollingTreeScrollingNodeDelegate::didStopAnimatedScroll()
{
scrollingNode().didStopAnimatedScroll();
}

void ThreadedScrollingTreeScrollingNodeDelegate::willStartWheelEventScroll()
{
scrollingNode().willStartWheelEventScroll();
}

void ThreadedScrollingTreeScrollingNodeDelegate::didStopWheelEventScroll()
{
scrollingNode().didStopWheelEventScroll();
}

void ThreadedScrollingTreeScrollingNodeDelegate::willStartScrollSnapAnimation()
{
scrollingNode().setScrollSnapInProgress(true);
Expand Down
Expand Up @@ -72,7 +72,10 @@ class ThreadedScrollingTreeScrollingNodeDelegate : public ScrollingTreeScrolling
FloatPoint scrollOffset() const override;
float pageScaleFactor() const override;

void willStartAnimatedScroll() override;
void didStopAnimatedScroll() override;
void willStartWheelEventScroll() override;
void didStopWheelEventScroll() override;
void willStartScrollSnapAnimation() override;
void didStopScrollSnapAnimation() override;

Expand Down
2 changes: 2 additions & 0 deletions Source/WebCore/platform/ScrollingEffectsController.cpp
Expand Up @@ -518,6 +518,8 @@ void ScrollingEffectsController::scrollAnimationWillStart(ScrollAnimation& anima
UNUSED_PARAM(animation);
#endif

m_client.willStartAnimatedScroll();

if (is<ScrollAnimationKeyboard>(animation)) {
willBeginKeyboardScrolling();
startDeferringWheelEventTestCompletion(WheelEventTestMonitor::ScrollAnimationInProgress);
Expand Down

0 comments on commit f7697e1

Please sign in to comment.