From 292f573f4e86d938a3bde80627637d245a949e56 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Mon, 9 May 2016 10:11:36 +0200 Subject: Fix event forwarding when activeFocusOnPress is false. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a QQuickWebEngineView does not have focus, and activeFocusOnPress is set to false, a user can still partially interact with the view. For instance hovering the mouse over a link would change the cursor, a link can be clicked to go to a different page. Clicking on a text input field would focus the text field, but entering characters will not be possible, because the view does not have QtQuick keyboard focus, and clicking does not give the focus (because activeFocusOnPress is set to false) and this leads to confusing behavior. Thus the fix is to make sure no mouse / keyboard events are forwarded to Chromium if the view has no focus, and activeFocusOnPress is set to false, in order to maintain a more user-friendly behavior. Manually forcing the focus via some user-provided method that calls forceActiveFocus() would allow further proper interaction. Change-Id: I72c3ff69438972b9a93ee2d415fa1d4b44b86cd9 Reviewed-by: Michael BrĂ¼ning --- .../qquickwebengineview/qquickwebengineview.pro | 2 +- .../tst_qquickwebengineview.cpp | 108 +++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) (limited to 'tests/auto') diff --git a/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro b/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro index 826b47de7..36e74a2a8 100644 --- a/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro +++ b/tests/auto/quick/qquickwebengineview/qquickwebengineview.pro @@ -1,6 +1,6 @@ include(../tests.pri) exists($${TARGET}.qrc):RESOURCES += $${TARGET}.qrc -QT_PRIVATE += webengine-private +QT_PRIVATE += webengine-private gui-private HEADERS += ../shared/util.h diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index d39a6df54..7e684a35a 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -63,6 +64,7 @@ private Q_SLOTS: void setZoomFactor(); void stopSettingFocusWhenDisabled(); void stopSettingFocusWhenDisabled_data(); + void inputEventForwardingDisabledWhenActiveFocusOnPressDisabled(); private: inline QQuickWebEngineView *newWebEngineView(); @@ -511,5 +513,111 @@ void tst_QQuickWebEngineView::stopSettingFocusWhenDisabled_data() QTest::newRow("disabled view does not get active focus") << false << false; } +class MouseTouchEventRecordingItem : public QQuickItem { +public: + explicit MouseTouchEventRecordingItem(QQuickItem *parent = 0) : + QQuickItem(parent), m_eventCounter(0) { + setFlag(ItemHasContents); + setAcceptedMouseButtons(Qt::AllButtons); + setAcceptHoverEvents(true); + } + + bool event(QEvent *event) Q_DECL_OVERRIDE + { + 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::HoverEnter: + case QEvent::HoverMove: + case QEvent::HoverLeave: + ++m_eventCounter; + event->accept(); + return true; + default: + break; + } + return QQuickItem::event(event); + } + + void clearEventCount() + { + m_eventCounter = 0; + } + + int eventCount() + { + return m_eventCounter; + } + +private: + int m_eventCounter; +}; + +void tst_QQuickWebEngineView::inputEventForwardingDisabledWhenActiveFocusOnPressDisabled() +{ + QQuickWebEngineView *view = webEngineView(); + MouseTouchEventRecordingItem item; + item.setParentItem(m_window->contentItem()); + item.setSize(QSizeF(640, 480)); + view->setParentItem(&item); + view->setSize(QSizeF(640, 480)); + m_window->show(); + + // Simulate click and move of mouse, so that last known position in the application + // is updated, thus a mouse move event is not generated when we don't expect it. + QTest::mouseClick(view->window(), Qt::LeftButton); + item.clearEventCount(); + + // First disable view, so it does not receive focus on page load. + view->setEnabled(false); + view->setActiveFocusOnPress(false); + view->loadHtml("" + "" + "TitleHello" + ""); + QVERIFY(waitForLoadSucceeded(view)); + QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), false, 1000); + + // Enable the view back so we can try to interact with it. + view->setEnabled(true); + + // Click on the view, to try and set focus. + QTest::mouseClick(view->window(), Qt::LeftButton); + + // View should not have focus after click, because setActiveFocusOnPress is false. + QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), false, 1000); + + // Now test sending various input events, to check that indeed all the input events are not + // forwarded to Chromium, but rather processed and accepted by the view's parent item. + QTest::mousePress(view->window(), Qt::LeftButton); + QTest::mouseRelease(view->window(), Qt::LeftButton); + + QTouchDevice *device = new QTouchDevice; + device->setType(QTouchDevice::TouchScreen); + QWindowSystemInterface::registerTouchDevice(device); + + QTest::touchEvent(view->window(), device).press(0, QPoint(0,0), view->window()); + QTest::touchEvent(view->window(), device).move(0, QPoint(1, 1), view->window()); + QTest::touchEvent(view->window(), device).release(0, QPoint(1, 1), view->window()); + + // We expect to catch 7 events - click = 2, press + release = 2, touches = 3. + QCOMPARE(item.eventCount(), 7); + + // Manually forcing focus should still be possible. + view->forceActiveFocus(); + QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), true, 1000); +} + QTEST_MAIN(tst_QQuickWebEngineView) #include "tst_qquickwebengineview.moc" -- cgit v1.2.3