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
Fixes: QTBUG-80859
Change-Id: I769e58ead3c2efcf8c451c363108848feade9388
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
(cherry picked from commit 009abcd7b66738bece6cf354776dfb2ef401636b)
Reviewed-by: Liang Qi <liang.qi@qt.io>
This commit is contained in:
Tor Arne Vestbø 2019-11-08 11:03:14 +01:00 committed by Liang Qi
parent 9d43d55b21
commit e2f35fa684
2 changed files with 71 additions and 0 deletions

View File

@ -8934,6 +8934,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<QPlatformSurfaceEvent*>(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;

View File

@ -57,6 +57,7 @@
#include <QtGui/qpaintengine.h>
#include <QtGui/qbackingstore.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qpa/qplatformwindow.h>
#include <QtGui/qscreen.h>
#include <qmenubar.h>
#include <qcompleter.h>
@ -221,6 +222,7 @@ private slots:
void setFixedSize();
void ensureCreated();
void createAndDestroy();
void winIdChangeEvent();
void persistentWinId();
void showNativeChild();
@ -4134,6 +4136,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()
{
{