Latest layer patch

David Hyatt hyatt at apple.com
Tue Sep 2 11:52:45 CEST 2003


Here's the latest layer patch.  I fixed another clipping bug with 
relative positioning, and I optimized relpositioning to only do a 
repaint when left/top/right/bottom changes and not a layout.  This 
patch also fixes a couple of hover-related crashes introduced by the 
last revision of the patch.

I've also attached the complete clipping test suite I'm using.  The 
tests are pretty self-explanatory.

Let me know if you have any feedback on the patch itself, as this patch 
has not yet landed in the Safari tree.

Dave
(hyatt at apple.com)

-------------- next part --------------
Index: khtml/css/cssstyleselector.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/cssstyleselector.cpp,v
retrieving revision 1.95
diff -u -p -r1.95 khtml/css/cssstyleselector.cpp
--- khtml/css/cssstyleselector.cpp	2003/08/26 22:19:17	1.95
+++ khtml/css/cssstyleselector.cpp	2003/09/02 17:44:09
@@ -527,6 +527,21 @@ void CSSStyleSelector::adjustRenderStyle
         }
     }
 
+    // Make sure our z-index value is only applied if the object is positioned,
+    // relatively positioned, or transparent.
+    if (style->position() == STATIC && style->opacity() == 1.0f) {
+        if (e && e->getDocument()->documentElement() == e)
+            style->setZIndex(0); // The root has a z-index of 0 if not positioned or transparent.
+        else
+            style->setHasAutoZIndex(); // Everyone else gets an auto z-index.
+    }
+
+    // Auto z-index becomes 0 for transparent objects.  This prevents cases where
+    // objects that should be blended as a single unit end up with a non-transparent object
+    // wedged in between them.
+    if (style->opacity() < 1.0f && style->hasAutoZIndex())
+        style->setZIndex(0);
+    
     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
     // tables, inline blocks, inline tables, or run-ins.
     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
Index: khtml/rendering/render_block.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_block.cpp,v
retrieving revision 1.55
diff -u -p -r1.55 khtml/rendering/render_block.cpp
--- khtml/rendering/render_block.cpp	2003/08/28 21:24:07	1.55
+++ khtml/rendering/render_block.cpp	2003/09/02 17:44:13
@@ -1853,13 +1853,14 @@ bool RenderBlock::isPointInScrollbar(int
     return false;    
 }
 
-bool RenderBlock::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, bool inBox)
+bool RenderBlock::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                              HitTestAction hitTestAction, bool inBox)
 {
     bool inScrollbar = isPointInScrollbar(_x, _y, _tx+xPos(), _ty+yPos());
-    if (inScrollbar)
+    if (inScrollbar && hitTestAction != HitTestChildrenOnly)
         inBox = true;
     
-    if (m_floatingObjects && !inScrollbar) {
+    if (hitTestAction != HitTestSelfOnly && m_floatingObjects && !inScrollbar) {
         int stx = _tx + xPos();
         int sty = _ty + yPos();
         if (style()->hidesOverflow() && m_layer)
@@ -1877,7 +1878,7 @@ bool RenderBlock::nodeAtPoint(NodeInfo& 
                                               sty+o->startY + o->node->marginTop() - o->node->yPos());
     }
 
-    inBox |= RenderFlow::nodeAtPoint(info, _x, _y, _tx, _ty, inBox);
+    inBox |= RenderFlow::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox);
     return inBox;
 }
 
Index: khtml/rendering/render_block.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_block.h,v
retrieving revision 1.21
diff -u -p -r1.21 khtml/rendering/render_block.h
--- khtml/rendering/render_block.h	2003/08/27 01:09:18	1.21
+++ khtml/rendering/render_block.h	2003/09/02 17:44:14
@@ -158,7 +158,8 @@ public:
                       int *heightRemaining = 0) const;
     int leftOffset(int y) const { return leftRelOffset(y, leftOffset(), true); }
 
-    virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, bool inside=false);
+    virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
+                             HitTestAction hitTestAction = HitTestAll, bool inside=false);
 
     bool isPointInScrollbar(int x, int y, int tx, int ty);
     
Index: khtml/rendering/render_box.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_box.cpp,v
retrieving revision 1.80
diff -u -p -r1.80 khtml/rendering/render_box.cpp
--- khtml/rendering/render_box.cpp	2003/08/21 18:52:06	1.80
+++ khtml/rendering/render_box.cpp	2003/09/02 17:44:15
@@ -108,34 +108,11 @@ void RenderBox::setStyle(RenderStyle *_s
         m_layer = 0;
     }
 
-    adjustZIndex();
-
     // Set the text color if we're the body.
     if (isBody())
         element()->getDocument()->setTextColor(_style->color());
 }
 
-void RenderBox::adjustZIndex()
-{
-    if (m_layer) {
-        // Make sure our z-index values are only applied if we're positioned or
-        // relpositioned or transparent.
-        if (!isPositioned() && !isRelPositioned() && style()->opacity() == 1.0f) {
-            // Set the auto z-index flag.
-            if (isRoot())
-                style()->setZIndex(0);
-            else
-                style()->setHasAutoZIndex();
-        }
-        
-        // Auto z-index becomes 0 for transparent objects.  This prevents cases where
-        // objects that should be blended as a single unit end up with a non-transparent object
-        // wedged in between them.
-        if (style()->opacity() < 1.0f && style()->hasAutoZIndex())
-            style()->setZIndex(0);
-    }
-}
-
 RenderBox::~RenderBox()
 {
     //kdDebug( 6040 ) << "Element destructor: this=" << nodeName().string() << endl;
@@ -612,8 +589,9 @@ void RenderBox::repaintRectangle(int x, 
     
     // Apply the relative position offset when invalidating a rectangle.  The layer
     // is translated, but the render box isn't, so we need to do this to get the
-    // right dirty rect.
-    if (isRelPositioned())
+    // right dirty rect.  Since this is called from RenderObject::setStyle, the relative position
+    // flag on the RenderObject has been cleared, so use the one on the style().
+    if (style()->position() == RELATIVE)
         relativePositionOffset(x,y);
     
     if (style()->position()==FIXED) f=true;
Index: khtml/rendering/render_box.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_box.h,v
retrieving revision 1.26
diff -u -p -r1.26 khtml/rendering/render_box.h
--- khtml/rendering/render_box.h	2003/07/11 17:55:42	1.26
+++ khtml/rendering/render_box.h	2003/09/02 17:44:15
@@ -137,9 +137,6 @@ protected:
     virtual QRect getOverflowClipRect(int tx, int ty);
     virtual QRect getClipRect(int tx, int ty);
 
-    // Called to correct the z-index after the style has been changed.
-    void adjustZIndex();
-    
     // the actual height of the contents + borders + padding
     int m_height;
 
Index: khtml/rendering/render_frames.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_frames.cpp,v
retrieving revision 1.42
diff -u -p -r1.42 khtml/rendering/render_frames.cpp
--- khtml/rendering/render_frames.cpp	2003/08/19 21:49:53	1.42
+++ khtml/rendering/render_frames.cpp	2003/09/02 17:44:17
@@ -84,9 +84,10 @@ RenderFrameSet::~RenderFrameSet()
       delete [] m_vSplitVar;
 }
 
-bool RenderFrameSet::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, bool inside)
+bool RenderFrameSet::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                                 HitTestAction hitTestAction, bool inside)
 {
-    RenderBox::nodeAtPoint(info, _x, _y, _tx, _ty, inside);
+    RenderBox::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inside);
 
     inside = m_resizing || canResize(_x, _y);
 
Index: khtml/rendering/render_frames.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_frames.h,v
retrieving revision 1.9
diff -u -p -r1.9 khtml/rendering/render_frames.h
--- khtml/rendering/render_frames.h	2003/05/17 01:40:18	1.9
+++ khtml/rendering/render_frames.h	2003/09/02 17:44:17
@@ -60,7 +60,8 @@ public:
   bool canResize( int _x, int _y);
   void setResizing(bool e);
 
-  bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, bool inside=false);
+  bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
+                   HitTestAction hitTestAction = HitTestAll, bool inside=false);
 
     DOM::HTMLFrameSetElementImpl *element() const
     { return static_cast<DOM::HTMLFrameSetElementImpl*>(RenderObject::element()); }
Index: khtml/rendering/render_image.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_image.cpp,v
retrieving revision 1.38
diff -u -p -r1.38 khtml/rendering/render_image.cpp
--- khtml/rendering/render_image.cpp	2003/07/30 21:03:32	1.38
+++ khtml/rendering/render_image.cpp	2003/09/02 17:44:18
@@ -439,9 +439,10 @@ void RenderImage::detach(RenderArena *ar
     RenderReplaced::detach(arena);
 }
 
-bool RenderImage::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, bool inside)
+bool RenderImage::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                              HitTestAction hitTestAction, bool inside)
 {
-    inside |= RenderReplaced::nodeAtPoint(info, _x, _y, _tx, _ty, inside);
+    inside |= RenderReplaced::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inside);
 
     if (inside && element()) {
         int tx = _tx + m_x;
Index: khtml/rendering/render_image.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_image.h,v
retrieving revision 1.11
diff -u -p -r1.11 khtml/rendering/render_image.h
--- khtml/rendering/render_image.h	2003/05/05 17:31:40	1.11
+++ khtml/rendering/render_image.h	2003/09/02 17:44:18
@@ -64,7 +64,8 @@ public:
     virtual void notifyFinished(CachedObject *finishedObj);
     void dispatchLoadEvent();
 
-    virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, bool inside=false);
+    virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
+                             HitTestAction hitTestAction = HitTestAll, bool inside=false);
     
     virtual short calcReplacedWidth() const;
     virtual int calcReplacedHeight() const;
Index: khtml/rendering/render_inline.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_inline.cpp,v
retrieving revision 1.16
diff -u -p -r1.16 khtml/rendering/render_inline.cpp
--- khtml/rendering/render_inline.cpp	2003/08/11 23:41:02	1.16
+++ khtml/rendering/render_inline.cpp	2003/09/02 17:44:18
@@ -366,15 +366,18 @@ const char *RenderInline::renderName() c
     return "RenderInline";
 }
 
-bool RenderInline::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, bool inside)
+bool RenderInline::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                               HitTestAction hitTestAction, bool inside)
 {
-    // Always check our kids.
-    for (RenderObject* child = lastChild(); child; child = child->previousSibling())
-        if (!child->layer() && !child->isFloating() && child->nodeAtPoint(info, _x, _y, _tx, _ty))
-            inside = true;
-
+    // Check our kids if our HitTestAction says to.
+    if (hitTestAction != HitTestSelfOnly) {
+        for (RenderObject* child = lastChild(); child; child = child->previousSibling())
+            if (!child->layer() && !child->isFloating() && child->nodeAtPoint(info, _x, _y, _tx, _ty))
+                inside = true;
+    }
+    
     // Check our line boxes if we're still not inside.
-    if (!inside && style()->visibility() != HIDDEN) {
+    if (hitTestAction != HitTestChildrenOnly && !inside && style()->visibility() != HIDDEN) {
         // See if we're inside one of our line boxes.
         for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
             if((_y >=_ty + curr->m_y) && (_y < _ty + curr->m_y + curr->m_height) &&
@@ -401,31 +404,8 @@ bool RenderInline::nodeAtPoint(NodeInfo&
 
         if(!info.innerNonSharedNode())
             info.setInnerNonSharedNode(element());
-
-        if (!info.URLElement()) {
-            RenderObject* p = this;
-            while (p) {
-                if (p->element() && p->element()->hasAnchor()) {
-                    info.setURLElement(p->element());
-                    break;
-                }
-                if (!isFloatingOrPositioned()) break;
-                p = p->parent();
-            }
-        }
-        
     }
 
-    if (!info.readonly()) {
-        // lets see if we need a new style
-        bool oldinside = mouseInside();
-        setMouseInside(inside);
-
-        setHoverAndActive(info, oldinside, inside);
-        if (!isInline() && continuation())
-            continuation()->setHoverAndActive(info, oldinside, inside);
-    }
-    
     return inside;
 }
 
Index: khtml/rendering/render_inline.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_inline.h,v
retrieving revision 1.11
diff -u -p -r1.11 khtml/rendering/render_inline.h
--- khtml/rendering/render_inline.h	2003/08/11 23:41:02	1.11
+++ khtml/rendering/render_inline.h	2003/09/02 17:44:19
@@ -58,7 +58,8 @@ public:
     virtual void paintObject(QPainter *, int x, int y, int w, int h,
                              int tx, int ty, PaintAction paintAction);
 
-    virtual bool nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, bool inside);
+    virtual bool nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                             HitTestAction hitTestAction = HitTestAll, bool inside=false);
     
     virtual void calcMinMaxWidth();
 
Index: khtml/rendering/render_layer.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_layer.cpp,v
retrieving revision 1.49
diff -u -p -r1.49 khtml/rendering/render_layer.cpp
--- khtml/rendering/render_layer.cpp	2003/07/24 01:51:17	1.49
+++ khtml/rendering/render_layer.cpp	2003/09/02 17:44:21
@@ -49,15 +49,18 @@
 #include "render_arena.h"
 #include "xml/dom_docimpl.h"
 
+#include <qscrollbar.h>
+#include <qptrvector.h>
+
 using namespace DOM;
 using namespace khtml;
 
-QWidget* RenderLayer::gScrollBar = 0;
+#ifdef APPLE_CHANGES
+QScrollBar* RenderLayer::gScrollBar = 0;
+#endif
 
 #ifndef NDEBUG
 static bool inRenderLayerDetach;
-static bool inRenderLayerElementDetach;
-static bool inRenderZTreeNodeDetach;
 #endif
 
 void
@@ -73,17 +76,20 @@ m_previous( 0 ),
 m_next( 0 ),
 m_first( 0 ),
 m_last( 0 ),
-m_height( 0 ),
-m_y( 0 ),
 m_x( 0 ),
+m_y( 0 ),
 m_width( 0 ),
+m_height( 0 ),
 m_scrollX( 0 ),
 m_scrollY( 0 ),
 m_scrollWidth( 0 ),
 m_scrollHeight( 0 ),
 m_hBar( 0 ),
 m_vBar( 0 ),
-m_scrollMediator( 0 )
+m_scrollMediator( 0 ),
+m_posZOrderList( 0 ),
+m_negZOrderList( 0 ),
+m_zOrderListsDirty( true )
 {
 }
 
@@ -95,6 +101,8 @@ RenderLayer::~RenderLayer()
     delete m_hBar;
     delete m_vBar;
     delete m_scrollMediator;
+    delete m_posZOrderList;
+    delete m_negZOrderList;
 }
 
 void RenderLayer::updateLayerPosition()
@@ -135,94 +143,44 @@ void RenderLayer::updateLayerPosition()
             setWidth(m_object->overflowWidth());
         if (m_object->overflowHeight() > m_object->height())
             setHeight(m_object->overflowHeight());
-    }
+    }    
 }
 
-RenderLayer*
-RenderLayer::enclosingPositionedAncestor()
+RenderLayer *RenderLayer::stackingContext() const
 {
     RenderLayer* curr = parent();
     for ( ; curr && !curr->m_object->isCanvas() && !curr->m_object->isRoot() &&
-         !curr->m_object->isPositioned() && !curr->m_object->isRelPositioned();
-         curr = curr->parent());
-         
+          curr->m_object->style()->hasAutoZIndex();
+          curr = curr->parent());
     return curr;
 }
 
 RenderLayer*
-RenderLayer::transparentAncestor()
+RenderLayer::enclosingPositionedAncestor() const
 {
     RenderLayer* curr = parent();
-    for ( ; curr && curr->m_object->style()->opacity() == 1.0f; curr = curr->parent());
+    for ( ; curr && !curr->m_object->isCanvas() && !curr->m_object->isRoot() &&
+         !curr->m_object->isPositioned() && !curr->m_object->isRelPositioned();
+         curr = curr->parent());
+         
     return curr;
 }
 
+#if APPLE_CHANGES
 bool
 RenderLayer::isTransparent()
 {
     return m_object->style()->opacity() < 1.0f;
 }
-
-static RenderLayer* commonTransparentAncestor(RenderLayer* layer1, RenderLayer* layer2)
-{
-    if (!layer1 || !layer2)
-        return 0;
-    
-    for (RenderLayer* currLayer1 = layer1; currLayer1; currLayer1 = currLayer1->transparentAncestor())
-        for (RenderLayer* currLayer2 = layer2; currLayer2; currLayer2 = currLayer2->transparentAncestor())
-            if (currLayer1 == currLayer2)
-                return currLayer1;
-    
-    return 0;
-}
-
-void RenderLayer::updateTransparentState(QPainter* painter, RenderLayer* newLayer, RenderLayer*& currLayer)
-{
-    RenderLayer* transparentLayer = (!newLayer || newLayer->isTransparent()) ? newLayer :
-                                    newLayer->transparentAncestor();
-    if (transparentLayer == currLayer)
-        return;
-    
-    RenderLayer* commonAncestor = commonTransparentAncestor(currLayer, transparentLayer);
-    endTransparencyLayers(painter, currLayer, commonAncestor);
-    beginTransparencyLayers(painter, transparentLayer, commonAncestor);
-    
-    // Update our current layer.
-    currLayer = transparentLayer;
-}
 
-void RenderLayer::beginTransparencyLayers(QPainter* painter, RenderLayer* newLayer, RenderLayer* ancestorLayer)
+RenderLayer*
+RenderLayer::transparentAncestor()
 {
-    if (!newLayer || newLayer == ancestorLayer)
-        return;
-    
-    // We need to open from the outside in, so begin ancestor layers first.
-    beginTransparencyLayers(painter, newLayer->transparentAncestor(), ancestorLayer);
-    
-    // Konqueror should add its own code for setting up the opacity layer here.
-    // Safari uses a custom extension to QPainter to communicate with CoreGraphics.
-#ifdef APPLE_CHANGES
-    // Begin the layer
-    painter->beginTransparencyLayer(newLayer->renderer()->style()->opacity());
-#endif
+    RenderLayer* curr = parent();
+    for ( ; curr && curr->m_object->style()->opacity() == 1.0f; curr = curr->parent());
+    return curr;
 }
-
-void RenderLayer::endTransparencyLayers(QPainter* painter, RenderLayer* newLayer, RenderLayer* ancestorLayer)
-{
-    if (!newLayer || newLayer == ancestorLayer)
-        return;
-    
-    // We need to close from the inside out.
-    
-    // Konqueror should add its own code for popping opacity layers here.
-    // Safari uses a custom extension to QPainter to communicate with CoreGraphics.
-#ifdef APPLE_CHANGES
-    // End the layer
-    painter->endTransparencyLayer();
 #endif
-    
-    endTransparencyLayers(painter, newLayer->transparentAncestor(), ancestorLayer);
-}
 
 void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
 {
@@ -269,6 +227,9 @@ void RenderLayer::addChild(RenderLayer *
         setLastChild(child);
    
     child->setParent(this);
+
+    // Dirty the z-order list in which we are contained.
+    child->stackingContext()->dirtyZOrderLists();
 }
 
 RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
@@ -284,6 +245,13 @@ RenderLayer* RenderLayer::removeChild(Re
     if (m_last == oldChild)
         m_last = oldChild->previousSibling();
 
+    // Dirty the z-order list in which we are contained.  When called via the
+    // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
+    // from the main layer tree, so we need to null-check the |stackingContext| value.
+    RenderLayer* stackingContext = oldChild->stackingContext();
+    if (stackingContext)
+        oldChild->stackingContext()->dirtyZOrderLists();
+    
     oldChild->setPreviousSibling(0);
     oldChild->setNextSibling(0);
     oldChild->setParent(0);
@@ -330,7 +298,7 @@ void RenderLayer::insertOnlyThisLayer()
 }
 
 void 
-RenderLayer::convertToLayerCoords(RenderLayer* ancestorLayer, int& x, int& y)
+RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
 {
     if (ancestorLayer == this)
         return;
@@ -533,8 +501,8 @@ RenderLayer::checkScrollbarsAfterLayout(
     if (bottomPos - m_object->borderTop() > m_scrollHeight)
         m_scrollHeight = bottomPos - m_object->borderTop();
     
-    bool needHorizontalBar = rightPos > m_width;
-    bool needVerticalBar = bottomPos > m_height;
+    bool needHorizontalBar = rightPos > width();
+    bool needVerticalBar = bottomPos > height();
 
     bool haveHorizontalBar = m_hBar;
     bool haveVerticalBar = m_vBar;
@@ -583,425 +551,405 @@ RenderLayer::checkScrollbarsAfterLayout(
     }
 }
 
+#if APPLE_CHANGES
 void
-RenderLayer::paintScrollbars(QPainter* p, int x, int y, int w, int h)
+RenderLayer::paintScrollbars(QPainter* p, const QRect& damageRect)
 {
-#if APPLE_CHANGES
     if (m_hBar)
-        m_hBar->paint(p, QRect(x, y, w, h));
+        m_hBar->paint(p, damageRect);
     if (m_vBar)
-        m_vBar->paint(p, QRect(x, y, w, h));
-#endif
+        m_vBar->paint(p, damageRect);
 }
+#endif
 
 void
-RenderLayer::paint(QPainter *p, int x, int y, int w, int h, bool selectionOnly)
+RenderLayer::paint(QPainter *p, const QRect& damageRect, bool selectionOnly)
 {
-    // Create the z-tree of layers that should be displayed.
-    QRect damageRect(x,y,w,h);
-    RenderZTreeNode* node = constructZTree(damageRect, damageRect, this);
-    if (!node)
+    paintLayer(this, p, damageRect, selectionOnly);
+}
+
+static void setClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect)
+{
+    if (paintDirtyRect == clipRect)
         return;
 
-    // Flatten the tree into a back-to-front list for painting.
-    QPtrVector<RenderLayerElement> layerList;
-    constructLayerList(node, &layerList);
-
-    // Walk the list and paint each layer, adding in the appropriate offset.
-    QRect paintRect(x, y, w, h);
-    QRect currRect(paintRect);
-    RenderLayer* currentTransparentLayer = 0;
-    
-    uint count = layerList.count();
-    for (uint i = 0; i < count; i++) {
-        RenderLayerElement* elt = layerList.at(i);
-
-        // Elements add in their own positions as a translation factor.  This forces
-        // us to subtract that out, so that when it's added back in, we get the right
-        // bounds.  This is really disgusting (that paint only sets up the right paint
-        // position after you call into it). -dwh
-        //printf("Painting layer at %d %d\n", elt->absBounds.x(), elt->absBounds.y());
-
-        bool updatedTransparentState = false;
-        if (elt->clipOriginator) {
-            // We originated a clip (we're either positioned or an element with
-            // overflow: hidden).  We need to paint our background and border, subject
-            // to clip regions established by our parent layers.
-            if (elt->backgroundClipRect != currRect) {
-                if (currRect != paintRect)
-                    p->restore(); // Pop the clip.
-
-                // This is called to update our transparency state.
-                updateTransparentState(p, elt->layer, currentTransparentLayer);
-                updatedTransparentState = true;
-                
-                currRect = elt->backgroundClipRect;
-                
-                // Now apply the clip rect.
-                QRect clippedRect = p->xForm(currRect);
+    p->save();
+    
 #if APPLE_CHANGES
-                p->save();
-                p->addClip(clippedRect);
+    p->addClip(clipRect);
 #else
-                QRegion creg(cr);
-                QRegion old = p->clipRegion();
-                if (!old.isNull())
-                    creg = old.intersect(creg);
-            
-                p->save();
-                p->setClipRegion(creg);
+    QRect clippedRect = p->xForm(clipRect);
+    QRegion creg(clippedRect);
+    QRegion old = p->clipRegion();
+    if (!old.isNull())
+        creg = old.intersect(creg);
+    p->setClipRegion(creg);
 #endif
-            }
-            
-            // A clip is in effect.  The clip is never allowed to clip our render object's
-            // background, borders or scrollbars.  Go ahead and draw those now without our clip (that will
-            // be used for our children) in effect.
-            elt->layer->renderer()->paintBoxDecorations(p, x, y, w, h,
-                                elt->absBounds.x(),
-                                elt->absBounds.y());
+    
+}
 
-            // Position our scrollbars prior to painting.
-            elt->layer->positionScrollbars(elt->absBounds);
+static void restoreClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect)
+{
+    if (paintDirtyRect == clipRect)
+        return;
+    p->restore();
+}
 
+void
+RenderLayer::paintLayer(RenderLayer* rootLayer, QPainter *p,
+                        const QRect& paintDirtyRect, bool selectionOnly)
+{
+    // Calculate the clip rects we should use.
+    QRect layerBounds, damageRect, clipRectToApply;
+    calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply);
+    int x = layerBounds.x();
+    int y = layerBounds.y();
+                             
+    // Ensure our z-order lists are up-to-date.
+    updateZOrderLists();
+
 #if APPLE_CHANGES
-            // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
-            // z-index.
-            elt->layer->paintScrollbars(p, x, y, w, h);
+    // Set our transparency if we need to.
+    if (isTransparent())
+        p->beginTransparencyLayer(renderer()->style()->opacity());
 #endif
-        }
-        
-        if (elt->clipRect != currRect) {
-            if (currRect != paintRect)
-                p->restore(); // Pop the clip.
-
-            if (!updatedTransparentState) {
-                // This is called to update our transparency state.
-                updateTransparentState(p, elt->layer, currentTransparentLayer);
-                updatedTransparentState = true;
-            }
-            
-            currRect = elt->clipRect;
-            if (currRect != paintRect) {
-                                
-                // Now apply the clip rect.
-                QRect clippedRect = p->xForm(currRect);
+    
+    // We want to paint our layer, but only if we intersect the damage rect.
+    bool shouldPaint = intersectsDamageRect(layerBounds, damageRect);
+    if (shouldPaint && !selectionOnly) {
+        // Paint our background first, before painting any child layers.
+        if (!damageRect.isEmpty()) {
+            // Establish the clip used to paint our background.
+            setClip(p, paintDirtyRect, damageRect);
+
+            // Paint the background.
+            renderer()->paint(p, damageRect.x(), damageRect.y(),
+                              damageRect.width(), damageRect.height(),
+                              x - renderer()->xPos(), y - renderer()->yPos(),
+                              PaintActionElementBackground);
+
+            // Position our scrollbars.
+            positionScrollbars(layerBounds);
+
 #if APPLE_CHANGES
-                p->save();
-                p->addClip(clippedRect);
-#else
-                QRegion creg(cr);
-                QRegion old = p->clipRegion();
-                if (!old.isNull())
-                    creg = old.intersect(creg);
-            
-                p->save();
-                p->setClipRegion(creg);
+            // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
+            // z-index.  We paint after we painted the background/border, so that the scrollbars will
+            // sit above the background/border.
+            paintScrollbars(p, damageRect);
 #endif
-            }
+            // Restore the clip.
+            restoreClip(p, paintDirtyRect, damageRect);
         }
+    }
 
-        if (!updatedTransparentState) {
-            // This is called to update our transparency state.
-            updateTransparentState(p, elt->layer, currentTransparentLayer);
-            updatedTransparentState = true;
+    // Now walk the sorted list of children with negative z-indices.
+    if (m_negZOrderList) {
+        uint count = m_negZOrderList->count();
+        for (uint i = 0; i < count; i++) {
+            RenderLayer* child = m_negZOrderList->at(i);
+            child->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);
         }
-        
-        if (currRect.isEmpty())
-            continue;
-        
-        if (selectionOnly) {
-            if (elt->layerElementType == RenderLayerElement::Normal ||
-                elt->layerElementType == RenderLayerElement::Foreground)
-                elt->layer->renderer()->paint(p, x, y, w, h,
-                                            elt->absBounds.x() - elt->layer->renderer()->xPos(),
-                                            elt->absBounds.y() - elt->layer->renderer()->yPos(),
-                                            PaintActionSelection);
-        } else {
-            if (elt->layerElementType == RenderLayerElement::Normal ||
-                elt->layerElementType == RenderLayerElement::Background)
-                elt->layer->renderer()->paint(p, x, y, w, h,
-                                            elt->absBounds.x() - elt->layer->renderer()->xPos(),
-                                            elt->absBounds.y() - elt->layer->renderer()->yPos(),
-                                            PaintActionElementBackground);
-
-            if (elt->layerElementType == RenderLayerElement::Normal ||
-                elt->layerElementType == RenderLayerElement::Foreground) {
-                elt->layer->renderer()->paint(p, x, y, w, h,
-                                              elt->absBounds.x() - elt->layer->renderer()->xPos(),
-                                              elt->absBounds.y() - elt->layer->renderer()->yPos(),
-                                              PaintActionChildBackgrounds);
-                elt->layer->renderer()->paint(p, x, y, w, h,
-                                            elt->absBounds.x() - elt->layer->renderer()->xPos(),
-                                            elt->absBounds.y() - elt->layer->renderer()->yPos(),
-                                            PaintActionFloat);
-                elt->layer->renderer()->paint(p, x, y, w, h,
-                                            elt->absBounds.x() - elt->layer->renderer()->xPos(),
-                                            elt->absBounds.y() - elt->layer->renderer()->yPos(),
-                                            PaintActionForeground);
-            }
-        }
     }
-    
-    if (currRect != paintRect)
-        p->restore(); // Pop the clip.
-        
-    updateTransparentState(p, 0, currentTransparentLayer); // End any open transparency layers.
     
-    node->detach(renderer()->renderArena());
-}
+    // Now establish the appropriate clip and paint our child RenderObjects.
+    if (shouldPaint && !clipRectToApply.isEmpty()) {
+        // Set up the clip used when painting our children.
+        setClip(p, paintDirtyRect, clipRectToApply);
+
+        if (selectionOnly)
+            renderer()->paint(p, clipRectToApply.x(), clipRectToApply.y(),
+                              clipRectToApply.width(), clipRectToApply.height(),
+                              x - renderer()->xPos(), y - renderer()->yPos(), PaintActionSelection);
+        else {
+            renderer()->paint(p, clipRectToApply.x(), clipRectToApply.y(),
+                              clipRectToApply.width(), clipRectToApply.height(),
+                              x - renderer()->xPos(), y - renderer()->yPos(), PaintActionChildBackgrounds);
+            renderer()->paint(p, clipRectToApply.x(), clipRectToApply.y(),
+                              clipRectToApply.width(), clipRectToApply.height(),
+                              x - renderer()->xPos(), y - renderer()->yPos(), PaintActionFloat);
+            renderer()->paint(p, clipRectToApply.x(), clipRectToApply.y(),
+                              clipRectToApply.width(), clipRectToApply.height(),
+                              x - renderer()->xPos(), y - renderer()->yPos(), PaintActionForeground);
+        }
 
-void
-RenderLayer::clearOtherLayersHoverActiveState()
-{
-    if (!m_parent)
-        return;
-        
-    for (RenderLayer* curr = m_parent->firstChild(); curr; curr = curr->nextSibling()) {
-        if (curr == this)
-            continue;
-        curr->clearHoverAndActiveState(curr->renderer());
+        // Now restore our clip.
+        restoreClip(p, paintDirtyRect, clipRectToApply);
     }
     
-    m_parent->clearOtherLayersHoverActiveState();
-}
-
-void
-RenderLayer::clearHoverAndActiveState(RenderObject* obj)
-{
-    if (!obj->mouseInside())
-        return;
-    
-    obj->setMouseInside(false);
-    if (obj->element()) {
-        obj->element()->setActive(false);
-        if (obj->style()->affectedByHoverRules() || obj->style()->affectedByActiveRules())
-            obj->element()->setChanged(true);
+    // Now walk the sorted list of children with positive z-indices.
+    if (m_posZOrderList) {
+        uint count = m_posZOrderList->count();
+        for (uint i = 0; i < count; i++) {
+            RenderLayer* child = m_posZOrderList->at(i);
+            child->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);
+        }
     }
     
-    for (RenderObject* child = obj->firstChild(); child; child = child->nextSibling())
-        if (child->mouseInside())
-            clearHoverAndActiveState(child);
+#if APPLE_CHANGES
+    // End our transparency layer
+    if (isTransparent())
+        p->endTransparencyLayer();
+#endif
 }
 
 bool
 RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
 {
-    // Clear out our global scrollbar tracking variable.
-    gScrollBar = 0;
+#if APPLE_CHANGES
+    // Clear our our scrollbar variable
+    RenderLayer::gScrollBar = 0;
+#endif
     
-    bool inside = false;
+    QRect damageRect(m_x, m_y, width(), height());
+    RenderLayer* insideLayer = nodeAtPointForLayer(this, info, x, y, damageRect);
+
+    // Now determine if the result is inside an anchor.
+    DOM::NodeImpl* node = info.innerNode();
+    while (node) {
+        if (node->hasAnchor())
+            info.setURLElement(node);
+        node = node->parentNode();
+    }
+
+    // Next set up the correct :hover/:active state along the new chain.
+    updateHoverActiveState(info);
+
+    // Now return whether we were inside this layer (this will always be true for the root
+    // layer).
+    return insideLayer;
+}
+
+RenderLayer*
+RenderLayer::nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
+                                 int xMousePos, int yMousePos, const QRect& hitTestRect)
+{
+    // Calculate the clip rects we should use.
+    QRect layerBounds, bgRect, fgRect;
+    calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect);
+    
+    // Ensure our z-order lists are up-to-date.
+    updateZOrderLists();
+
+    // This variable tracks which layer the mouse ends up being inside.  The minute we find an insideLayer,
+    // we are done and can return it.
     RenderLayer* insideLayer = 0;
-    QRect damageRect(m_x, m_y, m_width, m_height);
-    RenderZTreeNode* node = constructZTree(damageRect, damageRect, this, true, x, y);
-    if (!node)
-        return false;
-
-    // Flatten the tree into a back-to-front list for painting.
-    QPtrVector<RenderLayerElement> layerList;
-    constructLayerList(node, &layerList);
-
-    // Walk the list and test each layer, adding in the appropriate offset.
-    uint count = layerList.count();
-    for (int i = count-1; i >= 0; i--) {
-        RenderLayerElement* elt = layerList.at(i);
-        
-        // Elements add in their own positions as a translation factor.  This forces
-        // us to subtract that out, so that when it's added back in, we get the right
-        // bounds.  This is really disgusting (that paint only sets up the right paint
-        // position after you call into it). -dwh
-        //printf("Painting layer at %d %d\n", elt->absBounds.x(), elt->absBounds.y());
-
-        inside = elt->layer->renderer()->nodeAtPoint(info, x, y,
-                                      elt->absBounds.x() - elt->layer->renderer()->xPos(),
-                                      elt->absBounds.y() - elt->layer->renderer()->yPos());
-        if (inside) {
-            // For foreground layer elements where the layer has been split into two, we
-            // are only considered to be inside the foreground layer if we hit content other
-            // than ourselves.
-            if (elt->layerElementType == RenderLayerElement::Foreground &&
-                info.innerNode() == elt->layer->renderer()->element()) {
-                inside = false;
-                info.setInnerNode(0);
-                info.setInnerNonSharedNode(0);
-                info.setURLElement(0);
-                continue;
-            }
-            // Otherwise the mouse is inside this layer, and we can stop looking.
-            insideLayer = elt->layer;
-            break;
+    
+    // Begin by walking our list of positive layers from highest z-index down to the lowest
+    // z-index.
+    if (m_posZOrderList) {
+        uint count = m_posZOrderList->count();
+        for (int i = count-1; i >= 0; i--) {
+            RenderLayer* child = m_posZOrderList->at(i);
+            insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
+            if (insideLayer)
+                return insideLayer;
         }
     }
-    node->detach(renderer()->renderArena());
 
-    if (insideLayer) {
-        // Clear out the other layers' hover/active state
-        insideLayer->clearOtherLayersHoverActiveState();
-    
-        // Now clear out our descendant layers
-        for (RenderLayer* child = insideLayer->firstChild();
-             child; child = child->nextSibling())
-            child->clearHoverAndActiveState(child->renderer());
+    // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
+    if (containsPoint(xMousePos, yMousePos, fgRect) &&
+        renderer()->nodeAtPoint(info, xMousePos, yMousePos,
+                                layerBounds.x() - renderer()->xPos(),
+                                layerBounds.y() - renderer()->yPos(),
+                                HitTestChildrenOnly))
+        return this;
+        
+    // Now check our negative z-index children.
+    if (m_negZOrderList) {
+        uint count = m_negZOrderList->count();
+        for (int i = count-1; i >= 0; i--) {
+            RenderLayer* child = m_negZOrderList->at(i);
+            insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
+            if (insideLayer)
+                return insideLayer;
+        }
     }
-    
-    return inside;
+
+    // Next we want to see if the mouse pos is inside this layer but not any of its children.
+    if (containsPoint(xMousePos, yMousePos, bgRect) &&
+        renderer()->nodeAtPoint(info, xMousePos, yMousePos,
+                                layerBounds.x() - renderer()->xPos(),
+                                layerBounds.y() - renderer()->yPos(),
+                                HitTestSelfOnly))
+        return this;
+
+    // No luck.
+    return 0;
 }
 
-RenderLayer::RenderZTreeNode*
-RenderLayer::constructZTree(QRect overflowClipRect, QRect posClipRect,
-                            RenderLayer* rootLayer,
-                            bool eventProcessing, int xMousePos, int yMousePos)
+void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, QRect& overflowClipRect,
+                                     QRect& posClipRect, QRect& fixedClipRect)
 {
-    // The arena we use for allocating our temporary ztree elements.
-    RenderArena* renderArena = renderer()->renderArena();
-    
-    // This variable stores the result we will hand back.
-    RenderZTreeNode* returnNode = 0;
-
-    // FIXME: A child render object or layer could override visibility.  Don't remove this
-    // optimization though until nodeAtPoint is patched as well.
-    //
-    // If a layer isn't visible, then none of its child layers are visible either.
-    // Don't build this branch of the z-tree, since these layers should not be painted.
-    if (renderer()->style()->visibility() != VISIBLE)
-        return 0;
-    
-    // Compute this layer's absolute position, so that we can compare it with our
-    // damage rect and avoid repainting the layer if it falls outside that rect.
-    // An exception to this rule is the root layer, which always paints (hence the
-    // m_parent null check below).
-    updateLayerPosition(); // For relpositioned layers or non-positioned layers,
-                            // we need to keep in sync, since we may have shifted relative
-                            // to our parent layer.
-                               
-    int x = 0;
-    int y = 0;
-    convertToLayerCoords(rootLayer, x, y);
-    QRect layerBounds(x, y, width(), height());
-     
-    returnNode = new (renderArena) RenderZTreeNode(this);
-
-    // Positioned elements are clipped according to the posClipRect.  All other
-    // layers are clipped according to the overflowClipRect.
-    QRect clipRectToApply = m_object->isPositioned() ? posClipRect : overflowClipRect;
-    QRect damageRect = clipRectToApply.intersect(layerBounds);
-    
-    // Clip applies to *us* as well, so go ahead and update the damageRect.
-    if (m_object->hasClip())
-        damageRect = damageRect.intersect(m_object->getClipRect(x,y));
+    if (parent())
+        parent()->calculateClipRects(rootLayer, overflowClipRect, posClipRect, fixedClipRect);
         
-    // If we establish a clip rect, then we want to intersect that rect
-    // with the damage rect to form a new damage rect.
-    bool clipOriginator = false;
+    updateLayerPosition(); // For relpositioned layers or non-positioned layers,
+                           // we need to keep in sync, since we may have shifted relative
+                           // to our parent layer.
+
+    // A fixed object is essentially the root of its containing block hierarchy, so when
+    // we encounter such an object, we reset our clip rects to the fixedClipRect.
+    if (m_object->style()->position() == FIXED) {
+        posClipRect = fixedClipRect;
+        overflowClipRect = fixedClipRect;
+    }
+    else if (m_object->style()->position() == RELATIVE)
+        posClipRect = overflowClipRect;
     
-    // Update the clip rects that will be passed to children layers.
+    // Update the clip rects that will be passed to child layers.
     if (m_object->hasOverflowClip() || m_object->hasClip()) {
         // This layer establishes a clip of some kind.
-        clipOriginator = true;
+        int x = 0;
+        int y = 0;
+        convertToLayerCoords(rootLayer, x, y);
+        
         if (m_object->hasOverflowClip()) {
             QRect newOverflowClip = m_object->getOverflowClipRect(x,y);
             overflowClipRect  = newOverflowClip.intersect(overflowClipRect);
-            clipRectToApply = clipRectToApply.intersect(newOverflowClip);
             if (m_object->isPositioned() || m_object->isRelPositioned())
                 posClipRect = newOverflowClip.intersect(posClipRect);
         }
         if (m_object->hasClip()) {
             QRect newPosClip = m_object->getClipRect(x,y);
-            posClipRect = newPosClip.intersect(posClipRect);
-            overflowClipRect = overflowClipRect.intersect(posClipRect);
-            clipRectToApply = clipRectToApply.intersect(newPosClip);
+            posClipRect = posClipRect.intersect(newPosClip);
+            overflowClipRect = overflowClipRect.intersect(newPosClip);
+            fixedClipRect = fixedClipRect.intersect(newPosClip);
         }
     }
+}
+
+void RenderLayer::calculateRects(const RenderLayer* rootLayer, const QRect& paintDirtyRect, QRect& layerBounds,
+                                 QRect& backgroundRect, QRect& foregroundRect)
+{
+    QRect overflowClipRect = paintDirtyRect;
+    QRect posClipRect = paintDirtyRect;
+    QRect fixedClipRect = paintDirtyRect;
+    if (parent())
+        parent()->calculateClipRects(rootLayer, overflowClipRect, posClipRect, fixedClipRect);
+
+    updateLayerPosition();
     
-    // Walk our list of child layers looking only for those layers that have a 
-    // non-negative z-index (a z-index >= 0).
-    RenderZTreeNode* lastChildNode = 0;
-    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
-        if (child->zIndex() < 0)
-            continue; // Ignore negative z-indices in this first pass.
-
-        RenderZTreeNode* childNode = child->constructZTree(overflowClipRect, posClipRect, 
-                                                           rootLayer, eventProcessing, 
-                                                           xMousePos, yMousePos);
-        if (childNode) {
-            // Put the new node into the tree at the front of the parent's list.
-            if (lastChildNode)
-                lastChildNode->next = childNode;
-            else
-                returnNode->child = childNode;
-            lastChildNode = childNode;
-        }
-    }
+    int x = 0;
+    int y = 0;
+    convertToLayerCoords(rootLayer, x, y);
+    layerBounds = QRect(x,y,width(),height());
 
-    // Now add a leaf node for ourselves, but only if we intersect the damage
-    // rect.  This intersection test is valid only for replaced elements or
-    // block elements, since inline non-replaced elements have a width of 0 (and
-    // thus the layer does too).  We also exclude the root from this test, since
-    // the HTML can be much taller than the root (because of scrolling).
-    if (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||
-        renderer()->hasOverhangingFloats() || 
-        (renderer()->isInline() && !renderer()->isReplaced()) ||
-        (eventProcessing && damageRect.contains(xMousePos,yMousePos)) ||
-        (!eventProcessing && layerBounds.intersects(damageRect))) {
-        RenderLayerElement* layerElt = new (renderArena) RenderLayerElement(this, layerBounds, 
-                                                              damageRect, clipRectToApply,
-                                                              clipOriginator, x, y);
-        if (returnNode->child) {
-            RenderZTreeNode* leaf = new (renderArena) RenderZTreeNode(layerElt);
-            leaf->next = returnNode->child;
-            returnNode->child = leaf;
-            
-            // We are an interior node and have other child layers.  Our layer
-            // will need to be sorted with the other layers as though it has
-            // a z-index of 0.
-            if (!layerElt->zauto)
-                layerElt->zindex = 0;
-        }
-        else
-            returnNode->layerElement = layerElt;
-    } 
+    backgroundRect = m_object->style()->position() == FIXED ? fixedClipRect :
+        (m_object->isPositioned() ? posClipRect : overflowClipRect);
+    foregroundRect = backgroundRect;
     
-    // Now look for children that have a negative z-index.
-    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
-        if (child->zIndex() >= 0)
-            continue; // Ignore non-negative z-indices in this second pass.
-
-        RenderZTreeNode* childNode = child->constructZTree(overflowClipRect, posClipRect,
-                                                           rootLayer, eventProcessing,
-                                                           xMousePos, yMousePos);
-        if (childNode) {
-            // Deal with the case where all our children views had negative z-indices.
-            // Demote our leaf node and make a new interior node that can hold these
-            // children.
-            if (returnNode->layerElement) {
-                RenderZTreeNode* leaf = returnNode;
-                returnNode = new (renderArena) RenderZTreeNode(this);
-                returnNode->child = leaf;
-            }
-            
-            // Put the new node into the tree at the front of the parent's list.
-            childNode->next = returnNode->child;
-            returnNode->child = childNode;
+    // Update the clip rects that will be passed to child layers.
+    if (m_object->hasOverflowClip() || m_object->hasClip()) {
+        // This layer establishes a clip of some kind.
+        if (m_object->hasOverflowClip())
+            foregroundRect = foregroundRect.intersect(m_object->getOverflowClipRect(x,y));
+        if (m_object->hasClip()) {
+            // Clip applies to *us* as well, so go ahead and update the damageRect.
+            QRect newPosClip = m_object->getClipRect(x,y);
+            backgroundRect = backgroundRect.intersect(newPosClip);
+            foregroundRect = foregroundRect.intersect(newPosClip);
         }
+
+        // If we establish a clip at all, then go ahead and make sure our background
+        // rect is intersected with our layer's bounds.
+        backgroundRect = backgroundRect.intersect(layerBounds);
     }
-    
-    return returnNode;
 }
 
-void
-RenderLayer::constructLayerList(RenderZTreeNode* ztree, QPtrVector<RenderLayerElement>* result)
+bool RenderLayer::intersectsDamageRect(const QRect& layerBounds, const QRect& damageRect) const
+{
+    return (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||
+            renderer()->hasOverhangingFloats() ||
+            (renderer()->isInline() && !renderer()->isReplaced()) ||
+            layerBounds.intersects(damageRect));
+}
+
+bool RenderLayer::containsPoint(int x, int y, const QRect& damageRect) const
+{
+    return (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||
+            renderer()->hasOverhangingFloats() ||
+            (renderer()->isInline() && !renderer()->isReplaced()) ||
+            damageRect.contains(x, y));
+}
+
+// This code has been written to anticipate the addition of CSS3-::outside and ::inside generated
+// content (and perhaps XBL).  That's why it uses the render tree and not the DOM tree.
+static RenderObject* hoverAncestor(RenderObject* obj)
 {
-    // This merge buffer is just a temporary used during computation as we do merge sorting.
-    QPtrVector<RenderLayerElement> mergeBuffer;
-    ztree->constructLayerList(&mergeBuffer, result);
+    return (!obj->isInline() && obj->continuation()) ? obj->continuation() : obj->parent();
+}
+
+static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
+{
+    if (!obj1 || !obj2)
+        return 0;
+
+    for (RenderObject* currObj1 = obj1; currObj1; currObj1 = hoverAncestor(currObj1))
+        for (RenderObject* currObj2 = obj2; currObj2; currObj2 = hoverAncestor(currObj2))
+            if (currObj1 == currObj2)
+                return currObj1;
+
+    return 0;
+}
+
+void RenderLayer::updateHoverActiveState(RenderObject::NodeInfo& info)
+{
+    // We don't update :hover/:active state when the info is marked as readonly.
+    if (info.readonly())
+        return;
+    
+    // Check to see if the hovered node has changed.  If not, then we don't need to
+    // do anything.  An exception is if we just went from :hover into :hover:active,
+    // in which case we need to update to get the new :active state.
+    DOM::DocumentImpl* doc = renderer()->document();
+    DOM::NodeImpl* oldHoverNode = doc ? doc->hoverNode() : 0;
+    DOM::NodeImpl* newHoverNode = info.innerNode();
+        
+    if (oldHoverNode == newHoverNode && (!oldHoverNode || oldHoverNode->active() == info.active()))
+        return;
+
+    // Update our current hover node.
+    info.innerNode()->getDocument()->setHoverNode(newHoverNode);
+    
+    // We have two different objects.  Fetch their renderers.
+    RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
+    RenderObject* newHoverObj = info.innerNode() ? info.innerNode()->renderer() : 0;
+    
+    // Locate the common ancestor render object for the two renderers.
+    RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
+    
+    // The old hover path only needs to be cleared up to (and not including) the common ancestor;
+    for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = hoverAncestor(curr)) {
+        curr->setMouseInside(false);
+        if (curr->element() && !curr->isText()) {
+            bool oldActive = curr->element()->active();
+            curr->element()->setActive(false);
+            if (curr->style()->affectedByHoverRules() ||
+                (curr->style()->affectedByActiveRules() && oldActive))
+                curr->element()->setChanged();
+        }
+    }
+
+    // Now set the hover state for our new object up to the root.
+    for (RenderObject* curr = newHoverObj; curr; curr = hoverAncestor(curr)) {
+        bool oldInside = curr->mouseInside();
+        curr->setMouseInside(true);
+        if (curr->element() && !curr->isText()) {
+            bool oldActive = curr->element()->active();
+            curr->element()->setActive(info.active());
+            if ((curr->style()->affectedByHoverRules() && !oldInside) ||
+                (curr->style()->affectedByActiveRules() && oldActive != info.active()))
+                curr->element()->setChanged();
+        }
+    }
 }
 
 // Sort the buffer from lowest z-index to highest.  The common scenario will have
 // most z-indices equal, so we optimize for that case (i.e., the list will be mostly
 // sorted already).
-static void sortByZOrder(QPtrVector<RenderLayer::RenderLayerElement>* buffer,
-                         QPtrVector<RenderLayer::RenderLayerElement>* mergeBuffer,
-                         uint start,
-                         uint end)
+static void sortByZOrder(QPtrVector<RenderLayer::RenderLayer>* buffer,
+                         QPtrVector<RenderLayer::RenderLayer>* mergeBuffer,
+                         uint start, uint end)
 {
     if (start >= end)
         return; // Sanity check.
@@ -1011,9 +959,9 @@ static void sortByZOrder(QPtrVector<Rend
         for (uint i = end-1; i > start; i--) {
             bool sorted = true;
             for (uint j = start; j < i; j++) {
-                RenderLayer::RenderLayerElement* elt = buffer->at(j);
-                RenderLayer::RenderLayerElement* elt2 = buffer->at(j+1);
-                if (elt->zindex > elt2->zindex) {
+                RenderLayer* elt = buffer->at(j);
+                RenderLayer* elt2 = buffer->at(j+1);
+                if (elt->zIndex() > elt2->zIndex()) {
                     sorted = false;
                     buffer->insert(j, elt2);
                     buffer->insert(j+1, elt);
@@ -1029,12 +977,12 @@ static void sortByZOrder(QPtrVector<Rend
         sortByZOrder(buffer, mergeBuffer, start, mid);
         sortByZOrder(buffer, mergeBuffer, mid, end);
 
-        RenderLayer::RenderLayerElement* elt = buffer->at(mid-1);
-        RenderLayer::RenderLayerElement* elt2 = buffer->at(mid);
+        RenderLayer* elt = buffer->at(mid-1);
+        RenderLayer* elt2 = buffer->at(mid);
 
         // Handle the fast common case (of equal z-indices).  The list may already
         // be completely sorted.
-        if (elt->zindex <= elt2->zindex)
+        if (elt->zIndex() <= elt2->zIndex())
             return;
 
         // We have to merge sort.  Ensure our merge buffer is big enough to hold
@@ -1047,7 +995,7 @@ static void sortByZOrder(QPtrVector<Rend
         elt2 = buffer->at(i2);
 
         while (i1 < mid || i2 < end) {
-            if (i1 < mid && (i2 == end || elt->zindex <= elt2->zindex)) {
+            if (i1 < mid && (i2 == end || elt->zIndex() <= elt2->zIndex())) {
                 mergeBuffer->insert(mergeBuffer->count(), elt);
                 i1++;
                 if (i1 < mid)
@@ -1067,161 +1015,63 @@ static void sortByZOrder(QPtrVector<Rend
         mergeBuffer->clear();
     }
 }
-
-void RenderLayer::RenderZTreeNode::constructLayerList(QPtrVector<RenderLayerElement>* mergeTmpBuffer,
-                                                      QPtrVector<RenderLayerElement>* buffer)
-{
-    // The root always establishes a stacking context.  We could add a rule for this
-    // to the UA sheet, but this code guarantees that nobody can do anything wacky
-    // in CSS to prevent the root from establishing a stacking context.
-    bool autoZIndex = layer->parent() ? layer->hasAutoZIndex() : false;
-    int explicitZIndex = layer->zIndex();
-
-    if (layerElement) {
-        // We are a leaf node of the ztree, and so we just place our layer element into
-        // the buffer.
-        if (buffer->count() == buffer->size())
-            // Resize by a power of 2.
-            buffer->resize(2*(buffer->size()+1));
-        
-        buffer->insert(buffer->count(), layerElement);
-        return;
-    }
-
-    uint startIndex = buffer->count();
-    for (RenderZTreeNode* current = child; current; current = current->next)
-        current->constructLayerList(mergeTmpBuffer, buffer);
-    uint endIndex = buffer->count();
-
-    if (autoZIndex || !(endIndex-startIndex))
-        return; // We just had to collect the kids.  We don't apply a sort to them, since
-                // they will actually be layered in some ancestor layer's stacking context.
-    
-    sortByZOrder(buffer, mergeTmpBuffer, startIndex, endIndex);
-
-    // Find out if we have any elements with negative z-indices in this stacking context.
-    // If so, then we need to split our layer in two (a background layer and a foreground
-    // layer).  We then put the background layer before the negative z-index objects, and
-    // leave the foreground layer in the position previously occupied by the unsplit original.
-    RenderLayerElement* elt = buffer->at(startIndex);
-    if (elt->zindex < 0) {
-        // Locate our layer in the layer list.
-        for (uint i = startIndex; i < endIndex; i++) {
-            elt = buffer->at(i);
-            if (elt->layer == layer) {
-                // Clone the layer element.
-                RenderLayerElement* bgLayer =
-                  new (layer->renderer()->renderArena()) RenderLayerElement(*elt);
-
-                // Set the layer types (foreground and background) on the two layer elements.
-                elt->layerElementType = RenderLayerElement::Foreground;
-                bgLayer->layerElementType = RenderLayerElement::Background;
-
-                // Ensure our buffer is big enough to hold a new layer element.
-                if (buffer->count() == buffer->size())
-                    // Resize by a power of 2.
-                    buffer->resize(2*(buffer->size()+1));
-
-                // Insert the background layer element at the front of our sorted list.
-                for (uint j = buffer->count(); j > startIndex; j--)
-                    buffer->insert(j, buffer->at(j-1));
-                buffer->insert(startIndex, bgLayer);
-
-                // Augment endIndex since we added a layer element.
-                endIndex++;
-                break;
-            }
-        }
-    }
-    
-    // Now set all of the elements' z-indices to match the parent's explicit z-index, so that
-    // they will be layered properly in the ancestor layer's stacking context.
-    for (uint i = startIndex; i < endIndex; i++) {
-        elt = buffer->at(i);
-        elt->zindex = explicitZIndex;
-    }
-}
 
-void* RenderLayer::RenderLayerElement::operator new(size_t sz, RenderArena* renderArena) throw()
+void RenderLayer::dirtyZOrderLists()
 {
-    void* result = renderArena->allocate(sz);
-    if (result)
-        memset(result, 0, sz);
-    return result;
+    if (m_posZOrderList)
+        m_posZOrderList->clear();
+    if (m_negZOrderList)
+        m_negZOrderList->clear();
+    m_zOrderListsDirty = true;
 }
-
-void RenderLayer::RenderLayerElement::operator delete(void* ptr, size_t sz)
-{
-    assert(inRenderLayerElementDetach);
     
-    // Stash size where detach can find it.
-    *(size_t *)ptr = sz;
-}
-
-void RenderLayer::RenderLayerElement::detach(RenderArena* renderArena)
+void RenderLayer::updateZOrderLists()
 {
-#ifndef NDEBUG
-    inRenderLayerElementDetach = true;
-#endif
-    delete this;
-#ifndef NDEBUG
-    inRenderLayerElementDetach = false;
-#endif
-    
-    // Recover the size left there for us by operator delete and free the memory.
-    renderArena->free(*(size_t *)this, this);
-}
-
-void* RenderLayer::RenderZTreeNode::operator new(size_t sz, RenderArena* renderArena) throw()
-{
-    void* result = renderArena->allocate(sz);
-    if (result)
-        memset(result, 0, sz);
-    return result;
-}
-
-void RenderLayer::RenderZTreeNode::operator delete(void* ptr, size_t sz)
-{
-    assert(inRenderZTreeNodeDetach);
+    if (!isStackingContext() || !m_zOrderListsDirty)
+        return;
     
-    // Stash size where detach can find it.
-    *(size_t *)ptr = sz;
-}
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        child->collectLayers(m_posZOrderList, m_negZOrderList);
 
-void RenderLayer::RenderZTreeNode::detach(RenderArena* renderArena)
-{
-    assert(!next);
-    
-    RenderZTreeNode *n;
-    for (RenderZTreeNode *c = child; c; c = n) {
-        n = c->next;
-        c->next = 0;
-        c->detach(renderArena);
+    // Sort the two lists.
+    if (m_posZOrderList) {
+        QPtrVector<RenderLayer> mergeBuffer;
+        sortByZOrder(m_posZOrderList, &mergeBuffer, 0, m_posZOrderList->count());
     }
-    if (layerElement)
-        layerElement->detach(renderArena);
+    if (m_negZOrderList) {
+        QPtrVector<RenderLayer> mergeBuffer;
+        sortByZOrder(m_negZOrderList, &mergeBuffer, 0, m_negZOrderList->count());
+    }
 
-#ifndef NDEBUG
-    inRenderZTreeNodeDetach = true;
-#endif
-    delete this;
-#ifndef NDEBUG
-    inRenderZTreeNodeDetach = false;
-#endif
-    
-    // Recover the size left there for us by operator delete and free the memory.
-    renderArena->free(*(size_t *)this, this);
+    m_zOrderListsDirty = false;
 }
 
-QPtrVector<RenderLayer::RenderLayerElement> RenderLayer::elementList(RenderZTreeNode *&node)
+void RenderLayer::collectLayers(QPtrVector<RenderLayer>*& posBuffer, QPtrVector<RenderLayer>*& negBuffer)
 {
-    QPtrVector<RenderLayerElement> list;
+    // FIXME: A child render object or layer could override visibility.  Don't remove this
+    // optimization though until RenderObject's nodeAtPoint is patched to understand what to do
+    // when visibility is overridden by a child.
+    if (renderer()->style()->visibility() != VISIBLE)
+        return;
     
-    QRect damageRect(m_x, m_y, m_width, m_height);
-    node = constructZTree(damageRect, damageRect, this);
-    if (node) {
-        constructLayerList(node, &list);
+    // Determine which buffer the child should be in.
+    QPtrVector<RenderLayer>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
+
+    // Create the buffer if it doesn't exist yet.
+    if (!buffer)
+        buffer = new QPtrVector<RenderLayer>();
+    
+    // Resize by a power of 2 when our buffer fills up.
+    if (buffer->count() == buffer->size())
+        buffer->resize(2*(buffer->size()+1));
+
+    // Append ourselves at the end of the appropriate buffer.
+    buffer->insert(buffer->count(), this);
+
+    // Recur into our children to collect more layers, but only if we don't establish
+    // a stacking context.
+    if (!isStackingContext()) {
+        for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+            child->collectLayers(posBuffer, negBuffer);
     }
-    
-    return list;
 }
Index: khtml/rendering/render_layer.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_layer.h,v
retrieving revision 1.27
diff -u -p -r1.27 khtml/rendering/render_layer.h
--- khtml/rendering/render_layer.h	2003/07/11 17:55:42	1.27
+++ khtml/rendering/render_layer.h	2003/09/02 17:44:21
@@ -49,9 +49,10 @@
 #include <assert.h>
 
 #include "render_object.h"
-#include <qvector.h>
-#include <qscrollbar.h>
 
+class QScrollBar;
+template <class T> class QPtrVector;
+
 namespace khtml {
     class RenderStyle;
     class RenderTable;
@@ -60,7 +61,8 @@ namespace khtml {
     class RenderText;
     class RenderFrameSet;
     class RenderObject;
-
+    class RenderScrollMediator;
+    
 class RenderScrollMediator: public QObject
 {
 public:
@@ -76,6 +78,10 @@ private:
 class RenderLayer
 {
 public:
+#ifdef APPLE_CHANGES
+    static QScrollBar* gScrollBar;
+#endif
+    
     RenderLayer(RenderObject* object);
     ~RenderLayer();
     
@@ -90,14 +96,13 @@ public:
     void addChild(RenderLayer *newChild, RenderLayer* beforeChild = 0);
     RenderLayer* removeChild(RenderLayer *oldChild);
 
-    RenderLayer* transparentAncestor();
-    bool isTransparent();
-    void updateTransparentState(QPainter* painter, RenderLayer* newLayer, RenderLayer*& currLayer);
-    void beginTransparencyLayers(QPainter* painter, RenderLayer* newLayer, RenderLayer* ancestorLayer);
-    void endTransparencyLayers(QPainter* painter, RenderLayer* newLayer, RenderLayer* ancestorLayer);
-    
     void removeOnlyThisLayer();
     void insertOnlyThisLayer();
+
+#if APPLE_CHANGES
+    bool isTransparent();
+    RenderLayer* transparentAncestor();
+#endif
     
     RenderLayer* root() {
         RenderLayer* curr = this;
@@ -109,15 +114,13 @@ public:
     int yPos() const { return m_y; }
     short width() const { return m_width; }
     int height() const { return m_height; }
+
+    void setWidth(short w) { m_width = w; }
+    void setHeight(int h) { m_height = h; }
+    
     short scrollWidth() const { return m_scrollWidth; }
     int scrollHeight() const { return m_scrollHeight; }
     
-    void setWidth( int width ) {
-        m_width = width;
-    }
-    void setHeight( int height ) {
-        m_height = height;
-    }
     void setPos( int xPos, int yPos ) {
         m_x = xPos;
         m_y = yPos;
@@ -133,40 +136,62 @@ public:
     void scrollToYOffset(int y) { scrollToOffset(m_scrollX, y); }
     void setHasHorizontalScrollbar(bool hasScrollbar);
     void setHasVerticalScrollbar(bool hasScrollbar);
-    QWidget* horizontalScrollbar() { return m_hBar; }
-    QWidget* verticalScrollbar() { return m_vBar; }
+    QScrollBar* horizontalScrollbar() { return m_hBar; }
+    QScrollBar* verticalScrollbar() { return m_vBar; }
     int verticalScrollbarWidth();
     int horizontalScrollbarHeight();
     void moveScrollbarsAside();
     void positionScrollbars(const QRect& absBounds);
-    void paintScrollbars(QPainter* p, int x, int y, int w, int h);
+#ifdef APPLE_CHANGES
+    void paintScrollbars(QPainter* p, const QRect& damageRect);
+#endif
     void checkScrollbarsAfterLayout();
     void slotValueChanged(int);
     void updateScrollPositionFromScrollbars();
-    
+
     void updateLayerPosition();
+
+    // Get the enclosing stacking context for this layer.  A stacking context is a layer
+    // that has a non-auto z-index.
+    RenderLayer* stackingContext() const;
+    bool isStackingContext() const { return !hasAutoZIndex() || renderer()->isCanvas(); }
+
+    void dirtyZOrderLists();
+    void updateZOrderLists();
+    QPtrVector<RenderLayer>* posZOrderList() const { return m_posZOrderList; }
+    QPtrVector<RenderLayer>* negZOrderList() const { return m_negZOrderList; }
     
     // Gets the nearest enclosing positioned ancestor layer (also includes
     // the <html> layer and the root layer).
-    RenderLayer* enclosingPositionedAncestor();
+    RenderLayer* enclosingPositionedAncestor() const;
     
-    void convertToLayerCoords(RenderLayer* ancestorLayer, int& x, int& y);
+    void convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const;
     
-    bool hasAutoZIndex() { return renderer()->style()->hasAutoZIndex(); }
-    int zIndex() { return renderer()->style()->zIndex(); }
+    bool hasAutoZIndex() const { return renderer()->style()->hasAutoZIndex(); }
+    int zIndex() const { return renderer()->style()->zIndex(); }
 
     // The two main functions that use the layer system.  The paint method
     // paints the layers that intersect the damage rect from back to
     // front.  The nodeAtPoint method looks for mouse events by walking
     // layers that intersect the point from front to back.
-    void paint(QPainter *p, int x, int y, int w, int h, bool selectionOnly=false);
+    void paint(QPainter *p, const QRect& damageRect, bool selectionOnly=false);
     bool nodeAtPoint(RenderObject::NodeInfo& info, int x, int y);
+
+    // This method figures out our layerBounds in coordinates relative to
+    // |rootLayer}.  It also computes our background and foreground clip rects
+    // for painting/event handling.
+    void calculateRects(const RenderLayer* rootLayer, const QRect& paintDirtyRect, QRect& layerBounds,
+                        QRect& backgroundRect, QRect& foregroundRect);
+    void calculateClipRects(const RenderLayer* rootLayer, QRect& overflowClipRect,
+                            QRect& posClipRect, QRect& fixedClipRect);
+
+    bool intersectsDamageRect(const QRect& layerBounds, const QRect& damageRect) const;
+    bool containsPoint(int x, int y, const QRect& damageRect) const;
     
-    void clearOtherLayersHoverActiveState();
-    void clearHoverAndActiveState(RenderObject* obj);
+    void updateHoverActiveState(RenderObject::NodeInfo& info);
     
     void detach(RenderArena* renderArena);
-    
+
      // Overloaded new operator.  Derived classes must override operator new
     // in order to allocate out of the RenderArena.
     void* operator new(size_t sz, RenderArena* renderArena) throw();    
@@ -178,179 +203,6 @@ private:
     // The normal operator new is disallowed on all render objects.
     void* operator new(size_t sz) throw();
 
-public:
-    // Z-Index Implementation Notes
-    //
-    // In order to properly handle mouse events as well as painting,
-    // we must compute a correct list of layers that should be painted
-    // from back to front (and for mouse events walked from front to
-    // back).
-    //
-    // Positioned elements in the render tree (e.g., relative positioned
-    // divs and absolute positioned divs) have a corresponding layer
-    // that holds them and all children that reside in the same layer.
-    //
-    // When painting is performed on a layer, all render objects in that
-    // layer are painted.  If the render object has descendants in another
-    // layer, those will be dealt with separately.
-    //
-    // A RenderLayerElement represents a single entry in our list of
-    // layers that should be painted.  We perform computations as we
-    // build up this list so that we have the correct translation factor
-    // for painting.  We also use a temporary z-index variable for storage
-    // (more on this below).
-    // 
-    struct RenderLayerElement {
-      enum LayerElementType { Normal, Background, Foreground };
-        
-      RenderLayer* layer;
-      QRect absBounds; // Our bounds in absolute coordinates relative to the root.
-      QRect backgroundClipRect; // Clip rect used for our background/borders. 
-      QRect clipRect; // Clip rect used for our children.
-      int zindex; // Temporary z-index used for processing and sorting.
-      bool zauto : 1; // Whether or not we are using auto z-indexing.
-      bool clipOriginator : 1; // Whether or not we established a clip.
-      int x; // The coords relative to the layer that will be using this list
-             // to paint.
-      int y;
-      LayerElementType layerElementType; // For negative z-indices, we have to split a single layer into two
-                           // RenderLayerElements, one that sits beneath the negative content, and
-                           // another that sits above (denoted with values of Background and Foreground,
-                           // respectively).  A normal layer that fully paints is denoted with the value Normal.
-      
-      RenderLayerElement(RenderLayer* l, const QRect& rect, const QRect& bgclip, 
-                         const QRect& clip, bool clipOrig, int xpos, int ypos,
-                         LayerElementType lType = Normal)
-          :layer(l), absBounds(rect), backgroundClipRect(bgclip), clipRect(clip), 
-           zindex(l->zIndex()), zauto(l->hasAutoZIndex()), clipOriginator(clipOrig),
-           x(xpos), y(ypos), layerElementType(lType) {}
-          
-      void detach(RenderArena* renderArena);
-    
-      // Overloaded new operator.  Derived classes must override operator new
-      // in order to allocate out of the RenderArena.
-      void* operator new(size_t sz, RenderArena* renderArena) throw();    
-
-      // Overridden to prevent the normal delete from being called.
-      void operator delete(void* ptr, size_t sz);
-        
-      // The normal operator new is disallowed.
-      void* operator new(size_t sz) throw();
-    };
-
-    // The list of layer elements is built through a recursive examination
-    // of a tree of z nodes. This tree structure mimics the layer 
-    // hierarchy itself, but only leaf nodes represent items that will
-    // end up in the layer list for painting.
-    //
-    // Every leaf layer in the layer hierarchy will have a corresponding
-    // leaf node in the z-tree.  Layers with children have an
-    // interior z-tree node that contains the tree nodes for the child
-    // layers as well as a leaf node that represents the containing layer.
-    //
-    // Sibling z-tree nodes match the same order as the layers in the
-    // layer hierarchy, which will have been arranged in document order
-    // when the render tree was constructed (since the render tree
-    // constructed the layers).  An exception is if a negative z-index
-    // is specified on a child (see below).
-    
-    struct RenderZTreeNode {
-      RenderLayer* layer;
-      RenderZTreeNode* next;
-
-      // Only one of these will ever be defined.
-      RenderZTreeNode* child; // Defined for interior nodes.
-      RenderLayerElement* layerElement; // Defined for leaf nodes.
-
-      RenderZTreeNode(RenderLayer* l)
-          :layer(l), next(0), child(0), layerElement(0) {}
-
-      RenderZTreeNode(RenderLayerElement* layerElt)
-          :layer(layerElt->layer), next(0), child(0), layerElement(layerElt) {}
-      
-      ~RenderZTreeNode() {}
-
-      void constructLayerList(QPtrVector<RenderLayerElement>* mergeTmpBuffer,
-                              QPtrVector<RenderLayerElement>* finalBuffer);
-      
-      void detach(RenderArena* renderArena);
-          
-      // Overloaded new operator.  Derived classes must override operator new
-      // in order to allocate out of the RenderArena.
-      void* operator new(size_t sz, RenderArena* renderArena) throw();    
-
-      // Overridden to prevent the normal delete from being called.
-      void operator delete(void* ptr, size_t sz);
-        
-      // The normal operator new is disallowed.
-      void* operator new(size_t sz) throw();
-    };
-
-    static QWidget* gScrollBar;
-
-    // For debugging.
-    QPtrVector<RenderLayerElement> elementList(RenderZTreeNode *&node);
-      
-private:
-    // The constructZTree function creates a z-tree for a given layer hierarchy
-    // rooted on this layer.  It will ensure that immediate child
-    // elements of a given z-tree node are at least initially sorted
-    // into <negative z-index children>, <this layer>, <non-negative z-index
-    // children>.
-    //
-    // Here is a concrete example (lifted from Gecko's view system,
-    // which is analogous to our layer system and works the same way):
-    // z-index values as specified by CSS are shown in parentheses.
-    //
-    // L0(auto) --> L1(0) --> L2(auto) --> L3(0)
-    // |        |    +------> L4(2)
-    // |        +-----------> L5(1)
-    // +--------------------> L6(1)
-    //
-    // The corresponding z-tree for this layer hierarchy will be
-    // the following, where |I| represents an interior node, and |L|
-    // represents a leaf RenderLayerElement.
-    //
-    // I(L0) --> L(L0)
-    // +-------> I(L1) --------> L(L1)
-    // |           |   +-------> I(L2) ------> L(L2)
-    // |           |               +---------> L(L3)
-    // |           +-----------> L(L4)
-    // +-------> L(L5)
-    // +-------> L(L6)
-    //
-    RenderZTreeNode* constructZTree(QRect overflowClipRect,
-                                    QRect clipRect,
-                                    RenderLayer* rootLayer,
-                                    bool eventProcessing = false, int x=0, int y=0);
-
-    // Once the z-tree has been constructed, we call constructLayerList
-    // to produce a flattened layer list for rendering/event handling.
-    // This function recursively computes a layer list for each z-tree
-    // node by computing lists for each child node.  It then concatenates
-    // them and sorts them by z-index.
-    //
-    // Z-indices are updated during this computation.  After a list is
-    // computed for one z-tree node, the elements of the layer list are
-    // all changed so that their z-indices match the specified z-index
-    // of the tree node's layer (unless that layer doesn't establish
-    // a z-index, e.g., it just has z-index: auto).
-    //
-    // Continuing the above example, the computation of the list for
-    // L0 would be as follows:
-    //
-    // I(L2) has a list [ L(L2)(0), L(L3)(0), L(L4)(2) ]
-    // I(L2) is auto so the z-indices of the child layer elements remain
-    // unaltered.
-    // I(L1) has a list [ L(L1)(0), L(L2)(0), L(L3)(0), L(L4)(2), L(L5)(1) ]
-    // The nodes are sorted and then reassigned a z-index of 0, so this
-    // list becomes:
-    // [ L(L1)(0), L(L2)(0), L(L3)(0), L(L5)(0), L(L4)(0) ]
-    // Finally we end up with the list for L0, which sorted becomes:
-    // [ L(L0)(0), L(L1)(0), L(L2)(0), L(L3)(0), L(L5)(0), L(L4)(0), L(L6)(1) ]
-    void constructLayerList(RenderZTreeNode* ztree,
-                            QPtrVector<RenderLayerElement>* result);
-
 private:
     void setNextSibling(RenderLayer* next) { m_next = next; }
     void setPreviousSibling(RenderLayer* prev) { m_previous = prev; }
@@ -358,34 +210,50 @@ private:
     void setFirstChild(RenderLayer* first) { m_first = first; }
     void setLastChild(RenderLayer* last) { m_last = last; }
 
+    void collectLayers(QPtrVector<RenderLayer>*&, QPtrVector<RenderLayer>*&);
+
+    void paintLayer(RenderLayer* rootLayer, QPainter *p, const QRect& paintDirtyRect, bool selectionOnly=false);
+    RenderLayer* nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
+                                     int x, int y, const QRect& hitTestRect);
+
 protected:   
     RenderObject* m_object;
     
-    RenderLayer *m_parent;
-    RenderLayer *m_previous;
-    RenderLayer *m_next;
+    RenderLayer* m_parent;
+    RenderLayer* m_previous;
+    RenderLayer* m_next;
 
-    RenderLayer *m_first;
-    RenderLayer *m_last;
+    RenderLayer* m_first;
+    RenderLayer* m_last;
     
     // Our (x,y) coordinates are in our parent layer's coordinate space.
-    int m_height;
-    int m_y;
     short m_x;
-    short m_width;
+    int m_y;
 
+    // The layer's width/height
+    short m_width;
+    int m_height;
+    
     // Our scroll offsets if the view is scrolled.
     short m_scrollX;
     int m_scrollY;
-
+    
     // The width/height of our scrolled area.
     short m_scrollWidth;
-    short m_scrollHeight;
+    int m_scrollHeight;
     
     // For layers with overflow, we have a pair of scrollbars.
     QScrollBar* m_hBar;
     QScrollBar* m_vBar;
     RenderScrollMediator* m_scrollMediator;
+
+    // For layers that establish stacking contexts, m_posZOrderList holds a sorted list of all the
+    // descendant layers within the stacking context that have z-indices of 0 or greater
+    // (auto will count as 0).  m_negZOrderList holds descendants within our stacking context with negative
+    // z-indices.
+    QPtrVector<RenderLayer>* m_posZOrderList;
+    QPtrVector<RenderLayer>* m_negZOrderList;
+    bool m_zOrderListsDirty;
 };
 
 }; // namespace
Index: khtml/rendering/render_object.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_object.cpp,v
retrieving revision 1.97
diff -u -p -r1.97 khtml/rendering/render_object.cpp
--- khtml/rendering/render_object.cpp	2003/08/20 22:03:24	1.97
+++ khtml/rendering/render_object.cpp	2003/09/02 17:44:22
@@ -983,6 +983,19 @@ void RenderObject::setStyle(RenderStyle 
     if (m_style == style)
         return;
 
+    // If our z-index changes value or our visibility changes,
+    // we need to dirty our stacking context's z-order list.
+    if (m_style && style) {
+        if ((m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
+             m_style->zIndex() != style->zIndex() ||
+             m_style->visibility() != style->visibility()) && layer()) {
+            layer()->stackingContext()->dirtyZOrderLists();
+            if (m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
+                m_style->visibility() != style->visibility())
+                layer()->dirtyZOrderLists();
+        }
+    }
+
     RenderStyle::Diff d = m_style ? m_style->diff( style ) : RenderStyle::Layout;
 
     if (m_style && m_parent && d == RenderStyle::Visible && !isText())
@@ -1220,7 +1233,7 @@ void RenderObject::removeFromObjectLists
     }
 }
 
-RenderArena* RenderObject::renderArena() const
+DOM::DocumentImpl* RenderObject::document() const
 {
     DOM::NodeImpl* elt = element();
     RenderObject* current = parent();
@@ -1228,11 +1241,15 @@ RenderArena* RenderObject::renderArena()
         elt = current->element();
         current = current->parent();
     }
-    if (!elt)
-        return 0;
-    return elt->getDocument()->renderArena();
+    return elt ? elt->getDocument() : 0;
 }
 
+RenderArena* RenderObject::renderArena() const
+{
+    DOM::DocumentImpl* doc = document();
+    return doc ? doc->renderArena() : 0;
+}
+
 
 void RenderObject::detach(RenderArena* renderArena)
 {
@@ -1336,21 +1353,9 @@ bool RenderObject::mouseInside() const
     return m_mouseInside; 
 }
 
-void RenderObject::setHoverAndActive(NodeInfo& info, bool oldinside, bool inside)
+bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                               HitTestAction hitTestAction, bool inside)
 {
-    DOM::NodeImpl* elt = element();
-    if (elt) {
-        bool oldactive = elt->active();
-        if (oldactive != (inside && info.active()))
-            elt->setActive(inside && info.active());
-        if ((oldinside != mouseInside() && style()->affectedByHoverRules()) ||
-            (oldactive != elt->active() && style()->affectedByActiveRules()))
-            elt->setChanged();
-    }
-}
-
-bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, bool inside)
-{
     int tx = _tx + xPos();
     int ty = _ty + yPos();
 
@@ -1363,11 +1368,14 @@ bool RenderObject::nodeAtPoint(NodeInfo&
     }
     
     // ### table should have its own, more performant method
-    if ((!isRenderBlock() ||
+    if (hitTestAction != HitTestSelfOnly &&
+        ((!isRenderBlock() ||
          !static_cast<RenderBlock*>(this)->isPointInScrollbar(_x, _y, _tx, _ty)) &&
         (overhangingContents() || inOverflowRect || isInline() || isCanvas() ||
          isTableRow() || isTableSection() || inside || mouseInside() ||
-         (childrenInline() && firstChild() && firstChild()->isCompact()))) {
+         (childrenInline() && firstChild() && firstChild()->isCompact())))) {
+        if (hitTestAction == HitTestChildrenOnly)
+            inside = false;
         int stx = _tx + xPos();
         int sty = _ty + yPos();
         if (style()->hidesOverflow() && layer())
@@ -1379,6 +1387,15 @@ bool RenderObject::nodeAtPoint(NodeInfo&
     }
 
     if (inside) {
+        if (!info.innerNode() && !isInline() && continuation()) {
+            // We are in the margins of block elements that are part of a continuation.  In
+            // this case we're actually still inside the enclosing inline element that was
+            // split.  Go ahead and set our inner node accordingly.
+            info.setInnerNode(continuation()->element());
+            if (!info.innerNonSharedNode())
+                info.setInnerNonSharedNode(continuation()->element());
+        }
+            
         if (info.innerNode() && info.innerNode()->renderer() && 
             !info.innerNode()->renderer()->isInline() && element() && isInline()) {
             // Within the same layer, inlines are ALWAYS fully above blocks.  Change inner node.
@@ -1394,28 +1411,6 @@ bool RenderObject::nodeAtPoint(NodeInfo&
 
         if(!info.innerNonSharedNode() && element())
             info.setInnerNonSharedNode(element());
-        
-        if (!info.URLElement()) {
-            RenderObject* p = (!isInline() && continuation()) ? continuation() : this;
-            while (p) {
-                if (p->element() && p->element()->hasAnchor()) {
-                    info.setURLElement(p->element());
-                    break;
-                }
-                if (!isFloatingOrPositioned()) break;
-                p = p->parent();
-            }
-        }
-    }
-
-    if (!info.readonly()) {
-        // lets see if we need a new style
-        bool oldinside = mouseInside();
-        setMouseInside(inside);
-        
-        setHoverAndActive(info, oldinside, inside);
-        if (!isInline() && continuation())
-            continuation()->setHoverAndActive(info, oldinside, inside);
     }
 
     return inside;
Index: khtml/rendering/render_object.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_object.h,v
retrieving revision 1.79
diff -u -p -r1.79 khtml/rendering/render_object.h
--- khtml/rendering/render_object.h	2003/08/11 23:41:02	1.79
+++ khtml/rendering/render_object.h	2003/09/02 17:44:23
@@ -70,10 +70,17 @@ typedef enum {
     PaintActionSelection
 } PaintAction;
 
+typedef enum {
+    HitTestAll = 0,
+    HitTestSelfOnly = 1,
+    HitTestChildrenOnly = 2
+} HitTestAction;
+
 namespace DOM {
     class HTMLAreaElementImpl;
     class DOMString;
     class NodeImpl;
+    class DocumentImpl;
     class ElementImpl;
     class EventImpl;
 };
@@ -241,7 +248,8 @@ public:
 
     // don't even think about making this method virtual!
     DOM::NodeImpl* element() const { return m_node; }
-
+    DOM::DocumentImpl* document() const;
+    
    /**
      * returns the object containing this one. can be different from parent for
      * positioned elements
@@ -405,8 +413,8 @@ public:
 
     FindSelectionResult checkSelectionPoint(int x, int y, int tx, int ty, DOM::NodeImpl*&, int& offset);
     virtual FindSelectionResult checkSelectionPointIgnoringContinuations(int x, int y, int tx, int ty, DOM::NodeImpl*&, int& offset);
-    virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, bool inside=false);
-    void setHoverAndActive(NodeInfo& info, bool oldinside, bool inside);
+    virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
+                             HitTestAction hitTestAction = HitTestAll, bool inside=false);
     
     // set the style of the object.
     virtual void setStyle(RenderStyle *style);
Index: khtml/rendering/render_style.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_style.cpp,v
retrieving revision 1.27
diff -u -p -r1.27 khtml/rendering/render_style.cpp
--- khtml/rendering/render_style.cpp	2003/07/15 22:32:42	1.27
+++ khtml/rendering/render_style.cpp	2003/09/02 17:44:24
@@ -420,7 +420,9 @@ RenderStyle::Diff RenderStyle::diff( con
 //     DataRef<StyleInheritedData> inherited;
 
     if ( *box.get() != *other->box.get() ||
-        *surround.get() != *other->surround.get() ||
+         !(surround->margin == other->surround->margin) ||
+         !(surround->border == other->surround->border) || // FIXME: Width -> layout, but other styles -> repaint
+         !(surround->padding == other->surround->padding) ||
          *css3NonInheritedData->flexibleBox.get() != *other->css3NonInheritedData->flexibleBox.get() ||
         !(inherited->indent == other->inherited->indent) ||
         !(inherited->line_height == other->inherited->line_height) ||
@@ -490,6 +492,15 @@ RenderStyle::Diff RenderStyle::diff( con
     if ( !(noninherited_flags._effectiveDisplay == INLINE) &&
          !(noninherited_flags._vertical_align == other->noninherited_flags._vertical_align))
         return Layout;
+
+    // Make sure these left/top/right/bottom checks stay below all layout checks and above
+    // all visible checks.
+    if (other->position() != STATIC && !(surround->offset == other->surround->offset)) {
+        if (other->position() == RELATIVE)
+            return Visible;
+        else
+            return Layout;
+    }
 
     // Visible:
 // 	EVisibility _visibility : 2;
Index: khtml/rendering/render_text.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_text.cpp,v
retrieving revision 1.78
diff -u -p -r1.78 khtml/rendering/render_text.cpp
--- khtml/rendering/render_text.cpp	2003/08/27 22:57:14	1.78
+++ khtml/rendering/render_text.cpp	2003/09/02 17:44:25
@@ -377,7 +377,8 @@ TextRun * RenderText::findTextRun( int o
     return s;
 }
 
-bool RenderText::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, bool inside)
+bool RenderText::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
+                             HitTestAction hitTestAction, bool inside)
 {
     assert(parent());
 
@@ -393,8 +394,6 @@ bool RenderText::nodeAtPoint(NodeInfo& i
         s = si < (int) m_lines.count()-1 ? m_lines[++si] : 0;
     }
 
-    setMouseInside(inside);
-
     if (inside && element()) {
         if (info.innerNode() && info.innerNode()->renderer() && 
             !info.innerNode()->renderer()->isInline()) {
@@ -409,7 +408,7 @@ bool RenderText::nodeAtPoint(NodeInfo& i
         if (!info.innerNode())
             info.setInnerNode(element());
 
-        if(!info.innerNonSharedNode())
+        if (!info.innerNonSharedNode())
             info.setInnerNonSharedNode(element());
     }
 
Index: khtml/rendering/render_text.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/rendering/render_text.h,v
retrieving revision 1.34
diff -u -p -r1.34 khtml/rendering/render_text.h
--- khtml/rendering/render_text.h	2003/07/25 20:22:34	1.34
+++ khtml/rendering/render_text.h	2003/09/02 17:44:26
@@ -141,7 +141,8 @@ public:
     
     virtual void layout() {assert(false);}
 
-    virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty, bool inside = false);
+    virtual bool nodeAtPoint(NodeInfo& info, int x, int y, int tx, int ty,
+                             HitTestAction hitTestAction = HitTestAll, bool inside=false);
 
     // Return before, after (offset set to max), or inside the text, at @p offset
     virtual FindSelectionResult checkSelectionPointIgnoringContinuations
Index: khtml/xml/dom_docimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/xml/dom_docimpl.cpp,v
retrieving revision 1.75
diff -u -p -r1.75 khtml/xml/dom_docimpl.cpp
--- khtml/xml/dom_docimpl.cpp	2003/07/30 00:39:43	1.75
+++ khtml/xml/dom_docimpl.cpp	2003/09/02 17:44:30
@@ -284,6 +284,7 @@ DocumentImpl::DocumentImpl(DOMImplementa
     m_namespaceURIs[0] = new DOMStringImpl(xhtml.unicode(), xhtml.length());
     m_namespaceURIs[0]->ref();
     m_focusNode = 0;
+    m_hoverNode = 0;
     m_defaultView = new AbstractViewImpl(this);
     m_defaultView->ref();
     m_listenerTypes = 0;
@@ -336,9 +337,12 @@ DocumentImpl::~DocumentImpl()
     delete [] m_namespaceURIs;
     m_defaultView->deref();
     m_styleSheets->deref();
+
     if (m_focusNode)
         m_focusNode->deref();
-        
+    if (m_hoverNode)
+        m_hoverNode->deref();
+    
     if (m_renderArena){
         delete m_renderArena;
         m_renderArena = 0;
@@ -2014,6 +2018,17 @@ void DocumentImpl::recalcStyleSelector()
                                             !inCompatMode() );
 
     m_styleSelectorDirty = false;
+}
+
+void DocumentImpl::setHoverNode(NodeImpl* newHoverNode)
+{
+    if (m_hoverNode != newHoverNode) {
+        if (m_hoverNode)
+            m_hoverNode->deref();
+        m_hoverNode = newHoverNode;
+        if (m_hoverNode)
+            m_hoverNode->ref();
+    }    
 }
 
 void DocumentImpl::setFocusNode(NodeImpl *newFocusNode)
Index: khtml/xml/dom_docimpl.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/xml/dom_docimpl.h,v
retrieving revision 1.38
diff -u -p -r1.38 khtml/xml/dom_docimpl.h
--- khtml/xml/dom_docimpl.h	2003/07/30 00:39:43	1.38
+++ khtml/xml/dom_docimpl.h	2003/09/02 17:44:30
@@ -344,9 +344,13 @@ public:
     void setSelectedStylesheetSet(const DOMString& aString);
 
     QStringList availableStyleSheets() const;
+
     NodeImpl *focusNode() const { return m_focusNode; }
     void setFocusNode(NodeImpl *newFocusNode);
 
+    NodeImpl *hoverNode() const { return m_hoverNode; }
+    void setHoverNode(NodeImpl *newHoverNode);
+    
     // Updates for :target (CSS3 selector).
     void setCSSTarget(NodeImpl* n);
     NodeImpl* getCSSTarget();
@@ -478,8 +482,10 @@ protected:
     HTMLMode hMode;
 
     QColor m_textColor;
-    NodeImpl *m_focusNode;
 
+    NodeImpl *m_focusNode;
+    NodeImpl *m_hoverNode;
+    
     // ### replace me with something more efficient
     // in lookup and insertion.
     DOMStringImpl **m_elementNames;
Index: kwq/KWQKHTMLPart.mm
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/kwq/KWQKHTMLPart.mm,v
retrieving revision 1.391
diff -u -p -r1.391 kwq/KWQKHTMLPart.mm
--- kwq/KWQKHTMLPart.mm	2003/08/22 22:02:56	1.391
+++ kwq/KWQKHTMLPart.mm	2003/09/02 17:44:33
@@ -56,6 +56,8 @@
 
 #import <JavaScriptCore/property_map.h>
 
+#import <qscrollbar.h>
+
 #undef _KWQ_TIMING
 
 using DOM::DocumentImpl;
@@ -776,7 +778,7 @@ void KWQKHTMLPart::paint(QPainter *p, co
 #endif
 
     if (renderer()) {
-        renderer()->layer()->paint(p, rect.x(), rect.y(), rect.width(), rect.height(), false);
+        renderer()->layer()->paint(p, rect);
     } else {
         ERROR("called KWQKHTMLPart::paint with nil renderer");
     }
@@ -785,7 +787,7 @@ void KWQKHTMLPart::paint(QPainter *p, co
 void KWQKHTMLPart::paintSelectionOnly(QPainter *p, const QRect &rect)
 {
     if (renderer()) {
-        renderer()->layer()->paint(p, rect.x(), rect.y(), rect.width(), rect.height(), true);
+        renderer()->layer()->paint(p, rect, true);
     } else {
         ERROR("called KWQKHTMLPart::paintSelectionOnly with nil renderer");
     }
@@ -800,8 +802,9 @@ void KWQKHTMLPart::adjustPageHeight(floa
         painter.setPaintingDisabled(true);
 
         root->setTruncatedAt((int)floor(oldBottom));
-        root->layer()->paint(&painter, 0, (int)floor(oldTop),
-                             root->docWidth(), (int)ceil(oldBottom-oldTop), false);
+        QRect dirtyRect(0, (int)floor(oldTop),
+                        root->docWidth(), (int)ceil(oldBottom-oldTop));
+        root->layer()->paint(&painter, dirtyRect);
         *newBottom = root->bestTruncatedAt();
         if (*newBottom == 0) {
             *newBottom = oldBottom;
Index: kwq/KWQRect.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/kwq/KWQRect.h,v
retrieving revision 1.27
diff -u -p -r1.27 kwq/KWQRect.h
--- kwq/KWQRect.h	2003/01/22 00:12:35	1.27
+++ kwq/KWQRect.h	2003/09/02 17:44:33
@@ -61,7 +61,7 @@ public:
     bool intersects(const QRect &) const;
     QRect unite(const QRect &) const;
 
-    bool contains(int x, int y, bool proper = false) {
+    bool contains(int x, int y, bool proper = false) const {
         if (proper)
             return x > xp && (x < (xp + w - 1)) && y > yp && y < (yp + h - 1);
         return x >= xp && x < (xp + w) && y >= yp && y < (yp + h);
Index: kwq/KWQRenderTreeDebug.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/kwq/KWQRenderTreeDebug.cpp,v
retrieving revision 1.10
diff -u -p -r1.10 kwq/KWQRenderTreeDebug.cpp
--- kwq/KWQRenderTreeDebug.cpp	2003/05/06 22:26:07	1.10
+++ kwq/KWQRenderTreeDebug.cpp	2003/09/02 17:44:33
@@ -42,11 +42,9 @@ using khtml::RenderText;
 using khtml::TextRun;
 using khtml::TextRunArray;
 
-typedef khtml::RenderLayer::RenderLayerElement RenderLayerElement;
-typedef khtml::RenderLayer::RenderZTreeNode RenderZTreeNode;
+static void writeLayers(QTextStream &ts, const RenderLayer* rootLayer, RenderLayer* l,
+                        const QRect& paintDirtyRect, int indent=0);
 
-static void writeLayers(QTextStream &ts, const RenderObject &o, int indent = 0);
-
 static QTextStream &operator<<(QTextStream &ts, const QRect &r)
 {
     return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
@@ -149,16 +147,18 @@ static void write(QTextStream &ts, const
         if (view) {
             RenderObject *root = KWQ(view->part())->renderer();
             if (root) {
-                writeLayers(ts, *root, indent + 1);
+                RenderLayer* l = root->layer();
+                if (l)
+                    writeLayers(ts, l, l, QRect(l->xPos(), l->yPos(), l->width(), l->height()), indent+1);
             }
         }
     }
 }
 
-static void write(QTextStream &ts, const RenderLayerElement &e, int indent = 0)
+static void write(QTextStream &ts, const RenderLayer &l,
+                  const QRect& layerBounds, const QRect& backgroundClipRect, const QRect& clipRect,
+                  int layerType = 0, int indent = 0)
 {
-    RenderLayer &l = *e.layer;
-    
     writeIndent(ts, indent);
     
     ts << "layer";
@@ -166,34 +166,52 @@ static void write(QTextStream &ts, const
     QRect r(l.xPos(), l.yPos(), l.width(), l.height());
     
     ts << " " << r;
-    
-    if (r != r.intersect(e.backgroundClipRect)) {
-        ts << " backgroundClip " << e.backgroundClipRect;
+
+    if (layerBounds != layerBounds.intersect(backgroundClipRect)) {
+        ts << " backgroundClip " << backgroundClipRect;
     }
-    if (r != r.intersect(e.clipRect)) {
-        ts << " clip " << e.clipRect;
+    if (layerBounds != layerBounds.intersect(clipRect)) {
+        ts << " clip " << clipRect;
     }
 
-    if (e.layerElementType == RenderLayerElement::Background)
+    if (layerType == -1)
         ts << " layerType: background only";
-    else if (e.layerElementType == RenderLayerElement::Foreground)
+    else if (layerType == 1)
         ts << " layerType: foreground only";
     
     ts << "\n";
 
-    if (e.layerElementType != RenderLayerElement::Background)
+    if (layerType != -1)
         write(ts, *l.renderer(), indent + 1);
 }
-
-static void writeLayers(QTextStream &ts, const RenderObject &o, int indent)
+    
+static void writeLayers(QTextStream &ts, const RenderLayer* rootLayer, RenderLayer* l,
+                        const QRect& paintDirtyRect, int indent)
 {
-    RenderZTreeNode *node;
-    QPtrVector<RenderLayerElement> list = o.layer()->elementList(node);
-    for (unsigned i = 0; i != list.count(); ++i) {
-        write(ts, *list[i], indent);
+    // Calculate the clip rects we should use.
+    QRect layerBounds, damageRect, clipRectToApply;
+    l->calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply);
+    
+    // Ensure our z-order lists are up-to-date.
+    l->updateZOrderLists();
+
+    bool shouldPaint = l->intersectsDamageRect(layerBounds, damageRect);
+    QPtrVector<RenderLayer>* negList = l->negZOrderList();
+    if (shouldPaint && negList && negList->count() > 0)
+        write(ts, *l, layerBounds, damageRect, clipRectToApply, -1, indent);
+
+    if (negList) {
+        for (unsigned i = 0; i != negList->count(); ++i)
+            writeLayers(ts, rootLayer, negList->at(i), paintDirtyRect, indent);
     }
-    if (node) {
-        node->detach(o.renderArena());
+
+    if (shouldPaint)
+        write(ts, *l, layerBounds, damageRect, clipRectToApply, negList && negList->count() > 0, indent);
+
+    QPtrVector<RenderLayer>* posList = l->posZOrderList();
+    if (posList) {
+        for (unsigned i = 0; i != posList->count(); ++i)
+            writeLayers(ts, rootLayer, posList->at(i), paintDirtyRect, indent);
     }
 }
 
@@ -203,7 +221,9 @@ QString externalRepresentation(const Ren
     {
         QTextStream ts(&s);
         if (o) {
-            writeLayers(ts, *o);
+            RenderLayer* l = o->layer();
+            if (l)
+                writeLayers(ts, l, l, QRect(l->xPos(), l->yPos(), l->width(), l->height()));
         }
     }
     return s;
-------------- next part --------------


-------------- next part --------------
/*
 * Copyright (C) 2003 Apple Computer, Inc.
 *
 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
 *
 * Other contributors:
 *   Robert O'Callahan <roc+ at cs.cmu.edu>
 *   David Baron <dbaron at fas.harvard.edu>
 *   Christian Biesinger <cbiesinger at web.de>
 *   Randall Jesup <rjesup at wgate.com>
 *   Roland Mainz <roland.mainz at informatik.med.uni-giessen.de>
 *   Josh Soref <timeless at mac.com>
 *   Boris Zbarsky <bzbarsky at mit.edu>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Alternatively, the contents of this file may be used under the terms
 * of either the Mozilla Public License Version 1.1, found at
 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
 * (the "GPL"), in which case the provisions of the MPL or the GPL are
 * applicable instead of those above.  If you wish to allow use of your
 * version of this file only under the terms of one of those two
 * licenses (the MPL or the GPL) and not to allow others to use your
 * version of this file under the LGPL, indicate your decision by
 * deletingthe provisions above and replace them with the notice and
 * other provisions required by the MPL or the GPL, as the case may be.
 * If you do not delete the provisions above, a recipient may use your
 * version of this file under any of the LGPL, the MPL or the GPL.
 */

#include "render_layer.h"
#include <kdebug.h>
#include <assert.h>
#include "khtmlview.h"
#include "render_block.h"
#include "render_arena.h"
#include "xml/dom_docimpl.h"

#include <qscrollbar.h>
#include <qptrvector.h>

using namespace DOM;
using namespace khtml;

#ifdef APPLE_CHANGES
QScrollBar* RenderLayer::gScrollBar = 0;
#endif

#ifndef NDEBUG
static bool inRenderLayerDetach;
#endif

void
RenderScrollMediator::slotValueChanged(int val)
{
    m_layer->updateScrollPositionFromScrollbars();
}

RenderLayer::RenderLayer(RenderObject* object)
: m_object( object ),
m_parent( 0 ),
m_previous( 0 ),
m_next( 0 ),
m_first( 0 ),
m_last( 0 ),
m_x( 0 ),
m_y( 0 ),
m_width( 0 ),
m_height( 0 ),
m_scrollX( 0 ),
m_scrollY( 0 ),
m_scrollWidth( 0 ),
m_scrollHeight( 0 ),
m_hBar( 0 ),
m_vBar( 0 ),
m_scrollMediator( 0 ),
m_posZOrderList( 0 ),
m_negZOrderList( 0 ),
m_zOrderListsDirty( true )
{
}

RenderLayer::~RenderLayer()
{
    // Child layers will be deleted by their corresponding render objects, so
    // our destructor doesn't have to do anything.
    m_parent = m_previous = m_next = m_first = m_last = 0;
    delete m_hBar;
    delete m_vBar;
    delete m_scrollMediator;
    delete m_posZOrderList;
    delete m_negZOrderList;
}

void RenderLayer::updateLayerPosition()
{
    // The canvas is sized to the docWidth/Height over in RenderCanvas::layout, so we
    // don't need to ever update our layer position here.
    if (renderer()->isCanvas())
        return;
    
    int x = m_object->xPos();
    int y = m_object->yPos();

    if (!m_object->isPositioned()) {
        // We must adjust our position by walking up the render tree looking for the
        // nearest enclosing object with a layer.
        RenderObject* curr = m_object->parent();
        while (curr && !curr->layer()) {
            x += curr->xPos();
            y += curr->yPos();
            curr = curr->parent();
        }
    }

    if (m_object->isRelPositioned())
        static_cast<RenderBox*>(m_object)->relativePositionOffset(x, y);

    // Subtract our parent's scroll offset.
    if (parent())
        parent()->subtractScrollOffset(x, y);
    
    setPos(x,y);

    setWidth(m_object->width());
    setHeight(m_object->height());

    if (!m_object->style()->hidesOverflow()) {
        if (m_object->overflowWidth() > m_object->width())
            setWidth(m_object->overflowWidth());
        if (m_object->overflowHeight() > m_object->height())
            setHeight(m_object->overflowHeight());
    }    
}

RenderLayer *RenderLayer::stackingContext() const
{
    RenderLayer* curr = parent();
    for ( ; curr && !curr->m_object->isCanvas() && !curr->m_object->isRoot() &&
          curr->m_object->style()->hasAutoZIndex();
          curr = curr->parent());
    return curr;
}

RenderLayer*
RenderLayer::enclosingPositionedAncestor() const
{
    RenderLayer* curr = parent();
    for ( ; curr && !curr->m_object->isCanvas() && !curr->m_object->isRoot() &&
         !curr->m_object->isPositioned() && !curr->m_object->isRelPositioned();
         curr = curr->parent());
         
    return curr;
}

#if APPLE_CHANGES
bool
RenderLayer::isTransparent()
{
    return m_object->style()->opacity() < 1.0f;
}

RenderLayer*
RenderLayer::transparentAncestor()
{
    RenderLayer* curr = parent();
    for ( ; curr && curr->m_object->style()->opacity() == 1.0f; curr = curr->parent());
    return curr;
}
#endif

void* RenderLayer::operator new(size_t sz, RenderArena* renderArena) throw()
{
    return renderArena->allocate(sz);
}

void RenderLayer::operator delete(void* ptr, size_t sz)
{
    assert(inRenderLayerDetach);
    
    // Stash size where detach can find it.
    *(size_t *)ptr = sz;
}

void RenderLayer::detach(RenderArena* renderArena)
{
#ifndef NDEBUG
    inRenderLayerDetach = true;
#endif
    delete this;
#ifndef NDEBUG
    inRenderLayerDetach = false;
#endif
    
    // Recover the size left there for us by operator delete and free the memory.
    renderArena->free(*(size_t *)this, this);
}

void RenderLayer::addChild(RenderLayer *child, RenderLayer* beforeChild)
{
    RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
    if (prevSibling) {
        child->setPreviousSibling(prevSibling);
        prevSibling->setNextSibling(child);
    }
    else
        setFirstChild(child);

    if (beforeChild) {
        beforeChild->setPreviousSibling(child);
        child->setNextSibling(beforeChild);
    }
    else
        setLastChild(child);
   
    child->setParent(this);

    // Dirty the z-order list in which we are contained.
    child->stackingContext()->dirtyZOrderLists();
}

RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
{
    // remove the child
    if (oldChild->previousSibling())
        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
    if (oldChild->nextSibling())
        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());

    if (m_first == oldChild)
        m_first = oldChild->nextSibling();
    if (m_last == oldChild)
        m_last = oldChild->previousSibling();

    // Dirty the z-order list in which we are contained.  When called via the
    // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
    // from the main layer tree, so we need to null-check the |stackingContext| value.
    RenderLayer* stackingContext = oldChild->stackingContext();
    if (stackingContext)
        oldChild->stackingContext()->dirtyZOrderLists();
    
    oldChild->setPreviousSibling(0);
    oldChild->setNextSibling(0);
    oldChild->setParent(0);
    
    return oldChild;
}

void RenderLayer::removeOnlyThisLayer()
{
    if (!m_parent)
        return;
    
    // Remove us from the parent.
    RenderLayer* parent = m_parent;
    RenderLayer* nextSib = nextSibling();
    parent->removeChild(this);
    
    // Now walk our kids and reattach them to our parent.
    RenderLayer* current = m_first;
    while (current) {
        RenderLayer* next = current->nextSibling();
        removeChild(current);
        parent->addChild(current, nextSib);
        current = next;
    }
    
    detach(renderer()->renderArena());
}

void RenderLayer::insertOnlyThisLayer()
{
    if (!m_parent && renderer()->parent()) {
        // We need to connect ourselves when our renderer() has a parent.
        // Find our enclosingLayer and add ourselves.
        RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
        if (parentLayer)
            parentLayer->addChild(this, 
                                  renderer()->parent()->findNextLayer(parentLayer, renderer()));
    }
    
    // Remove all descendant layers from the hierarchy and add them to the new position.
    for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
        curr->moveLayers(m_parent, this);
}

void 
RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
{
    if (ancestorLayer == this)
        return;
        
    if (m_object->style()->position() == FIXED) {
        // Add in the offset of the view.  We can obtain this by calling
        // absolutePosition() on the RenderCanvas.
        int xOff, yOff;
        m_object->absolutePosition(xOff, yOff, true);
        x += xOff;
        y += yOff;
        return;
    }
 
    RenderLayer* parentLayer;
    if (m_object->style()->position() == ABSOLUTE)
        parentLayer = enclosingPositionedAncestor();
    else
        parentLayer = parent();
    
    if (!parentLayer) return;
    
    parentLayer->convertToLayerCoords(ancestorLayer, x, y);

    x += xPos();
    y += yPos();
}

void
RenderLayer::scrollOffset(int& x, int& y)
{
    x += scrollXOffset();
    y += scrollYOffset();
}

void
RenderLayer::subtractScrollOffset(int& x, int& y)
{
    x -= scrollXOffset();
    y -= scrollYOffset();
}

void
RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars)
{
    if (x < 0) x = 0;
    if (y < 0) y = 0;
    int maxX = m_scrollWidth - m_object->clientWidth();
    int maxY = m_scrollHeight - m_object->clientHeight();
    if (x > maxX) x = maxX;
    if (y > maxY) y = maxY;

    // FIXME: Eventually, we will want to perform a blit.  For now never
    // blit, since the check for blitting is going to be very
    // complicated (since it will involve testing whether our layer
    // is either occluded by another layer or clipped by an enclosing
    // layer or contains fixed backgrounds, etc.).
    m_scrollX = x;
    m_scrollY = y;

    // FIXME: Fire the onscroll DOM event.
    
    // Just schedule a full repaint of our object.
    m_object->repaint(true);
    
    if (updateScrollbars) {
        if (m_hBar)
            m_hBar->setValue(m_scrollX);
        if (m_vBar)
            m_vBar->setValue(m_scrollY);
    }
}

void
RenderLayer::updateScrollPositionFromScrollbars()
{
    bool needUpdate = false;
    int newX = m_scrollX;
    int newY = m_scrollY;
    
    if (m_hBar) {
        newX = m_hBar->value();
        if (newX != m_scrollX)
           needUpdate = true;
    }

    if (m_vBar) {
        newY = m_vBar->value();
        if (newY != m_scrollY)
           needUpdate = true;
    }

    if (needUpdate)
        scrollToOffset(newX, newY, false);
}

void
RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
{
    if (hasScrollbar && !m_hBar) {
        QScrollView* scrollView = m_object->element()->getDocument()->view();
        m_hBar = new QScrollBar(Qt::Horizontal, scrollView);
        scrollView->addChild(m_hBar, 0, -50000);
        if (!m_scrollMediator)
            m_scrollMediator = new RenderScrollMediator(this);
        m_scrollMediator->connect(m_hBar, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)));
    }
    else if (!hasScrollbar && m_hBar) {
        m_scrollMediator->disconnect(m_hBar, SIGNAL(valueChanged(int)),
                                     m_scrollMediator, SLOT(slotValueChanged(int)));
        delete m_hBar;
        m_hBar = 0;
    }
}

void
RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
{
    if (hasScrollbar && !m_vBar) {
        QScrollView* scrollView = m_object->element()->getDocument()->view();
        m_vBar = new QScrollBar(Qt::Vertical, scrollView);
        scrollView->addChild(m_vBar, 0, -50000);
        if (!m_scrollMediator)
            m_scrollMediator = new RenderScrollMediator(this);
        m_scrollMediator->connect(m_vBar, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)));
    }
    else if (!hasScrollbar && m_vBar) {
        m_scrollMediator->disconnect(m_vBar, SIGNAL(valueChanged(int)),
                                     m_scrollMediator, SLOT(slotValueChanged(int)));
        delete m_vBar;
        m_vBar = 0;
    }
}

int
RenderLayer::verticalScrollbarWidth()
{
    if (!m_vBar)
        return 0;

    return m_vBar->width();
}

int
RenderLayer::horizontalScrollbarHeight()
{
    if (!m_hBar)
        return 0;

    return m_hBar->height();
}

void
RenderLayer::moveScrollbarsAside()
{
    if (m_hBar)
        m_hBar->move(0, -50000);
    if (m_vBar)
        m_vBar->move(0, -50000);
}

void
RenderLayer::positionScrollbars(const QRect& absBounds)
{
    if (m_vBar) {
        m_vBar->move(absBounds.x()+absBounds.width()-m_object->borderRight()-m_vBar->width(),
                     absBounds.y()+m_object->borderTop());
        m_vBar->resize(m_vBar->width(), absBounds.height() -
                       (m_object->borderTop()+m_object->borderBottom()) -
                       (m_hBar ? m_hBar->height()-1 : 0));
    }

    if (m_hBar) {
        m_hBar->move(absBounds.x()+m_object->borderLeft(),
                     absBounds.y()+absBounds.height()-m_object->borderBottom()-m_hBar->height());
        m_hBar->resize(absBounds.width() - (m_object->borderLeft()+m_object->borderRight()) -
                       (m_vBar ? m_vBar->width()-1 : 0),
                       m_hBar->height());
    }
}

#define LINE_STEP   10
#define PAGE_KEEP   40

void
RenderLayer::checkScrollbarsAfterLayout()
{
    updateLayerPosition();
    
    int rightPos = m_object->rightmostPosition();
    int bottomPos = m_object->lowestPosition();

    int clientWidth = m_object->clientWidth();
    int clientHeight = m_object->clientHeight();
    m_scrollWidth = clientWidth;
    m_scrollHeight = clientHeight;
    
    if (rightPos - m_object->borderLeft() > m_scrollWidth)
        m_scrollWidth = rightPos - m_object->borderLeft();
    if (bottomPos - m_object->borderTop() > m_scrollHeight)
        m_scrollHeight = bottomPos - m_object->borderTop();
    
    bool needHorizontalBar = rightPos > width();
    bool needVerticalBar = bottomPos > height();

    bool haveHorizontalBar = m_hBar;
    bool haveVerticalBar = m_vBar;

    // overflow:scroll should just enable/disable.
    if (m_object->style()->overflow() == OSCROLL) {
        m_hBar->setEnabled(needHorizontalBar);
        m_vBar->setEnabled(needVerticalBar);
    }

    // overflow:auto may need to lay out again if scrollbars got added/removed.
    bool scrollbarsChanged = (m_object->style()->overflow() == OAUTO) &&
        (haveHorizontalBar != needHorizontalBar || haveVerticalBar != needVerticalBar);    
    if (scrollbarsChanged) {
        setHasHorizontalScrollbar(needHorizontalBar);
        setHasVerticalScrollbar(needVerticalBar);
       
        m_object->setNeedsLayout(true);
	if (m_object->isRenderBlock())
            static_cast<RenderBlock*>(m_object)->layoutBlock(true);
        else
            m_object->layout();
	return;
    }

    // Set up the range (and page step/line step).
    if (m_hBar) {
        int pageStep = (clientWidth-PAGE_KEEP);
        if (pageStep < 0) pageStep = clientWidth;
        m_hBar->setSteps(LINE_STEP, pageStep);
#ifdef APPLE_CHANGES
        m_hBar->setKnobProportion(clientWidth, m_scrollWidth);
#else
        m_hBar->setRange(0, m_scrollWidth-clientWidth);
#endif
    }
    if (m_vBar) {
        int pageStep = (clientHeight-PAGE_KEEP);
        if (pageStep < 0) pageStep = clientHeight;
        m_vBar->setSteps(LINE_STEP, pageStep);
#ifdef APPLE_CHANGES
        m_vBar->setKnobProportion(clientHeight, m_scrollHeight);
#else
        m_vBar->setRange(0, m_scrollHeight-clientHeight);
#endif
    }
}

#if APPLE_CHANGES
void
RenderLayer::paintScrollbars(QPainter* p, const QRect& damageRect)
{
    if (m_hBar)
        m_hBar->paint(p, damageRect);
    if (m_vBar)
        m_vBar->paint(p, damageRect);
}
#endif

void
RenderLayer::paint(QPainter *p, const QRect& damageRect, bool selectionOnly)
{
    paintLayer(this, p, damageRect, selectionOnly);
}

static void setClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect)
{
    if (paintDirtyRect == clipRect)
        return;

    p->save();
    
#if APPLE_CHANGES
    p->addClip(clipRect);
#else
    QRect clippedRect = p->xForm(clipRect);
    QRegion creg(clippedRect);
    QRegion old = p->clipRegion();
    if (!old.isNull())
        creg = old.intersect(creg);
    p->setClipRegion(creg);
#endif
    
}

static void restoreClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect)
{
    if (paintDirtyRect == clipRect)
        return;
    p->restore();
}

void
RenderLayer::paintLayer(RenderLayer* rootLayer, QPainter *p,
                        const QRect& paintDirtyRect, bool selectionOnly)
{
    // Calculate the clip rects we should use.
    QRect layerBounds, damageRect, clipRectToApply;
    calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply);
    int x = layerBounds.x();
    int y = layerBounds.y();
                             
    // Ensure our z-order lists are up-to-date.
    updateZOrderLists();

#if APPLE_CHANGES
    // Set our transparency if we need to.
    if (isTransparent())
        p->beginTransparencyLayer(renderer()->style()->opacity());
#endif
    
    // We want to paint our layer, but only if we intersect the damage rect.
    bool shouldPaint = intersectsDamageRect(layerBounds, damageRect);
    if (shouldPaint && !selectionOnly) {
        // Paint our background first, before painting any child layers.
        if (!damageRect.isEmpty()) {
            // Establish the clip used to paint our background.
            setClip(p, paintDirtyRect, damageRect);

            // Paint the background.
            renderer()->paint(p, damageRect.x(), damageRect.y(),
                              damageRect.width(), damageRect.height(),
                              x - renderer()->xPos(), y - renderer()->yPos(),
                              PaintActionElementBackground);

            // Position our scrollbars.
            positionScrollbars(layerBounds);

#if APPLE_CHANGES
            // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
            // z-index.  We paint after we painted the background/border, so that the scrollbars will
            // sit above the background/border.
            paintScrollbars(p, damageRect);
#endif
            // Restore the clip.
            restoreClip(p, paintDirtyRect, damageRect);
        }
    }

    // Now walk the sorted list of children with negative z-indices.
    if (m_negZOrderList) {
        uint count = m_negZOrderList->count();
        for (uint i = 0; i < count; i++) {
            RenderLayer* child = m_negZOrderList->at(i);
            child->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);
        }
    }
    
    // Now establish the appropriate clip and paint our child RenderObjects.
    if (shouldPaint && !clipRectToApply.isEmpty()) {
        // Set up the clip used when painting our children.
        setClip(p, paintDirtyRect, clipRectToApply);

        if (selectionOnly)
            renderer()->paint(p, clipRectToApply.x(), clipRectToApply.y(),
                              clipRectToApply.width(), clipRectToApply.height(),
                              x - renderer()->xPos(), y - renderer()->yPos(), PaintActionSelection);
        else {
            renderer()->paint(p, clipRectToApply.x(), clipRectToApply.y(),
                              clipRectToApply.width(), clipRectToApply.height(),
                              x - renderer()->xPos(), y - renderer()->yPos(), PaintActionChildBackgrounds);
            renderer()->paint(p, clipRectToApply.x(), clipRectToApply.y(),
                              clipRectToApply.width(), clipRectToApply.height(),
                              x - renderer()->xPos(), y - renderer()->yPos(), PaintActionFloat);
            renderer()->paint(p, clipRectToApply.x(), clipRectToApply.y(),
                              clipRectToApply.width(), clipRectToApply.height(),
                              x - renderer()->xPos(), y - renderer()->yPos(), PaintActionForeground);
        }

        // Now restore our clip.
        restoreClip(p, paintDirtyRect, clipRectToApply);
    }
    
    // Now walk the sorted list of children with positive z-indices.
    if (m_posZOrderList) {
        uint count = m_posZOrderList->count();
        for (uint i = 0; i < count; i++) {
            RenderLayer* child = m_posZOrderList->at(i);
            child->paintLayer(rootLayer, p, paintDirtyRect, selectionOnly);
        }
    }
    
#if APPLE_CHANGES
    // End our transparency layer
    if (isTransparent())
        p->endTransparencyLayer();
#endif
}

bool
RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
{
#if APPLE_CHANGES
    // Clear our our scrollbar variable
    RenderLayer::gScrollBar = 0;
#endif
    
    QRect damageRect(m_x, m_y, width(), height());
    RenderLayer* insideLayer = nodeAtPointForLayer(this, info, x, y, damageRect);

    // Now determine if the result is inside an anchor.
    DOM::NodeImpl* node = info.innerNode();
    while (node) {
        if (node->hasAnchor())
            info.setURLElement(node);
        node = node->parentNode();
    }

    // Next set up the correct :hover/:active state along the new chain.
    updateHoverActiveState(info);

    // Now return whether we were inside this layer (this will always be true for the root
    // layer).
    return insideLayer;
}

RenderLayer*
RenderLayer::nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
                                 int xMousePos, int yMousePos, const QRect& hitTestRect)
{
    // Calculate the clip rects we should use.
    QRect layerBounds, bgRect, fgRect;
    calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect);
    
    // Ensure our z-order lists are up-to-date.
    updateZOrderLists();

    // This variable tracks which layer the mouse ends up being inside.  The minute we find an insideLayer,
    // we are done and can return it.
    RenderLayer* insideLayer = 0;
    
    // Begin by walking our list of positive layers from highest z-index down to the lowest
    // z-index.
    if (m_posZOrderList) {
        uint count = m_posZOrderList->count();
        for (int i = count-1; i >= 0; i--) {
            RenderLayer* child = m_posZOrderList->at(i);
            insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
            if (insideLayer)
                return insideLayer;
        }
    }

    // Next we want to see if the mouse pos is inside the child RenderObjects of the layer.
    if (containsPoint(xMousePos, yMousePos, fgRect) &&
        renderer()->nodeAtPoint(info, xMousePos, yMousePos,
                                layerBounds.x() - renderer()->xPos(),
                                layerBounds.y() - renderer()->yPos(),
                                HitTestChildrenOnly))
        return this;
        
    // Now check our negative z-index children.
    if (m_negZOrderList) {
        uint count = m_negZOrderList->count();
        for (int i = count-1; i >= 0; i--) {
            RenderLayer* child = m_negZOrderList->at(i);
            insideLayer = child->nodeAtPointForLayer(rootLayer, info, xMousePos, yMousePos, hitTestRect);
            if (insideLayer)
                return insideLayer;
        }
    }

    // Next we want to see if the mouse pos is inside this layer but not any of its children.
    if (containsPoint(xMousePos, yMousePos, bgRect) &&
        renderer()->nodeAtPoint(info, xMousePos, yMousePos,
                                layerBounds.x() - renderer()->xPos(),
                                layerBounds.y() - renderer()->yPos(),
                                HitTestSelfOnly))
        return this;

    // No luck.
    return 0;
}

void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, QRect& overflowClipRect,
                                     QRect& posClipRect, QRect& fixedClipRect)
{
    if (parent())
        parent()->calculateClipRects(rootLayer, overflowClipRect, posClipRect, fixedClipRect);
        
    updateLayerPosition(); // For relpositioned layers or non-positioned layers,
                           // we need to keep in sync, since we may have shifted relative
                           // to our parent layer.

    // A fixed object is essentially the root of its containing block hierarchy, so when
    // we encounter such an object, we reset our clip rects to the fixedClipRect.
    if (m_object->style()->position() == FIXED) {
        posClipRect = fixedClipRect;
        overflowClipRect = fixedClipRect;
    }
    else if (m_object->style()->position() == RELATIVE)
        posClipRect = overflowClipRect;
    
    // Update the clip rects that will be passed to child layers.
    if (m_object->hasOverflowClip() || m_object->hasClip()) {
        // This layer establishes a clip of some kind.
        int x = 0;
        int y = 0;
        convertToLayerCoords(rootLayer, x, y);
        
        if (m_object->hasOverflowClip()) {
            QRect newOverflowClip = m_object->getOverflowClipRect(x,y);
            overflowClipRect  = newOverflowClip.intersect(overflowClipRect);
            if (m_object->isPositioned() || m_object->isRelPositioned())
                posClipRect = newOverflowClip.intersect(posClipRect);
        }
        if (m_object->hasClip()) {
            QRect newPosClip = m_object->getClipRect(x,y);
            posClipRect = posClipRect.intersect(newPosClip);
            overflowClipRect = overflowClipRect.intersect(newPosClip);
            fixedClipRect = fixedClipRect.intersect(newPosClip);
        }
    }
}

void RenderLayer::calculateRects(const RenderLayer* rootLayer, const QRect& paintDirtyRect, QRect& layerBounds,
                                 QRect& backgroundRect, QRect& foregroundRect)
{
    QRect overflowClipRect = paintDirtyRect;
    QRect posClipRect = paintDirtyRect;
    QRect fixedClipRect = paintDirtyRect;
    if (parent())
        parent()->calculateClipRects(rootLayer, overflowClipRect, posClipRect, fixedClipRect);

    updateLayerPosition();
    
    int x = 0;
    int y = 0;
    convertToLayerCoords(rootLayer, x, y);
    layerBounds = QRect(x,y,width(),height());

    backgroundRect = m_object->style()->position() == FIXED ? fixedClipRect :
        (m_object->isPositioned() ? posClipRect : overflowClipRect);
    foregroundRect = backgroundRect;
    
    // Update the clip rects that will be passed to child layers.
    if (m_object->hasOverflowClip() || m_object->hasClip()) {
        // This layer establishes a clip of some kind.
        if (m_object->hasOverflowClip())
            foregroundRect = foregroundRect.intersect(m_object->getOverflowClipRect(x,y));
        if (m_object->hasClip()) {
            // Clip applies to *us* as well, so go ahead and update the damageRect.
            QRect newPosClip = m_object->getClipRect(x,y);
            backgroundRect = backgroundRect.intersect(newPosClip);
            foregroundRect = foregroundRect.intersect(newPosClip);
        }

        // If we establish a clip at all, then go ahead and make sure our background
        // rect is intersected with our layer's bounds.
        backgroundRect = backgroundRect.intersect(layerBounds);
    }
}

bool RenderLayer::intersectsDamageRect(const QRect& layerBounds, const QRect& damageRect) const
{
    return (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||
            renderer()->hasOverhangingFloats() ||
            (renderer()->isInline() && !renderer()->isReplaced()) ||
            layerBounds.intersects(damageRect));
}

bool RenderLayer::containsPoint(int x, int y, const QRect& damageRect) const
{
    return (renderer()->isCanvas() || renderer()->isRoot() || renderer()->isBody() ||
            renderer()->hasOverhangingFloats() ||
            (renderer()->isInline() && !renderer()->isReplaced()) ||
            damageRect.contains(x, y));
}

// This code has been written to anticipate the addition of CSS3-::outside and ::inside generated
// content (and perhaps XBL).  That's why it uses the render tree and not the DOM tree.
static RenderObject* hoverAncestor(RenderObject* obj)
{
    return (!obj->isInline() && obj->continuation()) ? obj->continuation() : obj->parent();
}

static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
{
    if (!obj1 || !obj2)
        return 0;

    for (RenderObject* currObj1 = obj1; currObj1; currObj1 = hoverAncestor(currObj1))
        for (RenderObject* currObj2 = obj2; currObj2; currObj2 = hoverAncestor(currObj2))
            if (currObj1 == currObj2)
                return currObj1;

    return 0;
}

void RenderLayer::updateHoverActiveState(RenderObject::NodeInfo& info)
{
    // We don't update :hover/:active state when the info is marked as readonly.
    if (info.readonly())
        return;
    
    // Check to see if the hovered node has changed.  If not, then we don't need to
    // do anything.  An exception is if we just went from :hover into :hover:active,
    // in which case we need to update to get the new :active state.
    DOM::DocumentImpl* doc = renderer()->document();
    DOM::NodeImpl* oldHoverNode = doc ? doc->hoverNode() : 0;
    DOM::NodeImpl* newHoverNode = info.innerNode();
        
    if (oldHoverNode == newHoverNode && (!oldHoverNode || oldHoverNode->active() == info.active()))
        return;

    // Update our current hover node.
    info.innerNode()->getDocument()->setHoverNode(newHoverNode);
    
    // We have two different objects.  Fetch their renderers.
    RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0;
    RenderObject* newHoverObj = info.innerNode() ? info.innerNode()->renderer() : 0;
    
    // Locate the common ancestor render object for the two renderers.
    RenderObject* ancestor = commonAncestor(oldHoverObj, newHoverObj);
    
    // The old hover path only needs to be cleared up to (and not including) the common ancestor;
    for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = hoverAncestor(curr)) {
        curr->setMouseInside(false);
        if (curr->element() && !curr->isText()) {
            bool oldActive = curr->element()->active();
            curr->element()->setActive(false);
            if (curr->style()->affectedByHoverRules() ||
                (curr->style()->affectedByActiveRules() && oldActive))
                curr->element()->setChanged();
        }
    }

    // Now set the hover state for our new object up to the root.
    for (RenderObject* curr = newHoverObj; curr; curr = hoverAncestor(curr)) {
        bool oldInside = curr->mouseInside();
        curr->setMouseInside(true);
        if (curr->element() && !curr->isText()) {
            bool oldActive = curr->element()->active();
            curr->element()->setActive(info.active());
            if ((curr->style()->affectedByHoverRules() && !oldInside) ||
                (curr->style()->affectedByActiveRules() && oldActive != info.active()))
                curr->element()->setChanged();
        }
    }
}

// Sort the buffer from lowest z-index to highest.  The common scenario will have
// most z-indices equal, so we optimize for that case (i.e., the list will be mostly
// sorted already).
static void sortByZOrder(QPtrVector<RenderLayer::RenderLayer>* buffer,
                         QPtrVector<RenderLayer::RenderLayer>* mergeBuffer,
                         uint start, uint end)
{
    if (start >= end)
        return; // Sanity check.

    if (end - start <= 6) {
        // Apply a bubble sort for smaller lists.
        for (uint i = end-1; i > start; i--) {
            bool sorted = true;
            for (uint j = start; j < i; j++) {
                RenderLayer* elt = buffer->at(j);
                RenderLayer* elt2 = buffer->at(j+1);
                if (elt->zIndex() > elt2->zIndex()) {
                    sorted = false;
                    buffer->insert(j, elt2);
                    buffer->insert(j+1, elt);
                }
            }
            if (sorted)
                return;
        }
    }
    else {
        // Peform a merge sort for larger lists.
        uint mid = (start+end)/2;
        sortByZOrder(buffer, mergeBuffer, start, mid);
        sortByZOrder(buffer, mergeBuffer, mid, end);

        RenderLayer* elt = buffer->at(mid-1);
        RenderLayer* elt2 = buffer->at(mid);

        // Handle the fast common case (of equal z-indices).  The list may already
        // be completely sorted.
        if (elt->zIndex() <= elt2->zIndex())
            return;

        // We have to merge sort.  Ensure our merge buffer is big enough to hold
        // all the items.
        mergeBuffer->resize(end - start);
        uint i1 = start;
        uint i2 = mid;

        elt = buffer->at(i1);
        elt2 = buffer->at(i2);

        while (i1 < mid || i2 < end) {
            if (i1 < mid && (i2 == end || elt->zIndex() <= elt2->zIndex())) {
                mergeBuffer->insert(mergeBuffer->count(), elt);
                i1++;
                if (i1 < mid)
                    elt = buffer->at(i1);
            }
            else {
                mergeBuffer->insert(mergeBuffer->count(), elt2);
                i2++;
                if (i2 < end)
                    elt2 = buffer->at(i2);
            }
        }

        for (uint i = start; i < end; i++)
            buffer->insert(i, mergeBuffer->at(i-start));

        mergeBuffer->clear();
    }
}

void RenderLayer::dirtyZOrderLists()
{
    if (m_posZOrderList)
        m_posZOrderList->clear();
    if (m_negZOrderList)
        m_negZOrderList->clear();
    m_zOrderListsDirty = true;
}
    
void RenderLayer::updateZOrderLists()
{
    if (!isStackingContext() || !m_zOrderListsDirty)
        return;
    
    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
        child->collectLayers(m_posZOrderList, m_negZOrderList);

    // Sort the two lists.
    if (m_posZOrderList) {
        QPtrVector<RenderLayer> mergeBuffer;
        sortByZOrder(m_posZOrderList, &mergeBuffer, 0, m_posZOrderList->count());
    }
    if (m_negZOrderList) {
        QPtrVector<RenderLayer> mergeBuffer;
        sortByZOrder(m_negZOrderList, &mergeBuffer, 0, m_negZOrderList->count());
    }

    m_zOrderListsDirty = false;
}

void RenderLayer::collectLayers(QPtrVector<RenderLayer>*& posBuffer, QPtrVector<RenderLayer>*& negBuffer)
{
    // FIXME: A child render object or layer could override visibility.  Don't remove this
    // optimization though until RenderObject's nodeAtPoint is patched to understand what to do
    // when visibility is overridden by a child.
    if (renderer()->style()->visibility() != VISIBLE)
        return;
    
    // Determine which buffer the child should be in.
    QPtrVector<RenderLayer>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;

    // Create the buffer if it doesn't exist yet.
    if (!buffer)
        buffer = new QPtrVector<RenderLayer>();
    
    // Resize by a power of 2 when our buffer fills up.
    if (buffer->count() == buffer->size())
        buffer->resize(2*(buffer->size()+1));

    // Append ourselves at the end of the appropriate buffer.
    buffer->insert(buffer->count(), this);

    // Recur into our children to collect more layers, but only if we don't establish
    // a stacking context.
    if (!isStackingContext()) {
        for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
            child->collectLayers(posBuffer, negBuffer);
    }
}
-------------- next part --------------
/*
 * Copyright (C) 2003 Apple Computer, Inc.
 *
 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
 *
 * Other contributors:
 *   Robert O'Callahan <roc+ at cs.cmu.edu>
 *   David Baron <dbaron at fas.harvard.edu>
 *   Christian Biesinger <cbiesinger at web.de>
 *   Randall Jesup <rjesup at wgate.com>
 *   Roland Mainz <roland.mainz at informatik.med.uni-giessen.de>
 *   Josh Soref <timeless at mac.com>
 *   Boris Zbarsky <bzbarsky at mit.edu>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Alternatively, the contents of this file may be used under the terms
 * of either the Mozilla Public License Version 1.1, found at
 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
 * (the "GPL"), in which case the provisions of the MPL or the GPL are
 * applicable instead of those above.  If you wish to allow use of your
 * version of this file only under the terms of one of those two
 * licenses (the MPL or the GPL) and not to allow others to use your
 * version of this file under the LGPL, indicate your decision by
 * deletingthe provisions above and replace them with the notice and
 * other provisions required by the MPL or the GPL, as the case may be.
 * If you do not delete the provisions above, a recipient may use your
 * version of this file under any of the LGPL, the MPL or the GPL.
 */

#ifndef render_layer_h
#define render_layer_h

#include <qcolor.h>
#include <qrect.h>
#include <assert.h>

#include "render_object.h"

class QScrollBar;
template <class T> class QPtrVector;

namespace khtml {
    class RenderStyle;
    class RenderTable;
    class CachedObject;
    class RenderCanvas;
    class RenderText;
    class RenderFrameSet;
    class RenderObject;
    class RenderScrollMediator;
    
class RenderScrollMediator: public QObject
{
public:
    RenderScrollMediator(RenderLayer* layer)
    :m_layer(layer) {}

    void slotValueChanged(int);
    
private:
    RenderLayer* m_layer;
};
    
class RenderLayer
{
public:
#ifdef APPLE_CHANGES
    static QScrollBar* gScrollBar;
#endif
    
    RenderLayer(RenderObject* object);
    ~RenderLayer();
    
    RenderObject* renderer() const { return m_object; }
    RenderLayer *parent() const { return m_parent; }
    RenderLayer *previousSibling() const { return m_previous; }
    RenderLayer *nextSibling() const { return m_next; }

    RenderLayer *firstChild() const { return m_first; }
    RenderLayer *lastChild() const { return m_last; }

    void addChild(RenderLayer *newChild, RenderLayer* beforeChild = 0);
    RenderLayer* removeChild(RenderLayer *oldChild);

    void removeOnlyThisLayer();
    void insertOnlyThisLayer();

#if APPLE_CHANGES
    bool isTransparent();
    RenderLayer* transparentAncestor();
#endif
    
    RenderLayer* root() {
        RenderLayer* curr = this;
        while (curr->parent()) curr = curr->parent();
        return curr;
    }
    
    int xPos() const { return m_x; }
    int yPos() const { return m_y; }
    short width() const { return m_width; }
    int height() const { return m_height; }

    void setWidth(short w) { m_width = w; }
    void setHeight(int h) { m_height = h; }
    
    short scrollWidth() const { return m_scrollWidth; }
    int scrollHeight() const { return m_scrollHeight; }
    
    void setPos( int xPos, int yPos ) {
        m_x = xPos;
        m_y = yPos;
    }

    // Scrolling methods for layers that can scroll their overflow.
    void scrollOffset(int& x, int& y);
    void subtractScrollOffset(int& x, int& y);
    short scrollXOffset() { return m_scrollX; }
    int scrollYOffset() { return m_scrollY; }
    void scrollToOffset(int x, int y, bool updateScrollbars = true);
    void scrollToXOffset(int x) { scrollToOffset(x, m_scrollY); }
    void scrollToYOffset(int y) { scrollToOffset(m_scrollX, y); }
    void setHasHorizontalScrollbar(bool hasScrollbar);
    void setHasVerticalScrollbar(bool hasScrollbar);
    QScrollBar* horizontalScrollbar() { return m_hBar; }
    QScrollBar* verticalScrollbar() { return m_vBar; }
    int verticalScrollbarWidth();
    int horizontalScrollbarHeight();
    void moveScrollbarsAside();
    void positionScrollbars(const QRect& absBounds);
#ifdef APPLE_CHANGES
    void paintScrollbars(QPainter* p, const QRect& damageRect);
#endif
    void checkScrollbarsAfterLayout();
    void slotValueChanged(int);
    void updateScrollPositionFromScrollbars();

    void updateLayerPosition();

    // Get the enclosing stacking context for this layer.  A stacking context is a layer
    // that has a non-auto z-index.
    RenderLayer* stackingContext() const;
    bool isStackingContext() const { return !hasAutoZIndex() || renderer()->isCanvas(); }

    void dirtyZOrderLists();
    void updateZOrderLists();
    QPtrVector<RenderLayer>* posZOrderList() const { return m_posZOrderList; }
    QPtrVector<RenderLayer>* negZOrderList() const { return m_negZOrderList; }
    
    // Gets the nearest enclosing positioned ancestor layer (also includes
    // the <html> layer and the root layer).
    RenderLayer* enclosingPositionedAncestor() const;
    
    void convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const;
    
    bool hasAutoZIndex() const { return renderer()->style()->hasAutoZIndex(); }
    int zIndex() const { return renderer()->style()->zIndex(); }

    // The two main functions that use the layer system.  The paint method
    // paints the layers that intersect the damage rect from back to
    // front.  The nodeAtPoint method looks for mouse events by walking
    // layers that intersect the point from front to back.
    void paint(QPainter *p, const QRect& damageRect, bool selectionOnly=false);
    bool nodeAtPoint(RenderObject::NodeInfo& info, int x, int y);

    // This method figures out our layerBounds in coordinates relative to
    // |rootLayer}.  It also computes our background and foreground clip rects
    // for painting/event handling.
    void calculateRects(const RenderLayer* rootLayer, const QRect& paintDirtyRect, QRect& layerBounds,
                        QRect& backgroundRect, QRect& foregroundRect);
    void calculateClipRects(const RenderLayer* rootLayer, QRect& overflowClipRect,
                            QRect& posClipRect, QRect& fixedClipRect);

    bool intersectsDamageRect(const QRect& layerBounds, const QRect& damageRect) const;
    bool containsPoint(int x, int y, const QRect& damageRect) const;
    
    void updateHoverActiveState(RenderObject::NodeInfo& info);
    
    void detach(RenderArena* renderArena);

     // Overloaded new operator.  Derived classes must override operator new
    // in order to allocate out of the RenderArena.
    void* operator new(size_t sz, RenderArena* renderArena) throw();    

    // Overridden to prevent the normal delete from being called.
    void operator delete(void* ptr, size_t sz);
        
private:
    // The normal operator new is disallowed on all render objects.
    void* operator new(size_t sz) throw();

private:
    void setNextSibling(RenderLayer* next) { m_next = next; }
    void setPreviousSibling(RenderLayer* prev) { m_previous = prev; }
    void setParent(RenderLayer* parent) { m_parent = parent; }
    void setFirstChild(RenderLayer* first) { m_first = first; }
    void setLastChild(RenderLayer* last) { m_last = last; }

    void collectLayers(QPtrVector<RenderLayer>*&, QPtrVector<RenderLayer>*&);

    void paintLayer(RenderLayer* rootLayer, QPainter *p, const QRect& paintDirtyRect, bool selectionOnly=false);
    RenderLayer* nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
                                     int x, int y, const QRect& hitTestRect);

protected:   
    RenderObject* m_object;
    
    RenderLayer* m_parent;
    RenderLayer* m_previous;
    RenderLayer* m_next;

    RenderLayer* m_first;
    RenderLayer* m_last;
    
    // Our (x,y) coordinates are in our parent layer's coordinate space.
    short m_x;
    int m_y;

    // The layer's width/height
    short m_width;
    int m_height;
    
    // Our scroll offsets if the view is scrolled.
    short m_scrollX;
    int m_scrollY;
    
    // The width/height of our scrolled area.
    short m_scrollWidth;
    int m_scrollHeight;
    
    // For layers with overflow, we have a pair of scrollbars.
    QScrollBar* m_hBar;
    QScrollBar* m_vBar;
    RenderScrollMediator* m_scrollMediator;

    // For layers that establish stacking contexts, m_posZOrderList holds a sorted list of all the
    // descendant layers within the stacking context that have z-indices of 0 or greater
    // (auto will count as 0).  m_negZOrderList holds descendants within our stacking context with negative
    // z-indices.
    QPtrVector<RenderLayer>* m_posZOrderList;
    QPtrVector<RenderLayer>* m_negZOrderList;
    bool m_zOrderListsDirty;
};

}; // namespace
#endif
-------------- next part --------------


-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/001-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/002-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/003-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/004-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/005-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/006-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/007-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/008-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/009-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/010-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/011-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/012-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/013-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/014-0001.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.kde.org/mailman/private/khtml-devel/attachments/20030902/4c49d262/015-0001.html
-------------- next part --------------



More information about the Khtml-devel mailing list