Version: SVN trunk (using KDE Devel) Installed from: Compiled sources OS: Linux If you resize the KHTML area, a gray block will appear at the bottom of that area. To reproduce, open Konqueror at www.kde.org, scroll to the bottom, and vertically enlarge the window (at the bottom). Now you should see a gray block. Same with the messageviewer in KMail or the chat window in Kopete. See also http://lists.kde.org/?l=kfm-devel&m=118000495330438&w=2. This happens only in KDE4.
SVN commit 669159 by ggarand: Adapt to Qt 4.3's renewed lack of forgiveness. It is now mandatory to end any QPainter active on devices that are the target of a redirection, which in turn forces the unwinding of the stack, making save()/restore() useless. => reimplement save/restore for clipping ;( BUG: 145948 M +25 -10 render_layer.cpp M +2 -0 render_layer.h M +7 -1 render_replaced.cpp --- trunk/KDE/kdelibs/khtml/rendering/render_layer.cpp #669158:669159 @@ -60,11 +60,13 @@ #include "xml/dom_restyler.h" #include <QtGui/QStyle> +#include <QtCore/QStack> using namespace DOM; using namespace khtml; ScrollBarWidget* RenderLayer::gScrollBar = 0; +QStack<QRegion>* RenderLayer::s_clipHolder = 0; #ifndef NDEBUG static bool inRenderLayerDetach; @@ -815,30 +817,37 @@ paintLayer(this, p, damageRect, selectionOnly); } -static void setClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect) +static void setClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect, bool setup = false) { if (paintDirtyRect == clipRect) return; - p->save(); + if (!RenderLayer::s_clipHolder) + RenderLayer::s_clipHolder = new QStack<QRegion>; -#ifdef APPLE_CHANGES - p->addClip(clipRect); -#else - p->setClipRect(clipRect, Qt::IntersectClip); -#endif - + QRegion r = clipRect; + if (!RenderLayer::s_clipHolder->isEmpty()) + r &= RenderLayer::s_clipHolder->top(); + + p->setClipRegion( r ); + RenderLayer::s_clipHolder->push( r ); } -static void restoreClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect) +static void restoreClip(QPainter* p, const QRect& paintDirtyRect, const QRect& clipRect, bool cleanup = false) { if (paintDirtyRect == clipRect) return; - p->restore(); + RenderLayer::s_clipHolder->pop(); + if (!RenderLayer::s_clipHolder->isEmpty()) + p->setClipRegion( RenderLayer::s_clipHolder->top() ); + else + p->setClipRegion( QRegion(), Qt::NoClip ); } void RenderLayer::paintLayer(RenderLayer* rootLayer, QPainter *p, const QRect& paintDirtyRect, bool selectionOnly) { + assert( rootLayer != this || !s_clipHolder ); + // Calculate the clip rects we should use. QRect layerBounds, damageRect, clipRectToApply; calculateRects(rootLayer, paintDirtyRect, layerBounds, damageRect, clipRectToApply); @@ -951,6 +960,12 @@ // End our transparency layer if (isTransparent()) p->setOpacity(previousOpacity); + + if (s_clipHolder && rootLayer == this) { + assert(s_clipHolder->isEmpty()); + delete s_clipHolder; + s_clipHolder = 0; + } } bool RenderLayer::nodeAtPoint(RenderObject::NodeInfo& info, int x, int y) --- trunk/KDE/kdelibs/khtml/rendering/render_layer.h #669158:669159 @@ -51,6 +51,7 @@ #include "render_object.h" //template <class T*> class QVector; +template <class T> class QStack; namespace khtml { class RenderStyle; @@ -128,6 +129,7 @@ { public: static ScrollBarWidget* gScrollBar; + static QStack<QRegion>* s_clipHolder; RenderLayer(RenderObject* object); ~RenderLayer(); --- trunk/KDE/kdelibs/khtml/rendering/render_replaced.cpp #669158:669159 @@ -569,11 +569,17 @@ pp.setCompositionMode(QPainter::CompositionMode_Clear); pp.eraseRect(r); d = pm; - } + } else + p->end(); + QPainter::setRedirected(widget, d, buffered ? QPoint(0,0) : -thePoint); + QPaintEvent e( r ); QApplication::sendEvent(widget, &e); QPainter::restoreRedirected(widget); + + if (!p->isActive()) + p->begin(p->device()); p->setWorldMatrix( m ); if (buffered) {
Reopening. This still happens with today's SVN version.
Cannot reproduce on konqueror 4 (trunk r797319) (qt4.4 rc1)
> Cannot reproduce on konqueror 4 (trunk r797319) (qt4.4 rc1) Right, seems to be fixed in the meantime.