1 /* 2 * Copyright (C) 2003, 2009, 2012 Apple Inc. All rights reserved. 3 * Copyright (C) 2013 Intel Corporation. All rights reserved. 4 * 5 * Portions are Copyright (C) 1998 Netscape Communications Corporation. 6 * 7 * Other contributors: 8 * Robert O'Callahan <roc+@cs.cmu.edu> 9 * David Baron <dbaron (at) fas.harvard.edu> 10 * Christian Biesinger <cbiesinger (at) web.de> 11 * Randall Jesup <rjesup (at) wgate.com> 12 * Roland Mainz <roland.mainz (at) informatik.med.uni-giessen.de> 13 * Josh Soref <timeless (at) mac.com> 14 * Boris Zbarsky <bzbarsky (at) mit.edu> 15 * 16 * This library is free software; you can redistribute it and/or 17 * modify it under the terms of the GNU Lesser General Public 18 * License as published by the Free Software Foundation; either 19 * version 2.1 of the License, or (at your option) any later version. 20 * 21 * This library is distributed in the hope that it will be useful, 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 * Lesser General Public License for more details. 25 * 26 * You should have received a copy of the GNU Lesser General Public 27 * License along with this library; if not, write to the Free Software 28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 29 * 30 * Alternatively, the contents of this file may be used under the terms 31 * of either the Mozilla Public License Version 1.1, found at 32 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public 33 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html 34 * (the "GPL"), in which case the provisions of the MPL or the GPL are 35 * applicable instead of those above. If you wish to allow use of your 36 * version of this file only under the terms of one of those two 37 * licenses (the MPL or the GPL) and not to allow others to use your 38 * version of this file under the LGPL, indicate your decision by 39 * deletingthe provisions above and replace them with the notice and 40 * other provisions required by the MPL or the GPL, as the case may be. 41 * If you do not delete the provisions above, a recipient may use your 42 * version of this file under any of the LGPL, the MPL or the GPL. 43 */ 44 45 #ifndef RenderLayerStackingNode_h 46 #define RenderLayerStackingNode_h 47 48 #include "core/rendering/RenderLayerModelObject.h" 49 #include "wtf/Noncopyable.h" 50 #include "wtf/OwnPtr.h" 51 #include "wtf/Vector.h" 52 53 namespace WebCore { 54 55 class RenderLayer; 56 class RenderLayerCompositor; 57 class RenderStyle; 58 59 class RenderLayerStackingNode { 60 WTF_MAKE_NONCOPYABLE(RenderLayerStackingNode); 61 public: 62 explicit RenderLayerStackingNode(RenderLayer*); 63 ~RenderLayerStackingNode(); 64 65 int zIndex() const { return renderer()->style()->zIndex(); } 66 67 // A stacking context is a layer that has a non-auto z-index. 68 bool isStackingContext() const { return isStackingContext(renderer()->style()); } 69 70 // A stacking container can have z-order lists. All stacking contexts are 71 // stacking containers, but the converse is not true. Layers that use 72 // composited scrolling are stacking containers, but they may not 73 // necessarily be stacking contexts. 74 bool isStackingContainer() const { return isStackingContext() || needsToBeStackingContainer(); } 75 76 bool setNeedsToBeStackingContainer(bool); 77 78 // Returns true if z ordering would not change if this layer were a stacking container. 79 bool descendantsAreContiguousInStackingOrder() const; 80 void setDescendantsAreContiguousInStackingOrderDirty(bool flag) { m_descendantsAreContiguousInStackingOrderDirty = flag; } 81 void updateDescendantsAreContiguousInStackingOrder(); 82 83 // Update our normal and z-index lists. 84 void updateLayerListsIfNeeded(); 85 86 bool zOrderListsDirty() const { return m_zOrderListsDirty; } 87 void dirtyZOrderLists(); 88 void updateZOrderLists(); 89 void clearZOrderLists(); 90 void dirtyStackingContainerZOrderLists(); 91 92 bool hasPositiveZOrderList() const { return posZOrderList() && posZOrderList()->size(); } 93 bool hasNegativeZOrderList() const { return negZOrderList() && negZOrderList()->size(); } 94 95 bool isNormalFlowOnly() const { return m_isNormalFlowOnly; } 96 void updateIsNormalFlowOnly(); 97 bool normalFlowListDirty() const { return m_normalFlowListDirty; } 98 void dirtyNormalFlowList(); 99 100 enum PaintOrderListType {BeforePromote, AfterPromote}; 101 void computePaintOrderList(PaintOrderListType, Vector<RefPtr<Node> >&); 102 103 void updateStackingNodesAfterStyleChange(const RenderStyle* oldStyle); 104 105 RenderLayerStackingNode* ancestorStackingContainerNode() const; 106 RenderLayerStackingNode* ancestorStackingNode() const; 107 108 // Gets the enclosing stacking container for this node, possibly the node 109 // itself, if it is a stacking container. 110 RenderLayerStackingNode* enclosingStackingContainerNode() { return isStackingContainer() ? this : ancestorStackingContainerNode(); } 111 112 RenderLayer* layer() const { return m_layer; } 113 114 #if !ASSERT_DISABLED 115 bool layerListMutationAllowed() const { return m_layerListMutationAllowed; } 116 void setLayerListMutationAllowed(bool flag) { m_layerListMutationAllowed = flag; } 117 #endif 118 119 private: 120 friend class RenderLayerStackingNodeIterator; 121 friend class RenderLayerStackingNodeReverseIterator; 122 friend class RenderTreeAsText; 123 124 Vector<RenderLayerStackingNode*>* posZOrderList() const 125 { 126 ASSERT(!m_zOrderListsDirty); 127 ASSERT(isStackingContainer() || !m_posZOrderList); 128 return m_posZOrderList.get(); 129 } 130 131 Vector<RenderLayerStackingNode*>* normalFlowList() const 132 { 133 ASSERT(!m_normalFlowListDirty); 134 return m_normalFlowList.get(); 135 } 136 137 Vector<RenderLayerStackingNode*>* negZOrderList() const 138 { 139 ASSERT(!m_zOrderListsDirty); 140 ASSERT(isStackingContainer() || !m_negZOrderList); 141 return m_negZOrderList.get(); 142 } 143 144 enum CollectLayersBehavior { 145 ForceLayerToStackingContainer, 146 OverflowScrollCanBeStackingContainers, 147 OnlyStackingContextsCanBeStackingContainers 148 }; 149 150 bool isStackingContext(const RenderStyle*) const; 151 152 void rebuildZOrderLists(); 153 154 // layerToForceAsStackingContainer allows us to build pre-promotion and 155 // post-promotion layer lists, by allowing us to treat a layer as if it is a 156 // stacking context, without adding a new member to RenderLayer or modifying 157 // the style (which could cause extra allocations). 158 void rebuildZOrderLists(OwnPtr<Vector<RenderLayerStackingNode*> >&, OwnPtr<Vector<RenderLayerStackingNode*> >&, 159 const RenderLayerStackingNode* nodeToForceAsStackingContainer = 0, 160 CollectLayersBehavior = OverflowScrollCanBeStackingContainers); 161 162 void collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >&, 163 OwnPtr<Vector<RenderLayerStackingNode*> >&, const RenderLayerStackingNode* nodeToForceAsStackingContainer = 0, 164 CollectLayersBehavior = OverflowScrollCanBeStackingContainers); 165 166 #if !ASSERT_DISABLED 167 bool isInStackingParentZOrderLists() const; 168 bool isInStackingParentNormalFlowList() const; 169 void updateStackingParentForZOrderLists(RenderLayerStackingNode* stackingParent); 170 void updateStackingParentForNormalFlowList(RenderLayerStackingNode* stackingParent); 171 void setStackingParent(RenderLayerStackingNode* stackingParent) { m_stackingParent = stackingParent; } 172 #endif 173 174 bool shouldBeNormalFlowOnly() const; 175 bool shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const; 176 177 void updateNormalFlowList(); 178 void dirtyNormalFlowListCanBePromotedToStackingContainer(); 179 180 void dirtySiblingStackingNodeCanBePromotedToStackingContainer(); 181 182 void collectBeforePromotionZOrderList(RenderLayerStackingNode*, 183 OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList); 184 void collectAfterPromotionZOrderList(RenderLayerStackingNode*, 185 OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList); 186 187 bool isDirtyStackingContainer() const { return m_zOrderListsDirty && isStackingContainer(); } 188 189 bool needsToBeStackingContainer() const; 190 191 RenderLayerCompositor* compositor() const; 192 // FIXME: Investigate changing this to Renderbox. 193 RenderLayerModelObject* renderer() const; 194 195 RenderLayer* m_layer; 196 197 // For stacking contexts, m_posZOrderList holds a sorted list of all the 198 // descendant nodes within the stacking context that have z-indices of 0 or greater 199 // (auto will count as 0). m_negZOrderList holds descendants within our stacking context with negative 200 // z-indices. 201 OwnPtr<Vector<RenderLayerStackingNode*> > m_posZOrderList; 202 OwnPtr<Vector<RenderLayerStackingNode*> > m_negZOrderList; 203 204 // This list contains child nodes that cannot create stacking contexts. For now it is just 205 // overflow layers, but that may change in the future. 206 OwnPtr<Vector<RenderLayerStackingNode*> > m_normalFlowList; 207 208 // If this is true, then no non-descendant appears between any of our 209 // descendants in stacking order. This is one of the requirements of being 210 // able to safely become a stacking context. 211 unsigned m_descendantsAreContiguousInStackingOrder : 1; 212 unsigned m_descendantsAreContiguousInStackingOrderDirty : 1; 213 214 unsigned m_zOrderListsDirty : 1; 215 unsigned m_normalFlowListDirty: 1; 216 unsigned m_isNormalFlowOnly : 1; 217 218 unsigned m_needsToBeStackingContainer : 1; 219 unsigned m_needsToBeStackingContainerHasBeenRecorded : 1; 220 221 #if !ASSERT_DISABLED 222 unsigned m_layerListMutationAllowed : 1; 223 RenderLayerStackingNode* m_stackingParent; 224 #endif 225 }; 226 227 inline void RenderLayerStackingNode::clearZOrderLists() 228 { 229 ASSERT(!isStackingContainer()); 230 231 #if !ASSERT_DISABLED 232 updateStackingParentForZOrderLists(0); 233 #endif 234 235 m_posZOrderList.clear(); 236 m_negZOrderList.clear(); 237 } 238 239 inline void RenderLayerStackingNode::updateZOrderLists() 240 { 241 if (!m_zOrderListsDirty) 242 return; 243 244 if (!isStackingContainer()) { 245 clearZOrderLists(); 246 m_zOrderListsDirty = false; 247 return; 248 } 249 250 rebuildZOrderLists(); 251 } 252 253 #if !ASSERT_DISABLED 254 class LayerListMutationDetector { 255 public: 256 explicit LayerListMutationDetector(RenderLayerStackingNode* stackingNode) 257 : m_stackingNode(stackingNode) 258 , m_previousMutationAllowedState(stackingNode->layerListMutationAllowed()) 259 { 260 m_stackingNode->setLayerListMutationAllowed(false); 261 } 262 263 ~LayerListMutationDetector() 264 { 265 m_stackingNode->setLayerListMutationAllowed(m_previousMutationAllowedState); 266 } 267 268 private: 269 RenderLayerStackingNode* m_stackingNode; 270 bool m_previousMutationAllowedState; 271 }; 272 #endif 273 274 } // namespace WebCore 275 276 #endif // RenderLayerStackingNode_h 277