Title: [221153] trunk
Revision
221153
Author
timothy_hor...@apple.com
Date
2017-08-24 11:57:36 -0700 (Thu, 24 Aug 2017)

Log Message

Layout size override changes during in-flight animated resize are dropped on the floor forever
https://bugs.webkit.org/show_bug.cgi?id=175916
<rdar://problem/33887295>

Reviewed by Beth Dakin.

Source/WebKit:

Layout size override changes that come in during an animated resize
are currently stored, but not sent in a separate message, because
they're sent as part of the resize. However, if a layout size override
change happens after the animated resize message was already sent, but
before the animated resize is ended, that change will be stored, but
not sent in the animated resize message (because it's too late), and
then subsequent calls with the same size will early-return, because
we're testing against the stored size, not the size we last actually
sent to the Web Content process.

Instead, store the last-sent size, so that subsequent layout size override
changes with the same size won't bail, and if it differs from the active
state after the animated resize completes, send an out-of-band update.

All of the above also applies to device orientation, which follows
exactly the same pattern.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _initializeWithConfiguration:]):
(-[WKWebView _dispatchSetMinimumLayoutSize:]):
(-[WKWebView _dispatchSetMaximumUnobscuredSize:]):
(-[WKWebView _dispatchSetDeviceOrientation:]):
(-[WKWebView _frameOrBoundsChanged]):
(-[WKWebView _windowDidRotate:]):
(-[WKWebView _didRelaunchProcess]):
(-[WKWebView _setMinimumLayoutSizeOverride:]):
(-[WKWebView _setInterfaceOrientationOverride:]):
(-[WKWebView _setMaximumUnobscuredSizeOverride:]):
(-[WKWebView _beginAnimatedResizeWithUpdates:]):

Tools:

* TestWebKitAPI/Tests/WebKit2Cocoa/AnimatedResize.mm:
(TEST):
Add a test ensuring that override layout size changes
during an animated resize actually take effect.

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (221152 => 221153)


--- trunk/Source/WebKit/ChangeLog	2017-08-24 18:35:39 UTC (rev 221152)
+++ trunk/Source/WebKit/ChangeLog	2017-08-24 18:57:36 UTC (rev 221153)
@@ -1,5 +1,43 @@
 2017-08-24  Tim Horton  <timothy_hor...@apple.com>
 
+        Layout size override changes during in-flight animated resize are dropped on the floor forever
+        https://bugs.webkit.org/show_bug.cgi?id=175916
+        <rdar://problem/33887295>
+
+        Reviewed by Beth Dakin.
+
+        Layout size override changes that come in during an animated resize
+        are currently stored, but not sent in a separate message, because
+        they're sent as part of the resize. However, if a layout size override
+        change happens after the animated resize message was already sent, but
+        before the animated resize is ended, that change will be stored, but
+        not sent in the animated resize message (because it's too late), and
+        then subsequent calls with the same size will early-return, because
+        we're testing against the stored size, not the size we last actually
+        sent to the Web Content process.
+
+        Instead, store the last-sent size, so that subsequent layout size override
+        changes with the same size won't bail, and if it differs from the active
+        state after the animated resize completes, send an out-of-band update.
+
+        All of the above also applies to device orientation, which follows
+        exactly the same pattern.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _initializeWithConfiguration:]):
+        (-[WKWebView _dispatchSetMinimumLayoutSize:]):
+        (-[WKWebView _dispatchSetMaximumUnobscuredSize:]):
+        (-[WKWebView _dispatchSetDeviceOrientation:]):
+        (-[WKWebView _frameOrBoundsChanged]):
+        (-[WKWebView _windowDidRotate:]):
+        (-[WKWebView _didRelaunchProcess]):
+        (-[WKWebView _setMinimumLayoutSizeOverride:]):
+        (-[WKWebView _setInterfaceOrientationOverride:]):
+        (-[WKWebView _setMaximumUnobscuredSizeOverride:]):
+        (-[WKWebView _beginAnimatedResizeWithUpdates:]):
+
+2017-08-24  Tim Horton  <timothy_hor...@apple.com>
+
         _WKThumbnailView snapshots have to be copied by CA on first commit due to bad row alignment
         https://bugs.webkit.org/show_bug.cgi?id=175898
         <rdar://problem/34029673>

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm (221152 => 221153)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2017-08-24 18:35:39 UTC (rev 221152)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm	2017-08-24 18:57:36 UTC (rev 221153)
@@ -229,8 +229,10 @@
 
     BOOL _overridesMinimumLayoutSize;
     CGSize _minimumLayoutSizeOverride;
+    std::optional<WebCore::FloatSize> _lastSentMinimumLayoutSize;
     BOOL _overridesMaximumUnobscuredSize;
     CGSize _maximumUnobscuredSizeOverride;
+    std::optional<WebCore::FloatSize> _lastSentMaximumUnobscuredSize;
     CGRect _inputViewBounds;
     CGFloat _viewportMetaTagWidth;
     BOOL _viewportMetaTagWidthWasExplicit;
@@ -251,6 +253,7 @@
 
     UIInterfaceOrientation _interfaceOrientationOverride;
     BOOL _overridesInterfaceOrientation;
+    std::optional<int32_t> _lastSentDeviceOrientation;
 
     BOOL _allowsViewportShrinkToFit;
 
@@ -535,7 +538,7 @@
     _contentView = adoptNS([[WKContentView alloc] initWithFrame:bounds processPool:processPool configuration:WTFMove(pageConfiguration) webView:self]);
 
     _page = [_contentView page];
-    _page->setDeviceOrientation(deviceOrientation());
+    [self _dispatchSetDeviceOrientation:deviceOrientation()];
     _page->setDrawsBackground(self.opaque);
 
     [_contentView layer].anchorPoint = CGPointZero;
@@ -2344,6 +2347,33 @@
 #endif
 }
 
+- (void)_dispatchSetMinimumLayoutSize:(WebCore::FloatSize)minimumLayoutSize
+{
+    if (_lastSentMinimumLayoutSize && CGSizeEqualToSize(_lastSentMinimumLayoutSize.value(), minimumLayoutSize))
+        return;
+
+    _page->setViewportConfigurationMinimumLayoutSize(minimumLayoutSize);
+    _lastSentMinimumLayoutSize = minimumLayoutSize;
+}
+
+- (void)_dispatchSetMaximumUnobscuredSize:(WebCore::FloatSize)maximumUnobscuredSize
+{
+    if (_lastSentMaximumUnobscuredSize && CGSizeEqualToSize(_lastSentMaximumUnobscuredSize.value(), maximumUnobscuredSize))
+        return;
+
+    _page->setMaximumUnobscuredSize(maximumUnobscuredSize);
+    _lastSentMaximumUnobscuredSize = maximumUnobscuredSize;
+}
+
+- (void)_dispatchSetDeviceOrientation:(int32_t)deviceOrientation
+{
+    if (_lastSentDeviceOrientation && _lastSentDeviceOrientation.value() == deviceOrientation)
+        return;
+
+    _page->setDeviceOrientation(deviceOrientation);
+    _lastSentDeviceOrientation = deviceOrientation;
+}
+
 - (void)_frameOrBoundsChanged
 {
     CGRect bounds = self.bounds;
@@ -2351,9 +2381,9 @@
 
     if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing) {
         if (!_overridesMinimumLayoutSize)
-            _page->setViewportConfigurationMinimumLayoutSize(activeMinimumLayoutSize(self, self.bounds));
+            [self _dispatchSetMinimumLayoutSize:activeMinimumLayoutSize(self, self.bounds)];
         if (!_overridesMaximumUnobscuredSize)
-            _page->setMaximumUnobscuredSize(WebCore::FloatSize(bounds.size));
+            [self _dispatchSetMaximumUnobscuredSize:WebCore::FloatSize(bounds.size)];
 
         BOOL sizeChanged = NO;
         if (auto drawingArea = _page->drawingArea())
@@ -2659,7 +2689,7 @@
 - (void)_windowDidRotate:(NSNotification *)notification
 {
     if (!_overridesInterfaceOrientation)
-        _page->setDeviceOrientation(deviceOrientation());
+        [self _dispatchSetDeviceOrientation:deviceOrientation()];
 }
 
 - (void)_contentSizeCategoryDidChange:(NSNotification *)notification
@@ -3992,9 +4022,8 @@
 {
 #if PLATFORM(IOS)
     CGRect bounds = self.bounds;
-    WebCore::FloatSize minimalLayoutSize = activeMinimumLayoutSize(self, bounds);
-    _page->setViewportConfigurationMinimumLayoutSize(minimalLayoutSize);
-    _page->setMaximumUnobscuredSize(activeMaximumUnobscuredSize(self, bounds));
+    [self _dispatchSetMinimumLayoutSize:activeMinimumLayoutSize(self, bounds)];
+    [self _dispatchSetMaximumUnobscuredSize:activeMaximumUnobscuredSize(self, bounds)];
 #endif
 }
 
@@ -4655,12 +4684,11 @@
 - (void)_setMinimumLayoutSizeOverride:(CGSize)minimumLayoutSizeOverride
 {
     _overridesMinimumLayoutSize = YES;
-    if (CGSizeEqualToSize(_minimumLayoutSizeOverride, minimumLayoutSizeOverride))
-        return;
+    _minimumLayoutSizeOverride = minimumLayoutSizeOverride;
 
-    _minimumLayoutSizeOverride = minimumLayoutSizeOverride;
     if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
-        _page->setViewportConfigurationMinimumLayoutSize(WebCore::FloatSize(minimumLayoutSizeOverride));
+        [self _dispatchSetMinimumLayoutSize:WebCore::FloatSize(minimumLayoutSizeOverride)];
+
 }
 
 - (UIEdgeInsets)_obscuredInsets
@@ -4732,14 +4760,10 @@
 - (void)_setInterfaceOrientationOverride:(UIInterfaceOrientation)interfaceOrientation
 {
     _overridesInterfaceOrientation = YES;
-
-    if (interfaceOrientation == _interfaceOrientationOverride)
-        return;
-
     _interfaceOrientationOverride = interfaceOrientation;
 
     if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
-        _page->setDeviceOrientation(deviceOrientationForUIInterfaceOrientation(_interfaceOrientationOverride));
+        [self _dispatchSetDeviceOrientation:deviceOrientationForUIInterfaceOrientation(_interfaceOrientationOverride)];
 }
 
 - (UIInterfaceOrientation)_interfaceOrientationOverride
@@ -4764,12 +4788,10 @@
 {
     ASSERT(size.width <= self.bounds.size.width && size.height <= self.bounds.size.height);
     _overridesMaximumUnobscuredSize = YES;
-    if (CGSizeEqualToSize(_maximumUnobscuredSizeOverride, size))
-        return;
+    _maximumUnobscuredSizeOverride = size;
 
-    _maximumUnobscuredSizeOverride = size;
     if (_dynamicViewportUpdateMode == DynamicViewportUpdateMode::NotResizing)
-        _page->setMaximumUnobscuredSize(WebCore::FloatSize(size));
+        [self _dispatchSetMaximumUnobscuredSize:WebCore::FloatSize(size)];
 }
 
 - (void)_setBackgroundExtendsBeyondPage:(BOOL)backgroundExtends
@@ -4843,11 +4865,11 @@
         _dynamicViewportUpdateMode = DynamicViewportUpdateMode::NotResizing;
         [self _frameOrBoundsChanged];
         if (_overridesMinimumLayoutSize)
-            _page->setViewportConfigurationMinimumLayoutSize(WebCore::FloatSize(newMinimumLayoutSize));
+            [self _dispatchSetMinimumLayoutSize:WebCore::FloatSize(newMinimumLayoutSize)];
         if (_overridesMaximumUnobscuredSize)
-            _page->setMaximumUnobscuredSize(WebCore::FloatSize(newMaximumUnobscuredSize));
+            [self _dispatchSetMaximumUnobscuredSize:WebCore::FloatSize(newMaximumUnobscuredSize)];
         if (_overridesInterfaceOrientation)
-            _page->setDeviceOrientation(newOrientation);
+            [self _dispatchSetDeviceOrientation:newOrientation];
 
         [self _scheduleVisibleContentRectUpdate];
         return;
@@ -4920,6 +4942,10 @@
     UIEdgeInsets unobscuredSafeAreaInsets = [self _computedUnobscuredSafeAreaInset];
     WebCore::FloatBoxExtent unobscuredSafeAreaInsetsExtent(unobscuredSafeAreaInsets.top, unobscuredSafeAreaInsets.right, unobscuredSafeAreaInsets.bottom, unobscuredSafeAreaInsets.left);
 
+    _lastSentMinimumLayoutSize = newMinimumLayoutSize;
+    _lastSentMaximumUnobscuredSize = newMaximumUnobscuredSize;
+    _lastSentDeviceOrientation = newOrientation;
+
     _page->dynamicViewportSizeUpdate(newMinimumLayoutSize, newMaximumUnobscuredSize, visibleRectInContentCoordinates, unobscuredRectInContentCoordinates, futureUnobscuredRectInSelfCoordinates, unobscuredSafeAreaInsetsExtent, targetScale, newOrientation);
     if (WebKit::DrawingAreaProxy* drawingArea = _page->drawingArea())
         drawingArea->setSize(WebCore::IntSize(newBounds.size), WebCore::IntSize(), WebCore::IntSize());
@@ -4982,6 +5008,18 @@
     [_contentView setHidden:NO];
     [self _scheduleVisibleContentRectUpdate];
 
+    CGRect newBounds = self.bounds;
+    WebCore::FloatSize newMinimumLayoutSize = activeMinimumLayoutSize(self, newBounds);
+    WebCore::FloatSize newMaximumUnobscuredSize = activeMaximumUnobscuredSize(self, newBounds);
+    int32_t newOrientation = activeOrientation(self);
+
+    if (!_lastSentMinimumLayoutSize || newMinimumLayoutSize != _lastSentMinimumLayoutSize.value())
+        [self _dispatchSetMinimumLayoutSize:WebCore::FloatSize(newMinimumLayoutSize)];
+    if (!_lastSentMaximumUnobscuredSize || newMaximumUnobscuredSize != _lastSentMaximumUnobscuredSize.value())
+        [self _dispatchSetMaximumUnobscuredSize:WebCore::FloatSize(newMaximumUnobscuredSize)];
+    if (!_lastSentDeviceOrientation || newOrientation != _lastSentDeviceOrientation.value())
+        [self _dispatchSetDeviceOrientation:newOrientation];
+
     while (!_snapshotsDeferredDuringResize.isEmpty())
         _snapshotsDeferredDuringResize.takeLast()();
 }

Modified: trunk/Tools/ChangeLog (221152 => 221153)


--- trunk/Tools/ChangeLog	2017-08-24 18:35:39 UTC (rev 221152)
+++ trunk/Tools/ChangeLog	2017-08-24 18:57:36 UTC (rev 221153)
@@ -1,3 +1,16 @@
+2017-08-24  Tim Horton  <timothy_hor...@apple.com>
+
+        Layout size override changes during in-flight animated resize are dropped on the floor forever
+        https://bugs.webkit.org/show_bug.cgi?id=175916
+        <rdar://problem/33887295>
+
+        Reviewed by Beth Dakin.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/AnimatedResize.mm:
+        (TEST):
+        Add a test ensuring that override layout size changes
+        during an animated resize actually take effect.
+
 2017-08-23  Matt Lewis  <jlew...@apple.com>
 
         Disabled VideoControlsManagerMultipleVideosSwitchControlledVideoWhenScrolling.

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/AnimatedResize.mm (221152 => 221153)


--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/AnimatedResize.mm	2017-08-24 18:35:39 UTC (rev 221152)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/AnimatedResize.mm	2017-08-24 18:57:36 UTC (rev 221153)
@@ -184,4 +184,38 @@
     EXPECT_TRUE(didChangeSafeAreaShouldAffectObscuredInsets);
 }
 
+TEST(WebKit2, OverrideLayoutSizeChangesDuringAnimatedResizeSucceed)
+{
+    auto webView = createAnimatedResizeWebView();
+    [webView setUIDelegate:webView.get()];
+
+    [webView _overrideLayoutParametersWithMinimumLayoutSize:CGSizeMake(200, 50) maximumUnobscuredSizeOverride:CGSizeMake(200, 50)];
+
+    [webView loadHTMLString:@"<head><meta name='viewport' content='initial-scale=1' /></head>" baseURL:nil];
+    [webView _test_waitForDidFinishNavigation];
+
+    RetainPtr<UIWindow> window = adoptNS([[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
+    [window addSubview:webView.get()];
+    [window setHidden:NO];
+
+    [webView _beginAnimatedResizeWithUpdates:^ {
+        [webView setFrame:CGRectMake(0, 0, [webView frame].size.width + 100, 400)];
+    }];
+
+    [webView _overrideLayoutParametersWithMinimumLayoutSize:CGSizeMake(100, 200) maximumUnobscuredSizeOverride:CGSizeMake(100, 200)];
+    [webView _endAnimatedResize];
+
+    __block bool didReadLayoutSize = false;
+    [webView evaluateJavaScript:@"[window.innerWidth, window.innerHeight]" completionHandler:^(id value, NSError *error) {
+        CGFloat innerWidth = [[value objectAtIndex:0] floatValue];
+        CGFloat innerHeight = [[value objectAtIndex:1] floatValue];
+
+        EXPECT_EQ(innerWidth, 100);
+        EXPECT_EQ(innerHeight, 200);
+
+        didReadLayoutSize = true;
+    }];
+    TestWebKitAPI::Util::run(&didReadLayoutSize);
+}
+
 #endif
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to