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, |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 * Library General Public License for more details. | 13 * Library General Public License for more details. |
14 * | 14 * |
15 * You should have received a copy of the GNU Library General Public License | 15 * You should have received a copy of the GNU Library General Public License |
16 * along with this library; see the file COPYING.LIB. If not, write to | 16 * along with this library; see the file COPYING.LIB. If not, write to |
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 * Boston, MA 02110-1301, USA. | 18 * Boston, MA 02110-1301, USA. |
19 */ | 19 */ |
20 | 20 |
21 #include "config.h" | 21 #include "config.h" |
22 #include "core/layout/PendingSelection.h" | 22 #include "core/layout/PendingSelection.h" |
23 | 23 |
24 #include "core/dom/Document.h" | 24 #include "core/dom/Document.h" |
25 #include "core/editing/EditingUtilities.h" | 25 #include "core/editing/EditingUtilities.h" |
26 #include "core/editing/FrameSelection.h" | 26 #include "core/editing/FrameSelection.h" |
27 #include "core/editing/VisiblePosition.h" | 27 #include "core/editing/VisiblePosition.h" |
28 #include "core/editing/VisibleUnits.h" | 28 #include "core/editing/VisibleUnits.h" |
29 #include "core/html/HTMLTextFormControlElement.h" | 29 #include "core/html/HTMLTextFormControlElement.h" |
| 30 #include "core/layout/LayoutView.h" |
30 | 31 |
31 namespace blink { | 32 namespace blink { |
32 | 33 |
33 PendingSelection::PendingSelection() | 34 PendingSelection::PendingSelection() |
34 : m_hasPendingSelection(false) | 35 : m_hasPendingSelection(false) |
35 , m_shouldShowBlockCursor(false) | 36 , m_shouldShowBlockCursor(false) |
36 { | 37 { |
37 clear(); | 38 clear(); |
38 } | 39 } |
39 | 40 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 VisiblePosition visibleStart = createVisiblePosition(start, selectionType ==
SelectionType::RangeSelection ? TextAffinity::Downstream : affinity); | 99 VisiblePosition visibleStart = createVisiblePosition(start, selectionType ==
SelectionType::RangeSelection ? TextAffinity::Downstream : affinity); |
99 if (paintBlockCursor) { | 100 if (paintBlockCursor) { |
100 VisiblePosition visibleExtent = createVisiblePosition(end, affinity); | 101 VisiblePosition visibleExtent = createVisiblePosition(end, affinity); |
101 visibleExtent = nextPositionOf(visibleExtent, CanSkipOverEditingBoundary
); | 102 visibleExtent = nextPositionOf(visibleExtent, CanSkipOverEditingBoundary
); |
102 return VisibleSelection(visibleStart, visibleExtent); | 103 return VisibleSelection(visibleStart, visibleExtent); |
103 } | 104 } |
104 VisiblePosition visibleEnd = createVisiblePosition(end, selectionType == Sel
ectionType::RangeSelection ? TextAffinity::Upstream : affinity); | 105 VisiblePosition visibleEnd = createVisiblePosition(end, selectionType == Sel
ectionType::RangeSelection ? TextAffinity::Upstream : affinity); |
105 return VisibleSelection(visibleStart, visibleEnd); | 106 return VisibleSelection(visibleStart, visibleEnd); |
106 } | 107 } |
107 | 108 |
108 VisibleSelection PendingSelection::calcVisibleSelection() const | 109 template <typename Strategy> |
| 110 void PendingSelection::commitAlgorithm(LayoutView& layoutView) |
| 111 { |
| 112 using PositionType = typename Strategy::PositionType; |
| 113 |
| 114 if (!hasPendingSelection()) |
| 115 return; |
| 116 ASSERT(!layoutView.needsLayout()); |
| 117 |
| 118 // Skip if pending VisibilePositions became invalid before we reach here. |
| 119 if (!isInDocument(layoutView.document())) { |
| 120 clear(); |
| 121 return; |
| 122 } |
| 123 |
| 124 // Construct a new VisibleSolution, since m_selection is not necessarily |
| 125 // valid, and the following steps assume a valid selection. |
| 126 // See <https://bugs.webkit.org/show_bug.cgi?id=69563> and |
| 127 // <rdar://problem/10232866>. |
| 128 VisibleSelection selection = calcVisibleSelectionAlgorithm<Strategy>(); |
| 129 clear(); |
| 130 |
| 131 if (!selection.isRange()) { |
| 132 layoutView.clearSelection(); |
| 133 return; |
| 134 } |
| 135 |
| 136 // Use the rightmost candidate for the start of the selection, and the |
| 137 // leftmost candidate for the end of the selection. Example: foo <a>bar</a>. |
| 138 // Imagine that a line wrap occurs after 'foo', and that 'bar' is selected. |
| 139 // If we pass [foo, 3] as the start of the selection, the selection painting |
| 140 // code will think that content on the line containing 'foo' is selected |
| 141 // and will fill the gap before 'bar'. |
| 142 PositionType startPos = Strategy::selectionStart(selection); |
| 143 PositionType candidate = mostForwardCaretPosition(startPos); |
| 144 if (isVisuallyEquivalentCandidate(candidate)) |
| 145 startPos = candidate; |
| 146 PositionType endPos = Strategy::selectionEnd(selection); |
| 147 candidate = mostBackwardCaretPosition(endPos); |
| 148 if (isVisuallyEquivalentCandidate(candidate)) |
| 149 endPos = candidate; |
| 150 |
| 151 // We can get into a state where the selection endpoints map to the same |
| 152 // |VisiblePosition| when a selection is deleted because we don't yet notify |
| 153 // the |FrameSelection| of text removal. |
| 154 if (startPos.isNull() || endPos.isNull() || Strategy::selectionVisibleStart(
selection).deepEquivalent() == Strategy::selectionVisibleEnd(selection).deepEqui
valent()) |
| 155 return; |
| 156 LayoutObject* startLayoutObject = startPos.anchorNode()->layoutObject(); |
| 157 LayoutObject* endLayoutObject = endPos.anchorNode()->layoutObject(); |
| 158 if (!startLayoutObject || !endLayoutObject) |
| 159 return; |
| 160 ASSERT(layoutView == startLayoutObject->view() && layoutView == endLayoutObj
ect->view()); |
| 161 layoutView.setSelection(startLayoutObject, startPos.computeEditingOffset(),
endLayoutObject, endPos.computeEditingOffset()); |
| 162 } |
| 163 |
| 164 void PendingSelection::commit(LayoutView& layoutView) |
109 { | 165 { |
110 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) | 166 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) |
111 return calcVisibleSelectionAlgorithm<VisibleSelection::InComposedTree>()
; | 167 return commitAlgorithm<VisibleSelection::InComposedTree>(layoutView); |
112 return calcVisibleSelectionAlgorithm<VisibleSelection::InDOMTree>(); | 168 commitAlgorithm<VisibleSelection::InDOMTree>(layoutView); |
113 } | 169 } |
114 | 170 |
115 DEFINE_TRACE(PendingSelection) | 171 DEFINE_TRACE(PendingSelection) |
116 { | 172 { |
117 visitor->trace(m_selection); | 173 visitor->trace(m_selection); |
118 } | 174 } |
119 | 175 |
120 } // namespace blink | 176 } // namespace blink |
OLD | NEW |