diff options
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 143 | ||||
-rw-r--r-- | src/gui/kernel/qwindow_p.h | 1 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 8 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 18 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow_p.h | 3 | ||||
-rw-r--r-- | tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp | 16 |
6 files changed, 120 insertions, 69 deletions
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 796a552bcb..34d35ef2d1 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -317,6 +317,83 @@ void QWindow::setVisibility(Visibility v) } } +/* + Subclasses may override this function to run custom setVisible + logic. Subclasses that do so must call the base class implementation + at some point to make the native window visible, and must not + call QWindow::setVisble() since that will recurse back here. +*/ +void QWindowPrivate::setVisible(bool visible) +{ + Q_Q(QWindow); + + if (this->visible != visible) { + this->visible = visible; + emit q->visibleChanged(visible); + updateVisibility(); + } else if (platformWindow) { + // Visibility hasn't changed, and the platform window is in sync + return; + } + + if (!platformWindow) { + // If we have a parent window, but the parent hasn't been created yet, we + // can defer creation until the parent is created or we're re-parented. + if (parentWindow && !parentWindow->handle()) + return; + + // We only need to create the window if it's being shown + if (visible) + q->create(); + } + + if (visible) { + // remove posted quit events when showing a new window + QCoreApplication::removePostedEvents(qApp, QEvent::Quit); + + if (q->type() == Qt::Window) { + QGuiApplicationPrivate *app_priv = QGuiApplicationPrivate::instance(); + QString &firstWindowTitle = app_priv->firstWindowTitle; + if (!firstWindowTitle.isEmpty()) { + q->setTitle(firstWindowTitle); + firstWindowTitle = QString(); + } + if (!app_priv->forcedWindowIcon.isNull()) + q->setIcon(app_priv->forcedWindowIcon); + + // Handling of the -qwindowgeometry, -geometry command line arguments + static bool geometryApplied = false; + if (!geometryApplied) { + geometryApplied = true; + QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(q); + } + } + + QShowEvent showEvent; + QGuiApplication::sendEvent(q, &showEvent); + } + + if (q->isModal()) { + if (visible) + QGuiApplicationPrivate::showModalWindow(q); + else + QGuiApplicationPrivate::hideModalWindow(q); + } + +#ifndef QT_NO_CURSOR + if (visible && (hasCursor || QGuiApplication::overrideCursor())) + applyCursor(); +#endif + + if (platformWindow) + platformWindow->setVisible(visible); + + if (!visible) { + QHideEvent hideEvent; + QGuiApplication::sendEvent(q, &hideEvent); + } +} + void QWindowPrivate::updateVisibility() { Q_Q(QWindow); @@ -514,71 +591,7 @@ void QWindow::setVisible(bool visible) { Q_D(QWindow); - if (d->visible != visible) { - d->visible = visible; - emit visibleChanged(visible); - d->updateVisibility(); - } else if (d->platformWindow) { - // Visibility hasn't changed, and the platform window is in sync - return; - } - - if (!d->platformWindow) { - // If we have a parent window, but the parent hasn't been created yet, we - // can defer creation until the parent is created or we're re-parented. - if (parent() && !parent()->handle()) - return; - - // We only need to create the window if it's being shown - if (visible) - create(); - } - - if (visible) { - // remove posted quit events when showing a new window - QCoreApplication::removePostedEvents(qApp, QEvent::Quit); - - if (type() == Qt::Window) { - QGuiApplicationPrivate *app_priv = QGuiApplicationPrivate::instance(); - QString &firstWindowTitle = app_priv->firstWindowTitle; - if (!firstWindowTitle.isEmpty()) { - setTitle(firstWindowTitle); - firstWindowTitle = QString(); - } - if (!app_priv->forcedWindowIcon.isNull()) - setIcon(app_priv->forcedWindowIcon); - - // Handling of the -qwindowgeometry, -geometry command line arguments - static bool geometryApplied = false; - if (!geometryApplied) { - geometryApplied = true; - QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(this); - } - } - - QShowEvent showEvent; - QGuiApplication::sendEvent(this, &showEvent); - } - - if (isModal()) { - if (visible) - QGuiApplicationPrivate::showModalWindow(this); - else - QGuiApplicationPrivate::hideModalWindow(this); - } - -#ifndef QT_NO_CURSOR - if (visible && (d->hasCursor || QGuiApplication::overrideCursor())) - d->applyCursor(); -#endif - - if (d->platformWindow) - d->platformWindow->setVisible(visible); - - if (!visible) { - QHideEvent hideEvent; - QGuiApplication::sendEvent(this, &hideEvent); - } + d->setVisible(visible); } bool QWindow::isVisible() const diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h index cffe5b4125..9b8e2c47e4 100644 --- a/src/gui/kernel/qwindow_p.h +++ b/src/gui/kernel/qwindow_p.h @@ -132,6 +132,7 @@ public: virtual QWindow *eventReceiver() { Q_Q(QWindow); return q; } + virtual void setVisible(bool visible); void updateVisibility(); void _q_clearAlert(); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 7112e1c783..caa17e4aea 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -7952,7 +7952,7 @@ void QWidgetPrivate::show_sys() { Q_Q(QWidget); - QWindow *window = q->windowHandle(); + QWidgetWindow *window = qobject_cast<QWidgetWindow *>(q->windowHandle()); if (q->testAttribute(Qt::WA_DontShowOnScreen)) { invalidateBuffer(q->rect()); @@ -7999,7 +7999,7 @@ void QWidgetPrivate::show_sys() qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show #endif invalidateBuffer(q->rect()); - window->setVisible(true); + window->setNativeWindowVisibility(true); // Was the window moved by the Window system or QPlatformWindow::initialGeometry() ? if (window->isTopLevel()) { const QPoint crectTopLeft = q->data->crect.topLeft(); @@ -8091,7 +8091,7 @@ void QWidgetPrivate::hide_sys() { Q_Q(QWidget); - QWindow *window = q->windowHandle(); + QWidgetWindow *window = qobject_cast<QWidgetWindow *>(q->windowHandle()); if (q->testAttribute(Qt::WA_DontShowOnScreen)) { q->setAttribute(Qt::WA_Mapped, false); @@ -8121,7 +8121,7 @@ void QWidgetPrivate::hide_sys() } if (window) - window->setVisible(false); + window->setNativeWindowVisibility(false); } /*! diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 5b695d9f30..84323a5388 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -69,6 +69,15 @@ class QWidgetWindowPrivate : public QWindowPrivate { Q_DECLARE_PUBLIC(QWidgetWindow) public: + void setVisible(bool visible) override + { + Q_Q(QWidgetWindow); + if (QWidget *widget = q->widget()) + widget->setVisible(visible); + else + QWindowPrivate::setVisible(visible); + } + QWindow *eventReceiver() Q_DECL_OVERRIDE { Q_Q(QWidgetWindow); QWindow *w = q; @@ -164,6 +173,15 @@ QObject *QWidgetWindow::focusObject() const return widget; } +void QWidgetWindow::setNativeWindowVisibility(bool visible) +{ + Q_D(QWidgetWindow); + // Call base class setVisible() implementation to run the QWindow + // visibility logic. Don't call QWidgetWindowPrivate::setVisible() + // since that will recurse back into QWidget code. + d->QWindowPrivate::setVisible(visible); +} + static inline bool shouldBePropagatedToWidget(QEvent *event) { switch (event->type()) { diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h index a81355160e..4c7e30da2f 100644 --- a/src/widgets/kernel/qwidgetwindow_p.h +++ b/src/widgets/kernel/qwidgetwindow_p.h @@ -63,10 +63,12 @@ QT_BEGIN_NAMESPACE class QCloseEvent; class QMoveEvent; +class QWidgetWindowPrivate; class QWidgetWindow : public QWindow { Q_OBJECT + Q_DECLARE_PRIVATE(QWidgetWindow) public: QWidgetWindow(QWidget *widget); ~QWidgetWindow(); @@ -77,6 +79,7 @@ public: #endif QObject *focusObject() const Q_DECL_OVERRIDE; + void setNativeWindowVisibility(bool visible); protected: bool event(QEvent *) Q_DECL_OVERRIDE; diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index 97d7d78153..a6855a417e 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -102,6 +102,8 @@ private slots: void setWindowState_data(); void setWindowState(); + + void nativeShow(); }; void tst_QWidget_window::initTestCase() @@ -915,5 +917,19 @@ void tst_QWidget_window::setWindowState() QCOMPARE(w.windowHandle()->windowStates(), state | Qt::WindowMinimized); } +void tst_QWidget_window::nativeShow() +{ + // Verify that a native widget can be shown using the QWindow::setVisible() API + QWidget w; + w.winId(); + w.windowHandle()->setVisible(true); + QTest::qWaitForWindowExposed(&w); + QVERIFY(w.isVisible()); + + // ... and that we can hide it + w.windowHandle()->setVisible(false); + QTRY_VERIFY(!w.isVisible()); +} + QTEST_MAIN(tst_QWidget_window) #include "tst_qwidget_window.moc" |