bool RenderFlowThread::hitTestRegion(RenderRegion* region, const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset) { LayoutRect regionRect(region->regionRect()); LayoutRect regionOverflowRect = region->regionOverflowRect(); LayoutRect regionClippingRect(accumulatedOffset + (regionOverflowRect.location() - regionRect.location()), regionOverflowRect.size()); if (!regionClippingRect.contains(pointInContainer)) return false; LayoutPoint renderFlowThreadOffset; if (style()->isFlippedBlocksWritingMode()) { LayoutRect flippedRegionRect(regionRect); flipForWritingMode(flippedRegionRect); renderFlowThreadOffset = LayoutPoint(accumulatedOffset - flippedRegionRect.location()); } else renderFlowThreadOffset = LayoutPoint(accumulatedOffset - regionRect.location()); LayoutPoint transformedPoint(pointInContainer.x() - renderFlowThreadOffset.x(), pointInContainer.y() - renderFlowThreadOffset.y()); // Always ignore clipping, since the RenderFlowThread has nothing to do with the bounds of the FrameView. HitTestRequest newRequest(request.type() | HitTestRequest::IgnoreClipping); RenderRegion* oldRegion = result.region(); result.setRegion(region); LayoutPoint oldPoint = result.point(); result.setPoint(transformedPoint); bool isPointInsideFlowThread = layer()->hitTest(newRequest, result); result.setPoint(oldPoint); result.setRegion(oldRegion); // FIXME: Should we set result.m_localPoint back to the RenderRegion's coordinate space or leave it in the RenderFlowThread's coordinate // space? Right now it's staying in the RenderFlowThread's coordinate space, which may end up being ok. We will know more when we get around to // patching positionForPoint. return isPointInsideFlowThread; }
HitTestResult::HitTestResult(const HitTestResult& other) : HitTestPoint(other) , m_innerNode(other.innerNode()) , m_innerNonSharedNode(other.innerNonSharedNode()) , m_localPoint(other.localPoint()) , m_innerURLElement(other.URLElement()) , m_scrollbar(other.scrollbar()) , m_isOverWidget(other.isOverWidget()) , m_shadowContentFilterPolicy(other.shadowContentFilterPolicy()) , m_region(other.region()) { // Only copy the NodeSet in case of rect hit test. m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0); }
// Hit Testing bool RenderRegion::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& 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(result.region()); boundsRect.moveBy(adjustedLocation); if (visibleToHitTesting() && action == HitTestForeground && boundsRect.intersects(result.rectForPoint(pointInContainer))) { // 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 - toLayoutSize(adjustedLocation)); if (!result.addNodeToRectBasedTestResult(node(), pointInContainer, boundsRect)) return true; } return false; }
HitTestResult::HitTestResult(const HitTestResult& other) : m_innerNode(other.innerNode()) , m_innerNonSharedNode(other.innerNonSharedNode()) , m_point(other.point()) , m_localPoint(other.localPoint()) , m_innerURLElement(other.URLElement()) , m_scrollbar(other.scrollbar()) , m_isOverWidget(other.isOverWidget()) , m_region(other.region()) { // Only copy the padding and NodeSet in case of rect hit test. // Copying the later is rather expensive. if ((m_isRectBased = other.isRectBasedTest())) { m_topPadding = other.m_topPadding; m_rightPadding = other.m_rightPadding; m_bottomPadding = other.m_bottomPadding; m_leftPadding = other.m_leftPadding; } else m_topPadding = m_rightPadding = m_bottomPadding = m_leftPadding = 0; m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0); }