Changeset 270312 in webkit


Ignore:
Timestamp:
Dec 1, 2020, 10:01:31 AM (5 years ago)
Author:
Simon Fraser
Message:

[WK1] Only the first wheel event in a gesture should be cancelable
https://bugs.webkit.org/show_bug.cgi?id=219384

Reviewed by Chris Dumez.

Source/WebCore:

Implement the logic described at <https://w3c.github.io/uievents/#cancelability-of-wheel-events>,
where only the first wheel event in a sequence is cancelable, and, if not canceled, then the
rest of the events in the sequence become non-cancelable.

This is done for the non-async scrolling code path (i.e. WebKitLegacy) by storing
a Optional<WheelScrollGestureState> on EventHandler, which is cleared when we receive
the "begin" event, set when we finish processing that event, then consulted for subsequent
move events.

Tests: fast/events/wheel/first-wheel-event-cancelable.html

fast/events/wheel/wheel-events-become-non-cancelable.html

  • page/EventHandler.h:
  • page/ios/EventHandlerIOS.mm:

(WebCore::EventHandler::wheelEvent):

  • page/mac/EventHandlerMac.mm:

(WebCore::EventHandler::wheelEvent):
(WebCore::EventHandler::wheelEventWasProcessedByMainThread):

  • platform/PlatformWheelEvent.cpp:

(WebCore::operator<<):

  • platform/PlatformWheelEvent.h:

LayoutTests:

Add a temporary failing result for WK2 until the async scrolling implementation lands.

  • fast/events/wheel/first-wheel-event-cancelable-expected.txt: Added.
  • fast/events/wheel/first-wheel-event-cancelable.html: Added.
  • fast/events/wheel/wheel-events-become-non-cancelable-expected.txt: Added.
  • fast/events/wheel/wheel-events-become-non-cancelable.html: Added.
  • platform/mac-wk2/fast/events/wheel/wheel-events-become-non-cancelable-expected.txt: Added.
  • platform/win/TestExpectations:
Location:
trunk
Files:
6 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r270304 r270312  
     12020-11-30  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [WK1] Only the first wheel event in a gesture should be cancelable
     4        https://bugs.webkit.org/show_bug.cgi?id=219384
     5
     6        Reviewed by Chris Dumez.
     7
     8        Add a temporary failing result for WK2 until the async scrolling implementation lands.
     9
     10        * fast/events/wheel/first-wheel-event-cancelable-expected.txt: Added.
     11        * fast/events/wheel/first-wheel-event-cancelable.html: Added.
     12        * fast/events/wheel/wheel-events-become-non-cancelable-expected.txt: Added.
     13        * fast/events/wheel/wheel-events-become-non-cancelable.html: Added.
     14        * platform/mac-wk2/fast/events/wheel/wheel-events-become-non-cancelable-expected.txt: Added.
     15        * platform/win/TestExpectations:
     16
    1172020-12-01  Youenn Fablet  <youenn@apple.com>
    218
  • trunk/LayoutTests/platform/win/TestExpectations

    r270016 r270312  
    283283fast/events/wheel/wheel-event-listeners-on-window-made-passive.html [ Skip ]
    284284fast/events/wheel/wheel-event-in-passive-region-non-cancelable.html [ Skip ]
     285fast/events/wheel/wheel-events-become-non-cancelable.html [ Skip ]
     286fast/events/wheel/first-wheel-event-cancelable.html [ Skip ]
    285287
    286288scrollbars/scroll-rtl-or-bt-layer.html [ Timeout ]
  • trunk/Source/WebCore/ChangeLog

    r270304 r270312  
     12020-11-30  Simon Fraser  <simon.fraser@apple.com>
     2
     3        [WK1] Only the first wheel event in a gesture should be cancelable
     4        https://bugs.webkit.org/show_bug.cgi?id=219384
     5
     6        Reviewed by Chris Dumez.
     7
     8        Implement the logic described at <https://w3c.github.io/uievents/#cancelability-of-wheel-events>,
     9        where only the first wheel event in a sequence is cancelable, and, if not canceled, then the
     10        rest of the events in the sequence become non-cancelable.
     11
     12        This is done for the non-async scrolling code path (i.e. WebKitLegacy) by storing
     13        a Optional<WheelScrollGestureState> on EventHandler, which is cleared when we receive
     14        the "begin" event, set when we finish processing that event, then consulted for subsequent
     15        move events.
     16
     17        Tests: fast/events/wheel/first-wheel-event-cancelable.html
     18               fast/events/wheel/wheel-events-become-non-cancelable.html
     19
     20        * page/EventHandler.h:
     21        * page/ios/EventHandlerIOS.mm:
     22        (WebCore::EventHandler::wheelEvent):
     23        * page/mac/EventHandlerMac.mm:
     24        (WebCore::EventHandler::wheelEvent):
     25        (WebCore::EventHandler::wheelEventWasProcessedByMainThread):
     26        * platform/PlatformWheelEvent.cpp:
     27        (WebCore::operator<<):
     28        * platform/PlatformWheelEvent.h:
     29
    1302020-12-01  Youenn Fablet  <youenn@apple.com>
    231
  • trunk/Source/WebCore/page/EventHandler.h

    r270278 r270312  
    9898
    9999enum class WheelEventProcessingSteps : uint8_t;
     100enum class WheelScrollGestureState : uint8_t;
    100101
    101102#if ENABLE(DRAG_SUPPORT)
     
    607608    NSView *m_mouseDownView { nullptr };
    608609    bool m_sendingEventToSubview { false };
     610    Optional<WheelScrollGestureState> m_wheelScrollGestureState;
    609611#endif
    610612
  • trunk/Source/WebCore/page/ios/EventHandlerIOS.mm

    r269973 r270312  
    108108    CurrentEventScope scope(event);
    109109
    110     bool eventWasHandled = handleWheelEvent(PlatformEventFactory::createPlatformWheelEvent(event), { WheelEventProcessingSteps::MainThreadForScrolling, WheelEventProcessingSteps::MainThreadForBlockingDOMEventDispatch });
     110    auto wheelEvent = PlatformEventFactory::createPlatformWheelEvent(event);
     111    OptionSet<WheelEventProcessingSteps> processingSteps = { WheelEventProcessingSteps::MainThreadForScrolling, WheelEventProcessingSteps::MainThreadForBlockingDOMEventDispatch };
     112
     113    if (wheelEvent.isGestureStart())
     114        m_wheelScrollGestureState = WTF::nullopt;
     115    else if (wheelEvent.phase() == PlatformWheelEventPhase::Changed || wheelEvent.momentumPhase() == PlatformWheelEventPhase::Changed) {
     116        if (m_wheelScrollGestureState && *m_wheelScrollGestureState == WheelScrollGestureState::NonBlocking)
     117            processingSteps = { WheelEventProcessingSteps::MainThreadForScrolling, WheelEventProcessingSteps::MainThreadForNonBlockingDOMEventDispatch };
     118    }
     119
     120    bool eventWasHandled = handleWheelEvent(wheelEvent, processingSteps);
    111121    event.wasHandled = eventWasHandled;
    112122    return eventWasHandled;
  • trunk/Source/WebCore/page/mac/EventHandlerMac.mm

    r270278 r270312  
    150150    auto wheelEvent = PlatformEventFactory::createPlatformWheelEvent(event, page->chrome().platformPageClient());
    151151    OptionSet<WheelEventProcessingSteps> processingSteps = { WheelEventProcessingSteps::MainThreadForScrolling, WheelEventProcessingSteps::MainThreadForBlockingDOMEventDispatch };
     152
     153    if (wheelEvent.isGestureStart())
     154        m_wheelScrollGestureState = WTF::nullopt;
     155    else if (wheelEvent.phase() == PlatformWheelEventPhase::Changed || wheelEvent.momentumPhase() == PlatformWheelEventPhase::Changed) {
     156        if (m_frame.settings().wheelEventGesturesBecomeNonBlocking() && m_wheelScrollGestureState && *m_wheelScrollGestureState == WheelScrollGestureState::NonBlocking)
     157            processingSteps = { WheelEventProcessingSteps::MainThreadForScrolling, WheelEventProcessingSteps::MainThreadForNonBlockingDOMEventDispatch };
     158    }
    152159    return handleWheelEvent(wheelEvent, processingSteps);
    153160}
     
    970977            scrollingCoordinator->wheelEventWasProcessedByMainThread(wheelEvent, eventHandling);
    971978    }
     979
     980    if (wheelEvent.isGestureStart() && eventHandling.contains(EventHandling::DispatchedToDOM))
     981        m_wheelScrollGestureState = eventHandling.contains(EventHandling::DefaultPrevented) ? WheelScrollGestureState::Blocking : WheelScrollGestureState::NonBlocking;
    972982#else
    973983    UNUSED_PARAM(wheelEvent);
  • trunk/Source/WebCore/platform/PlatformWheelEvent.cpp

    r269973 r270312  
    8181}
    8282
     83TextStream& operator<<(TextStream& ts, WheelScrollGestureState state)
     84{
     85    switch (state) {
     86    case WheelScrollGestureState::Blocking: ts << "blocking"; break;
     87    case WheelScrollGestureState::NonBlocking: ts << "non-blocking"; break;
     88    }
     89    return ts;
     90}
     91
    8392} // namespace WebCore
  • trunk/Source/WebCore/platform/PlatformWheelEvent.h

    r269973 r270312  
    4444};
    4545
     46enum class WheelScrollGestureState : uint8_t {
     47    Blocking,
     48    NonBlocking
     49};
     50
    4651// The ScrollByPixelWheelEvent is a fine-grained event that specifies the precise number of pixels to scroll.
    4752// It is sent directly by touch pads on macOS, or synthesized when platforms generate line-by-line scrolling events.
     
    268273WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, WheelEventProcessingSteps);
    269274WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, EventHandling);
     275WEBCORE_EXPORT WTF::TextStream& operator<<(WTF::TextStream&, WheelScrollGestureState);
    270276
    271277} // namespace WebCore
Note: See TracChangeset for help on using the changeset viewer.