Changeset 270425 in webkit
- Timestamp:
- Dec 3, 2020 11:10:03 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 1 deleted
- 19 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r270424 r270425 1 2020-12-03 Simon Fraser <simon.fraser@apple.com> 2 3 Only the first wheel event in a gesture should be cancelable 4 https://bugs.webkit.org/show_bug.cgi?id=218764 5 <rdar://problem/71248946> 6 7 Reviewed by Tim Horton. 8 9 * fast/scrolling/mac/rubberband-overflow-in-wheel-region-root-jiggle.html: Make more robust. 10 * platform/mac-wk2/fast/events/wheel/wheel-events-become-non-cancelable-expected.txt: Test now passes in WK2. 11 1 12 2020-12-03 Lauro Moura <lmoura@igalia.com> 2 13 -
trunk/LayoutTests/fast/scrolling/latching/scroll-latched-nested-div.html
r259121 r270425 11 11 } 12 12 </style> 13 <script src="../../../resources/ui-helper.js"></script> 13 14 <script src="../../../resources/js-test-pre.js"></script> 14 15 <script> … … 44 45 else 45 46 testPassed("div did not receive wheel events during the second gesture."); 46 47 finishJSTest();48 47 } 49 48 50 function checkForFirstScroll()49 async function doSecondScroll() 51 50 { 52 51 // 'parent' should not have scrolled, and the content of 'target' should … … 82 81 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, 'none', 'continue'); 83 82 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'none', 'end'); 84 eventSender.callAfterScrollingCompletes(checkForSecondScroll); 83 84 await UIHelper.waitForScrollCompletion(); 85 85 } 86 86 87 function scrollTest()87 async function doFirstScroll() 88 88 { 89 89 pageScrollPositionBefore = document.scrollingElement.scrollTop; … … 111 111 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -10, 'none', 'continue'); 112 112 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, 'none', 'end'); 113 eventSender.callAfterScrollingCompletes(checkForFirstScroll); 113 114 await UIHelper.waitForScrollCompletion(); 115 } 116 117 async function scrollTest() 118 { 119 await doFirstScroll(); 120 await doSecondScroll(); 121 checkForSecondScroll(); 122 finishJSTest(); 114 123 } 115 124 -
trunk/LayoutTests/fast/scrolling/mac/rubberband-overflow-in-wheel-region-root-jiggle.html
r269360 r270425 52 52 // Scroll down to latch, then up to rubberband. 53 53 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -1, "began", "none"); 54 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -10, "changed", "none"); 55 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -10, "changed", "none"); 56 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 12, "changed", "none"); 57 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 12, "changed", "none"); 54 await UIHelper.renderingUpdate(); 55 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -5, "changed", "none"); 56 await UIHelper.renderingUpdate(); 57 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, -5, "changed", "none"); 58 await UIHelper.renderingUpdate(); 59 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 5, "changed", "none"); 60 await UIHelper.renderingUpdate(); 61 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 5, "changed", "none"); 62 await UIHelper.renderingUpdate(); 63 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 5, "changed", "none"); 64 await UIHelper.renderingUpdate(); 58 65 eventSender.mouseScrollByWithWheelAndMomentumPhases(0, 0, "ended", "none"); 59 66 -
trunk/Source/WebCore/ChangeLog
r270421 r270425 1 2020-12-03 Simon Fraser <simon.fraser@apple.com> 2 3 Only the first wheel event in a gesture should be cancelable 4 https://bugs.webkit.org/show_bug.cgi?id=218764 5 <rdar://problem/71248946> 6 7 Reviewed by Tim Horton. 8 9 Implement the WebKit2 version of r270312, where only the first wheel event in a gesture is 10 cancelable. 11 12 When scrolling over an element with handlers, we do event handling on the main thread, 13 so we can take the compute value of EventHandler's Optional<WheelScrollGestureState> 14 from the first event and send it back to the scrolling thread. 15 16 However, the scrolling thread needs to block until this first event comes back from 17 the main thread. To achieve this, EventDispatcher::wheelEvent() now dispaches 18 main thread scrolls from the scrolling thread (not the dispatcher thread), and 19 waits on m_waitingForBeganEventCondition with a 50ms timeout for that first event to 20 come back. 21 22 In the normal case, main thread handling dispatches the event back to the scrolling 23 thread for scrolling via handleWheelEventAfterMainThread(), and then calls 24 wheelEventWasProcessedByMainThread() to signal the condition. If for some reason 25 handleWheelEventAfterMainThread() doesn't get called (e.g. nothing was scrollable), 26 then wheelEventWasProcessedByMainThread() still gets called to signal. 27 28 If m_waitingForBeganEventCondition times out, then the scrolling thread falls back 29 to non-blocking behaviour (as if the first event was not canceled). 30 31 Finally, when we know the gesture will become non-blocking, we transition to running 32 the scroll from the scrolling thread, which requires that we set up latching, hence 33 the changes in ScrollingTreeLatchingController. 34 35 Tested by existing tests in fast/events/wheel. 36 37 * page/EventHandler.cpp: 38 (WebCore::EventHandler::wheelEventWasProcessedByMainThread): 39 (WebCore::EventHandler::handleWheelEventInScrollableArea): 40 * page/WheelEventTestMonitor.cpp: 41 (WebCore::operator<<): 42 * page/WheelEventTestMonitor.h: 43 * page/mac/EventHandlerMac.mm: 44 (WebCore::EventHandler::processWheelEventForScrolling): 45 * page/scrolling/ScrollingTree.cpp: 46 (WebCore::ScrollingTree::determineWheelEventProcessing): 47 (WebCore::ScrollingTree::setGestureState): 48 (WebCore::ScrollingTree::gestureState): 49 * page/scrolling/ScrollingTree.h: 50 (WebCore::ScrollingTree::willSendEventToMainThread): 51 (WebCore::ScrollingTree::waitForEventToBeProcessedByMainThread): 52 * page/scrolling/ScrollingTreeLatchingController.cpp: 53 (WebCore::ScrollingTreeLatchingController::receivedWheelEvent): 54 (WebCore::ScrollingTreeLatchingController::nodeDidHandleEvent): 55 * page/scrolling/ScrollingTreeLatchingController.h: 56 * page/scrolling/ThreadedScrollingTree.cpp: 57 (WebCore::ThreadedScrollingTree::handleWheelEventAfterMainThread): 58 (WebCore::ThreadedScrollingTree::wheelEventWasProcessedByMainThread): 59 (WebCore::ThreadedScrollingTree::willSendEventToMainThread): 60 (WebCore::ThreadedScrollingTree::waitForEventToBeProcessedByMainThread): 61 * page/scrolling/ThreadedScrollingTree.h: 62 * page/scrolling/mac/ScrollingCoordinatorMac.mm: 63 (WebCore::ScrollingCoordinatorMac::handleWheelEventForScrolling): Need to track deferral 64 for WheelEventTestMonitor. 65 (WebCore::ScrollingCoordinatorMac::wheelEventWasProcessedByMainThread): This is now synchronous 66 to the scrolling thread so no need for the deferrer. 67 (WebCore::nextDeferIdentifier): Deleted. 68 * page/scrolling/nicosia/ScrollingCoordinatorNicosia.cpp: 69 (WebCore::ScrollingCoordinatorNicosia::wheelEventWasProcessedByMainThread): 70 * platform/cocoa/ScrollController.mm: 71 (WebCore::ScrollController::handleWheelEvent): 72 1 73 2020-12-03 Kate Cheney <katherine_cheney@apple.com> 2 74 -
trunk/Source/WebCore/page/EventHandler.cpp
r270389 r270425 2723 2723 } 2724 2724 2725 void EventHandler::wheelEventWasProcessedByMainThread(const PlatformWheelEvent&, OptionSet<EventHandling>) 2726 { 2725 void EventHandler::wheelEventWasProcessedByMainThread(const PlatformWheelEvent& wheelEvent, OptionSet<EventHandling> eventHandling) 2726 { 2727 updateWheelGestureState(wheelEvent, eventHandling); 2728 2729 #if ENABLE(ASYNC_SCROLLING) 2730 FrameView* view = m_frame.view(); 2731 if (auto scrollingCoordinator = m_frame.page()->scrollingCoordinator()) { 2732 if (scrollingCoordinator->coordinatesScrollingForFrameView(*view)) 2733 scrollingCoordinator->wheelEventWasProcessedByMainThread(wheelEvent, m_wheelScrollGestureState); 2734 } 2735 #endif 2727 2736 } 2728 2737 … … 2983 2992 { 2984 2993 auto gestureState = updateWheelGestureState(wheelEvent, eventHandling); 2985 LOG_WITH_STREAM(Scrolling, stream << "EventHandler::handleWheelEventInScrollableArea() - eventHandling " << eventHandling << " -> gesture state " << gestureState);2994 LOG_WITH_STREAM(Scrolling, stream << "EventHandler::handleWheelEventInScrollableArea() " << scrollableArea << " - eventHandling " << eventHandling << " -> gesture state " << gestureState); 2986 2995 return scrollableArea.handleWheelEventForScrolling(wheelEvent, gestureState); 2987 2996 } -
trunk/Source/WebCore/page/WheelEventTestMonitor.cpp
r270338 r270425 173 173 case WheelEventTestMonitor::HandlingWheelEvent: ts << "handling wheel event"; break; 174 174 case WheelEventTestMonitor::HandlingWheelEventOnMainThread: ts << "handling wheel event on main thread"; break; 175 case WheelEventTestMonitor:: ReportDOMEventHandling: ts << "report DOMevent handling"; break;175 case WheelEventTestMonitor::PostMainThreadWheelEventHandling: ts << "post-main thread event handling"; break; 176 176 case WheelEventTestMonitor::RubberbandInProgress: ts << "rubberbanding"; break; 177 177 case WheelEventTestMonitor::ScrollSnapInProgress: ts << "scroll-snapping"; break; -
trunk/Source/WebCore/page/WheelEventTestMonitor.h
r270338 r270425 49 49 50 50 enum DeferReason { 51 HandlingWheelEvent = 1 << 0,52 HandlingWheelEventOnMainThread = 1 << 1,53 ReportDOMEventHandling= 1 << 2,54 RubberbandInProgress = 1 << 3,55 ScrollSnapInProgress = 1 << 4,56 ScrollingThreadSyncNeeded = 1 << 5,57 ContentScrollInProgress = 1 << 6,58 RequestedScrollPosition = 1 << 7,51 HandlingWheelEvent = 1 << 0, 52 HandlingWheelEventOnMainThread = 1 << 1, 53 PostMainThreadWheelEventHandling = 1 << 2, 54 RubberbandInProgress = 1 << 3, 55 ScrollSnapInProgress = 1 << 4, 56 ScrollingThreadSyncNeeded = 1 << 5, 57 ContentScrollInProgress = 1 << 6, 58 RequestedScrollPosition = 1 << 7, 59 59 }; 60 60 typedef const void* ScrollableAreaIdentifier; -
trunk/Source/WebCore/page/mac/EventHandlerMac.mm
r270389 r270425 955 955 return didHandleWheelEvent; 956 956 } 957 957 958 958 bool didHandleEvent = handleWheelEventInScrollableArea(wheelEvent, *view, eventHandling); 959 959 m_isHandlingWheelEvent = false; -
trunk/Source/WebCore/page/scrolling/ScrollingTree.cpp
r270156 r270425 74 74 return latchedNodeAndSteps->processingSteps; 75 75 } 76 if (wheelEvent.isGestureStart() || wheelEvent.isNonGestureEvent()) 77 m_treeState.gestureState = WTF::nullopt; 76 78 77 79 auto processingSteps = [&]() -> OptionSet<WheelEventProcessingSteps> { … … 97 99 #if ENABLE(WHEEL_EVENT_REGIONS) 98 100 auto eventListenerTypes = eventListenerRegionTypesForPoint(position); 99 if (eventListenerTypes.contains(EventListenerRegionType::NonPassiveWheel)) 101 if (eventListenerTypes.contains(EventListenerRegionType::NonPassiveWheel)) { 102 if (m_treeState.gestureState.valueOr(WheelScrollGestureState::Blocking) == WheelScrollGestureState::NonBlocking) 103 return { WheelEventProcessingSteps::ScrollingThread, WheelEventProcessingSteps::MainThreadForNonBlockingDOMEventDispatch }; 104 100 105 return { WheelEventProcessingSteps::MainThreadForScrolling, WheelEventProcessingSteps::MainThreadForBlockingDOMEventDispatch }; 106 } 101 107 102 108 if (eventListenerTypes.contains(EventListenerRegionType::Wheel)) … … 483 489 } 484 490 491 void ScrollingTree::setGestureState(Optional<WheelScrollGestureState> gestureState) 492 { 493 LockHolder lock(m_treeStateMutex); 494 m_treeState.gestureState = gestureState; 495 } 496 497 Optional<WheelScrollGestureState> ScrollingTree::gestureState() 498 { 499 LockHolder lock(m_treeStateMutex); 500 return m_treeState.gestureState; 501 } 502 485 503 TrackingType ScrollingTree::eventTrackingTypeForPoint(const AtomString& eventName, IntPoint p) 486 504 { -
trunk/Source/WebCore/page/scrolling/ScrollingTree.h
r270338 r270425 211 211 virtual void unlockLayersForHitTesting() { } 212 212 213 virtual void willSendEventToMainThread(const PlatformWheelEvent&) { } 214 virtual void waitForEventToBeProcessedByMainThread(const PlatformWheelEvent&) { }; 215 213 216 Lock& treeMutex() { return m_treeMutex; } 214 217 … … 246 249 void setMainFrameScrollPosition(FloatPoint); 247 250 251 void setGestureState(Optional<WheelScrollGestureState>); 252 Optional<WheelScrollGestureState> gestureState(); 253 248 254 Optional<unsigned> nominalFramesPerSecond(); 249 255 … … 286 292 PlatformDisplayID displayID { 0 }; 287 293 Optional<unsigned> nominalFramesPerSecond; 294 Optional<WheelScrollGestureState> gestureState; 288 295 HashSet<ScrollingNodeID> nodesWithActiveRubberBanding; 289 296 HashSet<ScrollingNodeID> nodesWithActiveScrollSnap; -
trunk/Source/WebCore/page/scrolling/ScrollingTreeLatchingController.cpp
r269973 r270425 42 42 ScrollingTreeLatchingController::ScrollingTreeLatchingController() = default; 43 43 44 void ScrollingTreeLatchingController::receivedWheelEvent(const PlatformWheelEvent& wheelEvent, OptionSet<WheelEventProcessingSteps> , bool allowLatching)44 void ScrollingTreeLatchingController::receivedWheelEvent(const PlatformWheelEvent& wheelEvent, OptionSet<WheelEventProcessingSteps> processingSteps, bool allowLatching) 45 45 { 46 46 if (!allowLatching) … … 48 48 49 49 LockHolder locker(m_latchedNodeMutex); 50 if (wheelEvent.isGestureStart() && m_latchedNodeAndSteps && !latchedNodeIsRelevant()) { 51 LOG_WITH_STREAM(ScrollLatching, stream << "ScrollingTreeLatchingController " << this << " receivedWheelEvent - " << (MonotonicTime::now() - m_lastLatchedNodeInterationTime).milliseconds() << "ms since last event, clearing latched node"); 52 m_latchedNodeAndSteps.reset(); 50 if (wheelEvent.isGestureStart() && !latchedNodeIsRelevant()) { 51 if (m_latchedNodeAndSteps) { 52 LOG_WITH_STREAM(ScrollLatching, stream << "ScrollingTreeLatchingController " << this << " receivedWheelEvent - " << (MonotonicTime::now() - m_lastLatchedNodeInterationTime).milliseconds() << "ms since last event, clearing latched node"); 53 m_latchedNodeAndSteps.reset(); 54 } 55 m_processingStepsForCurrentGesture = processingSteps; 53 56 } 54 57 } … … 97 100 } 98 101 99 if (wheelEvent.delta().isZero() || !wheelEvent.isGestureStart()) 102 auto shouldLatch = [&]() { 103 if (wheelEvent.delta().isZero()) 104 return false; 105 106 if (wheelEvent.isGestureStart()) 107 return true; 108 109 if (!wheelEvent.isGestureContinuation()) 110 return false; 111 112 if (m_processingStepsForCurrentGesture.valueOr(OptionSet<WheelEventProcessingSteps> { }).contains(WheelEventProcessingSteps::MainThreadForScrolling) && processingSteps.contains(WheelEventProcessingSteps::ScrollingThread)) 113 return true; 114 115 return false; 116 }; 117 118 if (!shouldLatch()) 100 119 return; 120 121 m_processingStepsForCurrentGesture = processingSteps; 101 122 102 123 LOG_WITH_STREAM(ScrollLatching, stream << "ScrollingTreeLatchingController " << this << " nodeDidHandleEvent: latching to " << scrollingNodeID); -
trunk/Source/WebCore/page/scrolling/ScrollingTreeLatchingController.h
r269973 r270425 65 65 mutable Lock m_latchedNodeMutex; 66 66 Optional<ScrollingNodeAndProcessingSteps> m_latchedNodeAndSteps; 67 Optional<OptionSet<WheelEventProcessingSteps>> m_processingStepsForCurrentGesture; 67 68 MonotonicTime m_lastLatchedNodeInterationTime; 68 69 }; -
trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp
r270389 r270425 65 65 } 66 66 67 bool ThreadedScrollingTree::handleWheelEventAfterMainThread(const PlatformWheelEvent& wheelEvent, ScrollingNodeID targetNodeID, Optional<WheelScrollGestureState>) 68 { 69 LOG_WITH_STREAM(Scrolling, stream << "ThreadedScrollingTree::handleWheelEventAfterMainThread " << wheelEvent << " node " << targetNodeID); 67 bool ThreadedScrollingTree::handleWheelEventAfterMainThread(const PlatformWheelEvent& wheelEvent, ScrollingNodeID targetNodeID, Optional<WheelScrollGestureState> gestureState) 68 { 69 ASSERT(ScrollingThread::isCurrentThread()); 70 71 LOG_WITH_STREAM(Scrolling, stream << "ThreadedScrollingTree::handleWheelEventAfterMainThread " << wheelEvent << " node " << targetNodeID << " gestureState " << gestureState); 70 72 71 73 LockHolder locker(m_treeMutex); 72 74 73 SetForScope<bool> disallowLatchingScope(m_allowLatching, false); 75 bool allowLatching = false; 76 OptionSet<WheelEventProcessingSteps> processingSteps; 77 if (gestureState.valueOr(WheelScrollGestureState::Blocking) == WheelScrollGestureState::NonBlocking) { 78 allowLatching = true; 79 processingSteps = { WheelEventProcessingSteps::ScrollingThread, WheelEventProcessingSteps::MainThreadForNonBlockingDOMEventDispatch }; 80 } 81 82 SetForScope<bool> disallowLatchingScope(m_allowLatching, allowLatching); 74 83 RefPtr<ScrollingTreeNode> targetNode = nodeForID(targetNodeID); 75 auto result = handleWheelEventWithNode(wheelEvent, { }, targetNode.get(), EventTargeting::NodeOnly);84 auto result = handleWheelEventWithNode(wheelEvent, processingSteps, targetNode.get(), EventTargeting::NodeOnly); 76 85 return result.wasHandled; 77 86 } 78 87 79 void ThreadedScrollingTree::wheelEventWasProcessedByMainThread(const PlatformWheelEvent&, Optional<WheelScrollGestureState>) 80 { 81 // FIXME: Set state based on EventHandling flags. 88 void ThreadedScrollingTree::wheelEventWasProcessedByMainThread(const PlatformWheelEvent& wheelEvent, Optional<WheelScrollGestureState> gestureState) 89 { 90 LOG_WITH_STREAM(Scrolling, stream << "ThreadedScrollingTree::wheelEventWasProcessedByMainThread - gestureState " << gestureState); 91 92 ASSERT(isMainThread()); 93 94 LockHolder locker(m_treeMutex); 95 if (m_receivedBeganEventFromMainThread || !wheelEvent.isGestureStart()) 96 return; 97 98 setGestureState(gestureState); 99 100 m_receivedBeganEventFromMainThread = true; 101 m_waitingForBeganEventCondition.notifyOne(); 102 } 103 104 void ThreadedScrollingTree::willSendEventToMainThread(const PlatformWheelEvent&) 105 { 106 ASSERT(ScrollingThread::isCurrentThread()); 107 108 LockHolder locker(m_treeMutex); 109 m_receivedBeganEventFromMainThread = false; 110 } 111 112 void ThreadedScrollingTree::waitForEventToBeProcessedByMainThread(const PlatformWheelEvent& wheelEvent) 113 { 114 ASSERT(ScrollingThread::isCurrentThread()); 115 116 if (!wheelEvent.isGestureStart()) 117 return; 118 119 LockHolder locker(m_treeMutex); 120 121 static constexpr auto maxAllowableMainThreadDelay = 50_ms; 122 auto startTime = MonotonicTime::now(); 123 auto timeoutTime = startTime + maxAllowableMainThreadDelay; 124 125 bool receivedEvent = m_waitingForBeganEventCondition.waitUntil(m_treeMutex, timeoutTime, [&] { 126 return m_receivedBeganEventFromMainThread; 127 }); 128 129 if (!receivedEvent) { 130 // Timed out, go asynchronous. 131 setGestureState(WheelScrollGestureState::NonBlocking); 132 } 133 134 LOG_WITH_STREAM(Scrolling, stream << "ThreadedScrollingTree::waitForBeganEventFromMainThread done - timed out " << !receivedEvent << " gesture state is " << gestureState()); 82 135 } 83 136 -
trunk/Source/WebCore/page/scrolling/ThreadedScrollingTree.h
r270389 r270425 51 51 void wheelEventWasProcessedByMainThread(const PlatformWheelEvent&, Optional<WheelScrollGestureState>); 52 52 53 WEBCORE_EXPORT void willSendEventToMainThread(const PlatformWheelEvent&) final; 54 WEBCORE_EXPORT void waitForEventToBeProcessedByMainThread(const PlatformWheelEvent&) final; 55 53 56 void invalidate() override; 54 57 … … 86 89 void displayDidRefreshOnScrollingThread(); 87 90 void waitForRenderingUpdateCompletionOrTimeout(); 88 91 89 92 bool canUpdateLayersOnScrollingThread() const; 90 93 … … 104 107 Condition m_stateCondition; 105 108 109 bool m_receivedBeganEventFromMainThread { false }; 110 Condition m_waitingForBeganEventCondition; 111 106 112 // Dynamically allocated because it has to use the ScrollingThread's runloop. 107 113 std::unique_ptr<RunLoop::Timer<ThreadedScrollingTree>> m_delayedRenderingUpdateDetectionTimer; -
trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm
r270389 r270425 82 82 return false; 83 83 84 LOG_WITH_STREAM(Scrolling, stream << "ScrollingCoordinatorMac::handleWheelEventForScrolling - sending event to scrolling thread, node " << targetNodeID << " gestureState " << gestureState); 85 84 LOG_WITH_STREAM(Scrolling, stream << "ScrollingCoordinatorMac::handleWheelEventForScrolling " << wheelEvent << " - sending event to scrolling thread, node " << targetNodeID << " gestureState " << gestureState); 85 86 auto deferrer = WheelEventTestMonitorCompletionDeferrer { m_page->wheelEventTestMonitor().get(), reinterpret_cast<WheelEventTestMonitor::ScrollableAreaIdentifier>(targetNodeID), WheelEventTestMonitor::PostMainThreadWheelEventHandling }; 87 86 88 RefPtr<ThreadedScrollingTree> threadedScrollingTree = downcast<ThreadedScrollingTree>(scrollingTree()); 87 ScrollingThread::dispatch([threadedScrollingTree, wheelEvent, targetNodeID, gestureState ] {89 ScrollingThread::dispatch([threadedScrollingTree, wheelEvent, targetNodeID, gestureState, deferrer = WTFMove(deferrer)] { 88 90 threadedScrollingTree->handleWheelEventAfterMainThread(wheelEvent, targetNodeID, gestureState); 89 91 }); … … 91 93 } 92 94 93 static uint64_t nextDeferIdentifier()94 {95 static uint64_t deferIdentifier;96 return ++deferIdentifier;97 }98 99 95 void ScrollingCoordinatorMac::wheelEventWasProcessedByMainThread(const PlatformWheelEvent& wheelEvent, Optional<WheelScrollGestureState> gestureState) 100 96 { 101 auto deferrer = WheelEventTestMonitorCompletionDeferrer { m_page->wheelEventTestMonitor().get(), reinterpret_cast<WheelEventTestMonitor::ScrollableAreaIdentifier>(nextDeferIdentifier()), WheelEventTestMonitor::ReportDOMEventHandling };97 LOG_WITH_STREAM(Scrolling, stream << "ScrollingCoordinatorMac::wheelEventWasProcessedByMainThread " << gestureState); 102 98 103 99 RefPtr<ThreadedScrollingTree> threadedScrollingTree = downcast<ThreadedScrollingTree>(scrollingTree()); 104 ScrollingThread::dispatch([threadedScrollingTree, wheelEvent, gestureState, deferrer = WTFMove(deferrer)] { 105 threadedScrollingTree->wheelEventWasProcessedByMainThread(wheelEvent, gestureState); 106 }); 100 threadedScrollingTree->wheelEventWasProcessedByMainThread(wheelEvent, gestureState); 107 101 } 108 102 -
trunk/Source/WebCore/page/scrolling/nicosia/ScrollingCoordinatorNicosia.cpp
r270389 r270425 84 84 void ScrollingCoordinatorNicosia::wheelEventWasProcessedByMainThread(const PlatformWheelEvent& wheelEvent, Optional<WheelScrollGestureState> gestureState) 85 85 { 86 ScrollingThread::dispatch([threadedScrollingTree = makeRef(downcast<ThreadedScrollingTree>(*scrollingTree())), wheelEvent, gestureState] { 87 threadedScrollingTree->wheelEventWasProcessedByMainThread(wheelEvent, gestureState); 88 }); 86 RefPtr<ThreadedScrollingTree> threadedScrollingTree = downcast<ThreadedScrollingTree>(scrollingTree()); 87 threadedScrollingTree->wheelEventWasProcessedByMainThread(wheelEvent, gestureState); 89 88 } 90 89 -
trunk/Source/WebCore/platform/PlatformWheelEvent.h
r270389 r270425 209 209 || m_momentumPhase == PlatformWheelEventPhase::Began 210 210 || m_momentumPhase == PlatformWheelEventPhase::Changed 211 || (m_phase == PlatformWheelEventPhase::Ended && m_momentumPhase == PlatformWheelEventPhase::None); 211 || (m_phase == PlatformWheelEventPhase::Ended && m_momentumPhase == PlatformWheelEventPhase::None) 212 || (m_phase == PlatformWheelEventPhase::None && m_momentumPhase == PlatformWheelEventPhase::Ended); 212 213 } 213 214 -
trunk/Source/WebKit/ChangeLog
r270422 r270425 1 2020-12-03 Simon Fraser <simon.fraser@apple.com> 2 3 Only the first wheel event in a gesture should be cancelable 4 https://bugs.webkit.org/show_bug.cgi?id=218764 5 <rdar://problem/71248946> 6 7 Reviewed by Tim Horton. 8 9 In EventDispatcher::wheelEvent(), all wheel events now bounce through the scrolling 10 thread, even those destined for main thread scrolling. This allows the scrolling thread 11 to wait on a condition for the event to come back to the scrolling thread via 12 handleWheelEventAfterMainThread(), since we have to know whether content called 13 preventDefault() on the first event before sending subsequent events. 14 15 * WebProcess/WebPage/EventDispatcher.cpp: 16 (WebKit::EventDispatcher::wheelEvent): 17 1 18 2020-12-03 Alex Christensen <achristensen@webkit.org> 2 19 -
trunk/Source/WebKit/WebProcess/WebPage/EventDispatcher.cpp
r270292 r270425 137 137 138 138 auto processingSteps = scrollingTree->determineWheelEventProcessing(platformWheelEvent); 139 if (!processingSteps.contains(WheelEventProcessingSteps::ScrollingThread))140 return processingSteps;141 139 142 140 scrollingTree->willProcessWheelEvent(); 143 141 144 142 ScrollingThread::dispatch([scrollingTree, wheelEvent, platformWheelEvent, processingSteps, pageID, protectedThis = makeRef(*this)] { 143 if (processingSteps.contains(WheelEventProcessingSteps::MainThreadForScrolling)) { 144 scrollingTree->willSendEventToMainThread(platformWheelEvent); 145 protectedThis->dispatchWheelEventViaMainThread(pageID, wheelEvent, processingSteps); 146 scrollingTree->waitForEventToBeProcessedByMainThread(platformWheelEvent); 147 return; 148 } 149 145 150 auto result = scrollingTree->handleWheelEvent(platformWheelEvent, processingSteps); 146 151 … … 158 163 return processingSteps; 159 164 }(); 160 161 if (processingSteps.contains(WheelEventProcessingSteps::ScrollingThread))162 return;163 164 165 #else 165 166 UNUSED_PARAM(canRubberBandAtLeft); … … 167 168 UNUSED_PARAM(canRubberBandAtTop); 168 169 UNUSED_PARAM(canRubberBandAtBottom); 169 #endif170 170 171 171 dispatchWheelEventViaMainThread(pageID, wheelEvent, processingSteps); 172 #endif 172 173 } 173 174
Note: See TracChangeset
for help on using the changeset viewer.