| Index: third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
|
| diff --git a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
|
| index 97baaabca2d756ceb2d1776496e7c67f0d518d3c..58932b0e1db3c1992a61a5eb95b5df9d767b9e3f 100644
|
| --- a/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
|
| +++ b/third_party/WebKit/Source/core/layout/LayoutBlockFlow.cpp
|
| @@ -31,6 +31,7 @@
|
| #include "core/layout/LayoutBlockFlow.h"
|
|
|
| #include "core/dom/AXObjectCache.h"
|
| +#include "core/editing/Editor.h"
|
| #include "core/frame/FrameView.h"
|
| #include "core/frame/LocalFrame.h"
|
| #include "core/frame/Settings.h"
|
| @@ -3180,6 +3181,106 @@ bool LayoutBlockFlow::recalcInlineChildrenOverflowAfterStyleChange()
|
| return childrenOverflowChanged;
|
| }
|
|
|
| +PositionWithAffinity LayoutBlockFlow::positionForPoint(const LayoutPoint& point)
|
| +{
|
| + if (isAtomicInlineLevel()) {
|
| + PositionWithAffinity position = positionForPointIfOutsideAtomicInlineLevel(point);
|
| + if (!position.isNull())
|
| + return position;
|
| + }
|
| + if (!childrenInline())
|
| + return LayoutBlock::positionForPoint(point);
|
| +
|
| + LayoutPoint pointInContents = point;
|
| + offsetForContents(pointInContents);
|
| + LayoutPoint pointInLogicalContents(pointInContents);
|
| + if (!isHorizontalWritingMode())
|
| + pointInLogicalContents = pointInLogicalContents.transposedPoint();
|
| +
|
| + if (!firstRootBox())
|
| + return createPositionWithAffinity(0);
|
| +
|
| + bool linesAreFlipped = style()->isFlippedLinesWritingMode();
|
| + bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
|
| +
|
| + // look for the closest line box in the root box which is at the passed-in y coordinate
|
| + InlineBox* closestBox = nullptr;
|
| + RootInlineBox* firstRootBoxWithChildren = nullptr;
|
| + RootInlineBox* lastRootBoxWithChildren = nullptr;
|
| + for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
|
| + if (!root->firstLeafChild())
|
| + continue;
|
| + if (!firstRootBoxWithChildren)
|
| + firstRootBoxWithChildren = root;
|
| +
|
| + if (!linesAreFlipped && root->isFirstAfterPageBreak() && (pointInLogicalContents.y() < root->lineTopWithLeading()
|
| + || (blocksAreFlipped && pointInLogicalContents.y() == root->lineTopWithLeading())))
|
| + break;
|
| +
|
| + lastRootBoxWithChildren = root;
|
| +
|
| + // check if this root line box is located at this y coordinate
|
| + if (pointInLogicalContents.y() < root->selectionBottom() || (blocksAreFlipped && pointInLogicalContents.y() == root->selectionBottom())) {
|
| + if (linesAreFlipped) {
|
| + RootInlineBox* nextRootBoxWithChildren = root->nextRootBox();
|
| + while (nextRootBoxWithChildren && !nextRootBoxWithChildren->firstLeafChild())
|
| + nextRootBoxWithChildren = nextRootBoxWithChildren->nextRootBox();
|
| +
|
| + if (nextRootBoxWithChildren && nextRootBoxWithChildren->isFirstAfterPageBreak() && (pointInLogicalContents.y() > nextRootBoxWithChildren->lineTopWithLeading()
|
| + || (!blocksAreFlipped && pointInLogicalContents.y() == nextRootBoxWithChildren->lineTopWithLeading())))
|
| + continue;
|
| + }
|
| + closestBox = root->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x());
|
| + if (closestBox)
|
| + break;
|
| + }
|
| + }
|
| +
|
| + bool moveCaretToBoundary = document().frame()->editor().behavior().shouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();
|
| +
|
| + if (!moveCaretToBoundary && !closestBox && lastRootBoxWithChildren) {
|
| + // y coordinate is below last root line box, pretend we hit it
|
| + closestBox = lastRootBoxWithChildren->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x());
|
| + }
|
| +
|
| + if (closestBox) {
|
| + if (moveCaretToBoundary) {
|
| + LayoutUnit firstRootBoxWithChildrenTop = std::min<LayoutUnit>(firstRootBoxWithChildren->selectionTop(), firstRootBoxWithChildren->logicalTop());
|
| + if (pointInLogicalContents.y() < firstRootBoxWithChildrenTop
|
| + || (blocksAreFlipped && pointInLogicalContents.y() == firstRootBoxWithChildrenTop)) {
|
| + InlineBox* box = firstRootBoxWithChildren->firstLeafChild();
|
| + if (box->isLineBreak()) {
|
| + if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak())
|
| + box = newBox;
|
| + }
|
| + // y coordinate is above first root line box, so return the start of the first
|
| + return PositionWithAffinity(positionForBox(box, true));
|
| + }
|
| + }
|
| +
|
| + // pass the box a top position that is inside it
|
| + LayoutPoint point(pointInLogicalContents.x(), closestBox->root().blockDirectionPointInLine());
|
| + if (!isHorizontalWritingMode())
|
| + point = point.transposedPoint();
|
| + if (closestBox->getLineLayoutItem().isAtomicInlineLevel())
|
| + return positionForPointRespectingEditingBoundaries(LineLayoutBox(closestBox->getLineLayoutItem()), point);
|
| + return closestBox->getLineLayoutItem().positionForPoint(point);
|
| + }
|
| +
|
| + if (lastRootBoxWithChildren) {
|
| + // We hit this case for Mac behavior when the Y coordinate is below the last box.
|
| + ASSERT(moveCaretToBoundary);
|
| + InlineBox* logicallyLastBox;
|
| + if (lastRootBoxWithChildren->getLogicalEndBoxWithNode(logicallyLastBox))
|
| + return PositionWithAffinity(positionForBox(logicallyLastBox, false));
|
| + }
|
| +
|
| + // Can't reach this. We have a root line box, but it has no kids.
|
| + // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text
|
| + // seems to hit this code path.
|
| + return createPositionWithAffinity(0);
|
| +}
|
| +
|
| #ifndef NDEBUG
|
|
|
| void LayoutBlockFlow::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const LayoutObject* obj) const
|
|
|