summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qwindow.cpp143
-rw-r--r--src/gui/kernel/qwindow_p.h1
-rw-r--r--src/widgets/kernel/qwidget.cpp8
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp18
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h3
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp16
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"