FrameView* AsyncScrollingCoordinator::frameViewForScrollingNode(ScrollingNodeID scrollingNodeID) const { if (!m_scrollingStateTree->rootStateNode()) return nullptr; if (scrollingNodeID == m_scrollingStateTree->rootStateNode()->scrollingNodeID()) return m_page->mainFrame().view(); ScrollingStateNode* stateNode = m_scrollingStateTree->stateNodeForID(scrollingNodeID); if (!stateNode) return nullptr; // Find the enclosing frame scrolling node. ScrollingStateNode* parentNode = stateNode; while (parentNode && parentNode->nodeType() != FrameScrollingNode) parentNode = parentNode->parent(); if (!parentNode) return nullptr; // Walk the frame tree to find the matching FrameView. This is not ideal, but avoids back pointers to FrameViews // from ScrollingTreeStateNodes. for (Frame* frame = &m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) { if (FrameView* view = frame->view()) { if (view->scrollLayerID() == parentNode->scrollingNodeID()) return view; } } return nullptr; }
void RemoteScrollingTreeTextStream::recursiveDumpNodes(const ScrollingStateNode& node, bool changedPropertiesOnly) { RemoteScrollingTreeTextStream& ts = *this; ts << "\n"; ts.increaseIndent(); ts.writeIndent(); dump(node, changedPropertiesOnly); if (node.children()) { ts << "\n"; ts.increaseIndent(); ts.writeIndent(); ts << "(children"; ts.increaseIndent(); for (auto& childNode : *node.children()) recursiveDumpNodes(*childNode, changedPropertiesOnly); ts << ")"; ts.decreaseIndent(); ts.decreaseIndent(); } ts << ")"; ts.decreaseIndent(); }
ScrollingNodeID ScrollingStateTree::attachNode(ScrollingNodeType nodeType, ScrollingNodeID newNodeID, ScrollingNodeID parentID) { ASSERT(newNodeID); if (ScrollingStateNode* node = stateNodeForID(newNodeID)) { ScrollingStateNode* parent = stateNodeForID(parentID); if (!parent) return newNodeID; if (node->parent() == parent) return newNodeID; // The node is being re-parented. To do that, we'll remove it, and then re-create a new node. removeNode(node); } ScrollingStateNode* newNode = 0; if (!parentID) { // If we're resetting the root node, we should clear the HashMap and destroy the current children. clear(); setRootStateNode(ScrollingStateFrameScrollingNode::create(*this, newNodeID)); newNode = rootStateNode(); m_hasNewRootStateNode = true; } else { ScrollingStateNode* parent = stateNodeForID(parentID); if (!parent) return 0; switch (nodeType) { case FixedNode: { OwnPtr<ScrollingStateFixedNode> fixedNode = ScrollingStateFixedNode::create(*this, newNodeID); newNode = fixedNode.get(); parent->appendChild(fixedNode.release()); break; } case StickyNode: { OwnPtr<ScrollingStateStickyNode> stickyNode = ScrollingStateStickyNode::create(*this, newNodeID); newNode = stickyNode.get(); parent->appendChild(stickyNode.release()); break; } case FrameScrollingNode: { OwnPtr<ScrollingStateFrameScrollingNode> scrollingNode = ScrollingStateFrameScrollingNode::create(*this, newNodeID); newNode = scrollingNode.get(); parent->appendChild(scrollingNode.release()); break; } case OverflowScrollingNode: { OwnPtr<ScrollingStateOverflowScrollingNode> scrollingNode = ScrollingStateOverflowScrollingNode::create(*this, newNodeID); newNode = scrollingNode.get(); parent->appendChild(scrollingNode.release()); break; } } } m_stateNodeMap.set(newNodeID, newNode); return newNodeID; }
bool RemoteScrollingCoordinatorTransaction::decode(IPC::ArgumentDecoder& decoder) { int numNodes; if (!decoder.decode(numNodes)) return false; bool hasNewRootNode; if (!decoder.decode(hasNewRootNode)) return false; m_scrollingStateTree = ScrollingStateTree::create(); for (int i = 0; i < numNodes; ++i) { ScrollingNodeType nodeType; if (!decoder.decodeEnum(nodeType)) return false; ScrollingNodeID nodeID; if (!decoder.decode(nodeID)) return false; ScrollingNodeID parentNodeID; if (!decoder.decode(parentNodeID)) return false; m_scrollingStateTree->attachNode(nodeType, nodeID, parentNodeID); ScrollingStateNode* newNode = m_scrollingStateTree->stateNodeForID(nodeID); ASSERT(newNode); ASSERT(!parentNodeID || newNode->parent()); switch (nodeType) { case FrameScrollingNode: case OverflowScrollingNode: if (!decoder.decode(*toScrollingStateScrollingNode(newNode))) return false; break; case FixedNode: if (!decoder.decode(*toScrollingStateFixedNode(newNode))) return false; break; case StickyNode: if (!decoder.decode(*toScrollingStateStickyNode(newNode))) return false; break; } } m_scrollingStateTree->setHasNewRootStateNode(hasNewRootNode); // Removed nodes Vector<ScrollingNodeID> removedNodes; if (!decoder.decode(removedNodes)) return false; if (removedNodes.size()) m_scrollingStateTree->setRemovedNodes(removedNodes); return true; }
void ScrollingCoordinatorCoordinatedGraphics::detachFromStateTree(ScrollingNodeID nodeID) { ScrollingStateNode* node = m_scrollingStateTree->stateNodeForID(nodeID); if (node && node->nodeType() == FixedNode) toCoordinatedGraphicsLayer(node->layer())->setFixedToViewport(false); m_scrollingStateTree->detachNode(nodeID); }
// This copy constructor is used for cloning nodes in the tree, and it doesn't make sense // to clone the relationship pointers, so don't copy that information from the original // node. ScrollingStateNode::ScrollingStateNode(const ScrollingStateNode& stateNode) : m_scrollingStateTree(0) , m_nodeID(stateNode.scrollingNodeID()) , m_changedProperties(stateNode.changedProperties()) , m_parent(0) { // FIXME: why doesn't this set the GraphicsLayer? setScrollPlatformLayer(stateNode.platformScrollLayer()); }
// This copy constructor is used for cloning nodes in the tree, and it doesn't make sense // to clone the relationship pointers, so don't copy that information from the original node. ScrollingStateNode::ScrollingStateNode(const ScrollingStateNode& stateNode, ScrollingStateTree& adoptiveTree) : m_nodeType(stateNode.nodeType()) , m_nodeID(stateNode.scrollingNodeID()) , m_changedProperties(stateNode.changedProperties()) , m_scrollingStateTree(adoptiveTree) , m_parent(nullptr) { if (hasChangedProperty(ScrollLayer)) setLayer(stateNode.layer().toRepresentation(adoptiveTree.preferredLayerRepresentation())); scrollingStateTree().addNode(this); }
void RemoteScrollingCoordinatorProxy::connectStateNodeLayers(ScrollingStateTree& stateTree, const RemoteLayerTreeHost& layerTreeHost) { for (auto it : stateTree.nodeMap()) { ScrollingStateNode* currNode = it.value; switch (currNode->nodeType()) { case ScrollingNode: { ScrollingStateScrollingNode* scrollingStateNode = toScrollingStateScrollingNode(currNode); if (scrollingStateNode->hasChangedProperty(ScrollingStateNode::ScrollLayer)) scrollingStateNode->setLayer(layerTreeHost.getLayer(scrollingStateNode->layer())); if (scrollingStateNode->hasChangedProperty(ScrollingStateScrollingNode::CounterScrollingLayer)) scrollingStateNode->setCounterScrollingLayer(layerTreeHost.getLayer(scrollingStateNode->counterScrollingLayer())); // FIXME: we should never have header and footer layers coming from the WebProcess. if (scrollingStateNode->hasChangedProperty(ScrollingStateScrollingNode::HeaderLayer)) scrollingStateNode->setHeaderLayer(layerTreeHost.getLayer(scrollingStateNode->headerLayer())); if (scrollingStateNode->hasChangedProperty(ScrollingStateScrollingNode::FooterLayer)) scrollingStateNode->setFooterLayer(layerTreeHost.getLayer(scrollingStateNode->footerLayer())); break; } case FixedNode: if (currNode->hasChangedProperty(ScrollingStateNode::ScrollLayer)) currNode->setLayer(layerTreeHost.getLayer(currNode->layer())); break; case StickyNode: if (currNode->hasChangedProperty(ScrollingStateNode::ScrollLayer)) currNode->setLayer(layerTreeHost.getLayer(currNode->layer())); break; } } }
ScrollingNodeID ScrollingStateTree::attachNode(ScrollingNodeType nodeType, ScrollingNodeID newNodeID, ScrollingNodeID parentID) { ASSERT(newNodeID); if (ScrollingStateNode* node = stateNodeForID(newNodeID)) { if (!parentID) return newNodeID; ScrollingStateNode* parent = stateNodeForID(parentID); if (!parent) return newNodeID; if (node->parent() == parent) return newNodeID; // The node is being re-parented. To do that, we'll remove it, and then re-create a new node. removeNodeAndAllDescendants(node, SubframeNodeRemoval::Orphan); } ScrollingStateNode* newNode = nullptr; if (!parentID) { // If we're resetting the root node, we should clear the HashMap and destroy the current children. clear(); setRootStateNode(ScrollingStateFrameScrollingNode::create(*this, newNodeID)); newNode = rootStateNode(); m_hasNewRootStateNode = true; } else { ScrollingStateNode* parent = stateNodeForID(parentID); if (!parent) return 0; if (nodeType == FrameScrollingNode && parentID) { if (RefPtr<ScrollingStateNode> orphanedNode = m_orphanedSubframeNodes.take(newNodeID)) { newNode = orphanedNode.get(); parent->appendChild(orphanedNode.release()); } } if (!newNode) { RefPtr<ScrollingStateNode> stateNode = createNode(nodeType, newNodeID); newNode = stateNode.get(); parent->appendChild(stateNode.release()); } } m_stateNodeMap.set(newNodeID, newNode); m_nodesRemovedSinceLastCommit.remove(newNodeID); return newNodeID; }
void AsyncScrollingCoordinator::syncChildPositions(const LayoutRect& viewportRect) { if (!m_scrollingStateTree->rootStateNode()) return; Vector<OwnPtr<ScrollingStateNode>>* children = m_scrollingStateTree->rootStateNode()->children(); if (!children) return; // FIXME: We'll have to traverse deeper into the tree at some point. size_t size = children->size(); for (size_t i = 0; i < size; ++i) { ScrollingStateNode* child = children->at(i).get(); child->syncLayerPositionForViewportRect(viewportRect); } }
void ScrollingStateNode::cloneAndResetChildren(ScrollingStateNode& clone, ScrollingStateTree& adoptiveTree) { if (!m_children) return; for (auto& child : *m_children) clone.appendChild(child->cloneAndReset(adoptiveTree)); }
bool ArgumentCoder<ScrollingStateNode>::decode(ArgumentDecoder& decoder, ScrollingStateNode& node) { // nodeType, scrollingNodeID and parentNodeID have already been decoded by the caller in order to create the node. ScrollingStateNode::ChangedProperties changedProperties; if (!decoder.decode(changedProperties)) return false; node.setChangedProperties(changedProperties); if (node.hasChangedProperty(ScrollingStateNode::ScrollLayer)) { GraphicsLayer::PlatformLayerID layerID; if (!decoder.decode(layerID)) return false; node.setLayer(layerID); } return true; }
void ScrollingStateTree::removeNodeAndAllDescendants(ScrollingStateNode* node, SubframeNodeRemoval subframeNodeRemoval) { ScrollingStateNode* parent = node->parent(); recursiveNodeWillBeRemoved(node, subframeNodeRemoval); if (node == m_rootStateNode) m_rootStateNode = nullptr; else if (parent) { ASSERT(parent->children() && parent->children()->find(node) != notFound); if (auto children = parent->children()) { size_t index = children->find(node); if (index != notFound) children->remove(index); } } }
static void encodeNodeAndDescendants(IPC::ArgumentEncoder& encoder, const ScrollingStateNode& stateNode) { switch (stateNode.nodeType()) { case FrameScrollingNode: case OverflowScrollingNode: encoder << toScrollingStateScrollingNode(stateNode); break; case FixedNode: encoder << toScrollingStateFixedNode(stateNode); break; case StickyNode: encoder << toScrollingStateStickyNode(stateNode); break; } if (!stateNode.children()) return; for (size_t i = 0; i < stateNode.children()->size(); ++i) { const OwnPtr<ScrollingStateNode>& child = stateNode.children()->at(i); encodeNodeAndDescendants(encoder, *child.get()); } }
void RemoteScrollingTreeTextStream::dump(const ScrollingStateNode& node, bool changedPropertiesOnly) { RemoteScrollingTreeTextStream& ts = *this; ts << "(node " << node.scrollingNodeID(); dumpProperty(ts, "type", node.nodeType()); if (!changedPropertiesOnly || node.hasChangedProperty(ScrollingStateNode::ScrollLayer)) dumpProperty(ts, "layer", static_cast<GraphicsLayer::PlatformLayerID>(node.layer())); switch (node.nodeType()) { case FrameScrollingNode: case OverflowScrollingNode: dump(toScrollingStateScrollingNode(node), changedPropertiesOnly); break; case FixedNode: dump(toScrollingStateFixedNode(node), changedPropertiesOnly); break; case StickyNode: dump(toScrollingStateStickyNode(node), changedPropertiesOnly); break; } }
void ArgumentCoder<ScrollingStateNode>::encode(ArgumentEncoder& encoder, const ScrollingStateNode& node) { encoder.encodeEnum(node.nodeType()); encoder << node.scrollingNodeID(); encoder << node.parentNodeID(); encoder << node.changedProperties(); if (node.hasChangedProperty(ScrollingStateNode::ScrollLayer)) encoder << static_cast<GraphicsLayer::PlatformLayerID>(node.layer()); }