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

Changeset 280492 in webkit


Ignore:
Timestamp:
Jul 30, 2021, 1:26:51 PM (5 years ago)
Author:
commit-queue@webkit.org
Message:

Add key-driven smooth scrolling to macOS
https://bugs.webkit.org/show_bug.cgi?id=228009

Patch by Dana Estra <destra@apple.com> on 2021-07-30
Reviewed by Tim Horton.

Cause keyboard scroll event to trigger start of smooth scroll animation, using same physics implementation as iOS smooth scrolling.

No tests yet.

  • WebCore.xcodeproj/project.pbxproj:
  • dom/Node.cpp:

(WebCore::Node::defaultEventHandler):

  • page/EventHandler.cpp:

(WebCore::EventHandler::defaultKeyboardEventHandler):
(WebCore::EventHandler::scrollDistance):
(WebCore::EventHandler::stopKeyboardScrolling):
(WebCore::EventHandler::startKeyboardScrolling):

  • platform/KeyboardScrollingAnimator.cpp: Added.
  • platform/KeyboardScrollingAnimator.h: Added.
  • platform/ScrollAnimator.cpp:

(WebCore::ScrollAnimator::startAnimationCallback):

  • platform/ScrollAnimator.h:
  • platform/ScrollController.cpp:

(WebCore::ScrollController::animationCallback):
(WebCore::ScrollController::startOrStopAnimationCallbacks):
(WebCore::ScrollController::beginKeyboardScrolling):
(WebCore::ScrollController::stopKeyboardScrolling):
(WebCore::ScrollController::setIsAnimatingKeyboardScrolling):
(WebCore::ScrollController::updateKeyboardScrollingAnimatingState):

  • platform/ScrollController.h:

(WebCore::ScrollControllerClient::updateKeyboardScrollPosition):

Location:
trunk/Source/WebCore
Files:
2 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r280491 r280492  
     12021-07-30  Dana Estra  <destra@apple.com>
     2
     3        Add key-driven smooth scrolling to macOS
     4        https://bugs.webkit.org/show_bug.cgi?id=228009
     5
     6        Reviewed by Tim Horton.
     7
     8        Cause keyboard scroll event to trigger start of smooth scroll animation, using same physics implementation as iOS smooth scrolling.
     9
     10        No tests yet.
     11
     12        * WebCore.xcodeproj/project.pbxproj:
     13        * dom/Node.cpp:
     14        (WebCore::Node::defaultEventHandler):
     15        * page/EventHandler.cpp:
     16        (WebCore::EventHandler::defaultKeyboardEventHandler):
     17        (WebCore::EventHandler::scrollDistance):
     18        (WebCore::EventHandler::stopKeyboardScrolling):
     19        (WebCore::EventHandler::startKeyboardScrolling):
     20        * platform/KeyboardScrollingAnimator.cpp: Added.
     21        * platform/KeyboardScrollingAnimator.h: Added.
     22        * platform/ScrollAnimator.cpp:
     23        (WebCore::ScrollAnimator::startAnimationCallback):
     24        * platform/ScrollAnimator.h:
     25        * platform/ScrollController.cpp:
     26        (WebCore::ScrollController::animationCallback):
     27        (WebCore::ScrollController::startOrStopAnimationCallbacks):
     28        (WebCore::ScrollController::beginKeyboardScrolling):
     29        (WebCore::ScrollController::stopKeyboardScrolling):
     30        (WebCore::ScrollController::setIsAnimatingKeyboardScrolling):
     31        (WebCore::ScrollController::updateKeyboardScrollingAnimatingState):
     32        * platform/ScrollController.h:
     33        (WebCore::ScrollControllerClient::updateKeyboardScrollPosition):
     34       
    1352021-07-30  Chris Dumez  <cdumez@apple.com>
    236
  • trunk/Source/WebCore/Sources.txt

    r280467 r280492  
    17461746platform/FileStream.cpp
    17471747platform/FrameRateMonitor.cpp
     1748platform/KeyboardScrollingAnimator.cpp
    17481749platform/LayoutUnit.cpp
    17491750platform/LegacySchemeRegistry.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r280467 r280492  
    674674                1FAFBF1915A5FA7400083A20 /* UTIUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FAFBF1615A5FA5200083A20 /* UTIUtilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
    675675                1FC40FBA1655CCB90040F29E /* SubimageCacheWithTimer.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FC40FB71655C5910040F29E /* SubimageCacheWithTimer.h */; };
     676                1FD992F826AA24F90088E596 /* KeyboardScrollingAnimator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FD992F626AA24F80088E596 /* KeyboardScrollingAnimator.h */; settings = {ATTRIBUTES = (Private, ); }; };
    676677                20D629271253690B00081543 /* InspectorInstrumentation.h in Headers */ = {isa = PBXBuildFile; fileRef = 20D629251253690B00081543 /* InspectorInstrumentation.h */; };
    677678                225A16B50D5C11E900090295 /* WebEventRegion.h in Headers */ = {isa = PBXBuildFile; fileRef = 225A16B30D5C11E900090295 /* WebEventRegion.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    70147015                1FC40FB71655C5910040F29E /* SubimageCacheWithTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubimageCacheWithTimer.h; sourceTree = "<group>"; };
    70157016                1FC40FB81655C5910040F29E /* SubimageCacheWithTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SubimageCacheWithTimer.cpp; sourceTree = "<group>"; };
     7017                1FD992F626AA24F80088E596 /* KeyboardScrollingAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeyboardScrollingAnimator.h; sourceTree = "<group>"; };
     7018                1FD992F926AA254D0088E596 /* KeyboardScrollingAnimator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeyboardScrollingAnimator.cpp; sourceTree = "<group>"; };
    70167019                20D629241253690B00081543 /* InspectorInstrumentation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorInstrumentation.cpp; sourceTree = "<group>"; };
    70177020                20D629251253690B00081543 /* InspectorInstrumentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorInstrumentation.h; sourceTree = "<group>"; };
     
    2755327556                                A8748BDF12CBF2DC001FBA41 /* HashTools.h */,
    2755427557                                BC3BC29B0E91AB0F00835588 /* HostWindow.h */,
     27558                                1FD992F926AA254D0088E596 /* KeyboardScrollingAnimator.cpp */,
     27559                                1FD992F626AA24F80088E596 /* KeyboardScrollingAnimator.h */,
    2755527560                                1AE00D57182DAC8D00087DD7 /* KeyedCoding.h */,
    2755627561                                E15FF7D418C9553800FE4C87 /* KeypressCommand.h */,
     
    3333433339                                85031B440A44EFC700F992E0 /* KeyboardEvent.h in Headers */,
    3333533340                                1F020AEF26780FCE0000809A /* KeyboardScroll.h in Headers */,
     33341                                1FD992F826AA24F90088E596 /* KeyboardScrollingAnimator.h in Headers */,
    3333633342                                1AE00D59182DAC8D00087DD7 /* KeyedCoding.h in Headers */,
    3333733343                                517A63C51B74318F00E7DCDC /* KeyedDecoderCF.h in Headers */,
  • trunk/Source/WebCore/dom/Node.cpp

    r280174 r280492  
    24332433        return;
    24342434    const AtomString& eventType = event.type();
    2435     if (eventType == eventNames().keydownEvent || eventType == eventNames().keypressEvent) {
     2435    if (eventType == eventNames().keydownEvent || eventType == eventNames().keypressEvent || eventType == eventNames().keyupEvent) {
    24362436        if (is<KeyboardEvent>(event)) {
    24372437            if (Frame* frame = document().frame())
  • trunk/Source/WebCore/page/EventHandler.cpp

    r280190 r280492  
    6969#include "InspectorInstrumentation.h"
    7070#include "KeyboardEvent.h"
    71 #include "KeyboardScroll.h"
     71#include "KeyboardScrollingAnimator.h"
    7272#include "Logging.h"
    7373#include "MouseEvent.h"
     
    38043804            defaultSpaceEventHandler(event);
    38053805    }
     3806    if (event.type() == eventNames().keyupEvent) {
     3807        m_frame.editor().handleKeyboardEvent(event);
     3808        if (event.defaultHandled())
     3809            return;
     3810        stopKeyboardScrolling();
     3811    }
    38063812}
    38073813
     
    41984204        return;
    41994205
    4200     bool defaultHandled = m_frame.settings().eventHandlerDrivenSmoothKeyboardScrollingEnabled() ? handleKeyboardScrolling(event) : view->logicalScroll(direction, ScrollByPage);
     4206    bool defaultHandled = m_frame.settings().eventHandlerDrivenSmoothKeyboardScrollingEnabled() ? startKeyboardScrolling(event) : view->logicalScroll(direction, ScrollByPage);
    42014207    if (defaultHandled)
    42024208        event.setDefaultHandled();
     
    42384244        return m_frame.view()->horizontalScrollbar();
    42394245    }();
    4240    
     4246
    42414247    switch (granularity) {
    42424248    case ScrollGranularity::ScrollByLine:
     
    42534259}
    42544260
    4255 bool EventHandler::handleKeyboardScrolling(KeyboardEvent& event)
     4261void EventHandler::stopKeyboardScrolling()
    42564262{
    42574263    Ref protectedFrame = m_frame;
    4258     // FIXME (bug 227459): This logic does not account for writing-mode.
    4259 
    4260     enum class Key : uint8_t { LeftArrow, RightArrow, UpArrow, DownArrow, Space };
    4261 
    4262     Key key;
    4263     if (event.keyIdentifier() == "Left")
    4264         key = Key::LeftArrow;
    4265     else if (event.keyIdentifier() == "Right")
    4266         key = Key::RightArrow;
    4267     else if (event.keyIdentifier() == "Up")
    4268         key = Key::UpArrow;
    4269     else if (event.keyIdentifier() == "Down")
    4270         key = Key::DownArrow;
    4271     else if (event.charCode() == ' ')
    4272         key = Key::Space;
    4273     else
    4274         return false;
    4275 
    4276     auto granularity = [&] {
    4277         switch (key) {
    4278         case Key::LeftArrow:
    4279         case Key::RightArrow:
    4280             return event.altKey() ? ScrollGranularity::ScrollByPage : ScrollGranularity::ScrollByLine;
    4281         case Key::UpArrow:
    4282         case Key::DownArrow:
    4283             if (event.metaKey())
    4284                 return ScrollGranularity::ScrollByDocument;
    4285             if (event.altKey())
    4286                 return ScrollGranularity::ScrollByPage;
    4287             return ScrollGranularity::ScrollByLine;
    4288         case Key::Space:
    4289             return ScrollGranularity::ScrollByPage;
    4290         };
    4291         RELEASE_ASSERT_NOT_REACHED();
    4292     }();
    4293 
    4294     auto direction = [&] {
    4295         switch (key) {
    4296         case Key::LeftArrow:
    4297             return ScrollDirection::ScrollLeft;
    4298         case Key::RightArrow:
    4299             return ScrollDirection::ScrollRight;
    4300         case Key::UpArrow:
    4301             return ScrollDirection::ScrollUp;
    4302         case Key::DownArrow:
    4303             return ScrollDirection::ScrollDown;
    4304         case Key::Space:
    4305             return event.shiftKey() ? ScrollDirection::ScrollUp : ScrollDirection::ScrollDown;
    4306         }
    4307         RELEASE_ASSERT_NOT_REACHED();
    4308     }();
    4309 
    4310     return EventHandler::scrollRecursively(direction, granularity, nullptr);
     4264    FrameView* view = m_frame.view();
     4265
     4266    KeyboardScrollingAnimator* animator = view->scrollAnimator().keyboardScrollingAnimator();
     4267
     4268    if (animator)
     4269        animator->handleKeyUpEvent();
     4270}
     4271
     4272bool EventHandler::startKeyboardScrolling(KeyboardEvent& event)
     4273{
     4274    Ref protectedFrame = m_frame;
     4275    FrameView* view = m_frame.view();
     4276
     4277    KeyboardScrollingAnimator* animator = view->scrollAnimator().keyboardScrollingAnimator();
     4278
     4279    if (animator)
     4280        return animator->beginKeyboardScrollGesture(event);
     4281
     4282    return false;
    43114283}
    43124284
     
    43174289    if (!isSpatialNavigationEnabled(&m_frame)) {
    43184290        if (m_frame.settings().eventHandlerDrivenSmoothKeyboardScrollingEnabled())
    4319             handleKeyboardScrolling(event);
     4291            startKeyboardScrolling(event);
    43204292        return;
    43214293    }
  • trunk/Source/WebCore/page/EventHandler.h

    r280190 r280492  
    378378
    379379    float scrollDistance(ScrollDirection, ScrollGranularity);
    380     bool handleKeyboardScrolling(KeyboardEvent&);
     380    bool startKeyboardScrolling(KeyboardEvent&);
     381    void stopKeyboardScrolling();
    381382
    382383#if ENABLE(DRAG_SUPPORT)
  • trunk/Source/WebCore/platform/ScrollAnimator.cpp

    r280171 r280492  
    3434
    3535#include "FloatPoint.h"
     36#include "KeyboardScrollingAnimator.h"
    3637#include "LayoutSize.h"
    3738#include "PlatformWheelEvent.h"
     
    6869            m_scrollableArea.setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
    6970        }))
     71    , m_keyboardScrollingAnimator(makeUnique<KeyboardScrollingAnimator>(*this, m_scrollController))
    7072{
    7173}
     
    333335    if (m_scrollControllerAnimationTimer.isActive())
    334336        return;
    335        
     337
    336338    m_scrollControllerAnimationTimer.startRepeating(1_s / 60.);
    337339}
  • trunk/Source/WebCore/platform/ScrollAnimator.h

    r280171 r280492  
    3535#include "PlatformWheelEvent.h"
    3636#include "ScrollController.h"
    37 #include "ScrollTypes.h"
    3837#include "Timer.h"
    3938#include "WheelEventTestMonitor.h"
     
    4443
    4544class FloatPoint;
     45class KeyboardScrollingAnimator;
    4646class PlatformTouchEvent;
    4747class ScrollAnimation;
     
    8181
    8282    virtual bool handleWheelEvent(const PlatformWheelEvent&);
     83
     84    KeyboardScrollingAnimator *keyboardScrollingAnimator() const override { return m_keyboardScrollingAnimator.get(); }
    8385
    8486#if ENABLE(TOUCH_EVENTS)
     
    179181
    180182    std::unique_ptr<ScrollAnimation> m_scrollAnimation;
     183    std::unique_ptr<KeyboardScrollingAnimator> m_keyboardScrollingAnimator;
    181184};
    182185
  • trunk/Source/WebCore/platform/ScrollController.cpp

    r280171 r280492  
    2727#include "ScrollController.h"
    2828
     29#include "KeyboardScrollingAnimator.h"
    2930#include "LayoutSize.h"
    3031#include "Logging.h"
     
    4445void ScrollController::animationCallback(MonotonicTime currentTime)
    4546{
    46     LOG_WITH_STREAM(Scrolling, stream << "ScrollController " << this << " animationCallback: isAnimatingRubberBand " << m_isAnimatingRubberBand << " isAnimatingScrollSnap " << m_isAnimatingScrollSnap);
     47    LOG_WITH_STREAM(Scrolling, stream << "ScrollController " << this << " animationCallback: isAnimatingRubberBand " << m_isAnimatingRubberBand << " isAnimatingScrollSnap " << m_isAnimatingScrollSnap << "isAnimatingKeyboardScrolling" << m_isAnimatingKeyboardScrolling);
    4748
    4849    updateScrollSnapAnimatingState(currentTime);
    4950    updateRubberBandAnimatingState(currentTime);
     51    updateKeyboardScrollingAnimatingState(currentTime);
    5052}
    5153
    5254void ScrollController::startOrStopAnimationCallbacks()
    5355{
    54     bool needsCallbacks = m_isAnimatingRubberBand || m_isAnimatingScrollSnap;
     56    bool needsCallbacks = m_isAnimatingRubberBand || m_isAnimatingScrollSnap || m_isAnimatingKeyboardScrolling;
    5557    if (needsCallbacks == m_isRunningAnimatingCallback)
    5658        return;
     
    6668}
    6769
     70void ScrollController::beginKeyboardScrolling()
     71{
     72    setIsAnimatingKeyboardScrolling(true);
     73}
     74
     75void ScrollController::stopKeyboardScrolling()
     76{
     77    setIsAnimatingKeyboardScrolling(false);
     78}
     79
    6880void ScrollController::setIsAnimatingRubberBand(bool isAnimatingRubberBand)
    6981{
     
    8193       
    8294    m_isAnimatingScrollSnap = isAnimatingScrollSnap;
     95    startOrStopAnimationCallbacks();
     96}
     97
     98void ScrollController::setIsAnimatingKeyboardScrolling(bool isAnimatingKeyboardScrolling)
     99{
     100    if (isAnimatingKeyboardScrolling == m_isAnimatingKeyboardScrolling)
     101        return;
     102
     103    m_isAnimatingKeyboardScrolling = isAnimatingKeyboardScrolling;
    83104    startOrStopAnimationCallbacks();
    84105}
     
    199220
    200221}
     222
     223void ScrollController::updateKeyboardScrollingAnimatingState(MonotonicTime currentTime)
     224{
     225    if (!m_isAnimatingKeyboardScrolling)
     226        return;
     227
     228    m_client.keyboardScrollingAnimator()->updateKeyboardScrollPosition(currentTime);
     229}
     230
    201231// Currently, only Mac supports momentum srolling-based scrollsnapping and rubber banding
    202232// so all of these methods are a noop on non-Mac platforms.
  • trunk/Source/WebCore/platform/ScrollController.h

    r280171 r280492  
    3939namespace WebCore {
    4040
     41class KeyboardScrollingAnimator;
    4142class LayoutSize;
    4243class PlatformWheelEvent;
     
    7273    virtual void startAnimationCallback(ScrollController&) = 0;
    7374    virtual void stopAnimationCallback(ScrollController&) = 0;
     75
     76    virtual void updateKeyboardScrollPosition(MonotonicTime) { }
     77    virtual KeyboardScrollingAnimator *keyboardScrollingAnimator() const { return nullptr; }
    7478
    7579#if ENABLE(RUBBER_BANDING)
     
    122126    void stopAllTimers();
    123127    void scrollPositionChanged();
     128
     129    void beginKeyboardScrolling();
     130    void stopKeyboardScrolling();
    124131   
    125132    // Should be called periodically by the client. Started by startAnimationCallback(), stopped by stopAnimationCallback().
     
    164171    void updateScrollSnapAnimatingState(MonotonicTime);
    165172    void updateRubberBandAnimatingState(MonotonicTime);
    166    
     173    void updateKeyboardScrollingAnimatingState(MonotonicTime);
     174
    167175    void setIsAnimatingRubberBand(bool);
    168176    void setIsAnimatingScrollSnap(bool);
     177    void setIsAnimatingKeyboardScrolling(bool);
    169178
    170179#if PLATFORM(MAC)
     
    200209    bool m_isAnimatingRubberBand { false };
    201210    bool m_isAnimatingScrollSnap { false };
     211    bool m_isAnimatingKeyboardScrolling { false };
    202212
    203213#if PLATFORM(MAC)
Note: See TracChangeset for help on using the changeset viewer.