From 009abcd7b66738bece6cf354776dfb2ef401636b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 8 Nov 2019 11:03:14 +0100 Subject: [PATCH] QWidget: React to platform surface being created or destroyed The platform window may create or destroy its surface from other entry points than the QWidget API, in which case QWidget needs to sync up its own state to match. In particular WA_WState_Created and the winId needs to be recomputed. Fixes: QTBUG-69289 Fixes: QTBUG-77350 Change-Id: I769e58ead3c2efcf8c451c363108848feade9388 Reviewed-by: Volker Hilsheimer Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qwidget.cpp | 17 ++++++ .../widgets/kernel/qwidget/tst_qwidget.cpp | 54 +++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 5a0ea58cf8..dcc694efe4 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -8624,6 +8624,23 @@ bool QWidget::event(QEvent *event) } } switch (event->type()) { + case QEvent::PlatformSurface: { + // Sync up QWidget's view of whether or not the widget has been created + switch (static_cast(event)->surfaceEventType()) { + case QPlatformSurfaceEvent::SurfaceCreated: + if (!testAttribute(Qt::WA_WState_Created)) + create(); + break; + case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: + if (testAttribute(Qt::WA_WState_Created)) { + // Child windows have already been destroyed by QWindow, + // so we skip them here. + destroy(false, false); + } + break; + } + break; + } case QEvent::MouseMove: mouseMoveEvent((QMouseEvent*)event); break; diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 67fdd13652..371738ad27 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -227,6 +228,7 @@ private slots: void setFixedSize(); void ensureCreated(); + void createAndDestroy(); void winIdChangeEvent(); void persistentWinId(); void showNativeChild(); @@ -4220,6 +4222,58 @@ public: int winIdChangeEventCount() const { return m_winIdList.count(); } }; +class CreateDestroyWidget : public WinIdChangeWidget +{ +public: + void create() { QWidget::create(); } + void destroy() { QWidget::destroy(); } +}; + +void tst_QWidget::createAndDestroy() +{ + CreateDestroyWidget widget; + + // Create and destroy via QWidget + widget.create(); + QVERIFY(widget.testAttribute(Qt::WA_WState_Created)); + QCOMPARE(widget.winIdChangeEventCount(), 1); + QVERIFY(widget.internalWinId()); + + widget.destroy(); + QVERIFY(!widget.testAttribute(Qt::WA_WState_Created)); + QCOMPARE(widget.winIdChangeEventCount(), 2); + QVERIFY(!widget.internalWinId()); + + // Create via QWidget, destroy via QWindow + widget.create(); + QVERIFY(widget.testAttribute(Qt::WA_WState_Created)); + QCOMPARE(widget.winIdChangeEventCount(), 3); + QVERIFY(widget.internalWinId()); + + widget.windowHandle()->destroy(); + QVERIFY(!widget.testAttribute(Qt::WA_WState_Created)); + QCOMPARE(widget.winIdChangeEventCount(), 4); + QVERIFY(!widget.internalWinId()); + + // Create via QWidget again + widget.create(); + QVERIFY(widget.testAttribute(Qt::WA_WState_Created)); + QCOMPARE(widget.winIdChangeEventCount(), 5); + QVERIFY(widget.internalWinId()); + + // Destroy via QWindow, create via QWindow + widget.windowHandle()->destroy(); + QVERIFY(widget.windowHandle()); + QVERIFY(!widget.testAttribute(Qt::WA_WState_Created)); + QCOMPARE(widget.winIdChangeEventCount(), 6); + QVERIFY(!widget.internalWinId()); + + widget.windowHandle()->create(); + QVERIFY(widget.testAttribute(Qt::WA_WState_Created)); + QCOMPARE(widget.winIdChangeEventCount(), 7); + QVERIFY(widget.internalWinId()); +} + void tst_QWidget::winIdChangeEvent() { {