Changeset 18758 in webkit
- Timestamp:
- Jan 10, 2007 11:26:44 PM (17 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r18757 r18758 1 2007-01-10 David Hyatt <hyatt@apple.com> 2 3 Rework positionForCoordinates to be more efficient and to handle multi-column content. This entailed 4 adding a new field to HitTestResult called localPoint that cached the mouse coordinate in the coordinate 5 space of the renderer. 6 7 positionForCoordinates now takes local coordinates and so no longer needs to waste time recomputing 8 absolute positions over and over again. 9 10 Reviewed by darin 11 12 * bridge/mac/WebCoreAXObject.mm: 13 (-[WebCoreAXObject value]): 14 (-[WebCoreAXObject doAXTextMarkerRangeForLine:]): 15 (-[WebCoreAXObject doAXTextMarkerForPosition:]): 16 * dom/Document.cpp: 17 (WebCore::Document::prepareMouseEvent): 18 * editing/SelectionController.cpp: 19 (WebCore::SelectionController::contains): 20 * editing/visible_units.cpp: 21 (WebCore::previousLinePosition): 22 (WebCore::nextLinePosition): 23 * page/EventHandler.cpp: 24 (WebCore::EventHandler::selectClosestWordFromMouseEvent): 25 (WebCore::EventHandler::handleMousePressEventDoubleClick): 26 (WebCore::EventHandler::handleMousePressEventTripleClick): 27 (WebCore::EventHandler::handleMousePressEventSingleClick): 28 (WebCore::EventHandler::handleMouseMoveEvent): 29 (WebCore::EventHandler::handleMouseReleaseEvent): 30 (WebCore::EventHandler::sendContextMenuEvent): 31 * page/EventHandler.h: 32 * page/MouseEventWithHitTestResults.cpp: 33 (WebCore::MouseEventWithHitTestResults::MouseEventWithHitTestResults): 34 * page/MouseEventWithHitTestResults.h: 35 (WebCore::MouseEventWithHitTestResults::localPoint): 36 * page/mac/WebCoreFrameBridge.mm: 37 (-[WebCoreFrameBridge _visiblePositionForPoint:]): 38 * rendering/EllipsisBox.cpp: 39 (WebCore::EllipsisBox::nodeAtPoint): 40 * rendering/HitTestResult.h: 41 (WebCore::HitTestResult::localPoint): 42 (WebCore::HitTestResult::setLocalPoint): 43 * rendering/InlineFlowBox.cpp: 44 (WebCore::InlineFlowBox::nodeAtPoint): 45 * rendering/InlineTextBox.cpp: 46 (WebCore::InlineTextBox::nodeAtPoint): 47 * rendering/RenderBlock.cpp: 48 (WebCore::RenderBlock::nodeAtPoint): 49 (WebCore::RenderBlock::hitTestContents): 50 (WebCore::RenderBlock::positionForCoordinates): 51 * rendering/RenderBox.cpp: 52 (WebCore::RenderBox::nodeAtPoint): 53 * rendering/RenderContainer.cpp: 54 (WebCore::RenderContainer::positionForCoordinates): 55 * rendering/RenderFlow.cpp: 56 (WebCore::RenderFlow::hitTestLines): 57 * rendering/RenderInline.cpp: 58 (WebCore::RenderInline::positionForCoordinates): 59 * rendering/RenderLayer.cpp: 60 (WebCore::RenderLayer::autoscroll): 61 (WebCore::RenderLayer::hitTestLayer): 62 * rendering/RenderObject.cpp: 63 (WebCore::RenderObject::updateHitTestResult): 64 * rendering/RenderObject.h: 65 * rendering/RenderPath.cpp: 66 (WebCore::RenderPath::nodeAtPoint): 67 * rendering/RenderReplaced.cpp: 68 (WebCore::RenderReplaced::positionForCoordinates): 69 * rendering/RenderTableRow.cpp: 70 (WebCore::RenderTableRow::nodeAtPoint): 71 * rendering/RenderTableSection.cpp: 72 (WebCore::RenderTableSection::nodeAtPoint): 73 * rendering/RenderText.cpp: 74 (WebCore::RenderText::positionForCoordinates): 75 * rendering/RootInlineBox.cpp: 76 (WebCore::RootInlineBox::nodeAtPoint): 77 (WebCore::RootInlineBox::closestLeafChildForXPos): 78 * rendering/RootInlineBox.h: 79 1 80 2007-01-11 George Staikos <staikos@kde.org> 2 81 -
trunk/WebCore/bridge/mac/WebCoreAXObject.mm
r18677 r18758 580 580 581 581 // FIXME: should use startOfDocument and endOfDocument (or rangeForDocument?) here 582 VisiblePosition startVisiblePosition = m_renderer->positionForCoordinates 583 VisiblePosition endVisiblePosition = m_renderer->positionForCoordinates 582 VisiblePosition startVisiblePosition = m_renderer->positionForCoordinates(0, 0); 583 VisiblePosition endVisiblePosition = m_renderer->positionForCoordinates(LONG_MAX, LONG_MAX); 584 584 if (startVisiblePosition.isNull() || endVisiblePosition.isNull()) 585 585 return nil; … … 1222 1222 // NOTE: BUG this is wrong when lineNumber is lineCount+1, because nextLinePosition takes you to the 1223 1223 // last offset of the last line 1224 VisiblePosition visiblePos = [self topRenderer]->positionForCoordinates 1224 VisiblePosition visiblePos = [self topRenderer]->positionForCoordinates(0, 0); 1225 1225 VisiblePosition savedVisiblePos; 1226 1226 while (--lineCount != 0) { … … 1267 1267 RenderObject* renderer = [self topRenderer]; 1268 1268 Node* innerNode = NULL; 1269 NSPoint ourpoint;1270 1269 1271 1270 // locate the node containing the point 1271 IntPoint pointResult; 1272 1272 while (1) { 1273 1273 // ask the document layer to hitTest 1274 1274 NSPoint windowCoord = [[view window] convertScreenToBase: point]; 1275 ourpoint = [view convertPoint:windowCoord fromView:nil];1276 1275 IntPoint ourpoint([view convertPoint:windowCoord fromView:nil]); 1276 1277 1277 HitTestRequest request(true, true); 1278 HitTestResult result = HitTestResult(IntPoint(ourpoint));1278 HitTestResult result(ourpoint); 1279 1279 renderer->layer()->hitTest(request, result); 1280 1280 innerNode = result.innerNode(); 1281 1281 if (!innerNode || !innerNode->renderer()) 1282 1282 return nil; 1283 1284 pointResult = result.localPoint(); 1283 1285 1284 1286 // done if hit something other than a widget … … 1303 1305 1304 1306 // get position within the node 1305 VisiblePosition pos = innerNode->renderer()->positionFor Coordinates ((int)ourpoint.x, (int)ourpoint.y);1307 VisiblePosition pos = innerNode->renderer()->positionForPoint(pointResult); 1306 1308 return (id) [self textMarkerForVisiblePosition:pos]; 1307 1309 } -
trunk/WebCore/dom/Document.cpp
r18712 r18758 1664 1664 1665 1665 if (!renderer()) 1666 return MouseEventWithHitTestResults(event, 0, 0, false);1666 return MouseEventWithHitTestResults(event, 0, IntPoint(), 0, false); 1667 1667 1668 1668 HitTestResult result(documentPoint); … … 1673 1673 1674 1674 bool isOverLink = result.URLElement() && !result.URLElement()->getAttribute(hrefAttr).isNull(); 1675 return MouseEventWithHitTestResults(event, result.innerNode(), result. scrollbar(), isOverLink);1675 return MouseEventWithHitTestResults(event, result.innerNode(), result.localPoint(), result.scrollbar(), isOverLink); 1676 1676 } 1677 1677 -
trunk/WebCore/editing/SelectionController.cpp
r18338 r18758 1008 1008 return false; 1009 1009 1010 Position pos(innerNode->renderer()->positionForPoint( point).deepEquivalent());1010 Position pos(innerNode->renderer()->positionForPoint(result.localPoint()).deepEquivalent()); 1011 1011 if (pos.isNull()) 1012 1012 return false; -
trunk/WebCore/editing/visible_units.cpp
r18637 r18758 444 444 445 445 if (root) { 446 // FIXME: Can be wrong for multi-column layout. 446 447 int absx, absy; 447 448 containingBlock->absolutePositionForContent(absx, absy); 448 449 if (containingBlock->hasOverflowClip()) 449 450 containingBlock->layer()->subtractScrollOffset(absx, absy); 450 RenderObject *renderer = root->closestLeafChildForXPos(x ,absx)->object();451 RenderObject *renderer = root->closestLeafChildForXPos(x - absx)->object(); 451 452 Node* node = renderer->element(); 452 453 if (editingIgnoresContent(node)) 453 454 return Position(node->parent(), node->nodeIndex()); 454 return renderer->positionForCoordinates(x , absy +root->topOverflow());455 return renderer->positionForCoordinates(x - absx, root->topOverflow()); 455 456 } 456 457 … … 513 514 514 515 if (root) { 516 // FIXME: Can be wrong for multi-column layout. 515 517 int absx, absy; 516 518 containingBlock->absolutePositionForContent(absx, absy); 517 519 if (containingBlock->hasOverflowClip()) 518 520 containingBlock->layer()->subtractScrollOffset(absx, absy); 519 RenderObject *renderer = root->closestLeafChildForXPos(x ,absx)->object();521 RenderObject *renderer = root->closestLeafChildForXPos(x - absx)->object(); 520 522 Node* node = renderer->element(); 521 523 if (editingIgnoresContent(node)) 522 524 return Position(node->parent(), node->nodeIndex()); 523 return renderer->positionForCoordinates(x , absy +root->topOverflow());525 return renderer->positionForCoordinates(x - absx, root->topOverflow()); 524 526 } 525 527 -
trunk/WebCore/page/EventHandler.cpp
r18610 r18758 126 126 } 127 127 128 void EventHandler::selectClosestWordFromMouseEvent(const PlatformMouseEvent& mouse, Node *innerNode) 129 { 128 void EventHandler::selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& result) 129 { 130 Node* innerNode = result.targetNode(); 130 131 Selection newSelection; 131 132 132 133 if (innerNode && innerNode->renderer() && m_mouseDownMayStartSelect && innerNode->renderer()->shouldSelect()) { 133 IntPoint vPoint = m_frame->view()->windowToContents(mouse.pos()); 134 VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint)); 134 VisiblePosition pos(innerNode->renderer()->positionForPoint(result.localPoint())); 135 135 if (pos.isNotNull()) { 136 136 newSelection = Selection(pos); … … 161 161 m_beganSelectingText = true; 162 162 else 163 selectClosestWordFromMouseEvent(event .event(), event.targetNode());163 selectClosestWordFromMouseEvent(event); 164 164 165 165 return true; … … 177 177 178 178 Selection newSelection; 179 IntPoint vPoint = m_frame->view()->windowToContents(event.event().pos()); 180 VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint)); 179 VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint())); 181 180 if (pos.isNotNull()) { 182 181 newSelection = Selection(pos); … … 213 212 return false; 214 213 215 VisiblePosition visiblePos(innerNode->renderer()->positionForPoint( vPoint));214 VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(event.localPoint())); 216 215 if (visiblePos.isNull()) 217 216 visiblePos = VisiblePosition(innerNode, innerNode->caretMinOffset(), DOWNSTREAM); … … 324 323 325 324 // handle making selection 326 IntPoint vPoint = m_frame->view()->windowToContents(event.event().pos()); 327 VisiblePosition pos(innerNode->renderer()->positionForPoint(vPoint)); 325 VisiblePosition pos(innerNode->renderer()->positionForPoint(event.localPoint())); 328 326 329 327 updateSelectionForMouseDragOverPosition(pos); … … 379 377 Node *node = event.targetNode(); 380 378 if (node && node->isContentEditable() && node->renderer()) { 381 IntPoint vPoint = m_frame->view()->windowToContents(event.event().pos()); 382 VisiblePosition pos = node->renderer()->positionForPoint(vPoint); 379 VisiblePosition pos = node->renderer()->positionForPoint(event.localPoint()); 383 380 newSelection = Selection(pos); 384 381 } … … 1129 1126 || (mev.targetNode() && mev.targetNode()->isContentEditable()))) { 1130 1127 m_mouseDownMayStartSelect = true; // context menu events are always allowed to perform a selection 1131 selectClosestWordFromMouseEvent( event, mev.targetNode());1128 selectClosestWordFromMouseEvent(mev); 1132 1129 } 1133 1130 -
trunk/WebCore/page/EventHandler.h
r18677 r18758 148 148 149 149 private: 150 void selectClosestWordFromMouseEvent(const PlatformMouseEvent&, Node* innerNode);150 void selectClosestWordFromMouseEvent(const MouseEventWithHitTestResults& event); 151 151 152 152 bool handleMouseDoubleClickEvent(const PlatformMouseEvent&); -
trunk/WebCore/page/MouseEventWithHitTestResults.cpp
r16815 r18758 36 36 37 37 MouseEventWithHitTestResults::MouseEventWithHitTestResults(const PlatformMouseEvent& event, 38 PassRefPtr<Node> node, PlatformScrollbar* scrollbar, bool isOverLink)38 PassRefPtr<Node> node, const IntPoint& localPoint, PlatformScrollbar* scrollbar, bool isOverLink) 39 39 : m_event(event) 40 40 , m_targetNode(node) 41 41 , m_targetElement(targetElement(m_targetNode.get())) 42 , m_localPoint(localPoint) 42 43 , m_scrollbar(scrollbar) 43 44 , m_isOverLink(isOverLink) -
trunk/WebCore/page/MouseEventWithHitTestResults.h
r16815 r18758 29 29 class PlatformScrollbar; 30 30 31 // FIXME: Why doesn't this class just cache a HitTestResult instead of copying all of HitTestResult's fields over? 31 32 class MouseEventWithHitTestResults { 32 33 public: 33 MouseEventWithHitTestResults(const PlatformMouseEvent&, PassRefPtr<Node>, PlatformScrollbar*, bool isOverLink);34 MouseEventWithHitTestResults(const PlatformMouseEvent&, PassRefPtr<Node>, const IntPoint& localPoint, PlatformScrollbar*, bool isOverLink); 34 35 35 36 const PlatformMouseEvent& event() const { return m_event; } 36 37 Node* targetNode() const; 38 const IntPoint& localPoint() const { return m_localPoint; } 37 39 PlatformScrollbar* scrollbar() const { return m_scrollbar; } 38 40 bool isOverLink() const { return m_isOverLink; } … … 42 44 RefPtr<Node> m_targetNode; 43 45 RefPtr<Element> m_targetElement; 46 IntPoint m_localPoint; 44 47 PlatformScrollbar* m_scrollbar; 45 48 bool m_isOverLink; -
trunk/WebCore/page/mac/WebCoreFrameBridge.mm
r18752 r18758 1206 1206 { 1207 1207 IntPoint outerPoint(point); 1208 Node* node = m_frame->eventHandler()->hitTestResultAtPoint(outerPoint, true).innerNode(); 1208 HitTestResult result = m_frame->eventHandler()->hitTestResultAtPoint(outerPoint, true); 1209 Node* node = result.innerNode(); 1209 1210 if (!node) 1210 1211 return VisiblePosition(); … … 1212 1213 if (!renderer) 1213 1214 return VisiblePosition(); 1214 FrameView* outerView = m_frame->view(); 1215 FrameView* innerView = node->document()->view(); 1216 IntPoint innerPoint = innerView->windowToContents(outerView->contentsToWindow(outerPoint)); 1217 VisiblePosition visiblePos = renderer->positionForCoordinates(innerPoint.x(), innerPoint.y()); 1215 VisiblePosition visiblePos = renderer->positionForCoordinates(result.localPoint().x(), result.localPoint().y()); 1218 1216 if (visiblePos.isNull()) 1219 1217 visiblePos = VisiblePosition(Position(node, 0)); -
trunk/WebCore/rendering/EllipsisBox.cpp
r18290 r18758 72 72 int mty = ty + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline()); 73 73 if (m_markupBox->nodeAtPoint(request, result, x, y, mtx, mty)) { 74 object()-> setInnerNode(result);74 object()->updateHitTestResult(result, IntPoint(x - mtx, y - mty)); 75 75 return true; 76 76 } … … 78 78 79 79 if (object()->style()->visibility() == VISIBLE && IntRect(tx, ty, m_width, m_height).contains(x, y)) { 80 object()-> setInnerNode(result);80 object()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); 81 81 return true; 82 82 } -
trunk/WebCore/rendering/HitTestResult.h
r17669 r18758 47 47 Node* innerNonSharedNode() const { return m_innerNonSharedNode.get(); } 48 48 IntPoint point() const { return m_point; } 49 IntPoint localPoint() const { return m_localPoint; } 49 50 Element* URLElement() const { return m_innerURLElement.get(); } 50 51 PlatformScrollbar* scrollbar() const { return m_scrollbar.get(); } … … 53 54 void setInnerNonSharedNode(Node*); 54 55 void setPoint(const IntPoint& p) { m_point = p; } 56 void setLocalPoint(const IntPoint& p) { m_localPoint = p; } 55 57 void setURLElement(Element*); 56 58 void setScrollbar(PlatformScrollbar*); … … 74 76 RefPtr<Node> m_innerNonSharedNode; 75 77 IntPoint m_point; 78 IntPoint m_localPoint; // A point in the local coordinate space of m_innerNonSharedNode's renderer. Allows us to efficiently 79 // determine where inside the renderer we hit on subsequent operations. 76 80 RefPtr<Element> m_innerURLElement; 77 81 RefPtr<PlatformScrollbar> m_scrollbar; -
trunk/WebCore/rendering/InlineFlowBox.cpp
r18655 r18758 535 535 for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) { 536 536 if (!curr->object()->layer() && curr->nodeAtPoint(request, result, x, y, tx, ty)) { 537 object()-> setInnerNode(result);537 object()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); 538 538 return true; 539 539 } … … 543 543 IntRect rect(tx + m_x, ty + m_y, m_width, m_height); 544 544 if (object()->style()->visibility() == VISIBLE && rect.contains(x, y)) { 545 object()-> setInnerNode(result);545 object()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); // Don't add in m_x or m_y here, we want coords in the containing block's space. 546 546 return true; 547 547 } -
trunk/WebCore/rendering/InlineTextBox.cpp
r18398 r18758 249 249 IntRect rect(tx + m_x, ty + m_y, m_width, m_height); 250 250 if (m_truncation != cFullTruncation && object()->style()->visibility() == VISIBLE && rect.contains(x, y)) { 251 object()-> setInnerNode(result);251 object()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); 252 252 return true; 253 253 } -
trunk/WebCore/rendering/RenderBlock.cpp
r18734 r18758 2628 2628 if (isPointInScrollbar(result, _x, _y, tx, ty)) { 2629 2629 if (hitTestAction == HitTestBlockBackground) { 2630 setInnerNode(result);2630 updateHitTestResult(result, IntPoint(_x - tx, _y - ty)); 2631 2631 return true; 2632 2632 } … … 2657 2657 FloatingObject* o; 2658 2658 DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); 2659 for (it.toLast(); (o = it.current()); --it) 2660 if (!o->noPaint && !o->node->layer() && o->node->hitTest(request, result, _x, _y, 2661 scrolledX + o->left + o->node->marginLeft() - o->node->xPos(), 2662 scrolledY + o->startY + o->node->marginTop() - o->node->yPos())) { 2663 setInnerNode(result); 2664 return true; 2665 } 2659 for (it.toLast(); (o = it.current()); --it) { 2660 if (!o->noPaint && !o->node->layer()) { 2661 int xoffset = scrolledX + o->left + o->node->marginLeft() - o->node->xPos(); 2662 int yoffset = scrolledY + o->startY + o->node->marginTop() - o->node->yPos(); 2663 if (o->node->hitTest(request, result, _x, _y, xoffset, yoffset)) { 2664 updateHitTestResult(result, IntPoint(_x - xoffset, _y - yoffset)); 2665 return true; 2666 } 2667 } 2668 } 2666 2669 } 2667 2670 … … 2671 2674 IntRect boundsRect(tx, ty - topExtra, m_width, m_height + topExtra + borderBottomExtra()); 2672 2675 if (style()->visibility() == VISIBLE && boundsRect.contains(_x, _y)) { 2673 setInnerNode(result);2676 updateHitTestResult(result, IntPoint(_x - tx, _y - ty + topExtra)); 2674 2677 return true; 2675 2678 } … … 2717 2720 // We have to hit-test our line boxes. 2718 2721 if (hitTestLines(request, result, x, y, tx, ty, hitTestAction)) { 2719 setInnerNode(result);2722 updateHitTestResult(result, IntPoint(x - tx, y - ty)); 2720 2723 return true; 2721 2724 } … … 2729 2732 // table-specific hit-test method (which we should do for performance reasons anyway), then we can remove this check. 2730 2733 if (!child->layer() && !child->isFloating() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, childHitTest)) { 2731 setInnerNode(result);2734 updateHitTestResult(result, IntPoint(x - tx, y - ty)); 2732 2735 return true; 2733 2736 } … … 2771 2774 return RenderFlow::positionForCoordinates(x, y); 2772 2775 2773 int absx, absy; 2774 absolutePositionForContent(absx, absy); 2775 2776 int top = absy + borderTop() + paddingTop(); 2777 int bottom = top + contentHeight(); 2778 2779 int left = absx + borderLeft() + paddingLeft(); 2776 int top = borderTop() + paddingTop(); 2777 int bottom = top + contentHeight() + borderTopExtra() + borderBottomExtra(); 2778 2779 int left = borderLeft() + paddingLeft(); 2780 2780 int right = left + contentWidth(); 2781 2781 2782 2782 Node* n = element(); 2783 2783 2784 int contentsX = x; 2785 int contentsY = y - borderTopExtra(); 2786 if (hasOverflowClip()) 2787 m_layer->scrollOffset(contentsX, contentsY); 2788 if (hasColumns()) { 2789 IntPoint contentsPoint(contentsX, contentsY); 2790 adjustPointToColumnContents(contentsPoint); 2791 contentsX = contentsPoint.x(); 2792 contentsY = contentsPoint.y(); 2793 } 2794 2784 2795 if (isReplaced()) { 2785 if (y < absy || y < absy + height() && x < absx)2796 if (y < 0 || y < height() && x < 0) 2786 2797 return VisiblePosition(n, caretMinOffset(), DOWNSTREAM); 2787 if (y >= absy + height() || y >= absy && x >= absx +width())2798 if (y >= height() || y >= 0 && x >= width()) 2788 2799 return VisiblePosition(n, caretMaxOffset(), DOWNSTREAM); 2789 2800 } … … 2797 2808 if (y < top || (isEditableRoot && (y < bottom && x < left))) { 2798 2809 if (!isEditableRoot) 2799 if (RenderObject* c = firstChild()) { 2800 VisiblePosition p = c->positionForCoordinates( x, y);2810 if (RenderObject* c = firstChild()) { // FIXME: This code doesn't make any sense. This child could be an inline or a positioned element or a float or a compact, etc. 2811 VisiblePosition p = c->positionForCoordinates(contentsX - c->xPos(), contentsY - c->yPos()); 2801 2812 if (p.isNotNull()) 2802 2813 return p; … … 2813 2824 if (y >= bottom || (isEditableRoot && (y >= top && x >= right))) { 2814 2825 if (!isEditableRoot) 2815 if (RenderObject* c = lastChild()) { 2816 VisiblePosition p = c->positionForCoordinates( x, y);2826 if (RenderObject* c = lastChild()) { // FIXME: This code doesn't make any sense. This child could be an inline or a positioned element or a float or a compact, ect. 2827 VisiblePosition p = c->positionForCoordinates(contentsX - c->xPos(), contentsY - c->yPos()); 2817 2828 if (p.isNotNull()) 2818 2829 return p; … … 2831 2842 if (!firstRootBox()) 2832 2843 return VisiblePosition(n, 0, DOWNSTREAM); 2833 2834 int contentsX = absx; 2835 int contentsY = absy; 2836 if (hasOverflowClip()) 2837 layer()->subtractScrollOffset(contentsX, contentsY); 2838 2839 if (y < contentsY + firstRootBox()->topOverflow() - verticalLineClickFudgeFactor) 2844 2845 if (contentsY < firstRootBox()->topOverflow() - verticalLineClickFudgeFactor) 2840 2846 // y coordinate is above first root line box 2841 2847 return VisiblePosition(positionForBox(firstRootBox()->firstLeafChild(), true), DOWNSTREAM); … … 2846 2852 if (root->nextRootBox()) 2847 2853 // FIXME: make the break point halfway between the bottom of the previous root box and the top of the next root box 2848 bottom = contentsY +root->nextRootBox()->topOverflow();2854 bottom = root->nextRootBox()->topOverflow(); 2849 2855 else 2850 bottom = contentsY +root->bottomOverflow() + verticalLineClickFudgeFactor;2856 bottom = root->bottomOverflow() + verticalLineClickFudgeFactor; 2851 2857 // check if this root line box is located at this y coordinate 2852 if ( y< bottom && root->firstChild()) {2853 InlineBox* closestBox = root->closestLeafChildForXPos(x , contentsX);2858 if (contentsY < bottom && root->firstChild()) { 2859 InlineBox* closestBox = root->closestLeafChildForXPos(x); 2854 2860 if (closestBox) 2855 2861 // pass the box a y position that is inside it 2856 return closestBox->object()->positionForCoordinates( x, contentsY +closestBox->m_y);2862 return closestBox->object()->positionForCoordinates(contentsX, closestBox->m_y); 2857 2863 } 2858 2864 } … … 2869 2875 if (renderer->height() == 0 || renderer->style()->visibility() != VISIBLE || renderer->isFloatingOrPositioned()) 2870 2876 continue; 2871 renderer->absolutePositionForContent(absx, top);2872 2877 RenderObject* next = renderer->nextSibling(); 2873 2878 while (next && next->isFloatingOrPositioned()) 2874 2879 next = next->nextSibling(); 2875 2880 if (next) 2876 next->absolutePositionForContent(absx, bottom);2881 bottom = next->yPos(); 2877 2882 else 2878 bottom = top + contentHeight();2879 if ( y >= top && y< bottom)2880 return renderer->positionForCoordinates( x, y);2883 bottom = top + scrollHeight(); 2884 if (contentsY >= renderer->yPos() && contentsY < bottom) 2885 return renderer->positionForCoordinates(contentsX - renderer->xPos(), contentsY - renderer->yPos()); 2881 2886 } 2882 2887 … … 3016 3021 3017 3022 ASSERT(m_columnRects && m_columnCount == m_columnRects->size()); 3023 } 3024 3025 void RenderBlock::adjustPointToColumnContents(IntPoint& point) const 3026 { 3027 // Just bail if we have no columns. 3028 if (!hasColumns() || !m_columnRects) 3029 return; 3030 3031 // Begin with a result rect that is empty. 3032 IntRect result; 3033 3034 // Determine which columns we intersect. 3035 int colGap = columnGap(); 3036 int leftGap = colGap / 2; 3037 IntPoint columnPoint(m_columnRects->at(0).location()); 3038 for (unsigned i = 0; i < m_columnRects->size(); i++) { 3039 // Add in half the column gap to the left and right of the rect. 3040 IntRect colRect = m_columnRects->at(i); 3041 IntRect gapAndColumnRect(colRect.x() - leftGap, colRect.y(), colRect.width() + colGap, colRect.height()); 3042 3043 if (gapAndColumnRect.contains(point)) 3044 // We're inside the column. Translate the x and y into our column coordinate space. 3045 point -= columnPoint - colRect.location(); 3046 3047 // Move to the next position. 3048 columnPoint.setY(columnPoint.y() + colRect.height()); 3049 } 3018 3050 } 3019 3051 -
trunk/WebCore/rendering/RenderBlock.h
r18734 r18758 283 283 virtual bool hasColumns() const { return m_columnCount > 1; } 284 284 void adjustRectForColumns(IntRect&) const; 285 private: 286 void adjustPointToColumnContents(IntPoint&) const; 285 287 286 288 protected: -
trunk/WebCore/rendering/RenderBox.cpp
r18734 r18758 273 273 // then we can remove this check. 274 274 if (!child->layer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) { 275 setInnerNode(result);275 updateHitTestResult(result, IntPoint(x - tx, y - ty)); 276 276 return true; 277 277 } … … 281 281 // foreground phase (which is true for replaced elements like images). 282 282 if (action == HitTestForeground && IntRect(tx, ty, m_width, m_height).contains(x, y)) { 283 setInnerNode(result);283 updateHitTestResult(result, IntPoint(x - tx, y - ty)); 284 284 return true; 285 285 } -
trunk/WebCore/rendering/RenderContainer.cpp
r18724 r18758 540 540 541 541 if (isTable() && element()) { 542 int absx, absy; 543 absolutePositionForContent(absx, absy); 544 545 int left = absx; 546 int right = left + contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft(); 547 int top = absy; 548 int bottom = top + contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom(); 549 550 if (x < left || x > right || y < top || y > bottom) { 551 if (x <= (left + right) / 2) 542 int right = contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft(); 543 int bottom = contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom(); 544 545 if (x < 0 || x > right || y < 0 || y > bottom) { 546 if (x <= right / 2) 552 547 return VisiblePosition(Position(element(), 0)); 553 548 else … … 559 554 int minDist = INT_MAX; 560 555 RenderObject* closestRenderer = 0; 556 int newX = x; 557 int newY = y; 558 if (isTableRow()) { 559 newX += xPos(); 560 newY += yPos(); 561 } 561 562 for (RenderObject* renderer = m_firstChild; renderer; renderer = renderer->nextSibling()) { 562 563 if (!renderer->firstChild() && !renderer->isInline() && !renderer->isBlockFlow() 563 564 || renderer->style()->visibility() != VISIBLE) 564 565 continue; 565 566 int absx, absy; 567 renderer->absolutePositionForContent(absx, absy); 568 569 int top = absy + borderTop() + paddingTop(); 566 567 int top = borderTop() + paddingTop() + isTableRow() ? 0 : renderer->xPos(); 570 568 int bottom = top + renderer->contentHeight(); 571 int left = absx + borderLeft() + paddingLeft();569 int left = borderLeft() + paddingLeft() + isTableRow() ? 0 : renderer->yPos(); 572 570 int right = left + renderer->contentWidth(); 573 571 574 if (x <= right && x >= left && y <= top && y >= bottom) 575 return renderer->positionForCoordinates(x, y); 576 572 if (x <= right && x >= left && y <= top && y >= bottom) { 573 if (renderer->isTableRow()) 574 return renderer->positionForCoordinates(x + newX - renderer->xPos(), y + newY - renderer->yPos()); 575 return renderer->positionForCoordinates(x - renderer->xPos(), y - renderer->yPos()); 576 } 577 577 578 // Find the distance from (x, y) to the box. Split the space around the box into 8 pieces 578 579 // and use a different compare depending on which piece (x, y) is in. … … 610 611 611 612 if (closestRenderer) 612 return closestRenderer->positionForCoordinates( x, y);613 return closestRenderer->positionForCoordinates(newX - closestRenderer->xPos(), newY - closestRenderer->yPos()); 613 614 614 615 return VisiblePosition(element(), 0, DOWNSTREAM); -
trunk/WebCore/rendering/RenderFlow.cpp
r18734 r18758 434 434 bool inside = curr->nodeAtPoint(request, result, x, y, tx, ty); 435 435 if (inside) { 436 setInnerNode(result);436 updateHitTestResult(result, IntPoint(x - tx, y - ty)); 437 437 return true; 438 438 } -
trunk/WebCore/rendering/RenderInline.cpp
r18559 r18758 355 355 VisiblePosition RenderInline::positionForCoordinates(int x, int y) 356 356 { 357 // Translate the coords from the pre-anonymous block to the post-anonymous block. 358 RenderBlock* cb = containingBlock(); 359 int parentBlockX = cb->xPos() + x; 360 int parentBlockY = cb->yPos() + y; 357 361 for (RenderObject* c = continuation(); c; c = c->continuation()) { 362 RenderObject* contBlock = c; 363 if (c->isInline()) 364 contBlock = c->containingBlock(); 358 365 if (c->isInline() || c->firstChild()) 359 return c->positionForCoordinates( x, y);366 return c->positionForCoordinates(parentBlockX - contBlock->xPos(), parentBlockY - contBlock->yPos()); 360 367 } 361 368 -
trunk/WebCore/rendering/RenderLayer.cpp
r18752 r18758 872 872 HitTestResult result(currentPos); 873 873 if (hitTest(request, result)) { 874 VisiblePosition pos(result.innerNode()->renderer()->positionForPoint( currentPos));874 VisiblePosition pos(result.innerNode()->renderer()->positionForPoint(result.localPoint())); 875 875 currentFrame->eventHandler()->updateSelectionForMouseDragOverPosition(pos); 876 876 } … … 1590 1590 // exited the WebView, and so hit testing over a scrollbar hits the content document. 1591 1591 if ((request.active || request.mouseUp) && renderer()->isRenderView()) { 1592 renderer()-> setInnerNode(result);1592 renderer()->updateHitTestResult(result, result.point()); 1593 1593 return this; 1594 1594 } -
trunk/WebCore/rendering/RenderObject.cpp
r18752 r18758 2610 2610 } 2611 2611 2612 void RenderObject:: setInnerNode(HitTestResult& result)2612 void RenderObject::updateHitTestResult(HitTestResult& result, const IntPoint& point) 2613 2613 { 2614 2614 if (result.innerNode()) … … 2616 2616 2617 2617 Node* node = element(); 2618 IntPoint localPoint(point); 2618 2619 if (isRenderView()) 2619 2620 node = document()->documentElement(); … … 2625 2626 2626 2627 if (node) { 2628 if (node->renderer()->continuation() && node->renderer() != this) { 2629 // We're in the continuation of a split inline. Adjust our local point to be in the coordinate space 2630 // of the principal renderer's containing block. This will end up being the innerNonSharedNode. 2631 RenderObject* firstBlock = node->renderer()->containingBlock(); 2632 2633 // Get our containing block. 2634 RenderObject* block = this; 2635 if (isInline()) 2636 block = containingBlock(); 2637 2638 localPoint.move(block->xPos() - firstBlock->xPos(), block->yPos() - firstBlock->yPos()); 2639 } 2640 2627 2641 result.setInnerNode(node); 2628 2642 if (!result.innerNonSharedNode()) 2629 2643 result.setInnerNonSharedNode(node); 2644 result.setLocalPoint(localPoint); 2630 2645 } 2631 2646 } -
trunk/WebCore/rendering/RenderObject.h
r18727 r18758 527 527 bool hitTest(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestFilter = HitTestAll); 528 528 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction); 529 void setInnerNode(HitTestResult&);529 void updateHitTestResult(HitTestResult&, const IntPoint&); 530 530 531 531 virtual VisiblePosition positionForCoordinates(int x, int y); -
trunk/WebCore/rendering/RenderPath.cpp
r18737 r18758 228 228 if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke) && strokeContains(hitPoint, hitRules.requireStroke)) 229 229 || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill) && fillContains(hitPoint, hitRules.requireFill))) { 230 setInnerNode(result);230 updateHitTestResult(result, IntPoint(_x, _y)); 231 231 return true; 232 232 } -
trunk/WebCore/rendering/RenderReplaced.cpp
r18637 r18758 119 119 } 120 120 121 VisiblePosition RenderReplaced::positionForCoordinates(int _x, int _y)122 { 123 InlineBox *box = inlineBoxWrapper();121 VisiblePosition RenderReplaced::positionForCoordinates(int x, int y) 122 { 123 InlineBox* box = inlineBoxWrapper(); 124 124 if (!box) 125 125 return VisiblePosition(element(), 0, DOWNSTREAM); 126 126 127 RootInlineBox *root = box->root(); 128 129 int absx, absy; 130 containingBlock()->absolutePosition(absx, absy); 131 132 int top = absy + root->topOverflow(); 133 int bottom = root->nextRootBox() ? absy + root->nextRootBox()->topOverflow() : absy + root->bottomOverflow(); 134 135 if (_y < top) 127 // FIXME: This code is buggy if the replaced element is relative positioned. 128 129 RootInlineBox* root = box->root(); 130 131 int top = root->topOverflow(); 132 int bottom = root->nextRootBox() ? root->nextRootBox()->topOverflow() : root->bottomOverflow(); 133 134 if (y + yPos() < top) 136 135 return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM); // coordinates are above 137 136 138 if ( _y>= bottom)137 if (y + yPos() >= bottom) 139 138 return VisiblePosition(element(), caretMaxOffset(), DOWNSTREAM); // coordinates are below 140 139 141 140 if (element()) { 142 if ( _x <= absx + xPos() + (width() / 2))141 if (x <= width() / 2) 143 142 return VisiblePosition(element(), 0, DOWNSTREAM); 144 145 143 return VisiblePosition(element(), 1, DOWNSTREAM); 146 144 } 147 145 148 return RenderBox::positionForCoordinates( _x, _y);146 return RenderBox::positionForCoordinates(x, y); 149 147 } 150 148 -
trunk/WebCore/rendering/RenderTableRow.cpp
r18608 r18758 148 148 // then we can remove this check. 149 149 if (!child->layer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) { 150 setInnerNode(result);150 updateHitTestResult(result, IntPoint(x - tx, y - ty)); 151 151 return true; 152 152 } -
trunk/WebCore/rendering/RenderTableSection.cpp
r18634 r18758 1003 1003 // then we can remove this check. 1004 1004 if (!child->layer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) { 1005 setInnerNode(result);1005 updateHitTestResult(result, IntPoint(x - tx, y - ty)); 1006 1006 return true; 1007 1007 } -
trunk/WebCore/rendering/RenderText.cpp
r18735 r18758 209 209 return VisiblePosition(element(), 0, DOWNSTREAM); 210 210 211 int absx, absy;212 RenderBlock* cb = containingBlock();213 cb->absolutePositionForContent(absx, absy);214 if (cb->hasOverflowClip())215 cb->layer()->subtractScrollOffset(absx, absy);216 217 211 // Get the offset for the position, since this will take rtl text into account. 218 212 int offset; 219 213 220 214 // FIXME: We should be able to roll these special cases into the general cases in the loop below. 221 if (firstTextBox() && y < absy + firstTextBox()->root()->bottomOverflow() && x < absx +firstTextBox()->m_x) {215 if (firstTextBox() && y < firstTextBox()->root()->bottomOverflow() && x < firstTextBox()->m_x) { 222 216 // at the y coordinate of the first line or above 223 217 // and the x coordinate is to the left of the first text box left edge 224 offset = firstTextBox()->offsetForPosition(x - absx);218 offset = firstTextBox()->offsetForPosition(x); 225 219 return VisiblePosition(element(), offset + firstTextBox()->m_start, DOWNSTREAM); 226 220 } 227 if (lastTextBox() && y >= absy + lastTextBox()->root()->topOverflow() && x >= absx +lastTextBox()->m_x + lastTextBox()->m_width) {221 if (lastTextBox() && y >= lastTextBox()->root()->topOverflow() && x >= lastTextBox()->m_x + lastTextBox()->m_width) { 228 222 // at the y coordinate of the last line or below 229 223 // and the x coordinate is to the right of the last text box right edge 230 offset = lastTextBox()->offsetForPosition(x - absx);224 offset = lastTextBox()->offsetForPosition(x); 231 225 return VisiblePosition(element(), offset + lastTextBox()->m_start, DOWNSTREAM); 232 226 } … … 234 228 InlineTextBox* lastBoxAbove = 0; 235 229 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { 236 if (y >= absy +box->root()->topOverflow()) {237 if (y < absy +box->root()->bottomOverflow()) {238 offset = box->offsetForPosition(x - absx);239 240 if (x == absx +box->m_x)230 if (y >= box->root()->topOverflow()) { 231 if (y < box->root()->bottomOverflow()) { 232 offset = box->offsetForPosition(x); 233 234 if (x == box->m_x) 241 235 // the x coordinate is equal to the left edge of this box 242 236 // the affinity must be downstream so the position doesn't jump back to the previous line 243 237 return VisiblePosition(element(), offset + box->m_start, DOWNSTREAM); 244 238 245 if (x < absx +box->m_x + box->m_width)239 if (x < box->m_x + box->m_width) 246 240 // and the x coordinate is to the left of the right edge of this box 247 241 // check to see if position goes in this box 248 242 return VisiblePosition(element(), offset + box->m_start, offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); 249 243 250 if (!box->prevOnLine() && x < absx +box->m_x)244 if (!box->prevOnLine() && x < box->m_x) 251 245 // box is first on line 252 246 // and the x coordinate is to the left of the first text box left edge -
trunk/WebCore/rendering/RootInlineBox.cpp
r18263 r18758 147 147 if (m_ellipsisBox && object()->style()->visibility() == VISIBLE) { 148 148 if (m_ellipsisBox->nodeAtPoint(request, result, x, y, tx, ty)) { 149 object()-> setInnerNode(result);149 object()->updateHitTestResult(result, IntPoint(x - tx, y - ty)); 150 150 return true; 151 151 } … … 287 287 } 288 288 289 InlineBox* RootInlineBox::closestLeafChildForXPos(int x , int tx)289 InlineBox* RootInlineBox::closestLeafChildForXPos(int x) 290 290 { 291 291 InlineBox* firstLeaf = firstLeafChildAfterBox(); … … 295 295 296 296 // Avoid returning a list marker when possible. 297 if (x <= tx +firstLeaf->m_x && !firstLeaf->object()->isListMarker())297 if (x <= firstLeaf->m_x && !firstLeaf->object()->isListMarker()) 298 298 // The x coordinate is less or equal to left edge of the firstLeaf. 299 299 // Return it. 300 300 return firstLeaf; 301 301 302 if (x >= tx +lastLeaf->m_x + lastLeaf->m_width && !lastLeaf->object()->isListMarker())302 if (x >= lastLeaf->m_x + lastLeaf->m_width && !lastLeaf->object()->isListMarker()) 303 303 // The x coordinate is greater or equal to right edge of the lastLeaf. 304 304 // Return it. … … 307 307 for (InlineBox* leaf = firstLeaf; leaf && leaf != lastLeaf; leaf = leaf->nextLeafChild()) { 308 308 if (!leaf->object()->isListMarker()) { 309 int leafX = tx +leaf->m_x;309 int leafX = leaf->m_x; 310 310 if (x < leafX + leaf->m_width) 311 311 // The x coordinate is less than the right edge of the box. -
trunk/WebCore/rendering/RootInlineBox.h
r18263 r18758 122 122 int selectionHeight() { return max(0, selectionBottom() - selectionTop()); } 123 123 124 InlineBox* closestLeafChildForXPos(int x , int tx);124 InlineBox* closestLeafChildForXPos(int x); 125 125 126 126 protected:
Note: See TracChangeset
for help on using the changeset viewer.