void PendingSelection::commitAlgorithm(LayoutView& layoutView) { if (!hasPendingSelection()) return; ASSERT(!layoutView.needsLayout()); m_hasPendingSelection = false; const VisibleSelectionTemplate<Strategy> originalSelection = m_frameSelection->visibleSelection<Strategy>(); // Skip if pending VisibilePositions became invalid before we reach here. if (!isSelectionInDocument(originalSelection, layoutView.document())) return; // Construct a new VisibleSolution, since visibleSelection() 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>. const VisibleSelectionTemplate<Strategy> selection = calcVisibleSelectionAlgorithm<Strategy>(originalSelection); 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'. PositionTemplate<Strategy> startPos = selection.start(); PositionTemplate<Strategy> candidate = mostForwardCaretPosition(startPos); if (isVisuallyEquivalentCandidate(candidate)) startPos = candidate; PositionTemplate<Strategy> endPos = selection.end(); 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() || selection.visibleStart().deepEquivalent() == selection.visibleEnd().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()); }
PositionIteratorAlgorithm<Strategy>::PositionIteratorAlgorithm( const PositionTemplate<Strategy>& pos) : PositionIteratorAlgorithm(pos.anchorNode(), pos.computeEditingOffset()) {}