Chromium Code Reviews| Index: Source/core/editing/GranularityStrategy.cpp |
| diff --git a/Source/core/editing/GranularityStrategy.cpp b/Source/core/editing/GranularityStrategy.cpp |
| index 5a5fd9ee30330abf12efdd949c68fff152dc0636..a2ef3d7d08dc1b5f8e1db2264921090cb0176026 100644 |
| --- a/Source/core/editing/GranularityStrategy.cpp |
| +++ b/Source/core/editing/GranularityStrategy.cpp |
| @@ -5,9 +5,28 @@ |
| #include "config.h" |
| #include "core/editing/GranularityStrategy.h" |
| +#include "core/editing/FrameSelection.h" |
| #include "core/editing/htmlediting.h" |
| +#include "core/layout/HitTestRequest.h" |
| +#include "core/layout/HitTestResult.h" |
| +#include "core/layout/LayoutView.h" |
| +#include "core/paint/DeprecatedPaintLayer.h" |
| + |
| namespace blink { |
| +namespace { |
| + |
| +VisiblePosition visiblePositionForFramePoint(const IntPoint& framePoint, LocalFrame* frame) |
| +{ |
| + HitTestRequest request = HitTestRequest::Move | HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping; |
| + HitTestResult result(request, framePoint); |
| + frame->document()->layoutView()->layer()->hitTest(result); |
| + |
| + if (Node* node = result.innerNode()) |
| + return frame->selection().selection().visiblePositionRespectingEditingBoundary(result.localPoint(), node); |
| + return VisiblePosition(); |
| +} |
| +} |
| GranularityStrategy::GranularityStrategy() { } |
| @@ -24,14 +43,19 @@ SelectionStrategy CharacterGranularityStrategy::GetType() const |
| void CharacterGranularityStrategy::Clear() { }; |
| -VisibleSelection CharacterGranularityStrategy::updateExtent(const VisiblePosition& extentPosition, const VisibleSelection& selection) |
| +VisibleSelection CharacterGranularityStrategy::updateExtent(const IntPoint& framePoint, LocalFrame* frame) |
| { |
| + const VisiblePosition& extentPosition = visiblePositionForFramePoint(framePoint, frame); |
| + const VisibleSelection& selection = frame->selection().selection(); |
| + if (selection.visibleBase() == extentPosition) |
| + return selection; |
| return VisibleSelection(selection.visibleBase(), extentPosition); |
| } |
| DirectionGranularityStrategy::DirectionGranularityStrategy() |
| : m_granularity(CharacterGranularity) |
| - , m_lastMoveShrunkSelection(false) { } |
| + , m_lastMoveShrunkSelection(false) |
| + , m_offset(0) { } |
| DirectionGranularityStrategy::~DirectionGranularityStrategy() { } |
| @@ -44,6 +68,7 @@ void DirectionGranularityStrategy::Clear() |
| { |
| m_granularity = CharacterGranularity; |
| m_lastMoveShrunkSelection = false; |
| + m_offset = 0; |
| } |
| VisiblePosition DirectionGranularityStrategy::nextWordBound( |
| @@ -60,9 +85,24 @@ VisiblePosition DirectionGranularityStrategy::nextWordBound( |
| return startOfWord(pos, wordSide); |
| } |
| -VisibleSelection DirectionGranularityStrategy::updateExtent(const VisiblePosition& extentPosition, const VisibleSelection& selection) |
| +VisibleSelection DirectionGranularityStrategy::updateExtent(const IntPoint& extentPoint, LocalFrame* frame) |
| { |
| - if (extentPosition == selection.visibleExtent()) |
| + // Apply the offset if needed |
| + IntPoint offsetExtentPoint = extentPoint; |
| + if (m_offset != 0) { |
| + int dx = extentPoint.x() - m_extentPoint.x(); |
| + if (m_offset > 0 && dx > 0) |
| + m_offset = std::max(0, m_offset - dx); |
| + else if (m_offset < 0 && dx < 0) |
| + m_offset = std::min(0, m_offset - dx); |
| + offsetExtentPoint.move(m_offset, 0); |
| + } |
| + m_extentPoint = extentPoint; |
| + |
| + VisiblePosition extentPosition = visiblePositionForFramePoint(offsetExtentPoint, frame); |
| + const VisibleSelection& selection = frame->selection().selection(); |
| + |
| + if (selection.visibleBase() == extentPosition || extentPosition == selection.visibleExtent()) |
| return selection; |
| const VisiblePosition base = selection.visibleBase(); |
| @@ -108,18 +148,51 @@ VisibleSelection DirectionGranularityStrategy::updateExtent(const VisiblePositio |
| if (expandedBeyondWordBoundary) { |
| m_granularity = WordGranularity; |
| } else if (thisMoveShrunkSelection) { |
| + // If the offset is 0, we may need to update it and apply the offset to the extent. |
| + if (m_offset == 0) { |
| + if (extentBaseOrder > 0) { |
| + if (selection.end() != selection.extent()) |
| + m_offset = selection.visibleEnd().absoluteCaretBounds().x() - selection.visibleExtent().absoluteCaretBounds().x(); |
| + } else { |
| + if (selection.start() != selection.extent()) |
| + m_offset = selection.visibleStart().absoluteCaretBounds().x() - selection.visibleExtent().absoluteCaretBounds().x(); |
| + } |
| + if (m_offset != 0) { |
| + offsetExtentPoint.move(m_offset, 0); |
| + extentPosition = visiblePositionForFramePoint(offsetExtentPoint, frame); |
| + } |
| + } |
| m_granularity = CharacterGranularity; |
| m_lastMoveShrunkSelection = true; |
| } |
| m_lastMoveShrunkSelection = thisMoveShrunkSelection; |
| VisibleSelection newSelection = selection; |
| - newSelection.setExtent(extentPosition); |
| - if (m_granularity == WordGranularity) { |
| - if (extentBaseOrder > 0) |
| + |
| + if (m_granularity == CharacterGranularity) { |
| + newSelection.setExtent(extentPosition); |
| + } else { |
| + // Need to adjust extent by one position for the purposes of setting the |
| + // selection if the length of the current word is greater than 3. |
| + // This is so that the selection only expands to the end of the word when |
| + // the extent moves beyond the first character for words that are more |
| + // than 3 characters long. |
| + bool adjustExtent = false; |
| + Position boundBeforeExtent = nextWordBound(extentPosition, SearchDirection::SearchBackwards, BoundAdjust::CurrentPosIfOnBound).deepEquivalent(); |
| + if (boundBeforeExtent != extentPosition.deepEquivalent()) { |
| + Position boundAfterExtent = nextWordBound(extentPosition, SearchDirection::SearchForward, BoundAdjust::CurrentPosIfOnBound).deepEquivalent(); |
| + int wordLength = boundAfterExtent.offsetInContainerNode() - boundBeforeExtent.offsetInContainerNode(); |
| + adjustExtent = wordLength > 3; |
| + } |
| + |
| + if (extentBaseOrder > 0) { |
| + newSelection.setExtent(adjustExtent ? extentPosition.previous() : extentPosition); |
| newSelection.setEndRespectingGranularity(m_granularity, LeftWordIfOnBoundary); |
| - else |
| + } else { |
| + newSelection.setExtent(adjustExtent ? extentPosition.next() : extentPosition); |
| newSelection.setStartRespectingGranularity(m_granularity, RightWordIfOnBoundary); |
| + } |
| + newSelection.setWithoutValidation(newSelection.base(), extentPosition.deepEquivalent(), newSelection.start(), newSelection.end()); |
|
mfomitchev
2015/05/01 23:31:51
Note we actually only need to set the extent witho
|
| } |
| return newSelection; |