void GraphicsLayerTreeBuilder::rebuild(PaintLayer& layer, AncestorInfo info) { // Make the layer compositing if necessary, and set up clipping and content layers. // Note that we can only do work here that is independent of whether the descendant layers // have been processed. computeCompositingRequirements() will already have done the paint invalidation if necessary. layer.stackingNode()->updateLayerListsIfNeeded(); const bool hasCompositedLayerMapping = layer.hasCompositedLayerMapping(); CompositedLayerMapping* currentCompositedLayerMapping = layer.compositedLayerMapping(); // If this layer has a compositedLayerMapping, then that is where we place subsequent children GraphicsLayers. // Otherwise children continue to append to the child list of the enclosing layer. GraphicsLayerVector layerChildren; AncestorInfo infoForChildren(info); if (hasCompositedLayerMapping) { infoForChildren.childLayersOfEnclosingCompositedLayer = &layerChildren; infoForChildren.enclosingCompositedLayer = &layer; } #if ENABLE(ASSERT) LayerListMutationDetector mutationChecker(layer.stackingNode()); #endif if (layer.stackingNode()->isStackingContext()) { PaintLayerStackingNodeIterator iterator(*layer.stackingNode(), NegativeZOrderChildren); while (PaintLayerStackingNode* curNode = iterator.next()) rebuild(*curNode->layer(), infoForChildren); // If a negative z-order child is compositing, we get a foreground layer which needs to get parented. if (hasCompositedLayerMapping && currentCompositedLayerMapping->foregroundLayer()) infoForChildren.childLayersOfEnclosingCompositedLayer->append(currentCompositedLayerMapping->foregroundLayer()); } PaintLayerStackingNodeIterator iterator(*layer.stackingNode(), NormalFlowChildren | PositiveZOrderChildren); while (PaintLayerStackingNode* curNode = iterator.next()) rebuild(*curNode->layer(), infoForChildren); if (hasCompositedLayerMapping) { bool parented = false; if (layer.layoutObject()->isLayoutPart()) parented = PaintLayerCompositor::attachFrameContentLayersToIframeLayer(toLayoutPart(layer.layoutObject())); if (!parented) currentCompositedLayerMapping->setSublayers(layerChildren); if (shouldAppendLayer(layer)) info.childLayersOfEnclosingCompositedLayer->append(currentCompositedLayerMapping->childForSuperlayers()); } if (layer.scrollParent() && layer.scrollParent()->hasCompositedLayerMapping() && layer.scrollParent()->compositedLayerMapping()->needsToReparentOverflowControls() && layer.scrollParent()->getScrollableArea()->topmostScrollChild() == &layer) info.childLayersOfEnclosingCompositedLayer->append(layer.scrollParent()->compositedLayerMapping()->detachLayerForOverflowControls(*info.enclosingCompositedLayer)); }
void InspectorLayerTreeAgent::buildLayerIdToNodeIdMap(PaintLayer* root, LayerIdToNodeIdMap& layerIdToNodeIdMap) { if (root->hasCompositedLayerMapping()) { if (Node* node = root->layoutObject()->generatingNode()) { GraphicsLayer* graphicsLayer = root->compositedLayerMapping()->childForSuperlayers(); layerIdToNodeIdMap.set(graphicsLayer->platformLayer()->id(), idForNode(node)); } } for (PaintLayer* child = root->firstChild(); child; child = child->nextSibling()) buildLayerIdToNodeIdMap(child, layerIdToNodeIdMap); if (!root->layoutObject()->isLayoutIFrame()) return; FrameView* childFrameView = toFrameView(toLayoutPart(root->layoutObject())->widget()); if (LayoutView* childLayoutView = childFrameView->layoutView()) { if (PaintLayerCompositor* childCompositor = childLayoutView->compositor()) buildLayerIdToNodeIdMap(childCompositor->rootLayer(), layerIdToNodeIdMap); } }
TEST_F(ScrollingCoordinatorTest, iframeScrolling) { registerMockedHttpURLLoad("iframe-scrolling.html"); registerMockedHttpURLLoad("iframe-scrolling-inner.html"); navigateTo(m_baseURL + "iframe-scrolling.html"); forceFullCompositingUpdate(); // Verify the properties of the accelerated scrolling element starting from the LayoutObject // all the way to the WebLayer. Element* scrollableFrame = frame()->document()->getElementById("scrollable"); ASSERT_TRUE(scrollableFrame); LayoutObject* layoutObject = scrollableFrame->layoutObject(); ASSERT_TRUE(layoutObject); ASSERT_TRUE(layoutObject->isLayoutPart()); LayoutPart* layoutPart = toLayoutPart(layoutObject); ASSERT_TRUE(layoutPart); ASSERT_TRUE(layoutPart->widget()); ASSERT_TRUE(layoutPart->widget()->isFrameView()); FrameView* innerFrameView = toFrameView(layoutPart->widget()); LayoutView* innerLayoutView = innerFrameView->layoutView(); ASSERT_TRUE(innerLayoutView); PaintLayerCompositor* innerCompositor = innerLayoutView->compositor(); ASSERT_TRUE(innerCompositor->inCompositingMode()); ASSERT_TRUE(innerCompositor->scrollLayer()); GraphicsLayer* scrollLayer = innerCompositor->scrollLayer(); ASSERT_EQ(innerFrameView, scrollLayer->scrollableArea()); WebLayer* webScrollLayer = scrollLayer->platformLayer(); ASSERT_TRUE(webScrollLayer->scrollable()); #if OS(ANDROID) // Now verify we've attached impl-side scrollbars onto the scrollbar layers ASSERT_TRUE(innerCompositor->layerForHorizontalScrollbar()); ASSERT_TRUE(innerCompositor->layerForHorizontalScrollbar()->hasContentsLayer()); ASSERT_TRUE(innerCompositor->layerForVerticalScrollbar()); ASSERT_TRUE(innerCompositor->layerForVerticalScrollbar()->hasContentsLayer()); #endif }
TEST_F(ScrollingCoordinatorTest, rtlIframe) { registerMockedHttpURLLoad("rtl-iframe.html"); registerMockedHttpURLLoad("rtl-iframe-inner.html"); navigateTo(m_baseURL + "rtl-iframe.html"); forceFullCompositingUpdate(); // Verify the properties of the accelerated scrolling element starting from the LayoutObject // all the way to the WebLayer. Element* scrollableFrame = frame()->document()->getElementById("scrollable"); ASSERT_TRUE(scrollableFrame); LayoutObject* layoutObject = scrollableFrame->layoutObject(); ASSERT_TRUE(layoutObject); ASSERT_TRUE(layoutObject->isLayoutPart()); LayoutPart* layoutPart = toLayoutPart(layoutObject); ASSERT_TRUE(layoutPart); ASSERT_TRUE(layoutPart->widget()); ASSERT_TRUE(layoutPart->widget()->isFrameView()); FrameView* innerFrameView = toFrameView(layoutPart->widget()); LayoutView* innerLayoutView = innerFrameView->layoutView(); ASSERT_TRUE(innerLayoutView); PaintLayerCompositor* innerCompositor = innerLayoutView->compositor(); ASSERT_TRUE(innerCompositor->inCompositingMode()); ASSERT_TRUE(innerCompositor->scrollLayer()); GraphicsLayer* scrollLayer = innerCompositor->scrollLayer(); ASSERT_EQ(innerFrameView, scrollLayer->scrollableArea()); WebLayer* webScrollLayer = scrollLayer->platformLayer(); ASSERT_TRUE(webScrollLayer->scrollable()); int expectedScrollPosition = 958 + (innerFrameView->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15); ASSERT_EQ(expectedScrollPosition, webScrollLayer->scrollPositionDouble().x); }
void ChromeClientImpl::showMouseOverURL(const HitTestResult& result) { if (!m_webView->client()) return; WebURL url; // Find out if the mouse is over a link, and if so, let our UI know... if (result.isLiveLink() && !result.absoluteLinkURL().getString().isEmpty()) { url = result.absoluteLinkURL(); } else if (result.innerNode() && (isHTMLObjectElement(*result.innerNode()) || isHTMLEmbedElement(*result.innerNode()))) { LayoutObject* object = result.innerNode()->layoutObject(); if (object && object->isLayoutPart()) { Widget* widget = toLayoutPart(object)->widget(); if (widget && widget->isPluginContainer()) { WebPluginContainerImpl* plugin = toWebPluginContainerImpl(widget); url = plugin->plugin()->linkAtPosition( result.roundedPointInInnerNodeFrame()); } } } m_webView->client()->setMouseOverURL(url); }
bool PaintLayerCompositor::allocateOrClearCompositedLayerMapping(PaintLayer* layer, const CompositingStateTransitionType compositedLayerUpdate) { bool compositedLayerMappingChanged = false; // FIXME: It would be nice to directly use the layer's compositing reason, // but allocateOrClearCompositedLayerMapping also gets called without having updated compositing // requirements fully. switch (compositedLayerUpdate) { case AllocateOwnCompositedLayerMapping: ASSERT(!layer->hasCompositedLayerMapping()); setCompositingModeEnabled(true); // If we need to issue paint invalidations, do so before allocating the compositedLayerMapping and clearing out the groupedMapping. paintInvalidationOnCompositingChange(layer); // If this layer was previously squashed, we need to remove its reference to a groupedMapping right away, so // that computing paint invalidation rects will know the layer's correct compositingState. // FIXME: do we need to also remove the layer from it's location in the squashing list of its groupedMapping? // Need to create a test where a squashed layer pops into compositing. And also to cover all other // sorts of compositingState transitions. layer->setLostGroupedMapping(false); layer->setGroupedMapping(nullptr, PaintLayer::InvalidateLayerAndRemoveFromMapping); layer->ensureCompositedLayerMapping(); compositedLayerMappingChanged = true; // At this time, the ScrollingCooridnator only supports the top-level frame. if (layer->isRootLayer() && m_layoutView.frame()->isLocalRoot()) { if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) scrollingCoordinator->frameViewRootLayerDidChange(m_layoutView.frameView()); } break; case RemoveOwnCompositedLayerMapping: // PutInSquashingLayer means you might have to remove the composited layer mapping first. case PutInSquashingLayer: if (layer->hasCompositedLayerMapping()) { // If we're removing the compositedLayerMapping from a reflection, clear the source GraphicsLayer's pointer to // its replica GraphicsLayer. In practice this should never happen because reflectee and reflection // are both either composited, or not composited. if (layer->isReflection()) { PaintLayer* sourceLayer = toLayoutBoxModelObject(layer->layoutObject()->parent())->layer(); if (sourceLayer->hasCompositedLayerMapping()) { ASSERT(sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->replicaLayer() == layer->compositedLayerMapping()->mainGraphicsLayer()); sourceLayer->compositedLayerMapping()->mainGraphicsLayer()->setReplicatedByLayer(nullptr); } } layer->clearCompositedLayerMapping(); compositedLayerMappingChanged = true; } break; case RemoveFromSquashingLayer: case NoCompositingStateChange: // Do nothing. break; } if (compositedLayerMappingChanged && layer->layoutObject()->isLayoutPart()) { PaintLayerCompositor* innerCompositor = frameContentsCompositor(toLayoutPart(layer->layoutObject())); if (innerCompositor && innerCompositor->staleInCompositingMode()) innerCompositor->updateRootLayerAttachment(); } if (compositedLayerMappingChanged) layer->clipper().clearClipRectsIncludingDescendants(PaintingClipRects); // If a fixed position layer gained/lost a compositedLayerMapping or the reason not compositing it changed, // the scrolling coordinator needs to recalculate whether it can do fast scrolling. if (compositedLayerMappingChanged) { if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) scrollingCoordinator->frameViewFixedObjectsDidChange(m_layoutView.frameView()); } return compositedLayerMappingChanged; }