void ScrollingTree::updateTreeFromStateNode(const ScrollingStateNode* stateNode, OrphanScrollingNodeMap& orphanNodes) { if (!stateNode) { m_nodeMap.clear(); m_rootNode = nullptr; return; } ScrollingNodeID nodeID = stateNode->scrollingNodeID(); ScrollingNodeID parentNodeID = stateNode->parentNodeID(); auto it = m_nodeMap.find(nodeID); RefPtr<ScrollingTreeNode> node; if (it != m_nodeMap.end()) node = it->value; else { node = createScrollingTreeNode(stateNode->nodeType(), nodeID); if (!parentNodeID) { // This is the root node. Clear the node map. ASSERT(stateNode->nodeType() == FrameScrollingNode); m_rootNode = node; m_nodeMap.clear(); } m_nodeMap.set(nodeID, node.get()); } if (parentNodeID) { auto parentIt = m_nodeMap.find(parentNodeID); ASSERT_WITH_SECURITY_IMPLICATION(parentIt != m_nodeMap.end()); if (parentIt != m_nodeMap.end()) { ScrollingTreeNode* parent = parentIt->value; node->setParent(parent); parent->appendChild(node); } } node->updateBeforeChildren(*stateNode); // Move all children into the orphanNodes map. Live ones will get added back as we recurse over children. if (auto nodeChildren = node->children()) { for (auto& childScrollingNode : *nodeChildren) { childScrollingNode->setParent(nullptr); orphanNodes.add(childScrollingNode->scrollingNodeID(), childScrollingNode); } nodeChildren->clear(); } // Now update the children if we have any. if (auto children = stateNode->children()) { for (auto& child : *children) updateTreeFromStateNode(child.get(), orphanNodes); } node->updateAfterChildren(*stateNode); }
void ScrollingTree::viewportChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const WebCore::FloatRect& viewportRect, double scale) { ScrollingTreeNode* node = nodeForID(nodeID); if (!node) return; if (!node->isScrollingNode()) return; toScrollingTreeScrollingNode(node)->updateLayersAfterViewportChange(viewportRect, scale); }
void ScrollingTree::removeDestroyedNodes(ScrollingStateTree* stateTree) { const Vector<ScrollingNodeID>& removedNodes = stateTree->removedNodes(); size_t size = removedNodes.size(); for (size_t i = 0; i < size; ++i) { ScrollingTreeNode* node = m_nodeMap.take(removedNodes[i]); // Never destroy the root node. There will be a new root node in the state tree, and we will // associate it with our existing root node in updateTreeFromStateNode(). if (node && node->parent()) m_rootNode->removeChild(node); } }
void ScrollingTree::scrollPositionChangedViaDelegatedScrolling(ScrollingNodeID nodeID, const WebCore::FloatPoint& scrollPosition) { ScrollingTreeNode* node = nodeForID(nodeID); if (!node) return; if (node->nodeType() != OverflowScrollingNode) return; // Update descendant nodes toScrollingTreeScrollingNode(node)->updateLayersAfterDelegatedScroll(scrollPosition); // Update GraphicsLayers and scroll state. scrollingTreeNodeDidScroll(nodeID, scrollPosition); }
void ScrollingTree::removeDestroyedNodes(const ScrollingStateTree& stateTree) { for (const auto& removedNode : stateTree.removedNodes()) { ScrollingTreeNode* node = m_nodeMap.take(removedNode); if (!node) continue; if (node->scrollingNodeID() == m_latchedNode) clearLatchedNode(); // Never destroy the root node. There will be a new root node in the state tree, and we will // associate it with our existing root node in updateTreeFromStateNode(). if (node->parent()) m_rootNode->removeChild(node); } }
void ScrollingTree::updateTreeFromStateNode(ScrollingStateNode* stateNode) { // This fuction recurses through the ScrollingStateTree and updates the corresponding ScrollingTreeNodes. // Find the ScrollingTreeNode associated with the current stateNode using the shared ID and our HashMap. ScrollingTreeNodeMap::const_iterator it = m_nodeMap.find(stateNode->scrollingNodeID()); if (it != m_nodeMap.end()) { ScrollingTreeNode* node = it->value; node->update(stateNode); } else { // If the node isn't found, it's either new and needs to be added to the tree, or there is a new ID for our // root node. ScrollingNodeID nodeID = stateNode->scrollingNodeID(); if (!stateNode->parent()) { // This is the root node. if (!m_rootNode) m_rootNode = ScrollingTreeScrollingNode::create(this, nodeID); m_nodeMap.set(nodeID, m_rootNode.get()); m_rootNode->update(stateNode); } else { OwnPtr<ScrollingTreeNode> newNode; if (stateNode->isScrollingNode()) newNode = ScrollingTreeScrollingNode::create(this, nodeID); else if (stateNode->isFixedNode()) newNode = ScrollingTreeFixedNode::create(this, nodeID); else if (stateNode->isStickyNode()) newNode = ScrollingTreeStickyNode::create(this, nodeID); else ASSERT_NOT_REACHED(); ScrollingTreeNode* newNodeRawPtr = newNode.get(); m_nodeMap.set(nodeID, newNodeRawPtr); ScrollingTreeNodeMap::const_iterator it = m_nodeMap.find(stateNode->parent()->scrollingNodeID()); ASSERT(it != m_nodeMap.end()); if (it != m_nodeMap.end()) { ScrollingTreeNode* parent = it->value; newNode->setParent(parent); parent->appendChild(newNode.release()); } newNodeRawPtr->update(stateNode); } } // Now update the children if we have any. Vector<OwnPtr<ScrollingStateNode> >* stateNodeChildren = stateNode->children(); if (!stateNodeChildren) return; size_t size = stateNodeChildren->size(); for (size_t i = 0; i < size; ++i) updateTreeFromStateNode(stateNodeChildren->at(i).get()); }
void ScrollingTree::updateTreeFromStateNode(const ScrollingStateNode* stateNode) { if (!stateNode) { m_nodeMap.clear(); m_rootNode = nullptr; return; } // This fuction recurses through the ScrollingStateTree and updates the corresponding ScrollingTreeNodes. // Find the ScrollingTreeNode associated with the current stateNode using the shared ID and our HashMap. ScrollingTreeNodeMap::const_iterator it = m_nodeMap.find(stateNode->scrollingNodeID()); ScrollingTreeNode* node; if (it != m_nodeMap.end()) { node = it->value; node->updateBeforeChildren(*stateNode); } else { // If the node isn't found, it's either new and needs to be added to the tree, or there is a new ID for our // root node. ScrollingNodeID nodeID = stateNode->scrollingNodeID(); if (!stateNode->parent()) { // This is the root node. Nuke the node map. m_nodeMap.clear(); m_rootNode = static_pointer_cast<ScrollingTreeScrollingNode>(createNode(FrameScrollingNode, nodeID)); m_nodeMap.set(nodeID, m_rootNode.get()); m_rootNode->updateBeforeChildren(*stateNode); node = m_rootNode.get(); } else { OwnPtr<ScrollingTreeNode> newNode = createNode(stateNode->nodeType(), nodeID); node = newNode.get(); m_nodeMap.set(nodeID, node); ScrollingTreeNodeMap::const_iterator it = m_nodeMap.find(stateNode->parent()->scrollingNodeID()); ASSERT(it != m_nodeMap.end()); if (it != m_nodeMap.end()) { ScrollingTreeNode* parent = it->value; newNode->setParent(parent); parent->appendChild(newNode.release()); } node->updateBeforeChildren(*stateNode); } } // Now update the children if we have any. Vector<OwnPtr<ScrollingStateNode>>* stateNodeChildren = stateNode->children(); if (stateNodeChildren) { size_t size = stateNodeChildren->size(); for (size_t i = 0; i < size; ++i) updateTreeFromStateNode(stateNodeChildren->at(i).get()); } node->updateAfterChildren(*stateNode); }
void ScrollingTree::updateTreeFromStateNode(ScrollingStateNode* stateNode) { // This fuction recurses through the ScrollingStateTree and updates the corresponding ScrollingTreeNodes. // Find the ScrollingTreeNode associated with the current stateNode using the shared ID and our HashMap. ScrollingTreeNodeMap::const_iterator it = m_nodeMap.find(stateNode->scrollingNodeID()); if (it != m_nodeMap.end()) { ScrollingTreeNode* node = it->value; node->update(stateNode); } else { // If the node isn't found, it's either new and needs to be added to the tree, or there is a new ID for our // root node. if (!stateNode->parent()) { // This is the root node. m_rootNode->setScrollingNodeID(stateNode->scrollingNodeID()); m_nodeMap.set(stateNode->scrollingNodeID(), m_rootNode.get()); m_rootNode->update(stateNode); } else { // FIXME: In the future, we will have more than just ScrollingTreeScrollingNode, so we'll have to // figure out which type of node to create. OwnPtr<ScrollingTreeNode> newNode = ScrollingTreeScrollingNode::create(this); ScrollingTreeNode* newNodeRawPtr = newNode.get(); m_nodeMap.set(stateNode->scrollingNodeID(), newNodeRawPtr); ScrollingTreeNodeMap::const_iterator it = m_nodeMap.find(stateNode->parent()->scrollingNodeID()); ASSERT(it != m_nodeMap.end()); if (it != m_nodeMap.end()) { ScrollingTreeNode* parent = it->value; newNode->setParent(parent); parent->appendChild(newNode.release()); } newNodeRawPtr->update(stateNode); } } // Now update the children if we have any. Vector<OwnPtr<ScrollingStateNode> >* stateNodeChildren = stateNode->children(); if (!stateNodeChildren) return; size_t size = stateNodeChildren->size(); for (size_t i = 0; i < size; ++i) updateTreeFromStateNode(stateNodeChildren->at(i).get()); }