Title: [202243] trunk
Revision
202243
Author
[email protected]
Date
2016-06-20 14:22:54 -0700 (Mon, 20 Jun 2016)

Log Message

Focus event dispatched in iframe causes parent document to scroll incorrectly
https://bugs.webkit.org/show_bug.cgi?id=158629
rdar://problem/26521616

Reviewed by Tim Horton.
Source/WebCore:

When focussing elements in iframes, the page could scroll to an incorrect location.
This happened because code in Element::focus() tried to disable scrolling on focus,
but did so only for the current frame, so ancestor frames got programmatically scrolled.
On iOS we handle the scrolling in the UI process, so never want the web process to
do programmatic scrolling.

Fix by changing the focus and cache restore code to use SelectionRevealMode::DoNotReveal,
rather than manually prohibiting frame scrolling. Pass SelectionRevealMode through various callers,
and use RevealUpToMainFrame for iOS, allowing the UI process to do the zoomToRect: for the main frame.

Tests: fast/forms/ios/focus-input-in-iframe.html
       fast/forms/ios/programmatic-focus-input-in-iframe.html

* dom/Document.h:
* dom/Element.cpp:
(WebCore::Element::scrollIntoView):
(WebCore::Element::scrollIntoViewIfNeeded):
(WebCore::Element::scrollIntoViewIfNotVisible):
(WebCore::Element::focus):
(WebCore::Element::updateFocusAppearance):
* dom/Element.h:
* editing/Editor.cpp:
(WebCore::Editor::insertTextWithoutSendingTextEvent):
(WebCore::Editor::revealSelectionAfterEditingOperation):
(WebCore::Editor::findStringAndScrollToVisible):
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::updateAndRevealSelection):
(WebCore::FrameSelection::revealSelection):
(WebCore::FrameSelection::FrameSelection): Deleted.
* editing/FrameSelection.h:
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::updateFocusAppearance):
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::updateFocusAppearance):
* page/ContextMenuController.cpp:
(WebCore::ContextMenuController::contextMenuItemSelected):
* page/FrameView.cpp:
(WebCore::FrameView::scrollToAnchor):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::scrollRectToVisible):
(WebCore::RenderLayer::autoscroll):
* rendering/RenderLayer.h:
* rendering/RenderObject.cpp:
(WebCore::RenderObject::scrollRectToVisible):
* rendering/RenderObject.h:

Source/WebKit/mac:

Pass SelectionRevealMode::Reveal in existing code.

* WebView/WebFrame.mm:
(-[WebFrame _scrollDOMRangeToVisible:]):
(-[WebFrame _scrollDOMRangeToVisible:withInset:]):
(-[WebFrame revealSelectionAtExtent:]):
* WebView/WebHTMLView.mm:
(-[WebHTMLView jumpToSelection:]):
(-[WebHTMLView centerSelectionInVisibleArea:]):

Source/WebKit2:

Pass SelectionRevealMode::Reveal in existing code.

* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::centerSelectionInVisibleArea):

LayoutTests:

* fast/forms/ios/focus-input-in-iframe-expected.txt: Added.
* fast/forms/ios/focus-input-in-iframe.html: Added.
* fast/forms/ios/programmatic-focus-input-in-iframe-expected.txt: Added.
* fast/forms/ios/programmatic-focus-input-in-iframe.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (202242 => 202243)


--- trunk/LayoutTests/ChangeLog	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/LayoutTests/ChangeLog	2016-06-20 21:22:54 UTC (rev 202243)
@@ -1,3 +1,16 @@
+2016-06-20  Simon Fraser  <[email protected]>
+
+        Focus event dispatched in iframe causes parent document to scroll incorrectly
+        https://bugs.webkit.org/show_bug.cgi?id=158629
+        rdar://problem/26521616
+
+        Reviewed by Tim Horton.
+
+        * fast/forms/ios/focus-input-in-iframe-expected.txt: Added.
+        * fast/forms/ios/focus-input-in-iframe.html: Added.
+        * fast/forms/ios/programmatic-focus-input-in-iframe-expected.txt: Added.
+        * fast/forms/ios/programmatic-focus-input-in-iframe.html: Added.
+
 2016-06-20  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r202179.

Added: trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe-expected.txt (0 => 202243)


--- trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe-expected.txt	2016-06-20 21:22:54 UTC (rev 202243)
@@ -0,0 +1,7 @@
+Tests zooming into a text input on tap.
+
+Click to focus input
+
+tap location	{ x: 20.000, y: 62.000 }
+scale	1.455
+visibleRect	{ left: 0.000, top: 1201.976, width: 219.979, height: 329.968 }

Added: trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe.html (0 => 202243)


--- trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/focus-input-in-iframe.html	2016-06-20 21:22:54 UTC (rev 202243)
@@ -0,0 +1,48 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+
+<html>
+<head>
+    <meta name="viewport" content="initial-scale=0.5">
+    <style>
+        button {
+            display: block;
+        }
+        iframe {
+            margin-top: 800px;
+        }
+    </style>
+    
+    <script src=""
+    <script>
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+
+    if (window.internals)
+        internals.settings.setFrameFlatteningEnabled(true);
+    
+    function buttonClicked()
+    {
+        document.getElementById('frame').contentDocument.getElementById('input').focus();
+    }
+
+    function doTest()
+    {
+        testZoomAfterTap(document.getElementById('target'), 10, 10);
+    }
+
+    window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+
+<p>Tests zooming into a text input on tap.</p>
+<button id="target" _onclick_="buttonClicked()">Click to focus input</button>
+
+<iframe id="frame" srcdoc="<style>input { margin: 400px 20px; }</style>
+<input id='input' type='text'>
+"></iframe>
+
+</body>
+</html>

Added: trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe-expected.txt (0 => 202243)


--- trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe-expected.txt	2016-06-20 21:22:54 UTC (rev 202243)
@@ -0,0 +1,4 @@
+Tests that a programmatic focus should not scroll into view
+
+PASS: page did not scroll.
+

Added: trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe.html (0 => 202243)


--- trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe.html	                        (rev 0)
+++ trunk/LayoutTests/fast/forms/ios/programmatic-focus-input-in-iframe.html	2016-06-20 21:22:54 UTC (rev 202243)
@@ -0,0 +1,57 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+
+<html>
+<head>
+    <meta name="viewport" content="initial-scale=0.5">
+    <style>
+        button {
+            display: block;
+        }
+        iframe {
+            margin-top: 800px;
+        }
+    </style>
+    
+    <script>
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+    
+    if (window.internals)
+        internals.settings.setFrameFlatteningEnabled(true);
+    
+    function pageDidScroll()
+    {
+        document.getElementById('result').textContent = 'FAIL: page scrolled to ' + document.scrollingElement.scrollTop;
+    }
+
+    function doTest()
+    {
+        window.setTimeout(function() {
+            document.getElementById('frame').contentDocument.getElementById('input').focus();
+        }, 0);
+
+        // Wait for any scroll to happen.
+        window.setTimeout(function() {
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, 100);
+    }
+
+    window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body _onscroll_="pageDidScroll()">
+
+<p>Tests that a programmatic focus should not scroll into view</p>
+<div id="result">
+    PASS: page did not scroll.
+</div>
+
+<iframe id="frame" srcdoc="<style>input { margin: 400px 20px; }</style>
+<input id='input' type='text'>
+"></iframe>
+
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (202242 => 202243)


--- trunk/Source/WebCore/ChangeLog	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/ChangeLog	2016-06-20 21:22:54 UTC (rev 202243)
@@ -1,3 +1,57 @@
+2016-06-20  Simon Fraser  <[email protected]>
+
+        Focus event dispatched in iframe causes parent document to scroll incorrectly
+        https://bugs.webkit.org/show_bug.cgi?id=158629
+        rdar://problem/26521616
+
+        Reviewed by Tim Horton.
+
+        When focussing elements in iframes, the page could scroll to an incorrect location.
+        This happened because code in Element::focus() tried to disable scrolling on focus,
+        but did so only for the current frame, so ancestor frames got programmatically scrolled.
+        On iOS we handle the scrolling in the UI process, so never want the web process to
+        do programmatic scrolling.
+
+        Fix by changing the focus and cache restore code to use SelectionRevealMode::DoNotReveal,
+        rather than manually prohibiting frame scrolling. Pass SelectionRevealMode through various callers,
+        and use RevealUpToMainFrame for iOS, allowing the UI process to do the zoomToRect: for the main frame.
+
+        Tests: fast/forms/ios/focus-input-in-iframe.html
+               fast/forms/ios/programmatic-focus-input-in-iframe.html
+
+        * dom/Document.h:
+        * dom/Element.cpp:
+        (WebCore::Element::scrollIntoView):
+        (WebCore::Element::scrollIntoViewIfNeeded):
+        (WebCore::Element::scrollIntoViewIfNotVisible):
+        (WebCore::Element::focus):
+        (WebCore::Element::updateFocusAppearance):
+        * dom/Element.h:
+        * editing/Editor.cpp:
+        (WebCore::Editor::insertTextWithoutSendingTextEvent):
+        (WebCore::Editor::revealSelectionAfterEditingOperation):
+        (WebCore::Editor::findStringAndScrollToVisible):
+        * editing/FrameSelection.cpp:
+        (WebCore::FrameSelection::updateAndRevealSelection):
+        (WebCore::FrameSelection::revealSelection):
+        (WebCore::FrameSelection::FrameSelection): Deleted.
+        * editing/FrameSelection.h:
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::updateFocusAppearance):
+        * html/HTMLTextAreaElement.cpp:
+        (WebCore::HTMLTextAreaElement::updateFocusAppearance):
+        * page/ContextMenuController.cpp:
+        (WebCore::ContextMenuController::contextMenuItemSelected):
+        * page/FrameView.cpp:
+        (WebCore::FrameView::scrollToAnchor):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::scrollRectToVisible):
+        (WebCore::RenderLayer::autoscroll):
+        * rendering/RenderLayer.h:
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::scrollRectToVisible):
+        * rendering/RenderObject.h:
+
 2016-06-20  Keith Rollin  <[email protected]>
 
         Remove RefPtr::release() and change calls sites to use WTFMove()

Modified: trunk/Source/WebCore/dom/Document.h (202242 => 202243)


--- trunk/Source/WebCore/dom/Document.h	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/dom/Document.h	2016-06-20 21:22:54 UTC (rev 202243)
@@ -282,11 +282,6 @@
     SetDefault,
 };
 
-enum class SelectionRevealMode {
-    Reveal,
-    DoNotReveal
-};
-
 enum class HttpEquivPolicy {
     Enabled,
     DisabledBySettings,

Modified: trunk/Source/WebCore/dom/Element.cpp (202242 => 202243)


--- trunk/Source/WebCore/dom/Element.cpp	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/dom/Element.cpp	2016-06-20 21:22:54 UTC (rev 202243)
@@ -639,9 +639,9 @@
     LayoutRect bounds = renderer()->anchorRect();
     // Align to the top / bottom and to the closest edge.
     if (alignToTop)
-        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
+        renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
     else
-        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
+        renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignBottomAlways);
 }
 
 void Element::scrollIntoViewIfNeeded(bool centerIfNeeded)
@@ -653,9 +653,9 @@
 
     LayoutRect bounds = renderer()->anchorRect();
     if (centerIfNeeded)
-        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
+        renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
     else
-        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
+        renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
 }
 
 void Element::scrollIntoViewIfNotVisible(bool centerIfNotVisible)
@@ -667,9 +667,9 @@
     
     LayoutRect bounds = renderer()->anchorRect();
     if (centerIfNotVisible)
-        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignCenterIfNotVisible, ScrollAlignment::alignCenterIfNotVisible);
+        renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignCenterIfNotVisible, ScrollAlignment::alignCenterIfNotVisible);
     else
-        renderer()->scrollRectToVisible(bounds, ScrollAlignment::alignToEdgeIfNotVisible, ScrollAlignment::alignToEdgeIfNotVisible);
+        renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, bounds, ScrollAlignment::alignToEdgeIfNotVisible, ScrollAlignment::alignToEdgeIfNotVisible);
 }
     
 void Element::scrollByUnits(int units, ScrollGranularity granularity)
@@ -2245,20 +2245,18 @@
     }
         
     cancelFocusAppearanceUpdate();
+
+    SelectionRevealMode revealMode = SelectionRevealMode::Reveal;
 #if PLATFORM(IOS)
     // Focusing a form element triggers animation in UIKit to scroll to the right position.
     // Calling updateFocusAppearance() would generate an unnecessary call to ScrollView::setScrollPosition(),
     // which would jump us around during this animation. See <rdar://problem/6699741>.
-    FrameView* view = document().view();
-    bool isFormControl = view && is<HTMLFormControlElement>(*this);
+    bool isFormControl = is<HTMLFormControlElement>(*this);
     if (isFormControl)
-        view->setProhibitsScrolling(true);
+        revealMode = SelectionRevealMode::RevealUpToMainFrame;
 #endif
-    updateFocusAppearance(restorePreviousSelection ? SelectionRestorationMode::Restore : SelectionRestorationMode::SetDefault);
-#if PLATFORM(IOS)
-    if (isFormControl)
-        view->setProhibitsScrolling(false);
-#endif
+
+    updateFocusAppearance(restorePreviousSelection ? SelectionRestorationMode::Restore : SelectionRestorationMode::SetDefault, revealMode);
 }
 
 void Element::updateFocusAppearanceAfterAttachIfNeeded()
@@ -2290,11 +2288,10 @@
         
         if (frame->selection().shouldChangeSelection(newSelection)) {
             frame->selection().setSelection(newSelection, FrameSelection::defaultSetSelectionOptions(), Element::defaultFocusTextStateChangeIntent());
-            if (revealMode == SelectionRevealMode::Reveal)
-                frame->selection().revealSelection();
+            frame->selection().revealSelection(revealMode);
         }
-    } else if (renderer() && !renderer()->isWidget() && revealMode == SelectionRevealMode::Reveal)
-        renderer()->scrollRectToVisible(renderer()->anchorRect());
+    } else if (renderer() && !renderer()->isWidget())
+        renderer()->scrollRectToVisible(revealMode, renderer()->anchorRect());
 }
 
 void Element::blur()

Modified: trunk/Source/WebCore/dom/Element.h (202242 => 202243)


--- trunk/Source/WebCore/dom/Element.h	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/dom/Element.h	2016-06-20 21:22:54 UTC (rev 202243)
@@ -60,6 +60,12 @@
     SpellcheckAttributeDefault
 };
 
+enum class SelectionRevealMode {
+    Reveal,
+    RevealUpToMainFrame, // Scroll overflow and iframes, but not the main frame.
+    DoNotReveal
+};
+
 class Element : public ContainerNode {
 public:
     static Ref<Element> create(const QualifiedName&, Document&);

Modified: trunk/Source/WebCore/editing/Editor.cpp (202242 => 202243)


--- trunk/Source/WebCore/editing/Editor.cpp	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/editing/Editor.cpp	2016-06-20 21:22:54 UTC (rev 202243)
@@ -1204,7 +1204,7 @@
             // Reveal the current selection
             if (Frame* editedFrame = document->frame())
                 if (Page* page = editedFrame->page())
-                    page->focusController().focusedOrMainFrame().selection().revealSelection(ScrollAlignment::alignCenterIfNeeded);
+                    page->focusController().focusedOrMainFrame().selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignCenterIfNeeded);
         }
     }
 
@@ -2799,7 +2799,7 @@
     if (m_ignoreCompositionSelectionChange)
         return;
 
-    m_frame.selection().revealSelection(alignment, revealExtentOption);
+    m_frame.selection().revealSelection(SelectionRevealMode::Reveal, alignment, revealExtentOption);
 }
 
 void Editor::setIgnoreCompositionSelectionChange(bool ignore, RevealSelection shouldRevealExistingSelection)
@@ -3147,7 +3147,7 @@
     if (!nextMatch)
         return nullptr;
 
-    nextMatch->firstNode()->renderer()->scrollRectToVisible(nextMatch->absoluteBoundingBox(),
+    nextMatch->firstNode()->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, nextMatch->absoluteBoundingBox(),
         ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeeded);
 
     return nextMatch;

Modified: trunk/Source/WebCore/editing/FrameSelection.cpp (202242 => 202243)


--- trunk/Source/WebCore/editing/FrameSelection.cpp	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/editing/FrameSelection.cpp	2016-06-20 21:22:54 UTC (rev 202243)
@@ -127,7 +127,6 @@
 #if PLATFORM(IOS)
     , m_updateAppearanceEnabled(false)
     , m_caretBlinks(true)
-    , m_scrollingSuppressCount(0)
 #endif
 {
     if (shouldAlwaysUseDirectionalSelection(m_frame))
@@ -388,7 +387,7 @@
         else
             alignment = m_alwaysAlignCursorOnScrollWhenRevealingSelection ? ScrollAlignment::alignTopAlways : ScrollAlignment::alignToEdgeIfNeeded;
 
-        revealSelection(alignment, RevealExtent);
+        revealSelection(SelectionRevealMode::Reveal, alignment, RevealExtent);
     }
 
     notifyAccessibilityForSelectionChange(intent);
@@ -2290,8 +2289,11 @@
     return scanForForm(start);
 }
 
-void FrameSelection::revealSelection(const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
+void FrameSelection::revealSelection(SelectionRevealMode revealMode, const ScrollAlignment& alignment, RevealExtentOption revealExtentOption)
 {
+    if (revealMode == SelectionRevealMode::DoNotReveal)
+        return;
+
     LayoutRect rect;
 
     switch (m_selection.selectionType()) {
@@ -2312,7 +2314,7 @@
         if (RenderLayer* layer = start.deprecatedNode()->renderer()->enclosingLayer()) {
             if (!m_scrollingSuppressCount) {
                 layer->setAdjustForIOSCaretWhenScrolling(true);
-                layer->scrollRectToVisible(rect, alignment, alignment);
+                layer->scrollRectToVisible(revealMode, rect, alignment, alignment);
                 layer->setAdjustForIOSCaretWhenScrolling(false);
                 updateAppearance();
                 if (m_frame->page())
@@ -2323,7 +2325,7 @@
         // FIXME: This code only handles scrolling the startContainer's layer, but
         // the selection rect could intersect more than just that.
         // See <rdar://problem/4799899>.
-        if (start.deprecatedNode()->renderer()->scrollRectToVisible(rect, alignment, alignment))
+        if (start.deprecatedNode()->renderer()->scrollRectToVisible(revealMode, rect, alignment, alignment))
             updateAppearance();
 #endif
     }

Modified: trunk/Source/WebCore/editing/FrameSelection.h (202242 => 202243)


--- trunk/Source/WebCore/editing/FrameSelection.h	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/editing/FrameSelection.h	2016-06-20 21:22:54 UTC (rev 202243)
@@ -28,6 +28,7 @@
 
 #include "AXTextStateChangeIntent.h"
 #include "EditingStyle.h"
+#include "Element.h"
 #include "IntRect.h"
 #include "LayoutRect.h"
 #include "Range.h"
@@ -266,7 +267,7 @@
 
     WEBCORE_EXPORT HTMLFormElement* currentForm() const;
 
-    WEBCORE_EXPORT void revealSelection(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, RevealExtentOption = DoNotRevealExtent);
+    WEBCORE_EXPORT void revealSelection(SelectionRevealMode = SelectionRevealMode::Reveal, const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, RevealExtentOption = DoNotRevealExtent);
     WEBCORE_EXPORT void setSelectionFromNone();
 
     bool shouldShowBlockCursor() const { return m_shouldShowBlockCursor; }
@@ -350,7 +351,7 @@
     bool m_updateAppearanceEnabled : 1;
     bool m_caretBlinks : 1;
     Color m_caretColor;
-    int m_scrollingSuppressCount;
+    int m_scrollingSuppressCount { 0 };
 #endif
 };
 

Modified: trunk/Source/WebCore/html/HTMLInputElement.cpp (202242 => 202243)


--- trunk/Source/WebCore/html/HTMLInputElement.cpp	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/html/HTMLInputElement.cpp	2016-06-20 21:22:54 UTC (rev 202243)
@@ -404,8 +404,8 @@
             select(Element::defaultFocusTextStateChangeIntent());
         else
             restoreCachedSelection();
-        if (document().frame() && revealMode == SelectionRevealMode::Reveal)
-            document().frame()->selection().revealSelection();
+        if (document().frame())
+            document().frame()->selection().revealSelection(revealMode);
     } else
         HTMLTextFormControlElement::updateFocusAppearance(restorationMode, revealMode);
 }

Modified: trunk/Source/WebCore/html/HTMLTextAreaElement.cpp (202242 => 202243)


--- trunk/Source/WebCore/html/HTMLTextAreaElement.cpp	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/html/HTMLTextAreaElement.cpp	2016-06-20 21:22:54 UTC (rev 202243)
@@ -260,8 +260,8 @@
     } else
         restoreCachedSelection(Element::defaultFocusTextStateChangeIntent());
 
-    if (document().frame() && revealMode == SelectionRevealMode::Reveal)
-        document().frame()->selection().revealSelection();
+    if (document().frame())
+        document().frame()->selection().revealSelection(revealMode);
 }
 
 void HTMLTextAreaElement::defaultEventHandler(Event* event)

Modified: trunk/Source/WebCore/page/ContextMenuController.cpp (202242 => 202243)


--- trunk/Source/WebCore/page/ContextMenuController.cpp	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/page/ContextMenuController.cpp	2016-06-20 21:22:54 UTC (rev 202243)
@@ -372,7 +372,7 @@
             ASSERT(document);
             RefPtr<ReplaceSelectionCommand> command = ReplaceSelectionCommand::create(*document, createFragmentFromMarkup(*document, title, ""), replaceOptions);
             applyCommand(command);
-            frame->selection().revealSelection(ScrollAlignment::alignToEdgeIfNeeded);
+            frame->selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignToEdgeIfNeeded);
         }
         break;
     }

Modified: trunk/Source/WebCore/page/FrameView.cpp (202242 => 202243)


--- trunk/Source/WebCore/page/FrameView.cpp	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/page/FrameView.cpp	2016-06-20 21:22:54 UTC (rev 202243)
@@ -3050,11 +3050,11 @@
     // Scroll nested layers and frames to reveal the anchor.
     // Align to the top and to the closest side (this matches other browsers).
     if (anchorNode->renderer()->style().isHorizontalWritingMode())
-        anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
+        anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
     else if (anchorNode->renderer()->style().isFlippedBlocksWritingMode())
-        anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignRightAlways, ScrollAlignment::alignToEdgeIfNeeded);
+        anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, ScrollAlignment::alignRightAlways, ScrollAlignment::alignToEdgeIfNeeded);
     else
-        anchorNode->renderer()->scrollRectToVisible(rect, ScrollAlignment::alignLeftAlways, ScrollAlignment::alignToEdgeIfNeeded);
+        anchorNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, rect, ScrollAlignment::alignLeftAlways, ScrollAlignment::alignToEdgeIfNeeded);
 
     if (AXObjectCache* cache = frame().document()->existingAXObjectCache())
         cache->handleScrolledToAnchor(anchorNode.get());

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (202242 => 202243)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2016-06-20 21:22:54 UTC (rev 202243)
@@ -80,6 +80,7 @@
 #include "HitTestRequest.h"
 #include "HitTestResult.h"
 #include "Logging.h"
+#include "MainFrame.h"
 #include "NoEventDispatchAssertion.h"
 #include "OverflowEvent.h"
 #include "OverlapTestRequestClient.h"
@@ -2490,7 +2491,7 @@
     return box->hasHorizontalOverflow() || box->hasVerticalOverflow();
 }
 
-void RenderLayer::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+void RenderLayer::scrollRectToVisible(SelectionRevealMode revealMode, const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
 {
     LOG_WITH_STREAM(Scrolling, stream << "Layer " << this << " scrollRectToVisible " << rect);
 
@@ -2550,6 +2551,9 @@
                     parentLayer = nullptr;
             }
         } else {
+            if (revealMode == SelectionRevealMode::RevealUpToMainFrame && frameView.frame().isMainFrame())
+                return;
+
 #if !PLATFORM(IOS)
             LayoutRect viewRect = frameView.visibleContentRect();
             LayoutRect visibleRectRelativeToDocument = viewRect;
@@ -2574,7 +2578,7 @@
     }
     
     if (parentLayer)
-        parentLayer->scrollRectToVisible(newRect, alignX, alignY);
+        parentLayer->scrollRectToVisible(revealMode, newRect, alignX, alignY);
 }
 
 void RenderLayer::updateCompositingLayersAfterScroll()
@@ -2667,7 +2671,7 @@
 void RenderLayer::autoscroll(const IntPoint& position)
 {
     IntPoint currentDocumentPosition = renderer().view().frameView().windowToContents(position);
-    scrollRectToVisible(LayoutRect(currentDocumentPosition, LayoutSize(1, 1)), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
+    scrollRectToVisible(SelectionRevealMode::Reveal, LayoutRect(currentDocumentPosition, LayoutSize(1, 1)), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
 }
 
 bool RenderLayer::canResize() const

Modified: trunk/Source/WebCore/rendering/RenderLayer.h (202242 => 202243)


--- trunk/Source/WebCore/rendering/RenderLayer.h	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/rendering/RenderLayer.h	2016-06-20 21:22:54 UTC (rev 202243)
@@ -205,7 +205,7 @@
 
     void availableContentSizeChanged(AvailableSizeChangeReason) override;
 
-    void scrollRectToVisible(const LayoutRect&, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
+    void scrollRectToVisible(SelectionRevealMode, const LayoutRect&, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
 
     LayoutRect getRectToExpose(const LayoutRect& visibleRect, const LayoutRect& visibleRectRelativeToDocument, const LayoutRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
 

Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (202242 => 202243)


--- trunk/Source/WebCore/rendering/RenderObject.cpp	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp	2016-06-20 21:22:54 UTC (rev 202243)
@@ -358,13 +358,16 @@
     return nullptr;
 }
 
-bool RenderObject::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+bool RenderObject::scrollRectToVisible(SelectionRevealMode revealMode, const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
 {
+    if (revealMode == SelectionRevealMode::DoNotReveal)
+        return false;
+
     RenderLayer* enclosingLayer = this->enclosingLayer();
     if (!enclosingLayer)
         return false;
 
-    enclosingLayer->scrollRectToVisible(rect, alignX, alignY);
+    enclosingLayer->scrollRectToVisible(revealMode, rect, alignX, alignY);
     return true;
 }
 

Modified: trunk/Source/WebCore/rendering/RenderObject.h (202242 => 202243)


--- trunk/Source/WebCore/rendering/RenderObject.h	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebCore/rendering/RenderObject.h	2016-06-20 21:22:54 UTC (rev 202243)
@@ -155,7 +155,7 @@
     WEBCORE_EXPORT RenderLayer* enclosingLayer() const;
 
     // Scrolling is a RenderBox concept, however some code just cares about recursively scrolling our enclosing ScrollableArea(s).
-    WEBCORE_EXPORT bool scrollRectToVisible(const LayoutRect&, const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded);
+    WEBCORE_EXPORT bool scrollRectToVisible(SelectionRevealMode, const LayoutRect&, const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded);
 
     // Convenience function for getting to the nearest enclosing box of a RenderObject.
     RenderBox& enclosingBox() const;

Modified: trunk/Source/WebKit/mac/ChangeLog (202242 => 202243)


--- trunk/Source/WebKit/mac/ChangeLog	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebKit/mac/ChangeLog	2016-06-20 21:22:54 UTC (rev 202243)
@@ -1,3 +1,21 @@
+2016-06-20  Simon Fraser  <[email protected]>
+
+        Focus event dispatched in iframe causes parent document to scroll incorrectly
+        https://bugs.webkit.org/show_bug.cgi?id=158629
+        rdar://problem/26521616
+
+        Reviewed by Tim Horton.
+        
+        Pass SelectionRevealMode::Reveal in existing code.
+
+        * WebView/WebFrame.mm:
+        (-[WebFrame _scrollDOMRangeToVisible:]):
+        (-[WebFrame _scrollDOMRangeToVisible:withInset:]):
+        (-[WebFrame revealSelectionAtExtent:]):
+        * WebView/WebHTMLView.mm:
+        (-[WebHTMLView jumpToSelection:]):
+        (-[WebHTMLView centerSelectionInVisibleArea:]):
+
 2016-06-20  Keith Rollin  <[email protected]>
 
         Remove RefPtr::release() and change calls sites to use WTFMove()

Modified: trunk/Source/WebKit/mac/WebView/WebFrame.mm (202242 => 202243)


--- trunk/Source/WebKit/mac/WebView/WebFrame.mm	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebKit/mac/WebView/WebFrame.mm	2016-06-20 21:22:54 UTC (rev 202243)
@@ -717,12 +717,12 @@
         
     if (startNode && startNode->renderer()) {
 #if !PLATFORM(IOS)
-        startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
+        startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
 #else
         RenderLayer* layer = startNode->renderer()->enclosingLayer();
         if (layer) {
             layer->setAdjustForIOSCaretWhenScrolling(true);
-            startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
+            startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
             layer->setAdjustForIOSCaretWhenScrolling(false);
             _private->coreFrame->selection().setCaretRectNeedsUpdate();
             _private->coreFrame->selection().updateAppearance();
@@ -741,7 +741,7 @@
         RenderLayer* layer = startNode->renderer()->enclosingLayer();
         if (layer) {
             layer->setAdjustForIOSCaretWhenScrolling(true);
-            startNode->renderer()->scrollRectToVisible(enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
+            startNode->renderer()->scrollRectToVisible(SelectionRevealMode::Reveal, enclosingIntRect(rangeRect), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
             layer->setAdjustForIOSCaretWhenScrolling(false);
 
             Frame *coreFrame = core(self);
@@ -1375,7 +1375,7 @@
 {
     WebCore::Frame *frame = core(self);
     RevealExtentOption revealExtentOption = revealExtent ? RevealExtent : DoNotRevealExtent;
-    frame->selection().revealSelection(ScrollAlignment::alignToEdgeIfNeeded, revealExtentOption);
+    frame->selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignToEdgeIfNeeded, revealExtentOption);
 }
 
 - (void)resetSelection

Modified: trunk/Source/WebKit/mac/WebView/WebHTMLView.mm (202242 => 202243)


--- trunk/Source/WebKit/mac/WebView/WebHTMLView.mm	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebKit/mac/WebView/WebHTMLView.mm	2016-06-20 21:22:54 UTC (rev 202243)
@@ -3146,7 +3146,7 @@
     COMMAND_PROLOGUE
 
     if (Frame* coreFrame = core([self _frame]))
-        coreFrame->selection().revealSelection(ScrollAlignment::alignCenterAlways);
+        coreFrame->selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignCenterAlways);
 }
 
 #if !PLATFORM(IOS)
@@ -5345,7 +5345,7 @@
     COMMAND_PROLOGUE
 
     if (Frame* coreFrame = core([self _frame]))
-        coreFrame->selection().revealSelection(ScrollAlignment::alignCenterAlways);
+        coreFrame->selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignCenterAlways);
 }
 
 #if !PLATFORM(IOS)

Modified: trunk/Source/WebKit2/ChangeLog (202242 => 202243)


--- trunk/Source/WebKit2/ChangeLog	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebKit2/ChangeLog	2016-06-20 21:22:54 UTC (rev 202243)
@@ -1,3 +1,16 @@
+2016-06-20  Simon Fraser  <[email protected]>
+
+        Focus event dispatched in iframe causes parent document to scroll incorrectly
+        https://bugs.webkit.org/show_bug.cgi?id=158629
+        rdar://problem/26521616
+
+        Reviewed by Tim Horton.
+
+        Pass SelectionRevealMode::Reveal in existing code.
+
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::centerSelectionInVisibleArea):
+
 2016-06-20  Keith Rollin  <[email protected]>
 
         Remove RefPtr::release() and change calls sites to use WTFMove()

Modified: trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp (202242 => 202243)


--- trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp	2016-06-20 20:52:45 UTC (rev 202242)
+++ trunk/Source/WebKit2/WebProcess/WebPage/WebPage.cpp	2016-06-20 21:22:54 UTC (rev 202243)
@@ -2396,7 +2396,7 @@
 void WebPage::centerSelectionInVisibleArea()
 {
     Frame& frame = m_page->focusController().focusedOrMainFrame();
-    frame.selection().revealSelection(ScrollAlignment::alignCenterAlways);
+    frame.selection().revealSelection(SelectionRevealMode::Reveal, ScrollAlignment::alignCenterAlways);
     m_findController.showFindIndicatorInSelection();
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to