diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-05-31 11:33:19 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2016-05-31 11:33:53 +0200 |
commit | d2d5d24f86f12a2d1b0a6bc46c0d48306d7d2130 (patch) | |
tree | d67555a6c699c49a89ea10863b6c0e4c0c3f5cae | |
parent | f9e951d0946fe0fcd51e9015108f92c46ecc8138 (diff) | |
parent | 42d864c86d8c85db7b2d42f8505d962a642e4c77 (diff) |
Merge remote-tracking branch 'origin/5.6' into 5.7
Change-Id: I561c00b3a844ab493a5bf0148a5923662842cf5d
23 files changed, 406 insertions, 63 deletions
diff --git a/.qmake.conf b/.qmake.conf index 3442ea6e1..52fc5b4ea 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,6 +1,5 @@ QMAKEPATH += $$PWD/tools/qmake load(qt_build_config) -CONFIG += qt_example_installs CONFIG += warning_clean MODULE_VERSION = 5.7.0 diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 19b67876c..a9f5adaba 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -15,6 +15,7 @@ CONFIG -= create_prl # Copy this logic from qt_module.prf so that the intermediate library can be # created to the same rules as the final module linking in core_module.pro. !host_build:if(win32|mac):!macx-xcode { + contains(QT_CONFIG, simulator_and_device): CONFIG += iphonesimulator_and_iphoneos contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release contains(QT_CONFIG, build_all):CONFIG += build_all } diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index bd62f4872..712ff5703 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -56,6 +56,13 @@ namespace QtWebEngineCore { +static void registerMetaTypes() +{ + qRegisterMetaType<QClipboard::Mode>("QClipboard::Mode"); +} + +Q_CONSTRUCTOR_FUNCTION(registerMetaTypes) + Q_GLOBAL_STATIC(ClipboardChangeObserver, clipboardChangeObserver) ClipboardChangeObserver::ClipboardChangeObserver() diff --git a/src/core/gyp_run.pro b/src/core/gyp_run.pro index 2e2422dce..41cdf4598 100644 --- a/src/core/gyp_run.pro +++ b/src/core/gyp_run.pro @@ -34,6 +34,7 @@ force_debug_info { # Copy this logic from qt_module.prf so that ninja can run according # to the same rules as the final module linking in core_module.pro. !host_build:if(win32|mac):!macx-xcode { + contains(QT_CONFIG, simulator_and_device): CONFIG += iphonesimulator_and_iphoneos contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release contains(QT_CONFIG, build_all):CONFIG += build_all } diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index 80aabaa4d..c50f38b38 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -257,6 +257,7 @@ public: virtual void updateContentsSize(const QSizeF &size) = 0; virtual void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) = 0; + virtual bool isEnabled() const = 0; virtual QSharedPointer<BrowserContextAdapter> browserContextAdapter() = 0; virtual WebContentsAdapter* webContentsAdapter() = 0; diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp index 1d39d8af8..e487fca46 100644 --- a/src/core/web_contents_view_qt.cpp +++ b/src/core/web_contents_view_qt.cpp @@ -120,6 +120,8 @@ void WebContentsViewQt::GetContainerBounds(gfx::Rect* out) const void WebContentsViewQt::Focus() { + if (!m_client->isEnabled()) + return; if (content::RenderWidgetHostView *rwhv = m_webContents->GetRenderWidgetHostView()) rwhv->Focus(); m_client->focusContainer(); diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 1b1dcec25..36a7b69b9 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -124,6 +124,8 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() , m_dpiScale(1.0) , m_backgroundColor(Qt::white) , m_defaultZoomFactor(1.0) + // QTBUG-53467 + , m_menuEnabled(true) { // The gold standard for mobile web content is 160 dpi, and the devicePixelRatio expected // is the (possibly quantized) ratio of device dpi to 160 dpi. @@ -141,6 +143,8 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate() // 1x, 2x, 3x etc assets that fit an integral number of pixels. setDevicePixelRatio(qMax(1, qRound(webPixelRatio))); } + if (platform == QLatin1Literal("eglfs")) + m_menuEnabled = false; #ifndef QT_NO_ACCESSIBILITY QAccessible::installFactory(&webAccessibleFactory); #endif // QT_NO_ACCESSIBILITY @@ -191,6 +195,12 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu { Q_Q(QQuickWebEngineView); + if (!m_menuEnabled) { + qWarning("You are trying to open context menu on eglfs backend, which is not currently supported\n" + "See QTBUG-53467."); + return false; + } + // Assign the WebEngineView as the parent of the menu, so mouse events are properly propagated // on OSX. QObject *menu = ui()->addMenu(q, QString(), data.pos); @@ -1075,6 +1085,12 @@ void QQuickWebEngineViewPrivate::startDragging(const content::DropData &dropData adapter->startDragging(q_ptr->window(), dropData, allowedActions, pixmap, offset); } +bool QQuickWebEngineViewPrivate::isEnabled() const +{ + const Q_Q(QQuickWebEngineView); + return q->isEnabled(); +} + bool QQuickWebEngineView::isLoading() const { Q_D(const QQuickWebEngineView); diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index 82a9e9612..909763614 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -187,6 +187,7 @@ public: virtual void updateContentsSize(const QSizeF &size) Q_DECL_OVERRIDE; void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) Q_DECL_OVERRIDE; + virtual bool isEnabled() const Q_DECL_OVERRIDE; virtual QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextAdapter() Q_DECL_OVERRIDE; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() Q_DECL_OVERRIDE; @@ -233,6 +234,8 @@ private: qreal m_dpiScale; QColor m_backgroundColor; qreal m_defaultZoomFactor; + // QTBUG-53467 + bool m_menuEnabled; }; #ifndef QT_NO_ACCESSIBILITY diff --git a/src/webengine/doc/qtwebengine.qdocconf b/src/webengine/doc/qtwebengine.qdocconf index 6d946c9c9..009902080 100644 --- a/src/webengine/doc/qtwebengine.qdocconf +++ b/src/webengine/doc/qtwebengine.qdocconf @@ -40,8 +40,10 @@ tagfile = ../../../doc/qtwebengine/qtwebengine.tags depends += qtcore \ qtgui \ + qtlocation \ qtnetwork \ qtprintsupport \ + qtpositioning \ qtqml \ qtquick \ qtquickcontrols \ diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp index 9ad86800c..5e39cc2b3 100644 --- a/src/webengine/render_widget_host_view_qt_delegate_quick.cpp +++ b/src/webengine/render_widget_host_view_qt_delegate_quick.cpp @@ -222,18 +222,33 @@ void RenderWidgetHostViewQtDelegateQuick::focusOutEvent(QFocusEvent *event) void RenderWidgetHostViewQtDelegateQuick::mousePressEvent(QMouseEvent *event) { - if (!m_isPopup && (parentItem() && parentItem()->property("activeFocusOnPress").toBool())) + QQuickItem *parent = parentItem(); + if (!m_isPopup && (parent && parent->property("activeFocusOnPress").toBool())) forceActiveFocus(); + if (parent && !parent->property("activeFocusOnPress").toBool() && !parent->hasActiveFocus()) { + event->ignore(); + return; + } m_client->forwardEvent(event); } void RenderWidgetHostViewQtDelegateQuick::mouseMoveEvent(QMouseEvent *event) { + QQuickItem *parent = parentItem(); + if (parent && !parent->property("activeFocusOnPress").toBool() && !parent->hasActiveFocus()) { + event->ignore(); + return; + } m_client->forwardEvent(event); } void RenderWidgetHostViewQtDelegateQuick::mouseReleaseEvent(QMouseEvent *event) { + QQuickItem *parent = parentItem(); + if (parent && !parent->property("activeFocusOnPress").toBool() && !parent->hasActiveFocus()) { + event->ignore(); + return; + } m_client->forwardEvent(event); } @@ -254,14 +269,24 @@ void RenderWidgetHostViewQtDelegateQuick::wheelEvent(QWheelEvent *event) void RenderWidgetHostViewQtDelegateQuick::touchEvent(QTouchEvent *event) { + QQuickItem *parent = parentItem(); if (event->type() == QEvent::TouchBegin && !m_isPopup - && (parentItem() && parentItem()->property("activeFocusOnPress").toBool())) + && (parent && parent->property("activeFocusOnPress").toBool())) forceActiveFocus(); + if (parent && !parent->property("activeFocusOnPress").toBool() && !parent->hasActiveFocus()) { + event->ignore(); + return; + } m_client->forwardEvent(event); } void RenderWidgetHostViewQtDelegateQuick::hoverMoveEvent(QHoverEvent *event) { + QQuickItem *parent = parentItem(); + if (parent && !parent->property("activeFocusOnPress").toBool() && !parent->hasActiveFocus()) { + event->ignore(); + return; + } m_client->forwardEvent(event); } diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index 0e7f02f16..04b8a2b6f 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -1269,6 +1269,15 @@ void QWebEnginePagePrivate::startDragging(const content::DropData &dropData, adapter->startDragging(view, dropData, allowedActions, pixmap, offset); } +bool QWebEnginePagePrivate::isEnabled() const +{ + const Q_Q(QWebEnginePage); + const QWidget *view = q->view(); + if (view) + return view->isEnabled(); + return true; +} + QMenu *QWebEnginePage::createStandardContextMenu() { Q_D(QWebEnginePage); diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 22bfaff95..26ef80e9a 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -135,6 +135,7 @@ public: virtual void updateContentsSize(const QSizeF &size) Q_DECL_OVERRIDE; void startDragging(const content::DropData &dropData, Qt::DropActions allowedActions, const QPixmap &pixmap, const QPoint &offset) Q_DECL_OVERRIDE; + virtual bool isEnabled() const Q_DECL_OVERRIDE; virtual QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextAdapter() Q_DECL_OVERRIDE; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() Q_DECL_OVERRIDE; diff --git a/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc b/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc index e6236ec98..89d7cfb0c 100644 --- a/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc +++ b/src/webenginewidgets/doc/src/qtwebkitportingguide.qdoc @@ -248,7 +248,7 @@ \b {Qt WebEngine} \code QWebEnginePage page; - page.runJavascript("document.documentElement.contentEditable = true"); + page.runJavaScript("document.documentElement.contentEditable = true"); \endcode @@ -287,7 +287,7 @@ \li QWebPage::setContentEditable \li In the latest HTML standard, any document element can be made editable through the \c contentEditable attribute. So \c runJavaScript is all that is needed: - \c{page->runJavascript("document.documentElement.contentEditable = true")} + \c{page->runJavaScript("document.documentElement.contentEditable = true")} \row \li QWebPage::setLinkDelegationPolicy \li There is no way to connect a signal to run C++ code when a link is clicked. However, diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp index 3f70187e7..99621b602 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -298,6 +298,34 @@ void RenderWidgetHostViewQtDelegateWidget::hideEvent(QHideEvent *event) bool RenderWidgetHostViewQtDelegateWidget::event(QEvent *event) { bool handled = false; + + // Mimic QWidget::event() by ignoring mouse, keyboard, touch and tablet events if the widget is + // disabled. + if (!isEnabled()) { + 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 + return false; + default: + break; + } + } + if (event->type() == QEvent::MouseButtonDblClick) { // QWidget keeps the Qt4 behavior where the DblClick event would replace the Press event. // QtQuick is different by sending both the Press and DblClick events for the second press diff --git a/sync.profile b/sync.profile index 7d6daec35..e4a88e0c2 100644 --- a/sync.profile +++ b/sync.profile @@ -20,7 +20,7 @@ %dependencies = ( "qtbase" => "", "qtdeclarative" => "", - "qtxmlpatterns" => "", + "qtlocation" => "", "qttools" => "", # FIXME: take examples out into their own module to avoid a potential circular dependency later ? "qtquickcontrols" => "", 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 0def76d6f..1c5461fa7 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -31,6 +31,7 @@ #include <QScopedPointer> #include <QtCore/qelapsedtimer.h> +#include <QtGui/qpa/qwindowsysteminterface.h> #include <QtQml/QQmlEngine> #include <QtTest/QtTest> #include <private/qquickwebengineview_p.h> @@ -71,6 +72,9 @@ private Q_SLOTS: void basicRenderingSanity(); void setZoomFactor(); void printToPdf(); + void stopSettingFocusWhenDisabled(); + void stopSettingFocusWhenDisabled_data(); + void inputEventForwardingDisabledWhenActiveFocusOnPressDisabled(); private: inline QQuickWebEngineView *newWebEngineView(); @@ -514,5 +518,139 @@ void tst_QQuickWebEngineView::printToPdf() QVERIFY(!QFile::exists(path)); } +void tst_QQuickWebEngineView::stopSettingFocusWhenDisabled() +{ + QFETCH(bool, viewEnabled); + QFETCH(bool, activeFocusResult); + + QQuickWebEngineView *view = webEngineView(); + m_window->show(); + view->setSize(QSizeF(640, 480)); + view->setEnabled(viewEnabled); + view->loadHtml("<html><head><title>Title</title></head><body>Hello" + "<input id=\"input\" type=\"text\"></body></html>"); + QVERIFY(waitForLoadSucceeded(view)); + + // When enabled, the view should get active focus after the page is loaded. + QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), activeFocusResult, 1000); + view->runJavaScript("document.getElementById(\"input\").focus()"); + QTRY_COMPARE_WITH_TIMEOUT(view->hasActiveFocus(), activeFocusResult, 1000); +} + +void tst_QQuickWebEngineView::stopSettingFocusWhenDisabled_data() +{ + QTest::addColumn<bool>("viewEnabled"); + QTest::addColumn<bool>("activeFocusResult"); + + QTest::newRow("enabled view gets active focus") << true << true; + 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("<html><head>" + "<script>" + "window.onload = function() { document.getElementById(\"input\").focus(); }" + "</script>" + "<title>Title</title></head><body>Hello" + "<input id=\"input\" type=\"text\"></body></html>"); + 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" diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index df290babf..d717c6c8a 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -203,9 +203,6 @@ private Q_SLOTS: void progressSignal(); void urlChange(); void requestedUrlAfterSetAndLoadFailures(); - void javaScriptWindowObjectCleared_data(); - void javaScriptWindowObjectCleared(); - void javaScriptWindowObjectClearedOnEvaluate(); void asyncAndDelete(); void earlyToHtml(); void setHtml(); @@ -3921,48 +3918,6 @@ void tst_QWebEnginePage::requestedUrlAfterSetAndLoadFailures() QVERIFY(!spy.at(1).first().toBool()); } -void tst_QWebEnginePage::javaScriptWindowObjectCleared_data() -{ - QTest::addColumn<QString>("html"); - QTest::addColumn<int>("signalCount"); - QTest::newRow("with <script>") << "<html><body><script>i=0</script><p>hello world</p></body></html>" << 1; - // NOTE: Empty scripts no longer cause this signal to be emitted. - QTest::newRow("with empty <script>") << "<html><body><script></script><p>hello world</p></body></html>" << 0; - QTest::newRow("without <script>") << "<html><body><p>hello world</p></body></html>" << 0; -} - -void tst_QWebEnginePage::javaScriptWindowObjectCleared() -{ -#if !defined(QWEBENGINEPAGE_JAVASCRIPTWINDOWOBJECTCLEARED) - QSKIP("QWEBENGINEPAGE_JAVASCRIPTWINDOWOBJECTCLEARED"); -#else - QWebEnginePage page; - QSignalSpy spy(&page, SIGNAL(javaScriptWindowObjectCleared())); - QFETCH(QString, html); - page.setHtml(html); - - QFETCH(int, signalCount); - QCOMPARE(spy.count(), signalCount); -#endif -} - -void tst_QWebEnginePage::javaScriptWindowObjectClearedOnEvaluate() -{ -#if !defined(QWEBENGINEPAGE_EVALUATEJAVASCRIPT) - QSKIP("QWEBENGINEPAGE_EVALUATEJAVASCRIPT"); -#else - QWebEnginePage page; - QSignalSpy spy(&page, SIGNAL(javaScriptWindowObjectCleared())); - page.setHtml("<html></html>"); - QCOMPARE(spy.count(), 0); - page.evaluateJavaScript("var a = 'a';"); - QCOMPARE(spy.count(), 1); - // no new clear for a new script: - page.evaluateJavaScript("var a = 1;"); - QCOMPARE(spy.count(), 1); -#endif -} - void tst_QWebEnginePage::asyncAndDelete() { QWebEnginePage *page = new QWebEnginePage; diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 8aaf9ccc3..afb53ba20 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -29,11 +29,20 @@ #include <qwebenginesettings.h> #include <qnetworkrequest.h> #include <qdiriterator.h> +#include <qstackedlayout.h> #include <qtemporarydir.h> #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 @@ -61,6 +70,10 @@ private Q_SLOTS: void setPalette_data(); void setPalette(); #endif + void doNotSendMouseKeyboardEventsWhenDisabled(); + void doNotSendMouseKeyboardEventsWhenDisabled_data(); + void stopSettingFocusWhenDisabled(); + void stopSettingFocusWhenDisabled_data(); }; // This will be called before the first test function is executed. @@ -591,5 +604,144 @@ 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<QString> 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("<html><head><title>Title</title></head><body>Hello" + "<input id=\"input\" type=\"text\"></body></html>"); + 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<bool>("viewEnabled"); + QTest::addColumn<int>("resultEventCount"); + + QTest::newRow("enabled view receives events") << true << 0; + 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("<html><head><title>Title</title></head><body>Hello" + "<input id=\"input\" type=\"text\"></body></html>"); + 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<bool>("viewEnabled"); + QTest::addColumn<bool>("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" diff --git a/tools/buildscripts/find-included-moc-files b/tools/buildscripts/find-included-moc-files index e55f3824c..678b2d6f5 100755 --- a/tools/buildscripts/find-included-moc-files +++ b/tools/buildscripts/find-included-moc-files @@ -3,7 +3,9 @@ import re, sys, os includedMocs = set() -for f in filter(os.path.isfile, sys.argv[1:]): +dir = sys.argv[1] +files = sys.argv[2:] +for f in filter(os.path.isfile, [os.path.join(dir, f) for f in files]): inBlockComment = False for line in open(f).readlines(): m = re.search('#include "(moc_\w+.cpp)"', line) diff --git a/tools/buildscripts/find-mocables b/tools/buildscripts/find-mocables index 7c383cfec..4bfa311b5 100755 --- a/tools/buildscripts/find-mocables +++ b/tools/buildscripts/find-mocables @@ -3,7 +3,9 @@ import re, sys, os mocables = set() -for f in filter(os.path.isfile, sys.argv[1:]): +dir = sys.argv[1] +files = sys.argv[2:] +for f in filter(os.path.isfile, [os.path.join(dir, f) for f in files]): inBlockComment = False for line in open(f).readlines(): # Block comments handling diff --git a/tools/qmake/mkspecs/features/configure.prf b/tools/qmake/mkspecs/features/configure.prf index 8c58b8e3f..7ef4b8545 100644 --- a/tools/qmake/mkspecs/features/configure.prf +++ b/tools/qmake/mkspecs/features/configure.prf @@ -117,6 +117,11 @@ defineTest(finalizeConfigure) { } else { log("Proprietary codecs (H264, MP3).... Not enabled (Default, enable with WEBENGINE_CONFIG+=use_proprietary_codecs)$${EOL}") } + qtHaveModule(positioning): { + log("Geolocation....................... Enabled$${EOL}") + } else { + log("Geolocation....................... Not enabled (Requires Qt Positioning module)$${EOL}") + } osx { use?(appstore_compliant_code) { log("AppStore Compliant ............... Enabled$${EOL}") diff --git a/tools/qmake/mkspecs/features/functions.prf b/tools/qmake/mkspecs/features/functions.prf index 26db26f44..9e8886e86 100644 --- a/tools/qmake/mkspecs/features/functions.prf +++ b/tools/qmake/mkspecs/features/functions.prf @@ -149,19 +149,13 @@ defineReplace(extractCFlag) { } defineReplace(findMocables) { - input = $$1 - for (file, input): \ - infiles += $$absolute_path($$file, $$_PRO_FILE_PWD_) - mocables = $$system("python $$QTWEBENGINE_ROOT/tools/buildscripts/find-mocables $$infiles") - mocables = $$replace(mocables, $$re_escape($${_PRO_FILE_PWD_}/), '') + mocables = $$system("$$system_path(python $$QTWEBENGINE_ROOT/tools/buildscripts/find-mocables $$_PRO_FILE_PWD_ $$1)") + mocables = $$replace(mocables, $$re_escape($$system_path($${_PRO_FILE_PWD_}/)), '') return($$mocables) } defineReplace(findIncludedMocFiles) { - input = $$1 - for (file, input): \ - infiles += $$absolute_path($$file, $$_PRO_FILE_PWD_) - return($$system("python $$QTWEBENGINE_ROOT/tools/buildscripts/find-included-moc-files $$infiles")) + return($$system("$$system_path(python $$QTWEBENGINE_ROOT/tools/buildscripts/find-included-moc-files $$_PRO_FILE_PWD_ $$1)")) } defineReplace(mocOutput) { |