bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) { if (request.allowsChildFrameContent() && widget() && widget()->isFrameView() && toFrameView(widget())->renderView()) { FrameView* childFrameView = toFrameView(widget()); RenderView* childRoot = childFrameView->renderView(); LayoutPoint adjustedLocation = accumulatedOffset + location(); LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - childFrameView->scrollOffset(); HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset); HitTestRequest newHitTestRequest(request.type() | HitTestRequest::ChildFrameHitTest); HitTestResult childFrameResult(newHitTestLocation); bool isInsideChildFrame = childRoot->hitTest(newHitTestRequest, newHitTestLocation, childFrameResult); if (newHitTestLocation.isRectBasedTest()) result.append(childFrameResult); else if (isInsideChildFrame) result = childFrameResult; if (isInsideChildFrame) return true; } bool hadResult = result.innerNode(); bool inside = RenderReplaced::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action); // Check to see if we are really over the widget itself (and not just in the border/padding area). if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == &frameOwnerElement()) result.setIsOverWidget(contentBoxRect().contains(result.localPoint())); return inside; }
bool RenderFlowThread::hitTestFlowThreadPortionInRegion(RenderRegion* region, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const { LayoutRect regionClippingRect = computeRegionClippingRect(accumulatedOffset, flowThreadPortionRect, flowThreadPortionOverflowRect); if (!regionClippingRect.contains(locationInContainer.point())) return false; LayoutSize renderFlowThreadOffset; if (style()->isFlippedBlocksWritingMode()) { LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect); flipForWritingMode(flippedFlowThreadPortionRect); renderFlowThreadOffset = accumulatedOffset - flippedFlowThreadPortionRect.location(); } else renderFlowThreadOffset = accumulatedOffset - flowThreadPortionRect.location(); // Always ignore clipping, since the RenderFlowThread has nothing to do with the bounds of the FrameView. HitTestRequest newRequest(request.type() | HitTestRequest::IgnoreClipping); // Make a new temporary HitTestLocation in the new region. HitTestLocation newHitTestLocation(locationInContainer, -renderFlowThreadOffset, region); bool isPointInsideFlowThread = layer()->hitTest(newRequest, newHitTestLocation, result); // 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; }
bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction) { // Give RenderSVGViewportContainer a chance to apply its viewport clip if (!pointIsInsideViewportClip(pointInParent)) return false; FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent); if (!SVGRenderSupport::pointInClippingArea(this, localPoint)) return false; for (RenderObject* child = lastChild(); child; child = child->previousSibling()) { if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) { updateHitTestResult(result, roundedLayoutPoint(localPoint)); return true; } } // Accessibility wants to return SVG containers, if appropriate. if (request.type() & HitTestRequest::AccessibilityHitTest && m_objectBoundingBox.contains(localPoint)) { updateHitTestResult(result, roundedLayoutPoint(localPoint)); return true; } // Spec: Only graphical elements can be targeted by the mouse, period. // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched." return false; }
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; }
bool RenderPart::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) { if (!widget() || !widget()->isFrameView() || !request.allowsChildFrameContent()) return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action); FrameView* childFrameView = toFrameView(widget()); RenderView* childRoot = childFrameView->renderView(); if (childRoot) { LayoutPoint adjustedLocation = accumulatedOffset + location(); LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - childFrameView->scrollOffset(); HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset); HitTestRequest newHitTestRequest(request.type() | HitTestRequest::ChildFrameHitTest); HitTestResult childFrameResult(newHitTestLocation); bool isInsideChildFrame = childRoot->hitTest(newHitTestRequest, newHitTestLocation, childFrameResult); if (newHitTestLocation.isRectBasedTest()) result.append(childFrameResult); else if (isInsideChildFrame) result = childFrameResult; if (isInsideChildFrame) return true; } return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action); }
bool RenderPart::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) { if (!widget() || !widget()->isFrameView() || !request.allowsChildFrameContent()) return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action); FrameView* childFrameView = toFrameView(widget()); RenderView* childRoot = childFrameView->renderView(); if (childRoot) { LayoutPoint adjustedLocation = accumulatedOffset + location(); LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - childFrameView->scrollOffset(); HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset); HitTestRequest newHitTestRequest(request.type() | HitTestRequest::ChildFrameHitTest); HitTestResult childFrameResult(newHitTestLocation); bool isInsideChildFrame = childRoot->hitTest(newHitTestRequest, newHitTestLocation, childFrameResult); if (newHitTestLocation.isRectBasedTest()) result.append(childFrameResult); else if (isInsideChildFrame) result = childFrameResult; if (isInsideChildFrame) return true; if (request.allowsFrameScrollbars()) { // ScrollView scrollbars are not the same as RenderLayer scrollbars tested by RenderLayer::hitTestOverflowControls, // so we need to test ScrollView scrollbars separately here. // FIXME: Consider if this test could be done unconditionally. Scrollbar* frameScrollbar = childFrameView->scrollbarAtPoint(newHitTestLocation.roundedPoint()); if (frameScrollbar) result.setScrollbar(frameScrollbar); } } return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action); }