[iOS WK2] Make -webkit-overflow-scrolling:touch work
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 24 Apr 2014 03:31:30 +0000 (03:31 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 24 Apr 2014 03:31:30 +0000 (03:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=132097

Reviewed by Tim Horton.

Scrolling of UIScrollViews in content (for -webkit-overflow-scrolling:touch)
depends on them getting hit-tested correctly. UIKit hit testing assumes
that subviews are enclosed by their ancestors, but this is not true of
web content. In addition, we had a root layer that was zero sized.

Fix by overriding hitTest:withEvent: on our content WKViews to hit
test subviews even if they are not enclosed.

* UIProcess/ios/RemoteLayerTreeHostIOS.mm:
(-[UIView _recursiveFindDescendantViewAtPoint:withEvent:]):
(-[UIView _findDescendantViewAtPoint:withEvent:]):
(-[WKCompositingView hitTest:withEvent:]):
(-[WKTransformView hitTest:withEvent:]):
(-[WKRemoteView hitTest:withEvent:]):
(WebKit::RemoteLayerTreeHost::createLayer):
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::updatePreferences):
Update debug borders on the root layer.
(WebKit::RemoteLayerTreeDrawingArea::mainFrameContentSizeChanged):
Size the root layer to the contents size. This isn't strictly necessary
given the hit testing overrides, but seems sensible to do anyway.

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

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/ios/RemoteLayerTreeHostIOS.mm
Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm

index 2bd5e25..1e682bd 100644 (file)
@@ -1,5 +1,34 @@
 2014-04-23  Simon Fraser  <simon.fraser@apple.com>
 
+        [iOS WK2] Make -webkit-overflow-scrolling:touch work
+        https://bugs.webkit.org/show_bug.cgi?id=132097
+
+        Reviewed by Tim Horton.
+        
+        Scrolling of UIScrollViews in content (for -webkit-overflow-scrolling:touch)
+        depends on them getting hit-tested correctly. UIKit hit testing assumes
+        that subviews are enclosed by their ancestors, but this is not true of
+        web content. In addition, we had a root layer that was zero sized.
+        
+        Fix by overriding hitTest:withEvent: on our content WKViews to hit
+        test subviews even if they are not enclosed.
+
+        * UIProcess/ios/RemoteLayerTreeHostIOS.mm:
+        (-[UIView _recursiveFindDescendantViewAtPoint:withEvent:]):
+        (-[UIView _findDescendantViewAtPoint:withEvent:]):
+        (-[WKCompositingView hitTest:withEvent:]):
+        (-[WKTransformView hitTest:withEvent:]):
+        (-[WKRemoteView hitTest:withEvent:]):
+        (WebKit::RemoteLayerTreeHost::createLayer):
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
+        (WebKit::RemoteLayerTreeDrawingArea::updatePreferences):
+        Update debug borders on the root layer.
+        (WebKit::RemoteLayerTreeDrawingArea::mainFrameContentSizeChanged):
+        Size the root layer to the contents size. This isn't strictly necessary
+        given the hit testing overrides, but seems sensible to do anyway.
+
+2014-04-23  Simon Fraser  <simon.fraser@apple.com>
+
         Nonopaque layers double-paint with UI-side compositing
         https://bugs.webkit.org/show_bug.cgi?id=132101
 
index f638ef9..44cc000 100644 (file)
@@ -41,6 +41,53 @@ using namespace WebCore;
 - (void)setContextId:(uint32_t)contextID;
 @end
 
+@interface UIView (WKHitTesting)
+- (UIView *)_findDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event;
+@end
+
+@implementation UIView (WKHitTesting)
+
+// UIView hit testing assumes that views should only hit test subviews that are entirely contained
+// in the view. This is not true of web content.
+- (UIView *)_recursiveFindDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event
+{
+    if (self.clipsToBounds && ![self pointInside:point withEvent:event])
+        return nil;
+
+    __block UIView *foundView = nil;
+    [[self subviews] enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
+        CGPoint subviewPoint = [view convertPoint:point fromView:self];
+
+        if ([view pointInside:subviewPoint withEvent:event])
+            foundView = view;
+
+        if (![view subviews])
+            return;
+
+        if (UIView *hitView = [view _recursiveFindDescendantViewAtPoint:subviewPoint withEvent:event])
+            foundView = hitView;
+    }];
+
+    return foundView;
+}
+
+- (UIView *)_findDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event
+{
+    return [self _recursiveFindDescendantViewAtPoint:point withEvent:event];
+}
+
+@end
+
+@interface WKCompositingView : UIView
+@end
+
+@implementation WKCompositingView
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
+{
+    return [self _findDescendantViewAtPoint:point withEvent:event];
+}
+@end
+
 @interface WKTransformView : UIView
 @end
 
@@ -49,6 +96,11 @@ using namespace WebCore;
 {
     return [CATransformLayer self];
 }
+
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
+{
+    return [self _findDescendantViewAtPoint:point withEvent:event];
+}
 @end
 
 @interface WKRemoteView : UIView
@@ -68,6 +120,12 @@ using namespace WebCore;
 {
     return NSClassFromString(@"CALayerHost");
 }
+
+- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
+{
+    return [self _findDescendantViewAtPoint:point withEvent:event];
+}
+
 @end
 
 namespace WebKit {
@@ -89,7 +147,7 @@ LayerOrView *RemoteLayerTreeHost::createLayer(const RemoteLayerTreeTransaction::
         if (layerProperties && layerProperties->customBehavior == GraphicsLayer::CustomScrollingBehavior)
             layerOrView = adoptNS([[UIScrollView alloc] init]);
         else
-            layerOrView = adoptNS([[UIView alloc] init]);
+            layerOrView = adoptNS([[WKCompositingView alloc] init]);
         break;
     case PlatformCALayer::LayerTypeTransformLayer:
         layerOrView = adoptNS([[WKTransformView alloc] init]);
@@ -98,7 +156,7 @@ LayerOrView *RemoteLayerTreeHost::createLayer(const RemoteLayerTreeTransaction::
         if (!m_isDebugLayerTreeHost)
             layerOrView = adoptNS([[WKRemoteView alloc] initWithFrame:CGRectZero contextID:properties.hostingContextID]);
         else
-            layerOrView = adoptNS([[UIView alloc] init]);
+            layerOrView = adoptNS([[WKCompositingView alloc] init]);
         break;
     default:
         ASSERT_NOT_REACHED();
index 1d0cd8f..967dcb2 100644 (file)
@@ -119,6 +119,8 @@ void RemoteLayerTreeDrawingArea::updatePreferences(const WebPreferencesStore&)
     // in order to be scrolled by the ScrollingCoordinator.
     settings.setAcceleratedCompositingForFixedPositionEnabled(true);
     settings.setFixedPositionCreatesStackingContext(true);
+
+    m_rootLayer->setShowDebugBorder(settings.showDebugBorders());
 }
 
 #if PLATFORM(IOS)
@@ -295,8 +297,9 @@ void RemoteLayerTreeDrawingArea::didUpdate()
     }
 }
 
-void RemoteLayerTreeDrawingArea::mainFrameContentSizeChanged(const IntSize&)
+void RemoteLayerTreeDrawingArea::mainFrameContentSizeChanged(const IntSize& contentsSize)
 {
+    m_rootLayer->setSize(contentsSize);
     m_webPage->pageOverlayController().didChangeDocumentSize();
 }