File indexing completed on 2024-04-28 15:24:05

0001 /*
0002  * Copyright (C) 2003 Apple Computer, Inc.
0003  *
0004  * Portions are Copyright (C) 1998 Netscape Communications Corporation.
0005  *
0006  * Other contributors:
0007  *   Robert O'Callahan <roc+@cs.cmu.edu>
0008  *   David Baron <dbaron@fas.harvard.edu>
0009  *   Christian Biesinger <cbiesinger@web.de>
0010  *   Randall Jesup <rjesup@wgate.com>
0011  *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
0012  *   Josh Soref <timeless@mac.com>
0013  *   Boris Zbarsky <bzbarsky@mit.edu>
0014  *
0015  * This library is free software; you can redistribute it and/or
0016  * modify it under the terms of the GNU Lesser General Public
0017  * License as published by the Free Software Foundation; either
0018  * version 2.1 of the License, or (at your option) any later version.
0019  *
0020  * This library is distributed in the hope that it will be useful,
0021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0023  * Lesser General Public License for more details.
0024  *
0025  * You should have received a copy of the GNU Lesser General Public
0026  * License along with this library; if not, write to the Free Software
0027  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
0028  *
0029  * Alternatively, the contents of this file may be used under the terms
0030  * of either the Mozilla Public License Version 1.1, found at
0031  * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
0032  * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
0033  * (the "GPL"), in which case the provisions of the MPL or the GPL are
0034  * applicable instead of those above.  If you wish to allow use of your
0035  * version of this file only under the terms of one of those two
0036  * licenses (the MPL or the GPL) and not to allow others to use your
0037  * version of this file under the LGPL, indicate your decision by
0038  * deletingthe provisions above and replace them with the notice and
0039  * other provisions required by the MPL or the GPL, as the case may be.
0040  * If you do not delete the provisions above, a recipient may use your
0041  * version of this file under any of the LGPL, the MPL or the GPL.
0042  */
0043 
0044 #ifndef render_layer_h
0045 #define render_layer_h
0046 
0047 #include <QColor>
0048 #include <QRect>
0049 #include <assert.h>
0050 
0051 #include "render_object.h"
0052 
0053 //template <class T*> class QVector;
0054 
0055 namespace khtml
0056 {
0057 class RenderObject;
0058 class RenderScrollMediator;
0059 class ScrollBarWidget;
0060 
0061 class RenderScrollMediator: public QObject
0062 {
0063     Q_OBJECT
0064 public:
0065     RenderScrollMediator(RenderLayer *layer)
0066         : m_layer(layer), m_waitingForUpdate(false) {}
0067 
0068 public Q_SLOTS:
0069     void slotValueChanged();
0070 
0071 private:
0072     RenderLayer *m_layer;
0073     bool m_waitingForUpdate;
0074 };
0075 
0076 // This class handles the auto-scrolling of layers with overflow: marquee.
0077 class Marquee: public QObject
0078 {
0079     Q_OBJECT
0080 
0081 public:
0082     Marquee(RenderLayer *l);
0083 
0084     void timerEvent(QTimerEvent *) override;
0085 
0086     int speed() const
0087     {
0088         return m_speed;
0089     }
0090     int marqueeSpeed() const;
0091     EMarqueeDirection direction() const;
0092     EMarqueeDirection reverseDirection() const
0093     {
0094         return static_cast<EMarqueeDirection>(-direction());
0095     }
0096     bool isHorizontal() const;
0097     bool isUnfurlMarquee() const;
0098     int unfurlPos() const
0099     {
0100         return m_unfurlPos;
0101     }
0102 
0103     EWhiteSpace whiteSpace()
0104     {
0105         return KDE_CAST_BF_ENUM(EWhiteSpace, m_whiteSpace);
0106     }
0107 
0108     int computePosition(EMarqueeDirection dir, bool stopAtClientEdge);
0109 
0110     void setEnd(int end)
0111     {
0112         m_end = end;
0113     }
0114 
0115     void start();
0116     void suspend();
0117     void stop();
0118 
0119     void updateMarqueeStyle();
0120     void updateMarqueePosition();
0121 
0122 private:
0123     RenderLayer *m_layer;
0124     int m_currentLoop;
0125     int m_totalLoops;
0126     int m_timerId;
0127     int m_start;
0128     int m_end;
0129     int m_speed;
0130     int m_unfurlPos;
0131     bool m_reset: 1;
0132     bool m_suspended: 1;
0133     bool m_stopped: 1;
0134     KDE_BF_ENUM(EWhiteSpace) m_whiteSpace : 3;
0135     KDE_BF_ENUM(EMarqueeDirection) m_direction : 4;
0136 };
0137 
0138 class RenderLayer
0139 {
0140 public:
0141     static ScrollBarWidget *gScrollBar;
0142 
0143     RenderLayer(RenderObject *object);
0144     ~RenderLayer();
0145 
0146     RenderObject *renderer() const
0147     {
0148         return m_object;
0149     }
0150     RenderLayer *parent() const
0151     {
0152         return m_parent;
0153     }
0154     RenderLayer *previousSibling() const
0155     {
0156         return m_previous;
0157     }
0158     RenderLayer *nextSibling() const
0159     {
0160         return m_next;
0161     }
0162 
0163     RenderLayer *firstChild() const
0164     {
0165         return m_first;
0166     }
0167     RenderLayer *lastChild() const
0168     {
0169         return m_last;
0170     }
0171 
0172     void addChild(RenderLayer *newChild, RenderLayer *beforeChild = nullptr);
0173     RenderLayer *removeChild(RenderLayer *oldChild);
0174 
0175     void removeOnlyThisLayer();
0176     void insertOnlyThisLayer();
0177 
0178     void styleChanged();
0179 
0180     Marquee *marquee() const
0181     {
0182         return m_marquee;
0183     }
0184     void suspendMarquees();
0185 
0186     bool isOverflowOnly() const
0187     {
0188         return m_isOverflowOnly;
0189     }
0190 
0191     bool isTransparent() const;
0192     RenderLayer *transparentAncestor() const;
0193 
0194     RenderLayer *root()
0195     {
0196         RenderLayer *curr = this;
0197         while (curr->parent()) {
0198             curr = curr->parent();
0199         }
0200         return curr;
0201     }
0202 
0203     int xPos() const
0204     {
0205         return m_x;
0206     }
0207     int yPos() const
0208     {
0209         return m_y;
0210     }
0211 
0212     int width() const;
0213     int height() const;
0214 
0215     int scrollWidth() const
0216     {
0217         return m_scrollWidth;
0218     }
0219     int scrollHeight() const
0220     {
0221         return m_scrollHeight;
0222     }
0223 
0224     void resize(int w, int h)
0225     {
0226         m_scrollWidth = w; m_scrollHeight = h;
0227     }
0228 
0229     void setPos(int xPos, int yPos)
0230     {
0231         m_x = xPos;
0232         m_y = yPos;
0233     }
0234 
0235     // Scrolling methods for layers that can scroll their overflow.
0236     void scrollOffset(int &x, int &y);
0237     void subtractScrollOffset(int &x, int &y);
0238     void checkInlineRelOffset(const RenderObject *o, int &x, int &y);
0239     int scrollXOffset()
0240     {
0241         return m_scrollX + m_scrollXOrigin;
0242     }
0243     int scrollYOffset()
0244     {
0245         return m_scrollY;
0246     }
0247     void scrollToOffset(int x, int y, bool updateScrollbars = true, bool repaint = true, bool dispatchEvent = true);
0248     void scrollToXOffset(int x)
0249     {
0250         scrollToOffset(x, m_scrollY);
0251     }
0252     void scrollToYOffset(int y)
0253     {
0254         scrollToOffset(m_scrollX + m_scrollXOrigin, y);
0255     }
0256     void resetXOffset()
0257     {
0258         scrollToOffset(0, m_scrollY, false, false, false);
0259     }
0260     void resetYOffset()
0261     {
0262         scrollToOffset(m_scrollX + m_scrollXOrigin, 0, false, false, false);
0263     }
0264     void showScrollbar(Qt::Orientation, bool);
0265     ScrollBarWidget *horizontalScrollbar()
0266     {
0267         return m_hBar;
0268     }
0269     ScrollBarWidget *verticalScrollbar()
0270     {
0271         return m_vBar;
0272     }
0273     bool hasReversedScrollbar() const;
0274     int verticalScrollbarWidth();
0275     int horizontalScrollbarHeight();
0276     void positionScrollbars(const QRect &damageRect);
0277     void paintScrollbars(RenderObject::PaintInfo &pI);
0278     void checkScrollbarsAfterLayout();
0279     void slotValueChanged(int);
0280     void repaint(Priority p = NormalPriority, bool markForRepaint = false);
0281     void updateScrollPositionFromScrollbars();
0282 
0283     void updateLayerPosition();
0284     void updateLayerPositions(RenderLayer *rootLayer, bool doFullRepaint = false, bool checkForRepaint = false);
0285 
0286     // Get the enclosing stacking context for this layer.  A stacking context is a layer
0287     // that has a non-auto z-index.
0288     RenderLayer *stackingContext() const;
0289     bool isStackingContext() const
0290     {
0291         return !hasAutoZIndex() || renderer()->isCanvas();
0292     }
0293 
0294     void dirtyZOrderLists();
0295     void updateZOrderLists();
0296     QVector<RenderLayer *> *posZOrderList() const
0297     {
0298         return m_posZOrderList;
0299     }
0300     QVector<RenderLayer *> *negZOrderList() const
0301     {
0302         return m_negZOrderList;
0303     }
0304 
0305     void dirtyOverflowList();
0306     void updateOverflowList();
0307     QVector<RenderLayer *> *overflowList() const
0308     {
0309         return m_overflowList;
0310     }
0311 
0312     bool hasVisibleContent() const
0313     {
0314         return m_hasVisibleContent;
0315     }
0316     void setHasVisibleContent(bool b);
0317     void dirtyVisibleContentStatus();
0318 
0319     void setHasOverlaidWidgets(bool b = true)
0320     {
0321         m_hasOverlaidWidgets = b;
0322     }
0323     bool hasOverlaidWidgets() const
0324     {
0325         return m_hasOverlaidWidgets;
0326     }
0327     QRegion getMask() const
0328     {
0329         return m_region;
0330     }
0331     QRegion paintedRegion(RenderLayer *rootLayer);
0332     void updateWidgetMasks(RenderLayer *rootLayer);
0333 
0334     // Gets the nearest enclosing positioned ancestor layer (also includes
0335     // the <html> layer and the root layer).
0336     RenderLayer *enclosingPositionedAncestor() const;
0337 
0338     void convertToLayerCoords(const RenderLayer *ancestorLayer, int &x, int &y) const;
0339 
0340     bool hasAutoZIndex() const
0341     {
0342         return renderer()->style()->hasAutoZIndex();
0343     }
0344     int zIndex() const
0345     {
0346         return renderer()->style()->zIndex();
0347     }
0348 
0349     // The two main functions that use the layer system.  The paint method
0350     // paints the layers that intersect the damage rect from back to
0351     // front.  The nodeAtPoint method looks for mouse events by walking
0352     // layers that intersect the point from front to back.
0353     KHTML_EXPORT void paint(QPainter *p, const QRect &damageRect, bool selectionOnly = false);
0354     bool nodeAtPoint(RenderObject::NodeInfo &info, int x, int y);
0355 
0356     // This method figures out our layerBounds in coordinates relative to
0357     // |rootLayer}.  It also computes our background and foreground clip rects
0358     // for painting/event handling.
0359     void calculateRects(const RenderLayer *rootLayer, const QRect &paintDirtyRect, QRect &layerBounds,
0360                         QRect &backgroundRect, QRect &foregroundRect);
0361     void calculateClipRects(const RenderLayer *rootLayer, QRect &overflowClipRect,
0362                             QRect &posClipRect, QRect &fixedClipRect);
0363 
0364     bool intersectsDamageRect(const QRect &layerBounds, const QRect &damageRect) const;
0365     bool containsPoint(int x, int y, const QRect &damageRect) const;
0366 
0367     void updateHoverActiveState(RenderObject::NodeInfo &info);
0368 
0369     void detach(RenderArena *renderArena);
0370 
0371 #ifdef ENABLE_DUMP
0372     KHTML_EXPORT void dump(QTextStream &stream, const QString &ind = QString());
0373 #endif
0374 
0375     // Overloaded new operator.  Derived classes must override operator new
0376     // in order to allocate out of the RenderArena.
0377     void *operator new(size_t sz, RenderArena *renderArena) throw();
0378 
0379     // Overridden to prevent the normal delete from being called.
0380     void operator delete(void *ptr, size_t sz);
0381 
0382 private:
0383     // The normal operator new is disallowed on all render objects.
0384     void *operator new(size_t sz) throw();
0385 
0386 private:
0387     void setNextSibling(RenderLayer *next)
0388     {
0389         m_next = next;
0390     }
0391     void setPreviousSibling(RenderLayer *prev)
0392     {
0393         m_previous = prev;
0394     }
0395     void setParent(RenderLayer *parent)
0396     {
0397         m_parent = parent;
0398     }
0399     void setFirstChild(RenderLayer *first)
0400     {
0401         m_first = first;
0402     }
0403     void setLastChild(RenderLayer *last)
0404     {
0405         m_last = last;
0406     }
0407 
0408     void collectLayers(QVector<RenderLayer *> *&, QVector<RenderLayer *> *&);
0409 
0410     KHTML_EXPORT void paintLayer(RenderLayer *rootLayer, QPainter *p, const QRect &paintDirtyRect, bool selectionOnly = false);
0411     RenderLayer *nodeAtPointForLayer(RenderLayer *rootLayer, RenderObject::NodeInfo &info,
0412                                      int x, int y, const QRect &hitTestRect);
0413     bool shouldBeOverflowOnly() const;
0414 
0415     void childVisibilityChanged(bool newVisibility);
0416     void dirtyVisibleDescendantStatus();
0417     void updateVisibilityStatus();
0418 
0419 protected:
0420     void setClip(QPainter *p, const QRect &paintDirtyRect, const QRect &clipRect, bool setup = false);
0421     void restoreClip(QPainter *p, const QRect &paintDirtyRect, const QRect &clipRect, bool cleanup = false);
0422 
0423     RenderObject *m_object;
0424 
0425     RenderLayer *m_parent;
0426     RenderLayer *m_previous;
0427     RenderLayer *m_next;
0428 
0429     RenderLayer *m_first;
0430     RenderLayer *m_last;
0431 
0432     // Our (x,y) coordinates are in our parent layer's coordinate space.
0433     int m_x;
0434     int m_y;
0435 
0436     // Our scroll offsets if the view is scrolled.
0437     int m_scrollX;
0438     int m_scrollY;
0439 
0440     // the reference for our x offset (will vary depending on layout direction)
0441     int m_scrollXOrigin;
0442 
0443     // The width/height of our scrolled area.
0444     int m_scrollWidth;
0445     int m_scrollHeight;
0446 
0447     // For layers with overflow, we have a pair of scrollbars.
0448     ScrollBarWidget *m_hBar;
0449     ScrollBarWidget *m_vBar;
0450     QPixmap *m_buffer[2];
0451 
0452     RenderScrollMediator *m_scrollMediator;
0453 
0454     // For layers that establish stacking contexts, m_posZOrderList holds a sorted list of all the
0455     // descendant layers within the stacking context that have z-indices of 0 or greater
0456     // (auto will count as 0).  m_negZOrderList holds descendants within our stacking context with negative
0457     // z-indices.
0458     QVector<RenderLayer *> *m_posZOrderList;
0459     QVector<RenderLayer *> *m_negZOrderList;
0460 
0461     // This list contains our overflow child layers.
0462     QVector<RenderLayer *> *m_overflowList;
0463 
0464     bool m_zOrderListsDirty: 1;
0465     bool m_overflowListDirty: 1;
0466     bool m_isOverflowOnly: 1;
0467     bool m_markedForRepaint: 1;
0468     bool m_hasOverlaidWidgets: 1;
0469     bool m_visibleContentStatusDirty : 1;
0470     bool m_hasVisibleContent : 1;
0471     bool m_visibleDescendantStatusDirty : 1;
0472     bool m_hasVisibleDescendant : 1;
0473     bool m_inScrollbarRelayout : 1;
0474     bool m_wasStackingContext : 1; // set to 1 when last style application
0475     // establised us as a stacking context
0476 
0477     QRect m_visibleRect;
0478 
0479     QRegion m_region; // used by overlaid (non z-order aware) widgets
0480 
0481     Marquee *m_marquee; // Used by layers with overflow:marquee
0482 };
0483 
0484 } // namespace
0485 #endif