summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/widgets/kernel/qwidget.cpp18
-rw-r--r--src/widgets/kernel/qwidget_p.h2
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp34
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp48
4 files changed, 92 insertions, 10 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index b1d80d7b8f..b99fca6620 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -276,6 +276,8 @@ QWidgetPrivate::QWidgetPrivate(int version)
, renderToTextureReallyDirty(1)
, renderToTextureComposeActive(0)
#endif
+ , childrenHiddenByWState(0)
+ , childrenShownByExpose(0)
#if defined(Q_OS_WIN)
, noPaintOnScreen(0)
#endif
@@ -9005,13 +9007,23 @@ bool QWidget::event(QEvent *event)
case QEvent::WindowStateChange: {
const bool wasMinimized = static_cast<const QWindowStateChangeEvent *>(event)->oldState() & Qt::WindowMinimized;
if (wasMinimized != isMinimized()) {
+ QWidget *widget = const_cast<QWidget *>(this);
if (wasMinimized) {
- QShowEvent showEvent;
- QCoreApplication::sendEvent(const_cast<QWidget *>(this), &showEvent);
+ // Always send the spontaneous events here, otherwise it can break the application!
+ if (!d->childrenShownByExpose) {
+ // Show widgets only when they are not yet shown by the expose event
+ d->showChildren(true);
+ QShowEvent showEvent;
+ QCoreApplication::sendSpontaneousEvent(widget, &showEvent);
+ }
+ d->childrenHiddenByWState = false; // Set it always to "false" when window is restored
} else {
QHideEvent hideEvent;
- QCoreApplication::sendEvent(const_cast<QWidget *>(this), &hideEvent);
+ QCoreApplication::sendSpontaneousEvent(widget, &hideEvent);
+ d->hideChildren(true);
+ d->childrenHiddenByWState = true;
}
+ d->childrenShownByExpose = false; // Set it always to "false" when window state changes
}
changeEvent(event);
}
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index b130c5421a..5f07a8802a 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -746,6 +746,8 @@ public:
uint renderToTextureReallyDirty : 1;
uint renderToTextureComposeActive : 1;
#endif
+ uint childrenHiddenByWState : 1;
+ uint childrenShownByExpose : 1;
// *************************** Platform specific ************************************
#if defined(Q_OS_WIN)
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 872572a7e2..aa7bcc2ef8 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -871,10 +871,40 @@ void QWidgetWindow::handleDropEvent(QDropEvent *event)
void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
{
- if (isExposed()) {
+ QWidgetPrivate *wPriv = m_widget->d_func();
+ const bool exposed = isExposed();
+
+ if (wPriv->childrenHiddenByWState) {
+ // If widgets has been previously hidden by window state change event
+ // and they aren't yet shown...
+ if (exposed) {
+ // If the window becomes exposed...
+ if (!wPriv->childrenShownByExpose) {
+ // ... and they haven't been shown by this function yet - show it.
+ wPriv->showChildren(true);
+ QShowEvent showEvent;
+ QCoreApplication::sendSpontaneousEvent(m_widget, &showEvent);
+ wPriv->childrenShownByExpose = true;
+ }
+ } else {
+ // If the window becomes not exposed...
+ if (wPriv->childrenShownByExpose) {
+ // ... and child widgets was previously shown by the expose event - hide widgets again.
+ // This is a workaround, because sometimes when window is minimized programatically,
+ // the QPA can notify that the window is exposed after changing window state to minimized
+ // and then, the QPA can send next expose event with null exposed region (not exposed).
+ wPriv->hideChildren(true);
+ QHideEvent hideEvent;
+ QCoreApplication::sendSpontaneousEvent(m_widget, &hideEvent);
+ wPriv->childrenShownByExpose = false;
+ }
+ }
+ }
+
+ if (exposed) {
m_widget->setAttribute(Qt::WA_Mapped);
if (!event->region().isNull())
- m_widget->d_func()->syncBackingStore(event->region());
+ wPriv->syncBackingStore(event->region());
} else {
m_widget->setAttribute(Qt::WA_Mapped, false);
}
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index b7c152603c..34a1835413 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -294,6 +294,7 @@ private slots:
void showHideEvent_data();
void showHideEvent();
void showHideEventWhileMinimize();
+ void showHideChildrenWhileMinimize_QTBUG50589();
void lostUpdatesOnHide();
@@ -4078,19 +4079,30 @@ class ShowHideEventWidget : public QWidget
{
public:
int numberOfShowEvents, numberOfHideEvents;
+ int numberOfSpontaneousShowEvents, numberOfSpontaneousHideEvents;
ShowHideEventWidget(QWidget *parent = 0)
- : QWidget(parent), numberOfShowEvents(0), numberOfHideEvents(0)
+ : QWidget(parent)
+ , numberOfShowEvents(0), numberOfHideEvents(0)
+ , numberOfSpontaneousShowEvents(0), numberOfSpontaneousHideEvents(0)
{ }
void create()
{ QWidget::create(); }
- void showEvent(QShowEvent *)
- { ++numberOfShowEvents; }
+ void showEvent(QShowEvent *e)
+ {
+ ++numberOfShowEvents;
+ if (e->spontaneous())
+ ++numberOfSpontaneousShowEvents;
+ }
- void hideEvent(QHideEvent *)
- { ++numberOfHideEvents; }
+ void hideEvent(QHideEvent *e)
+ {
+ ++numberOfHideEvents;
+ if (e->spontaneous())
+ ++numberOfSpontaneousHideEvents;
+ }
};
void tst_QWidget::showHideEvent_data()
@@ -4182,6 +4194,32 @@ void tst_QWidget::showHideEventWhileMinimize()
QTRY_COMPARE(widget.numberOfShowEvents, showEventsBeforeMinimize + 1);
}
+void tst_QWidget::showHideChildrenWhileMinimize_QTBUG50589()
+{
+ const QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
+ if (!pi->hasCapability(QPlatformIntegration::MultipleWindows)
+ || !pi->hasCapability(QPlatformIntegration::NonFullScreenWindows)
+ || !pi->hasCapability(QPlatformIntegration::WindowManagement)) {
+ QSKIP("This test requires window management capabilities");
+ }
+
+ QWidget parent;
+ ShowHideEventWidget child(&parent);
+
+ parent.setWindowTitle(QTest::currentTestFunction());
+ parent.resize(m_testWidgetSize);
+ centerOnScreen(&parent);
+ parent.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&parent));
+
+ const int showEventsBeforeMinimize = child.numberOfSpontaneousShowEvents;
+ const int hideEventsBeforeMinimize = child.numberOfSpontaneousHideEvents;
+ parent.showMinimized();
+ QTRY_COMPARE(child.numberOfSpontaneousHideEvents, hideEventsBeforeMinimize + 1);
+ parent.showNormal();
+ QTRY_COMPARE(child.numberOfSpontaneousShowEvents, showEventsBeforeMinimize + 1);
+}
+
void tst_QWidget::update()
{
#ifdef Q_OS_OSX