1 /*
2  * Copyright (C) 2003 Apple Computer, Inc.
3  *
4  * Portions are Copyright (C) 1998 Netscape Communications Corporation.
5  *
6  * Other contributors:
7  *   Robert O'Callahan <roc+@cs.cmu.edu>
8  *   David Baron <dbaron@fas.harvard.edu>
9  *   Christian Biesinger <cbiesinger@web.de>
10  *   Randall Jesup <rjesup@wgate.com>
11  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
12  *   Josh Soref <timeless@mac.com>
13  *   Boris Zbarsky <bzbarsky@mit.edu>
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2.1 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28  *
29  * Alternatively, the contents of this file may be used under the terms
30  * of either the Mozilla Public License Version 1.1, found at
31  * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
32  * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
33  * (the "GPL"), in which case the provisions of the MPL or the GPL are
34  * applicable instead of those above.  If you wish to allow use of your
35  * version of this file only under the terms of one of those two
36  * licenses (the MPL or the GPL) and not to allow others to use your
37  * version of this file under the LGPL, indicate your decision by
38  * deletingthe provisions above and replace them with the notice and
39  * other provisions required by the MPL or the GPL, as the case may be.
40  * If you do not delete the provisions above, a recipient may use your
41  * version of this file under any of the LGPL, the MPL or the GPL.
42  */
43 
44 #ifndef render_layer_h
45 #define render_layer_h
46 
47 #include <QColor>
48 #include <QRect>
49 #include <assert.h>
50 
51 #include "render_object.h"
52 
53 //template <class T*> class QVector;
54 
55 namespace khtml
56 {
57 class RenderObject;
58 class RenderScrollMediator;
59 class ScrollBarWidget;
60 
61 class RenderScrollMediator: public QObject
62 {
63     Q_OBJECT
64 public:
RenderScrollMediator(RenderLayer * layer)65     RenderScrollMediator(RenderLayer *layer)
66         : m_layer(layer), m_waitingForUpdate(false) {}
67 
68 public Q_SLOTS:
69     void slotValueChanged();
70 
71 private:
72     RenderLayer *m_layer;
73     bool m_waitingForUpdate;
74 };
75 
76 // This class handles the auto-scrolling of layers with overflow: marquee.
77 class Marquee: public QObject
78 {
79     Q_OBJECT
80 
81 public:
82     Marquee(RenderLayer *l);
83 
84     void timerEvent(QTimerEvent *) override;
85 
speed()86     int speed() const
87     {
88         return m_speed;
89     }
90     int marqueeSpeed() const;
91     EMarqueeDirection direction() const;
reverseDirection()92     EMarqueeDirection reverseDirection() const
93     {
94         return static_cast<EMarqueeDirection>(-direction());
95     }
96     bool isHorizontal() const;
97     bool isUnfurlMarquee() const;
unfurlPos()98     int unfurlPos() const
99     {
100         return m_unfurlPos;
101     }
102 
whiteSpace()103     EWhiteSpace whiteSpace()
104     {
105         return KDE_CAST_BF_ENUM(EWhiteSpace, m_whiteSpace);
106     }
107 
108     int computePosition(EMarqueeDirection dir, bool stopAtClientEdge);
109 
setEnd(int end)110     void setEnd(int end)
111     {
112         m_end = end;
113     }
114 
115     void start();
116     void suspend();
117     void stop();
118 
119     void updateMarqueeStyle();
120     void updateMarqueePosition();
121 
122 private:
123     RenderLayer *m_layer;
124     int m_currentLoop;
125     int m_totalLoops;
126     int m_timerId;
127     int m_start;
128     int m_end;
129     int m_speed;
130     int m_unfurlPos;
131     bool m_reset: 1;
132     bool m_suspended: 1;
133     bool m_stopped: 1;
134     KDE_BF_ENUM(EWhiteSpace) m_whiteSpace : 3;
135     KDE_BF_ENUM(EMarqueeDirection) m_direction : 4;
136 };
137 
138 class RenderLayer
139 {
140 public:
141     static ScrollBarWidget *gScrollBar;
142 
143     RenderLayer(RenderObject *object);
144     ~RenderLayer();
145 
renderer()146     RenderObject *renderer() const
147     {
148         return m_object;
149     }
parent()150     RenderLayer *parent() const
151     {
152         return m_parent;
153     }
previousSibling()154     RenderLayer *previousSibling() const
155     {
156         return m_previous;
157     }
nextSibling()158     RenderLayer *nextSibling() const
159     {
160         return m_next;
161     }
162 
firstChild()163     RenderLayer *firstChild() const
164     {
165         return m_first;
166     }
lastChild()167     RenderLayer *lastChild() const
168     {
169         return m_last;
170     }
171 
172     void addChild(RenderLayer *newChild, RenderLayer *beforeChild = nullptr);
173     RenderLayer *removeChild(RenderLayer *oldChild);
174 
175     void removeOnlyThisLayer();
176     void insertOnlyThisLayer();
177 
178     void styleChanged();
179 
marquee()180     Marquee *marquee() const
181     {
182         return m_marquee;
183     }
184     void suspendMarquees();
185 
isOverflowOnly()186     bool isOverflowOnly() const
187     {
188         return m_isOverflowOnly;
189     }
190 
191     bool isTransparent() const;
192     RenderLayer *transparentAncestor() const;
193 
root()194     RenderLayer *root()
195     {
196         RenderLayer *curr = this;
197         while (curr->parent()) {
198             curr = curr->parent();
199         }
200         return curr;
201     }
202 
xPos()203     int xPos() const
204     {
205         return m_x;
206     }
yPos()207     int yPos() const
208     {
209         return m_y;
210     }
211 
212     int width() const;
213     int height() const;
214 
scrollWidth()215     int scrollWidth() const
216     {
217         return m_scrollWidth;
218     }
scrollHeight()219     int scrollHeight() const
220     {
221         return m_scrollHeight;
222     }
223 
resize(int w,int h)224     void resize(int w, int h)
225     {
226         m_scrollWidth = w; m_scrollHeight = h;
227     }
228 
setPos(int xPos,int yPos)229     void setPos(int xPos, int yPos)
230     {
231         m_x = xPos;
232         m_y = yPos;
233     }
234 
235     // Scrolling methods for layers that can scroll their overflow.
236     void scrollOffset(int &x, int &y);
237     void subtractScrollOffset(int &x, int &y);
238     void checkInlineRelOffset(const RenderObject *o, int &x, int &y);
scrollXOffset()239     int scrollXOffset()
240     {
241         return m_scrollX + m_scrollXOrigin;
242     }
scrollYOffset()243     int scrollYOffset()
244     {
245         return m_scrollY;
246     }
247     void scrollToOffset(int x, int y, bool updateScrollbars = true, bool repaint = true, bool dispatchEvent = true);
scrollToXOffset(int x)248     void scrollToXOffset(int x)
249     {
250         scrollToOffset(x, m_scrollY);
251     }
scrollToYOffset(int y)252     void scrollToYOffset(int y)
253     {
254         scrollToOffset(m_scrollX + m_scrollXOrigin, y);
255     }
resetXOffset()256     void resetXOffset()
257     {
258         scrollToOffset(0, m_scrollY, false, false, false);
259     }
resetYOffset()260     void resetYOffset()
261     {
262         scrollToOffset(m_scrollX + m_scrollXOrigin, 0, false, false, false);
263     }
264     void showScrollbar(Qt::Orientation, bool);
horizontalScrollbar()265     ScrollBarWidget *horizontalScrollbar()
266     {
267         return m_hBar;
268     }
verticalScrollbar()269     ScrollBarWidget *verticalScrollbar()
270     {
271         return m_vBar;
272     }
273     bool hasReversedScrollbar() const;
274     int verticalScrollbarWidth();
275     int horizontalScrollbarHeight();
276     void positionScrollbars(const QRect &damageRect);
277     void paintScrollbars(RenderObject::PaintInfo &pI);
278     void checkScrollbarsAfterLayout();
279     void slotValueChanged(int);
280     void repaint(Priority p = NormalPriority, bool markForRepaint = false);
281     void updateScrollPositionFromScrollbars();
282 
283     void updateLayerPosition();
284     void updateLayerPositions(RenderLayer *rootLayer, bool doFullRepaint = false, bool checkForRepaint = false);
285 
286     // Get the enclosing stacking context for this layer.  A stacking context is a layer
287     // that has a non-auto z-index.
288     RenderLayer *stackingContext() const;
isStackingContext()289     bool isStackingContext() const
290     {
291         return !hasAutoZIndex() || renderer()->isCanvas();
292     }
293 
294     void dirtyZOrderLists();
295     void updateZOrderLists();
posZOrderList()296     QVector<RenderLayer *> *posZOrderList() const
297     {
298         return m_posZOrderList;
299     }
negZOrderList()300     QVector<RenderLayer *> *negZOrderList() const
301     {
302         return m_negZOrderList;
303     }
304 
305     void dirtyOverflowList();
306     void updateOverflowList();
overflowList()307     QVector<RenderLayer *> *overflowList() const
308     {
309         return m_overflowList;
310     }
311 
hasVisibleContent()312     bool hasVisibleContent() const
313     {
314         return m_hasVisibleContent;
315     }
316     void setHasVisibleContent(bool b);
317     void dirtyVisibleContentStatus();
318 
319     void setHasOverlaidWidgets(bool b = true)
320     {
321         m_hasOverlaidWidgets = b;
322     }
hasOverlaidWidgets()323     bool hasOverlaidWidgets() const
324     {
325         return m_hasOverlaidWidgets;
326     }
getMask()327     QRegion getMask() const
328     {
329         return m_region;
330     }
331     QRegion paintedRegion(RenderLayer *rootLayer);
332     void updateWidgetMasks(RenderLayer *rootLayer);
333 
334     // Gets the nearest enclosing positioned ancestor layer (also includes
335     // the <html> layer and the root layer).
336     RenderLayer *enclosingPositionedAncestor() const;
337 
338     void convertToLayerCoords(const RenderLayer *ancestorLayer, int &x, int &y) const;
339 
hasAutoZIndex()340     bool hasAutoZIndex() const
341     {
342         return renderer()->style()->hasAutoZIndex();
343     }
zIndex()344     int zIndex() const
345     {
346         return renderer()->style()->zIndex();
347     }
348 
349     // The two main functions that use the layer system.  The paint method
350     // paints the layers that intersect the damage rect from back to
351     // front.  The nodeAtPoint method looks for mouse events by walking
352     // layers that intersect the point from front to back.
353     KHTML_EXPORT void paint(QPainter *p, const QRect &damageRect, bool selectionOnly = false);
354     bool nodeAtPoint(RenderObject::NodeInfo &info, int x, int y);
355 
356     // This method figures out our layerBounds in coordinates relative to
357     // |rootLayer}.  It also computes our background and foreground clip rects
358     // for painting/event handling.
359     void calculateRects(const RenderLayer *rootLayer, const QRect &paintDirtyRect, QRect &layerBounds,
360                         QRect &backgroundRect, QRect &foregroundRect);
361     void calculateClipRects(const RenderLayer *rootLayer, QRect &overflowClipRect,
362                             QRect &posClipRect, QRect &fixedClipRect);
363 
364     bool intersectsDamageRect(const QRect &layerBounds, const QRect &damageRect) const;
365     bool containsPoint(int x, int y, const QRect &damageRect) const;
366 
367     void updateHoverActiveState(RenderObject::NodeInfo &info);
368 
369     void detach(RenderArena *renderArena);
370 
371 #ifdef ENABLE_DUMP
372     KHTML_EXPORT void dump(QTextStream &stream, const QString &ind = QString());
373 #endif
374 
375     // Overloaded new operator.  Derived classes must override operator new
376     // in order to allocate out of the RenderArena.
377     void *operator new(size_t sz, RenderArena *renderArena) throw();
378 
379     // Overridden to prevent the normal delete from being called.
380     void operator delete(void *ptr, size_t sz);
381 
382 private:
383     // The normal operator new is disallowed on all render objects.
384     void *operator new(size_t sz) throw();
385 
386 private:
setNextSibling(RenderLayer * next)387     void setNextSibling(RenderLayer *next)
388     {
389         m_next = next;
390     }
setPreviousSibling(RenderLayer * prev)391     void setPreviousSibling(RenderLayer *prev)
392     {
393         m_previous = prev;
394     }
setParent(RenderLayer * parent)395     void setParent(RenderLayer *parent)
396     {
397         m_parent = parent;
398     }
setFirstChild(RenderLayer * first)399     void setFirstChild(RenderLayer *first)
400     {
401         m_first = first;
402     }
setLastChild(RenderLayer * last)403     void setLastChild(RenderLayer *last)
404     {
405         m_last = last;
406     }
407 
408     void collectLayers(QVector<RenderLayer *> *&, QVector<RenderLayer *> *&);
409 
410     KHTML_EXPORT void paintLayer(RenderLayer *rootLayer, QPainter *p, const QRect &paintDirtyRect, bool selectionOnly = false);
411     RenderLayer *nodeAtPointForLayer(RenderLayer *rootLayer, RenderObject::NodeInfo &info,
412                                      int x, int y, const QRect &hitTestRect);
413     bool shouldBeOverflowOnly() const;
414 
415     void childVisibilityChanged(bool newVisibility);
416     void dirtyVisibleDescendantStatus();
417     void updateVisibilityStatus();
418 
419 protected:
420     void setClip(QPainter *p, const QRect &paintDirtyRect, const QRect &clipRect, bool setup = false);
421     void restoreClip(QPainter *p, const QRect &paintDirtyRect, const QRect &clipRect, bool cleanup = false);
422 
423     RenderObject *m_object;
424 
425     RenderLayer *m_parent;
426     RenderLayer *m_previous;
427     RenderLayer *m_next;
428 
429     RenderLayer *m_first;
430     RenderLayer *m_last;
431 
432     // Our (x,y) coordinates are in our parent layer's coordinate space.
433     int m_x;
434     int m_y;
435 
436     // Our scroll offsets if the view is scrolled.
437     int m_scrollX;
438     int m_scrollY;
439 
440     // the reference for our x offset (will vary depending on layout direction)
441     int m_scrollXOrigin;
442 
443     // The width/height of our scrolled area.
444     int m_scrollWidth;
445     int m_scrollHeight;
446 
447     // For layers with overflow, we have a pair of scrollbars.
448     ScrollBarWidget *m_hBar;
449     ScrollBarWidget *m_vBar;
450     QPixmap *m_buffer[2];
451 
452     RenderScrollMediator *m_scrollMediator;
453 
454     // For layers that establish stacking contexts, m_posZOrderList holds a sorted list of all the
455     // descendant layers within the stacking context that have z-indices of 0 or greater
456     // (auto will count as 0).  m_negZOrderList holds descendants within our stacking context with negative
457     // z-indices.
458     QVector<RenderLayer *> *m_posZOrderList;
459     QVector<RenderLayer *> *m_negZOrderList;
460 
461     // This list contains our overflow child layers.
462     QVector<RenderLayer *> *m_overflowList;
463 
464     bool m_zOrderListsDirty: 1;
465     bool m_overflowListDirty: 1;
466     bool m_isOverflowOnly: 1;
467     bool m_markedForRepaint: 1;
468     bool m_hasOverlaidWidgets: 1;
469     bool m_visibleContentStatusDirty : 1;
470     bool m_hasVisibleContent : 1;
471     bool m_visibleDescendantStatusDirty : 1;
472     bool m_hasVisibleDescendant : 1;
473     bool m_inScrollbarRelayout : 1;
474     bool m_wasStackingContext : 1; // set to 1 when last style application
475     // establised us as a stacking context
476 
477     QRect m_visibleRect;
478 
479     QRegion m_region; // used by overlaid (non z-order aware) widgets
480 
481     Marquee *m_marquee; // Used by layers with overflow:marquee
482 };
483 
484 } // namespace
485 #endif
486