OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. | 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. |
4 * | 4 * |
5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
9 * | 9 * |
10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
(...skipping 755 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
766 | 766 |
767 void LayoutView::setSelection(const FrameSelection& selection) | 767 void LayoutView::setSelection(const FrameSelection& selection) |
768 { | 768 { |
769 // No need to create a pending clearSelection() to be executed in PendingSel
ection::commit() | 769 // No need to create a pending clearSelection() to be executed in PendingSel
ection::commit() |
770 // if there's no selection, since it's no-op. This is a frequent code path w
orth to optimize. | 770 // if there's no selection, since it's no-op. This is a frequent code path w
orth to optimize. |
771 if (selection.isNone() && !m_selectionStart && !m_selectionEnd && !hasPendin
gSelection()) | 771 if (selection.isNone() && !m_selectionStart && !m_selectionEnd && !hasPendin
gSelection()) |
772 return; | 772 return; |
773 m_pendingSelection->setSelection(selection); | 773 m_pendingSelection->setSelection(selection); |
774 } | 774 } |
775 | 775 |
776 template <typename Strategy> | |
777 void LayoutView::commitPendingSelectionAlgorithm() | |
778 { | |
779 using PositionType = typename Strategy::PositionType; | |
780 | |
781 if (!hasPendingSelection()) | |
782 return; | |
783 ASSERT(!needsLayout()); | |
784 | |
785 // Skip if pending VisibilePositions became invalid before we reach here. | |
786 if (!m_pendingSelection->isInDocument(document())) { | |
787 m_pendingSelection->clear(); | |
788 return; | |
789 } | |
790 | |
791 // Construct a new VisibleSolution, since m_selection is not necessarily val
id, and the following steps | |
792 // assume a valid selection. See <https://bugs.webkit.org/show_bug.cgi?id=69
563> and <rdar://problem/10232866>. | |
793 VisibleSelection selection = m_pendingSelection->calcVisibleSelection(); | |
794 m_pendingSelection->clear(); | |
795 | |
796 if (!selection.isRange()) { | |
797 clearSelection(); | |
798 return; | |
799 } | |
800 | |
801 // Use the rightmost candidate for the start of the selection, and the leftm
ost candidate for the end of the selection. | |
802 // Example: foo <a>bar</a>. Imagine that a line wrap occurs after 'foo', an
d that 'bar' is selected. If we pass [foo, 3] | |
803 // as the start of the selection, the selection painting code will think tha
t content on the line containing 'foo' is selected | |
804 // and will fill the gap before 'bar'. | |
805 PositionType startPos = Strategy::selectionStart(selection); | |
806 PositionType candidate = mostForwardCaretPosition(startPos); | |
807 if (isVisuallyEquivalentCandidate(candidate)) | |
808 startPos = candidate; | |
809 PositionType endPos = Strategy::selectionEnd(selection); | |
810 candidate = mostBackwardCaretPosition(endPos); | |
811 if (isVisuallyEquivalentCandidate(candidate)) | |
812 endPos = candidate; | |
813 | |
814 // We can get into a state where the selection endpoints map to the same Vis
iblePosition when a selection is deleted | |
815 // because we don't yet notify the FrameSelection of text removal. | |
816 if (startPos.isNull() || endPos.isNull() || Strategy::selectionVisibleStart(
selection).deepEquivalent() == Strategy::selectionVisibleEnd(selection).deepEqui
valent()) | |
817 return; | |
818 LayoutObject* startLayoutObject = startPos.anchorNode()->layoutObject(); | |
819 LayoutObject* endLayoutObject = endPos.anchorNode()->layoutObject(); | |
820 if (!startLayoutObject || !endLayoutObject) | |
821 return; | |
822 ASSERT(startLayoutObject->view() == this && endLayoutObject->view() == this)
; | |
823 setSelection(startLayoutObject, startPos.computeEditingOffset(), endLayoutOb
ject, endPos.computeEditingOffset()); | |
824 } | |
825 | |
826 void LayoutView::commitPendingSelection() | 776 void LayoutView::commitPendingSelection() |
827 { | 777 { |
828 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) | 778 m_pendingSelection->commit(*this); |
829 return commitPendingSelectionAlgorithm<VisibleSelection::InComposedTree>
(); | |
830 commitPendingSelectionAlgorithm<VisibleSelection::InDOMTree>(); | |
831 } | 779 } |
832 | 780 |
833 LayoutObject* LayoutView::selectionStart() | 781 LayoutObject* LayoutView::selectionStart() |
834 { | 782 { |
835 commitPendingSelection(); | 783 commitPendingSelection(); |
836 return m_selectionStart; | 784 return m_selectionStart; |
837 } | 785 } |
838 | 786 |
839 LayoutObject* LayoutView::selectionEnd() | 787 LayoutObject* LayoutView::selectionEnd() |
840 { | 788 { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 return viewHeight(IncludeScrollbars) / scale; | 954 return viewHeight(IncludeScrollbars) / scale; |
1007 } | 955 } |
1008 | 956 |
1009 void LayoutView::willBeDestroyed() | 957 void LayoutView::willBeDestroyed() |
1010 { | 958 { |
1011 LayoutBlockFlow::willBeDestroyed(); | 959 LayoutBlockFlow::willBeDestroyed(); |
1012 m_compositor.clear(); | 960 m_compositor.clear(); |
1013 } | 961 } |
1014 | 962 |
1015 } // namespace blink | 963 } // namespace blink |
OLD | NEW |