Exemple #1
0
bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const HitTestPoint& pointInContainer, const FloatRect& rect)
{
    // If it is not a rect-based hit test, this method has to be no-op.
    // Return false, so the hit test stops.
    if (!isRectBasedTest())
        return false;

    // If node is null, return true so the hit test can continue.
    if (!node)
        return true;

    if (m_shadowContentFilterPolicy == DoNotAllowShadowContent)
        node = node->shadowAncestorNode();

    mutableRectBasedTestResult().add(node);

    bool regionFilled = rect.contains(rectForPoint(pointInContainer.point()));
    // FIXME: This code (incorrectly) attempts to correct for culled inline nodes. See https://bugs.webkit.org/show_bug.cgi?id=85849.
    if (node->renderer()->isInline() && !regionFilled) {
        for (RenderObject* curr = node->renderer()->parent(); curr; curr = curr->parent()) {
            if (!curr->isRenderInline())
                break;

            // We need to make sure the nodes for culled inlines get included.
            RenderInline* currInline = toRenderInline(curr);
            if (currInline->alwaysCreateLineBoxes())
                break;

            if (currInline->visibleToHitTesting() && currInline->node())
                mutableRectBasedTestResult().add(currInline->node()->shadowAncestorNode());
        }
    }
    return !regionFilled;
}
Exemple #2
0
bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) const
{
    if (hitTestAction != HitTestForeground)
        return false;

    ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could hit test like this is if it has a layer.

    // If we have no lines then we have no work to do.
    if (!firstLineBox())
        return false;

    LayoutPoint point = pointInContainer.point();
    LayoutRect rect = firstLineBox()->isHorizontal() ?
        IntRect(point.x(), point.y() - pointInContainer.topPadding(), 1, pointInContainer.topPadding() + pointInContainer.bottomPadding() + 1) :
        IntRect(point.x() - pointInContainer.leftPadding(), point.y(), pointInContainer.rightPadding() + pointInContainer.leftPadding() + 1, 1);

    if (!anyLineIntersectsRect(renderer, rect, accumulatedOffset))
        return false;

    // See if our root lines contain the point.  If so, then we hit test
    // them further.  Note that boxes can easily overlap, so we can't make any assumptions
    // based off positions of our first line box or our last line box.
    for (InlineFlowBox* curr = lastLineBox(); curr; curr = curr->prevLineBox()) {
        RootInlineBox* root = curr->root();
        if (rangeIntersectsRect(renderer, curr->logicalTopVisualOverflow(root->lineTop()), curr->logicalBottomVisualOverflow(root->lineBottom()), rect, accumulatedOffset)) {
            bool inside = curr->nodeAtPoint(request, result, pointInContainer, accumulatedOffset, root->lineTop(), root->lineBottom());
            if (inside) {
                renderer->updateHitTestResult(result, pointInContainer.point() - toLayoutSize(accumulatedOffset));
                return true;
            }
        }
    }

    return false;
}
Exemple #3
0
// Hit Testing
bool RenderRegion::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
    if (!isValid())
        return false;

    LayoutPoint adjustedLocation = accumulatedOffset + location();

    // Check our bounds next. For this purpose always assume that we can only be hit in the
    // foreground phase (which is true for replaced elements like images).
    LayoutRect boundsRect = borderBoxRectInRegion(pointInContainer.region());
    boundsRect.moveBy(adjustedLocation);
    if (visibleToHitTesting() && action == HitTestForeground && pointInContainer.intersects(boundsRect)) {
        // Check the contents of the RenderFlowThread.
        if (m_flowThread && m_flowThread->hitTestRegion(this, request, result, pointInContainer, LayoutPoint(adjustedLocation.x() + borderLeft() + paddingLeft(), adjustedLocation.y() + borderTop() + paddingTop())))
            return true;
        updateHitTestResult(result, pointInContainer.point() - toLayoutSize(adjustedLocation));
        if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect))
            return true;
    }

    return false;
}
Exemple #4
0
// Hit Testing
bool RenderTableRow::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
{
    // Table rows cannot ever be hit tested.  Effectively they do not exist.
    // Just forward to our children always.
    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
        // FIXME: We have to skip over inline flows, since they can show up inside table rows
        // at the moment (a demoted inline <form> for example). If we ever implement a
        // table-specific hit-test method (which we should do for performance reasons anyway),
        // then we can remove this check.
        if (child->isTableCell() && !toRenderBox(child)->hasSelfPaintingLayer()) {
            LayoutPoint cellPoint = flipForWritingModeForChild(toRenderTableCell(child), accumulatedOffset);
            if (child->nodeAtPoint(request, result, pointInContainer, cellPoint, action)) {
                updateHitTestResult(result, pointInContainer.point() - toLayoutSize(cellPoint));
                return true;
            }
        }
    }

    return false;
}