• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@fas.harvard.edu>
10  *   Christian Biesinger <cbiesinger@web.de>
11  *   Randall Jesup <rjesup@wgate.com>
12  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
13  *   Josh Soref <timeless@mac.com>
14  *   Boris Zbarsky <bzbarsky@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 
zIndex()65     int zIndex() const { return renderer()->style()->zIndex(); }
66 
67     // A stacking context is a layer that has a non-auto z-index.
isStackingContext()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.
isStackingContainer()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;
setDescendantsAreContiguousInStackingOrderDirty(bool flag)80     void setDescendantsAreContiguousInStackingOrderDirty(bool flag) { m_descendantsAreContiguousInStackingOrderDirty = flag; }
81     void updateDescendantsAreContiguousInStackingOrder();
82 
83     // Update our normal and z-index lists.
84     void updateLayerListsIfNeeded();
85 
zOrderListsDirty()86     bool zOrderListsDirty() const { return m_zOrderListsDirty; }
87     void dirtyZOrderLists();
88     void updateZOrderLists();
89     void clearZOrderLists();
90     void dirtyStackingContainerZOrderLists();
91 
hasPositiveZOrderList()92     bool hasPositiveZOrderList() const { return posZOrderList() && posZOrderList()->size(); }
hasNegativeZOrderList()93     bool hasNegativeZOrderList() const { return negZOrderList() && negZOrderList()->size(); }
94 
isNormalFlowOnly()95     bool isNormalFlowOnly() const { return m_isNormalFlowOnly; }
96     void updateIsNormalFlowOnly();
normalFlowListDirty()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.
enclosingStackingContainerNode()110     RenderLayerStackingNode* enclosingStackingContainerNode() { return isStackingContainer() ? this : ancestorStackingContainerNode(); }
111 
layer()112     RenderLayer* layer() const { return m_layer; }
113 
114 #if !ASSERT_DISABLED
layerListMutationAllowed()115     bool layerListMutationAllowed() const { return m_layerListMutationAllowed; }
setLayerListMutationAllowed(bool flag)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 
posZOrderList()124     Vector<RenderLayerStackingNode*>* posZOrderList() const
125     {
126         ASSERT(!m_zOrderListsDirty);
127         ASSERT(isStackingContainer() || !m_posZOrderList);
128         return m_posZOrderList.get();
129     }
130 
normalFlowList()131     Vector<RenderLayerStackingNode*>* normalFlowList() const
132     {
133         ASSERT(!m_normalFlowListDirty);
134         return m_normalFlowList.get();
135     }
136 
negZOrderList()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);
setStackingParent(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 
isDirtyStackingContainer()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 
clearZOrderLists()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 
updateZOrderLists()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:
LayerListMutationDetector(RenderLayerStackingNode * stackingNode)256     explicit LayerListMutationDetector(RenderLayerStackingNode* stackingNode)
257         : m_stackingNode(stackingNode)
258         , m_previousMutationAllowedState(stackingNode->layerListMutationAllowed())
259     {
260         m_stackingNode->setLayerListMutationAllowed(false);
261     }
262 
~LayerListMutationDetector()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