Changeset 270712 in webkit
- Timestamp:
- Dec 11, 2020 2:59:22 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r270710 r270712 1 2020-12-11 Tim Horton <timothy_horton@apple.com> 2 3 Trackpad and Mouse scroll events on iPad only fire "pointermove" -- not "wheel" 4 https://bugs.webkit.org/show_bug.cgi?id=210071 5 <rdar://problem/54616853> 6 7 Reviewed by Simon Fraser. 8 9 * wtf/PlatformEnableCocoa.h: 10 Enable wheel event regions on iOS + macCatalyst. 11 1 12 2020-12-11 Brent Fulgham <bfulgham@apple.com> 2 13 -
trunk/Source/WTF/wtf/PlatformEnableCocoa.h
r270565 r270712 523 523 #endif 524 524 525 #if !defined(ENABLE_WHEEL_EVENT_REGIONS) && PLATFORM(MAC)525 #if !defined(ENABLE_WHEEL_EVENT_REGIONS) && (PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(MACCATALYST)) 526 526 #define ENABLE_WHEEL_EVENT_REGIONS 1 527 527 #endif -
trunk/Source/WebCore/ChangeLog
r270708 r270712 1 2020-12-11 Tim Horton <timothy_horton@apple.com> 2 3 Trackpad and Mouse scroll events on iPad only fire "pointermove" -- not "wheel" 4 https://bugs.webkit.org/show_bug.cgi?id=210071 5 <rdar://problem/54616853> 6 7 Reviewed by Simon Fraser. 8 9 * page/EventHandler.cpp: 10 (WebCore::EventHandler::handleWheelEventInternal): 11 Fix a minor logic error when WHEEL_EVENT_LATCHING is off; allowScrolling 12 would always be true, even if the set of processing steps does not include any scrolling steps. 13 14 * rendering/EventRegion.h: 15 (WebCore::EventRegion::encode const): 16 (WebCore::EventRegion::decode): 17 Encode/decode the wheel and passive wheel event regions. 18 1 19 2020-12-11 Peng Liu <peng.liu6@apple.com> 2 20 -
trunk/Source/WebCore/page/EventHandler.cpp
r270446 r270712 2915 2915 2916 2916 bool handledEvent = false; 2917 bool allowScrolling = true; 2917 bool allowScrolling = m_currentWheelEventAllowsScrolling; 2918 2918 2919 #if ENABLE(WHEEL_EVENT_LATCHING) 2919 allowScrolling = m_currentWheelEventAllowsScrolling && m_frame.page()->scrollLatchingController().latchingAllowsScrollingInFrame(m_frame, scrollableArea); 2920 #endif 2920 if (allowScrolling) 2921 allowScrolling = m_frame.page()->scrollLatchingController().latchingAllowsScrollingInFrame(m_frame, scrollableArea); 2922 #endif 2923 2921 2924 if (allowScrolling) { 2922 2925 // FIXME: processWheelEventForScrolling() is only called for FrameView scrolling, not overflow scrolling, which is confusing. -
trunk/Source/WebCore/page/EventHandler.h
r270446 r270712 347 347 WEBCORE_EXPORT Optional<Cursor> selectCursor(const HitTestResult&, bool shiftKey); 348 348 349 #if ENABLE(KINETIC_SCROLLING) 350 Optional<WheelScrollGestureState> wheelScrollGestureState() const { return m_wheelScrollGestureState; } 351 #endif 352 349 353 #if ENABLE(DRAG_SUPPORT) 350 354 Element* draggingElement() const; -
trunk/Source/WebCore/rendering/EventRegion.h
r263762 r270712 83 83 84 84 #if ENABLE(WHEEL_EVENT_REGIONS) 85 OptionSet<EventListenerRegionType> eventListenerRegionTypesForPoint(const IntPoint&) const;85 WEBCORE_EXPORT OptionSet<EventListenerRegionType> eventListenerRegionTypesForPoint(const IntPoint&) const; 86 86 const Region& eventListenerRegionForType(EventListenerRegionType) const; 87 87 #endif … … 126 126 { 127 127 encoder << m_region; 128 #if ENABLE(WHEEL_EVENT_REGIONS) 129 encoder << m_wheelEventListenerRegion; 130 encoder << m_nonPassiveWheelEventListenerRegion; 131 #endif 128 132 #if ENABLE(TOUCH_ACTION_REGIONS) 129 133 encoder << m_touchActionRegions; … … 144 148 EventRegion eventRegion; 145 149 eventRegion.m_region = WTFMove(*region); 150 151 #if ENABLE(WHEEL_EVENT_REGIONS) 152 Optional<Region> wheelEventListenerRegion; 153 decoder >> wheelEventListenerRegion; 154 if (!wheelEventListenerRegion) 155 return WTF::nullopt; 156 157 eventRegion.m_wheelEventListenerRegion = WTFMove(*wheelEventListenerRegion); 158 159 Optional<Region> nonPassiveWheelEventListenerRegion; 160 decoder >> nonPassiveWheelEventListenerRegion; 161 if (!nonPassiveWheelEventListenerRegion) 162 return WTF::nullopt; 163 164 eventRegion.m_nonPassiveWheelEventListenerRegion = WTFMove(*nonPassiveWheelEventListenerRegion); 165 #endif 146 166 147 167 #if ENABLE(TOUCH_ACTION_REGIONS) -
trunk/Source/WebKit/ChangeLog
r270710 r270712 1 2020-12-11 Tim Horton <timothy_horton@apple.com> 2 3 Trackpad and Mouse scroll events on iPad only fire "pointermove" -- not "wheel" 4 https://bugs.webkit.org/show_bug.cgi?id=210071 5 <rdar://problem/54616853> 6 7 Reviewed by Simon Fraser. 8 9 * Platform/spi/ios/UIKitSPI.h: 10 Add some SPI. 11 12 * Shared/ios/WebIOSEventFactory.h: 13 * Shared/ios/WebIOSEventFactory.mm: 14 (toWebPhase): 15 (WebIOSEventFactory::createWebWheelEvent): 16 Add a UIScrollEvent->WebWheelEvent conversion helper. 17 18 * UIProcess/API/Cocoa/WKWebViewInternal.h: 19 * UIProcess/API/ios/WKWebViewIOS.h: 20 * UIProcess/API/ios/WKWebViewIOS.mm: 21 (-[WKWebView _setupScrollAndContentViews]): 22 Enable async UIScrollEvent handling for WKScrollView. 23 24 (-[WKWebView _scrollView:asynchronouslyHandleScrollEvent:completion:]): 25 Adopt new UIKit SPI to asynchronously defer UIScrollEvents. 26 We pass them to the Web Content process, where they are processed 27 *only* for event handling, not for scrolling. 28 29 If the event is not cancelable, we will synchronously reply that it was 30 not handled; if it is cancelable, or we don't yet know if it will be, 31 we'll wait to hear back from the Web Content process before replying. 32 33 UIKit will wait until our reply to apply the UIScrollEvent to the UIScrollView. 34 35 * UIProcess/PageClient.h: 36 * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h: 37 * UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm: 38 (WebKit::eventListenerTypesAtPoint): 39 Expose a mechanism for retrieving the event listener types at a given point, 40 similar to the existing mechanism for touch event listeners. 41 42 (-[WKChildScrollView initWithFrame:]): 43 Enable async UIScrollEvent handling for WKChildScrollView. 44 45 * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h: 46 * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm: 47 (-[WKScrollingNodeScrollViewDelegate _scrollView:asynchronouslyHandleScrollEvent:completion:]): 48 (WebKit::ScrollingTreeScrollingNodeDelegateIOS::handleAsynchronousCancelableScrollEvent): 49 Plumb async scroll events for sub-scrollable regions through PageClient 50 to WKWebView; we don't actually care which UIScrollView they're handed to, 51 since we re-hit-test ourselves. 52 53 * UIProcess/WebPageProxy.cpp: 54 (WebKit::WebPageProxy::dispatchWheelEventWithoutScrolling): 55 * UIProcess/WebPageProxy.h: 56 * UIProcess/ios/PageClientImplIOS.h: 57 * UIProcess/ios/PageClientImplIOS.mm: 58 (WebKit::PageClientImpl::handleAsynchronousCancelableScrollEvent): 59 * WebProcess/WebPage/WebPage.cpp: 60 (WebKit::WebPage::wheelEvent): 61 (WebKit::WebPage::dispatchWheelEventWithoutScrolling): 62 * WebProcess/WebPage/WebPage.h: 63 * WebProcess/WebPage/WebPage.messages.in: 64 1 65 2020-12-11 Brent Fulgham <bfulgham@apple.com> 2 66 -
trunk/Source/WebKit/Platform/spi/ios/UIKitSPI.h
r270669 r270712 63 63 #import <UIKit/UIResponder_Private.h> 64 64 #import <UIKit/UIScene_Private.h> 65 #import <UIKit/UIScrollEvent_Private.h> 66 #import <UIKit/UIScrollView_ForWebKitOnly.h> 65 67 #import <UIKit/UIScrollView_Private.h> 66 68 #import <UIKit/UIStringDrawing_Private.h> … … 417 419 @property (nonatomic, readonly) UIEdgeInsets _systemContentInset; 418 420 @property (nonatomic, readonly) UIEdgeInsets _effectiveContentInset; 419 @end 421 @property (nonatomic, getter=_allowsAsyncScrollEvent, setter=_setAllowsAsyncScrollEvent:) BOOL _allowsAsyncScrollEvent; 422 @end 423 424 typedef NS_ENUM(NSUInteger, UIScrollPhase) { 425 UIScrollPhaseNone, 426 UIScrollPhaseMayBegin, 427 UIScrollPhaseBegan, 428 UIScrollPhaseChanged, 429 UIScrollPhaseEnded, 430 UIScrollPhaseCancelled 431 }; 432 433 @interface UIScrollEvent : UIEvent 434 435 @property (assign, readonly) UIScrollPhase phase; 436 - (CGPoint)locationInView:(UIView *)view; 437 - (CGVector)_adjustedAcceleratedDeltaInView:(UIView *)view; 438 439 @end 440 420 441 421 442 @interface NSString (UIKitDetails) -
trunk/Source/WebKit/Shared/ios/WebIOSEventFactory.h
r267916 r270712 30 30 #import "WebKeyboardEvent.h" 31 31 #import "WebMouseEvent.h" 32 #import "WebWheelEvent.h" 32 33 #import <UIKit/UIKit.h> 33 34 #import <WebCore/WebEvent.h> 35 36 OBJC_CLASS UIScrollEvent; 34 37 35 38 class WebIOSEventFactory { … … 37 40 static WebKit::WebKeyboardEvent createWebKeyboardEvent(::WebEvent *, bool handledByInputMethod); 38 41 static WebKit::WebMouseEvent createWebMouseEvent(::WebEvent *); 42 static WebKit::WebWheelEvent createWebWheelEvent(UIScrollEvent *, UIView *contentView); 39 43 40 44 static UIKeyModifierFlags toUIKeyModifierFlags(OptionSet<WebKit::WebEvent::Modifier>); -
trunk/Source/WebKit/Shared/ios/WebIOSEventFactory.mm
r244975 r270712 29 29 #if PLATFORM(IOS_FAMILY) 30 30 31 #import "UIKitSPI.h" 31 32 #import <WebCore/KeyEventCodesIOS.h> 32 33 #import <WebCore/PlatformEventFactoryIOS.h> … … 131 132 } 132 133 134 static WebKit::WebWheelEvent::Phase toWebPhase(UIScrollPhase phase) 135 { 136 switch (phase) { 137 case UIScrollPhaseNone: 138 return WebKit::WebWheelEvent::PhaseNone; 139 case UIScrollPhaseMayBegin: 140 return WebKit::WebWheelEvent::PhaseMayBegin; 141 case UIScrollPhaseBegan: 142 return WebKit::WebWheelEvent::PhaseBegan; 143 case UIScrollPhaseChanged: 144 return WebKit::WebWheelEvent::PhaseChanged; 145 case UIScrollPhaseEnded: 146 return WebKit::WebWheelEvent::PhaseEnded; 147 case UIScrollPhaseCancelled: 148 return WebKit::WebWheelEvent::PhaseCancelled; 149 default: 150 ASSERT_NOT_REACHED(); 151 return WebKit::WebWheelEvent::PhaseNone; 152 } 153 } 154 155 WebKit::WebWheelEvent WebIOSEventFactory::createWebWheelEvent(UIScrollEvent *event, UIView *contentView) 156 { 157 WebCore::IntPoint scrollLocation = WebCore::roundedIntPoint([event locationInView:contentView]); 158 CGVector deltaVector = [event _adjustedAcceleratedDeltaInView:contentView]; 159 WebCore::FloatSize delta(deltaVector.dx, deltaVector.dy); 160 161 return { 162 WebKit::WebEvent::Wheel, 163 scrollLocation, 164 scrollLocation, 165 delta, 166 { } /* wheelTicks */, 167 WebKit::WebWheelEvent::Granularity::ScrollByPixelWheelEvent, 168 false, 169 toWebPhase(event.phase), 170 WebKit::WebWheelEvent::PhaseNone, 171 true, 172 1, 173 delta, 174 { }, 175 MonotonicTime::fromRawSeconds(event.timestamp).approximateWallTime() 176 }; 177 } 178 133 179 #endif // PLATFORM(IOS_FAMILY) -
trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewInternal.h
r266890 r270712 66 66 } 67 67 68 namespace WebCore { 69 enum class WheelScrollGestureState : uint8_t; 70 } 71 68 72 namespace WebKit { 69 73 enum class ContinueUnsafeLoad : bool; … … 230 234 BOOL _visibleContentRectUpdateScheduledFromScrollViewInStableState; 231 235 236 Optional<WebCore::WheelScrollGestureState> _currentScrollGestureState; 237 232 238 _WKDragInteractionPolicy _dragInteractionPolicy; 233 239 -
trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.h
r266342 r270712 25 25 26 26 #import "WKWebViewInternal.h" 27 28 @class UIScrollEvent; 27 29 28 30 #if PLATFORM(IOS_FAMILY) … … 126 128 - (void)_updateScrollViewInsetAdjustmentBehavior; 127 129 130 - (BOOL)_effectiveAppearanceIsDark; 131 - (BOOL)_effectiveUserInterfaceLevelIsElevated; 132 133 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 134 - (void)_scrollView:(UIScrollView *)scrollView asynchronouslyHandleScrollEvent:(UIScrollEvent *)scrollEvent completion:(void (^)(BOOL handled))completion; 135 #endif 136 128 137 @property (nonatomic, readonly) WKPasswordView *_passwordView; 129 138 @property (nonatomic, readonly) WKWebViewContentProviderRegistry *_contentProviderRegistry; … … 138 147 @property (nonatomic, readonly) int32_t _deviceOrientation; 139 148 140 - (BOOL)_effectiveAppearanceIsDark;141 - (BOOL)_effectiveUserInterfaceLevelIsElevated;142 143 149 @end 144 150 -
trunk/Source/WebKit/UIProcess/API/ios/WKWebViewIOS.mm
r270669 r270712 30 30 31 31 #import "FrontBoardServicesSPI.h" 32 #import "NativeWebWheelEvent.h" 32 33 #import "NavigationState.h" 33 34 #import "RemoteLayerTreeDrawingAreaProxy.h" 34 35 #import "RemoteLayerTreeScrollingPerformanceData.h" 36 #import "RemoteLayerTreeViews.h" 35 37 #import "RemoteScrollingCoordinatorProxy.h" 36 38 #import "VideoFullscreenManagerProxy.h" … … 48 50 #import "WKWebViewPrivateForTestingIOS.h" 49 51 #import "WebBackForwardList.h" 52 #import "WebIOSEventFactory.h" 50 53 #import "WebPageProxy.h" 51 54 #import "_WKActivatedElementInfoInternal.h" … … 141 144 [_scrollView setInternalDelegate:self]; 142 145 [_scrollView setBouncesZoom:YES]; 146 147 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 148 [_scrollView _setAllowsAsyncScrollEvent:YES]; 149 #endif 143 150 144 151 if ([_scrollView respondsToSelector:@selector(_setAvoidsJumpOnInterruptedBounce:)]) { … … 1593 1600 } 1594 1601 1602 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 1603 - (void)_scrollView:(UIScrollView *)scrollView asynchronouslyHandleScrollEvent:(UIScrollEvent *)scrollEvent completion:(void (^)(BOOL handled))completion 1604 { 1605 if (scrollEvent.phase == UIScrollPhaseMayBegin) { 1606 completion(NO); 1607 return; 1608 } 1609 1610 WebCore::IntPoint scrollLocation = WebCore::roundedIntPoint([scrollEvent locationInView:_contentView.get()]); 1611 auto eventListeners = WebKit::eventListenerTypesAtPoint(_contentView.get(), scrollLocation); 1612 bool hasWheelHandlers = eventListeners.contains(WebCore::EventListenerRegionType::Wheel); 1613 if (!hasWheelHandlers) { 1614 completion(NO); 1615 return; 1616 } 1617 1618 bool isFirstEventInGesture = scrollEvent.phase == UIScrollPhaseBegan; 1619 if (isFirstEventInGesture) 1620 _currentScrollGestureState = WTF::nullopt; 1621 1622 bool hasActiveWheelHandlers = eventListeners.contains(WebCore::EventListenerRegionType::NonPassiveWheel); 1623 bool isCancelable = hasActiveWheelHandlers && (!_currentScrollGestureState || _currentScrollGestureState == WebCore::WheelScrollGestureState::Blocking); 1624 auto event = WebIOSEventFactory::createWebWheelEvent(scrollEvent, _contentView.get()); 1625 1626 _page->dispatchWheelEventWithoutScrolling(event, [weakSelf = WeakObjCPtr<WKWebView>(self), strongCompletion = makeBlockPtr(completion), isCancelable, isFirstEventInGesture](bool handled) { 1627 auto strongSelf = weakSelf.get(); 1628 if (!strongSelf) { 1629 strongCompletion(NO); 1630 return; 1631 } 1632 1633 if (isCancelable) { 1634 if (isFirstEventInGesture) 1635 strongSelf->_currentScrollGestureState = handled ? WebCore::WheelScrollGestureState::Blocking : WebCore::WheelScrollGestureState::NonBlocking; 1636 strongCompletion(handled); 1637 } 1638 }); 1639 1640 if (!isCancelable) 1641 completion(NO); 1642 } 1643 #endif // HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 1644 1595 1645 - (void)scrollViewDidScroll:(UIScrollView *)scrollView 1596 1646 { -
trunk/Source/WebKit/UIProcess/PageClient.h
r270573 r270712 66 66 OBJC_CLASS NSTextAlternatives; 67 67 OBJC_CLASS UIGestureRecognizer; 68 OBJC_CLASS UIScrollEvent; 69 OBJC_CLASS UIScrollView; 68 70 OBJC_CLASS _WKRemoteObjectRegistry; 69 71 … … 464 466 465 467 virtual void handleAutocorrectionContext(const WebAutocorrectionContext&) = 0; 468 469 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 470 virtual void handleAsynchronousCancelableScrollEvent(UIScrollView *, UIScrollEvent *, void (^completion)(BOOL handled)) = 0; 471 #endif 466 472 #endif 467 473 -
trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.h
r266342 r270712 72 72 UIScrollView *findActingScrollParent(UIScrollView *, const RemoteLayerTreeHost&); 73 73 74 OptionSet<WebCore::EventListenerRegionType> eventListenerTypesAtPoint(UIView *rootView, const WebCore::IntPoint&); 75 74 76 #if ENABLE(EDITABLE_REGION) 75 77 bool mayContainEditableElementsInRect(UIView *rootView, const WebCore::FloatRect&); -
trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/RemoteLayerTreeViews.mm
r266342 r270712 206 206 } 207 207 208 #if ENABLE(WHEEL_EVENT_REGIONS) 209 OptionSet<WebCore::EventListenerRegionType> eventListenerTypesAtPoint(UIView *rootView, const WebCore::IntPoint& point) 210 { 211 Vector<UIView *, 16> viewsAtPoint; 212 collectDescendantViewsAtPoint(viewsAtPoint, rootView, point, nil); 213 214 if (viewsAtPoint.isEmpty()) 215 return { }; 216 217 UIView *hitView = nil; 218 for (auto *view : WTF::makeReversedRange(viewsAtPoint)) { 219 if ([view isKindOfClass:[WKCompositingView class]]) { 220 hitView = view; 221 break; 222 } 223 } 224 225 if (!hitView) 226 return { }; 227 228 CGPoint hitViewPoint = [hitView convertPoint:point fromView:rootView]; 229 230 auto* node = RemoteLayerTreeNode::forCALayer(hitView.layer); 231 if (!node) 232 return { }; 233 234 return node->eventRegion().eventListenerRegionTypesForPoint(WebCore::IntPoint(hitViewPoint)); 235 } 236 #endif 237 208 238 UIScrollView *findActingScrollParent(UIScrollView *scrollView, const RemoteLayerTreeHost& host) 209 239 { … … 405 435 #endif 406 436 437 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 438 [self _setAllowsAsyncScrollEvent:YES]; 439 #endif 440 407 441 return self; 408 442 } -
trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h
r260366 r270712 66 66 void repositionScrollingLayers(); 67 67 68 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 69 void handleAsynchronousCancelableScrollEvent(UIScrollView *, UIScrollEvent *, void (^completion)(BOOL handled)); 70 #endif 71 68 72 OptionSet<WebCore::TouchAction> activeTouchActions() const { return m_activeTouchActions; } 69 73 void computeActiveTouchActionsForGestureRecognizer(UIGestureRecognizer*); -
trunk/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm
r270390 r270712 177 177 } 178 178 179 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 180 - (void)_scrollView:(UIScrollView *)scrollView asynchronouslyHandleScrollEvent:(UIScrollEvent *)scrollEvent completion:(void (^)(BOOL handled))completion 181 { 182 _scrollingTreeNodeDelegate->handleAsynchronousCancelableScrollEvent(scrollView, scrollEvent, completion); 183 } 184 #endif 185 179 186 - (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view 180 187 { … … 299 306 } 300 307 308 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 309 void ScrollingTreeScrollingNodeDelegateIOS::handleAsynchronousCancelableScrollEvent(UIScrollView *scrollView, UIScrollEvent *scrollEvent, void (^completion)(BOOL handled)) 310 { 311 auto& scrollingCoordinatorProxy = downcast<WebKit::RemoteScrollingTree>(scrollingTree()).scrollingCoordinatorProxy(); 312 scrollingCoordinatorProxy.webPageProxy().pageClient().handleAsynchronousCancelableScrollEvent(scrollView, scrollEvent, completion); 313 } 314 #endif 315 301 316 void ScrollingTreeScrollingNodeDelegateIOS::repositionScrollingLayers() 302 317 { -
trunk/Source/WebKit/UIProcess/WebPageProxy.cpp
r270682 r270712 2639 2639 } 2640 2640 2641 void WebPageProxy::dispatchWheelEventWithoutScrolling(const WebWheelEvent& event, CompletionHandler<void(bool)>&& completionHandler) 2642 { 2643 sendWithAsyncReply(Messages::WebPage::DispatchWheelEventWithoutScrolling(event), WTFMove(completionHandler)); 2644 } 2645 2641 2646 void WebPageProxy::handleWheelEvent(const NativeWebWheelEvent& event) 2642 2647 { -
trunk/Source/WebKit/UIProcess/WebPageProxy.h
r270669 r270712 1847 1847 #endif 1848 1848 1849 void dispatchWheelEventWithoutScrolling(const WebWheelEvent&, CompletionHandler<void(bool)>&&); 1850 1849 1851 private: 1850 1852 WebPageProxy(PageClient&, WebProcessProxy&, Ref<API::PageConfiguration>&&); -
trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h
r269394 r270712 272 272 void showDictationAlternativeUI(const WebCore::FloatRect&, WebCore::DictationContext) final; 273 273 274 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 275 void handleAsynchronousCancelableScrollEvent(UIScrollView *, UIScrollEvent *, void (^completion)(BOOL handled)) final; 276 #endif 277 274 278 WeakObjCPtr<WKContentView> m_contentView; 275 279 RetainPtr<WKEditorUndoTarget> m_undoTarget; -
trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
r269394 r270712 962 962 } 963 963 964 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 965 void PageClientImpl::handleAsynchronousCancelableScrollEvent(UIScrollView *scrollView, UIScrollEvent *scrollEvent, void (^completion)(BOOL handled)) 966 { 967 [m_webView _scrollView:scrollView asynchronouslyHandleScrollEvent:scrollEvent completion:completion]; 968 } 969 #endif 970 964 971 } // namespace WebKit 965 972 -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp
r270710 r270712 2871 2871 } 2872 2872 2873 voidWebPage::wheelEvent(const WebWheelEvent& wheelEvent, OptionSet<WheelEventProcessingSteps> processingSteps)2873 bool WebPage::wheelEvent(const WebWheelEvent& wheelEvent, OptionSet<WheelEventProcessingSteps> processingSteps) 2874 2874 { 2875 2875 m_userActivity.impulse(); … … 2881 2881 if (processingSteps.contains(WheelEventProcessingSteps::MainThreadForScrolling)) 2882 2882 send(Messages::WebPageProxy::DidReceiveEvent(static_cast<uint32_t>(wheelEvent.type()), handled)); 2883 2884 return handled; 2885 } 2886 2887 void WebPage::dispatchWheelEventWithoutScrolling(const WebWheelEvent& wheelEvent, CompletionHandler<void(bool)>&& completionHandler) 2888 { 2889 #if ENABLE(KINETIC_SCROLLING) 2890 auto gestureState = m_page->mainFrame().eventHandler().wheelScrollGestureState(); 2891 bool isCancelable = !gestureState || gestureState == WheelScrollGestureState::Blocking; 2892 #else 2893 bool isCancelable = true; 2894 #endif 2895 bool handled = this->wheelEvent(wheelEvent, { isCancelable ? WheelEventProcessingSteps::MainThreadForBlockingDOMEventDispatch : WheelEventProcessingSteps::MainThreadForNonBlockingDOMEventDispatch }); 2896 completionHandler(handled); 2883 2897 } 2884 2898 -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.h
r270587 r270712 1014 1014 #endif 1015 1015 1016 voidwheelEvent(const WebWheelEvent&, OptionSet<WebCore::WheelEventProcessingSteps>);1016 bool wheelEvent(const WebWheelEvent&, OptionSet<WebCore::WheelEventProcessingSteps>); 1017 1017 1018 1018 void wheelEventHandlersChanged(bool); … … 1371 1371 bool createAppHighlightInSelectedRange(CreateNewGroupForHighlight); 1372 1372 #endif 1373 1374 void dispatchWheelEventWithoutScrolling(const WebWheelEvent&, CompletionHandler<void(bool)>&&); 1373 1375 1374 1376 private: -
trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in
r270512 r270712 622 622 #endif 623 623 624 DispatchWheelEventWithoutScrolling(WebKit::WebWheelEvent event) -> (bool handled) Async 624 625 } -
trunk/Tools/ChangeLog
r270697 r270712 1 2020-12-11 Tim Horton <timothy_horton@apple.com> 2 3 Trackpad and Mouse scroll events on iPad only fire "pointermove" -- not "wheel" 4 https://bugs.webkit.org/show_bug.cgi?id=210071 5 <rdar://problem/54616853> 6 7 Reviewed by Simon Fraser. 8 9 * TestWebKitAPI/Tests/ios/WKScrollViewTests.mm: 10 (-[WKUIScrollEvent initWithPhase:location:delta:]): 11 (-[WKUIScrollEvent phase]): 12 (-[WKUIScrollEvent locationInView:]): 13 (-[WKUIScrollEvent _adjustedAcceleratedDeltaInView:]): 14 (TEST): 15 * TestWebKitAPI/ios/UIKitSPI.h: 16 Add a very simple test that directly calls the new UIScrollViewDelegate SPI 17 and verifies that only the first event is cancelable (unless the first event 18 is canceled, in which case all subsequent events are cancelable). 19 1 20 2020-12-11 Jonathan Bedard <jbedard@apple.com> 2 21 -
trunk/Tools/TestWebKitAPI/Tests/ios/WKScrollViewTests.mm
r260366 r270712 30 30 #import "PlatformUtilities.h" 31 31 #import "TestWKWebView.h" 32 #import "UIKitSPI.h" 32 33 #import <WebKit/WKWebViewPrivate.h> 34 35 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 36 @interface WKUIScrollEvent : UIScrollEvent 37 38 - (instancetype)initWithPhase:(UIScrollPhase)phase location:(CGPoint)location delta:(CGVector)delta; 39 40 @end 41 42 @implementation WKUIScrollEvent { 43 UIScrollPhase _phase; 44 CGPoint _location; 45 CGVector _delta; 46 } 47 48 - (instancetype)initWithPhase:(UIScrollPhase)phase location:(CGPoint)location delta:(CGVector)delta 49 { 50 self = [super init]; 51 if (!self) 52 return nil; 53 54 _phase = phase; 55 _location = location; 56 _delta = delta; 57 58 return self; 59 } 60 61 - (UIScrollPhase)phase 62 { 63 return _phase; 64 } 65 66 - (CGPoint)locationInView:(UIView *)view 67 { 68 return _location; 69 } 70 71 - (CGVector)_adjustedAcceleratedDeltaInView:(UIView *)view 72 { 73 return _delta; 74 } 75 76 @end 77 #endif // HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 33 78 34 79 static void traverseLayerTree(CALayer *layer, void(^block)(CALayer *)) … … 72 117 } 73 118 119 #if HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 120 TEST(WKScrollViewTests, AsynchronousWheelEventHandling) 121 { 122 auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)]); 123 [webView synchronouslyLoadHTMLString:@"" 124 "<style>#handler { width: 200px; height: 200px; }</style>" 125 "<div id='handler'></div>" 126 "<script>window.preventDefaultOnScrollEvents = false;" 127 "document.getElementById('handler').addEventListener('wheel', " 128 "function (e) {" 129 " window.lastWheelEvent = e;" 130 " if (window.preventDefaultOnScrollEvents)" 131 " e.preventDefault();" 132 "})</script>"]; 133 [webView waitForNextPresentationUpdate]; 134 135 __block bool done; 136 __block bool wasHandled; 137 138 auto synchronouslyHandleScrollEvent = ^(UIScrollPhase phase, CGPoint location, CGVector delta) { 139 done = false; 140 auto event = adoptNS([[WKUIScrollEvent alloc] initWithPhase:phase location:location delta:delta]); 141 [webView _scrollView:[webView scrollView] asynchronouslyHandleScrollEvent:event.get() completion:^(BOOL handled) { 142 wasHandled = handled; 143 done = true; 144 }]; 145 TestWebKitAPI::Util::run(&done); 146 }; 147 148 // Don't preventDefault() at all. 149 synchronouslyHandleScrollEvent(UIScrollPhaseMayBegin, CGPointMake(100, 100), CGVectorMake(0, 0)); 150 EXPECT_FALSE(wasHandled); 151 synchronouslyHandleScrollEvent(UIScrollPhaseBegan, CGPointMake(100, 100), CGVectorMake(0, 10)); 152 EXPECT_FALSE(wasHandled); 153 EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"window.lastWheelEvent.cancelable"] intValue]); 154 EXPECT_EQ(-10, [[webView objectByEvaluatingJavaScript:@"window.lastWheelEvent.deltaY"] intValue]); 155 synchronouslyHandleScrollEvent(UIScrollPhaseChanged, CGPointMake(100, 100), CGVectorMake(0, 10)); 156 EXPECT_FALSE(wasHandled); 157 synchronouslyHandleScrollEvent(UIScrollPhaseEnded, CGPointMake(100, 100), CGVectorMake(0, 0)); 158 EXPECT_FALSE(wasHandled); 159 160 // preventDefault() on all events. 161 [webView stringByEvaluatingJavaScript:@"window.preventDefaultOnScrollEvents = true;"]; 162 synchronouslyHandleScrollEvent(UIScrollPhaseMayBegin, CGPointMake(100, 100), CGVectorMake(0, 0)); 163 EXPECT_FALSE(wasHandled); 164 synchronouslyHandleScrollEvent(UIScrollPhaseBegan, CGPointMake(100, 100), CGVectorMake(0, 10)); 165 EXPECT_TRUE(wasHandled); 166 synchronouslyHandleScrollEvent(UIScrollPhaseChanged, CGPointMake(100, 100), CGVectorMake(0, 10)); 167 EXPECT_TRUE(wasHandled); 168 synchronouslyHandleScrollEvent(UIScrollPhaseEnded, CGPointMake(100, 100), CGVectorMake(0, 0)); 169 EXPECT_FALSE(wasHandled); 170 171 // preventDefault() on all but the begin event; it will be ignored. 172 [webView stringByEvaluatingJavaScript:@"window.preventDefaultOnScrollEvents = false;"]; 173 synchronouslyHandleScrollEvent(UIScrollPhaseMayBegin, CGPointMake(100, 100), CGVectorMake(0, 0)); 174 EXPECT_FALSE(wasHandled); 175 synchronouslyHandleScrollEvent(UIScrollPhaseBegan, CGPointMake(100, 100), CGVectorMake(0, 10)); 176 EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"window.lastWheelEvent.cancelable"] intValue]); 177 EXPECT_FALSE(wasHandled); 178 [webView stringByEvaluatingJavaScript:@"window.preventDefaultOnScrollEvents = true;"]; 179 synchronouslyHandleScrollEvent(UIScrollPhaseChanged, CGPointMake(100, 100), CGVectorMake(0, 10)); 180 EXPECT_FALSE(wasHandled); 181 EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"window.lastWheelEvent.cancelable"] intValue]); 182 synchronouslyHandleScrollEvent(UIScrollPhaseEnded, CGPointMake(100, 100), CGVectorMake(0, 0)); 183 EXPECT_FALSE(wasHandled); 184 185 // preventDefault() on the begin event, and some subsequent events. 186 [webView stringByEvaluatingJavaScript:@"window.preventDefaultOnScrollEvents = true;"]; 187 synchronouslyHandleScrollEvent(UIScrollPhaseMayBegin, CGPointMake(100, 100), CGVectorMake(0, 0)); 188 EXPECT_FALSE(wasHandled); 189 synchronouslyHandleScrollEvent(UIScrollPhaseBegan, CGPointMake(100, 100), CGVectorMake(0, 10)); 190 EXPECT_TRUE(wasHandled); 191 synchronouslyHandleScrollEvent(UIScrollPhaseChanged, CGPointMake(100, 100), CGVectorMake(0, 10)); 192 EXPECT_TRUE(wasHandled); 193 [webView stringByEvaluatingJavaScript:@"window.preventDefaultOnScrollEvents = false;"]; 194 synchronouslyHandleScrollEvent(UIScrollPhaseChanged, CGPointMake(100, 100), CGVectorMake(0, 10)); 195 EXPECT_FALSE(wasHandled); 196 synchronouslyHandleScrollEvent(UIScrollPhaseEnded, CGPointMake(100, 100), CGVectorMake(0, 0)); 197 EXPECT_FALSE(wasHandled); 198 } 199 #endif // HAVE(UISCROLLVIEW_ASYNCHRONOUS_SCROLL_EVENT_HANDLING) 200 74 201 #endif // PLATFORM(IOS_FAMILY) -
trunk/Tools/TestWebKitAPI/ios/UIKitSPI.h
r270565 r270712 38 38 #import <UIKit/UIResponder_Private.h> 39 39 #import <UIKit/UIScreen_Private.h> 40 #import <UIKit/UIScrollEvent_Private.h> 41 #import <UIKit/UIScrollView_ForWebKitOnly.h> 40 42 #import <UIKit/UIScrollView_Private.h> 41 43 #import <UIKit/UITextAutofillSuggestion.h> … … 241 243 @end 242 244 245 @interface UIScrollEvent : UIEvent 246 @end 247 248 @interface NSObject (UIScrollViewDelegate_ForWebKitOnly) 249 - (void)_scrollView:(UIScrollView *)scrollView asynchronouslyHandleScrollEvent:(UIScrollEvent *)scrollEvent completion:(void (^)(BOOL handled))completion; 250 @end 251 243 252 #endif // USE(APPLE_INTERNAL_SDK) 244 253
Note: See TracChangeset
for help on using the changeset viewer.