diff options
Diffstat (limited to 'src/widgets/kernel/qwindowcontainer.cpp')
-rw-r--r-- | src/widgets/kernel/qwindowcontainer.cpp | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 072a0bc5fa..376a93c758 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -3,7 +3,9 @@ #include "qwindowcontainer_p.h" #include "qwidget_p.h" +#include "qwidgetwindow_p.h" #include <QtGui/qwindow.h> +#include <QtGui/private/qwindow_p.h> #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformintegration.h> #include <QDebug> @@ -14,6 +16,8 @@ #include <QAbstractScrollArea> #include <QPainter> +#include <QtCore/qpointer.h> + QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; @@ -25,7 +29,6 @@ public: QWindowContainerPrivate() : window(nullptr) - , oldFocusWindow(nullptr) , usesNativeWidgets(false) { } @@ -100,7 +103,6 @@ public: } QPointer<QWindow> window; - QWindow *oldFocusWindow; QWindow fakeParent; uint usesNativeWidgets : 1; @@ -162,11 +164,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 +206,7 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: } d->window = embeddedWindow; + d->window->installEventFilter(this); QString windowName = d->window->objectName(); if (windowName.isEmpty()) @@ -196,7 +219,8 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: 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 @@ -217,29 +241,14 @@ 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) -{ - Q_D(QWindowContainer); - d->oldFocusWindow = focusWindow; - if (focusWindow == d->window) { - QWidget *widget = QApplication::focusWidget(); - if (widget) - widget->clearFocus(); - } -} - /*! \internal */ @@ -254,8 +263,12 @@ bool QWindowContainer::eventFilter(QObject *o, QEvent *e) 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; } @@ -305,11 +318,16 @@ bool QWindowContainer::event(QEvent *e) break; case QEvent::FocusIn: if (d->window->parent()) { - if (d->oldFocusWindow != d->window) { + if (QGuiApplication::focusWindow() != d->window) { + QFocusEvent *event = static_cast<QFocusEvent *>(e); + const auto reason = event->reason(); + QWindowPrivate::FocusTarget target = QWindowPrivate::FocusTarget::Current; + if (reason == Qt::TabFocusReason) + target = QWindowPrivate::FocusTarget::First; + else if (reason == Qt::BacktabFocusReason) + target = QWindowPrivate::FocusTarget::Last; + qt_window_private(d->window)->setFocusToTarget(target); d->window->requestActivate(); - } else { - QWidget *next = nextInFocusChain(); - next->setFocus(); } } break; @@ -346,6 +364,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) { |