WKInteractionView always blocks the main thread when sending touch events
authorbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Feb 2014 05:22:51 +0000 (05:22 +0000)
committerbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 21 Feb 2014 05:22:51 +0000 (05:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=129059

Patch by Benjamin Poulain <bpoulain@apple.com> on 2014-02-20
Reviewed by Enrica Casucci.

Add the asynchronous dispatching to WebKit2.

* Shared/NativeWebTouchEvent.h:
(WebKit::NativeWebTouchEvent::uniqueId):
* Shared/ios/NativeWebTouchEventIOS.mm:
(WebKit::NativeWebTouchEvent::NativeWebTouchEvent):
* UIProcess/API/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::doneWithTouchEvent):
* UIProcess/API/ios/WKContentView.h:
* UIProcess/API/ios/WKContentView.mm:
(-[WKContentView willStartUserTriggeredScroll]):
(-[WKContentView willStartUserTriggeredZoom]):
(-[WKContentView _webTouchEvent:WebKit::preventsNativeGestures:]):
* UIProcess/API/ios/WKContentViewInternal.h:
* UIProcess/API/ios/WKInteractionView.h:
* UIProcess/API/ios/WKInteractionView.mm:
(-[WKInteractionView _webTouchEventsRecognized:]):
(-[WKInteractionView _webTouchEvent:WebKit::preventsNativeGestures:]):
(-[WKInteractionView _willStartUserTriggeredScrollingOrZooming]):
* UIProcess/API/ios/WKViewIOS.mm:
(-[WKView scrollViewWillBeginDragging:]):
* WebKit2.xcodeproj/project.pbxproj:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@164469 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/Shared/NativeWebTouchEvent.h
Source/WebKit2/Shared/ios/NativeWebTouchEventIOS.mm
Source/WebKit2/UIProcess/API/ios/PageClientImplIOS.mm
Source/WebKit2/UIProcess/API/ios/WKContentView.h
Source/WebKit2/UIProcess/API/ios/WKContentView.mm
Source/WebKit2/UIProcess/API/ios/WKContentViewInternal.h
Source/WebKit2/UIProcess/API/ios/WKInteractionView.h
Source/WebKit2/UIProcess/API/ios/WKInteractionView.mm
Source/WebKit2/UIProcess/API/ios/WKViewIOS.mm
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj

index ab96888..acea5ba 100644 (file)
@@ -1,5 +1,35 @@
 2014-02-20  Benjamin Poulain  <bpoulain@apple.com>
 
+        WKInteractionView always blocks the main thread when sending touch events
+        https://bugs.webkit.org/show_bug.cgi?id=129059
+
+        Reviewed by Enrica Casucci.
+
+        Add the asynchronous dispatching to WebKit2.
+
+        * Shared/NativeWebTouchEvent.h:
+        (WebKit::NativeWebTouchEvent::uniqueId):
+        * Shared/ios/NativeWebTouchEventIOS.mm:
+        (WebKit::NativeWebTouchEvent::NativeWebTouchEvent):
+        * UIProcess/API/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::doneWithTouchEvent):
+        * UIProcess/API/ios/WKContentView.h:
+        * UIProcess/API/ios/WKContentView.mm:
+        (-[WKContentView willStartUserTriggeredScroll]):
+        (-[WKContentView willStartUserTriggeredZoom]):
+        (-[WKContentView _webTouchEvent:WebKit::preventsNativeGestures:]):
+        * UIProcess/API/ios/WKContentViewInternal.h:
+        * UIProcess/API/ios/WKInteractionView.h:
+        * UIProcess/API/ios/WKInteractionView.mm:
+        (-[WKInteractionView _webTouchEventsRecognized:]):
+        (-[WKInteractionView _webTouchEvent:WebKit::preventsNativeGestures:]):
+        (-[WKInteractionView _willStartUserTriggeredScrollingOrZooming]):
+        * UIProcess/API/ios/WKViewIOS.mm:
+        (-[WKView scrollViewWillBeginDragging:]):
+        * WebKit2.xcodeproj/project.pbxproj:
+
+2014-02-20  Benjamin Poulain  <bpoulain@apple.com>
+
         Start fixing the view states driven by the WKScrollView
         https://bugs.webkit.org/show_bug.cgi?id=129140
 
index ef5bf65..2a1339a 100644 (file)
@@ -46,7 +46,7 @@ class NativeWebTouchEvent : public WebTouchEvent {
 public:
 #if PLATFORM(IOS)
     explicit NativeWebTouchEvent(UIWebTouchEventsGestureRecognizer *);
-    const UIWebTouchEventsGestureRecognizer* nativeEvent() const { return m_nativeEvent.get(); }
+    unsigned uniqueId() const { return m_uniqueID; }
 #elif PLATFORM(GTK)
     NativeWebTouchEvent(const NativeWebTouchEvent&);
     NativeWebTouchEvent(GdkEvent*, WebCore::GtkTouchContextHelper&);
@@ -59,7 +59,7 @@ public:
 
 private:
 #if PLATFORM(IOS)
-    RetainPtr<UIWebTouchEventsGestureRecognizer> m_nativeEvent;
+    unsigned m_uniqueID;
 #elif PLATFORM(GTK)
     GUniquePtr<GdkEvent> m_nativeEvent;
     const WebCore::GtkTouchContextHelper& m_touchContext;
index f20b000..1a020aa 100644 (file)
@@ -35,6 +35,8 @@
 
 namespace WebKit {
 
+static unsigned uniqueTouchEventIdIndex = 0;
+
 static inline WebEvent::Type webEventTypeForUIWebTouchEventType(UIWebTouchEventType type)
 {
     switch (type) {
@@ -95,7 +97,7 @@ static inline Vector<WebPlatformTouchPoint> extractWebTouchPoint(UIWebTouchEvent
 
 NativeWebTouchEvent::NativeWebTouchEvent(UIWebTouchEventsGestureRecognizer *gestureRecognizer)
     : WebTouchEvent(webEventTypeForUIWebTouchEventType(gestureRecognizer.type), static_cast<Modifiers>(0), WTF::currentTime(), extractWebTouchPoint(gestureRecognizer), positionForCGPoint(gestureRecognizer.locationInWindow), gestureRecognizer.inJavaScriptGesture, gestureRecognizer.scale, gestureRecognizer.rotation)
-    , m_nativeEvent(gestureRecognizer)
+    , m_uniqueID(uniqueTouchEventIdIndex++)
 {
 }
 
index ad5229b..9aa27cd 100644 (file)
@@ -276,7 +276,7 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent&, bool)
 #if ENABLE(TOUCH_EVENTS)
 void PageClientImpl::doneWithTouchEvent(const NativeWebTouchEvent& nativeWebtouchEvent, bool eventHandled)
 {
-    [nativeWebtouchEvent.nativeEvent() setDefaultPrevented:eventHandled];
+    [m_view _webTouchEvent:nativeWebtouchEvent preventsNativeGestures:eventHandled];
 }
 #endif
 
index 075fadd..068886f 100644 (file)
@@ -67,6 +67,7 @@ WK_API_CLASS
 - (void)didFinishScrolling;
 - (void)didZoomToScale:(CGFloat)scale;
 - (void)willStartZoomOrScroll;
+- (void)willStartUserTriggeredScroll;
 - (void)willStartUserTriggeredZoom;
 
 @end
index f22bc62..b716b50 100644 (file)
@@ -199,8 +199,14 @@ using namespace WebKit;
     [_interactionView _willStartScrollingOrZooming];
 }
 
+- (void)willStartUserTriggeredScroll
+{
+    [_interactionView _willStartUserTriggeredScrollingOrZooming];
+}
+
 - (void)willStartUserTriggeredZoom
 {
+    [_interactionView _willStartUserTriggeredScrollingOrZooming];
     _page->willStartUserTriggeredZooming();
 }
 
@@ -261,6 +267,11 @@ using namespace WebKit;
         [_delegate contentView:self didCommitLayerTree:layerTreeTransaction];
 }
 
+- (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&)touchEvent preventsNativeGestures:(BOOL)preventsNativeGesture
+{
+    [_interactionView _webTouchEvent:touchEvent preventsNativeGestures:preventsNativeGesture];
+}
+
 - (void)_didGetTapHighlightForRequest:(uint64_t)requestID color:(const Color&)color quads:(const Vector<FloatQuad>&)highlightedQuads topLeftRadius:(const IntSize&)topLeftRadius topRightRadius:(const IntSize&)topRightRadius bottomLeftRadius:(const IntSize&)bottomLeftRadius bottomRightRadius:(const IntSize&)bottomRightRadius
 {
     [_interactionView _didGetTapHighlightForRequest:requestID color:color quads:highlightedQuads topLeftRadius:topLeftRadius topRightRadius:topRightRadius bottomLeftRadius:bottomLeftRadius bottomRightRadius:bottomRightRadius];
index e1aa295..5247dcb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -39,6 +39,7 @@ namespace WebKit {
 class DrawingAreaProxy;
 class GeolocationPermissionRequestProxy;
 class LayerTreeContext;
+class NativeWebTouchEvent;
 class RemoteLayerTreeTransaction;
 class WebFrameProxy;
 class WebPageProxy;
@@ -61,6 +62,7 @@ struct InteractionInformationAtPosition;
 - (void)_didCommitLoadForMainFrame;
 - (void)_didCommitLayerTree:(const WebKit::RemoteLayerTreeTransaction&)layerTreeTransaction;
 
+- (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&)touchEvent preventsNativeGestures:(BOOL)preventsDefault;
 - (void)_didGetTapHighlightForRequest:(uint64_t)requestID color:(const WebCore::Color&)color quads:(const Vector<WebCore::FloatQuad>&)highlightedQuads topLeftRadius:(const WebCore::IntSize&)topLeftRadius topRightRadius:(const WebCore::IntSize&)topRightRadius bottomLeftRadius:(const WebCore::IntSize&)bottomLeftRadius bottomRightRadius:(const WebCore::IntSize&)bottomRightRadius;
 
 - (void)_startAssistingNode;
index 69ad6c2..6145f50 100644 (file)
@@ -42,6 +42,7 @@ class IntSize;
 }
 
 namespace WebKit {
+class NativeWebTouchEvent;
 class WebPageProxy;
 struct InteractionInformationAtPosition;
 }
@@ -55,6 +56,7 @@ struct InteractionInformationAtPosition;
 - (void)setScrollView:(UIWebScrollView *)scrollView;
 - (void)setPage:(PassRefPtr<WebKit::WebPageProxy>)page;
 
+- (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&)touchEvent preventsNativeGestures:(BOOL)preventsDefault;
 - (void)_didGetTapHighlightForRequest:(uint64_t)requestID color:(const WebCore::Color&)color quads:(const Vector<WebCore::FloatQuad>&)highlightedQuads topLeftRadius:(const WebCore::IntSize&)topLeftRadius topRightRadius:(const WebCore::IntSize&)topRightRadius bottomLeftRadius:(const WebCore::IntSize&)bottomLeftRadius bottomRightRadius:(const WebCore::IntSize&)bottomRightRadius;
 
 - (void)_startAssistingNode;
@@ -66,6 +68,7 @@ struct InteractionInformationAtPosition;
 - (void)_updatePositionInformation;
 - (void)_performAction:(WebKit::WKSheetActions)action;
 - (void)_willStartScrollingOrZooming;
+- (void)_willStartUserTriggeredScrollingOrZooming;
 - (void)_didEndScrollingOrZooming;
 @property (readonly, nonatomic) WebKit::InteractionInformationAtPosition positionInformation;
 @end
index 14d4441..710e2e4 100644 (file)
@@ -148,6 +148,9 @@ struct WKAutoCorrectionData{
 
 @implementation WKInteractionView {
     RetainPtr<UIWebTouchEventsGestureRecognizer> _touchEventGestureRecognizer;
+    BOOL _canSendTouchEventsAsynchronously;
+    unsigned _nativeWebTouchEventUniqueIdBeingSentSynchronously;
+
     RetainPtr<UITapGestureRecognizer> _singleTapGestureRecognizer;
     RetainPtr<_UIWebHighlightLongPressGestureRecognizer> _highlightLongPressGestureRecognizer;
     RetainPtr<UILongPressGestureRecognizer> _longPressGestureRecognizer;
@@ -279,8 +282,13 @@ struct WKAutoCorrectionData{
 {
     NativeWebTouchEvent nativeWebTouchEvent(gestureRecognizer);
 
-    // FIXME: this kind of event delivery is supposed to be only used for testing. We must switch to asynchronous handling.
-    _page->setShouldSendEventsSynchronously(true);
+    if (nativeWebTouchEvent.type() == WebKit::WebEvent::TouchStart)
+        _canSendTouchEventsAsynchronously = NO;
+
+    if (!_canSendTouchEventsAsynchronously)
+        _nativeWebTouchEventUniqueIdBeingSentSynchronously = nativeWebTouchEvent.uniqueId();
+
+    _page->setShouldSendEventsSynchronously(!_canSendTouchEventsAsynchronously);
     _page->handleTouchEvent(nativeWebTouchEvent);
     _page->setShouldSendEventsSynchronously(false);
 }
@@ -322,6 +330,20 @@ static FloatQuad inflateQuad(const FloatQuad& quad, float inflateSize)
     return FloatQuad(points[1], points[0], points[2], points[3]);
 }
 
+- (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&)touchEvent preventsNativeGestures:(BOOL)preventsNativeGesture
+{
+    if (preventsNativeGesture) {
+        // If we are dispatching events synchronously and the event coming back is not the one we are sending, it is a callback
+        // from an event sent asynchronously prior to the synchronous event. In that case, it should not use that information
+        // to update UIWebTouchEventsGestureRecognizer.
+        if (!_canSendTouchEventsAsynchronously && _nativeWebTouchEventUniqueIdBeingSentSynchronously != touchEvent.uniqueId())
+            return;
+
+        _canSendTouchEventsAsynchronously = YES;
+        [_touchEventGestureRecognizer setDefaultPrevented:YES];
+    }
+}
+
 - (void)_didGetTapHighlightForRequest:(uint64_t)requestID color:(const WebCore::Color&)color quads:(const Vector<WebCore::FloatQuad>&)highlightedQuads topLeftRadius:(const WebCore::IntSize&)topLeftRadius topRightRadius:(const WebCore::IntSize&)topRightRadius bottomLeftRadius:(const WebCore::IntSize&)bottomLeftRadius bottomRightRadius:(const WebCore::IntSize&)bottomRightRadius
 {
     if (!_isTapHighlightIDValid || _latestTapHighlightID != requestID)
@@ -685,6 +707,11 @@ static inline bool isSamePair(UIGestureRecognizer *a, UIGestureRecognizer *b, UI
     [_textSelectionAssistant willStartScrollingOverflow];
 }
 
+- (void)_willStartUserTriggeredScrollingOrZooming
+{
+    _canSendTouchEventsAsynchronously = YES;
+}
+
 - (void)_didEndScrollingOrZooming
 {
     [_webSelectionAssistant didEndScrollingOrZoomingPage];
index eabd95e..829199e 100644 (file)
@@ -190,6 +190,8 @@ using namespace WebKit;
 
 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
 {
+    if (scrollView.panGestureRecognizer.state == UIGestureRecognizerStateBegan)
+        [_contentView willStartUserTriggeredScroll];
     [_contentView willStartZoomOrScroll];
 }
 
index 8bb36a4..de9aac1 100644 (file)
                1FB00AC9185F76460019142E /* WKWebProcessPlugInPageGroupInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 1FB00AC6185F76460019142E /* WKWebProcessPlugInPageGroupInternal.h */; };
                1QQ417CB12C00CCA002BE67B /* TextCheckerCompletion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CC417C912C00CCA002BE67B /* TextCheckerCompletion.h */; };
                1ZZ417EF12C00D87002BE67B /* TextCheckerCompletion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1BB417C912C00CCA002BE67B /* TextCheckerCompletion.cpp */; };
+               263172CF18B469490065B9C3 /* NativeWebTouchEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 263172CE18B469490065B9C3 /* NativeWebTouchEvent.h */; };
                26F9A83B18A3468100AEB88A /* WKWebViewPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 26F9A83A18A3463F00AEB88A /* WKWebViewPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                290F4272172A0C7400939FF0 /* ChildProcessSupplement.h in Headers */ = {isa = PBXBuildFile; fileRef = 290F4271172A0C7400939FF0 /* ChildProcessSupplement.h */; };
                293EBEAB1627D9C9005F89F1 /* WKDOMText.h in Headers */ = {isa = PBXBuildFile; fileRef = 293EBEA91627D9C9005F89F1 /* WKDOMText.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1FB00AC4185F76460019142E /* WKWebProcessPlugInPageGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebProcessPlugInPageGroup.h; sourceTree = "<group>"; };
                1FB00AC5185F76460019142E /* WKWebProcessPlugInPageGroup.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKWebProcessPlugInPageGroup.mm; sourceTree = "<group>"; };
                1FB00AC6185F76460019142E /* WKWebProcessPlugInPageGroupInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKWebProcessPlugInPageGroupInternal.h; sourceTree = "<group>"; };
+               263172CE18B469490065B9C3 /* NativeWebTouchEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeWebTouchEvent.h; sourceTree = "<group>"; };
                26659AA0185FAAED004303DD /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = "<group>"; };
                26F9A83A18A3463F00AEB88A /* WKWebViewPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKWebViewPrivate.h; sourceTree = "<group>"; };
                290F4271172A0C7400939FF0 /* ChildProcessSupplement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChildProcessSupplement.h; sourceTree = "<group>"; };
                                1ADCB869189831B30022EE5A /* NavigationActionData.h */,
                                C02BFF1512514FD8009CCBEA /* NativeWebKeyboardEvent.h */,
                                31EA25D3134F78D6005B1452 /* NativeWebMouseEvent.h */,
+                               263172CE18B469490065B9C3 /* NativeWebTouchEvent.h */,
                                DF58C6311371AC5800F9A37C /* NativeWebWheelEvent.h */,
                                BCCF673212C7F15C008F9C35 /* OriginAndDatabases.cpp */,
                                BCCF672C12C7EDF7008F9C35 /* OriginAndDatabases.h */,
                                377EAD4517E2C51A002D193D /* WKDeclarationSpecifiers.h in Headers */,
                                1FB00AC7185F76460019142E /* WKWebProcessPlugInPageGroup.h in Headers */,
                                377EAD4917E2C77B002D193D /* WKUserScriptInjectionTime.h in Headers */,
+                               263172CF18B469490065B9C3 /* NativeWebTouchEvent.h in Headers */,
                                1F7506B21859163E00EC0FF7 /* WKWebProcessPlugInHitTestResult.h in Headers */,
                                1F7506B11859163700EC0FF7 /* WKWebProcessPlugInFrame.h in Headers */,
                                BC59548915C7868500FD1E3E /* WebKit2.h in Headers */,