diff options
Diffstat (limited to 'src/widgets/kernel/qwindowcontainer.cpp')
-rw-r--r-- | src/widgets/kernel/qwindowcontainer.cpp | 72 |
1 files changed, 65 insertions, 7 deletions
diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 847058e5b2..c15ec54f35 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> @@ -14,6 +15,8 @@ #include <QAbstractScrollArea> #include <QPainter> +#include <QtCore/qpointer.h> + QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; @@ -162,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); } @@ -191,11 +214,16 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: d->fakeParent.setObjectName(windowName + "ContainerFakeParent"_L1); d->window->setParent(&d->fakeParent); + d->window->parent()->installEventFilter(this); d->window->setFlag(Qt::SubWindow); setAcceptDrops(true); - connect(QGuiApplication::instance(), SIGNAL(focusWindowChanged(QWindow*)), this, SLOT(focusWindowChanged(QWindow*))); + connect(qGuiApp, &QGuiApplication::focusWindowChanged, + this, &QWindowContainer::focusWindowChanged); + + connect(containedWindow(), &QWindow::minimumHeightChanged, this, &QWindowContainer::updateGeometry); + connect(containedWindow(), &QWindow::minimumWidthChanged, this, &QWindowContainer::updateGeometry); } QWindow *QWindowContainer::containedWindow() const @@ -220,6 +248,9 @@ QWindowContainer::~QWindowContainer() d->window->destroy(); delete d->window; + + disconnect(qGuiApp, &QGuiApplication::focusWindowChanged, + this, &QWindowContainer::focusWindowChanged); } @@ -243,6 +274,26 @@ void QWindowContainer::focusWindowChanged(QWindow *focusWindow) \internal */ +bool QWindowContainer::eventFilter(QObject *o, QEvent *e) +{ + Q_D(QWindowContainer); + if (!d->window) + return false; + + if (e->type() == QEvent::ChildRemoved) { + QChildEvent *ce = static_cast<QChildEvent *>(e); + if (ce->child() == d->window) { + o->removeEventFilter(this); + d->window = nullptr; + } + } + return false; +} + +/*! + \internal + */ + bool QWindowContainer::event(QEvent *e) { Q_D(QWindowContainer); @@ -251,12 +302,6 @@ bool QWindowContainer::event(QEvent *e) QEvent::Type type = e->type(); switch (type) { - case QEvent::ChildRemoved: { - QChildEvent *ce = static_cast<QChildEvent *>(e); - if (ce->child() == d->window) - d->window = nullptr; - break; - } // The only thing we are interested in is making sure our sizes stay // in sync, so do a catch-all case. case QEvent::Resize: @@ -271,10 +316,13 @@ bool QWindowContainer::event(QEvent *e) case QEvent::Show: d->updateUsesNativeWidgets(); if (d->isStillAnOrphan()) { + d->window->parent()->removeEventFilter(this); d->window->setParent(d->usesNativeWidgets ? windowHandle() : window()->windowHandle()); d->fakeParent.destroy(); + if (d->window->parent()) + d->window->parent()->installEventFilter(this); } if (d->window->parent()) { d->markParentChain(); @@ -328,6 +376,11 @@ bool QWindowContainer::event(QEvent *e) return QWidget::event(e); } +QSize QWindowContainer::minimumSizeHint() const +{ + return containedWindow() ? containedWindow()->minimumSize() : QSize(0, 0); +} + typedef void (*qwindowcontainer_traverse_callback)(QWidget *parent); static void qwindowcontainer_traverse(QWidget *parent, qwindowcontainer_traverse_callback callback) { @@ -345,7 +398,10 @@ static void qwindowcontainer_traverse(QWidget *parent, qwindowcontainer_traverse void QWindowContainer::toplevelAboutToBeDestroyed(QWidget *parent) { if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) { + if (d->window->parent()) + d->window->parent()->removeEventFilter(parent); d->window->setParent(&d->fakeParent); + d->window->parent()->installEventFilter(parent); } qwindowcontainer_traverse(parent, toplevelAboutToBeDestroyed); } @@ -363,7 +419,9 @@ void QWindowContainer::parentWasChanged(QWidget *parent) tld->createTLSysExtra(); Q_ASSERT(toplevel->windowHandle()); } + d->window->parent()->removeEventFilter(parent); d->window->setParent(toplevel->windowHandle()); + toplevel->windowHandle()->installEventFilter(parent); d->fakeParent.destroy(); d->updateGeometry(); } |