Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "core/editing/GranularityStrategy.h" | 6 #include "core/editing/GranularityStrategy.h" |
| 7 | 7 |
| 8 #include "core/editing/FrameSelection.h" | |
| 8 #include "core/editing/htmlediting.h" | 9 #include "core/editing/htmlediting.h" |
| 10 #include "core/layout/HitTestRequest.h" | |
| 11 #include "core/layout/HitTestResult.h" | |
| 12 #include "core/layout/LayoutView.h" | |
| 13 #include "core/paint/DeprecatedPaintLayer.h" | |
| 14 | |
| 9 | 15 |
| 10 namespace blink { | 16 namespace blink { |
| 17 namespace { | |
| 18 | |
| 19 VisiblePosition visiblePositionForFramePoint(const IntPoint& framePoint, LocalFr ame* frame) | |
| 20 { | |
| 21 HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | H itTestRequest::Active | HitTestRequest::IgnoreClipping; | |
| 22 HitTestResult result(request, framePoint); | |
| 23 frame->document()->layoutView()->layer()->hitTest(result); | |
| 24 | |
| 25 if (Node* node = result.innerNode()) | |
| 26 return frame->selection().selection().visiblePositionRespectingEditingBo undary(result.localPoint(), node); | |
| 27 return VisiblePosition(); | |
| 28 } | |
| 29 } | |
| 11 | 30 |
| 12 GranularityStrategy::GranularityStrategy() { } | 31 GranularityStrategy::GranularityStrategy() { } |
| 13 | 32 |
| 14 GranularityStrategy::~GranularityStrategy() { } | 33 GranularityStrategy::~GranularityStrategy() { } |
| 15 | 34 |
| 16 CharacterGranularityStrategy::CharacterGranularityStrategy() { } | 35 CharacterGranularityStrategy::CharacterGranularityStrategy() { } |
| 17 | 36 |
| 18 CharacterGranularityStrategy::~CharacterGranularityStrategy() { } | 37 CharacterGranularityStrategy::~CharacterGranularityStrategy() { } |
| 19 | 38 |
| 20 SelectionStrategy CharacterGranularityStrategy::GetType() const | 39 SelectionStrategy CharacterGranularityStrategy::GetType() const |
| 21 { | 40 { |
| 22 return SelectionStrategy::Character; | 41 return SelectionStrategy::Character; |
| 23 } | 42 } |
| 24 | 43 |
| 25 void CharacterGranularityStrategy::Clear() { }; | 44 void CharacterGranularityStrategy::Clear() { }; |
| 26 | 45 |
| 27 VisibleSelection CharacterGranularityStrategy::updateExtent(const VisiblePositio n& extentPosition, const VisibleSelection& selection) | 46 VisibleSelection CharacterGranularityStrategy::updateExtent(const IntPoint& fram ePoint, LocalFrame* frame) |
| 28 { | 47 { |
| 48 const VisiblePosition& extentPosition = visiblePositionForFramePoint(framePo int, frame); | |
| 49 const VisibleSelection& selection = frame->selection().selection(); | |
| 50 if (selection.visibleBase() == extentPosition) | |
| 51 return selection; | |
| 29 return VisibleSelection(selection.visibleBase(), extentPosition); | 52 return VisibleSelection(selection.visibleBase(), extentPosition); |
| 30 } | 53 } |
| 31 | 54 |
| 32 DirectionGranularityStrategy::DirectionGranularityStrategy() | 55 DirectionGranularityStrategy::DirectionGranularityStrategy() |
| 33 : m_granularity(CharacterGranularity) | 56 : m_granularity(CharacterGranularity) |
| 34 , m_lastMoveShrunkSelection(false) { } | 57 , m_lastMoveShrunkSelection(false) |
| 58 , m_offset(0) { } | |
| 35 | 59 |
| 36 DirectionGranularityStrategy::~DirectionGranularityStrategy() { } | 60 DirectionGranularityStrategy::~DirectionGranularityStrategy() { } |
| 37 | 61 |
| 38 SelectionStrategy DirectionGranularityStrategy::GetType() const | 62 SelectionStrategy DirectionGranularityStrategy::GetType() const |
| 39 { | 63 { |
| 40 return SelectionStrategy::Direction; | 64 return SelectionStrategy::Direction; |
| 41 } | 65 } |
| 42 | 66 |
| 43 void DirectionGranularityStrategy::Clear() | 67 void DirectionGranularityStrategy::Clear() |
| 44 { | 68 { |
| 45 m_granularity = CharacterGranularity; | 69 m_granularity = CharacterGranularity; |
| 46 m_lastMoveShrunkSelection = false; | 70 m_lastMoveShrunkSelection = false; |
| 71 m_offset = 0; | |
| 47 } | 72 } |
| 48 | 73 |
| 49 VisiblePosition DirectionGranularityStrategy::nextWordBound( | 74 VisiblePosition DirectionGranularityStrategy::nextWordBound( |
| 50 const VisiblePosition& pos, | 75 const VisiblePosition& pos, |
| 51 SearchDirection direction, | 76 SearchDirection direction, |
| 52 BoundAdjust wordBoundAdjust) | 77 BoundAdjust wordBoundAdjust) |
| 53 { | 78 { |
| 54 bool nextBoundIfOnBound = wordBoundAdjust == BoundAdjust::NextBoundIfOnBoun d; | 79 bool nextBoundIfOnBound = wordBoundAdjust == BoundAdjust::NextBoundIfOnBoun d; |
| 55 if (direction == SearchDirection::SearchForward) { | 80 if (direction == SearchDirection::SearchForward) { |
| 56 EWordSide wordSide = nextBoundIfOnBound ? RightWordIfOnBoundary : LeftWo rdIfOnBoundary; | 81 EWordSide wordSide = nextBoundIfOnBound ? RightWordIfOnBoundary : LeftWo rdIfOnBoundary; |
| 57 return endOfWord(pos, wordSide); | 82 return endOfWord(pos, wordSide); |
| 58 } | 83 } |
| 59 EWordSide wordSide = nextBoundIfOnBound ? LeftWordIfOnBoundary : RightWordIf OnBoundary; | 84 EWordSide wordSide = nextBoundIfOnBound ? LeftWordIfOnBoundary : RightWordIf OnBoundary; |
| 60 return startOfWord(pos, wordSide); | 85 return startOfWord(pos, wordSide); |
| 61 } | 86 } |
| 62 | 87 |
| 63 VisibleSelection DirectionGranularityStrategy::updateExtent(const VisiblePositio n& extentPosition, const VisibleSelection& selection) | 88 VisibleSelection DirectionGranularityStrategy::updateExtent(const IntPoint& exte ntPoint, LocalFrame* frame) |
| 64 { | 89 { |
| 65 if (extentPosition == selection.visibleExtent()) | 90 // Apply the offset if needed |
| 91 IntPoint offsetExtentPoint = extentPoint; | |
| 92 if (m_offset != 0) { | |
| 93 int dx = extentPoint.x() - m_extentPoint.x(); | |
| 94 if (m_offset > 0 && dx > 0) | |
| 95 m_offset = std::max(0, m_offset - dx); | |
| 96 else if (m_offset < 0 && dx < 0) | |
| 97 m_offset = std::min(0, m_offset - dx); | |
| 98 offsetExtentPoint.move(m_offset, 0); | |
| 99 } | |
| 100 m_extentPoint = extentPoint; | |
| 101 | |
| 102 VisiblePosition extentPosition = visiblePositionForFramePoint(offsetExtentPo int, frame); | |
| 103 const VisibleSelection& selection = frame->selection().selection(); | |
| 104 | |
| 105 if (selection.visibleBase() == extentPosition || extentPosition == selection .visibleExtent()) | |
| 66 return selection; | 106 return selection; |
| 67 | 107 |
| 68 const VisiblePosition base = selection.visibleBase(); | 108 const VisiblePosition base = selection.visibleBase(); |
| 69 const VisiblePosition oldExtentWithGranularity = selection.isBaseFirst() ? s election.visibleEnd() : selection.visibleStart(); | 109 const VisiblePosition oldExtentWithGranularity = selection.isBaseFirst() ? s election.visibleEnd() : selection.visibleStart(); |
| 70 | 110 |
| 71 int extentBaseOrder = comparePositions(extentPosition, base); | 111 int extentBaseOrder = comparePositions(extentPosition, base); |
| 72 int oldExtentBaseOrder = comparePositions(oldExtentWithGranularity, base); | 112 int oldExtentBaseOrder = comparePositions(oldExtentWithGranularity, base); |
| 73 | 113 |
| 74 bool extentBaseOrderSwitched = (extentBaseOrder > 0 && oldExtentBaseOrder < 0) | 114 bool extentBaseOrderSwitched = (extentBaseOrder > 0 && oldExtentBaseOrder < 0) |
| 75 || (extentBaseOrder < 0 && oldExtentBaseOrder > 0); | 115 || (extentBaseOrder < 0 && oldExtentBaseOrder > 0); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 101 } | 141 } |
| 102 | 142 |
| 103 bool expandedBeyondWordBoundary; | 143 bool expandedBeyondWordBoundary; |
| 104 if (extentBaseOrder > 0) | 144 if (extentBaseOrder > 0) |
| 105 expandedBeyondWordBoundary = comparePositions(extentPosition, currentWor dBoundary) > 0; | 145 expandedBeyondWordBoundary = comparePositions(extentPosition, currentWor dBoundary) > 0; |
| 106 else | 146 else |
| 107 expandedBeyondWordBoundary = comparePositions(extentPosition, currentWor dBoundary) < 0; | 147 expandedBeyondWordBoundary = comparePositions(extentPosition, currentWor dBoundary) < 0; |
| 108 if (expandedBeyondWordBoundary) { | 148 if (expandedBeyondWordBoundary) { |
| 109 m_granularity = WordGranularity; | 149 m_granularity = WordGranularity; |
| 110 } else if (thisMoveShrunkSelection) { | 150 } else if (thisMoveShrunkSelection) { |
| 151 // If the offset is 0, we may need to update it and apply the offset to the extent. | |
| 152 if (m_offset == 0) { | |
| 153 if (extentBaseOrder > 0) { | |
| 154 if (selection.end() != selection.extent()) | |
| 155 m_offset = selection.visibleEnd().absoluteCaretBounds().x() - selection.visibleExtent().absoluteCaretBounds().x(); | |
| 156 } else { | |
| 157 if (selection.start() != selection.extent()) | |
| 158 m_offset = selection.visibleStart().absoluteCaretBounds().x( ) - selection.visibleExtent().absoluteCaretBounds().x(); | |
| 159 } | |
| 160 if (m_offset != 0) { | |
| 161 offsetExtentPoint.move(m_offset, 0); | |
| 162 extentPosition = visiblePositionForFramePoint(offsetExtentPoint, frame); | |
| 163 } | |
| 164 } | |
| 111 m_granularity = CharacterGranularity; | 165 m_granularity = CharacterGranularity; |
| 112 m_lastMoveShrunkSelection = true; | 166 m_lastMoveShrunkSelection = true; |
| 113 } | 167 } |
| 114 | 168 |
| 115 m_lastMoveShrunkSelection = thisMoveShrunkSelection; | 169 m_lastMoveShrunkSelection = thisMoveShrunkSelection; |
| 116 VisibleSelection newSelection = selection; | 170 VisibleSelection newSelection = selection; |
| 117 newSelection.setExtent(extentPosition); | 171 |
| 118 if (m_granularity == WordGranularity) { | 172 if (m_granularity == CharacterGranularity) { |
| 119 if (extentBaseOrder > 0) | 173 newSelection.setExtent(extentPosition); |
| 174 } else { | |
| 175 // Need to adjust extent by one position for the purposes of setting the | |
| 176 // selection if the length of the current word is greater than 3. | |
| 177 // This is so that the selection only expands to the end of the word whe n | |
| 178 // the extent moves beyond the first character for words that are more | |
| 179 // than 3 characters long. | |
| 180 bool adjustExtent = false; | |
| 181 Position boundBeforeExtent = nextWordBound(extentPosition, SearchDirecti on::SearchBackwards, BoundAdjust::CurrentPosIfOnBound).deepEquivalent(); | |
| 182 if (boundBeforeExtent != extentPosition.deepEquivalent()) { | |
| 183 Position boundAfterExtent = nextWordBound(extentPosition, SearchDire ction::SearchForward, BoundAdjust::CurrentPosIfOnBound).deepEquivalent(); | |
| 184 int wordLength = boundAfterExtent.offsetInContainerNode() - boundBef oreExtent.offsetInContainerNode(); | |
| 185 adjustExtent = wordLength > 3; | |
| 186 } | |
| 187 | |
| 188 if (extentBaseOrder > 0) { | |
| 189 newSelection.setExtent(adjustExtent ? extentPosition.previous() : ex tentPosition); | |
| 120 newSelection.setEndRespectingGranularity(m_granularity, LeftWordIfOn Boundary); | 190 newSelection.setEndRespectingGranularity(m_granularity, LeftWordIfOn Boundary); |
| 121 else | 191 } else { |
| 192 newSelection.setExtent(adjustExtent ? extentPosition.next() : extent Position); | |
| 122 newSelection.setStartRespectingGranularity(m_granularity, RightWordI fOnBoundary); | 193 newSelection.setStartRespectingGranularity(m_granularity, RightWordI fOnBoundary); |
| 194 } | |
| 195 newSelection.setWithoutValidation(newSelection.base(), extentPosition.de epEquivalent(), newSelection.start(), newSelection.end()); | |
|
mfomitchev
2015/05/01 23:31:51
Note we actually only need to set the extent witho
| |
| 123 } | 196 } |
| 124 | 197 |
| 125 return newSelection; | 198 return newSelection; |
| 126 } | 199 } |
| 127 | 200 |
| 128 } // namespace blink | 201 } // namespace blink |
| OLD | NEW |