Title: [249296] trunk
Revision
249296
Author
wenson_hs...@apple.com
Date
2019-08-29 15:17:46 -0700 (Thu, 29 Aug 2019)

Log Message

[iOS 13] Caret does not appear in text field if the body element is translated completely out of the viewport
https://bugs.webkit.org/show_bug.cgi?id=201287
<rdar://problem/54780864>

Reviewed by Tim Horton.

Source/WebKit:

During EditorState computation, we use the hidden editable element heuristic to determine whether we should
begin suppressing selection gestures and UI. Currently, we use the editable root of the selection range to
determine where in the layer tree we should start our ascent, in search of a completely transparent or
completely clipped container.

However, in the case where the selection is inside a focused text field, this causes us to walk up the layer
tree starting at the RenderLayer corresponding to the text field's inner contenteditable div, which is different
than the text field's enclosing RenderLayer in the case where the containing block is transformed, such that no
part of it is within the visible viewport. This scenario is exercised by the below test case, in which the caret
after transforming the body horizontally by -100vw is hidden due to a false positive in the hidden editable area
heuristic.

Fix this by starting the layer tree ascent from the enclosing layer of the text form control if applicable,
instead of the inner editable area under the shadow root of the form control.

Test: editing/selection/ios/show-selection-in-transformed-container.html

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::platformEditorState const):

LayoutTests:

Add a new layout test that covers this scenario. See WebKit ChangeLog for additional detail.

* editing/selection/ios/show-selection-in-transformed-container-expected.txt: Added.
* editing/selection/ios/show-selection-in-transformed-container.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (249295 => 249296)


--- trunk/LayoutTests/ChangeLog	2019-08-29 22:01:53 UTC (rev 249295)
+++ trunk/LayoutTests/ChangeLog	2019-08-29 22:17:46 UTC (rev 249296)
@@ -1,3 +1,16 @@
+2019-08-29  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS 13] Caret does not appear in text field if the body element is translated completely out of the viewport
+        https://bugs.webkit.org/show_bug.cgi?id=201287
+        <rdar://problem/54780864>
+
+        Reviewed by Tim Horton.
+
+        Add a new layout test that covers this scenario. See WebKit ChangeLog for additional detail.
+
+        * editing/selection/ios/show-selection-in-transformed-container-expected.txt: Added.
+        * editing/selection/ios/show-selection-in-transformed-container.html: Added.
+
 2019-08-29  Ryosuke Niwa  <rn...@webkit.org>
 
         Flaky Test: svg/custom/tabindex-order.html

Added: trunk/LayoutTests/editing/selection/ios/show-selection-in-transformed-container-expected.txt (0 => 249296)


--- trunk/LayoutTests/editing/selection/ios/show-selection-in-transformed-container-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/selection/ios/show-selection-in-transformed-container-expected.txt	2019-08-29 22:17:46 UTC (rev 249296)
@@ -0,0 +1,19 @@
+
+
+Apply transform
+This test verifies that after focusing a visible input field in a body element that has been translated horizontally out of view, the caret is still visible. To run the test manually, first tap the input field and check that the caret shows up. Then, tap the button to apply the CSS transform, tap the input field again, and check that the caret is still visible.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+PASS caretBefore.left is 20
+PASS caretBefore.top is 14
+PASS caretBefore.width is 2
+PASS caretBefore.height is 23
+PASS caretAfter.left is 20
+PASS caretAfter.top is 14
+PASS caretAfter.width is 2
+PASS caretAfter.height is 23
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/editing/selection/ios/show-selection-in-transformed-container.html (0 => 249296)


--- trunk/LayoutTests/editing/selection/ios/show-selection-in-transformed-container.html	                        (rev 0)
+++ trunk/LayoutTests/editing/selection/ios/show-selection-in-transformed-container.html	2019-08-29 22:17:46 UTC (rev 249296)
@@ -0,0 +1,89 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+<html>
+<head>
+<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
+<script src=""
+<script src=""
+<style>
+.container {
+    width: 100%;
+    display: -webkit-box;
+}
+
+.container > div {
+    width: 100vw;
+}
+
+.hidden {
+    overflow: hidden;
+}
+
+input {
+    font-size: 18px;
+}
+
+button {
+    margin: 1em;
+}
+
+.translated {
+    transform: translate3d(-100vw, 0, 0);
+}
+</style>
+<script>
+jsTestIsAsync = true;
+
+async function waitForCaretToAppear() {
+    while (true) {
+        const rect = await UIHelper.getUICaretViewRect();
+        if (rect && rect.width && rect.height)
+            return rect;
+    }
+}
+
+addEventListener("load", async () => {
+    description("This test verifies that after focusing a visible input field in a body element that has been translated horizontally out of view, the caret is still visible. To run the test manually, first tap the input field and check that the caret shows up. Then, tap the button to apply the CSS transform, tap the input field again, and check that the caret is still visible.");
+
+    transformButton = document.querySelector("button");
+    transformButton.addEventListener("click", () => document.body.classList.add("translated"));
+    if (!window.testRunner)
+        return;
+
+    // Tap the input and wait for the caret.
+    await UIHelper.activateAndWaitForInputSessionAt(20, 20);
+    caretBefore = await waitForCaretToAppear();
+    shouldBe("caretBefore.left", "20");
+    shouldBe("caretBefore.top", "14");
+    shouldBe("caretBefore.width", "2");
+    shouldBe("caretBefore.height", "23");
+
+    // Translate the body, tap the input again, and wait for the caret.
+    await UIHelper.activateElement(transformButton);
+    await UIHelper.waitForKeyboardToHide();
+    await UIHelper.activateAndWaitForInputSessionAt(20, 20);
+    caretAfter = await waitForCaretToAppear();
+    shouldBe("caretAfter.left", "20");
+    shouldBe("caretAfter.top", "14");
+    shouldBe("caretAfter.width", "2");
+    shouldBe("caretAfter.height", "23");
+
+    document.activeElement.blur();
+    await UIHelper.waitForKeyboardToHide();
+    finishJSTest();
+});
+</script>
+</head>
+<body class="hidden">
+    <div class="container">
+        <div class="hidden">
+            <input id="target">
+        </div>
+        <div class="hidden">
+            <input>
+        </div>
+    </div>
+    <button>Apply transform</button>
+<div id="description"></div>
+<div id="console"></div>
+</body>
+</html>

Modified: trunk/Source/WebKit/ChangeLog (249295 => 249296)


--- trunk/Source/WebKit/ChangeLog	2019-08-29 22:01:53 UTC (rev 249295)
+++ trunk/Source/WebKit/ChangeLog	2019-08-29 22:17:46 UTC (rev 249296)
@@ -1,3 +1,31 @@
+2019-08-29  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        [iOS 13] Caret does not appear in text field if the body element is translated completely out of the viewport
+        https://bugs.webkit.org/show_bug.cgi?id=201287
+        <rdar://problem/54780864>
+
+        Reviewed by Tim Horton.
+
+        During EditorState computation, we use the hidden editable element heuristic to determine whether we should
+        begin suppressing selection gestures and UI. Currently, we use the editable root of the selection range to
+        determine where in the layer tree we should start our ascent, in search of a completely transparent or
+        completely clipped container.
+
+        However, in the case where the selection is inside a focused text field, this causes us to walk up the layer
+        tree starting at the RenderLayer corresponding to the text field's inner contenteditable div, which is different
+        than the text field's enclosing RenderLayer in the case where the containing block is transformed, such that no
+        part of it is within the visible viewport. This scenario is exercised by the below test case, in which the caret
+        after transforming the body horizontally by -100vw is hidden due to a false positive in the hidden editable area
+        heuristic.
+
+        Fix this by starting the layer tree ascent from the enclosing layer of the text form control if applicable,
+        instead of the inner editable area under the shadow root of the form control.
+
+        Test: editing/selection/ios/show-selection-in-transformed-container.html
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::platformEditorState const):
+
 2019-08-29  Youenn Fablet  <you...@apple.com>
 
         Skip fetch event dispatching if no fetch event handler is added at script evaluation time

Modified: trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm (249295 => 249296)


--- trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2019-08-29 22:01:53 UTC (rev 249295)
+++ trunk/Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm	2019-08-29 22:17:46 UTC (rev 249296)
@@ -273,8 +273,11 @@
             postLayoutData.caretColor = renderer.style().caretColor();
         }
         if (result.isContentEditable) {
-            if (auto container = makeRefPtr(selection.rootEditableElement()))
-                postLayoutData.editableRootIsTransparentOrFullyClipped = isTransparentOrFullyClipped(*container);
+            if (auto editableRootOrFormControl = makeRefPtr(selection.rootEditableElement())) {
+                if (is<HTMLTextFormControlElement>(editableRootOrFormControl->shadowHost()))
+                    editableRootOrFormControl = editableRootOrFormControl->shadowHost();
+                postLayoutData.editableRootIsTransparentOrFullyClipped = isTransparentOrFullyClipped(*editableRootOrFormControl);
+            }
         }
         computeEditableRootHasContentAndPlainText(selection, postLayoutData);
         postLayoutData.selectionStartIsAtParagraphBoundary = atBoundaryOfGranularity(selection.visibleStart(), TextGranularity::ParagraphGranularity, SelectionDirection::DirectionBackward);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to