summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/image/qpixmap.cpp7
-rw-r--r--src/gui/kernel/qwidget.cpp176
-rw-r--r--src/gui/kernel/qwidget_p.h2
-rw-r--r--tests/auto/qpixmap/tst_qpixmap.cpp27
4 files changed, 122 insertions, 90 deletions
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 985a20b..b085c09 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1076,6 +1076,9 @@ QPixmap QPixmap::grabWidget(QWidget * widget, const QRect &rect)
if (widget->testAttribute(Qt::WA_PendingResizeEvent) || !widget->testAttribute(Qt::WA_WState_Created))
sendResizeEvents(widget);
+ widget->d_func()->prepareToRender(QRegion(),
+ QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
+
QRect r(rect);
if (r.width() < 0)
r.setWidth(widget->width() - rect.x());
@@ -1086,8 +1089,8 @@ QPixmap QPixmap::grabWidget(QWidget * widget, const QRect &rect)
return QPixmap();
QPixmap res(r.size());
- widget->render(&res, QPoint(), r,
- QWidget::DrawWindowBackground | QWidget::DrawChildren | QWidget::IgnoreMask);
+ widget->d_func()->render(&res, QPoint(), r, QWidget::DrawWindowBackground
+ | QWidget::DrawChildren | QWidget::IgnoreMask, true);
return res;
}
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index c776c36..f1b90f0 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -4838,90 +4838,7 @@ void QWidget::unsetCursor()
void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
const QRegion &sourceRegion, RenderFlags renderFlags)
{
- Q_D(QWidget);
- if (!target) {
- qWarning("QWidget::render: null pointer to paint device");
- return;
- }
-
- const bool inRenderWithPainter = d->extra && d->extra->inRenderWithPainter;
- QRegion paintRegion = !inRenderWithPainter ? d->prepareToRender(sourceRegion, renderFlags)
- : sourceRegion;
- if (paintRegion.isEmpty())
- return;
-
-#ifndef Q_WS_MAC
- QPainter *oldSharedPainter = inRenderWithPainter ? d->sharedPainter() : 0;
-
- // Use the target's shared painter if set (typically set when doing
- // "other->render(widget);" in the widget's paintEvent.
- if (target->devType() == QInternal::Widget) {
- QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
- if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
- QPainter *targetPainter = targetPrivate->sharedPainter();
- if (targetPainter && targetPainter->isActive())
- d->setSharedPainter(targetPainter);
- }
- }
-#endif
-
- // Use the target's redirected device if set and adjust offset and paint
- // region accordingly. This is typically the case when people call render
- // from the paintEvent.
- QPoint offset = targetOffset;
- offset -= paintRegion.boundingRect().topLeft();
- QPoint redirectionOffset;
- QPaintDevice *redirected = 0;
-
- if (target->devType() == QInternal::Widget)
- redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
- if (!redirected)
- redirected = QPainter::redirected(target, &redirectionOffset);
-
- if (redirected) {
- target = redirected;
- offset -= redirectionOffset;
- }
-
- if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
- if (QPaintEngine *targetEngine = target->paintEngine()) {
- const QRegion targetSystemClip = targetEngine->systemClip();
- if (!targetSystemClip.isEmpty())
- paintRegion &= targetSystemClip.translated(-offset);
- }
- }
-
- // Set backingstore flags.
- int flags = QWidgetPrivate::DrawPaintOnScreen | QWidgetPrivate::DrawInvisible;
- if (renderFlags & DrawWindowBackground)
- flags |= QWidgetPrivate::DrawAsRoot;
-
- if (renderFlags & DrawChildren)
- flags |= QWidgetPrivate::DrawRecursive;
- else
- flags |= QWidgetPrivate::DontSubtractOpaqueChildren;
-
-#ifdef Q_WS_QWS
- flags |= QWidgetPrivate::DontSetCompositionMode;
-#endif
-
- if (target->devType() == QInternal::Printer) {
- QPainter p(target);
- d->render_helper(&p, targetOffset, paintRegion, renderFlags);
- return;
- }
-
-#ifndef Q_WS_MAC
- // Render via backingstore.
- d->drawWidget(target, paintRegion, offset, flags, d->sharedPainter());
-
- // Restore shared painter.
- if (oldSharedPainter)
- d->setSharedPainter(oldSharedPainter);
-#else
- // Render via backingstore (no shared painter).
- d->drawWidget(target, paintRegion, offset, flags, 0);
-#endif
+ d_func()->render(target, targetOffset, sourceRegion, renderFlags, false);
}
/*!
@@ -5371,6 +5288,97 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
}
+void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,
+ const QRegion &sourceRegion, QWidget::RenderFlags renderFlags,
+ bool readyToRender)
+{
+ Q_Q(QWidget);
+ if (!target) {
+ qWarning("QWidget::render: null pointer to paint device");
+ return;
+ }
+
+ const bool inRenderWithPainter = extra && extra->inRenderWithPainter;
+ QRegion paintRegion = !inRenderWithPainter && !readyToRender
+ ? prepareToRender(sourceRegion, renderFlags)
+ : sourceRegion;
+ if (paintRegion.isEmpty())
+ return;
+
+#ifndef Q_WS_MAC
+ QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : 0;
+
+ // Use the target's shared painter if set (typically set when doing
+ // "other->render(widget);" in the widget's paintEvent.
+ if (target->devType() == QInternal::Widget) {
+ QWidgetPrivate *targetPrivate = static_cast<QWidget *>(target)->d_func();
+ if (targetPrivate->extra && targetPrivate->extra->inRenderWithPainter) {
+ QPainter *targetPainter = targetPrivate->sharedPainter();
+ if (targetPainter && targetPainter->isActive())
+ setSharedPainter(targetPainter);
+ }
+ }
+#endif
+
+ // Use the target's redirected device if set and adjust offset and paint
+ // region accordingly. This is typically the case when people call render
+ // from the paintEvent.
+ QPoint offset = targetOffset;
+ offset -= paintRegion.boundingRect().topLeft();
+ QPoint redirectionOffset;
+ QPaintDevice *redirected = 0;
+
+ if (target->devType() == QInternal::Widget)
+ redirected = static_cast<QWidget *>(target)->d_func()->redirected(&redirectionOffset);
+ if (!redirected)
+ redirected = QPainter::redirected(target, &redirectionOffset);
+
+ if (redirected) {
+ target = redirected;
+ offset -= redirectionOffset;
+ }
+
+ if (!inRenderWithPainter) { // Clip handled by shared painter (in qpainter.cpp).
+ if (QPaintEngine *targetEngine = target->paintEngine()) {
+ const QRegion targetSystemClip = targetEngine->systemClip();
+ if (!targetSystemClip.isEmpty())
+ paintRegion &= targetSystemClip.translated(-offset);
+ }
+ }
+
+ // Set backingstore flags.
+ int flags = DrawPaintOnScreen | DrawInvisible;
+ if (renderFlags & QWidget::DrawWindowBackground)
+ flags |= DrawAsRoot;
+
+ if (renderFlags & QWidget::DrawChildren)
+ flags |= DrawRecursive;
+ else
+ flags |= DontSubtractOpaqueChildren;
+
+#ifdef Q_WS_QWS
+ flags |= DontSetCompositionMode;
+#endif
+
+ if (target->devType() == QInternal::Printer) {
+ QPainter p(target);
+ render_helper(&p, targetOffset, paintRegion, renderFlags);
+ return;
+ }
+
+#ifndef Q_WS_MAC
+ // Render via backingstore.
+ drawWidget(target, paintRegion, offset, flags, sharedPainter());
+
+ // Restore shared painter.
+ if (oldSharedPainter)
+ setSharedPainter(oldSharedPainter);
+#else
+ // Render via backingstore (no shared painter).
+ drawWidget(target, paintRegion, offset, flags, 0);
+#endif
+}
+
void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn,
const QPoint &offset, int flags
#ifdef Q_BACKINGSTORE_SUBSURFACES
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index df28bac..220dc7c 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -353,6 +353,8 @@ public:
QRegion prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags);
void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion,
QWidget::RenderFlags renderFlags);
+ void render(QPaintDevice *target, const QPoint &targetOffset, const QRegion &sourceRegion,
+ QWidget::RenderFlags renderFlags, bool readyToRender);
void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags,
QPainter *sharedPainter = 0, QWidgetBackingStore *backingStore = 0);
diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp
index d7f042e..fcb59f9 100644
--- a/tests/auto/qpixmap/tst_qpixmap.cpp
+++ b/tests/auto/qpixmap/tst_qpixmap.cpp
@@ -47,6 +47,7 @@
#include <qmatrix.h>
#include <qdesktopwidget.h>
#include <qpaintengine.h>
+#include <qtreewidget.h>
#include <private/qpixmapdata_p.h>
@@ -791,14 +792,32 @@ void tst_QPixmap::drawBitmap()
void tst_QPixmap::grabWidget()
{
QWidget widget;
- widget.setPalette(Qt::green);
- widget.resize(128, 128);
+ QImage image(128, 128, QImage::Format_ARGB32_Premultiplied);
+ for (int row = 0; row < image.height(); ++row) {
+ QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(row));
+ for (int col = 0; col < image.width(); ++col)
+ line[col] = qRgb(rand() & 255, row, col);
+ }
- QPixmap expected(64, 64);
- expected.fill(Qt::green);
+ QPalette pal = widget.palette();
+ pal.setBrush(QPalette::Window, QBrush(image));
+ widget.setPalette(pal);
+ widget.resize(128, 128);
+ QPixmap expected = QPixmap::fromImage(QImage(image.scanLine(64) + 64 * 4, 64, 64, image.bytesPerLine(), image.format()));
QPixmap actual = QPixmap::grabWidget(&widget, QRect(64, 64, 64, 64));
QVERIFY(lenientCompare(actual, expected));
+
+ actual = QPixmap::grabWidget(&widget, 64, 64);
+ QVERIFY(lenientCompare(actual, expected));
+
+ // Make sure a widget that is not yet shown is grabbed correctly.
+ QTreeWidget widget2;
+ actual = QPixmap::grabWidget(&widget2);
+ widget2.show();
+ expected = QPixmap::grabWidget(&widget2);
+
+ QVERIFY(lenientCompare(actual, expected));
}
void tst_QPixmap::grabWindow()