Provide a mechanism to specify the maximum size of WKThumbnailView snapshots
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 Sep 2016 21:09:35 +0000 (21:09 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 13 Sep 2016 21:09:35 +0000 (21:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161896
<rdar://problem/28229827>

Reviewed by Simon Fraser.

Some clients know that their thumbnail views will only be displayed up to
a specific size that is significantly smaller than the WKView size. Allow
them to avoid wasting lots of memory on unnecessarily large snapshots.

* UIProcess/API/Cocoa/_WKThumbnailView.h:
* UIProcess/API/Cocoa/_WKThumbnailView.mm:
(-[_WKThumbnailView requestSnapshot]):
(-[_WKThumbnailView _requestSnapshotIfNeeded]):
(-[_WKThumbnailView setMaximumSnapshotSize:]):
Add a maximumSnapshotSize property which can be changed dynamically.

* TestWebKitAPI/Tests/WebKit2/WKThumbnailView.mm:
(TestWebKitAPI::TEST):
Add a test for the new property.
Also fix the old new test to run on arbitrary scale displays without failing.

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

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/Cocoa/_WKThumbnailView.h
Source/WebKit2/UIProcess/API/Cocoa/_WKThumbnailView.mm
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WebKit2/WKThumbnailView.mm

index 0ba98eb..5516d5d 100644 (file)
@@ -1,3 +1,22 @@
+2016-09-13  Tim Horton  <timothy_horton@apple.com>
+
+        Provide a mechanism to specify the maximum size of WKThumbnailView snapshots
+        https://bugs.webkit.org/show_bug.cgi?id=161896
+        <rdar://problem/28229827>
+
+        Reviewed by Simon Fraser.
+
+        Some clients know that their thumbnail views will only be displayed up to
+        a specific size that is significantly smaller than the WKView size. Allow
+        them to avoid wasting lots of memory on unnecessarily large snapshots.
+
+        * UIProcess/API/Cocoa/_WKThumbnailView.h:
+        * UIProcess/API/Cocoa/_WKThumbnailView.mm:
+        (-[_WKThumbnailView requestSnapshot]):
+        (-[_WKThumbnailView _requestSnapshotIfNeeded]):
+        (-[_WKThumbnailView setMaximumSnapshotSize:]):
+        Add a maximumSnapshotSize property which can be changed dynamically.
+
 2016-09-13  Anders Carlsson  <andersca@apple.com>
 
         REGRESSION (r196321): Amazon Videos are all black in Fullscreen
index 7363ae4..b19d3e7 100644 (file)
@@ -40,6 +40,7 @@ WK_CLASS_AVAILABLE(macosx(10.10), ios(8.0))
 
 @property (nonatomic) CGFloat scale;
 @property (nonatomic, readonly) CGSize snapshotSize;
+@property (nonatomic) CGSize maximumSnapshotSize;
 @property (nonatomic) BOOL exclusivelyUsesSnapshot;
 
 // Defaults to NO.
index 4b4a865..8442823 100644 (file)
@@ -53,7 +53,8 @@ using namespace WebKit;
     BOOL _originalSourceViewIsInWindow;
 
     BOOL _snapshotWasDeferred;
-    double _lastSnapshotScale;
+    CGFloat _lastSnapshotScale;
+    CGSize _lastSnapshotMaximumSize;
 }
 
 @synthesize snapshotSize=_snapshotSize;
@@ -94,7 +95,18 @@ using namespace WebKit;
     SnapshotOptions options = SnapshotOptionsInViewCoordinates;
     IntSize bitmapSize = snapshotRect.size();
     bitmapSize.scale(_scale * _webPageProxy->deviceScaleFactor());
+
+    if (!CGSizeEqualToSize(_maximumSnapshotSize, CGSizeZero)) {
+        double sizeConstraintScale = 1;
+        if (_maximumSnapshotSize.width)
+            sizeConstraintScale = CGFloatMin(sizeConstraintScale, _maximumSnapshotSize.width / bitmapSize.width());
+        if (_maximumSnapshotSize.height)
+            sizeConstraintScale = CGFloatMin(sizeConstraintScale, _maximumSnapshotSize.height / bitmapSize.height());
+        bitmapSize = IntSize(CGCeiling(bitmapSize.width() * sizeConstraintScale), CGCeiling(bitmapSize.height() * sizeConstraintScale));
+    }
+
     _lastSnapshotScale = _scale;
+    _lastSnapshotMaximumSize = _maximumSnapshotSize;
     _webPageProxy->takeSnapshot(snapshotRect, bitmapSize, options, [thumbnailView](const ShareableBitmap::Handle& imageHandle, WebKit::CallbackBase::Error) {
         RefPtr<ShareableBitmap> bitmap = ShareableBitmap::create(imageHandle, SharedMemory::Protection::ReadOnly);
         RetainPtr<CGImageRef> cgImage = bitmap ? bitmap->makeCGImage() : nullptr;
@@ -135,7 +147,7 @@ using namespace WebKit;
 
 - (void)_requestSnapshotIfNeeded
 {
-    if (self.layer.contents && _lastSnapshotScale == _scale)
+    if (self.layer.contents && _lastSnapshotScale == _scale && CGSizeEqualToSize(_lastSnapshotMaximumSize, _maximumSnapshotSize))
         return;
 
     [self requestSnapshot];
@@ -180,6 +192,16 @@ using namespace WebKit;
     self.layer.sublayerTransform = CATransform3DMakeScale(_scale, _scale, 1);
 }
 
+- (void)setMaximumSnapshotSize:(CGSize)maximumSnapshotSize
+{
+    if (CGSizeEqualToSize(_maximumSnapshotSize, maximumSnapshotSize))
+        return;
+
+    _maximumSnapshotSize = maximumSnapshotSize;
+
+    [self _requestSnapshotIfNeeded];
+}
+
 // This should be removed when all clients go away; it is always YES now.
 - (void)setUsesSnapshot:(BOOL)usesSnapshot
 {
index c74d614..f3e9685 100644 (file)
@@ -1,3 +1,16 @@
+2016-09-13  Tim Horton  <timothy_horton@apple.com>
+
+        Provide a mechanism to specify the maximum width of WKThumbnailView snapshots
+        https://bugs.webkit.org/show_bug.cgi?id=161896
+        <rdar://problem/28229827>
+
+        Reviewed by Simon Fraser.
+
+        * TestWebKitAPI/Tests/WebKit2/WKThumbnailView.mm:
+        (TestWebKitAPI::TEST):
+        Add a test for the new property.
+        Also fix the old new test to run on arbitrary scale displays without failing.
+
 2016-09-12  Brent Fulgham  <bfulgham@apple.com>
 
         [Win][Direct2D] Provide Direct2D-based geometry and transform cast operations
index c107056..e08f179 100644 (file)
@@ -76,11 +76,11 @@ static void setPageLoaderClient(WKPageRef page)
 
 TEST(WebKit2, WKThumbnailViewKeepSnapshotWhenRemovedFromSuperview)
 {
-    WKRetainPtr<WKContextRef> context = adoptWK(Util::createContextForInjectedBundleTest("MouseMoveAfterCrashTest"));
-
+    WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
     PlatformWebView webView(context.get());
     WKView *wkView = webView.platformView();
     setPageLoaderClient(webView.page());
+    WKPageSetCustomBackingScaleFactor(webView.page(), 1);
 
     WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("lots-of-text", "html"));
     WKPageLoadURL(webView.page(), url.get());
@@ -120,6 +120,59 @@ TEST(WebKit2, WKThumbnailViewKeepSnapshotWhenRemovedFromSuperview)
     [thumbnailView removeObserver:observer.get() forKeyPath:@"snapshotSize" context:snapshotSizeChangeKVOContext];
 }
 
+TEST(WebKit2, WKThumbnailViewMaximumSnapshotSize)
+{
+    WKRetainPtr<WKContextRef> context = adoptWK(WKContextCreate());
+    PlatformWebView webView(context.get());
+    WKView *wkView = webView.platformView();
+    setPageLoaderClient(webView.page());
+    WKPageSetCustomBackingScaleFactor(webView.page(), 1);
+
+    WKRetainPtr<WKURLRef> url(AdoptWK, Util::createURLForResource("lots-of-text", "html"));
+    WKPageLoadURL(webView.page(), url.get());
+    Util::run(&didFinishLoad);
+    didFinishLoad = false;
+
+    RetainPtr<_WKThumbnailView> thumbnailView = adoptNS([[_WKThumbnailView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) fromWKView:wkView]);
+
+    RetainPtr<SnapshotSizeObserver> observer = adoptNS([[SnapshotSizeObserver alloc] init]);
+
+    [thumbnailView addObserver:observer.get() forKeyPath:@"snapshotSize" options:NSKeyValueObservingOptionNew context:snapshotSizeChangeKVOContext];
+
+    [wkView.window.contentView addSubview:thumbnailView.get()];
+    Util::run(&didTakeSnapshot);
+    didTakeSnapshot = false;
+
+    EXPECT_EQ([thumbnailView snapshotSize].width, 800);
+    EXPECT_FALSE([thumbnailView layer].contents == nil);
+
+    [thumbnailView setMaximumSnapshotSize:CGSizeMake(200, 0)];
+    Util::run(&didTakeSnapshot);
+    didTakeSnapshot = false;
+
+    EXPECT_EQ([thumbnailView snapshotSize].width, 200);
+    EXPECT_EQ([thumbnailView snapshotSize].height, 150);
+    EXPECT_FALSE([thumbnailView layer].contents == nil);
+
+    [thumbnailView setMaximumSnapshotSize:CGSizeMake(0, 300)];
+    Util::run(&didTakeSnapshot);
+    didTakeSnapshot = false;
+
+    EXPECT_EQ([thumbnailView snapshotSize].width, 400);
+    EXPECT_EQ([thumbnailView snapshotSize].height, 300);
+    EXPECT_FALSE([thumbnailView layer].contents == nil);
+
+    [thumbnailView setMaximumSnapshotSize:CGSizeMake(200, 300)];
+    Util::run(&didTakeSnapshot);
+    didTakeSnapshot = false;
+
+    EXPECT_EQ([thumbnailView snapshotSize].width, 200);
+    EXPECT_EQ([thumbnailView snapshotSize].height, 150);
+    EXPECT_FALSE([thumbnailView layer].contents == nil);
+
+    [thumbnailView removeObserver:observer.get() forKeyPath:@"snapshotSize" context:snapshotSizeChangeKVOContext];
+}
+
 } // namespace TestWebKitAPI
 
 #endif