[iOS WK2] Don't disable position:fixed when a form element has focus
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Dec 2016 19:19:51 +0000 (19:19 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 15 Dec 2016 19:19:51 +0000 (19:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=165891
rdar://problem/29271694

Reviewed by Wenson Hsieh.

Source/WebKit2:

Before visual viewports, we had to lay out position:fixed relative to the document rect (effectively
disabling position:fixed) when a form element was focused, to ensure that we could scroll to inputs
inside position:Fixed.

When visual viewports are enabled, we can do a better job of this, and keep position:fixed active.

Test: fast/visual-viewport/ios/zoomed-focus-in-fixed.html

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _zoomToFocusRect:selectionRect:insideFixed:fontSize:minimumScale:maximumScale:allowScaling:forceScroll:]): Soon this will use
insideFixed to have better scroll-into-view behavior.
(-[WKWebView _zoomToFocusRect:selectionRect:fontSize:minimumScale:maximumScale:allowScaling:forceScroll:]): Deleted.
* UIProcess/API/Cocoa/WKWebViewInternal.h:
* UIProcess/ios/WKContentView.h:
* UIProcess/ios/WKContentView.mm:
(-[WKContentView _zoomToFocusRect:selectionRect:insideFixed:fontSize:minimumScale:maximumScale:allowScaling:forceScroll:]):
(-[WKContentView _zoomToFocusRect:selectionRect:fontSize:minimumScale:maximumScale:allowScaling:forceScroll:]): Deleted.
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _displayFormNodeInputView]):
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::computeCustomFixedPositionRect): Don't fall back to using the documentRect as the fixed
position rect if visual viewports are enabled.
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::getAssistedNodeInformation): Don't reset the customtFixedPositionRect around computing element
coordinates if visual viewports are enabled.

LayoutTests:

* TestExpectations:
* fast/visual-viewport/ios/zoomed-focus-in-fixed-expected.txt: Added.
* fast/visual-viewport/ios/zoomed-focus-in-fixed.html: Added.
* platform/ios-simulator-wk2/TestExpectations:

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

13 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/fast/visual-viewport/ios/zoomed-focus-in-fixed-expected.txt [new file with mode: 0644]
LayoutTests/fast/visual-viewport/ios/zoomed-focus-in-fixed.html [new file with mode: 0644]
LayoutTests/platform/ios-simulator-wk2/TestExpectations
Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm
Source/WebKit2/UIProcess/API/Cocoa/WKWebViewInternal.h
Source/WebKit2/UIProcess/ios/WKContentView.h
Source/WebKit2/UIProcess/ios/WKContentView.mm
Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm
Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm
Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm

index 86cfdc4..482c2b6 100644 (file)
@@ -1,3 +1,16 @@
+2016-12-15  Simon Fraser  <simon.fraser@apple.com>
+
+        [iOS WK2] Don't disable position:fixed when a form element has focus
+        https://bugs.webkit.org/show_bug.cgi?id=165891
+        rdar://problem/29271694
+
+        Reviewed by Wenson Hsieh.
+
+        * TestExpectations:
+        * fast/visual-viewport/ios/zoomed-focus-in-fixed-expected.txt: Added.
+        * fast/visual-viewport/ios/zoomed-focus-in-fixed.html: Added.
+        * platform/ios-simulator-wk2/TestExpectations:
+
 2016-12-15  Darin Adler  <darin@apple.com>
 
         Remove custom binding for MediaDevices
index b42bd62..c8bf0b6 100644 (file)
@@ -20,6 +20,7 @@ swipe [ Skip ]
 fast/zooming/ios [ Skip ]
 fast/forms/ios [ Skip ]
 fast/viewport/ios [ Skip ]
+fast/visual-viewport/ios/ [ Skip ]
 fast/events/ios [ Skip ]
 fast/events/touch/ios [ Skip ]
 fast/scrolling/ios [ Skip ]
diff --git a/LayoutTests/fast/visual-viewport/ios/zoomed-focus-in-fixed-expected.txt b/LayoutTests/fast/visual-viewport/ios/zoomed-focus-in-fixed-expected.txt
new file mode 100644 (file)
index 0000000..57fdd3d
--- /dev/null
@@ -0,0 +1,3 @@
+Layout viewport: {"top":746.703125,"right":320,"bottom":1314.703125,"left":0,"width":320,"height":568}
+Visual viewport: {"top":747,"right":220,"bottom":1138,"left":0,"width":220,"height":391}
+
diff --git a/LayoutTests/fast/visual-viewport/ios/zoomed-focus-in-fixed.html b/LayoutTests/fast/visual-viewport/ios/zoomed-focus-in-fixed.html
new file mode 100644 (file)
index 0000000..cc9e1fc
--- /dev/null
@@ -0,0 +1,73 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+
+<html>
+<head>
+    <meta name="viewport" content="initial-scale=1.0">
+    <style>
+        body {
+            width: 1000px;
+            height: 2000px;
+        }
+        .fixed {
+            position: fixed;
+            background-color: silver;
+            top: 10px;
+            padding: 10px;
+        }
+    </style>
+    <script>
+        if (window.testRunner) {
+            testRunner.waitUntilDone();
+            testRunner.dumpAsText();
+        }
+
+        function getScrollDownUIScript()
+        {
+            return `(function() {
+                uiController.immediateScrollToOffset(0, 800);
+            })();`;
+        }
+        
+        function getFocusInputUIScript(x, y)
+        {
+            return `(function() {
+                uiController.didShowKeyboardCallback = function() {
+                    uiController.uiScriptComplete();
+                }
+                
+                uiController.singleTapAtPoint(${x}, ${y}, function() {});
+            })();`;
+        }
+
+        function runTest()
+        {
+            if (!window.testRunner || !testRunner.runUIScript)
+                return;
+
+            testRunner.runUIScript(getScrollDownUIScript(), function() {
+                window.setTimeout(function() {
+                    var rect = document.getElementById('input').getBoundingClientRect();
+                    // singleTapAtPoint takes document coordinates, so add scrollTop to clientRect.top.
+                    testRunner.runUIScript(getFocusInputUIScript(rect.left, rect.top + document.scrollingElement.scrollTop), function() {
+
+                        if (window.internals) {
+                            var output = 'Layout viewport: ' + JSON.stringify(internals.layoutViewportRect()) + '\nVisual viewport: ' + JSON.stringify(internals.visualViewportRect()) + '\n';
+                            document.getElementById('results').innerText = output;
+                        }
+
+                        testRunner.notifyDone();
+                    });
+                }, 0);
+            });
+        }
+
+        window.addEventListener('load', runTest, false);
+    </script>
+</head>
+<body>
+<pre id="results"></pre>
+<div class="fixed">
+    <input id="input" type="text">
+</div>
+</body>
+</html>
index 9abb025..5a827b4 100644 (file)
@@ -8,6 +8,7 @@
 
 fast/scrolling/ios [ Pass ]
 fast/viewport/ios [ Pass ]
+fast/visual-viewport/ios/ [ Pass ]
 scrollingcoordinator/ios [ Pass ]
 editing/selection/character-granularity-rect.html [ Pass ]
 
index 3a1ca89..8d03f48 100644 (file)
@@ -1,3 +1,37 @@
+2016-12-15  Simon Fraser  <simon.fraser@apple.com>
+
+        [iOS WK2] Don't disable position:fixed when a form element has focus
+        https://bugs.webkit.org/show_bug.cgi?id=165891
+        rdar://problem/29271694
+
+        Reviewed by Wenson Hsieh.
+
+        Before visual viewports, we had to lay out position:fixed relative to the document rect (effectively
+        disabling position:fixed) when a form element was focused, to ensure that we could scroll to inputs
+        inside position:Fixed.
+
+        When visual viewports are enabled, we can do a better job of this, and keep position:fixed active.
+        
+        Test: fast/visual-viewport/ios/zoomed-focus-in-fixed.html
+
+        * UIProcess/API/Cocoa/WKWebView.mm: 
+        (-[WKWebView _zoomToFocusRect:selectionRect:insideFixed:fontSize:minimumScale:maximumScale:allowScaling:forceScroll:]): Soon this will use
+        insideFixed to have better scroll-into-view behavior.
+        (-[WKWebView _zoomToFocusRect:selectionRect:fontSize:minimumScale:maximumScale:allowScaling:forceScroll:]): Deleted.
+        * UIProcess/API/Cocoa/WKWebViewInternal.h:
+        * UIProcess/ios/WKContentView.h:
+        * UIProcess/ios/WKContentView.mm:
+        (-[WKContentView _zoomToFocusRect:selectionRect:insideFixed:fontSize:minimumScale:maximumScale:allowScaling:forceScroll:]):
+        (-[WKContentView _zoomToFocusRect:selectionRect:fontSize:minimumScale:maximumScale:allowScaling:forceScroll:]): Deleted.
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _displayFormNodeInputView]):
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::computeCustomFixedPositionRect): Don't fall back to using the documentRect as the fixed
+        position rect if visual viewports are enabled.
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::getAssistedNodeInformation): Don't reset the customtFixedPositionRect around computing element
+        coordinates if visual viewports are enabled.
+
 2016-12-15  Andreas Kling  <akling@apple.com>
 
         Always clear RenderLayer backing stores when going into page cache.
index 4a91cf6..16102dd 100644 (file)
@@ -1619,8 +1619,12 @@ static WebCore::FloatPoint constrainContentOffset(WebCore::FloatPoint contentOff
 }
 
 // focusedElementRect and selectionRect are both in document coordinates.
-- (void)_zoomToFocusRect:(WebCore::FloatRect)focusedElementRectInDocumentCoordinates selectionRect:(WebCore::FloatRect)selectionRectInDocumentCoordinates fontSize:(float)fontSize minimumScale:(double)minimumScale maximumScale:(double)maximumScale allowScaling:(BOOL)allowScaling forceScroll:(BOOL)forceScroll
+- (void)_zoomToFocusRect:(WebCore::FloatRect)focusedElementRectInDocumentCoordinates selectionRect:(WebCore::FloatRect)selectionRectInDocumentCoordinates insideFixed:(BOOL)insideFixed
+    fontSize:(float)fontSize minimumScale:(double)minimumScale maximumScale:(double)maximumScale allowScaling:(BOOL)allowScaling forceScroll:(BOOL)forceScroll
 {
+    LOG_WITH_STREAM(VisibleRects, stream << "_zoomToFocusRect:" << focusedElementRectInDocumentCoordinates << " selectionRect:" << selectionRectInDocumentCoordinates);
+    UNUSED_PARAM(insideFixed);
+
     const double WKWebViewStandardFontSize = 16;
     const double kMinimumHeightToShowContentAboveKeyboard = 106;
     const CFTimeInterval UIWebFormAnimationDuration = 0.25;
index 44d65b2..0abc26b 100644 (file)
@@ -88,7 +88,7 @@ struct PrintInfo;
 - (void)_scrollToContentScrollPosition:(WebCore::FloatPoint)scrollPosition scrollOrigin:(WebCore::IntPoint)scrollOrigin;
 - (BOOL)_scrollToRect:(WebCore::FloatRect)targetRect origin:(WebCore::FloatPoint)origin minimumScrollDistance:(float)minimumScrollDistance;
 - (void)_scrollByContentOffset:(WebCore::FloatPoint)offset;
-- (void)_zoomToFocusRect:(WebCore::FloatRect)focusedElementRect selectionRect:(WebCore::FloatRect)selectionRectInDocumentCoordinates fontSize:(float)fontSize minimumScale:(double)minimumScale maximumScale:(double)maximumScale allowScaling:(BOOL)allowScaling forceScroll:(BOOL)forceScroll;
+- (void)_zoomToFocusRect:(WebCore::FloatRect)focusedElementRect selectionRect:(WebCore::FloatRect)selectionRectInDocumentCoordinates insideFixed:(BOOL)insideFixed fontSize:(float)fontSize minimumScale:(double)minimumScale maximumScale:(double)maximumScale allowScaling:(BOOL)allowScaling forceScroll:(BOOL)forceScroll;
 - (BOOL)_zoomToRect:(WebCore::FloatRect)targetRect withOrigin:(WebCore::FloatPoint)origin fitEntireRect:(BOOL)fitEntireRect minimumScale:(double)minimumScale maximumScale:(double)maximumScale minimumScrollDistance:(float)minimumScrollDistance;
 - (void)_zoomOutWithOrigin:(WebCore::FloatPoint)origin animated:(BOOL)animated;
 - (void)_zoomToInitialScaleWithOrigin:(WebCore::FloatPoint)origin animated:(BOOL)animated;
index 381d106..f7a8af3 100644 (file)
@@ -98,7 +98,7 @@ class WebProcessPool;
 - (void)_setAccessibilityWebProcessToken:(NSData *)data;
 
 - (BOOL)_scrollToRect:(CGRect)targetRect withOrigin:(CGPoint)origin minimumScrollDistance:(CGFloat)minimumScrollDistance;
-- (void)_zoomToFocusRect:(CGRect)rectToFocus selectionRect:(CGRect)selectionRect fontSize:(float)fontSize minimumScale:(double)minimumScale maximumScale:(double)maximumScale allowScaling:(BOOL)allowScaling forceScroll:(BOOL)forceScroll;
+- (void)_zoomToFocusRect:(CGRect)rectToFocus selectionRect:(CGRect)selectionRect insideFixed:(BOOL)insideFixed fontSize:(float)fontSize minimumScale:(double)minimumScale maximumScale:(double)maximumScale allowScaling:(BOOL)allowScaling forceScroll:(BOOL)forceScroll;
 - (BOOL)_zoomToRect:(CGRect)targetRect withOrigin:(CGPoint)origin fitEntireRect:(BOOL)fitEntireRect minimumScale:(double)minimumScale maximumScale:(double)maximumScale minimumScrollDistance:(CGFloat)minimumScrollDistance;
 - (void)_zoomOutWithOrigin:(CGPoint)origin;
 - (void)_zoomToInitialScaleWithOrigin:(CGPoint)origin;
index 9d432d3..d0bebbd 100644 (file)
@@ -577,10 +577,11 @@ static void storeAccessibilityRemoteConnectionInformation(id element, pid_t pid,
     return [_webView _scrollToRect:targetRect origin:origin minimumScrollDistance:minimumScrollDistance];
 }
 
-- (void)_zoomToFocusRect:(CGRect)rectToFocus selectionRect:(CGRect)selectionRect fontSize:(float)fontSize minimumScale:(double)minimumScale maximumScale:(double)maximumScale allowScaling:(BOOL)allowScaling forceScroll:(BOOL)forceScroll
+- (void)_zoomToFocusRect:(CGRect)rectToFocus selectionRect:(CGRect)selectionRect insideFixed:(BOOL)insideFixed fontSize:(float)fontSize minimumScale:(double)minimumScale maximumScale:(double)maximumScale allowScaling:(BOOL)allowScaling forceScroll:(BOOL)forceScroll
 {
     [_webView _zoomToFocusRect:rectToFocus
                  selectionRect:selectionRect
+                   insideFixed:insideFixed
                       fontSize:fontSize
                   minimumScale:minimumScale
                   maximumScale:maximumScale
index cdca851..a5cc97f 100644 (file)
@@ -1100,6 +1100,7 @@ static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius,
     // Zooming above the page's default scale factor should only happen when the user performs it.
     [self _zoomToFocusRect:_assistedNodeInformation.elementRect
              selectionRect: _didAccessoryTabInitiateFocus ? IntRect() : _assistedNodeInformation.selectionRect
+               insideFixed:_assistedNodeInformation.insideFixedPosition
                   fontSize:_assistedNodeInformation.nodeFontSize
               minimumScale:_assistedNodeInformation.minimumScaleFactor
               maximumScale:_assistedNodeInformation.maximumScaleFactorIgnoringAlwaysScalable
index 69a51d2..2e9c6c7 100644 (file)
@@ -225,7 +225,7 @@ WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect&
     FloatRect constrainedUnobscuredRect = unobscuredContentRect;
     FloatRect documentRect = m_pageClient.documentRect();
 
-    if (m_pageClient.isAssistingNode())
+    if (!visualViewportEnabled && m_pageClient.isAssistingNode())
         return documentRect;
 
     if (constraint == UnobscuredRectConstraint::ConstrainedToDocumentRect)
index 17fde78..e0c8e3d 100644 (file)
@@ -2553,9 +2553,9 @@ void WebPage::getAssistedNodeInformation(AssistedNodeInformation& information)
         renderer->localToContainerPoint(FloatPoint(), nullptr, UseTransforms, &inFixed);
         information.insideFixedPosition = inFixed;
         information.isRTL = renderer->style().direction() == RTL;
-        
-        if (inFixed && elementFrame.isMainFrame()) {
-            FrameView* frameView = elementFrame.view();
+
+        FrameView* frameView = elementFrame.view();
+        if (inFixed && elementFrame.isMainFrame() && !frameView->frame().settings().visualViewportEnabled()) {
             IntRect currentFixedPositionRect = frameView->customFixedPositionLayoutRect();
             frameView->setCustomFixedPositionLayoutRect(frameView->renderView()->documentRect());
             information.elementRect = frameView->contentsToRootView(renderer->absoluteBoundingBoxRect());