diff options
Diffstat (limited to 'src/widgets/kernel/qwindowcontainer.cpp')
-rw-r--r-- | src/widgets/kernel/qwindowcontainer.cpp | 82 |
1 files changed, 59 insertions, 23 deletions
diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 847058e5b2..2c374ac408 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; @@ -25,7 +28,6 @@ public: QWindowContainerPrivate() : window(nullptr) - , oldFocusWindow(nullptr) , usesNativeWidgets(false) { } @@ -100,7 +102,6 @@ public: } QPointer<QWindow> window; - QWindow *oldFocusWindow; QWindow fakeParent; uint usesNativeWidgets : 1; @@ -162,11 +163,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); } @@ -184,6 +205,7 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: } d->window = embeddedWindow; + d->window->installEventFilter(this); QString windowName = d->window->objectName(); if (windowName.isEmpty()) @@ -191,11 +213,13 @@ 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(containedWindow(), &QWindow::minimumHeightChanged, this, &QWindowContainer::updateGeometry); + connect(containedWindow(), &QWindow::minimumWidthChanged, this, &QWindowContainer::updateGeometry); } QWindow *QWindowContainer::containedWindow() const @@ -216,27 +240,36 @@ QWindowContainer::~QWindowContainer() // QEvent::PlatformSurface delivery relies on virtuals. Getting // SurfaceAboutToBeDestroyed can be essential for OpenGL, Vulkan, etc. // QWindow subclasses in particular. Keep these working. - if (d->window) + if (d->window) { + d->window->removeEventFilter(this); d->window->destroy(); + } delete d->window; } - - /*! \internal */ -void QWindowContainer::focusWindowChanged(QWindow *focusWindow) +bool QWindowContainer::eventFilter(QObject *o, QEvent *e) { Q_D(QWindowContainer); - d->oldFocusWindow = focusWindow; - if (focusWindow == d->window) { - QWidget *widget = QApplication::focusWidget(); - if (widget) - widget->clearFocus(); + 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->removeEventFilter(this); + d->window = nullptr; + } + } else if (e->type() == QEvent::FocusIn) { + if (o == d->window) + setFocus(Qt::ActiveWindowFocusReason); } + return false; } /*! @@ -251,12 +284,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 +298,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(); @@ -287,12 +317,8 @@ bool QWindowContainer::event(QEvent *e) break; case QEvent::FocusIn: if (d->window->parent()) { - if (d->oldFocusWindow != d->window) { + if (QGuiApplication::focusWindow() != d->window) d->window->requestActivate(); - } else { - QWidget *next = nextInFocusChain(); - next->setFocus(); - } } break; #if QT_CONFIG(draganddrop) @@ -328,6 +354,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 +376,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 +397,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(); } |