// Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips, // up to the enclosing compositing ancestor. This is required because compositing layers are parented // according to the z-order hierarchy, yet clipping goes down the renderer hierarchy. // Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy, // but a sibling in the z-order hierarchy. bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const { if (!layer->isComposited() || !layer->parent()) return false; RenderLayer* compositingAncestor = layer->ancestorCompositingLayer(); if (!compositingAncestor) return false; // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(), // so we only care about clipping between its first child that is our ancestor (the computeClipRoot), // and layer. RenderLayer* computeClipRoot = 0; RenderLayer* curr = layer; while (curr) { RenderLayer* next = curr->parent(); if (next == compositingAncestor) { computeClipRoot = curr; break; } curr = next; } if (!computeClipRoot || computeClipRoot == layer) return false; IntRect backgroundRect = layer->backgroundClipRect(computeClipRoot, true); return backgroundRect != ClipRects::infiniteRect(); }
void GraphicsLayerUpdater::update(RenderLayer& layer, UpdateType updateType) { if (layer.hasCompositedLayerMapping()) { CompositedLayerMappingPtr mapping = layer.compositedLayerMapping(); // Note carefully: here we assume that the compositing state of all descendants have been updated already, // so it is legitimate to compute and cache the composited bounds for this layer. mapping->updateCompositedBounds(updateType); if (RenderLayerReflectionInfo* reflection = layer.reflectionInfo()) { if (reflection->reflectionLayer()->hasCompositedLayerMapping()) reflection->reflectionLayer()->compositedLayerMapping()->updateCompositedBounds(ForceUpdate); } mapping->updateGraphicsLayerConfiguration(); updateType = mapping->updateGraphicsLayerGeometry(updateType); mapping->clearNeedsGeometryUpdate(); if (!layer.parent()) layer.compositor()->updateRootLayerPosition(); if (mapping->hasUnpositionedOverflowControlsLayers()) layer.scrollableArea()->positionOverflowControls(); } for (RenderLayer* child = layer.firstChild(); child; child = child->nextSibling()) update(*child, updateType); }
void MouseRelatedEvent::computeRelativePosition() { Node* targetNode = target() ? target()->toNode() : 0; if (!targetNode) return; // Compute coordinates that are based on the target. m_layerLocation = m_pageLocation; m_offsetLocation = m_pageLocation; // Must have an updated render tree for this math to work correctly. targetNode->document().updateLayoutIgnorePendingStylesheets(); // Adjust offsetLocation to be relative to the target's position. if (RenderObject* r = targetNode->renderer()) { FloatPoint localPos = r->absoluteToLocal(absoluteLocation(), UseTransforms); m_offsetLocation = roundedLayoutPoint(localPos); } // Adjust layerLocation to be relative to the layer. // FIXME: event.layerX and event.layerY are poorly defined, // and probably don't always correspond to RenderLayer offsets. // https://bugs.webkit.org/show_bug.cgi?id=21868 Node* n = targetNode; while (n && !n->renderer()) n = n->parentNode(); if (n) { // FIXME: This logic is a wrong implementation of convertToLayerCoords. for (RenderLayer* layer = n->renderer()->enclosingLayer(); layer; layer = layer->parent()) m_layerLocation -= toLayoutSize(layer->location()); } m_hasCachedRelativePosition = true; }
AffineTransform SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject& renderer) { AffineTransform absoluteTransform = currentContentTransformation(); float deviceScaleFactor = renderer.document().deviceScaleFactor(); // Walk up the render tree, accumulating SVG transforms. const RenderObject* ancestor = &renderer; while (ancestor) { absoluteTransform = ancestor->localToParentTransform() * absoluteTransform; if (ancestor->isSVGRoot()) break; ancestor = ancestor->parent(); } // Continue walking up the layer tree, accumulating CSS transforms. RenderLayer* layer = ancestor ? ancestor->enclosingLayer() : nullptr; while (layer) { if (TransformationMatrix* layerTransform = layer->transform()) absoluteTransform = layerTransform->toAffineTransform() * absoluteTransform; // We can stop at compositing layers, to match the backing resolution. if (layer->isComposited()) break; layer = layer->parent(); } absoluteTransform.scale(deviceScaleFactor); return absoluteTransform; }
RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingContextNode() const { for (RenderLayer* ancestor = layer()->parent(); ancestor; ancestor = ancestor->parent()) { RenderLayerStackingNode* stackingNode = ancestor->stackingNode(); if (stackingNode->isStackingContext()) return stackingNode; } return 0; }
RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingNode() const { RenderLayer* ancestor = layer()->parent(); while (ancestor && !ancestor->stackingNode()->isStackingContext()) ancestor = ancestor->parent(); if (ancestor) return ancestor->stackingNode(); return 0; }
RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const { for (RenderLayer* curr = layer->parent(); curr != 0; curr = curr->parent()) { if (curr->isStackingContext()) return 0; if (curr->renderer()->hasOverflowClip() || layer->renderer()->hasClip()) return curr; } return 0; }
RenderLayer* LinkHighlight::computeEnclosingCompositingLayer() { if (!m_node || !m_node->renderer()) return 0; RenderLayer* renderLayer = m_node->renderer()->enclosingLayer(); // Find the nearest enclosing composited layer and attach to it. We may need to cross frame boundaries // to find a suitable layer. while (renderLayer && !renderLayer->isComposited()) { if (!renderLayer->parent()) { // See if we've reached the root in an enclosed frame. if (renderLayer->renderer()->frame()->ownerRenderer()) renderLayer = renderLayer->renderer()->frame()->ownerRenderer()->enclosingLayer(); else renderLayer = 0; } else renderLayer = renderLayer->parent(); } if (!renderLayer || !renderLayer->isComposited()) return 0; GraphicsLayerChromium* newGraphicsLayer = static_cast<GraphicsLayerChromium*>(renderLayer->backing()->graphicsLayer()); m_clipLayer->setSublayerTransform(SkMatrix44()); if (!newGraphicsLayer->drawsContent()) { m_clipLayer->setSublayerTransform(newGraphicsLayer->platformLayer()->transform()); newGraphicsLayer = static_cast<GraphicsLayerChromium*>(m_owningWebViewImpl->nonCompositedContentHost()->topLevelRootLayer()); } if (m_currentGraphicsLayer != newGraphicsLayer) { if (m_currentGraphicsLayer) clearGraphicsLayerLinkHighlightPointer(); m_currentGraphicsLayer = newGraphicsLayer; m_currentGraphicsLayer->setLinkHighlight(this); } return renderLayer; }
void MouseRelatedEvent::computeRelativePosition() { Node* targetNode = target() ? target()->toNode() : 0; if (!targetNode) return; // Compute coordinates that are based on the target. m_layerLocation = m_pageLocation; m_offsetLocation = m_pageLocation; // Must have an updated render tree for this math to work correctly. targetNode->document()->updateStyleIfNeeded(); // Adjust offsetLocation to be relative to the target's position. if (!isSimulated()) { if (RenderObject* r = targetNode->renderer()) { FloatPoint localPos = r->absoluteToLocal(absoluteLocation(), false, true); m_offsetLocation = roundedLayoutPoint(localPos); float scaleFactor = 1 / pageZoomFactor(this); if (scaleFactor != 1.0f) m_offsetLocation.scale(scaleFactor, scaleFactor); } } // Adjust layerLocation to be relative to the layer. // FIXME: We're pretty sure this is the wrong definition of "layer." // Our RenderLayer is a more modern concept, and layerX/Y is some // other notion about groups of elements (left over from the Netscape 4 days?); // we should test and fix this. Node* n = targetNode; while (n && !n->renderer()) n = n->parentNode(); RenderLayer* layer; if (n && (layer = n->renderer()->enclosingLayer())) { layer->updateLayerPosition(); for (; layer; layer = layer->parent()) { m_layerLocation -= toSize(layer->location()); } } m_hasCachedRelativePosition = true; }
void MouseRelatedEvent::receivedTarget() { ASSERT(target()); Node* targ = target()->toNode(); if (!targ) return; // Compute coordinates that are based on the target. m_layerX = m_pageX; m_layerY = m_pageY; m_offsetX = m_pageX; m_offsetY = m_pageY; // Must have an updated render tree for this math to work correctly. targ->document()->updateStyleIfNeeded(); // Adjust offsetX/Y to be relative to the target's position. if (!isSimulated()) { if (RenderObject* r = targ->renderer()) { FloatPoint localPos = r->absoluteToLocal(absoluteLocation(), false, true); float zoomFactor = pageZoomFactor(this); m_offsetX = lroundf(localPos.x() / zoomFactor); m_offsetY = lroundf(localPos.y() / zoomFactor); } } // Adjust layerX/Y to be relative to the layer. // FIXME: We're pretty sure this is the wrong definition of "layer." // Our RenderLayer is a more modern concept, and layerX/Y is some // other notion about groups of elements (left over from the Netscape 4 days?); // we should test and fix this. Node* n = targ; while (n && !n->renderer()) n = n->parentNode(); if (n) { RenderLayer* layer = n->renderer()->enclosingLayer(); layer->updateLayerPosition(); for (; layer; layer = layer->parent()) { m_layerX -= layer->x(); m_layerY -= layer->y(); } } }
void GraphicsLayerUpdater::update(RenderLayer& layer, UpdateType updateType, const UpdateContext& context) { if (layer.hasCompositedLayerMapping()) { CompositedLayerMappingPtr mapping = layer.compositedLayerMapping(); const RenderLayer* compositingContainer = context.compositingContainer(layer); ASSERT(compositingContainer == layer.ancestorCompositingLayer()); if (mapping->updateRequiresOwnBackingStoreForAncestorReasons(compositingContainer)) updateType = ForceUpdate; // Note carefully: here we assume that the compositing state of all descendants have been updated already, // so it is legitimate to compute and cache the composited bounds for this layer. mapping->updateCompositedBounds(updateType); if (RenderLayerReflectionInfo* reflection = layer.reflectionInfo()) { if (reflection->reflectionLayer()->hasCompositedLayerMapping()) reflection->reflectionLayer()->compositedLayerMapping()->updateCompositedBounds(ForceUpdate); } if (mapping->updateGraphicsLayerConfiguration(updateType)) m_needsRebuildTree = true; mapping->updateGraphicsLayerGeometry(updateType, compositingContainer); updateType = mapping->updateTypeForChildren(updateType); mapping->clearNeedsGraphicsLayerUpdate(); if (!layer.parent()) layer.compositor()->updateRootLayerPosition(); if (mapping->hasUnpositionedOverflowControlsLayers()) layer.scrollableArea()->positionOverflowControls(); } UpdateContext childContext(context, layer); for (RenderLayer* child = layer.firstChild(); child; child = child->nextSibling()) update(*child, updateType, childContext); }
void MouseRelatedEvent::computeRelativePosition() { Node* targetNode = target() ? target()->toNode() : nullptr; if (!targetNode) return; // Compute coordinates that are based on the target. m_layerLocation = m_pageLocation; m_offsetLocation = m_pageLocation; // Must have an updated render tree for this math to work correctly. targetNode->document().updateLayoutIgnorePendingStylesheets(); // Adjust offsetLocation to be relative to the target's position. if (RenderObject* r = targetNode->renderer()) { m_offsetLocation = LayoutPoint(r->absoluteToLocal(absoluteLocation(), UseTransforms)); float scaleFactor = 1 / (pageZoomFactor(this) * frameScaleFactor(this)); if (scaleFactor != 1.0f) m_offsetLocation.scale(scaleFactor, scaleFactor); } // Adjust layerLocation to be relative to the layer. // FIXME: event.layerX and event.layerY are poorly defined, // and probably don't always correspond to RenderLayer offsets. // https://bugs.webkit.org/show_bug.cgi?id=21868 Node* n = targetNode; while (n && !n->renderer()) n = n->parentNode(); RenderLayer* layer; if (n && (layer = n->renderer()->enclosingLayer())) { for (; layer; layer = layer->parent()) { m_layerLocation -= toLayoutSize(layer->location()); } } m_hasCachedRelativePosition = true; }
void MouseEventImpl::computeLayerPos() { m_layerX = m_pageX; m_layerY = m_pageY; DocumentImpl* doc = view() ? view()->document() : 0; if (doc && doc->renderer()) { khtml::RenderObject::NodeInfo renderInfo(true, false); doc->renderer()->layer()->nodeAtPoint(renderInfo, m_pageX, m_pageY); NodeImpl *node = renderInfo.innerNonSharedNode(); while (node && !node->renderer()) node = node->parent(); if (node) { node->renderer()->enclosingLayer()->updateLayerPosition(); for (RenderLayer* layer = node->renderer()->enclosingLayer(); layer; layer = layer->parent()) { m_layerX -= layer->xPos(); m_layerY -= layer->yPos(); } } } }
bool CompositingReasonFinder::requiresCompositingForPositionFixed(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason, bool* needToRecomputeCompositingRequirements) const { if (!(m_compositingTriggers & ViewportConstrainedPositionedTrigger)) return false; if (renderer->style()->position() != FixedPosition) return false; RenderObject* container = renderer->container(); // If the renderer is not hooked up yet then we have to wait until it is. if (!container) { ASSERT(m_renderView.document().lifecycle().state() < DocumentLifecycle::InCompositingUpdate); // FIXME: Remove this and ASSERT(container) once we get rid of the incremental // allocateOrClearCompositedLayerMapping compositing update. This happens when // adding the renderer to the tree because we setStyle before addChild in // createRendererForElementIfNeeded. *needToRecomputeCompositingRequirements = true; return false; } // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements. // They will stay fixed wrt the container rather than the enclosing frame. if (container != &m_renderView) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNonViewContainer; return false; } // If the fixed-position element does not have any scrollable ancestor between it and // its container, then we do not need to spend compositor resources for it. Start by // assuming we can opt-out (i.e. no scrollable ancestor), and refine the answer below. bool hasScrollableAncestor = false; // The FrameView has the scrollbars associated with the top level viewport, so we have to // check the FrameView in addition to the hierarchy of ancestors. FrameView* frameView = m_renderView.frameView(); if (frameView && frameView->isScrollable()) hasScrollableAncestor = true; RenderLayer* ancestor = layer->parent(); while (ancestor && !hasScrollableAncestor) { if (ancestor->scrollsOverflow()) hasScrollableAncestor = true; if (ancestor->renderer() == &m_renderView) break; ancestor = ancestor->parent(); } if (!hasScrollableAncestor) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForUnscrollableAncestors; return false; } // Subsequent tests depend on layout. If we can't tell now, just keep things the way they are until layout is done. // FIXME: Get rid of this codepath once we get rid of the incremental compositing update in RenderLayer::styleChanged. if (m_renderView.document().lifecycle().state() < DocumentLifecycle::LayoutClean) { *needToRecomputeCompositingRequirements = true; return layer->hasCompositedLayerMapping(); } bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant(); if (!paintsContent) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNoVisibleContent; return false; } // Fixed position elements that are invisible in the current view don't get their own layer. if (FrameView* frameView = m_renderView.frameView()) { ASSERT(m_renderView.document().lifecycle().state() == DocumentLifecycle::InCompositingUpdate); LayoutRect viewBounds = frameView->viewportConstrainedVisibleContentRect(); LayoutRect layerBounds = layer->boundingBoxForCompositing(layer->compositor()->rootRenderLayer(), RenderLayer::ApplyBoundsChickenEggHacks); if (!viewBounds.intersects(enclosingIntRect(layerBounds))) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView; return false; } } return true; }
bool CompositingReasonFinder::requiresCompositingForPosition(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason, bool* needToRecomputeCompositingRequirements) const { // position:fixed elements that create their own stacking context (e.g. have an explicit z-index, // opacity, transform) can get their own composited layer. A stacking context is required otherwise // z-index and clipping will be broken. if (!renderer->isPositioned()) return false; EPosition position = renderer->style()->position(); bool isFixed = renderer->isOutOfFlowPositioned() && position == FixedPosition; // FIXME: The isStackingContainer check here is redundant. Fixed position elements are always stacking contexts. if (isFixed && !layer->stackingNode()->isStackingContainer()) return false; bool isSticky = renderer->isInFlowPositioned() && position == StickyPosition; if (!isFixed && !isSticky) return false; // FIXME: acceleratedCompositingForFixedPositionEnabled should probably be renamed acceleratedCompositingForViewportConstrainedPositionEnabled(). if (Settings* settings = m_renderView.document().settings()) { if (!settings->acceleratedCompositingForFixedPositionEnabled()) return false; } if (isSticky) return isViewportConstrainedFixedOrStickyLayer(layer); RenderObject* container = renderer->container(); // If the renderer is not hooked up yet then we have to wait until it is. if (!container) { *needToRecomputeCompositingRequirements = true; return false; } // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements. // They will stay fixed wrt the container rather than the enclosing frame. if (container != &m_renderView) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNonViewContainer; return false; } // If the fixed-position element does not have any scrollable ancestor between it and // its container, then we do not need to spend compositor resources for it. Start by // assuming we can opt-out (i.e. no scrollable ancestor), and refine the answer below. bool hasScrollableAncestor = false; // The FrameView has the scrollbars associated with the top level viewport, so we have to // check the FrameView in addition to the hierarchy of ancestors. FrameView* frameView = m_renderView.frameView(); if (frameView && frameView->isScrollable()) hasScrollableAncestor = true; RenderLayer* ancestor = layer->parent(); while (ancestor && !hasScrollableAncestor) { if (frameView->containsScrollableArea(ancestor->scrollableArea())) hasScrollableAncestor = true; if (ancestor->renderer() == &m_renderView) break; ancestor = ancestor->parent(); } if (!hasScrollableAncestor) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForUnscrollableAncestors; return false; } // Subsequent tests depend on layout. If we can't tell now, just keep things the way they are until layout is done. if (m_renderView.document().lifecycle().state() < DocumentLifecycle::LayoutClean) { *needToRecomputeCompositingRequirements = true; return layer->hasCompositedLayerMapping(); } bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant(); if (!paintsContent) { if (viewportConstrainedNotCompositedReason) *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNoVisibleContent; return false; } // Fixed position elements that are invisible in the current view don't get their own layer. if (FrameView* frameView = m_renderView.frameView()) { LayoutRect viewBounds = frameView->viewportConstrainedVisibleContentRect(); LayoutRect layerBounds = layer->calculateLayerBounds(layer->compositor()->rootRenderLayer(), 0, RenderLayer::DefaultCalculateLayerBoundsFlags | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask | RenderLayer::IncludeCompositedDescendants | RenderLayer::PretendLayerHasOwnBacking); if (!viewBounds.intersects(enclosingIntRect(layerBounds))) { if (viewportConstrainedNotCompositedReason) { *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView; *needToRecomputeCompositingRequirements = true; } return false; } } return true; }
bool RenderEmbeddedObject::isReplacementObscured() const { // Return whether or not the replacement content for blocked plugins is accessible to the user. // Check the opacity of each layer containing the element or its ancestors. float opacity = 1.0; for (RenderLayer* layer = enclosingLayer(); layer; layer = layer->parent()) { RenderLayerModelObject* renderer = layer->renderer(); RenderStyle* style = renderer->style(); opacity *= style->opacity(); if (opacity < 0.1) return true; } // Calculate the absolute rect for the blocked plugin replacement text. IntRect absoluteBoundingBox = absoluteBoundingBoxRect(); LayoutPoint absoluteLocation(absoluteBoundingBox.location()); LayoutRect rect = replacementTextRect(absoluteLocation); if (rect.isEmpty()) return true; RenderView* docRenderer = document()->renderView(); ASSERT(docRenderer); if (!docRenderer) return true; HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent); HitTestResult result; HitTestLocation location; LayoutUnit x = rect.x(); LayoutUnit y = rect.y(); LayoutUnit width = rect.width(); LayoutUnit height = rect.height(); // Hit test the center and near the corners of the replacement text to ensure // it is visible and is not masked by other elements. bool hit = false; location = LayoutPoint(x + width / 2, y + height / 2); hit = docRenderer->hitTest(request, location, result); if (!hit || result.innerNode() != node()) return true; location = LayoutPoint(x, y); hit = docRenderer->hitTest(request, location, result); if (!hit || result.innerNode() != node()) return true; location = LayoutPoint(x + width, y); hit = docRenderer->hitTest(request, location, result); if (!hit || result.innerNode() != node()) return true; location = LayoutPoint(x + width, y + height); hit = docRenderer->hitTest(request, location, result); if (!hit || result.innerNode() != node()) return true; location = LayoutPoint(x, y + height); hit = docRenderer->hitTest(request, location, result); if (!hit || result.innerNode() != node()) return true; return false; }
bool RenderEmbeddedObject::isReplacementObscured() const { // Return whether or not the replacement content for blocked plugins is accessible to the user. // Check the opacity of each layer containing the element or its ancestors. float opacity = 1.0; for (RenderLayer* layer = enclosingLayer(); layer; layer = layer->parent()) { opacity *= layer->renderer().style().opacity(); if (opacity < 0.1) return true; } // Calculate the absolute rect for the blocked plugin replacement text. IntRect absoluteBoundingBox = absoluteBoundingBoxRect(); LayoutPoint absoluteLocation(absoluteBoundingBox.location()); LayoutRect rect = unavailablePluginIndicatorBounds(absoluteLocation); if (rect.isEmpty()) return true; RenderView* rootRenderView = document().topDocument().renderView(); ASSERT(rootRenderView); if (!rootRenderView) return true; IntRect rootViewRect = view().frameView().convertToRootView(snappedIntRect(rect)); HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::AllowChildFrameContent); HitTestResult result; HitTestLocation location; LayoutUnit x = rootViewRect.x(); LayoutUnit y = rootViewRect.y(); LayoutUnit width = rootViewRect.width(); LayoutUnit height = rootViewRect.height(); // Hit test the center and near the corners of the replacement text to ensure // it is visible and is not masked by other elements. bool hit = false; location = LayoutPoint(x + width / 2, y + height / 2); hit = rootRenderView->hitTest(request, location, result); if (!hit || result.innerNode() != &frameOwnerElement()) return true; location = LayoutPoint(x, y); hit = rootRenderView->hitTest(request, location, result); if (!hit || result.innerNode() != &frameOwnerElement()) return true; location = LayoutPoint(x + width, y); hit = rootRenderView->hitTest(request, location, result); if (!hit || result.innerNode() != &frameOwnerElement()) return true; location = LayoutPoint(x + width, y + height); hit = rootRenderView->hitTest(request, location, result); if (!hit || result.innerNode() != &frameOwnerElement()) return true; location = LayoutPoint(x, y + height); hit = rootRenderView->hitTest(request, location, result); if (!hit || result.innerNode() != &frameOwnerElement()) return true; return false; }