Use current selection when tab navigation.
This CL lets FrameSelection::RevealSelection()
use VisibleUnits::ComputeTextRect() to compute current selection range
instead of LayoutSelection::Bounds() of last selection range.
VisibleUnits.cpp::ComputeTextRect():
templatize to define flat tree version.
BUG=712986
Review-Url: https://codereview.chromium.org/2894803002
Cr-Commit-Position: refs/heads/master@{#473546}
diff --git a/third_party/WebKit/LayoutTests/editing/input/scroll-with-tab-to-input-regression.html b/third_party/WebKit/LayoutTests/editing/input/scroll-with-tab-to-input-regression.html
new file mode 100644
index 0000000..97bbc20
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/editing/input/scroll-with-tab-to-input-regression.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<div style="margin-top:120%"><input id="checkbox" type="checkbox" /></div>
+<input id="input" value="foo">
+<script>
+promise_test(() =>{return new Promise((resolve) => {
+ if (window.eventSender === undefined)
+ return reject('required window.eventSender');
+ checkbox.focus();
+ setTimeout(resolve, 0);
+}).then(() => {
+ var scrollY = window.scrollY;
+ assert_greater_than(window.scrollY, 0);
+ assert_equals(document.activeElement, checkbox);
+ eventSender.keyDown('Tab');
+ assert_equals(document.activeElement, input);
+ eventSender.keyDown('Tab', ['shiftKey']);
+ assert_equals(document.activeElement, checkbox);
+ eventSender.keyDown('Tab');
+ return new Promise((resolve) => {
+ setTimeout(resolve(scrollY), 0);
+ });
+}).then((scrollY) => {
+ assert_equals(window.scrollY, scrollY, 'Screen should not scroll');
+});});
+</script>
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.cpp b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
index b321e50..91eca913 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.cpp
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.cpp
@@ -949,6 +949,13 @@
return LayoutRect(layout_selection_->SelectionBounds());
}
+static IntRect AbsoluteSelectionBoundsOf(
+ const VisibleSelectionInFlatTree& selection) {
+ return ComputeTextRect(
+ EphemeralRangeInFlatTree(selection.Start(), selection.end()));
+}
+
+// TODO(editing-dev): This should be done in FlatTree world.
void FrameSelection::RevealSelection(const ScrollAlignment& alignment,
RevealExtentOption reveal_extent_option) {
DCHECK(IsAvailable());
@@ -967,10 +974,11 @@
rect = LayoutRect(AbsoluteCaretBounds());
break;
case kRangeSelection:
- rect = LayoutRect(reveal_extent_option == kRevealExtent
- ? AbsoluteCaretBoundsOf(CreateVisiblePosition(
- ComputeVisibleSelectionInDOMTree().Extent()))
- : EnclosingIntRect(UnclippedBounds()));
+ rect = LayoutRect(
+ reveal_extent_option == kRevealExtent
+ ? AbsoluteCaretBoundsOf(CreateVisiblePosition(
+ ComputeVisibleSelectionInDOMTree().Extent()))
+ : AbsoluteSelectionBoundsOf(ComputeVisibleSelectionInFlatTree()));
break;
}
diff --git a/third_party/WebKit/Source/core/editing/FrameSelection.h b/third_party/WebKit/Source/core/editing/FrameSelection.h
index b5125f1..b8e39d7 100644
--- a/third_party/WebKit/Source/core/editing/FrameSelection.h
+++ b/third_party/WebKit/Source/core/editing/FrameSelection.h
@@ -230,6 +230,8 @@
String SelectedTextForClipboard() const;
// The bounds are clipped to the viewport as this is what callers expect.
+ // This returns last layouted selection bounds of LayoutSelection rather than
+ // SelectionEditor keeps.
LayoutRect Bounds() const;
LayoutRect UnclippedBounds() const;
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
index e9a3f65..d9581df 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.cpp
@@ -4119,10 +4119,11 @@
layout_text.AbsoluteQuadsForRange(quads, start, end);
}
-template <typename RectType>
-static Vector<RectType> ComputeTextBounds(const EphemeralRange& range) {
- const Position& start_position = range.StartPosition();
- const Position& end_position = range.EndPosition();
+template <typename RectType, typename Strategy>
+static Vector<RectType> ComputeTextBounds(
+ const EphemeralRangeTemplate<Strategy>& range) {
+ const PositionTemplate<Strategy>& start_position = range.StartPosition();
+ const PositionTemplate<Strategy>& end_position = range.EndPosition();
Node* const start_container = start_position.ComputeContainerNode();
DCHECK(start_container);
Node* const end_container = end_position.ComputeContainerNode();
@@ -4145,14 +4146,24 @@
return result;
}
-IntRect ComputeTextRect(const EphemeralRange& range) {
+template <typename Strategy>
+static IntRect ComputeTextRectTemplate(
+ const EphemeralRangeTemplate<Strategy>& range) {
IntRect result;
- const Vector<IntRect>& rects = ComputeTextBounds<IntRect>(range);
+ const Vector<IntRect>& rects = ComputeTextBounds<IntRect, Strategy>(range);
for (const IntRect& rect : rects)
result.Unite(rect);
return result;
}
+IntRect ComputeTextRect(const EphemeralRange& range) {
+ return ComputeTextRectTemplate(range);
+}
+
+IntRect ComputeTextRect(const EphemeralRangeInFlatTree& range) {
+ return ComputeTextRectTemplate(range);
+}
+
Vector<FloatQuad> ComputeTextQuads(const EphemeralRange& range) {
return ComputeTextBounds<FloatQuad>(range);
}
diff --git a/third_party/WebKit/Source/core/editing/VisibleUnits.h b/third_party/WebKit/Source/core/editing/VisibleUnits.h
index 28908be..e62d4f2a 100644
--- a/third_party/WebKit/Source/core/editing/VisibleUnits.h
+++ b/third_party/WebKit/Source/core/editing/VisibleUnits.h
@@ -343,6 +343,7 @@
CORE_EXPORT PositionInFlatTree SkipWhitespace(const PositionInFlatTree&);
CORE_EXPORT IntRect ComputeTextRect(const EphemeralRange&);
+IntRect ComputeTextRect(const EphemeralRangeInFlatTree&);
CORE_EXPORT Vector<FloatQuad> ComputeTextQuads(const EphemeralRange&);
} // namespace blink