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