From aeea8816a7228e9e89fff15b26005eaaa38fce2d Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Fri, 6 May 2016 16:12:15 +0200 Subject: Stop disabled QWebEngineView widget from processing input events. If a QWebEngineView is disabled, input events are still forwarded to Chromium, thus allowing the user to interact with a web page. Fix consists in stopping the forwarding of input events in the generic event handler, just like QWidget::event() does. Change-Id: Ie822d1f3d640840569a282223d76749686cf3419 Reviewed-by: Michal Klocek --- .../widgets/qwebengineview/tst_qwebengineview.cpp | 120 +++++++++++++++++++++ 1 file changed, 120 insertions(+) (limited to 'tests/auto/widgets/qwebengineview') diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 1ebb22cc9..d496362f9 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -28,10 +28,19 @@ #include #include #include +#include #define VERIFY_INPUTMETHOD_HINTS(actual, expect) \ QVERIFY(actual == expect); +#define QTRY_COMPARE_WITH_TIMEOUT_FAIL_BLOCK(__expr, __expected, __timeout, __fail_block) \ +do { \ + QTRY_IMPL(((__expr) == (__expected)), __timeout);\ + if (__expr != __expected)\ + __fail_block\ + QCOMPARE((__expr), __expected); \ +} while (0) + class tst_QWebEngineView : public QObject { Q_OBJECT @@ -59,6 +68,8 @@ private Q_SLOTS: void setPalette_data(); void setPalette(); #endif + void doNotSendMouseKeyboardEventsWhenDisabled(); + void doNotSendMouseKeyboardEventsWhenDisabled_data(); }; // This will be called before the first test function is executed. @@ -589,5 +600,114 @@ void tst_QWebEngineView::renderingAfterMaxAndBack() #endif } +class KeyboardAndMouseEventRecordingWidget : public QWidget { +public: + explicit KeyboardAndMouseEventRecordingWidget(QWidget *parent = 0) : + QWidget(parent), m_eventCounter(0) {} + + bool event(QEvent *event) Q_DECL_OVERRIDE + { + QString eventString; + switch (event->type()) { + case QEvent::TabletPress: + case QEvent::TabletRelease: + case QEvent::TabletMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + case QEvent::TouchCancel: + case QEvent::ContextMenu: + case QEvent::KeyPress: + case QEvent::KeyRelease: +#ifndef QT_NO_WHEELEVENT + case QEvent::Wheel: +#endif + ++m_eventCounter; + event->setAccepted(true); + QDebug(&eventString) << event; + m_eventHistory.append(eventString); + return true; + default: + break; + } + return QWidget::event(event); + } + + void clearEventCount() + { + m_eventCounter = 0; + } + + int eventCount() + { + return m_eventCounter; + } + + void printEventHistory() + { + qDebug() << "Received events are:"; + for (int i = 0; i < m_eventHistory.size(); ++i) { + qDebug() << m_eventHistory[i]; + } + } + +private: + int m_eventCounter; + QVector m_eventHistory; +}; + +void tst_QWebEngineView::doNotSendMouseKeyboardEventsWhenDisabled() +{ + QFETCH(bool, viewEnabled); + QFETCH(int, resultEventCount); + + KeyboardAndMouseEventRecordingWidget parentWidget; + QWebEngineView webView(&parentWidget); + webView.setEnabled(viewEnabled); + parentWidget.setLayout(new QStackedLayout); + parentWidget.layout()->addWidget(&webView); + webView.resize(640, 480); + parentWidget.show(); + QTest::qWaitForWindowExposed(&webView); + + QSignalSpy loadSpy(&webView, SIGNAL(loadFinished(bool))); + webView.setHtml("TitleHello" + ""); + QTRY_COMPARE(loadSpy.count(), 1); + + // When the webView is enabled, the events are swallowed by it, and the parent widget + // does not receive any events, otherwise all events are processed by the parent widget. + parentWidget.clearEventCount(); + QTest::mousePress(parentWidget.windowHandle(), Qt::LeftButton); + QTest::mouseMove(parentWidget.windowHandle(), QPoint(100, 100)); + QTest::mouseRelease(parentWidget.windowHandle(), Qt::LeftButton, + Qt::KeyboardModifiers(), QPoint(100, 100)); + + // Wait a bit for the mouse events to be processed, so they don't interfere with the js focus + // below. + QTest::qWait(100); + evaluateJavaScriptSync(webView.page(), "document.getElementById(\"input\").focus()"); + QTest::keyPress(parentWidget.windowHandle(), Qt::Key_H); + + // Wait a bit for the key press to be handled. We have to do it, because the compare + // below could immediately finish successfully, without alloing for the events to be handled. + QTest::qWait(100); + QTRY_COMPARE_WITH_TIMEOUT_FAIL_BLOCK(parentWidget.eventCount(), resultEventCount, + 1000, parentWidget.printEventHistory();); +} + +void tst_QWebEngineView::doNotSendMouseKeyboardEventsWhenDisabled_data() +{ + QTest::addColumn("viewEnabled"); + QTest::addColumn("resultEventCount"); + + QTest::newRow("enabled view receives events") << true << 0; + QTest::newRow("disabled view does not receive events") << false << 4; +} + QTEST_MAIN(tst_QWebEngineView) #include "tst_qwebengineview.moc" -- cgit v1.2.3 From 4c305cba0bf7cc021fd355af574b431f0d5a057d Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 9 May 2016 09:26:27 +0200 Subject: Disabled WebEngine views should not receive focus. Currently if a QWebEngineView or a QQuickWebEngineView is disabled using setEnabled(false), after loading a web page, the views are automatically focused, and a user might see a blinking caret in an html input for example, even though the user can't interact with it. Fix consists in not calling the Focus() method whenever a view is disabled. Change-Id: I1014fb5898a5ddf01a4e9b14c3eaf5d4006e5131 Task-number: QTBUG-53159 Reviewed-by: Michal Klocek --- .../widgets/qwebengineview/tst_qwebengineview.cpp | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'tests/auto/widgets/qwebengineview') diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index d496362f9..e66bf18cd 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -70,6 +70,8 @@ private Q_SLOTS: #endif void doNotSendMouseKeyboardEventsWhenDisabled(); void doNotSendMouseKeyboardEventsWhenDisabled_data(); + void stopSettingFocusWhenDisabled(); + void stopSettingFocusWhenDisabled_data(); }; // This will be called before the first test function is executed. @@ -709,5 +711,35 @@ void tst_QWebEngineView::doNotSendMouseKeyboardEventsWhenDisabled_data() QTest::newRow("disabled view does not receive events") << false << 4; } +void tst_QWebEngineView::stopSettingFocusWhenDisabled() +{ + QFETCH(bool, viewEnabled); + QFETCH(bool, focusResult); + + QWebEngineView webView; + webView.resize(640, 480); + webView.show(); + webView.setEnabled(viewEnabled); + QTest::qWaitForWindowExposed(&webView); + + QSignalSpy loadSpy(&webView, SIGNAL(loadFinished(bool))); + webView.setHtml("TitleHello" + ""); + QTRY_COMPARE(loadSpy.count(), 1); + + QTRY_COMPARE_WITH_TIMEOUT(webView.hasFocus(), focusResult, 1000); + evaluateJavaScriptSync(webView.page(), "document.getElementById(\"input\").focus()"); + QTRY_COMPARE_WITH_TIMEOUT(webView.hasFocus(), focusResult, 1000); +} + +void tst_QWebEngineView::stopSettingFocusWhenDisabled_data() +{ + QTest::addColumn("viewEnabled"); + QTest::addColumn("focusResult"); + + QTest::newRow("enabled view gets focus") << true << true; + QTest::newRow("disabled view does not get focus") << false << false; +} + QTEST_MAIN(tst_QWebEngineView) #include "tst_qwebengineview.moc" -- cgit v1.2.3