1/* 2 * Copyright (C) 2014 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#import "config.h" 27 28#if PLATFORM(IOS) 29 30#import "RemoteLayerTreeHost.h" 31#import <QuartzCore/QuartzCore.h> 32#import <UIKit/UIScrollView.h> 33#import <WebKitSystemInterface.h> 34 35using namespace WebCore; 36 37@interface CALayer(WKLayerInternal) 38- (void)setContextId:(uint32_t)contextID; 39@end 40 41@interface UIView (WKHitTesting) 42- (UIView *)_findDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event; 43@end 44 45@implementation UIView (WKHitTesting) 46 47// UIView hit testing assumes that views should only hit test subviews that are entirely contained 48// in the view. This is not true of web content. 49// We only want to find UIScrollViews here. Other views are ignored. 50- (UIView *)_recursiveFindDescendantScrollViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event 51{ 52 if (self.clipsToBounds && ![self pointInside:point withEvent:event]) 53 return nil; 54 55 __block UIView *foundView = nil; 56 [[self subviews] enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) { 57 CGPoint subviewPoint = [view convertPoint:point fromView:self]; 58 59 if ([view pointInside:subviewPoint withEvent:event] && [view isKindOfClass:[UIScrollView class]]) 60 foundView = view; 61 62 if (![view subviews]) 63 return; 64 65 if (UIView *hitView = [view _recursiveFindDescendantScrollViewAtPoint:subviewPoint withEvent:event]) 66 foundView = hitView; 67 }]; 68 69 return foundView; 70} 71 72- (UIView *)_findDescendantViewAtPoint:(CGPoint)point withEvent:(UIEvent *)event 73{ 74 return [self _recursiveFindDescendantScrollViewAtPoint:point withEvent:event]; 75} 76 77@end 78 79@interface WKCompositingView : UIView 80@end 81 82@implementation WKCompositingView 83- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event 84{ 85 return [self _findDescendantViewAtPoint:point withEvent:event]; 86} 87 88- (NSString *)description 89{ 90 NSString *viewDescription = [super description]; 91 NSString *webKitDetails = [NSString stringWithFormat:@" layerID = %llu \"%@\"", WebKit::RemoteLayerTreeHost::layerID(self.layer), self.layer.name ? self.layer.name : @""]; 92 return [viewDescription stringByAppendingString:webKitDetails]; 93} 94@end 95 96@interface WKTransformView : WKCompositingView 97@end 98 99@implementation WKTransformView 100+ (Class)layerClass 101{ 102 return [CATransformLayer self]; 103} 104 105@end 106 107@interface WKRemoteView : WKCompositingView 108@end 109 110@implementation WKRemoteView 111- (instancetype)initWithFrame:(CGRect)frame contextID:(uint32_t)contextID 112{ 113 if ((self = [super initWithFrame:frame])) { 114 [[self layer] setContextId:contextID]; 115 } 116 117 return self; 118} 119 120+ (Class)layerClass 121{ 122 return NSClassFromString(@"CALayerHost"); 123} 124 125@end 126 127namespace WebKit { 128 129LayerOrView *RemoteLayerTreeHost::createLayer(const RemoteLayerTreeTransaction::LayerCreationProperties& properties, const RemoteLayerTreeTransaction::LayerProperties* layerProperties) 130{ 131 RetainPtr<LayerOrView>& view = m_layers.add(properties.layerID, nullptr).iterator->value; 132 133 ASSERT(!view); 134 135 switch (properties.type) { 136 case PlatformCALayer::LayerTypeLayer: 137 case PlatformCALayer::LayerTypeWebLayer: 138 case PlatformCALayer::LayerTypeRootLayer: 139 case PlatformCALayer::LayerTypeSimpleLayer: 140 case PlatformCALayer::LayerTypeTiledBackingLayer: 141 case PlatformCALayer::LayerTypePageTiledBackingLayer: 142 case PlatformCALayer::LayerTypeTiledBackingTileLayer: 143 if (layerProperties && layerProperties->customBehavior == GraphicsLayer::CustomScrollingBehavior) { 144 if (!m_isDebugLayerTreeHost) 145 view = adoptNS([[UIScrollView alloc] init]); 146 else // The debug indicator parents views under layers, which can cause crashes with UIScrollView. 147 view = adoptNS([[UIView alloc] init]); 148 } else 149 view = adoptNS([[WKCompositingView alloc] init]); 150 break; 151 case PlatformCALayer::LayerTypeTransformLayer: 152 view = adoptNS([[WKTransformView alloc] init]); 153 break; 154 case PlatformCALayer::LayerTypeCustom: 155 case PlatformCALayer::LayerTypeAVPlayerLayer: 156 case PlatformCALayer::LayerTypeWebGLLayer: 157 if (!m_isDebugLayerTreeHost) 158 view = adoptNS([[WKRemoteView alloc] initWithFrame:CGRectZero contextID:properties.hostingContextID]); 159 else 160 view = adoptNS([[WKCompositingView alloc] init]); 161 break; 162 default: 163 ASSERT_NOT_REACHED(); 164 } 165 166 setLayerID([view layer], properties.layerID); 167 168 return view.get(); 169} 170 171} // namespace WebKit 172 173#endif // PLATFORM(IOS) 174