summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/kernel/qwidget_window
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2020-04-20 14:06:53 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2020-04-24 17:40:36 +0200
commited86a4f25322ab0d08ad8ee9d3c507146573b1e0 (patch)
tree88a15541206d228aef4aea18ab71189e7ce6d425 /tests/auto/widgets/kernel/qwidget_window
parentcc54685b8d0610a682983418bd771e4d6f5f338b (diff)
Don't send QEvent::Hide to an already hidden top level widget
When hiding a popup by clicking outside of its area, a window is closed. Depending on the platform specific implementation details, this can result in multiple calls to QWidgetPrivate::setVisible(false). The first one from the handling of the close event in QWidgetWindow::event; the second from the destruction of the window in QWindow::event. Since the first call already sets the Qt::WA_WState_Hidden flag before calling QWidgetPrivate::hide_helper, we can test if the flag is set and skip the second call if it is. The included test does not reproduce the issue, as that issue only reproduces if the close event is generated by the mouse event handling in the Cocoa platform plugin (which doesn't call QWidget::close, but rather sends a native close event to the platform window). However, it verifies that the fix doesn't introduce any regressions. Change-Id: Id0eda9326a8adf0cc1f6a3840f9ac0b635ab39a1 Fixes: QTBUG-79134 Pick-to: 5.15 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'tests/auto/widgets/kernel/qwidget_window')
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp74
1 files changed, 74 insertions, 0 deletions
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 f42e2d777b..12d60a33c2 100644
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -113,6 +113,8 @@ private slots:
void tst_resize_count();
void tst_move_count();
+ void tst_showhide_count();
+
void tst_eventfilter_on_toplevel();
void QTBUG_50561_QCocoaBackingStore_paintDevice_crash();
@@ -1021,6 +1023,78 @@ void tst_QWidget_window::tst_resize_count()
}
+/*!
+ This test verifies that windows get a balanced number of show
+ and hide events, no matter how the window was closed.
+*/
+void tst_QWidget_window::tst_showhide_count()
+{
+ class EventSpy : public QObject
+ {
+ public:
+ EventSpy()
+ {
+ QApplication::instance()->installEventFilter(this);
+ }
+
+ int takeCount(QWidget *widget, QEvent::Type type) {
+ const auto entry = Entry(widget, type);
+ int count = counter[entry];
+ counter[entry] = 0;
+ return count;
+ }
+ protected:
+ bool eventFilter(QObject *receiver, QEvent *event)
+ {
+ if (QWidget *widget = qobject_cast<QWidget*>(receiver)) {
+ const auto entry = Entry(widget, event->type());
+ ++counter[entry];
+ return false;
+ }
+ return QObject::eventFilter(receiver, event);
+ }
+ private:
+ using Entry = QPair<QWidget*, QEvent::Type>;
+ QHash<Entry, int> counter;
+ };
+
+ EventSpy spy;
+
+ QWidget w1;
+ w1.setGeometry(100, 100, 200, 200);
+
+ w1.show();
+ QCOMPARE(spy.takeCount(&w1, QEvent::Show), 1);
+ w1.hide();
+ QCOMPARE(spy.takeCount(&w1, QEvent::Hide), 1);
+ w1.close();
+ QCOMPARE(spy.takeCount(&w1, QEvent::Close), 1);
+ w1.show();
+ QCOMPARE(spy.takeCount(&w1, QEvent::Show), 1);
+ w1.close();
+ QCOMPARE(spy.takeCount(&w1, QEvent::Hide), 1);
+ QCOMPARE(spy.takeCount(&w1, QEvent::Close), 1);
+
+ w1.show();
+ QWidget *popup = new QWidget(&w1, Qt::Popup);
+ popup->setGeometry(120, 120, 30, 30);
+ popup->show();
+ popup->close();
+ QCOMPARE(spy.takeCount(popup, QEvent::Show), 1);
+ QCOMPARE(spy.takeCount(popup, QEvent::Hide), 1);
+ QCOMPARE(spy.takeCount(popup, QEvent::Close), 1);
+
+ popup->show();
+
+ // clicking outside the popup should close the popup
+ QTest::mousePress(popup->window(), Qt::LeftButton, {}, QPoint(-10, -10));
+
+ QCOMPARE(spy.takeCount(popup, QEvent::Show), 1);
+ QCOMPARE(spy.takeCount(popup, QEvent::Hide), 1);
+ QCOMPARE(spy.takeCount(popup, QEvent::Close), 1);
+}
+
+
class MoveWidget : public QWidget
{
Q_OBJECT