diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-06-03 02:47:41 +0200 |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-06-03 02:47:41 +0200 |
commit | 7c6afcb1cf9db23f7a8bb04c68d58b3581ebd7b5 (patch) | |
tree | fc4d5a51335f0a88e13600f10b449ca13ab814d1 | |
parent | 932b4b95cf4c7cc250b2c3f23d9b903292f84ab4 (diff) | |
parent | 6acfea19d4c00150602c152943d89bf429462c39 (diff) |
Merge branch '4.6' of scm.dev.nokia.troll.no:qt/qt-s60-public into 4.6-integration
* '4.6' of scm.dev.nokia.troll.no:qt/qt-s60-public:
Removed compiler warnings
Window visibility changes update TLW backing store reference count
Enable visibility change events on all Symbian native windows
Added reference counting to QWidgetBackingStore
Added tst_QWidget::destroyBackingStoreWhenHidden
-rw-r--r-- | src/3rdparty/phonon/mmf/abstractaudioeffect.cpp | 2 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/abstractaudioeffect.h | 4 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/audiooutput.cpp | 3 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/bassboost.cpp | 1 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/effectfactory.cpp | 5 | ||||
-rw-r--r-- | src/3rdparty/phonon/mmf/loudness.cpp | 1 | ||||
-rw-r--r-- | src/gui/embedded/qwsmanager_qws.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_s60.cpp | 24 | ||||
-rw-r--r-- | src/gui/kernel/qapplication_x11.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qwidget.cpp | 57 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_p.h | 44 | ||||
-rw-r--r-- | src/gui/kernel/qwidget_s60.cpp | 5 | ||||
-rw-r--r-- | src/gui/painting/qbackingstore.cpp | 4 | ||||
-rw-r--r-- | tests/auto/qwidget/tst_qwidget.cpp | 258 |
14 files changed, 377 insertions, 35 deletions
diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp index 6cfeb768ae..9b64ab3ff2 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp @@ -184,6 +184,8 @@ int AbstractAudioEffect::effectParameterChanged( const EffectParameter ¶m, const QVariant &value) { // Default implementation + Q_UNUSED(param) + Q_UNUSED(value) Q_ASSERT_X(false, Q_FUNC_INFO, "Effect has no parameters"); return 0; } diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.h b/src/3rdparty/phonon/mmf/abstractaudioeffect.h index d71993b146..70adcf644f 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.h +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.h @@ -118,6 +118,10 @@ private: // for each of the effects. Using this reduces repetition of boilerplate // in the implementations of the backend effect nodes. +#ifdef Q_CC_NOKIAX86 +# pragma warn_illtokenpasting off +#endif + #define PHONON_MMF_DEFINE_EFFECT_FUNCTIONS(Effect) \ \ void Effect##::createEffect(AudioPlayer::NativePlayer *player) \ diff --git a/src/3rdparty/phonon/mmf/audiooutput.cpp b/src/3rdparty/phonon/mmf/audiooutput.cpp index c6be20b3de..358868379b 100644 --- a/src/3rdparty/phonon/mmf/audiooutput.cpp +++ b/src/3rdparty/phonon/mmf/audiooutput.cpp @@ -78,6 +78,9 @@ bool MMF::AudioOutput::setOutputDevice(int index) { Q_ASSERT_X(index == AudioOutputDeviceID, Q_FUNC_INFO, "We only support one output device, with id 0"); +#ifdef QT_NO_DEBUG + Q_UNUSED(index) +#endif return true; } diff --git a/src/3rdparty/phonon/mmf/bassboost.cpp b/src/3rdparty/phonon/mmf/bassboost.cpp index c7af93924b..67076f62d0 100644 --- a/src/3rdparty/phonon/mmf/bassboost.cpp +++ b/src/3rdparty/phonon/mmf/bassboost.cpp @@ -49,6 +49,7 @@ const char* BassBoost::description() bool BassBoost::getParameters(CMdaAudioOutputStream *stream, QList<EffectParameter> ¶meters) { + Q_UNUSED(parameters) QScopedPointer<CBassBoost> effect; TRAPD(err, effect.reset(CBassBoost::NewL(*stream))); return (KErrNone == err); diff --git a/src/3rdparty/phonon/mmf/effectfactory.cpp b/src/3rdparty/phonon/mmf/effectfactory.cpp index c5e33d5c7a..4643978d2f 100644 --- a/src/3rdparty/phonon/mmf/effectfactory.cpp +++ b/src/3rdparty/phonon/mmf/effectfactory.cpp @@ -183,8 +183,9 @@ EffectFactory::EffectData EffectFactory::getData() /* defaultValue */ QVariant(bool(true))); data.m_parameters.append(param); - if (data.m_supported = BackendNode::getParameters - (stream.data(), data.m_parameters)) { + data.m_supported = BackendNode::getParameters(stream.data(), + data.m_parameters); + if (data.m_supported) { const QString description = QCoreApplication::translate ("Phonon::MMF::EffectFactory", BackendNode::description()); data.m_descriptions.insert("name", description); diff --git a/src/3rdparty/phonon/mmf/loudness.cpp b/src/3rdparty/phonon/mmf/loudness.cpp index 1079a35653..ca05ab0989 100644 --- a/src/3rdparty/phonon/mmf/loudness.cpp +++ b/src/3rdparty/phonon/mmf/loudness.cpp @@ -49,6 +49,7 @@ const char* Loudness::description() bool Loudness::getParameters(CMdaAudioOutputStream *stream, QList<EffectParameter> ¶meters) { + Q_UNUSED(parameters) QScopedPointer<CLoudness> effect; TRAPD(err, effect.reset(CLoudness::NewL(*stream))); return (KErrNone == err); diff --git a/src/gui/embedded/qwsmanager_qws.cpp b/src/gui/embedded/qwsmanager_qws.cpp index d6ef14858b..ac6d36eb25 100644 --- a/src/gui/embedded/qwsmanager_qws.cpp +++ b/src/gui/embedded/qwsmanager_qws.cpp @@ -392,7 +392,7 @@ void QWSManagerPrivate::dirtyRegion(int decorationRegion, const QRegion &clip) { QTLWExtra *topextra = managed->d_func()->extra->topextra; - QWidgetBackingStore *bs = topextra->backingStore; + QWidgetBackingStore *bs = topextra->backingStore.data(); const bool pendingUpdateRequest = bs->isDirty(); if (decorationRegion == QDecoration::All) { diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index b1e0f63d0f..78027b2752 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1703,19 +1703,27 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent return 1; const TWsVisibilityChangedEvent *visChangedEvent = event->VisibilityChanged(); QWidget *w = QWidgetPrivate::mapper->value(control); - if (!w->d_func()->maybeTopData()) + QWidget *const window = w->window(); + if (!window->d_func()->maybeTopData()) break; + QRefCountedWidgetBackingStore &backingStore = window->d_func()->maybeTopData()->backingStore; if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) { - delete w->d_func()->topData()->backingStore; - w->d_func()->topData()->backingStore = 0; + // Decrement backing store reference count + backingStore.deref(); // In order to ensure that any resources used by the window surface // are immediately freed, we flush the WSERV command buffer. S60->wsSession().Flush(); - } else if ((visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible) - && !w->d_func()->maybeBackingStore()) { - w->d_func()->topData()->backingStore = new QWidgetBackingStore(w); - w->d_func()->invalidateBuffer(w->rect()); - w->repaint(); + } else if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible) { + if (backingStore.data()) { + // Increment backing store reference count + backingStore.ref(); + } else { + // Create backing store with an initial reference count of 1 + backingStore.create(window); + backingStore.ref(); + w->d_func()->invalidateBuffer(w->rect()); + w->repaint(); + } } return 1; } diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 25a7750d96..304cd173e9 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -5245,7 +5245,7 @@ bool QETWidget::translateConfigEvent(const XEvent *event) if (isVisible() && data->crect.size() != oldSize) { Q_ASSERT(d->extra->topextra); - QWidgetBackingStore *bs = d->extra->topextra->backingStore; + QWidgetBackingStore *bs = d->extra->topextra->backingStore.data(); const bool hasStaticContents = bs && bs->hasStaticContents(); // If we have a backing store with static contents, we have to disable the top-level // resize optimization in order to get invalidated regions for resized widgets. diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index e180001291..a9ea9ac563 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -161,6 +161,51 @@ static inline bool hasBackingStoreSupport() extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp + +QRefCountedWidgetBackingStore::QRefCountedWidgetBackingStore() + : m_ptr(0) + , m_count(0) +{ + +} + +QRefCountedWidgetBackingStore::~QRefCountedWidgetBackingStore() +{ + delete m_ptr; +} + +void QRefCountedWidgetBackingStore::create(QWidget *widget) +{ + destroy(); + m_ptr = new QWidgetBackingStore(widget); + m_count = 0; +} + +void QRefCountedWidgetBackingStore::destroy() +{ + delete m_ptr; + m_ptr = 0; + m_count = 0; +} + +void QRefCountedWidgetBackingStore::ref() +{ + Q_ASSERT(m_ptr); + ++m_count; +} + +void QRefCountedWidgetBackingStore::deref() +{ + if (m_count) { + Q_ASSERT(m_ptr); + if (0 == --m_count) { + delete m_ptr; + m_ptr = 0; + } + } +} + + QWidgetPrivate::QWidgetPrivate(int version) : QObjectPrivate(version) , extra(0) @@ -1324,11 +1369,9 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) // a real toplevel window needs a backing store if (isWindow() && windowType() != Qt::Desktop) { - delete d->topData()->backingStore; - // QWidgetBackingStore will check this variable, hence it must be 0 - d->topData()->backingStore = 0; + d->topData()->backingStore.destroy(); if (hasBackingStoreSupport()) - d->topData()->backingStore = new QWidgetBackingStore(this); + d->topData()->backingStore.create(this); } d->setModal_sys(); @@ -1451,8 +1494,7 @@ QWidget::~QWidget() // the backing store will delete its window surface, which may or may // not have a reference to this widget that will be used later to // notify the window it no longer has a surface. - delete d->extra->topextra->backingStore; - d->extra->topextra->backingStore = 0; + d->extra->topextra->backingStore.destroy(); } #endif if (QWidgetBackingStore *bs = d->maybeBackingStore()) { @@ -1540,7 +1582,6 @@ void QWidgetPrivate::createTLExtra() QTLWExtra* x = extra->topextra = new QTLWExtra; x->icon = 0; x->iconPixmap = 0; - x->backingStore = 0; x->windowSurface = 0; x->sharedPainter = 0; x->incw = x->inch = 0; @@ -1619,7 +1660,7 @@ void QWidgetPrivate::deleteExtra() #endif if (extra->topextra) { deleteTLSysExtra(); - delete extra->topextra->backingStore; + extra->topextra->backingStore.destroy(); delete extra->topextra->icon; delete extra->topextra->iconPixmap; #if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER) diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 555647c1df..9f7ad95aac 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -110,13 +110,53 @@ class QWidgetItemV2; class QStyle; +class Q_AUTOTEST_EXPORT QRefCountedWidgetBackingStore +{ +public: + QRefCountedWidgetBackingStore(); + ~QRefCountedWidgetBackingStore(); + + void create(QWidget *tlw); + void destroy(); + + void ref(); + void deref(); + + inline QWidgetBackingStore* data() + { + return m_ptr; + } + + inline QWidgetBackingStore* operator->() + { + return m_ptr; + } + + inline QWidgetBackingStore& operator*() + { + return *m_ptr; + } + + inline operator bool() const + { + return (0 != m_ptr); + } + +private: + Q_DISABLE_COPY(QRefCountedWidgetBackingStore) + +private: + QWidgetBackingStore* m_ptr; + int m_count; +}; + struct QTLWExtra { // *************************** Cross-platform variables ***************************** // Regular pointers (keep them together to avoid gaps on 64 bits architectures). QIcon *icon; // widget icon QPixmap *iconPixmap; - QWidgetBackingStore *backingStore; + QRefCountedWidgetBackingStore backingStore; QWindowSurface *windowSurface; QPainter *sharedPainter; @@ -907,7 +947,7 @@ inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const { Q_Q(const QWidget); QTLWExtra *x = q->window()->d_func()->maybeTopData(); - return x ? x->backingStore : 0; + return x ? x->backingStore.data() : 0; } QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 438c2a303a..86b858dabd 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -433,6 +433,7 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de // Request mouse move events. drawableWindow->PointerFilter(EPointerFilterEnterExit | EPointerFilterMove | EPointerFilterDrag, 0); + drawableWindow->EnableVisibilityChangeEvents(); if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) { activateSymbianWindow(control.data()); @@ -908,14 +909,12 @@ void QWidgetPrivate::registerDropSite(bool /* on */) void QWidgetPrivate::createTLSysExtra() { - extra->topextra->backingStore = 0; extra->topextra->inExpose = 0; } void QWidgetPrivate::deleteTLSysExtra() { - delete extra->topextra->backingStore; - extra->topextra->backingStore = 0; + extra->topextra->backingStore.destroy(); } void QWidgetPrivate::createSysExtra() diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index 8de9eaa5c8..3ddffef7c2 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -914,7 +914,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) invalidateBuffer((newRect & clipR).translated(-data.crect.topLeft())); } else { - QWidgetBackingStore *wbs = x->backingStore; + QWidgetBackingStore *wbs = x->backingStore.data(); QRegion childExpose(newRect & clipR); if (sourceRect.isValid() && wbs->bltRect(sourceRect, dx, dy, pw)) @@ -957,7 +957,7 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) if (x->inTopLevelResize) return; - QWidgetBackingStore *wbs = x->backingStore; + QWidgetBackingStore *wbs = x->backingStore.data(); if (!wbs) return; diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 76e20b997e..7d4f8ffa1a 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -385,6 +385,7 @@ private slots: void setGraphicsEffect(); void destroyBackingStore(); + void destroyBackingStoreWhenHidden(); void activateWindow(); @@ -9499,9 +9500,7 @@ void tst_QWidget::destroyBackingStore() QTRY_VERIFY(w.numPaintEvents > 0); w.reset(); w.update(); - delete qt_widget_private(&w)->topData()->backingStore; - qt_widget_private(&w)->topData()->backingStore = 0; - qt_widget_private(&w)->topData()->backingStore = new QWidgetBackingStore(&w); + qt_widget_private(&w)->topData()->backingStore.create(&w); w.update(); QApplication::processEvents(); @@ -9517,6 +9516,252 @@ void tst_QWidget::destroyBackingStore() #endif } +// Helper function +QWidgetBackingStore* backingStore(QWidget &widget) +{ + QWidgetBackingStore *backingStore = 0; +#ifdef QT_BUILD_INTERNAL + if (QTLWExtra *topExtra = qt_widget_private(&widget)->maybeTopData()) + backingStore = topExtra->backingStore.data(); +#endif + return backingStore; +} + +// Wait for a condition to be true, timing out after 1 second +// This is used following calls to QWidget::show() and QWidget::hide(), which are +// expected to asynchronously trigger native window visibility events. +#define WAIT_AND_VERIFY(condition) \ + do { \ + QTime start = QTime::currentTime(); \ + while (!(condition) && (start.elapsed() < 1000)) { \ + qApp->processEvents(); \ + QTest::qWait(50); \ + } \ + if (!QTest::qVerify((condition), #condition, "", __FILE__, __LINE__)) \ + return; \ + } while (0) + +void tst_QWidget::destroyBackingStoreWhenHidden() +{ +#ifndef QT_BUILD_INTERNAL + QSKIP("Test step requires access to Q_AUTOTEST_EXPORT", SkipAll); +#endif + +#ifndef Q_OS_SYMBIAN + QSKIP("Only Symbian destroys backing store when native window becomes invisible", SkipAll); +#endif + + testWidget->hide(); + QTest::qWait(1000); + + // 1. Single top-level QWidget + { + QWidget w; + w.setAutoFillBackground(true); + w.setPalette(Qt::yellow); + w.setGeometry(0, 0, 100, 100); + w.show(); + QTest::qWaitForWindowShown(&w); + QVERIFY(0 != backingStore(w)); + + w.hide(); + WAIT_AND_VERIFY(0 == backingStore(w)); + + w.show(); + QTest::qWaitForWindowShown(&w); + QVERIFY(0 != backingStore(w)); + } + + // 2. Two top-level widgets + { + QWidget w1; + w1.setGeometry(0, 0, 100, 100); + w1.setAutoFillBackground(true); + w1.setPalette(Qt::red); + w1.show(); + QTest::qWaitForWindowShown(&w1); + QVERIFY(0 != backingStore(w1)); + + QWidget w2; + w2.setGeometry(w1.geometry()); + w1.setAutoFillBackground(true); + w1.setPalette(Qt::blue); + w2.show(); + QTest::qWaitForWindowShown(&w2); + QVERIFY(0 != backingStore(w2)); + + // Check that w1 deleted its backing store when obscured by w2 + QVERIFY(0 == backingStore(w1)); + + w2.move(w2.pos() + QPoint(10, 10)); + + // Check that w1 recreates its backing store when partially revealed + WAIT_AND_VERIFY(0 != backingStore(w1)); + } + + // 3. Native child widget + { + QWidget parent; + parent.setGeometry(0, 0, 100, 100); + parent.setAutoFillBackground(true); + parent.setPalette(Qt::yellow); + + QWidget child(&parent); + child.setAutoFillBackground(true); + child.setPalette(Qt::green); + + QVBoxLayout layout(&parent); + layout.setContentsMargins(10, 10, 10, 10); + layout.addWidget(&child); + parent.setLayout(&layout); + + child.winId(); + + parent.show(); + QTest::qWaitForWindowShown(&parent); + + // Check that child window does not obscure parent window + QVERIFY(!parent.visibleRegion().subtracted(child.visibleRegion()).isEmpty()); + + // Native child widget should share parent's backing store + QWidgetBackingStore *const parentBs = backingStore(parent); + QVERIFY(0 != parentBs); + QVERIFY(0 == backingStore(child)); + + // Set margins to zero so that child widget totally obscures parent + layout.setContentsMargins(0, 0, 0, 0); + + WAIT_AND_VERIFY(parent.visibleRegion().subtracted(child.visibleRegion()).isEmpty()); + + // Backing store should remain unchanged despite child window obscuring + // parent window + QVERIFY(parentBs == backingStore(parent)); + QVERIFY(0 == backingStore(child)); + } + + // 4. Alien child widget which is made full-screen + { + QWidget parent; + parent.setGeometry(0, 0, 100, 100); + parent.setAutoFillBackground(true); + parent.setPalette(Qt::red); + + QWidget child(&parent); + child.setAutoFillBackground(true); + child.setPalette(Qt::blue); + + QVBoxLayout layout(&parent); + layout.setContentsMargins(10, 10, 10, 10); + layout.addWidget(&child); + parent.setLayout(&layout); + + parent.show(); + QTest::qWaitForWindowShown(&parent); + + // Check that child window does not obscure parent window + QVERIFY(!parent.visibleRegion().subtracted(child.visibleRegion()).isEmpty()); + + // Native child widget should share parent's backing store + QVERIFY(0 != backingStore(parent)); + QVERIFY(0 == backingStore(child)); + + // Make child widget full screen + child.setWindowFlags((child.windowFlags() | Qt::Window) ^ Qt::SubWindow); + child.setWindowState(child.windowState() | Qt::WindowFullScreen); + child.show(); + QTest::qWaitForWindowShown(&child); + + // Check that child window obscures parent window + QVERIFY(parent.visibleRegion().subtracted(child.visibleRegion()).isEmpty()); + + // Now that extent of child widget goes beyond parent's extent, + // a new backing store should be created for the child widget. + QVERIFY(0 != backingStore(child)); + + // Parent is obscured, therefore its backing store should be destroyed + QVERIFY(0 == backingStore(parent)); + + // Disable full screen + child.setWindowFlags(child.windowFlags() ^ (Qt::Window | Qt::SubWindow)); + child.setWindowState(child.windowState() ^ Qt::WindowFullScreen); + child.show(); + QTest::qWaitForWindowShown(&child); + + // Check that parent is now visible again + QVERIFY(!parent.visibleRegion().subtracted(child.visibleRegion()).isEmpty()); + + // Native child widget should once again share parent's backing store + QVERIFY(0 != backingStore(parent)); + QEXPECT_FAIL("", "QTBUG-10643", Continue); + QVERIFY(0 == backingStore(child)); + } + + // 5. Native child widget which is made full-screen + { + QWidget parent; + parent.setGeometry(0, 0, 100, 100); + parent.setAutoFillBackground(true); + parent.setPalette(Qt::red); + + QWidget child(&parent); + child.setAutoFillBackground(true); + child.setPalette(Qt::blue); + + QVBoxLayout layout(&parent); + layout.setContentsMargins(10, 10, 10, 10); + layout.addWidget(&child); + parent.setLayout(&layout); + + child.winId(); + + parent.show(); + QTest::qWaitForWindowShown(&parent); + + // Check that child window does not obscure parent window + QVERIFY(!parent.visibleRegion().subtracted(child.visibleRegion()).isEmpty()); + + // Native child widget should share parent's backing store + QVERIFY(0 != backingStore(parent)); + QVERIFY(0 == backingStore(child)); + + // Make child widget full screen + child.setWindowFlags((child.windowFlags() | Qt::Window) ^ Qt::SubWindow); + child.setWindowState(child.windowState() | Qt::WindowFullScreen); + child.show(); + QTest::qWaitForWindowShown(&child); + + // Ensure that 'window hidden' event is received by parent + qApp->processEvents(); + + // Check that child window obscures parent window + QVERIFY(parent.visibleRegion().subtracted(child.visibleRegion()).isEmpty()); + + // Now that extent of child widget goes beyond parent's extent, + // a new backing store should be created for the child widget. + QVERIFY(0 != backingStore(child)); + + // Parent is obscured, therefore its backing store should be destroyed + QEXPECT_FAIL("", "QTBUG-10643", Continue); + QVERIFY(0 == backingStore(parent)); + + // Disable full screen + child.setWindowFlags(child.windowFlags() ^ (Qt::Window | Qt::SubWindow)); + child.setWindowState(child.windowState() ^ Qt::WindowFullScreen); + child.show(); + QTest::qWaitForWindowShown(&child); + + // Check that parent is now visible again + QVERIFY(!parent.visibleRegion().subtracted(child.visibleRegion()).isEmpty()); + + // Native child widget should once again share parent's backing store + QVERIFY(0 != backingStore(parent)); + QEXPECT_FAIL("", "QTBUG-10643", Continue); + QVERIFY(0 == backingStore(child)); + } +} + +#undef WAIT_AND_VERIFY + void tst_QWidget::rectOutsideCoordinatesLimit_task144779() { #ifdef Q_OS_WINCE_WM @@ -9997,15 +10242,12 @@ class scrollWidgetWBS : public QWidget public: void deleteBackingStore() { - if (static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) { - delete static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStore; - static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStore = 0; - } + static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStore.destroy(); } void enableBackingStore() { if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) { - static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStore = new QWidgetBackingStore(this); + static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStore.create(this); static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect()); repaint(); } |