From 1a71668483380f45cacda30cc55424d09def0636 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 24 Aug 2009 16:10:22 +0200 Subject: Fix Qt::ClickFocus for QGraphicsProxyWidget. This fixes click-focus for the Embedded Dialogs demo and the Pad Navigator demo. In Qt 4.6, the behavior of the spontaneous-bit in events has changed. This has happened in a number of submits that also modify Graphics View to have the correct behavior. Somewhere on the line, the spontaneous bit has been reset, preventing QApplicationPrivate's ClickFocus handling to kick in. This again causes the Embedded Dialogs demo to not give focus to widgets that are clicked. This fix is not likely to be 100% correct. What it does is ensure that the spont-bit survives a call to qt_sendSpontaneousEvent (as this bit is for some reason reset at the end of QApplicationPrivate::notify_helper), and this fixes the most apparent regression in ClickFocus handling. Pending closer review. The fix includes an autotest that should be kept if the fix is reverted. Reviewed-by: bnilsen --- src/corelib/kernel/qcoreevent.h | 1 + src/gui/graphicsview/qgraphicswidget.cpp | 8 +- .../tst_qgraphicsproxywidget.cpp | 85 ++++++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index babb89d..75af3e7 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -324,6 +324,7 @@ private: friend class QGraphicsView; friend class QGraphicsViewPrivate; friend class QGraphicsScenePrivate; + friend class QGraphicsWidget; }; class Q_CORE_EXPORT QTimerEvent : public QEvent diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 157fbe5..033723a 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -168,6 +168,8 @@ QT_BEGIN_NAMESPACE \sa QGraphicsProxyWidget, QGraphicsItem, {Widgets and Layouts} */ +bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); + /*! Constructs a QGraphicsWidget instance. The optional \a parent argument is passed to QGraphicsItem's constructor. The optional \a wFlags argument @@ -1097,7 +1099,11 @@ QVariant QGraphicsWidget::propertyChange(const QString &propertyName, const QVar */ bool QGraphicsWidget::sceneEvent(QEvent *event) { - return QCoreApplication::sendEvent(this, event) || QGraphicsItem::sceneEvent(event); + bool spont = event->spontaneous(); + if (spont ? qt_sendSpontaneousEvent(this, event) : QApplication::sendEvent(this, event)) + return true; + event->spont = spont; + return QGraphicsItem::sceneEvent(event); } /*! diff --git a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index 7536855..462dbfa 100644 --- a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -180,6 +180,7 @@ private slots: void comboboxWindowFlags(); void updateAndDelete(); void inputMethod(); + void clickFocus(); }; // Subclass that exposes the protected functions. @@ -3299,6 +3300,90 @@ void tst_QGraphicsProxyWidget::inputMethod() } } +void tst_QGraphicsProxyWidget::clickFocus() +{ + QGraphicsScene scene; + scene.setItemIndexMethod(QGraphicsScene::NoIndex); + QGraphicsProxyWidget *proxy = scene.addWidget(new QLineEdit); + + EventSpy proxySpy(proxy); + EventSpy widgetSpy(proxy->widget()); + + QGraphicsView view(&scene); + view.setFrameStyle(0); + view.resize(300, 300); + view.show(); +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&view); +#endif + QTest::qWait(250); + + QVERIFY(!proxy->hasFocus()); + QVERIFY(!proxy->widget()->hasFocus()); + + QCOMPARE(proxySpy.counts[QEvent::FocusIn], 0); + QCOMPARE(proxySpy.counts[QEvent::FocusOut], 0); + QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 0); + QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 0); + + // Spontaneous mouse click sets focus on a clickable widget. + QPointF lineEditCenter = proxy->mapToScene(proxy->boundingRect().center()); + QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter)); + QVERIFY(proxy->hasFocus()); + QVERIFY(proxy->widget()->hasFocus()); + QCOMPARE(proxySpy.counts[QEvent::FocusIn], 1); + QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 1); + + scene.setFocusItem(0); + QVERIFY(!proxy->hasFocus()); + QVERIFY(!proxy->widget()->hasFocus()); + QCOMPARE(proxySpy.counts[QEvent::FocusOut], 1); + QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 1); + + // Non-spontaneous mouse click sets focus if the widget has been clicked before + { + QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); + event.setScenePos(lineEditCenter); + event.setButton(Qt::LeftButton); + qApp->sendEvent(&scene, &event); + QVERIFY(proxy->hasFocus()); + QVERIFY(proxy->widget()->hasFocus()); + QCOMPARE(proxySpy.counts[QEvent::FocusIn], 2); + QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 2); + } + + scene.setFocusItem(0); + proxy->setWidget(new QLineEdit); // resets focusWidget + QVERIFY(!proxy->hasFocus()); + QVERIFY(!proxy->widget()->hasFocus()); + QCOMPARE(proxySpy.counts[QEvent::FocusOut], 2); + QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 2); + + // Non-spontaneous mouse click does not set focus on the embedded widget. + { + QGraphicsSceneMouseEvent event(QEvent::GraphicsSceneMousePress); + event.setScenePos(lineEditCenter); + event.setButton(Qt::LeftButton); + qApp->sendEvent(&scene, &event); + QVERIFY(!proxy->hasFocus()); + QVERIFY(!proxy->widget()->hasFocus()); + QCOMPARE(proxySpy.counts[QEvent::FocusIn], 2); + QCOMPARE(widgetSpy.counts[QEvent::FocusIn], 2); + } + + scene.setFocusItem(0); + QVERIFY(!proxy->hasFocus()); + QVERIFY(!proxy->widget()->hasFocus()); + QCOMPARE(proxySpy.counts[QEvent::FocusOut], 2); + QCOMPARE(widgetSpy.counts[QEvent::FocusOut], 2); + + // Spontaneous click on non-clickable widget does not give focus. + proxy->widget()->setFocusPolicy(Qt::NoFocus); + QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.mapFromScene(lineEditCenter)); + QVERIFY(!proxy->hasFocus()); + QVERIFY(!proxy->widget()->hasFocus()); +} + QTEST_MAIN(tst_QGraphicsProxyWidget) #include "tst_qgraphicsproxywidget.moc" -- cgit v0.12