[SCM] WebKit Debian packaging branch, debian/unstable, updated. debian/1.1.15-1-40151-g37bb677
hyatt
hyatt at 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Sat Sep 26 07:56:40 UTC 2009
The following commit has been merged in the debian/unstable branch:
commit 29ff69e75388b38357ee72f296dbac7af3cd631e
Author: hyatt <hyatt at 268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Fri Sep 19 22:54:38 2003 +0000
Fix for 3401409, fix negative z-index. This code actually substantially
reworks layers to be more efficient in both painting and event handling.
It also fixes bugs with clipping as well as with negative z-indices.
Reviewed by kocienda
* khtml/css/cssstyleselector.cpp:
* khtml/rendering/render_block.cpp:
* khtml/rendering/render_block.h:
* khtml/rendering/render_box.cpp:
(RenderBox::setStyle):
(RenderBox::repaintRectangle):
* khtml/rendering/render_box.h:
* khtml/rendering/render_frames.cpp:
(RenderFrameSet::nodeAtPoint):
* khtml/rendering/render_frames.h:
* khtml/rendering/render_image.cpp:
(RenderImage::nodeAtPoint):
* khtml/rendering/render_image.h:
* khtml/rendering/render_inline.cpp:
(RenderInline::nodeAtPoint):
* khtml/rendering/render_inline.h:
* khtml/rendering/render_layer.cpp:
(RenderLayer::RenderLayer):
(RenderLayer::~RenderLayer):
(RenderLayer::updateLayerPosition):
(RenderLayer::stackingContext):
(RenderLayer::enclosingPositionedAncestor):
(RenderLayer::transparentAncestor):
(RenderLayer::addChild):
(RenderLayer::removeChild):
(RenderLayer::convertToLayerCoords):
(RenderLayer::checkScrollbarsAfterLayout):
(RenderLayer::paintScrollbars):
(RenderLayer::paint):
(setClip):
(restoreClip):
(RenderLayer::paintLayer):
(RenderLayer::nodeAtPoint):
(RenderLayer::nodeAtPointForLayer):
(RenderLayer::calculateClipRects):
(RenderLayer::calculateRects):
(RenderLayer::intersectsDamageRect):
(RenderLayer::containsPoint):
(hoverAncestor):
(commonAncestor):
(RenderLayer::updateHoverActiveState):
(sortByZOrder):
(RenderLayer::dirtyZOrderLists):
(RenderLayer::updateZOrderLists):
(RenderLayer::collectLayers):
* khtml/rendering/render_layer.h:
* khtml/rendering/render_object.cpp:
(RenderObject::setStyle):
(RenderObject::document):
(RenderObject::renderArena):
(RenderObject::nodeAtPoint):
* khtml/rendering/render_object.h:
* khtml/rendering/render_text.cpp:
(RenderText::nodeAtPoint):
* khtml/rendering/render_text.h:
* khtml/xml/dom_docimpl.cpp:
(DocumentImpl::DocumentImpl):
(DocumentImpl::~DocumentImpl):
(DocumentImpl::recalcStyleSelector):
(DocumentImpl::setHoverNode):
* khtml/xml/dom_docimpl.h:
* kwq/KWQKHTMLPart.mm:
(KWQKHTMLPart::paint):
(KWQKHTMLPart::paintSelectionOnly):
(KWQKHTMLPart::adjustPageHeight):
* kwq/KWQRect.h:
* kwq/KWQRenderTreeDebug.cpp:
(write):
(writeLayers):
(externalRepresentation):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@5009 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebCore/ChangeLog-2003-10-25 b/WebCore/ChangeLog-2003-10-25
index c1728ce..bd4a785 100644
--- a/WebCore/ChangeLog-2003-10-25
+++ b/WebCore/ChangeLog-2003-10-25
@@ -1,3 +1,82 @@
+2003-09-19 David Hyatt <hyatt at apple.com>
+
+ Fix for 3401409, fix negative z-index. This code actually substantially
+ reworks layers to be more efficient in both painting and event handling.
+ It also fixes bugs with clipping as well as with negative z-indices.
+
+ Reviewed by kocienda
+
+ * khtml/css/cssstyleselector.cpp:
+ * khtml/rendering/render_block.cpp:
+ * khtml/rendering/render_block.h:
+ * khtml/rendering/render_box.cpp:
+ (RenderBox::setStyle):
+ (RenderBox::repaintRectangle):
+ * khtml/rendering/render_box.h:
+ * khtml/rendering/render_frames.cpp:
+ (RenderFrameSet::nodeAtPoint):
+ * khtml/rendering/render_frames.h:
+ * khtml/rendering/render_image.cpp:
+ (RenderImage::nodeAtPoint):
+ * khtml/rendering/render_image.h:
+ * khtml/rendering/render_inline.cpp:
+ (RenderInline::nodeAtPoint):
+ * khtml/rendering/render_inline.h:
+ * khtml/rendering/render_layer.cpp:
+ (RenderLayer::RenderLayer):
+ (RenderLayer::~RenderLayer):
+ (RenderLayer::updateLayerPosition):
+ (RenderLayer::stackingContext):
+ (RenderLayer::enclosingPositionedAncestor):
+ (RenderLayer::transparentAncestor):
+ (RenderLayer::addChild):
+ (RenderLayer::removeChild):
+ (RenderLayer::convertToLayerCoords):
+ (RenderLayer::checkScrollbarsAfterLayout):
+ (RenderLayer::paintScrollbars):
+ (RenderLayer::paint):
+ (setClip):
+ (restoreClip):
+ (RenderLayer::paintLayer):
+ (RenderLayer::nodeAtPoint):
+ (RenderLayer::nodeAtPointForLayer):
+ (RenderLayer::calculateClipRects):
+ (RenderLayer::calculateRects):
+ (RenderLayer::intersectsDamageRect):
+ (RenderLayer::containsPoint):
+ (hoverAncestor):
+ (commonAncestor):
+ (RenderLayer::updateHoverActiveState):
+ (sortByZOrder):
+ (RenderLayer::dirtyZOrderLists):
+ (RenderLayer::updateZOrderLists):
+ (RenderLayer::collectLayers):
+ * khtml/rendering/render_layer.h:
+ * khtml/rendering/render_object.cpp:
+ (RenderObject::setStyle):
+ (RenderObject::document):
+ (RenderObject::renderArena):
+ (RenderObject::nodeAtPoint):
+ * khtml/rendering/render_object.h:
+ * khtml/rendering/render_text.cpp:
+ (RenderText::nodeAtPoint):
+ * khtml/rendering/render_text.h:
+ * khtml/xml/dom_docimpl.cpp:
+ (DocumentImpl::DocumentImpl):
+ (DocumentImpl::~DocumentImpl):
+ (DocumentImpl::recalcStyleSelector):
+ (DocumentImpl::setHoverNode):
+ * khtml/xml/dom_docimpl.h:
+ * kwq/KWQKHTMLPart.mm:
+ (KWQKHTMLPart::paint):
+ (KWQKHTMLPart::paintSelectionOnly):
+ (KWQKHTMLPart::adjustPageHeight):
+ * kwq/KWQRect.h:
+ * kwq/KWQRenderTreeDebug.cpp:
+ (write):
+ (writeLayers):
+ (externalRepresentation):
+
2003-09-19 Darin Adler <darin at apple.com>
Reviewed by Dave.
diff --git a/WebCore/ChangeLog-2005-08-23 b/WebCore/ChangeLog-2005-08-23
index c1728ce..bd4a785 100644
--- a/WebCore/ChangeLog-2005-08-23
+++ b/WebCore/ChangeLog-2005-08-23
@@ -1,3 +1,82 @@
+2003-09-19 David Hyatt <hyatt at apple.com>
+
+ Fix for 3401409, fix negative z-index. This code actually substantially
+ reworks layers to be more efficient in both painting and event handling.
+ It also fixes bugs with clipping as well as with negative z-indices.
+
+ Reviewed by kocienda
+
+ * khtml/css/cssstyleselector.cpp:
+ * khtml/rendering/render_block.cpp:
+ * khtml/rendering/render_block.h:
+ * khtml/rendering/render_box.cpp:
+ (RenderBox::setStyle):
+ (RenderBox::repaintRectangle):
+ * khtml/rendering/render_box.h:
+ * khtml/rendering/render_frames.cpp:
+ (RenderFrameSet::nodeAtPoint):
+ * khtml/rendering/render_frames.h:
+ * khtml/rendering/render_image.cpp:
+ (RenderImage::nodeAtPoint):
+ * khtml/rendering/render_image.h:
+ * khtml/rendering/render_inline.cpp:
+ (RenderInline::nodeAtPoint):
+ * khtml/rendering/render_inline.h:
+ * khtml/rendering/render_layer.cpp:
+ (RenderLayer::RenderLayer):
+ (RenderLayer::~RenderLayer):
+ (RenderLayer::updateLayerPosition):
+ (RenderLayer::stackingContext):
+ (RenderLayer::enclosingPositionedAncestor):
+ (RenderLayer::transparentAncestor):
+ (RenderLayer::addChild):
+ (RenderLayer::removeChild):
+ (RenderLayer::convertToLayerCoords):
+ (RenderLayer::checkScrollbarsAfterLayout):
+ (RenderLayer::paintScrollbars):
+ (RenderLayer::paint):
+ (setClip):
+ (restoreClip):
+ (RenderLayer::paintLayer):
+ (RenderLayer::nodeAtPoint):
+ (RenderLayer::nodeAtPointForLayer):
+ (RenderLayer::calculateClipRects):
+ (RenderLayer::calculateRects):
+ (RenderLayer::intersectsDamageRect):
+ (RenderLayer::containsPoint):
+ (hoverAncestor):
+ (commonAncestor):
+ (RenderLayer::updateHoverActiveState):
+ (sortByZOrder):
+ (RenderLayer::dirtyZOrderLists):
+ (RenderLayer::updateZOrderLists):
+ (RenderLayer::collectLayers):
+ * khtml/rendering/render_layer.h:
+ * khtml/rendering/render_object.cpp:
+ (RenderObject::setStyle):
+ (RenderObject::document):
+ (RenderObject::renderArena):
+ (RenderObject::nodeAtPoint):
+ * khtml/rendering/render_object.h:
+ * khtml/rendering/render_text.cpp:
+ (RenderText::nodeAtPoint):
+ * khtml/rendering/render_text.h:
+ * khtml/xml/dom_docimpl.cpp:
+ (DocumentImpl::DocumentImpl):
+ (DocumentImpl::~DocumentImpl):
+ (DocumentImpl::recalcStyleSelector):
+ (DocumentImpl::setHoverNode):
+ * khtml/xml/dom_docimpl.h:
+ * kwq/KWQKHTMLPart.mm:
+ (KWQKHTMLPart::paint):
+ (KWQKHTMLPart::paintSelectionOnly):
+ (KWQKHTMLPart::adjustPageHeight):
+ * kwq/KWQRect.h:
+ * kwq/KWQRenderTreeDebug.cpp:
+ (write):
+ (writeLayers):
+ (externalRepresentation):
+
2003-09-19 Darin Adler <darin at apple.com>
Reviewed by Dave.
diff --git a/WebCore/khtml/css/cssstyleselector.cpp b/WebCore/khtml/css/cssstyleselector.cpp
index 291c39a..8e3359c 100644
--- a/WebCore/khtml/css/cssstyleselector.cpp
+++ b/WebCore/khtml/css/cssstyleselector.cpp
@@ -527,6 +527,21 @@ void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e
}
}
+ // 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
diff --git a/WebCore/khtml/rendering/render_block.cpp b/WebCore/khtml/rendering/render_block.cpp
index 3c5c328..bb97360 100644
--- a/WebCore/khtml/rendering/render_block.cpp
+++ b/WebCore/khtml/rendering/render_block.cpp
@@ -1853,13 +1853,14 @@ bool RenderBlock::isPointInScrollbar(int _x, int _y, int _tx, int _ty)
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& info, int _x, int _y, int _tx, int _ty,
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;
}
diff --git a/WebCore/khtml/rendering/render_block.h b/WebCore/khtml/rendering/render_block.h
index e4733d1..6675b74 100644
--- a/WebCore/khtml/rendering/render_block.h
+++ b/WebCore/khtml/rendering/render_block.h
@@ -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);
diff --git a/WebCore/khtml/rendering/render_box.cpp b/WebCore/khtml/rendering/render_box.cpp
index ab6ccc3..4ad3b97 100644
--- a/WebCore/khtml/rendering/render_box.cpp
+++ b/WebCore/khtml/rendering/render_box.cpp
@@ -108,34 +108,11 @@ void RenderBox::setStyle(RenderStyle *_style)
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, int y, int w, int h, bool immediate, boo
// 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;
diff --git a/WebCore/khtml/rendering/render_box.h b/WebCore/khtml/rendering/render_box.h
index a18711f..1023b82 100644
--- a/WebCore/khtml/rendering/render_box.h
+++ b/WebCore/khtml/rendering/render_box.h
@@ -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;
diff --git a/WebCore/khtml/rendering/render_frames.cpp b/WebCore/khtml/rendering/render_frames.cpp
index eda1e13..611d7a6 100644
--- a/WebCore/khtml/rendering/render_frames.cpp
+++ b/WebCore/khtml/rendering/render_frames.cpp
@@ -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);
diff --git a/WebCore/khtml/rendering/render_frames.h b/WebCore/khtml/rendering/render_frames.h
index c71fa5b..4e0067b 100644
--- a/WebCore/khtml/rendering/render_frames.h
+++ b/WebCore/khtml/rendering/render_frames.h
@@ -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()); }
diff --git a/WebCore/khtml/rendering/render_image.cpp b/WebCore/khtml/rendering/render_image.cpp
index 4122a1e..4ed65bc 100644
--- a/WebCore/khtml/rendering/render_image.cpp
+++ b/WebCore/khtml/rendering/render_image.cpp
@@ -439,9 +439,10 @@ void RenderImage::detach(RenderArena *arena)
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;
diff --git a/WebCore/khtml/rendering/render_image.h b/WebCore/khtml/rendering/render_image.h
index 55558d4..c8083c2 100644
--- a/WebCore/khtml/rendering/render_image.h
+++ b/WebCore/khtml/rendering/render_image.h
@@ -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;
diff --git a/WebCore/khtml/rendering/render_inline.cpp b/WebCore/khtml/rendering/render_inline.cpp
index c43d1dd..69fa098 100644
--- a/WebCore/khtml/rendering/render_inline.cpp
+++ b/WebCore/khtml/rendering/render_inline.cpp
@@ -366,15 +366,18 @@ const char *RenderInline::renderName() const
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& info, int _x, int _y, int _tx, int _ty,
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;
}
diff --git a/WebCore/khtml/rendering/render_inline.h b/WebCore/khtml/rendering/render_inline.h
index 364e5b7..3e17624 100644
--- a/WebCore/khtml/rendering/render_inline.h
+++ b/WebCore/khtml/rendering/render_inline.h
@@ -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();
diff --git a/WebCore/khtml/rendering/render_layer.cpp b/WebCore/khtml/rendering/render_layer.cpp
index b3864cc..05b35c7 100644
--- a/WebCore/khtml/rendering/render_layer.cpp
+++ b/WebCore/khtml/rendering/render_layer.cpp
@@ -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 *child, RenderLayer* beforeChild)
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(RenderLayer* oldChild)
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)
- return;
+ paintLayer(this, p, damageRect, selectionOnly);
+}
- // Flatten the tree into a back-to-front list for painting.
- QPtrVector<RenderLayerElement> layerList;
- constructLayerList(node, &layerList);
+static void setClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect)
+{
+ if (paintDirtyRect == clipRect)
+ return;
- // Walk the list and paint each layer, adding in the appropriate offset.
- QRect paintRect(x, y, w, h);
- QRect currRect(paintRect);
- RenderLayer* currentTransparentLayer = 0;
+ p->save();
- 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);
#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;
- }
-
- 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);
- }
+ // 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 != 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);
+ }
+
+ // 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);
+ }
}
- m_parent->clearOtherLayersHoverActiveState();
+#if APPLE_CHANGES
+ // End our transparency layer
+ if (isTransparent())
+ p->endTransparencyLayer();
+#endif
}
-void
-RenderLayer::clearHoverAndActiveState(RenderObject* obj)
+bool
+RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
{
- if (!obj->mouseInside())
- return;
+#if APPLE_CHANGES
+ // Clear our our scrollbar variable
+ RenderLayer::gScrollBar = 0;
+#endif
- obj->setMouseInside(false);
- if (obj->element()) {
- obj->element()->setActive(false);
- if (obj->style()->affectedByHoverRules() || obj->style()->affectedByActiveRules())
- obj->element()->setChanged(true);
+ 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();
}
-
- for (RenderObject* child = obj->firstChild(); child; child = child->nextSibling())
- if (child->mouseInside())
- clearHoverAndActiveState(child);
+
+ // 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;
}
-bool
-RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y)
+RenderLayer*
+RenderLayer::nodeAtPointForLayer(RenderLayer* rootLayer, RenderObject::NodeInfo& info,
+ int xMousePos, int yMousePos, const QRect& hitTestRect)
{
- // Clear out our global scrollbar tracking variable.
- gScrollBar = 0;
+ // Calculate the clip rects we should use.
+ QRect layerBounds, bgRect, fgRect;
+ calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect);
- bool inside = false;
+ // 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)
+{
+ return (!obj->isInline() && obj->continuation()) ? obj->continuation() : obj->parent();
+}
+
+static RenderObject* commonAncestor(RenderObject* obj1, RenderObject* obj2)
{
- // This merge buffer is just a temporary used during computation as we do merge sorting.
- QPtrVector<RenderLayerElement> mergeBuffer;
- ztree->constructLayerList(&mergeBuffer, result);
+ 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<RenderLayer::RenderLayerElement>* buffer,
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<RenderLayer::RenderLayerElement>* buffer,
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<RenderLayer::RenderLayerElement>* buffer,
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)
@@ -1068,160 +1016,62 @@ static void sortByZOrder(QPtrVector<RenderLayer::RenderLayerElement>* buffer,
}
}
-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
+ if (!isStackingContext() || !m_zOrderListsDirty)
+ return;
- // Recover the size left there for us by operator delete and free the memory.
- renderArena->free(*(size_t *)this, this);
-}
+ for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+ child->collectLayers(m_posZOrderList, m_negZOrderList);
-void* RenderLayer::RenderZTreeNode::operator new(size_t sz, RenderArena* renderArena) throw()
-{
- void* result = renderArena->allocate(sz);
- if (result)
- memset(result, 0, sz);
- return result;
-}
+ // 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());
+ }
-void RenderLayer::RenderZTreeNode::operator delete(void* ptr, size_t sz)
-{
- assert(inRenderZTreeNodeDetach);
-
- // Stash size where detach can find it.
- *(size_t *)ptr = sz;
+ m_zOrderListsDirty = false;
}
-void RenderLayer::RenderZTreeNode::detach(RenderArena* renderArena)
+void RenderLayer::collectLayers(QPtrVector<RenderLayer>*& posBuffer, QPtrVector<RenderLayer>*& negBuffer)
{
- assert(!next);
-
- RenderZTreeNode *n;
- for (RenderZTreeNode *c = child; c; c = n) {
- n = c->next;
- c->next = 0;
- c->detach(renderArena);
- }
- if (layerElement)
- layerElement->detach(renderArena);
-
-#ifndef NDEBUG
- inRenderZTreeNodeDetach = true;
-#endif
- delete this;
-#ifndef NDEBUG
- inRenderZTreeNodeDetach = false;
-#endif
+ // 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;
- // Recover the size left there for us by operator delete and free the memory.
- renderArena->free(*(size_t *)this, this);
-}
+ // Determine which buffer the child should be in.
+ QPtrVector<RenderLayer>*& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
-QPtrVector<RenderLayer::RenderLayerElement> RenderLayer::elementList(RenderZTreeNode *&node)
-{
- QPtrVector<RenderLayerElement> list;
+ // Create the buffer if it doesn't exist yet.
+ if (!buffer)
+ buffer = new QPtrVector<RenderLayer>();
- QRect damageRect(m_x, m_y, m_width, m_height);
- node = constructZTree(damageRect, damageRect, this);
- if (node) {
- constructLayerList(node, &list);
+ // 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;
}
diff --git a/WebCore/khtml/rendering/render_layer.h b/WebCore/khtml/rendering/render_layer.h
index 35b14a4..6408fd2 100644
--- a/WebCore/khtml/rendering/render_layer.h
+++ b/WebCore/khtml/rendering/render_layer.h
@@ -49,8 +49,9 @@
#include <assert.h>
#include "render_object.h"
-#include <qvector.h>
-#include <qscrollbar.h>
+
+class QScrollBar;
+template <class T> class QPtrVector;
namespace khtml {
class RenderStyle;
@@ -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
diff --git a/WebCore/khtml/rendering/render_object.cpp b/WebCore/khtml/rendering/render_object.cpp
index 73d7801..5a8679e 100644
--- a/WebCore/khtml/rendering/render_object.cpp
+++ b/WebCore/khtml/rendering/render_object.cpp
@@ -983,6 +983,19 @@ void RenderObject::setStyle(RenderStyle *style)
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,9 +1241,13 @@ RenderArena* RenderObject::renderArena() const
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;
}
@@ -1336,20 +1353,8 @@ bool RenderObject::mouseInside() const
return m_mouseInside;
}
-void RenderObject::setHoverAndActive(NodeInfo& info, bool oldinside, 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)
+bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
+ HitTestAction hitTestAction, bool inside)
{
int tx = _tx + xPos();
int ty = _ty + yPos();
@@ -1363,11 +1368,14 @@ bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
}
// ### 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& info, int _x, int _y, int _tx, int _ty,
}
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& info, int _x, int _y, int _tx, int _ty,
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;
diff --git a/WebCore/khtml/rendering/render_object.h b/WebCore/khtml/rendering/render_object.h
index 8d6dcab..cab0c0f 100644
--- a/WebCore/khtml/rendering/render_object.h
+++ b/WebCore/khtml/rendering/render_object.h
@@ -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);
diff --git a/WebCore/khtml/rendering/render_text.cpp b/WebCore/khtml/rendering/render_text.cpp
index 5928633..32faef7 100644
--- a/WebCore/khtml/rendering/render_text.cpp
+++ b/WebCore/khtml/rendering/render_text.cpp
@@ -379,7 +379,8 @@ TextRun * RenderText::findTextRun( int offset, int &pos )
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());
@@ -395,8 +396,6 @@ bool RenderText::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, b
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()) {
@@ -411,7 +410,7 @@ bool RenderText::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, b
if (!info.innerNode())
info.setInnerNode(element());
- if(!info.innerNonSharedNode())
+ if (!info.innerNonSharedNode())
info.setInnerNonSharedNode(element());
}
diff --git a/WebCore/khtml/rendering/render_text.h b/WebCore/khtml/rendering/render_text.h
index 032d6a1..c3ae5ac 100644
--- a/WebCore/khtml/rendering/render_text.h
+++ b/WebCore/khtml/rendering/render_text.h
@@ -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
diff --git a/WebCore/khtml/xml/dom_docimpl.cpp b/WebCore/khtml/xml/dom_docimpl.cpp
index 876302f..66c373c 100644
--- a/WebCore/khtml/xml/dom_docimpl.cpp
+++ b/WebCore/khtml/xml/dom_docimpl.cpp
@@ -284,6 +284,7 @@ DocumentImpl::DocumentImpl(DOMImplementationImpl *_implementation, KHTMLView *v)
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;
@@ -2022,6 +2026,17 @@ void DocumentImpl::recalcStyleSelector()
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)
{
// Make sure newFocusNode is actually in this document
diff --git a/WebCore/khtml/xml/dom_docimpl.h b/WebCore/khtml/xml/dom_docimpl.h
index 6c88c75..e3bc40f 100644
--- a/WebCore/khtml/xml/dom_docimpl.h
+++ b/WebCore/khtml/xml/dom_docimpl.h
@@ -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;
diff --git a/WebCore/kwq/KWQKHTMLPart.mm b/WebCore/kwq/KWQKHTMLPart.mm
index 3286f71..0c9a886 100644
--- a/WebCore/kwq/KWQKHTMLPart.mm
+++ b/WebCore/kwq/KWQKHTMLPart.mm
@@ -56,6 +56,8 @@
#import <JavaScriptCore/property_map.h>
+#import <qscrollbar.h>
+
#undef _KWQ_TIMING
using DOM::DocumentImpl;
@@ -787,7 +789,7 @@ void KWQKHTMLPart::paint(QPainter *p, const QRect &rect)
#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");
}
@@ -796,7 +798,7 @@ void KWQKHTMLPart::paint(QPainter *p, const QRect &rect)
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");
}
@@ -811,8 +813,9 @@ void KWQKHTMLPart::adjustPageHeight(float *newBottom, float oldTop, float oldBot
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;
diff --git a/WebCore/kwq/KWQRect.h b/WebCore/kwq/KWQRect.h
index e36359a..9591a9a 100644
--- a/WebCore/kwq/KWQRect.h
+++ b/WebCore/kwq/KWQRect.h
@@ -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);
diff --git a/WebCore/kwq/KWQRenderTreeDebug.cpp b/WebCore/kwq/KWQRenderTreeDebug.cpp
index 3df48ef..06d6edc 100644
--- a/WebCore/kwq/KWQRenderTreeDebug.cpp
+++ b/WebCore/kwq/KWQRenderTreeDebug.cpp
@@ -42,10 +42,8 @@ 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 RenderObject &o, int indent = 0);
+static void writeLayers(QTextStream &ts, const RenderLayer* rootLayer, RenderLayer* l,
+ const QRect& paintDirtyRect, int indent=0);
static QTextStream &operator<<(QTextStream &ts, const QRect &r)
{
@@ -149,16 +147,18 @@ static void write(QTextStream &ts, const RenderObject &o, int indent = 0)
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 RenderLayerElement &e, int indent = 0)
QRect r(e.absBounds);
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 RenderObject *o)
{
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;
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list