summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAxel Spoerl <axel.spoerl@qt.io>2023-12-19 11:20:41 +0100
committerAxel Spoerl <axel.spoerl@qt.io>2023-12-21 18:49:29 +0000
commitb9ee6d3b2e465eb70ba43ea62d2ada5327a138c8 (patch)
tree2c7e8db4b5bfcac6a68e0ea94dda03bf65ed63d7
parent29a4323974a1877faf389637be40688e3bc1790d (diff)
QWindowContainer: Don't embed a QWidget
Embedding a QWidget in a window container (via its windowHandle()) may cause crashes, e.g. during drag & drop and when the application goes out of scope. If a QWidget->windowHandle() is attempted to be embedded in a window container, return the pointer to the widget instead of creating a container. Add an autotest. Update documentation. [ChangeLog][QtWidgets][QWindowContainer] If createWindowContainer() is called with a QWidgetWindow argument, return pointer to the widget instead of new container. Pick-to: 6.7 Fixes: QTBUG-119113 Change-Id: Id052a03be13adce05bbd025d86270d265dfb662e Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
-rw-r--r--src/widgets/kernel/qwindowcontainer.cpp21
-rw-r--r--tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp34
2 files changed, 55 insertions, 0 deletions
diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp
index 14286406dc..7a7de66012 100644
--- a/src/widgets/kernel/qwindowcontainer.cpp
+++ b/src/widgets/kernel/qwindowcontainer.cpp
@@ -3,6 +3,7 @@
#include "qwindowcontainer_p.h"
#include "qwidget_p.h"
+#include "qwidgetwindow_p.h"
#include <QtGui/qwindow.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
@@ -164,11 +165,31 @@ public:
application can greatly hurt the overall performance of the
application.
+ \li Since 6.7, if \a window belongs to a widget (that is, \a window
+ was received from calling \l windowHandle()), no container will be
+ created. Instead, this function will return the widget itself, after
+ being reparented to \l parent. Since no container will be created,
+ \a flags will be ignored. In other words, if \a window belongs to
+ a widget, consider just reparenting that widget to \a parent instead
+ of using this function.
+
\endlist
*/
QWidget *QWidget::createWindowContainer(QWindow *window, QWidget *parent, Qt::WindowFlags flags)
{
+ // Embedding a QWidget in a window container doesn't make sense,
+ // and has various issues in practice, so just return the widget
+ // itself.
+ if (auto *widgetWindow = qobject_cast<QWidgetWindow *>(window)) {
+ QWidget *widget = widgetWindow->widget();
+ if (flags != Qt::WindowFlags()) {
+ qWarning() << window << "refers to a widget:" << widget
+ << "WindowFlags" << flags << "will be ignored.";
+ }
+ widget->setParent(parent);
+ return widget;
+ }
return new QWindowContainer(window, parent, flags);
}
diff --git a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp
index 19c9606d79..08c2f364df 100644
--- a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp
+++ b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp
@@ -57,6 +57,7 @@ private slots:
void testDockWidget();
void testNativeContainerParent();
void testPlatformSurfaceEvent();
+ void embedWidgetWindow();
void cleanup();
private:
@@ -410,6 +411,39 @@ void tst_QWindowContainer::testPlatformSurfaceEvent()
QVERIFY(ok);
}
+void tst_QWindowContainer::embedWidgetWindow()
+{
+ {
+ QWidget parent;
+ QWidget *widget = new QWidget;
+ widget->show();
+ QVERIFY(QTest::qWaitForWindowExposed(widget));
+ QVERIFY(widget->windowHandle());
+ QPointer<QWindow> widgetWindow = widget->windowHandle();
+ auto *container = QWidget::createWindowContainer(widgetWindow, &parent);
+ QCOMPARE(container, widget);
+ QCOMPARE(widget->parent(), &parent);
+ delete widget;
+ QTRY_VERIFY(widgetWindow.isNull());
+ }
+
+ QPointer<QWidget> widget = new QWidget;
+ QPointer<QWindow> widgetWindow;
+ {
+ QWidget parent;
+ widget->show();
+ QVERIFY(QTest::qWaitForWindowExposed(widget));
+ QVERIFY(widget->windowHandle());
+ widgetWindow = widget->windowHandle();
+ auto *container = QWidget::createWindowContainer(widgetWindow, &parent);
+ QCOMPARE(container, widget);
+ QCOMPARE(widget->parent(), &parent);
+ }
+ QTRY_VERIFY(widget.isNull());
+ QTRY_VERIFY(widgetWindow.isNull());
+
+}
+
QTEST_MAIN(tst_QWindowContainer)
#include "tst_qwindowcontainer.moc"