From 78edc18057d04a8329060b52d78833711bcadf39 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Sat, 25 Jan 2020 00:48:48 +0100 Subject: QGraphicsProxyWidget: fix handling of proxy focus If a widget inside a QGPW has a proxy focus, the code would keep sending focus in events to the proxy even if the proxy was already focused. Amend the check in place to prevent this from happening. Change-Id: Id28d3bfe4f396da5c9477df713441ca7d506662f Fixes: QTBUG-51856 Reviewed-by: Christian Ehrlicher Reviewed-by: Richard Moe Gustavsen --- .../tst_qgraphicsproxywidget.cpp | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp') diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index a437b05479..8c2d89e34b 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -89,6 +89,7 @@ private slots: void focusNextPrevChild(); void focusOutEvent_data(); void focusOutEvent(); + void focusProxy_QTBUG_51856(); void hoverEnterLeaveEvent_data(); void hoverEnterLeaveEvent(); void hoverMoveEvent_data(); @@ -864,6 +865,75 @@ void tst_QGraphicsProxyWidget::focusOutEvent() } } +void tst_QGraphicsProxyWidget::focusProxy_QTBUG_51856() +{ + // QSpinBox has an internal QLineEdit; this QLineEdit has the spinbox + // as its focus proxy. + struct FocusedSpinBox : QSpinBox + { + int focusCount = 0; + + bool event(QEvent *event) override + { + switch (event->type()) { + case QEvent::FocusIn: + ++focusCount; + break; + case QEvent::FocusOut: + --focusCount; + break; + default: + break; + } + return QSpinBox::event(event); + } + }; + + QGraphicsScene scene; + QGraphicsView view(&scene); + SubQGraphicsProxyWidget *proxy = new SubQGraphicsProxyWidget; + scene.addItem(proxy); + view.show(); + view.raise(); + view.activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(&view)); + + FocusedSpinBox *spinBox = new FocusedSpinBox; + + proxy->setWidget(spinBox); + proxy->show(); + proxy->setFocus(); + QVERIFY(proxy->hasFocus()); + QEXPECT_FAIL("", "Widget should have focus but doesn't", Continue); + QVERIFY(spinBox->hasFocus()); + QEXPECT_FAIL("", "Widget should have focus but doesn't", Continue); + QCOMPARE(spinBox->focusCount, 1); + + enum { Count = 10 }; + + for (int i = 0; i < Count; ++i) { + for (int clickCount = 0; clickCount < Count; ++clickCount) { + auto proxyCenter = proxy->boundingRect().center(); + auto proxyCenterInScene = proxy->mapToScene(proxyCenter); + auto proxyCenterInView = view.mapFromScene(proxyCenterInScene); + + QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, proxyCenterInView); + QTRY_COMPARE(spinBox->focusCount, 1); + } + + QLineEdit *edit = new QLineEdit(&view); + edit->show(); + QTRY_VERIFY(edit->isVisible()); + edit->setFocus(); + QTRY_VERIFY(edit->hasFocus()); + QTRY_VERIFY(!proxy->hasFocus()); + QTRY_COMPARE(proxy->focusOut, i + 1); + QTRY_VERIFY(!spinBox->hasFocus()); + QTRY_COMPARE(spinBox->focusCount, 0); + delete edit; + } +} + class EventLogger : public QWidget { public: -- cgit v1.2.3