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. Fixes: QTBUG-119113 Change-Id: Id052a03be13adce05bbd025d86270d265dfb662e Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> (cherry picked from commit b9ee6d3b2e465eb70ba43ea62d2ada5327a138c8) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
eb9252526e
commit
c6219ebfb5
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include "qwindowcontainer_p.h"
|
#include "qwindowcontainer_p.h"
|
||||||
#include "qwidget_p.h"
|
#include "qwidget_p.h"
|
||||||
|
#include "qwidgetwindow_p.h"
|
||||||
#include <QtGui/qwindow.h>
|
#include <QtGui/qwindow.h>
|
||||||
#include <QtGui/private/qguiapplication_p.h>
|
#include <QtGui/private/qguiapplication_p.h>
|
||||||
#include <qpa/qplatformintegration.h>
|
#include <qpa/qplatformintegration.h>
|
||||||
@ -164,11 +165,31 @@ public:
|
|||||||
application can greatly hurt the overall performance of the
|
application can greatly hurt the overall performance of the
|
||||||
application.
|
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
|
\endlist
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QWidget *QWidget::createWindowContainer(QWindow *window, QWidget *parent, Qt::WindowFlags flags)
|
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);
|
return new QWindowContainer(window, parent, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ private slots:
|
|||||||
void testDockWidget();
|
void testDockWidget();
|
||||||
void testNativeContainerParent();
|
void testNativeContainerParent();
|
||||||
void testPlatformSurfaceEvent();
|
void testPlatformSurfaceEvent();
|
||||||
|
void embedWidgetWindow();
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -410,6 +411,39 @@ void tst_QWindowContainer::testPlatformSurfaceEvent()
|
|||||||
QVERIFY(ok);
|
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)
|
QTEST_MAIN(tst_QWindowContainer)
|
||||||
|
|
||||||
#include "tst_qwindowcontainer.moc"
|
#include "tst_qwindowcontainer.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user