Fix text autoscrolling when typing in modern webkit
authormegan_gardner@apple.com <megan_gardner@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Apr 2019 18:47:25 +0000 (18:47 +0000)
committermegan_gardner@apple.com <megan_gardner@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Apr 2019 18:47:25 +0000 (18:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196718
Source/WebCore:

<rdar://problem/49225507>

Reviewed by Tim Horton.

Tests: fast/events/autoscroll-when-input-is-offscreen.html
       fast/events/autoscroll-with-software-keyboard.html

We have been relying on UIKit to scroll editable text, but
since we cannot give them enough information for them to always
do the right thing, we should just do all the work in WebKit.
This has the added benifit of fixing some tricky autoscrolling
bugs that have cropped up recently.

* editing/Editor.cpp:
(WebCore::Editor::insertTextWithoutSendingTextEvent):
(WebCore::Editor::revealSelectionAfterEditingOperation):
We should be scrolling the main frame in WebKit. We have been relying on UIKit,
but we cannot give them enough information to guarantee a correct scroll, so just
do all the work in WebKit.
* page/FrameView.cpp:
(WebCore::FrameView::unobscuredContentRectExpandedByContentInsets const):
Update to use the rect that is actually visible, accounting for the software keyboard.

Source/WebKit:

<rdar://problem/49225507>

Reviewed by Tim Horton.

For staging only. We need to turn off UIKit's scrolling behavior to land
the changes we are making. To keep from the build ever breaking,
I am temporarily circumventing the changes in UIKit. This will be removed
once the next UIKit submission happens.

* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKUIWKTextInteractionAssistant scrollSelectionToVisible]):
(-[WKContentView setUpTextSelectionAssistant]):

LayoutTests:

Reviewed by Tim Horton.

* fast/events/autoscroll-when-input-is-offscreen-expected.txt: Added.
* fast/events/autoscroll-when-input-is-offscreen.html: Added.
* fast/events/autoscroll-with-software-keyboard-expected.txt: Added.
* fast/events/autoscroll-with-software-keyboard.html: Added.

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

16 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/events/autoscroll-when-input-is-offscreen-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/autoscroll-when-input-is-offscreen.html [new file with mode: 0644]
LayoutTests/fast/events/autoscroll-with-software-keyboard-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/autoscroll-with-software-keyboard.html [new file with mode: 0644]
LayoutTests/platform/mac/fast/events/autoscroll-when-input-is-offscreen-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/events/autoscroll-with-software-keyboard-expected.txt [new file with mode: 0644]
LayoutTests/platform/win/fast/events/autoscroll-when-input-is-offscreen-expected.txt [new file with mode: 0644]
LayoutTests/platform/win/fast/events/autoscroll-with-software-keyboard-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/editing/Editor.cpp
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/rendering/RenderLayer.cpp
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm

index c17aa9d..9aa7847 100644 (file)
@@ -1,3 +1,15 @@
+2019-04-10  Megan Gardner  <megan_gardner@apple.com>
+
+        Fix text autoscrolling when typing in modern webkit
+        https://bugs.webkit.org/show_bug.cgi?id=196718
+
+        Reviewed by Tim Horton.
+
+        * fast/events/autoscroll-when-input-is-offscreen-expected.txt: Added.
+        * fast/events/autoscroll-when-input-is-offscreen.html: Added.
+        * fast/events/autoscroll-with-software-keyboard-expected.txt: Added.
+        * fast/events/autoscroll-with-software-keyboard.html: Added.
+
 2019-04-10  Youenn Fablet  <youenn@apple.com>
 
         Delay initialization of quota users until the first quota request
diff --git a/LayoutTests/fast/events/autoscroll-when-input-is-offscreen-expected.txt b/LayoutTests/fast/events/autoscroll-when-input-is-offscreen-expected.txt
new file mode 100644 (file)
index 0000000..73459bc
--- /dev/null
@@ -0,0 +1,3 @@
+This test focuses a form, them scrolls to the bottom of the page. Then text is entered in the form, and we check to make sure the page has scrolled so that the input is visible again.
+PASS: page has scrolled back to the top to show the element that has text being entered into it.
+
diff --git a/LayoutTests/fast/events/autoscroll-when-input-is-offscreen.html b/LayoutTests/fast/events/autoscroll-when-input-is-offscreen.html
new file mode 100644 (file)
index 0000000..bf469e9
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/basic-gestures.js"></script>
+<script src="../../resources/ui-helper.js"></script>
+<script>
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+
+    async function runTest()
+    {
+        if (!testRunner.runUIScript)
+            return;
+    
+        var output = '';
+        var firstTargetRect = document.getElementById('editable').getBoundingClientRect();
+
+        var pressPointX = firstTargetRect.x;
+        var pressPointY = firstTargetRect.y;
+
+    
+        await tapAtPoint(pressPointX,pressPointY);
+        
+        var programaticScroll = 500;
+        document.scrollingElement.scrollTop = programaticScroll;
+        await UIHelper.enterText("Test");
+
+        if (window.pageYOffset < programaticScroll)
+            output += 'PASS: page has scrolled back to the top to show the element that has text being entered into it.';
+        else
+            output += 'FAIL: page has failed to scroll when entering text into a form that is offscreen.';
+        output += '<br>';
+
+        document.getElementById('testArea').innerHTML = output;
+        testRunner.notifyDone();
+    }
+
+    window.addEventListener('load', runTest, false);
+</script>
+<style>
+    #testArea {
+        height: 2000px;
+        width: 300px;
+        background-color: silver;
+        font-family: monospace;
+        font-size: 18px;
+    }
+    #editable {
+        font-family: monospace;
+        font-size: 18px;
+    }
+</style>
+</head>
+<body>
+This test focuses a form, them scrolls to the bottom of the page.
+Then text is entered in the form, and we check to make sure the page has scrolled
+so that the input is visible again.
+<div id="result"></div>
+<div id="testArea"><input id="editable" type="text"></input></div>
+</body>
+</html>
+
+
+
+
diff --git a/LayoutTests/fast/events/autoscroll-with-software-keyboard-expected.txt b/LayoutTests/fast/events/autoscroll-with-software-keyboard-expected.txt
new file mode 100644 (file)
index 0000000..da38a70
--- /dev/null
@@ -0,0 +1,4 @@
+This test presses return until the cursor would be behind the keyboard, forcing the content to be scrolled to stay in view with a software keyboard on screen.
+PASS: page has scrolled when caret is behind software keyboard.
+PASS: page has continuted to scroll when caret is beyond the edge of the screen.
+
diff --git a/LayoutTests/fast/events/autoscroll-with-software-keyboard.html b/LayoutTests/fast/events/autoscroll-with-software-keyboard.html
new file mode 100644 (file)
index 0000000..bd8d75b
--- /dev/null
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/basic-gestures.js"></script>
+<script src="../../resources/ui-helper.js"></script>
+<script>
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+
+    async function runTest()
+    {
+        if (!testRunner.runUIScript)
+            return;
+    
+        var output = '';
+        var firstTargetRect = document.getElementById('editable').getBoundingClientRect();
+    
+        var pressPointX = firstTargetRect.x;
+        var pressPointY = firstTargetRect.y;
+
+    
+        await tapAtPoint(pressPointX,pressPointY);
+        await UIHelper.enterText("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nTest");
+
+        var firstPageOffset = window.pageYOffset;
+        if (window.pageYOffset > 0)
+            output += 'PASS: page has scrolled when caret is behind software keyboard.';
+        else
+            output += 'FAIL: page has failed to scroll when caret is behind software keyboard.';
+        output += '<br>';
+
+        await UIHelper.enterText("\n\n\n\n\n\n\n\n\n\n\n\n\n\nTest");
+        if (window.pageYOffset > 0 && window.pageYOffset > firstPageOffset)
+            output += 'PASS: page has continuted to scroll when caret is beyond the edge of the screen.';
+        else
+            output += 'FAIL: page has failed to scroll when caret is beyond the edge of the screen.';
+        output += '<br>';
+
+        document.getElementById('editable').innerHTML = output;
+        testRunner.notifyDone();
+    }
+
+    window.addEventListener('load', runTest, false);
+</script>
+<style>
+    #editable {
+        height: 1000px;
+        width: 300px;
+        background-color: silver;
+        font-family: monospace;
+        font-size: 18px;
+    }
+</style>
+</head>
+<body>
+This test presses return until the cursor would be behind the keyboard,
+forcing the content to be scrolled to stay in view with a software keyboard on screen.
+<div id="editable" contenteditable>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/events/autoscroll-when-input-is-offscreen-expected.txt b/LayoutTests/platform/mac/fast/events/autoscroll-when-input-is-offscreen-expected.txt
new file mode 100644 (file)
index 0000000..522e657
--- /dev/null
@@ -0,0 +1,3 @@
+This test focuses a form, them scrolls to the bottom of the page. Then text is entered in the form, and we check to make sure the page has scrolled so that the input is visible again.
+FAIL: page has failed to scroll when entering text into a form that is offscreen.
+
diff --git a/LayoutTests/platform/mac/fast/events/autoscroll-with-software-keyboard-expected.txt b/LayoutTests/platform/mac/fast/events/autoscroll-with-software-keyboard-expected.txt
new file mode 100644 (file)
index 0000000..e788cac
--- /dev/null
@@ -0,0 +1,4 @@
+This test presses return until the cursor would be behind the keyboard, forcing the content to be scrolled to stay in view with a software keyboard on screen.
+FAIL: page has failed to scroll when caret is behind software keyboard.
+FAIL: page has failed to scroll when caret is beyond the edge of the screen.
+
diff --git a/LayoutTests/platform/win/fast/events/autoscroll-when-input-is-offscreen-expected.txt b/LayoutTests/platform/win/fast/events/autoscroll-when-input-is-offscreen-expected.txt
new file mode 100644 (file)
index 0000000..522e657
--- /dev/null
@@ -0,0 +1,3 @@
+This test focuses a form, them scrolls to the bottom of the page. Then text is entered in the form, and we check to make sure the page has scrolled so that the input is visible again.
+FAIL: page has failed to scroll when entering text into a form that is offscreen.
+
diff --git a/LayoutTests/platform/win/fast/events/autoscroll-with-software-keyboard-expected.txt b/LayoutTests/platform/win/fast/events/autoscroll-with-software-keyboard-expected.txt
new file mode 100644 (file)
index 0000000..e788cac
--- /dev/null
@@ -0,0 +1,4 @@
+This test presses return until the cursor would be behind the keyboard, forcing the content to be scrolled to stay in view with a software keyboard on screen.
+FAIL: page has failed to scroll when caret is behind software keyboard.
+FAIL: page has failed to scroll when caret is beyond the edge of the screen.
+
index c71c438..7bb9bba 100644 (file)
@@ -1,3 +1,30 @@
+2019-04-10  Megan Gardner  <megan_gardner@apple.com>
+
+        Fix text autoscrolling when typing in modern webkit
+        https://bugs.webkit.org/show_bug.cgi?id=196718
+        <rdar://problem/49225507>
+
+        Reviewed by Tim Horton.
+
+        Tests: fast/events/autoscroll-when-input-is-offscreen.html
+               fast/events/autoscroll-with-software-keyboard.html
+
+        We have been relying on UIKit to scroll editable text, but
+        since we cannot give them enough information for them to always
+        do the right thing, we should just do all the work in WebKit.
+        This has the added benifit of fixing some tricky autoscrolling
+        bugs that have cropped up recently.
+
+        * editing/Editor.cpp:
+        (WebCore::Editor::insertTextWithoutSendingTextEvent):
+        (WebCore::Editor::revealSelectionAfterEditingOperation):
+        We should be scrolling the main frame in WebKit. We have been relying on UIKit,
+        but we cannot give them enough information to guarantee a correct scroll, so just
+        do all the work in WebKit.
+        * page/FrameView.cpp:
+        (WebCore::FrameView::unobscuredContentRectExpandedByContentInsets const):
+        Update to use the rect that is actually visible, accounting for the software keyboard.
+
 2019-04-10  Ross Kirsling  <ross.kirsling@sony.com>
 
         WebCore should build successfully even with -DENABLE_UNIFIED_BUILDS=OFF
index 009301e..3c9f6d5 100644 (file)
@@ -1280,11 +1280,7 @@ bool Editor::insertTextWithoutSendingTextEvent(const String& text, bool selectIn
             // Reveal the current selection
             if (Frame* editedFrame = document->frame())
                 if (Page* page = editedFrame->page()) {
-#if PLATFORM(IOS_FAMILY)
-                    SelectionRevealMode revealMode = SelectionRevealMode::RevealUpToMainFrame;
-#else
                     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
-#endif
                     page->focusController().focusedOrMainFrame().selection().revealSelection(revealMode, ScrollAlignment::alignCenterIfNeeded);
                 }
         }
@@ -3055,12 +3051,7 @@ void Editor::revealSelectionAfterEditingOperation(const ScrollAlignment& alignme
     if (m_ignoreSelectionChanges)
         return;
 
-#if PLATFORM(IOS_FAMILY)
-    SelectionRevealMode revealMode = SelectionRevealMode::RevealUpToMainFrame;
-#else
     SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
-#endif
-
     m_frame.selection().revealSelection(revealMode, alignment, revealExtentOption);
 }
 
index 6ca57e3..1e0a34d 100644 (file)
@@ -1993,9 +1993,9 @@ void FrameView::viewportContentsChanged()
 #endif
 }
 
-IntRect FrameView::unobscuredContentRectExpandedByContentInsets() const
+IntRect FrameView::visualViewportRectExpandedByContentInsets() const
 {
-    FloatRect unobscuredContentRect = this->unobscuredContentRect();
+    FloatRect unobscuredContentRect = this->visualViewportRect();
     if (auto* page = frame().page())
         unobscuredContentRect.expand(page->contentInsets());
     return IntRect(unobscuredContentRect);
index ae16ab6..4da8e3d 100644 (file)
@@ -329,7 +329,7 @@ public:
     WEBCORE_EXPORT static LayoutRect rectForViewportConstrainedObjects(const LayoutRect& visibleContentRect, const LayoutSize& totalContentsSize, float frameScaleFactor, bool fixedElementsLayoutRelativeToFrame, ScrollBehaviorForFixedElements);
 #endif
 
-    IntRect unobscuredContentRectExpandedByContentInsets() const;
+    IntRect visualViewportRectExpandedByContentInsets() const;
     
     bool fixedElementsLayoutRelativeToFrame() const;
 
index 9268399..6966283 100644 (file)
@@ -2568,7 +2568,7 @@ void RenderLayer::scrollRectToVisible(const LayoutRect& absoluteRect, bool insid
 #if !PLATFORM(IOS_FAMILY)
             LayoutRect viewRect = frameView.visibleContentRect();
 #else
-            LayoutRect viewRect = frameView.unobscuredContentRectExpandedByContentInsets();
+            LayoutRect viewRect = frameView.visualViewportRectExpandedByContentInsets();
 #endif
             // Move the target rect into "scrollView contents" coordinates.
             LayoutRect targetRect = absoluteRect;
index 1a1208c..063c8b8 100644 (file)
@@ -1,3 +1,20 @@
+2019-04-10  Megan Gardner  <megan_gardner@apple.com>
+
+        Fix text autoscrolling when typing in modern webkit
+        https://bugs.webkit.org/show_bug.cgi?id=196718
+        <rdar://problem/49225507>
+
+        Reviewed by Tim Horton.
+
+        For staging only. We need to turn off UIKit's scrolling behavior to land
+        the changes we are making. To keep from the build ever breaking,
+        I am temporarily circumventing the changes in UIKit. This will be removed
+        once the next UIKit submission happens.
+
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKUIWKTextInteractionAssistant scrollSelectionToVisible]):
+        (-[WKContentView setUpTextSelectionAssistant]):
+
 2019-04-10  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         [iOSMac] Opt into modern compatibility mode by default
index 354189e..84e731f 100644 (file)
@@ -154,6 +154,16 @@ SOFT_LINK_CONSTANT(ManagedConfiguration, MCFeatureDefinitionLookupAllowed, NSStr
 
 #endif
 
+// For staging with UIKit, will be removed ASAP.
+@interface WKUIWKTextInteractionAssistant : UIWKTextInteractionAssistant
+@end
+
+@implementation WKUIWKTextInteractionAssistant
+- (void)scrollSelectionToVisible
+{
+}
+@end
+
 namespace WebKit {
 using namespace WebCore;
 using namespace WebKit;
@@ -2371,7 +2381,7 @@ static void cancelPotentialTapIfNecessary(WKContentView* contentView)
 - (void)setUpTextSelectionAssistant
 {
     if (!_textSelectionAssistant)
-        _textSelectionAssistant = adoptNS([[UIWKTextInteractionAssistant alloc] initWithView:self]);
+        _textSelectionAssistant = adoptNS([[WKUIWKTextInteractionAssistant alloc] initWithView:self]);
     else {
         // Reset the gesture recognizers in case editability has changed.
         [_textSelectionAssistant setGestureRecognizers];