Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutBlock.cpp

Issue 1957633003: Move line-specific code into LayoutBlockFlow::positionForPoint(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2007 David Smith (catfish.man@gmail.com) 4 * (C) 2007 David Smith (catfish.man@gmail.com)
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
6 * Copyright (C) Research In Motion Limited 2010. All rights reserved. 6 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 13 matching lines...) Expand all
24 #include "core/layout/LayoutBlock.h" 24 #include "core/layout/LayoutBlock.h"
25 25
26 #include "core/HTMLNames.h" 26 #include "core/HTMLNames.h"
27 #include "core/dom/AXObjectCache.h" 27 #include "core/dom/AXObjectCache.h"
28 #include "core/dom/Document.h" 28 #include "core/dom/Document.h"
29 #include "core/dom/Element.h" 29 #include "core/dom/Element.h"
30 #include "core/dom/StyleEngine.h" 30 #include "core/dom/StyleEngine.h"
31 #include "core/dom/shadow/ShadowRoot.h" 31 #include "core/dom/shadow/ShadowRoot.h"
32 #include "core/editing/DragCaretController.h" 32 #include "core/editing/DragCaretController.h"
33 #include "core/editing/EditingUtilities.h" 33 #include "core/editing/EditingUtilities.h"
34 #include "core/editing/Editor.h"
35 #include "core/editing/FrameSelection.h" 34 #include "core/editing/FrameSelection.h"
36 #include "core/frame/FrameView.h" 35 #include "core/frame/FrameView.h"
37 #include "core/frame/LocalFrame.h" 36 #include "core/frame/LocalFrame.h"
38 #include "core/frame/Settings.h" 37 #include "core/frame/Settings.h"
39 #include "core/html/HTMLMarqueeElement.h" 38 #include "core/html/HTMLMarqueeElement.h"
40 #include "core/layout/HitTestLocation.h" 39 #include "core/layout/HitTestLocation.h"
41 #include "core/layout/HitTestResult.h" 40 #include "core/layout/HitTestResult.h"
42 #include "core/layout/LayoutAnalyzer.h" 41 #include "core/layout/LayoutAnalyzer.h"
43 #include "core/layout/LayoutFlexibleBox.h" 42 #include "core/layout/LayoutFlexibleBox.h"
44 #include "core/layout/LayoutFlowThread.h" 43 #include "core/layout/LayoutFlowThread.h"
(...skipping 1565 matching lines...) Expand 10 before | Expand all | Expand 10 after
1610 } 1609 }
1611 1610
1612 static inline bool isEditingBoundary(LayoutObject* ancestor, LineLayoutBox child ) 1611 static inline bool isEditingBoundary(LayoutObject* ancestor, LineLayoutBox child )
1613 { 1612 {
1614 ASSERT(!ancestor || ancestor->nonPseudoNode()); 1613 ASSERT(!ancestor || ancestor->nonPseudoNode());
1615 ASSERT(child && child.nonPseudoNode()); 1614 ASSERT(child && child.nonPseudoNode());
1616 return !ancestor || !ancestor->parent() || (ancestor->hasLayer() && ancestor ->parent()->isLayoutView()) 1615 return !ancestor || !ancestor->parent() || (ancestor->hasLayer() && ancestor ->parent()->isLayoutView())
1617 || ancestor->nonPseudoNode()->hasEditableStyle() == child.nonPseudoNode( )->hasEditableStyle(); 1616 || ancestor->nonPseudoNode()->hasEditableStyle() == child.nonPseudoNode( )->hasEditableStyle();
1618 } 1617 }
1619 1618
1620 // FIXME: This function should go on LayoutObject as an instance method. Then 1619 // FIXME: This function should go on LayoutObject.
1621 // all cases in which positionForPoint recurs could call this instead to 1620 // Then all cases in which positionForPoint recurs could call this instead to
1622 // prevent crossing editable boundaries. This would require many tests. 1621 // prevent crossing editable boundaries. This would require many tests.
1623 static PositionWithAffinity positionForPointRespectingEditingBoundaries(LayoutBl ock* parent, LineLayoutBox child, const LayoutPoint& pointInParentCoordinates) 1622 PositionWithAffinity LayoutBlock::positionForPointRespectingEditingBoundaries(Li neLayoutBox child, const LayoutPoint& pointInParentCoordinates)
1624 { 1623 {
1625 LayoutPoint childLocation = child.location(); 1624 LayoutPoint childLocation = child.location();
1626 if (child.isInFlowPositioned()) 1625 if (child.isInFlowPositioned())
1627 childLocation += child.offsetForInFlowPosition(); 1626 childLocation += child.offsetForInFlowPosition();
1628 1627
1629 // FIXME: This is wrong if the child's writing-mode is different from the pa rent's. 1628 // FIXME: This is wrong if the child's writing-mode is different from the pa rent's.
1630 LayoutPoint pointInChildCoordinates(toLayoutPoint(pointInParentCoordinates - childLocation)); 1629 LayoutPoint pointInChildCoordinates(toLayoutPoint(pointInParentCoordinates - childLocation));
1631 1630
1632 // If this is an anonymous layoutObject, we just recur normally 1631 // If this is an anonymous layoutObject, we just recur normally
1633 Node* childNode = child.nonPseudoNode(); 1632 Node* childNode = child.nonPseudoNode();
1634 if (!childNode) 1633 if (!childNode)
1635 return child.positionForPoint(pointInChildCoordinates); 1634 return child.positionForPoint(pointInChildCoordinates);
1636 1635
1637 // Otherwise, first make sure that the editability of the parent and child a gree. 1636 // Otherwise, first make sure that the editability of the parent and child a gree.
1638 // If they don't agree, then we return a visible position just before or aft er the child 1637 // If they don't agree, then we return a visible position just before or aft er the child
1639 LayoutObject* ancestor = parent; 1638 LayoutObject* ancestor = this;
1640 while (ancestor && !ancestor->nonPseudoNode()) 1639 while (ancestor && !ancestor->nonPseudoNode())
1641 ancestor = ancestor->parent(); 1640 ancestor = ancestor->parent();
1642 1641
1643 // If we can't find an ancestor to check editability on, or editability is u nchanged, we recur like normal 1642 // If we can't find an ancestor to check editability on, or editability is u nchanged, we recur like normal
1644 if (isEditingBoundary(ancestor, child)) 1643 if (isEditingBoundary(ancestor, child))
1645 return child.positionForPoint(pointInChildCoordinates); 1644 return child.positionForPoint(pointInChildCoordinates);
1646 1645
1647 // Otherwise return before or after the child, depending on if the click was to the logical left or logical right of the child 1646 // Otherwise return before or after the child, depending on if the click was to the logical left or logical right of the child
1648 LayoutUnit childMiddle = parent->logicalWidthForChildSize(child.size()) / 2; 1647 LayoutUnit childMiddle = logicalWidthForChildSize(child.size()) / 2;
1649 LayoutUnit logicalLeft = parent->isHorizontalWritingMode() ? pointInChildCoo rdinates.x() : pointInChildCoordinates.y(); 1648 LayoutUnit logicalLeft = isHorizontalWritingMode() ? pointInChildCoordinates .x() : pointInChildCoordinates.y();
1650 if (logicalLeft < childMiddle) 1649 if (logicalLeft < childMiddle)
1651 return ancestor->createPositionWithAffinity(childNode->nodeIndex()); 1650 return ancestor->createPositionWithAffinity(childNode->nodeIndex());
1652 return ancestor->createPositionWithAffinity(childNode->nodeIndex() + 1, Text Affinity::Upstream); 1651 return ancestor->createPositionWithAffinity(childNode->nodeIndex() + 1, Text Affinity::Upstream);
1653 } 1652 }
1654 1653
1655 PositionWithAffinity LayoutBlock::positionForPointWithInlineChildren(const Layou tPoint& pointInLogicalContents) 1654 PositionWithAffinity LayoutBlock::positionForPointIfOutsideAtomicInlineLevel(con st LayoutPoint& point)
1656 { 1655 {
1657 ASSERT(childrenInline()); 1656 ASSERT(isAtomicInlineLevel());
1657 // FIXME: This seems wrong when the object's writing-mode doesn't match the line's writing-mode.
1658 LayoutUnit pointLogicalLeft = isHorizontalWritingMode() ? point.x() : point. y();
1659 LayoutUnit pointLogicalTop = isHorizontalWritingMode() ? point.y() : point.x ();
1658 1660
1659 if (!firstRootBox()) 1661 if (pointLogicalLeft < 0)
1660 return createPositionWithAffinity(0); 1662 return createPositionWithAffinity(caretMinOffset());
1661 1663 if (pointLogicalLeft >= logicalWidth())
1662 bool linesAreFlipped = style()->isFlippedLinesWritingMode(); 1664 return createPositionWithAffinity(caretMaxOffset());
1663 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode(); 1665 if (pointLogicalTop < 0)
1664 1666 return createPositionWithAffinity(caretMinOffset());
1665 // look for the closest line box in the root box which is at the passed-in y coordinate 1667 if (pointLogicalTop >= logicalHeight())
1666 InlineBox* closestBox = nullptr; 1668 return createPositionWithAffinity(caretMaxOffset());
1667 RootInlineBox* firstRootBoxWithChildren = nullptr; 1669 return PositionWithAffinity();
1668 RootInlineBox* lastRootBoxWithChildren = nullptr;
1669 for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
1670 if (!root->firstLeafChild())
1671 continue;
1672 if (!firstRootBoxWithChildren)
1673 firstRootBoxWithChildren = root;
1674
1675 if (!linesAreFlipped && root->isFirstAfterPageBreak() && (pointInLogical Contents.y() < root->lineTopWithLeading()
1676 || (blocksAreFlipped && pointInLogicalContents.y() == root->lineTopW ithLeading())))
1677 break;
1678
1679 lastRootBoxWithChildren = root;
1680
1681 // check if this root line box is located at this y coordinate
1682 if (pointInLogicalContents.y() < root->selectionBottom() || (blocksAreFl ipped && pointInLogicalContents.y() == root->selectionBottom())) {
1683 if (linesAreFlipped) {
1684 RootInlineBox* nextRootBoxWithChildren = root->nextRootBox();
1685 while (nextRootBoxWithChildren && !nextRootBoxWithChildren->firs tLeafChild())
1686 nextRootBoxWithChildren = nextRootBoxWithChildren->nextRootB ox();
1687
1688 if (nextRootBoxWithChildren && nextRootBoxWithChildren->isFirstA fterPageBreak() && (pointInLogicalContents.y() > nextRootBoxWithChildren->lineTo pWithLeading()
1689 || (!blocksAreFlipped && pointInLogicalContents.y() == nextR ootBoxWithChildren->lineTopWithLeading())))
1690 continue;
1691 }
1692 closestBox = root->closestLeafChildForLogicalLeftPosition(pointInLog icalContents.x());
1693 if (closestBox)
1694 break;
1695 }
1696 }
1697
1698 bool moveCaretToBoundary = document().frame()->editor().behavior().shouldMov eCaretToHorizontalBoundaryWhenPastTopOrBottom();
1699
1700 if (!moveCaretToBoundary && !closestBox && lastRootBoxWithChildren) {
1701 // y coordinate is below last root line box, pretend we hit it
1702 closestBox = lastRootBoxWithChildren->closestLeafChildForLogicalLeftPosi tion(pointInLogicalContents.x());
1703 }
1704
1705 if (closestBox) {
1706 if (moveCaretToBoundary) {
1707 LayoutUnit firstRootBoxWithChildrenTop = std::min<LayoutUnit>(firstR ootBoxWithChildren->selectionTop(), firstRootBoxWithChildren->logicalTop());
1708 if (pointInLogicalContents.y() < firstRootBoxWithChildrenTop
1709 || (blocksAreFlipped && pointInLogicalContents.y() == firstRootB oxWithChildrenTop)) {
1710 InlineBox* box = firstRootBoxWithChildren->firstLeafChild();
1711 if (box->isLineBreak()) {
1712 if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak( ))
1713 box = newBox;
1714 }
1715 // y coordinate is above first root line box, so return the star t of the first
1716 return PositionWithAffinity(positionForBox(box, true));
1717 }
1718 }
1719
1720 // pass the box a top position that is inside it
1721 LayoutPoint point(pointInLogicalContents.x(), closestBox->root().blockDi rectionPointInLine());
1722 if (!isHorizontalWritingMode())
1723 point = point.transposedPoint();
1724 if (closestBox->getLineLayoutItem().isAtomicInlineLevel())
1725 return positionForPointRespectingEditingBoundaries(this, LineLayoutB ox(closestBox->getLineLayoutItem()), point);
1726 return closestBox->getLineLayoutItem().positionForPoint(point);
1727 }
1728
1729 if (lastRootBoxWithChildren) {
1730 // We hit this case for Mac behavior when the Y coordinate is below the last box.
1731 ASSERT(moveCaretToBoundary);
1732 InlineBox* logicallyLastBox;
1733 if (lastRootBoxWithChildren->getLogicalEndBoxWithNode(logicallyLastBox))
1734 return PositionWithAffinity(positionForBox(logicallyLastBox, false)) ;
1735 }
1736
1737 // Can't reach this. We have a root line box, but it has no kids.
1738 // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text
1739 // seems to hit this code path.
1740 return createPositionWithAffinity(0);
1741 } 1670 }
1742 1671
1743 static inline bool isChildHitTestCandidate(LayoutBox* box) 1672 static inline bool isChildHitTestCandidate(LayoutBox* box)
1744 { 1673 {
1745 return box->size().height() && box->style()->visibility() == VISIBLE && !box ->isFloatingOrOutOfFlowPositioned() && !box->isLayoutFlowThread(); 1674 return box->size().height() && box->style()->visibility() == VISIBLE && !box ->isFloatingOrOutOfFlowPositioned() && !box->isLayoutFlowThread();
1746 } 1675 }
1747 1676
1748 PositionWithAffinity LayoutBlock::positionForPoint(const LayoutPoint& point) 1677 PositionWithAffinity LayoutBlock::positionForPoint(const LayoutPoint& point)
1749 { 1678 {
1750 if (isTable()) 1679 if (isTable())
1751 return LayoutBox::positionForPoint(point); 1680 return LayoutBox::positionForPoint(point);
1752 1681
1753 if (isAtomicInlineLevel()) { 1682 if (isAtomicInlineLevel()) {
1754 // FIXME: This seems wrong when the object's writing-mode doesn't match the line's writing-mode. 1683 PositionWithAffinity position = positionForPointIfOutsideAtomicInlineLev el(point);
1755 LayoutUnit pointLogicalLeft = isHorizontalWritingMode() ? point.x() : po int.y(); 1684 if (!position.isNull())
1756 LayoutUnit pointLogicalTop = isHorizontalWritingMode() ? point.y() : poi nt.x(); 1685 return position;
1757
1758 if (pointLogicalLeft < 0)
1759 return createPositionWithAffinity(caretMinOffset());
1760 if (pointLogicalLeft >= logicalWidth())
1761 return createPositionWithAffinity(caretMaxOffset());
1762 if (pointLogicalTop < 0)
1763 return createPositionWithAffinity(caretMinOffset());
1764 if (pointLogicalTop >= logicalHeight())
1765 return createPositionWithAffinity(caretMaxOffset());
1766 } 1686 }
1767 1687
1768 LayoutPoint pointInContents = point; 1688 LayoutPoint pointInContents = point;
1769 offsetForContents(pointInContents); 1689 offsetForContents(pointInContents);
1770 LayoutPoint pointInLogicalContents(pointInContents); 1690 LayoutPoint pointInLogicalContents(pointInContents);
1771 if (!isHorizontalWritingMode()) 1691 if (!isHorizontalWritingMode())
1772 pointInLogicalContents = pointInLogicalContents.transposedPoint(); 1692 pointInLogicalContents = pointInLogicalContents.transposedPoint();
1773 1693
1774 if (childrenInline()) 1694 ASSERT(!childrenInline());
1775 return positionForPointWithInlineChildren(pointInLogicalContents);
1776 1695
1777 LayoutBox* lastCandidateBox = lastChildBox(); 1696 LayoutBox* lastCandidateBox = lastChildBox();
1778 while (lastCandidateBox && !isChildHitTestCandidate(lastCandidateBox)) 1697 while (lastCandidateBox && !isChildHitTestCandidate(lastCandidateBox))
1779 lastCandidateBox = lastCandidateBox->previousSiblingBox(); 1698 lastCandidateBox = lastCandidateBox->previousSiblingBox();
1780 1699
1781 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode(); 1700 bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
1782 if (lastCandidateBox) { 1701 if (lastCandidateBox) {
1783 if (pointInLogicalContents.y() > logicalTopForChild(*lastCandidateBox) 1702 if (pointInLogicalContents.y() > logicalTopForChild(*lastCandidateBox)
1784 || (!blocksAreFlipped && pointInLogicalContents.y() == logicalTopFor Child(*lastCandidateBox))) 1703 || (!blocksAreFlipped && pointInLogicalContents.y() == logicalTopFor Child(*lastCandidateBox)))
1785 return positionForPointRespectingEditingBoundaries(this, LineLayoutB ox(lastCandidateBox), pointInContents); 1704 return positionForPointRespectingEditingBoundaries(LineLayoutBox(las tCandidateBox), pointInContents);
1786 1705
1787 for (LayoutBox* childBox = firstChildBox(); childBox; childBox = childBo x->nextSiblingBox()) { 1706 for (LayoutBox* childBox = firstChildBox(); childBox; childBox = childBo x->nextSiblingBox()) {
1788 if (!isChildHitTestCandidate(childBox)) 1707 if (!isChildHitTestCandidate(childBox))
1789 continue; 1708 continue;
1790 LayoutUnit childLogicalBottom = logicalTopForChild(*childBox) + logi calHeightForChild(*childBox); 1709 LayoutUnit childLogicalBottom = logicalTopForChild(*childBox) + logi calHeightForChild(*childBox);
1791 // We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3). 1710 // We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3).
1792 if (isChildHitTestCandidate(childBox) && (pointInLogicalContents.y() < childLogicalBottom 1711 if (isChildHitTestCandidate(childBox) && (pointInLogicalContents.y() < childLogicalBottom
1793 || (blocksAreFlipped && pointInLogicalContents.y() == childLogic alBottom))) 1712 || (blocksAreFlipped && pointInLogicalContents.y() == childLogic alBottom)))
1794 return positionForPointRespectingEditingBoundaries(this, LineLay outBox(childBox), pointInContents); 1713 return positionForPointRespectingEditingBoundaries(LineLayoutBox (childBox), pointInContents);
1795 } 1714 }
1796 } 1715 }
1797 1716
1798 // We only get here if there are no hit test candidate children below the cl ick. 1717 // We only get here if there are no hit test candidate children below the cl ick.
1799 return LayoutBox::positionForPoint(point); 1718 return LayoutBox::positionForPoint(point);
1800 } 1719 }
1801 1720
1802 void LayoutBlock::offsetForContents(LayoutPoint& offset) const 1721 void LayoutBlock::offsetForContents(LayoutPoint& offset) const
1803 { 1722 {
1804 offset = flipForWritingMode(offset); 1723 offset = flipForWritingMode(offset);
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after
2599 for (TrackedLayoutBoxListHashSet::const_iterator it = positionedDescenda ntSet->begin(); it != end; ++it) { 2518 for (TrackedLayoutBoxListHashSet::const_iterator it = positionedDescenda ntSet->begin(); it != end; ++it) {
2600 LayoutBox* currBox = *it; 2519 LayoutBox* currBox = *it;
2601 ASSERT(!currBox->needsLayout()); 2520 ASSERT(!currBox->needsLayout());
2602 } 2521 }
2603 } 2522 }
2604 } 2523 }
2605 2524
2606 #endif 2525 #endif
2607 2526
2608 } // namespace blink 2527 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutBlock.h ('k') | third_party/WebKit/Source/core/layout/LayoutBlockFlow.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698