| Index: Source/core/layout/PendingSelection.cpp
|
| diff --git a/Source/core/layout/PendingSelection.cpp b/Source/core/layout/PendingSelection.cpp
|
| index e466c4875fc6602cefe0ba3e7f2a831d9900dcf5..6686a1033137fc52de3e9da9e78f27a0fd967d01 100644
|
| --- a/Source/core/layout/PendingSelection.cpp
|
| +++ b/Source/core/layout/PendingSelection.cpp
|
| @@ -27,6 +27,7 @@
|
| #include "core/editing/VisiblePosition.h"
|
| #include "core/editing/VisibleUnits.h"
|
| #include "core/html/HTMLTextFormControlElement.h"
|
| +#include "core/layout/LayoutView.h"
|
|
|
| namespace blink {
|
|
|
| @@ -105,11 +106,66 @@ VisibleSelection PendingSelection::calcVisibleSelectionAlgorithm() const
|
| return VisibleSelection(visibleStart, visibleEnd);
|
| }
|
|
|
| -VisibleSelection PendingSelection::calcVisibleSelection() const
|
| +template <typename Strategy>
|
| +void PendingSelection::commitAlgorithm(LayoutView& layoutView)
|
| +{
|
| + using PositionType = typename Strategy::PositionType;
|
| +
|
| + if (!hasPendingSelection())
|
| + return;
|
| + ASSERT(!layoutView.needsLayout());
|
| +
|
| + // Skip if pending VisibilePositions became invalid before we reach here.
|
| + if (!isInDocument(layoutView.document())) {
|
| + clear();
|
| + return;
|
| + }
|
| +
|
| + // Construct a new VisibleSolution, since m_selection is not necessarily
|
| + // valid, and the following steps assume a valid selection.
|
| + // See <https://bugs.webkit.org/show_bug.cgi?id=69563> and
|
| + // <rdar://problem/10232866>.
|
| + VisibleSelection selection = calcVisibleSelectionAlgorithm<Strategy>();
|
| + clear();
|
| +
|
| + if (!selection.isRange()) {
|
| + layoutView.clearSelection();
|
| + return;
|
| + }
|
| +
|
| + // Use the rightmost candidate for the start of the selection, and the
|
| + // leftmost candidate for the end of the selection. Example: foo <a>bar</a>.
|
| + // Imagine that a line wrap occurs after 'foo', and that 'bar' is selected.
|
| + // If we pass [foo, 3] as the start of the selection, the selection painting
|
| + // code will think that content on the line containing 'foo' is selected
|
| + // and will fill the gap before 'bar'.
|
| + PositionType startPos = Strategy::selectionStart(selection);
|
| + PositionType candidate = mostForwardCaretPosition(startPos);
|
| + if (isVisuallyEquivalentCandidate(candidate))
|
| + startPos = candidate;
|
| + PositionType endPos = Strategy::selectionEnd(selection);
|
| + candidate = mostBackwardCaretPosition(endPos);
|
| + if (isVisuallyEquivalentCandidate(candidate))
|
| + endPos = candidate;
|
| +
|
| + // We can get into a state where the selection endpoints map to the same
|
| + // |VisiblePosition| when a selection is deleted because we don't yet notify
|
| + // the |FrameSelection| of text removal.
|
| + if (startPos.isNull() || endPos.isNull() || Strategy::selectionVisibleStart(selection).deepEquivalent() == Strategy::selectionVisibleEnd(selection).deepEquivalent())
|
| + return;
|
| + LayoutObject* startLayoutObject = startPos.anchorNode()->layoutObject();
|
| + LayoutObject* endLayoutObject = endPos.anchorNode()->layoutObject();
|
| + if (!startLayoutObject || !endLayoutObject)
|
| + return;
|
| + ASSERT(layoutView == startLayoutObject->view() && layoutView == endLayoutObject->view());
|
| + layoutView.setSelection(startLayoutObject, startPos.computeEditingOffset(), endLayoutObject, endPos.computeEditingOffset());
|
| +}
|
| +
|
| +void PendingSelection::commit(LayoutView& layoutView)
|
| {
|
| if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled())
|
| - return calcVisibleSelectionAlgorithm<VisibleSelection::InComposedTree>();
|
| - return calcVisibleSelectionAlgorithm<VisibleSelection::InDOMTree>();
|
| + return commitAlgorithm<VisibleSelection::InComposedTree>(layoutView);
|
| + commitAlgorithm<VisibleSelection::InDOMTree>(layoutView);
|
| }
|
|
|
| DEFINE_TRACE(PendingSelection)
|
|
|