Changeset 209967 in webkit


Ignore:
Timestamp:
Dec 17, 2016 11:18:12 AM (7 years ago)
Author:
Wenson Hsieh
Message:

Visual viewports: bottom fixed elements disappear behind the keyboard
https://bugs.webkit.org/show_bug.cgi?id=165983
<rdar://problem/29409852>

Reviewed by Simon Fraser.

Source/WebKit2:

Accounts for input view bounds in WebPageProxy::computeCustomFixedPositionRect. To do this, we introduce and
pass unobscuredContentRectRespectingInputViewBounds along with the regular unobscuredContentRect (which does not
respect the obscuring keyboard rect). This unobscuredContentRectRespectingInputViewBounds is then used when
computing the origin of the updated layout viewport rect (and also, when we are _not_ below minimum scale),

Additionally, the size is computed using the (unconstrained) unobscured rect. This is because we previously
would use the document-constrained version of the unobscured rect, which caused the layout viewport to shrink
when approaching the max scroll extents of the document while the keyboard is up, since the unobscured rect
would spill out of the document rect. However, using this unconstrained rect's size also means that if the user
rubber-bands out of the document rect, we would end up pushing the layout viewport rect out of the document,
with no way of adjusting it back in without the user scrolling to push the layout viewport into back document
bounds. To address this, we move the layout rect to be within document bounds after computing its size and
location.

Added a new layout test: fast/visual-viewport/ios/fixed-element-on-bottom-with-keyboard.html, and also tweaked
fixed-caret-position-after-scroll.html to cover these changes.

  • Shared/VisibleContentRectUpdateInfo.cpp:

(WebKit::operator<<):

  • Shared/VisibleContentRectUpdateInfo.h:

(WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
(WebKit::VisibleContentRectUpdateInfo::unobscuredContentRectRespectingInputViewBounds):

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _updateContentRectsWithState:]):
(-[WKWebView _inputViewBounds]):

Returns the current bounds of the input view. For testing purposes.

  • UIProcess/API/Cocoa/WKWebViewPrivate.h:
  • UIProcess/WebPageProxy.h:

(WebKit::WebPageProxy::unobscuredContentRectRespectingInputViewBounds):

  • UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:

(WebKit::RemoteScrollingCoordinatorProxy::customFixedPositionRect):

  • UIProcess/ios/WKContentView.h:
  • UIProcess/ios/WKContentView.mm:

(-[WKContentView _computeUnobscuredContentRectRespectingInputViewBounds:unobscuredContentRect:inputViewBounds:scale:]):

Helper to compute the unobscured rect, accounting for the bounds of the current input view.

(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInset:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
(-[WKContentView _didCommitLayerTree:]):
(-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInset:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]): Deleted.

  • UIProcess/ios/WebPageProxyIOS.mm:

(WebKit::WebPageProxy::computeCustomFixedPositionRect):

  • UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:

(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):

Tools:

Add support for UIScriptController.inputViewBounds, which UI-side scripts may use to fetch the bounding rect of
the keyboard when it is up.

  • DumpRenderTree/ios/UIScriptControllerIOS.mm:

(WTR::UIScriptController::inputViewBounds):

  • TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
  • TestRunnerShared/UIScriptContext/UIScriptController.cpp:

(WTR::UIScriptController::inputViewBounds):

  • TestRunnerShared/UIScriptContext/UIScriptController.h:
  • WebKitTestRunner/ios/PlatformWebViewIOS.mm:

(WTR::viewRectForWindowRect):

Previously, we accounted for the status bar height by translating the entire web view down by the height of the
status bar. However, we did not shrink the height of the web view itself, which means that for tests which
involve scrolling past the end of the document, the bottom strip of the web view is out of bounds of the window.

(WTR::PlatformWebView::PlatformWebView):
(WTR::PlatformWebView::setWindowFrame):

  • WebKitTestRunner/ios/UIScriptControllerIOS.mm:

(WTR::UIScriptController::inputViewBounds):

LayoutTests:

Tweaked fixed-caret-position-after-scroll.html to account for the keyboard height, and also added a new layout
test, fixed-element-on-bottom-with-keyboard.html, which checks that the layout viewport does not change before
and after showing the keyboard, and that scrolling past the end of the document does not bump the layout
viewport past document bounds.

The rest of the changes here involve rebaselining existing tests to account for the height of the web view no
longer being equal to the height of the window.

  • editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
  • editing/caret/ios/absolute-caret-position-after-scroll.html:
  • editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
  • editing/caret/ios/fixed-caret-position-after-scroll.html:
  • editing/selection/ios/absolute-selection-after-scroll.html:
  • editing/selection/ios/fixed-selection-after-scroll.html:
  • fast/events/ios/keyboard-scrolling-distance-expected.txt:
  • fast/events/ios/keyboard-should-not-trigger-resize-expected.txt:
  • fast/events/ios/viewport-zooms-from-element-to-initial-scale-expected.txt:
  • fast/forms/ios/accessory-bar-navigation-expected.txt:
  • fast/forms/ios/focus-input-in-fixed-expected.txt:
  • fast/forms/ios/focus-input-in-iframe-expected.txt:
  • fast/forms/ios/focus-input-via-button-expected.txt:
  • fast/forms/ios/focus-input-via-button-no-scaling-expected.txt:
  • fast/forms/ios/focus-long-textarea-expected.txt:
  • fast/forms/ios/zoom-after-input-tap-expected.txt:
  • fast/forms/ios/zoom-after-input-tap-wide-input-expected.txt:
  • fast/scrolling/ios/subpixel-overflow-scrolling-with-ancestor-expected.txt:
  • fast/viewport/ios/width-is-device-width-expected.txt:
  • fast/visual-viewport/ios/fixed-element-on-bottom-with-keyboard-expected.txt: Added.
  • fast/visual-viewport/ios/fixed-element-on-bottom-with-keyboard.html: Added.
  • fast/visual-viewport/ios/zoomed-focus-in-fixed-expected.txt:
  • platform/ios-simulator/fast/scrolling/ios/clipping-ancestor-with-accelerated-scrolling-ancestor-expected.txt:
  • platform/ios-simulator/fast/scrolling/ios/overflow-scrolling-ancestor-clip-expected.txt:
  • platform/ios-simulator/fast/scrolling/ios/overflow-scrolling-ancestor-clip-size-expected.txt:
  • platform/ios-simulator/fast/scrolling/ios/scrolling-content-clip-to-viewport-expected.txt:
  • platform/ios-simulator/fast/scrolling/ios/touch-stacking-expected.txt:
  • scrollingcoordinator/ios/non-stable-viewport-scroll-expected.txt:
  • scrollingcoordinator/ios/ui-scrolling-tree-expected.txt:
Location:
trunk
Files:
2 added
46 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r209964 r209967  
     12016-12-17  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        Visual viewports: bottom fixed elements disappear behind the keyboard
     4        https://bugs.webkit.org/show_bug.cgi?id=165983
     5        <rdar://problem/29409852>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Tweaked fixed-caret-position-after-scroll.html to account for the keyboard height, and also added a new layout
     10        test, fixed-element-on-bottom-with-keyboard.html, which checks that the layout viewport does not change before
     11        and after showing the keyboard, and that scrolling past the end of the document does not bump the layout
     12        viewport past document bounds.
     13
     14        The rest of the changes here involve rebaselining existing tests to account for the height of the web view no
     15        longer being equal to the height of the window.
     16
     17        * editing/caret/ios/absolute-caret-position-after-scroll-expected.txt:
     18        * editing/caret/ios/absolute-caret-position-after-scroll.html:
     19        * editing/caret/ios/fixed-caret-position-after-scroll-expected.txt:
     20        * editing/caret/ios/fixed-caret-position-after-scroll.html:
     21        * editing/selection/ios/absolute-selection-after-scroll.html:
     22        * editing/selection/ios/fixed-selection-after-scroll.html:
     23        * fast/events/ios/keyboard-scrolling-distance-expected.txt:
     24        * fast/events/ios/keyboard-should-not-trigger-resize-expected.txt:
     25        * fast/events/ios/viewport-zooms-from-element-to-initial-scale-expected.txt:
     26        * fast/forms/ios/accessory-bar-navigation-expected.txt:
     27        * fast/forms/ios/focus-input-in-fixed-expected.txt:
     28        * fast/forms/ios/focus-input-in-iframe-expected.txt:
     29        * fast/forms/ios/focus-input-via-button-expected.txt:
     30        * fast/forms/ios/focus-input-via-button-no-scaling-expected.txt:
     31        * fast/forms/ios/focus-long-textarea-expected.txt:
     32        * fast/forms/ios/zoom-after-input-tap-expected.txt:
     33        * fast/forms/ios/zoom-after-input-tap-wide-input-expected.txt:
     34        * fast/scrolling/ios/subpixel-overflow-scrolling-with-ancestor-expected.txt:
     35        * fast/viewport/ios/width-is-device-width-expected.txt:
     36        * fast/visual-viewport/ios/fixed-element-on-bottom-with-keyboard-expected.txt: Added.
     37        * fast/visual-viewport/ios/fixed-element-on-bottom-with-keyboard.html: Added.
     38        * fast/visual-viewport/ios/zoomed-focus-in-fixed-expected.txt:
     39        * platform/ios-simulator/fast/scrolling/ios/clipping-ancestor-with-accelerated-scrolling-ancestor-expected.txt:
     40        * platform/ios-simulator/fast/scrolling/ios/overflow-scrolling-ancestor-clip-expected.txt:
     41        * platform/ios-simulator/fast/scrolling/ios/overflow-scrolling-ancestor-clip-size-expected.txt:
     42        * platform/ios-simulator/fast/scrolling/ios/scrolling-content-clip-to-viewport-expected.txt:
     43        * platform/ios-simulator/fast/scrolling/ios/touch-stacking-expected.txt:
     44        * scrollingcoordinator/ios/non-stable-viewport-scroll-expected.txt:
     45        * scrollingcoordinator/ios/ui-scrolling-tree-expected.txt:
     46
    1472016-12-17  Jer Noble  <jer.noble@apple.com>
    248
  • trunk/LayoutTests/editing/caret/ios/absolute-caret-position-after-scroll-expected.txt

    r209931 r209967  
    22
    33TEST COMPLETE
    4 The initial caret rect is: [6 17 ; 3 15]
    5 The caret rect after scrolling 1000px down is: [6 17 ; 3 15]
     4The initial caret rect is: [6 21 ; 3 15]
     5The caret rect after scrolling 1000px down is: [6 21 ; 3 15]
    66PASS finalCaretRect.top is initialCaretRect.top
    77PASS finalCaretRect.left is initialCaretRect.left
  • trunk/LayoutTests/editing/caret/ios/absolute-caret-position-after-scroll.html

    r209931 r209967  
     1<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
    12<html>
    23<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
  • trunk/LayoutTests/editing/caret/ios/fixed-caret-position-after-scroll-expected.txt

    r209931 r209967  
    22
    33TEST COMPLETE
    4 The initial caret rect is: [6 17 ; 3 15]
    5 The caret rect after scrolling 1000px down is: [6 1017 ; 3 15]
    6 PASS finalCaretRect.top - initialCaretRect.top is 1000
     4PASS finalCaretRect.top - initialCaretRect.top is 500
    75
  • trunk/LayoutTests/editing/caret/ios/fixed-caret-position-after-scroll.html

    r209931 r209967  
     1<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
    12<html>
    23<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
     
    89        }
    910
    10         input {
     11        #input {
    1112            width: 100%;
    1213            height: 50px;
     
    2728    }
    2829
    29     function tapInInputScript(tapX, tapY)
     30    function getInputViewBoundsAfterTappingInInputScript(tapX, tapY)
    3031    {
    3132        return `(function() {
    3233            uiController.didShowKeyboardCallback = function() {
    3334                uiController.doAfterNextStablePresentationUpdate(function() {
    34                     uiController.uiScriptComplete(JSON.stringify(uiController.textSelectionCaretRect));
     35                    uiController.uiScriptComplete(JSON.stringify(uiController.inputViewBounds));
    3536                });
    3637            };
     
    3940    }
    4041
    41     function simulateScrollingScript(distance)
     42    function getCaretRectAfterScrollToOffsetScript(distance)
    4243    {
    4344        return `(function() {
     
    6364        }
    6465
    65         testRunner.runUIScript(tapInInputScript(window.innerWidth / 2, 30), initialCaretRect => {
    66             initialCaretRect = JSON.parse(initialCaretRect);
    67             window.initialCaretRect = initialCaretRect;
    68             debug(`The initial caret rect is: ${toString(initialCaretRect)}`);
    69             testRunner.runUIScript(simulateScrollingScript(1000), finalCaretRect => {
    70                 finalCaretRect = JSON.parse(finalCaretRect);
    71                 window.finalCaretRect = finalCaretRect;
    72                 debug(`The caret rect after scrolling 1000px down is: ${toString(finalCaretRect)}`);
    73                 shouldBe("finalCaretRect.top - initialCaretRect.top", "1000");
    74                 testRunner.notifyDone();
     66        testRunner.runUIScript(getInputViewBoundsAfterTappingInInputScript(window.innerWidth / 2, 30), (inputViewBounds) => {
     67            window.inputViewBounds = inputViewBounds = JSON.parse(inputViewBounds);
     68            testRunner.runUIScript(getCaretRectAfterScrollToOffsetScript(inputViewBounds.height), initialCaretRect => {
     69                window.initialCaretRect = initialCaretRect = JSON.parse(initialCaretRect);
     70                testRunner.runUIScript(getCaretRectAfterScrollToOffsetScript(inputViewBounds.height + 500), finalCaretRect => {
     71                    window.finalCaretRect = finalCaretRect = JSON.parse(finalCaretRect);
     72                    shouldBe("finalCaretRect.top - initialCaretRect.top", "500");
     73                    testRunner.notifyDone();
     74                });
    7575            });
    7676        });
     
    7979</head>
    8080<body onload=run()>
    81     <input></input>
     81    <input id="input"></input>
    8282    <script src="../../../resources/js-test-post.js"></script>
    8383</body>
  • trunk/LayoutTests/editing/selection/ios/absolute-selection-after-scroll.html

    r209931 r209967  
     1<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
    12<html>
    23<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
  • trunk/LayoutTests/editing/selection/ios/fixed-selection-after-scroll.html

    r209931 r209967  
     1<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
    12<html>
    23<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
  • trunk/LayoutTests/fast/events/ios/keyboard-scrolling-distance-expected.txt

    r204385 r209967  
    33TEST COMPLETE
    44Before pressing the spacebar, window.scrollY = 0
    5 After pressing the spacebar, window.scrollY = 302
     5After pressing the spacebar, window.scrollY = 291
    66
  • trunk/LayoutTests/fast/events/ios/keyboard-should-not-trigger-resize-expected.txt

    r204385 r209967  
    33
    44TEST COMPLETE
    5 After showing the keyboard, window.innerHeight = 568
    6 After hiding the keyboard, window.innerHeight = 568
     5After showing the keyboard, window.innerHeight = 548
     6After hiding the keyboard, window.innerHeight = 548
    77
  • trunk/LayoutTests/fast/events/ios/viewport-zooms-from-element-to-initial-scale-expected.txt

    r191644 r209967  
    1 The viewport zoomed to scale: 5
     1The viewport zoomed to scale: 1.6
  • trunk/LayoutTests/fast/forms/ios/accessory-bar-navigation-expected.txt

    r204385 r209967  
    66tap location    { x: 38.000, y: 446.000 }
    77scale   0.749
    8 visibleRect     { left: 0.000, top: 279.552, width: 427.000, height: 757.925 }
     8visibleRect     { left: 0.000, top: 279.552, width: 427.000, height: 731.237 }
    99After move to second field
    1010
    1111scale   0.749
    12 visibleRect     { left: 0.000, top: 700.547, width: 427.000, height: 757.925 }
     12visibleRect     { left: 0.000, top: 700.547, width: 427.000, height: 731.237 }
    1313After move to first field
    1414
    1515scale   0.749
    16 visibleRect     { left: 0.000, top: 279.552, width: 427.000, height: 757.925 }
     16visibleRect     { left: 0.000, top: 279.552, width: 427.000, height: 731.237 }
  • trunk/LayoutTests/fast/forms/ios/focus-input-in-fixed-expected.txt

    r204385 r209967  
    22tap location    { x: 40.000, y: 130.000 }
    33scale   1.455
    4 visibleRect     { left: 0.000, top: 44.683, width: 219.979, height: 390.462 }
     4visibleRect     { left: 0.000, top: 44.683, width: 219.979, height: 376.713 }
  • trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe-expected.txt

    r204385 r209967  
    55tap location    { x: 20.000, y: 62.000 }
    66scale   1.455
    7 visibleRect     { left: 0.000, top: 1208.851, width: 219.979, height: 390.462 }
     7visibleRect     { left: 0.000, top: 1208.851, width: 219.979, height: 376.713 }
  • trunk/LayoutTests/fast/forms/ios/focus-input-via-button-expected.txt

    r204385 r209967  
    55tap location    { x: 20.000, y: 62.000 }
    66scale   1.455
    7 visibleRect     { left: 0.000, top: 798.797, width: 219.979, height: 390.462 }
     7visibleRect     { left: 0.000, top: 798.797, width: 219.979, height: 376.713 }
  • trunk/LayoutTests/fast/forms/ios/focus-input-via-button-no-scaling-expected.txt

    r204385 r209967  
    55tap location    { x: 20.000, y: 62.000 }
    66scale   0.749
    7 visibleRect     { left: 0.000, top: 717.227, width: 427.000, height: 757.925 }
     7visibleRect     { left: 0.000, top: 717.227, width: 427.000, height: 731.237 }
  • trunk/LayoutTests/fast/forms/ios/focus-long-textarea-expected.txt

    r204385 r209967  
    44tap location    { x: 38.000, y: 664.000 }
    55scale   1.455
    6 visibleRect     { left: 0.000, top: 506.294, width: 219.979, height: 390.462 }
     6visibleRect     { left: 0.000, top: 506.294, width: 219.979, height: 376.713 }
  • trunk/LayoutTests/fast/forms/ios/zoom-after-input-tap-expected.txt

    r204385 r209967  
    44tap location    { x: 38.000, y: 862.000 }
    55scale   1.455
    6 visibleRect     { left: 0.000, top: 776.799, width: 219.979, height: 390.462 }
     6visibleRect     { left: 0.000, top: 776.799, width: 219.979, height: 376.713 }
  • trunk/LayoutTests/fast/forms/ios/zoom-after-input-tap-wide-input-expected.txt

    r204385 r209967  
    44tap location    { x: 328.000, y: 862.000 }
    55scale   1.455
    6 visibleRect     { left: 122.707, top: 776.803, width: 219.980, height: 390.464 }
     6visibleRect     { left: 122.707, top: 776.803, width: 219.980, height: 376.715 }
  • trunk/LayoutTests/fast/scrolling/ios/subpixel-overflow-scrolling-with-ancestor-expected.txt

    r204552 r209967  
    11(GraphicsLayer
    22  (anchor 0.00 0.00)
    3   (bounds 320.00 568.00)
     3  (bounds 320.00 548.00)
    44  (children 1
    55    (GraphicsLayer
    6       (bounds 320.00 568.00)
     6      (bounds 320.00 548.00)
    77      (contentsOpaque 1)
    88      (children 1
  • trunk/LayoutTests/fast/viewport/ios/width-is-device-width-expected.txt

    r204363 r209967  
    44maxScale        5.00000
    55minScale        1.00000
    6 visibleRect     {"left":"0.00000","top":"0.00000","width":"320.00000","height":"568.00000"}
     6visibleRect     {"left":"0.00000","top":"0.00000","width":"320.00000","height":"548.00000"}
  • trunk/LayoutTests/fast/visual-viewport/ios/zoomed-focus-in-fixed-expected.txt

    r209887 r209967  
    1 Layout viewport: {"top":659.734375,"right":320,"bottom":1227.734375,"left":0,"width":320,"height":568}
    2 Visual viewport: {"top":660,"right":220,"bottom":1051,"left":0,"width":220,"height":391}
     1Layout viewport: {"top":746.703125,"right":320,"bottom":1294.703125,"left":0,"width":320,"height":548}
     2Visual viewport: {"top":747,"right":220,"bottom":1124,"left":0,"width":220,"height":377}
    33
  • trunk/LayoutTests/platform/ios-simulator/fast/scrolling/ios/clipping-ancestor-with-accelerated-scrolling-ancestor-expected.txt

    r204363 r209967  
    1 layer at (0,0) size 320x568
    2   RenderView at (0,0) size 320x568
     1layer at (0,0) size 320x548
     2  RenderView at (0,0) size 320x548
    33layer at (0,0) size 320x316
    44  RenderBlock {HTML} at (0,0) size 320x316
  • trunk/LayoutTests/platform/ios-simulator/fast/scrolling/ios/overflow-scrolling-ancestor-clip-expected.txt

    r204363 r209967  
    11(GraphicsLayer
    22  (anchor 0.00 0.00)
    3   (bounds 320.00 568.00)
     3  (bounds 320.00 548.00)
    44  (children 1
    55    (GraphicsLayer
    6       (bounds 320.00 568.00)
     6      (bounds 320.00 548.00)
    77      (contentsOpaque 1)
    88      (children 1
  • trunk/LayoutTests/platform/ios-simulator/fast/scrolling/ios/overflow-scrolling-ancestor-clip-size-expected.txt

    r204363 r209967  
    11(GraphicsLayer
    22  (anchor 0.00 0.00)
    3   (bounds 330.00 568.00)
     3  (bounds 330.00 548.00)
    44  (children 1
    55    (GraphicsLayer
    6       (bounds 330.00 568.00)
     6      (bounds 330.00 548.00)
    77      (contentsOpaque 1)
    88      (children 1
  • trunk/LayoutTests/platform/ios-simulator/fast/scrolling/ios/scrolling-content-clip-to-viewport-expected.txt

    r204363 r209967  
    11(GraphicsLayer
    22  (anchor 0.00 0.00)
    3   (bounds 320.00 568.00)
     3  (bounds 320.00 548.00)
    44  (children 1
    55    (GraphicsLayer
    6       (bounds 320.00 568.00)
     6      (bounds 320.00 548.00)
    77      (contentsOpaque 1)
    88      (children 1
  • trunk/LayoutTests/platform/ios-simulator/fast/scrolling/ios/touch-stacking-expected.txt

    r204363 r209967  
    1 layer at (0,0) size 320x568
    2   RenderView at (0,0) size 320x568
     1layer at (0,0) size 320x548
     2  RenderView at (0,0) size 320x548
    33layer at (0,0) size 320x148 layerType: background only
    44layer at (0,0) size 100x100
  • trunk/LayoutTests/scrollingcoordinator/ios/non-stable-viewport-scroll-expected.txt

    r209409 r209967  
    33  (anchor 0.00 0.00)
    44  (bounds 320.00 5013.00)
    5   (visible rect 0.00, 1000.00 106.67 x 189.33)
    6   (coverage rect 0.00, 1000.00 106.67 x 189.33)
     5  (visible rect 0.00, 1000.00 106.67 x 182.67)
     6  (coverage rect 0.00, 1000.00 106.67 x 182.67)
    77  (intersects coverage rect 1)
    88  (contentsScale 6.00)
     
    1111      (bounds 320.00 5013.00)
    1212      (contentsOpaque 1)
    13       (visible rect 0.00, 1000.00 106.67 x 189.33)
    14       (coverage rect 0.00, 957.33 192.00 x 274.67)
     13      (visible rect 0.00, 1000.00 106.67 x 182.67)
     14      (coverage rect 0.00, 957.33 192.00 x 268.00)
    1515      (intersects coverage rect 1)
    1616      (contentsScale 6.00)
     
    1818        (GraphicsLayer
    1919          (position 10.00 0.00)
    20           (approximate position 10.00 621.34)
    21           (bounds 100.00 568.00)
     20          (approximate position 10.00 634.67)
     21          (bounds 100.00 548.00)
    2222          (usingTiledLayer 1)
    2323          (contentsOpaque 1)
    2424          (drawsContent 1)
    25           (visible rect 0.00, 378.66 96.67 x 189.33)
    26           (coverage rect -10.00, 335.99 192.00 x 274.67)
     25          (visible rect 0.00, 365.33 96.67 x 182.67)
     26          (coverage rect -10.00, 322.66 192.00 x 268.00)
    2727          (intersects coverage rect 1)
    2828          (contentsScale 6.00)
  • trunk/LayoutTests/scrollingcoordinator/ios/ui-scrolling-tree-expected.txt

    r209409 r209967  
    22(scrolling tree
    33  (frame scrolling node
    4     (layout viewport (0,0) width=320 height=568)
     4    (layout viewport (0,0) width=320 height=548)
    55    (min layoutViewport origin (0,0))
    6     (max layoutViewport origin (988,1453))
     6    (max layoutViewport origin (988,1473))
    77    (behavior for fixed 0)
    88    (fixed node
    99      (fixed constraints
    10         (viewport-rect-at-last-layout (0,0) width=320 height=568)
     10        (viewport-rect-at-last-layout (0,0) width=320 height=548)
    1111        (layer-position-at-last-layout (12,10)))
    1212      (layer top left (12,10))))
  • trunk/Source/WebKit2/ChangeLog

    r209957 r209967  
     12016-12-17  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        Visual viewports: bottom fixed elements disappear behind the keyboard
     4        https://bugs.webkit.org/show_bug.cgi?id=165983
     5        <rdar://problem/29409852>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Accounts for input view bounds in WebPageProxy::computeCustomFixedPositionRect. To do this, we introduce and
     10        pass unobscuredContentRectRespectingInputViewBounds along with the regular unobscuredContentRect (which does not
     11        respect the obscuring keyboard rect). This unobscuredContentRectRespectingInputViewBounds is then used when
     12        computing the origin of the updated layout viewport rect (and also, when we are _not_ below minimum scale),
     13       
     14        Additionally, the size is computed using the (unconstrained) unobscured rect. This is because we previously
     15        would use the document-constrained version of the unobscured rect, which caused the layout viewport to shrink
     16        when approaching the max scroll extents of the document while the keyboard is up, since the unobscured rect
     17        would spill out of the document rect. However, using this unconstrained rect's size also means that if the user
     18        rubber-bands out of the document rect, we would end up pushing the layout viewport rect out of the document,
     19        with no way of adjusting it back in without the user scrolling to push the layout viewport into back document
     20        bounds. To address this, we move the layout rect to be within document bounds after computing its size and
     21        location.
     22
     23        Added a new layout test: fast/visual-viewport/ios/fixed-element-on-bottom-with-keyboard.html, and also tweaked
     24        fixed-caret-position-after-scroll.html to cover these changes.
     25
     26        * Shared/VisibleContentRectUpdateInfo.cpp:
     27        (WebKit::operator<<):
     28        * Shared/VisibleContentRectUpdateInfo.h:
     29        (WebKit::VisibleContentRectUpdateInfo::VisibleContentRectUpdateInfo):
     30        (WebKit::VisibleContentRectUpdateInfo::unobscuredContentRectRespectingInputViewBounds):
     31        * UIProcess/API/Cocoa/WKWebView.mm:
     32        (-[WKWebView _updateContentRectsWithState:]):
     33        (-[WKWebView _inputViewBounds]):
     34
     35        Returns the current bounds of the input view. For testing purposes.
     36
     37        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
     38        * UIProcess/WebPageProxy.h:
     39        (WebKit::WebPageProxy::unobscuredContentRectRespectingInputViewBounds):
     40        * UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm:
     41        (WebKit::RemoteScrollingCoordinatorProxy::customFixedPositionRect):
     42        * UIProcess/ios/WKContentView.h:
     43        * UIProcess/ios/WKContentView.mm:
     44        (-[WKContentView _computeUnobscuredContentRectRespectingInputViewBounds:unobscuredContentRect:inputViewBounds:scale:]):
     45
     46        Helper to compute the unobscured rect, accounting for the bounds of the current input view.
     47
     48        (-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInset:inputViewBounds:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]):
     49        (-[WKContentView _didCommitLayerTree:]):
     50        (-[WKContentView didUpdateVisibleRect:unobscuredRect:unobscuredRectInScrollViewCoordinates:obscuredInset:scale:minimumScale:inStableState:isChangingObscuredInsetsInteractively:enclosedInScrollableAncestorView:]): Deleted.
     51        * UIProcess/ios/WebPageProxyIOS.mm:
     52        (WebKit::WebPageProxy::computeCustomFixedPositionRect):
     53        * UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
     54        (WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
     55
    1562016-12-16  Ryosuke Niwa  <rniwa@webkit.org>
    257
  • trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.cpp

    r209845 r209967  
    110110    ts.dumpProperty("unobscuredContentRect", info.unobscuredContentRect());
    111111    ts.dumpProperty("unobscuredRectInScrollViewCoordinates", info.unobscuredRectInScrollViewCoordinates());
     112    ts.dumpProperty("unobscuredContentRectRespectingInputViewBounds", info.unobscuredContentRectRespectingInputViewBounds());
    112113    ts.dumpProperty("customFixedPositionRect", info.customFixedPositionRect());
    113114    ts.dumpProperty("obscuredInset", info.obscuredInset());
  • trunk/Source/WebKit2/Shared/VisibleContentRectUpdateInfo.h

    r209845 r209967  
    4646
    4747    VisibleContentRectUpdateInfo(const WebCore::FloatRect& exposedContentRect, const WebCore::FloatRect& unobscuredContentRect,
    48         const WebCore::FloatRect& unobscuredRectInScrollViewCoordinates, const WebCore::FloatRect& customFixedPositionRect,
     48        const WebCore::FloatRect& unobscuredRectInScrollViewCoordinates, const WebCore::FloatRect& unobscuredContentRectRespectingInputViewBounds, const WebCore::FloatRect& customFixedPositionRect,
    4949        const WebCore::FloatSize& obscuredInset, double scale, bool inStableState, bool isFirstUpdateForNewViewSize, bool isChangingObscuredInsetsInteractively, bool allowShrinkToFit, bool enclosedInScrollableAncestorView,
    5050        MonotonicTime timestamp, double horizontalVelocity, double verticalVelocity, double scaleChangeRate, uint64_t lastLayerTreeTransactionId)
     
    5252        , m_unobscuredContentRect(unobscuredContentRect)
    5353        , m_unobscuredRectInScrollViewCoordinates(unobscuredRectInScrollViewCoordinates)
     54        , m_unobscuredContentRectRespectingInputViewBounds(unobscuredContentRectRespectingInputViewBounds)
    5455        , m_customFixedPositionRect(customFixedPositionRect)
    5556        , m_obscuredInset(obscuredInset)
     
    7172    const WebCore::FloatRect& unobscuredContentRect() const { return m_unobscuredContentRect; }
    7273    const WebCore::FloatRect& unobscuredRectInScrollViewCoordinates() const { return m_unobscuredRectInScrollViewCoordinates; }
     74    const WebCore::FloatRect& unobscuredContentRectRespectingInputViewBounds() const { return m_unobscuredContentRectRespectingInputViewBounds; }
    7375    const WebCore::FloatRect& customFixedPositionRect() const { return m_customFixedPositionRect; }
    7476    const WebCore::FloatSize obscuredInset() const { return m_obscuredInset; }
     
    9799    WebCore::FloatRect m_unobscuredContentRect;
    98100    WebCore::FloatRect m_unobscuredRectInScrollViewCoordinates;
     101    WebCore::FloatRect m_unobscuredContentRectRespectingInputViewBounds;
    99102    WebCore::FloatRect m_customFixedPositionRect; // When visual viewports are enabled, this is the layout viewport.
    100103    WebCore::FloatSize m_obscuredInset;
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm

    r209931 r209967  
    21632163        unobscuredRectInScrollViewCoordinates:unobscuredRect
    21642164        obscuredInset:CGSizeMake(_obscuredInsets.left, _obscuredInsets.top)
     2165        inputViewBounds:_inputViewBounds
    21652166        scale:scaleFactor minimumScale:[_scrollView minimumZoomScale]
    21662167        inStableState:inStableState
     
    47534754}
    47544755
     4756- (CGRect)_inputViewBounds
     4757{
     4758    return _inputViewBounds;
     4759}
     4760
    47554761- (NSArray<NSValue *> *)_uiTextSelectionRects
    47564762{
  • trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h

    r209931 r209967  
    292292@property (nonatomic, readonly) NSArray<NSValue *> *_uiTextSelectionRects WK_API_AVAILABLE(ios(WK_IOS_TBA));
    293293@property (nonatomic, readonly) CGRect _uiTextCaretRect WK_API_AVAILABLE(ios(WK_IOS_TBA));
     294@property (nonatomic, readonly) CGRect _inputViewBounds WK_API_AVAILABLE(ios(WK_IOS_TBA));
    294295
    295296@property (nonatomic, readonly) NSString *_scrollingTreeAsText WK_API_AVAILABLE(ios(WK_IOS_TBA));
  • trunk/Source/WebKit2/UIProcess/WebPageProxy.h

    r209931 r209967  
    469469    const WebCore::FloatRect& unobscuredContentRect() const { return m_lastVisibleContentRectUpdate.unobscuredContentRect(); }
    470470    bool inStableState() const { return m_lastVisibleContentRectUpdate.inStableState(); }
     471    const WebCore::FloatRect& unobscuredContentRectRespectingInputViewBounds() const { return m_lastVisibleContentRectUpdate.unobscuredContentRectRespectingInputViewBounds(); }
    471472    // When visual viewports are enabled, this is the layout viewport rect.
    472473    const WebCore::FloatRect& customFixedPositionRect() const { return m_lastVisibleContentRectUpdate.customFixedPositionRect(); }
     
    476477
    477478    enum class UnobscuredRectConstraint { ConstrainedToDocumentRect, Unconstrained };
    478     WebCore::FloatRect computeCustomFixedPositionRect(const WebCore::FloatRect& unobscuredContentRect, const WebCore::FloatRect& currentCustomFixedPositionRect, double displayedContentScale, UnobscuredRectConstraint = UnobscuredRectConstraint::Unconstrained, bool visualViewportEnabled = false) const;
     479    WebCore::FloatRect computeCustomFixedPositionRect(const WebCore::FloatRect& unobscuredContentRect, const WebCore::FloatRect& unobscuredContentRectRespectingInputViewBounds, const WebCore::FloatRect& currentCustomFixedPositionRect, double displayedContentScale, UnobscuredRectConstraint = UnobscuredRectConstraint::Unconstrained, bool visualViewportEnabled = false) const;
    479480
    480481    void overflowScrollViewWillStartPanGesture();
  • trunk/Source/WebKit2/UIProcess/ios/RemoteScrollingCoordinatorProxyIOS.mm

    r208748 r209967  
    9595FloatRect RemoteScrollingCoordinatorProxy::customFixedPositionRect() const
    9696{
    97     return m_webPageProxy.computeCustomFixedPositionRect(m_webPageProxy.unobscuredContentRect(), m_webPageProxy.customFixedPositionRect(), m_webPageProxy.displayedContentScale());
     97    return m_webPageProxy.computeCustomFixedPositionRect(m_webPageProxy.unobscuredContentRect(), m_webPageProxy.unobscuredContentRectRespectingInputViewBounds(), m_webPageProxy.customFixedPositionRect(), m_webPageProxy.displayedContentScale());
    9898}
    9999
  • trunk/Source/WebKit2/UIProcess/ios/WKContentView.h

    r209867 r209967  
    7272    unobscuredRectInScrollViewCoordinates:(CGRect)unobscuredRectInScrollViewCoordinates
    7373    obscuredInset:(CGSize)topInset
     74    inputViewBounds:(CGRect)inputViewBounds
    7475    scale:(CGFloat)scale minimumScale:(CGFloat)minimumScale
    7576    inStableState:(BOOL)isStableState
  • trunk/Source/WebKit2/UIProcess/ios/WKContentView.mm

    r209931 r209967  
    373373}
    374374
     375- (CGRect)_computeUnobscuredContentRectRespectingInputViewBounds:(CGRect)visibleContentRect unobscuredContentRect:(CGRect)unobscuredContentRect inputViewBounds:(CGRect)inputViewBounds scale:(CGFloat)scale
     376{
     377    if (inputViewBounds.size.height)
     378        unobscuredContentRect.size.height = std::min<float>(unobscuredContentRect.size.height, visibleContentRect.origin.y + (inputViewBounds.origin.y / scale) - unobscuredContentRect.origin.y);
     379    return unobscuredContentRect;
     380}
     381
    375382- (void)didUpdateVisibleRect:(CGRect)visibleContentRect
    376383    unobscuredRect:(CGRect)unobscuredContentRect
    377384    unobscuredRectInScrollViewCoordinates:(CGRect)unobscuredRectInScrollViewCoordinates
    378385    obscuredInset:(CGSize)obscuredInset
     386    inputViewBounds:(CGRect)inputViewBounds
    379387    scale:(CGFloat)zoomScale minimumScale:(CGFloat)minimumScale
    380388    inStableState:(BOOL)isStableState
     
    394402
    395403    RemoteScrollingCoordinatorProxy* scrollingCoordinator = _page->scrollingCoordinatorProxy();
    396     FloatRect fixedPositionRectForLayout = _page->computeCustomFixedPositionRect(unobscuredContentRect, _page->customFixedPositionRect(), zoomScale, WebPageProxy::UnobscuredRectConstraint::ConstrainedToDocumentRect, scrollingCoordinator->visualViewportEnabled());
     404
     405    CGRect unobscuredContentRectRespectingInputViewBounds = [self _computeUnobscuredContentRectRespectingInputViewBounds:visibleContentRect unobscuredContentRect:unobscuredContentRect inputViewBounds:inputViewBounds scale:zoomScale];
     406    FloatRect fixedPositionRectForLayout = _page->computeCustomFixedPositionRect(unobscuredContentRect, unobscuredContentRectRespectingInputViewBounds, _page->customFixedPositionRect(), zoomScale, WebPageProxy::UnobscuredRectConstraint::ConstrainedToDocumentRect, scrollingCoordinator->visualViewportEnabled());
    397407
    398408    VisibleContentRectUpdateInfo visibleContentRectUpdateInfo(
     
    400410        unobscuredContentRect,
    401411        unobscuredRectInScrollViewCoordinates,
     412        unobscuredContentRectRespectingInputViewBounds,
    402413        fixedPositionRectForLayout,
    403414        WebCore::FloatSize(obscuredInset),
     
    421432    _sizeChangedSinceLastVisibleContentRectUpdate = NO;
    422433
    423     FloatRect fixedPositionRect = _page->computeCustomFixedPositionRect(_page->unobscuredContentRect(), _page->customFixedPositionRect(), zoomScale, WebPageProxy::UnobscuredRectConstraint::Unconstrained, scrollingCoordinator->visualViewportEnabled());
     434    FloatRect fixedPositionRect = _page->computeCustomFixedPositionRect(_page->unobscuredContentRect(), _page->unobscuredContentRectRespectingInputViewBounds(), _page->customFixedPositionRect(), zoomScale, WebPageProxy::UnobscuredRectConstraint::Unconstrained, scrollingCoordinator->visualViewportEnabled());
    424435    scrollingCoordinator->viewportChangedViaDelegatedScrolling(scrollingCoordinator->rootScrollingNodeID(), fixedPositionRect, zoomScale);
    425436
     
    560571    if (boundsChanged) {
    561572        // FIXME: factor computeCustomFixedPositionRect() into something that gives us this rect.
    562         FloatRect fixedPositionRect = _page->computeCustomFixedPositionRect(_page->unobscuredContentRect(), _page->customFixedPositionRect(), [[_webView scrollView] zoomScale]);
     573        FloatRect fixedPositionRect = _page->computeCustomFixedPositionRect(_page->unobscuredContentRect(), _page->unobscuredContentRectRespectingInputViewBounds(), _page->customFixedPositionRect(), [[_webView scrollView] zoomScale]);
    563574        [self updateFixedClippingView:fixedPositionRect];
    564575
  • trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm

    r209867 r209967  
    221221
    222222// FIXME: rename this when visual viewports are the default.
    223 WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect& unobscuredContentRect, const FloatRect& currentCustomFixedPositionRect, double displayedContentScale, UnobscuredRectConstraint constraint, bool visualViewportEnabled) const
     223WebCore::FloatRect WebPageProxy::computeCustomFixedPositionRect(const FloatRect& unobscuredContentRect, const FloatRect& unobscuredContentRectRespectingInputViewBounds, const FloatRect& currentCustomFixedPositionRect, double displayedContentScale, UnobscuredRectConstraint constraint, bool visualViewportEnabled) const
    224224{
    225225    FloatRect constrainedUnobscuredRect = unobscuredContentRect;
     
    233233
    234234    double minimumScale = m_pageClient.minimumZoomScale();
    235    
    236     if (displayedContentScale < minimumScale) {
     235    bool isBelowMinimumScale = displayedContentScale < minimumScale;
     236    if (isBelowMinimumScale) {
    237237        const CGFloat slope = 12;
    238238        CGFloat factor = std::max<CGFloat>(1 - slope * (minimumScale - displayedContentScale), 0);
     
    244244    }
    245245   
    246     if (visualViewportEnabled) {
    247         FloatRect layoutViewportRect = currentCustomFixedPositionRect;
    248        
    249         // The layout viewport is never smaller than m_baseLayoutViewportSize, and never be smaller than the constrainedUnobscuredRect.
    250         FloatSize constrainedSize = m_baseLayoutViewportSize;
     246    if (!visualViewportEnabled)
     247        return FrameView::rectForViewportConstrainedObjects(enclosingLayoutRect(constrainedUnobscuredRect), LayoutSize(documentRect.size()), displayedContentScale, false, StickToViewportBounds);
     248
     249    FloatRect layoutViewportRect = currentCustomFixedPositionRect;
     250
     251    // The layout viewport is never smaller than m_baseLayoutViewportSize, and never be smaller than the constrainedUnobscuredRect.
     252    FloatSize constrainedSize = m_baseLayoutViewportSize;
     253    if (isBelowMinimumScale)
    251254        layoutViewportRect.setSize(constrainedSize.expandedTo(constrainedUnobscuredRect.size()));
    252 
    253         LayoutPoint layoutViewportOrigin = FrameView::computeLayoutViewportOrigin(enclosingLayoutRect(constrainedUnobscuredRect), m_minStableLayoutViewportOrigin, m_maxStableLayoutViewportOrigin, enclosingLayoutRect(layoutViewportRect));
    254         layoutViewportRect.setLocation(layoutViewportOrigin);
    255 
    256         if (layoutViewportRect != currentCustomFixedPositionRect)
    257             LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::computeCustomFixedPositionRect: new layout viewport  " << layoutViewportRect);
    258         return layoutViewportRect;
    259     }
    260    
    261     return FrameView::rectForViewportConstrainedObjects(enclosingLayoutRect(constrainedUnobscuredRect), LayoutSize(documentRect.size()), displayedContentScale, false, StickToViewportBounds);
     255    else
     256        layoutViewportRect.setSize(constrainedSize.expandedTo(unobscuredContentRect.size()));
     257
     258    LayoutPoint layoutViewportOrigin;
     259    if (isBelowMinimumScale)
     260        layoutViewportOrigin = FrameView::computeLayoutViewportOrigin(enclosingLayoutRect(constrainedUnobscuredRect), m_minStableLayoutViewportOrigin, m_maxStableLayoutViewportOrigin, enclosingLayoutRect(layoutViewportRect));
     261    else
     262        layoutViewportOrigin = FrameView::computeLayoutViewportOrigin(enclosingLayoutRect(unobscuredContentRectRespectingInputViewBounds), m_minStableLayoutViewportOrigin, m_maxStableLayoutViewportOrigin, enclosingLayoutRect(layoutViewportRect));
     263
     264    if (constraint == UnobscuredRectConstraint::ConstrainedToDocumentRect) {
     265        // The max stable layout viewport origin really depends on the size of the layout viewport itself, so we need to adjust the location of the layout viewport one final time to make sure it does not end up out of bounds of the document.
     266        // Without this adjustment (and with using the non-constrained unobscuredContentRect's size as the size of the layout viewport) the layout viewport can be pushed past the bounds of the document during rubber-banding, and cannot be pushed
     267        // back in until the user scrolls back in the other direction.
     268        layoutViewportOrigin.setX(clampTo<float>(layoutViewportOrigin.x(), 0, documentRect.width() - layoutViewportRect.width()));
     269        layoutViewportOrigin.setY(clampTo<float>(layoutViewportOrigin.y(), 0, documentRect.height() - layoutViewportRect.height()));
     270    }
     271    layoutViewportRect.setLocation(layoutViewportOrigin);
     272   
     273    if (layoutViewportRect != currentCustomFixedPositionRect)
     274        LOG_WITH_STREAM(VisibleRects, stream << "WebPageProxy::computeCustomFixedPositionRect: new layout viewport  " << layoutViewportRect);
     275    return layoutViewportRect;
    262276}
    263277
  • trunk/Source/WebKit2/UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm

    r209369 r209967  
    215215    if (m_webPageProxy.scrollingCoordinatorProxy()->hasFixedOrSticky()) {
    216216        // If we got a new layer for a fixed or sticky node, its position from the WebProcess is probably stale. We need to re-run the "viewport" changed logic to udpate it with our UI-side state.
    217         FloatRect customFixedPositionRect = m_webPageProxy.computeCustomFixedPositionRect(m_webPageProxy.unobscuredContentRect(), m_webPageProxy.customFixedPositionRect(), m_webPageProxy.displayedContentScale(), WebPageProxy::UnobscuredRectConstraint::Unconstrained, m_webPageProxy.scrollingCoordinatorProxy()->visualViewportEnabled());
     217        FloatRect customFixedPositionRect = m_webPageProxy.computeCustomFixedPositionRect(m_webPageProxy.unobscuredContentRect(), m_webPageProxy.unobscuredContentRectRespectingInputViewBounds(), m_webPageProxy.customFixedPositionRect(), m_webPageProxy.displayedContentScale(), WebPageProxy::UnobscuredRectConstraint::Unconstrained, m_webPageProxy.scrollingCoordinatorProxy()->visualViewportEnabled());
    218218        m_webPageProxy.scrollingCoordinatorProxy()->viewportChangedViaDelegatedScrolling(m_webPageProxy.scrollingCoordinatorProxy()->rootScrollingNodeID(), customFixedPositionRect, m_webPageProxy.displayedContentScale());
    219219    }
  • trunk/Tools/ChangeLog

    r209957 r209967  
     12016-12-17  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        Visual viewports: bottom fixed elements disappear behind the keyboard
     4        https://bugs.webkit.org/show_bug.cgi?id=165983
     5        <rdar://problem/29409852>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Add support for UIScriptController.inputViewBounds, which UI-side scripts may use to fetch the bounding rect of
     10        the keyboard when it is up.
     11
     12        * DumpRenderTree/ios/UIScriptControllerIOS.mm:
     13        (WTR::UIScriptController::inputViewBounds):
     14        * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
     15        * TestRunnerShared/UIScriptContext/UIScriptController.cpp:
     16        (WTR::UIScriptController::inputViewBounds):
     17        * TestRunnerShared/UIScriptContext/UIScriptController.h:
     18        * WebKitTestRunner/ios/PlatformWebViewIOS.mm:
     19        (WTR::viewRectForWindowRect):
     20
     21        Previously, we accounted for the status bar height by translating the entire web view down by the height of the
     22        status bar. However, we did not shrink the height of the web view itself, which means that for tests which
     23        involve scrolling past the end of the document, the bottom strip of the web view is out of bounds of the window.
     24
     25        (WTR::PlatformWebView::PlatformWebView):
     26        (WTR::PlatformWebView::setWindowFrame):
     27        * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
     28        (WTR::UIScriptController::inputViewBounds):
     29
    1302016-12-16  Ryosuke Niwa  <rniwa@webkit.org>
    231
  • trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm

    r209931 r209967  
    272272}
    273273
     274JSObjectRef UIScriptController::inputViewBounds() const
     275{
     276    return nullptr;
     277}
     278
    274279void UIScriptController::removeAllDynamicDictionaries()
    275280{
  • trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl

    r209931 r209967  
    207207    readonly attribute object selectionRangeViewRects; // An array of objects with 'left', 'top', 'width', and 'height' properties.
    208208    readonly attribute object textSelectionCaretRect; // An object with 'left', 'top', 'width', 'height' properties.
     209    readonly attribute object inputViewBounds;
    209210
    210211    void insertText(DOMString text, long location, long length);
  • trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp

    r209931 r209967  
    317317}
    318318
     319JSObjectRef UIScriptController::inputViewBounds() const
     320{
     321    return nullptr;
     322}
     323
    319324void UIScriptController::removeAllDynamicDictionaries()
    320325{
  • trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h

    r209931 r209967  
    131131    JSObjectRef selectionRangeViewRects() const;
    132132    JSObjectRef textSelectionCaretRect() const;
     133    JSObjectRef inputViewBounds() const;
    133134
    134135    void insertText(JSStringRef, int location, int length);
  • trunk/Tools/WebKitTestRunner/ios/PlatformWebViewIOS.mm

    r209364 r209967  
    110110namespace WTR {
    111111
    112 static CGRect viewRectForWindowRect(CGRect windowRect)
     112enum class WebViewSizingMode {
     113    Default,
     114    HeightRespectsStatusBar
     115};
     116
     117static CGRect viewRectForWindowRect(CGRect windowRect, WebViewSizingMode mode)
    113118{
    114119    CGFloat statusBarBottom = CGRectGetMaxY([[UIApplication sharedApplication] statusBarFrame]);
    115     return CGRectMake(windowRect.origin.x, windowRect.origin.y + statusBarBottom, windowRect.size.width, windowRect.size.height);
     120    return CGRectMake(windowRect.origin.x, windowRect.origin.y + statusBarBottom, windowRect.size.width, windowRect.size.height - (mode == WebViewSizingMode::HeightRespectsStatusBar ? statusBarBottom : 0));
    116121}
    117122
     
    130135    [viewController release];
    131136
    132     m_view = [[TestRunnerWKWebView alloc] initWithFrame:viewRectForWindowRect(rect) configuration:configuration];
     137    m_view = [[TestRunnerWKWebView alloc] initWithFrame:viewRectForWindowRect(rect, WebViewSizingMode::Default) configuration:configuration];
    133138
    134139    [m_window.rootViewController.view addSubview:m_view];
     
    196201{
    197202    [m_window setFrame:CGRectMake(frame.origin.x, frame.origin.y, frame.size.width, frame.size.height)];
    198     [platformView() setFrame:viewRectForWindowRect(CGRectMake(0, 0, frame.size.width, frame.size.height))];
     203    [platformView() setFrame:viewRectForWindowRect(CGRectMake(0, 0, frame.size.width, frame.size.height), WebViewSizingMode::HeightRespectsStatusBar)];
    199204}
    200205
  • trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm

    r209931 r209967  
    496496}
    497497
     498JSObjectRef UIScriptController::inputViewBounds() const
     499{
     500    return JSValueToObject(m_context->jsContext(), [JSValue valueWithObject:toNSDictionary(TestController::singleton().mainWebView()->platformView()._inputViewBounds) inContext:[JSContext contextWithJSGlobalContextRef:m_context->jsContext()]].JSValueRef, nullptr);
     501}
     502
    498503void UIScriptController::removeAllDynamicDictionaries()
    499504{
Note: See TracChangeset for help on using the changeset viewer.