Details
-
Bug
-
Resolution: Fixed
-
P2: Important
-
5.3.0, 5.3.1, 5.3.2, 5.4.0, 5.4.1, 5.4.2, 5.5.0, 5.5.1, 5.6.0
-
None
-
Windows, msvc2012, msvc2013
Description
The attached example application demonstrates use case. The attached screenshots demonstrate difference between 5.2.1 and 5.4.0.
Run app. Click on button 2 or 3 or 5 or 6. Even without clicking QTabWidget rendered incorrectly.
If sibling widgets have assigned QGraphicsDropShadowEffect they're not drawn starting from Qt 5.3.0 release. After little investigation I found outthere is regression introduced in commit https://qt.gitorious.org/qt/qtbase/commit/071098b08b12fc1af6341ff6d7ba6713e5de1481
To generate a pixmap QGraphicsDropShadowEffect use QWidgetEffectSourcePrivate::pixmap(). This method calls m_widget->render(&pixmap, pixmapOffset, QRegion(), QWidget::DrawChildren).
In 5.2.1 this method called QWidgetPrivate::render() which do not set any sharedPainter.
But in Qt version >= 5.3.0 that method calls another version of QWidget::render() which sets a sharedPainter.
As you can see in QWidgetPrivate::drawWidget there is checking for valid sharedPainter and now there is such sharedPainter so there is drawing of siblings with offset.
void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags, QPainter *sharedPainter, QWidgetBackingStore *backingStore) { if (rgn.isEmpty()) return; const bool asRoot = flags & DrawAsRoot; bool onScreen = paintOnScreen(); Q_Q(QWidget); #ifndef QT_NO_GRAPHICSEFFECT if (graphicsEffect && graphicsEffect->isEnabled()) { QGraphicsEffectSource *source = graphicsEffect->d_func()->source; QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *> (source->d_func()); if (!sourced->context) { QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore); sourced->context = &context; if (!sharedPainter) { setSystemClip(pdev, rgn.translated(offset)); //in Qt 5.2.1 this branch always executed when QGraphicsDropShadowEffect used QPainter p(pdev); p.translate(offset); context.painter = &p; graphicsEffect->draw(&p); setSystemClip(pdev, QRegion()); } else { context.painter = sharedPainter; //in Qt >= 5.3.0 this branch executed if (sharedPainter->worldTransform() != sourced->lastEffectTransform) { sourced->invalidateCache(); sourced->lastEffectTransform = sharedPainter->worldTransform(); } sharedPainter->save(); sharedPainter->translate(offset); // <-------- here may be a problem graphicsEffect->draw(sharedPainter); sharedPainter->restore(); } sourced->context = 0;