WebKit Bugzilla
Attachment 358693 Details for
Bug 191464
: [WPE] Add Qt extension
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-191464-20190109123421.patch (text/plain), 98.14 KB, created by
Philippe Normand
on 2019-01-09 04:34:22 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Philippe Normand
Created:
2019-01-09 04:34:22 PST
Size:
98.14 KB
patch
obsolete
>Subversion Revision: 239767 >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index dcb7b352f602fa2f9f09bd4d8cb70fc7f7e3fa27..f31779816c259b61b91bf26db17da9c1e0053ea1 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,94 @@ >+2019-01-09 Philippe Normand <pnormand@igalia.com> >+ >+ [WPE] Add Qt extension >+ https://bugs.webkit.org/show_bug.cgi?id=191464 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This new extension is a QML plugin embedding a WPE ViewBackend >+ implementation. It provides a public API very similar to Qt's >+ WebView module. It comes with a simple mini-browser implemented in >+ QML. >+ >+ QtWPE is known to work with the Wayland-EGL (in GNOME and Weston >+ compositors) and EGLFS QPAs. >+ >+ * PlatformWPE.cmake: >+ * UIProcess/API/wpe/qt/WPEQmlExtensionPlugin.cpp: Added. >+ (WPEQmlExtensionPlugin::registerTypes): >+ * UIProcess/API/wpe/qt/WPEQmlExtensionPlugin.h: Added. >+ * UIProcess/API/wpe/qt/WPEQtView.cpp: Added. >+ (WPEQtView::WPEQtView): >+ (WPEQtView::~WPEQtView): >+ (WPEQtView::geometryChanged): >+ (WPEQtView::configureWindow): >+ (WPEQtView::createOffscreen): >+ (WPEQtView::backendCreated): >+ (WPEQtView::notifyUrlChangedCallback): >+ (WPEQtView::notifyTitleChangedCallback): >+ (WPEQtView::notifyLoadProgressCallback): >+ (WPEQtView::notifyLoadChangedCallback): >+ (WPEQtView::notifyLoadFailedCallback): >+ (WPEQtView::updatePaintNode): >+ (WPEQtView::url const): >+ (WPEQtView::setUrl): >+ (WPEQtView::loadProgress const): >+ (WPEQtView::title const): >+ (WPEQtView::canGoBack const): >+ (WPEQtView::isLoading const): >+ (WPEQtView::canGoForward const): >+ (WPEQtView::goBack): >+ (WPEQtView::goForward): >+ (WPEQtView::reload): >+ (WPEQtView::stop): >+ (WPEQtView::loadHtml): >+ (WPEQtView::jsAsyncReadyCallback): >+ (WPEQtView::handleJsResult): >+ (WPEQtView::runJavaScript): >+ (WPEQtView::mousePressEvent): >+ (WPEQtView::mouseReleaseEvent): >+ (WPEQtView::hoverEnterEvent): >+ (WPEQtView::hoverLeaveEvent): >+ (WPEQtView::hoverMoveEvent): >+ (WPEQtView::wheelEvent): >+ (WPEQtView::keyPressEvent): >+ (WPEQtView::keyReleaseEvent): >+ (WPEQtView::touchEvent): >+ * UIProcess/API/wpe/qt/WPEQtView.h: Added. >+ * UIProcess/API/wpe/qt/WPEQtViewBackend.cpp: Added. >+ (configureCallback): >+ (WPEQtViewBackend::WPEQtViewBackend): >+ (WPEQtViewBackend::~WPEQtViewBackend): >+ (WPEQtViewBackend::configureGlibEglDisplay): >+ (WPEQtViewBackend::configureEglDisplay): >+ (WPEQtViewBackend::initialize): >+ (WPEQtViewBackend::backend const): >+ (WPEQtViewBackend::resize): >+ (WPEQtViewBackend::getTexture): >+ (WPEQtViewBackend::initSurface): >+ (WPEQtViewBackend::displayImage): >+ (WPEQtViewBackend::modifiers const): >+ (WPEQtViewBackend::dispatchHoverEnterEvent): >+ (WPEQtViewBackend::dispatchHoverLeaveEvent): >+ (WPEQtViewBackend::dispatchHoverMoveEvent): >+ (WPEQtViewBackend::dispatchMousePressEvent): >+ (WPEQtViewBackend::dispatchMouseReleaseEvent): >+ (WPEQtViewBackend::dispatchWheelEvent): >+ (WPEQtViewBackend::dispatchKeyEvent): >+ (WPEQtViewBackend::dispatchTouchEvent): >+ * UIProcess/API/wpe/qt/WPEQtViewBackend.h: Added. >+ * UIProcess/API/wpe/qt/WPEQtViewLoadRequest.cpp: Added. >+ (WPEQtViewLoadRequest::WPEQtViewLoadRequest): >+ (WPEQtViewLoadRequest::~WPEQtViewLoadRequest): >+ (WPEQtViewLoadRequest::url const): >+ (WPEQtViewLoadRequest::status const): >+ (WPEQtViewLoadRequest::errorString const): >+ * UIProcess/API/wpe/qt/WPEQtViewLoadRequest.h: Added. >+ * UIProcess/API/wpe/qt/WPEQtViewLoadRequestPrivate.h: Added. >+ (WPEQtViewLoadRequestPrivate::WPEQtViewLoadRequestPrivate): >+ (WPEQtViewLoadRequestPrivate::~WPEQtViewLoadRequestPrivate): >+ * UIProcess/API/wpe/qt/qmldir: Added. >+ > 2019-01-08 Alex Christensen <achristensen@webkit.org> > > Fix CompletionHandler assertions introduced today. >diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake >index 1f675c44e4c7459c005dd6781adb762a56a7ac37..a3e6351cafd993a6049cce67dc105131304335d9 100644 >--- a/Source/WebKit/PlatformWPE.cmake >+++ b/Source/WebKit/PlatformWPE.cmake >@@ -1,4 +1,5 @@ > include(InspectorGResources.cmake) >+include(GNUInstallDirs) > > set(WebKit_OUTPUT_NAME WPEWebKit-${WPE_API_VERSION}) > set(WebKit_WebProcess_OUTPUT_NAME WPEWebProcess) >@@ -316,22 +317,6 @@ target_link_libraries(WPEInjectedBundle WebKit) > target_include_directories(WPEInjectedBundle PRIVATE ${WebKit_INCLUDE_DIRECTORIES}) > target_include_directories(WPEInjectedBundle SYSTEM PRIVATE ${WebKit_SYSTEM_INCLUDE_DIRECTORIES}) > >-install(TARGETS WPEInjectedBundle >- DESTINATION "${LIB_INSTALL_DIR}/wpe-webkit-${WPE_API_VERSION}/injected-bundle" >-) >- >-install(FILES "${CMAKE_BINARY_DIR}/wpe-webkit-${WPE_API_VERSION}.pc" >- "${CMAKE_BINARY_DIR}/wpe-web-extension-${WPE_API_VERSION}.pc" >- DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" >- COMPONENT "Development" >-) >- >-install(FILES ${WPE_API_INSTALLED_HEADERS} >- ${WPE_WEB_EXTENSION_API_INSTALLED_HEADERS} >- DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/wpe-webkit-${WPE_API_VERSION}/wpe" >- COMPONENT "Development" >-) >- > file(WRITE ${CMAKE_BINARY_DIR}/gtkdoc-wpe.cfg > "[wpe-${WPE_API_VERSION}]\n" > "pkgconfig_file=${WPE_PKGCONFIG_FILE}\n" >@@ -370,3 +355,69 @@ file(WRITE ${CMAKE_BINARY_DIR}/gtkdoc-webextensions.cfg > "headers=${WPE_WEB_EXTENSION_API_INSTALLED_HEADERS}\n" > "main_sgml_file=wpe-webextensions-docs.sgml\n" > ) >+ >+ >+set(qtwpe_SOURCES >+ ${WEBKIT_DIR}/UIProcess/API/wpe/qt/WPEQtViewBackend.cpp >+ ${WEBKIT_DIR}/UIProcess/API/wpe/qt/WPEQmlExtensionPlugin.cpp >+ ${WEBKIT_DIR}/UIProcess/API/wpe/qt/WPEQtView.cpp >+ ${WEBKIT_DIR}/UIProcess/API/wpe/qt/WPEQtViewLoadRequest.cpp >+) >+ >+if (ENABLE_WPE_QT_API) >+ set(qtwpe_LIBRARIES >+ Qt5::Core Qt5::Quick >+ WebKit >+ ${LIBEPOXY_LIBRARIES} >+ ${WPE_BACKEND_FDO_LIBRARIES} >+ ) >+ >+ set(qtwpe_INCLUDE_DIRECTORIES >+ ${Qt5_INCLUDE_DIRS} >+ ${Qt5Gui_PRIVATE_INCLUDE_DIRS} >+ ${LIBEPOXY_INCLUDE_DIRS} >+ ${WPE_BACKEND_FDO_INCLUDE_DIRS} >+ ) >+ >+ list(APPEND WPE_API_INSTALLED_HEADERS >+ ${WEBKIT_DIR}/UIProcess/API/wpe/qt/WPEQtView.h >+ ${WEBKIT_DIR}/UIProcess/API/wpe/qt/WPEQtViewLoadRequest.h >+ ) >+ >+ add_library(qtwpe SHARED ${qtwpe_SOURCES}) >+ set_target_properties(qtwpe PROPERTIES >+ OUTPUT_NAME qtwpe >+ AUTOMOC ON >+ CXX_STANDARD 14 >+ ) >+ target_compile_definitions(qtwpe PUBLIC QT_NO_KEYWORDS=1) >+ target_link_libraries(qtwpe ${qtwpe_LIBRARIES}) >+ target_include_directories(qtwpe SYSTEM PRIVATE ${qtwpe_INCLUDE_DIRECTORIES}) >+ install(TARGETS qtwpe DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/qml/org/wpewebkit/qtwpe/") >+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/qmldir DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/qml/org/wpewebkit/qtwpe/") >+ >+ file(MAKE_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/qml/org/wpewebkit/qtwpe) >+ add_custom_command(TARGET qtwpe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy >+ ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/libqtwpe.so >+ ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/qml/org/wpewebkit/qtwpe) >+ add_custom_command(TARGET qtwpe POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy >+ ${WEBKIT_DIR}/UIProcess/API/wpe/qt/qmldir >+ ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/qml/org/wpewebkit/qtwpe) >+endif () >+ >+ >+install(TARGETS WPEInjectedBundle >+ DESTINATION "${LIB_INSTALL_DIR}/wpe-webkit-${WPE_API_VERSION}/injected-bundle" >+) >+ >+install(FILES "${CMAKE_BINARY_DIR}/wpe-webkit-${WPE_API_VERSION}.pc" >+ "${CMAKE_BINARY_DIR}/wpe-web-extension-${WPE_API_VERSION}.pc" >+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" >+ COMPONENT "Development" >+) >+ >+install(FILES ${WPE_API_INSTALLED_HEADERS} >+ ${WPE_WEB_EXTENSION_API_INSTALLED_HEADERS} >+ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/wpe-webkit-${WPE_API_VERSION}/wpe" >+ COMPONENT "Development" >+) >diff --git a/Source/WebKit/UIProcess/API/wpe/qt/WPEQmlExtensionPlugin.cpp b/Source/WebKit/UIProcess/API/wpe/qt/WPEQmlExtensionPlugin.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..bceb904fdaa9edccb09c863408f01ad9c9260a11 >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/qt/WPEQmlExtensionPlugin.cpp >@@ -0,0 +1,36 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L >+ * Copyright (C) 2018, 2019 Zodiac Inflight Innovations >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include "config.h" >+#include "WPEQmlExtensionPlugin.h" >+ >+#include "WPEQtView.h" >+#include "WPEQtViewLoadRequest.h" >+ >+#include <qqml.h> >+ >+void WPEQmlExtensionPlugin::registerTypes(const char* uri) >+{ >+ // @uri org.wpewebkit.qtwpe >+ qmlRegisterType<WPEQtView>(uri, 1, 0, "WPEView"); >+ >+ const QString& msg = QObject::tr("Cannot create separate instance of WPEQtViewLoadRequest"); >+ qmlRegisterUncreatableType<WPEQtViewLoadRequest>(uri, 1, 0, "WPEViewLoadRequest", msg); >+} >diff --git a/Source/WebKit/UIProcess/API/wpe/qt/WPEQmlExtensionPlugin.h b/Source/WebKit/UIProcess/API/wpe/qt/WPEQmlExtensionPlugin.h >new file mode 100644 >index 0000000000000000000000000000000000000000..5fd6fd64249a2798a17f011820b8bc7e65f75e7e >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/qt/WPEQmlExtensionPlugin.h >@@ -0,0 +1,31 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L >+ * Copyright (C) 2018, 2019 Zodiac Inflight Innovations >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#pragma once >+ >+#include <QQmlExtensionPlugin> >+ >+class WPEQmlExtensionPlugin : public QQmlExtensionPlugin { >+ Q_OBJECT >+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) >+ >+public: >+ void registerTypes(const char* uri); >+}; >diff --git a/Source/WebKit/UIProcess/API/wpe/qt/WPEQtView.cpp b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtView.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..8c558d9970cf46df4fb631d1bee7eb23d548c6f4 >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtView.cpp >@@ -0,0 +1,496 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L >+ * Copyright (C) 2018, 2019 Zodiac Inflight Innovations >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include "config.h" >+#include "WPEQtView.h" >+ >+#include "WPEQtViewLoadRequest.h" >+#include "WPEQtViewLoadRequestPrivate.h" >+ >+#include <QGuiApplication> >+#include <QQmlEngine> >+#include <QQuickWindow> >+#include <QSGSimpleTextureNode> >+#include <QScreen> >+#include <QtPlatformHeaders/QEGLNativeContext> >+#include <qpa/qplatformnativeinterface.h> >+ >+/*! >+ \qmltype WPEView >+ \inqmlmodule org.wpewebkit.qtwpe >+ \brief A component for displaying web content. >+ >+ WPEView is a component for displaying web content which is implemented using native >+ APIs on the platforms where this is available, thus it does not necessarily require >+ including a full web browser stack as part of the application. >+ >+ WPEView provides an API compatible with Qt's QtWebView component. However >+ WPEView is limited to Linux platforms supporting EGL KHR extensions. WPEView >+ was successfully tested with the EGLFS and Wayland-EGL QPAs. >+*/ >+WPEQtView::WPEQtView(QQuickItem* parent) >+ : QQuickItem(parent) >+ , m_backend(this) >+{ >+ connect(this, &QQuickItem::windowChanged, this, &WPEQtView::configureWindow); >+ setFlag(ItemHasContents, true); >+ setAcceptedMouseButtons(Qt::AllButtons); >+ setAcceptHoverEvents(true); >+ setAcceptTouchEvents(true); >+} >+ >+WPEQtView::~WPEQtView() >+{ >+ if (m_webView) >+ g_object_unref(m_webView); >+} >+ >+void WPEQtView::geometryChanged(const QRectF& newGeometry, const QRectF&) >+{ >+ m_backend.resize(newGeometry); >+} >+ >+void WPEQtView::configureWindow() >+{ >+ auto* win = window(); >+ if (!win) >+ return; >+ win->setSurfaceType(QWindow::OpenGLSurface); >+ connect(win, &QQuickWindow::sceneGraphInitialized, this, &WPEQtView::createOffscreen); >+} >+ >+void WPEQtView::createOffscreen() >+{ >+ if (!m_backend.hasValidSurface()) >+ m_backend.initSurface(window()->openglContext()); >+} >+ >+void WPEQtView::backendCreated() >+{ >+ struct wpe_view_backend* wpeBackend = m_backend.backend(); >+ RELEASE_ASSERT(wpeBackend); >+ >+ auto* settings = webkit_settings_new_with_settings("enable-developer-extras", TRUE, >+ "enable-webgl", TRUE, "enable-mediasource", TRUE, nullptr); >+ m_webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, >+ "backend", webkit_web_view_backend_new(wpeBackend, [](gpointer) { }, nullptr), >+ "settings", settings, nullptr)); >+ g_object_unref(settings); >+ >+ g_signal_connect_swapped(m_webView, "notify::uri", G_CALLBACK(notifyUrlChangedCallback), this); >+ g_signal_connect_swapped(m_webView, "notify::title", G_CALLBACK(notifyTitleChangedCallback), this); >+ g_signal_connect_swapped(m_webView, "notify::estimated-load-progress", G_CALLBACK(notifyLoadProgressCallback), this); >+ g_signal_connect(m_webView, "load-changed", G_CALLBACK(notifyLoadChangedCallback), this); >+ g_signal_connect(m_webView, "load-failed", G_CALLBACK(notifyLoadFailedCallback), this); >+ >+ if (!m_url.isEmpty()) >+ webkit_web_view_load_uri(m_webView, m_url.toString().toUtf8().constData()); >+ else if (!m_html.isEmpty()) >+ webkit_web_view_load_html(m_webView, m_html.toUtf8().constData(), m_baseUrl.toString().toUtf8().constData()); >+ >+ Q_EMIT webViewCreated(); >+} >+ >+void WPEQtView::notifyUrlChangedCallback(WPEQtView* view) >+{ >+ Q_EMIT view->urlChanged(); >+} >+ >+void WPEQtView::notifyTitleChangedCallback(WPEQtView* view) >+{ >+ Q_EMIT view->titleChanged(); >+} >+ >+void WPEQtView::notifyLoadProgressCallback(WPEQtView* view) >+{ >+ Q_EMIT view->loadProgressChanged(); >+} >+ >+void WPEQtView::notifyLoadChangedCallback(WebKitWebView*, WebKitLoadEvent event, WPEQtView* view) >+{ >+ bool statusSet = false; >+ WPEQtView::LoadStatus loadStatus; >+ switch (event) { >+ case WEBKIT_LOAD_STARTED: >+ loadStatus = WPEQtView::LoadStatus::LoadStartedStatus; >+ statusSet = true; >+ break; >+ case WEBKIT_LOAD_FINISHED: >+ loadStatus = WPEQtView::LoadStatus::LoadSucceededStatus; >+ statusSet = true; >+ break; >+ default: >+ break; >+ } >+ >+ if (statusSet) { >+ WPEQtViewLoadRequestPrivate loadRequestPrivate(view->url(), loadStatus, ""); >+ std::unique_ptr<WPEQtViewLoadRequest> loadRequest = std::make_unique<WPEQtViewLoadRequest>(loadRequestPrivate); >+ Q_EMIT view->loadingChanged(loadRequest.get()); >+ } >+} >+ >+void WPEQtView::notifyLoadFailedCallback(WebKitWebView*, WebKitLoadEvent, const gchar* failingURI, GError* error, WPEQtView* view) >+{ >+ WPEQtView::LoadStatus loadStatus; >+ if (g_error_matches(error, WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED)) >+ loadStatus = WPEQtView::LoadStatus::LoadStoppedStatus; >+ else >+ loadStatus = WPEQtView::LoadStatus::LoadFailedStatus; >+ >+ WPEQtViewLoadRequestPrivate loadRequestPrivate(QUrl(QString(failingURI)), loadStatus, error->message); >+ std::unique_ptr<WPEQtViewLoadRequest> loadRequest = std::make_unique<WPEQtViewLoadRequest>(loadRequestPrivate); >+ Q_EMIT view->loadingChanged(loadRequest.get()); >+} >+ >+QSGNode* WPEQtView::updatePaintNode(QSGNode* node, UpdatePaintNodeData*) >+{ >+ if (!m_webView) { >+ QPlatformNativeInterface* native = QGuiApplication::platformNativeInterface(); >+ m_backend.configureGlibEglDisplay(window()->openglContext(), static_cast<EGLDisplay>(native->nativeResourceForIntegration("egldisplay"))); >+ return node; >+ } >+ >+ GLuint textureId = m_backend.getTexture(window()->openglContext()); >+ if (!textureId) >+ return node; >+ >+ QSGSimpleTextureNode* n = static_cast<QSGSimpleTextureNode*>(node); >+ if (!n) >+ n = new QSGSimpleTextureNode(); >+ >+ if (textureId > 0) { >+ QSize size(m_backend.size().width(), m_backend.size().height()); >+ n->setTexture(window()->createTextureFromId(textureId, size, QQuickWindow::TextureHasAlphaChannel)); >+ } >+ n->setRect(boundingRect()); >+ return n; >+} >+ >+QUrl WPEQtView::url() const >+{ >+ if (!m_webView) >+ return m_url; >+ >+ const gchar* uri = webkit_web_view_get_uri(m_webView); >+ return uri ? QUrl(QString(uri)) : m_url; >+} >+ >+/*! >+ \qmlproperty url WPEView::url >+ >+ The URL of currently loaded web page. Changing this will trigger >+ loading new content. >+ >+ The URL is used as-is. URLs that originate from user input should >+ be parsed with QUrl::fromUserInput(). >+ >+ \note The WPEView does not support loading content through the Qt Resource system. >+*/ >+void WPEQtView::setUrl(const QUrl& url) >+{ >+ if (url == m_url) >+ return; >+ >+ m_url = url; >+ if (m_webView) >+ webkit_web_view_load_uri(m_webView, m_url.toString().toUtf8().constData()); >+} >+ >+/*! >+ \qmlproperty int WPEView::loadProgress >+ \readonly >+ >+ The current load progress of the web content, represented as >+ an integer between 0 and 100. >+*/ >+int WPEQtView::loadProgress() const >+{ >+ if (!m_webView) >+ return 0; >+ >+ gdouble estimatedProgress; >+ g_object_get(m_webView, "estimated-load-progress", &estimatedProgress, nullptr); >+ return estimatedProgress * 100; >+} >+ >+/*! >+ \qmlproperty string WPEView::title >+ \readonly >+ >+ The title of the currently loaded web page. >+*/ >+QString WPEQtView::title() const >+{ >+ if (!m_webView) >+ return ""; >+ >+ return webkit_web_view_get_title(m_webView); >+} >+ >+/*! >+ \qmlproperty bool WPEView::canGoBack >+ \readonly >+ >+ Holds \c true if it's currently possible to navigate back in the web history. >+*/ >+bool WPEQtView::canGoBack() const >+{ >+ if (!m_webView) >+ return false; >+ >+ return webkit_web_view_can_go_back(m_webView); >+} >+ >+/*! >+ \qmlproperty bool WPEView::loading >+ \readonly >+ >+ Holds \c true if the WPEView is currently in the process of loading >+ new content, \c false otherwise. >+ >+ \sa loadingChanged() >+*/ >+ >+/*! >+ \qmlsignal WPEView::loadingChanged(WPEViewLoadRequest loadRequest) >+ >+ This signal is emitted when the state of loading the web content changes. >+ By handling this signal it's possible, for example, to react to page load >+ errors. >+ >+ The \a loadRequest parameter holds the \e url and \e status of the request, >+ as well as an \e errorString containing an error message for a failed >+ request. >+ >+ \sa WPEViewLoadRequest >+*/ >+bool WPEQtView::isLoading() const >+{ >+ if (!m_webView) >+ return false; >+ >+ gboolean isLoading = false; >+ g_object_get(m_webView, "is-loading", &isLoading, nullptr); >+ return isLoading; >+} >+ >+/*! >+ \qmlproperty bool WPEView::canGoForward >+ \readonly >+ >+ Holds \c true if it's currently possible to navigate forward in the web history. >+*/ >+bool WPEQtView::canGoForward() const >+{ >+ if (!m_webView) >+ return false; >+ >+ return webkit_web_view_can_go_forward(m_webView); >+} >+ >+/*! >+ \qmlmethod void WPEView::goBack() >+ >+ Navigates back in the web history. >+*/ >+void WPEQtView::goBack() >+{ >+ if (m_webView) >+ webkit_web_view_go_back(m_webView); >+} >+ >+/*! >+ \qmlmethod void WPEView::goForward() >+ >+ Navigates forward in the web history. >+*/ >+void WPEQtView::goForward() >+{ >+ if (m_webView) >+ webkit_web_view_go_forward(m_webView); >+} >+ >+/*! >+ \qmlmethod void WPEView::reload() >+ >+ Reloads the current \l url. >+*/ >+void WPEQtView::reload() >+{ >+ if (m_webView) >+ webkit_web_view_reload(m_webView); >+} >+ >+/*! >+ \qmlmethod void WPEView::stop() >+ >+ Stops loading the current \l url. >+*/ >+void WPEQtView::stop() >+{ >+ if (m_webView) >+ webkit_web_view_stop_loading(m_webView); >+} >+ >+/*! >+ \qmlmethod void WPEView::loadHtml(string html, url baseUrl) >+ >+ Loads the specified \a html content to the web view. >+ >+ This method offers a lower-level alternative to the \l url property, >+ which references HTML pages via URL. >+ >+ External objects such as stylesheets or images referenced in the HTML >+ document should be located relative to \a baseUrl. For example, if \a html >+ is retrieved from \c http://www.example.com/documents/overview.html, which >+ is the base URL, then an image referenced with the relative url, \c diagram.png, >+ should be at \c{http://www.example.com/documents/diagram.png}. >+ >+ \note The WPEView does not support loading content through the Qt Resource system. >+ >+ \sa url >+*/ >+void WPEQtView::loadHtml(const QString& html, const QUrl& baseUrl) >+{ >+ m_html = html; >+ m_baseUrl = baseUrl; >+ >+ if (m_webView) >+ webkit_web_view_load_html(m_webView, html.toUtf8().constData(), baseUrl.toString().toUtf8().constData()); >+} >+ >+void WPEQtView::jsAsyncReadyCallback(GObject* object, GAsyncResult* result, gpointer userData) >+{ >+ WebKitJavascriptResult* jsResult; >+ GError* error = nullptr; >+ >+ jsResult = webkit_web_view_run_javascript_finish(WEBKIT_WEB_VIEW(object), result, &error); >+ if (!jsResult) { >+ qWarning("Error running javascript: %s", error->message); >+ g_error_free(error); >+ return; >+ } >+ >+ WPEQtView* view = reinterpret_cast<WPEQtView*>(userData); >+ view->handleJsResult(jsResult); >+} >+ >+void WPEQtView::handleJsResult(WebKitJavascriptResult* jsResult) >+{ >+ QQmlEngine* engine = qmlEngine(this); >+ if (!engine) { >+ qWarning("No JavaScript engine, unable to handle JavaScript callback!"); >+ webkit_javascript_result_unref(jsResult); >+ return; >+ } >+ >+ JSCValue* value = webkit_javascript_result_get_js_value(jsResult); >+ QJSValueList args; >+ QVariant variant; >+ // TODO: Handle more value types? >+ if (jsc_value_is_string(value)) { >+ JSCException* exception; >+ gchar* str_value = jsc_value_to_string(value); >+ JSCContext* context = jsc_value_get_context(value); >+ exception = jsc_context_get_exception(context); >+ if (exception) { >+ qWarning("Error running javascript: %s", jsc_exception_get_message(exception)); >+ jsc_context_clear_exception(context); >+ } else >+ variant.setValue(QString(g_strdup(str_value))); >+ g_free(str_value); >+ } >+ args.append(engine->toScriptValue(variant)); >+ m_jsCallback.call(args); >+ webkit_javascript_result_unref(jsResult); >+} >+ >+/*! >+ \qmlmethod void WPEView::runJavaScript(string script, variant callback) >+ >+ Runs the specified JavaScript. >+ In case a \a callback function is provided, it will be invoked after the \a script >+ finished running. >+ >+ \badcode >+ runJavaScript("document.title", function(result) { console.log(result); }); >+ \endcode >+*/ >+void WPEQtView::runJavaScript(const QString& script, const QJSValue& callback) >+{ >+ m_jsCallback = callback; >+ webkit_web_view_run_javascript(m_webView, script.toUtf8().constData(), nullptr, jsAsyncReadyCallback, this); >+} >+ >+void WPEQtView::mousePressEvent(QMouseEvent* event) >+{ >+ forceActiveFocus(); >+ if (m_webView) >+ m_backend.dispatchMousePressEvent(event); >+} >+ >+void WPEQtView::mouseReleaseEvent(QMouseEvent* event) >+{ >+ if (m_webView) >+ m_backend.dispatchMouseReleaseEvent(event); >+} >+ >+void WPEQtView::hoverEnterEvent(QHoverEvent* event) >+{ >+ if (m_webView) >+ m_backend.dispatchHoverEnterEvent(event); >+} >+ >+void WPEQtView::hoverLeaveEvent(QHoverEvent* event) >+{ >+ if (m_webView) >+ m_backend.dispatchHoverLeaveEvent(event); >+} >+ >+void WPEQtView::hoverMoveEvent(QHoverEvent* event) >+{ >+ if (m_webView) >+ m_backend.dispatchHoverMoveEvent(event); >+} >+ >+void WPEQtView::wheelEvent(QWheelEvent* event) >+{ >+ if (m_webView) >+ m_backend.dispatchWheelEvent(event); >+} >+ >+void WPEQtView::keyPressEvent(QKeyEvent* event) >+{ >+ if (m_webView) >+ m_backend.dispatchKeyEvent(event, true); >+} >+ >+void WPEQtView::keyReleaseEvent(QKeyEvent* event) >+{ >+ if (m_webView) >+ m_backend.dispatchKeyEvent(event, false); >+} >+ >+void WPEQtView::touchEvent(QTouchEvent* event) >+{ >+ if (m_webView) >+ m_backend.dispatchTouchEvent(event); >+} >diff --git a/Source/WebKit/UIProcess/API/wpe/qt/WPEQtView.h b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtView.h >new file mode 100644 >index 0000000000000000000000000000000000000000..f5b03b4be005966b9599fd1051187de3cf8a0b98 >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtView.h >@@ -0,0 +1,117 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L >+ * Copyright (C) 2018, 2019 Zodiac Inflight Innovations >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#pragma once >+ >+#include "WPEQtViewBackend.h" >+ >+#include <QQuickItem> >+#include <QUrl> >+#include <memory> >+#include <wpe/webkit.h> >+ >+class WPEQtViewLoadRequest; >+ >+class WPEQtView : public QQuickItem, public WPEQtViewBackendClient { >+ Q_OBJECT >+ Q_DISABLE_COPY(WPEQtView) >+ Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged) >+ Q_PROPERTY(bool loading READ isLoading NOTIFY loadingChanged) >+ Q_PROPERTY(int loadProgress READ loadProgress NOTIFY loadProgressChanged) >+ Q_PROPERTY(QString title READ title NOTIFY titleChanged) >+ Q_PROPERTY(bool canGoBack READ canGoBack NOTIFY loadingChanged) >+ Q_PROPERTY(bool canGoForward READ canGoForward NOTIFY loadingChanged) >+ Q_ENUMS(LoadStatus) >+ >+public: >+ enum LoadStatus { >+ LoadStartedStatus, >+ LoadStoppedStatus, >+ LoadSucceededStatus, >+ LoadFailedStatus >+ }; >+ >+ WPEQtView(QQuickItem* parent = nullptr); >+ ~WPEQtView(); >+ QSGNode* updatePaintNode(QSGNode*, UpdatePaintNodeData*) final; >+ >+ void triggerUpdate() final { QMetaObject::invokeMethod(this, "update"); }; >+ void backendCreated() final; >+ >+ QUrl url() const; >+ void setUrl(const QUrl&); >+ int loadProgress() const; >+ QString title() const; >+ bool canGoBack() const; >+ bool isLoading() const; >+ bool canGoForward() const; >+ >+public Q_SLOTS: >+ void goBack(); >+ void goForward(); >+ void reload(); >+ void stop(); >+ void loadHtml(const QString& html, const QUrl& baseUrl = QUrl()); >+ void runJavaScript(const QString& script, const QJSValue& callback = QJSValue()); >+ >+Q_SIGNALS: >+ void webViewCreated(); >+ void urlChanged(); >+ void titleChanged(); >+ void loadingChanged(WPEQtViewLoadRequest*); >+ void loadProgressChanged(); >+ >+protected: >+ void geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) override; >+ >+ void handleJsResult(WebKitJavascriptResult*); >+ >+ void hoverEnterEvent(QHoverEvent*) override; >+ void hoverLeaveEvent(QHoverEvent*) override; >+ void hoverMoveEvent(QHoverEvent*) override; >+ >+ void mousePressEvent(QMouseEvent*) override; >+ void mouseReleaseEvent(QMouseEvent*) override; >+ void wheelEvent(QWheelEvent*) override; >+ >+ void keyPressEvent(QKeyEvent*) override; >+ void keyReleaseEvent(QKeyEvent*) override; >+ >+ void touchEvent(QTouchEvent*) override; >+ >+private Q_SLOTS: >+ void createOffscreen(); >+ void configureWindow(); >+ >+private: >+ static void jsAsyncReadyCallback(GObject*, GAsyncResult*, gpointer); >+ static void notifyUrlChangedCallback(WPEQtView*); >+ static void notifyTitleChangedCallback(WPEQtView*); >+ static void notifyLoadProgressCallback(WPEQtView*); >+ static void notifyLoadChangedCallback(WebKitWebView*, WebKitLoadEvent, WPEQtView*); >+ static void notifyLoadFailedCallback(WebKitWebView*, WebKitLoadEvent, const gchar* failingURI, GError*, WPEQtView*); >+ >+ WebKitWebView* m_webView { nullptr }; >+ QUrl m_url; >+ QString m_html; >+ QUrl m_baseUrl; >+ WPEQtViewBackend m_backend; >+ QJSValue m_jsCallback { }; >+}; >diff --git a/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewBackend.cpp b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewBackend.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..4c79de0d7339be49d65f186471e15c8999689982 >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewBackend.cpp >@@ -0,0 +1,431 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L >+ * Copyright (C) 2018, 2019 Zodiac Inflight Innovations >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include "config.h" >+#include "WPEQtViewBackend.h" >+ >+#include <QGuiApplication> >+#include <QOpenGLFunctions> >+#include <QtDebug> >+#include <glib.h> >+ >+struct EGLConfigurationData { >+ QOpenGLContext* context; >+ EGLDisplay display; >+ WPEQtViewBackend* backend; >+}; >+ >+static gboolean configureCallback(gpointer data) >+{ >+ EGLConfigurationData* configData = reinterpret_cast<EGLConfigurationData*>(data); >+ >+ RELEASE_ASSERT(configData->backend); >+ configData->backend->configureEglDisplay(configData->context, configData->display); >+ return G_SOURCE_REMOVE; >+} >+ >+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC imageTargetTexture2DOES; >+ >+WPEQtViewBackend::WPEQtViewBackend(WPEQtViewBackendClient* client) >+ : m_lockedImage(EGL_NO_IMAGE_KHR) >+ , m_client(client) >+ , m_textureId(0) >+{ >+#if defined(WPE_BACKEND_CHECK_VERSION) && WPE_BACKEND_CHECK_VERSION(0, 2, 0) >+ wpe_loader_init("libWPEBackend-fdo-0.1.so"); >+#endif >+} >+ >+WPEQtViewBackend::~WPEQtViewBackend() >+{ >+ if (m_exportable) { >+ wpe_view_backend_exportable_fdo_destroy(m_exportable); >+ m_exportable = nullptr; >+ } >+ >+ if (m_eglContext) { >+ eglDestroyContext(m_eglDisplay, m_eglContext); >+ m_eglContext = nullptr; >+ } >+} >+ >+void WPEQtViewBackend::configureGlibEglDisplay(QOpenGLContext* context, EGLDisplay display) >+{ >+ EGLConfigurationData* configData = g_new0(EGLConfigurationData, 1); >+ configData->context = context; >+ configData->display = display; >+ configData->backend = this; >+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, configureCallback, configData, g_free); >+} >+ >+void WPEQtViewBackend::configureEglDisplay(QOpenGLContext* context, EGLDisplay display) >+{ >+ m_eglDisplay = display; >+ if (!initialize()) { >+ qWarning() << "EGL initialization failed"; >+ return; >+ } >+ >+ imageTargetTexture2DOES = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES")); >+ >+ { >+ static const char* vertexShaderSource = >+ "attribute vec2 pos;\n" >+ "attribute vec2 texture;\n" >+ "varying vec2 v_texture;\n" >+ "void main() {\n" >+ " v_texture = texture;\n" >+ " gl_Position = vec4(pos, 0, 1);\n" >+ "}\n"; >+ static const char* fragmentShaderSource = >+ "precision mediump float;\n" >+ "uniform sampler2D u_texture;\n" >+ "varying vec2 v_texture;\n" >+ "void main() {\n" >+ " gl_FragColor = texture2D(u_texture, v_texture);\n" >+ "}\n"; >+ >+ QOpenGLFunctions* f = context->functions(); >+ >+ GLuint vertexShader = f->glCreateShader(GL_VERTEX_SHADER); >+ f->glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr); >+ f->glCompileShader(vertexShader); >+ >+ GLuint fragmentShader = f->glCreateShader(GL_FRAGMENT_SHADER); >+ f->glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr); >+ f->glCompileShader(fragmentShader); >+ >+ m_program = f->glCreateProgram(); >+ f->glAttachShader(m_program, vertexShader); >+ f->glAttachShader(m_program, fragmentShader); >+ f->glLinkProgram(m_program); >+ >+ f->glBindAttribLocation(m_program, 0, "pos"); >+ f->glBindAttribLocation(m_program, 1, "texture"); >+ m_textureUniform = f->glGetUniformLocation(m_program, "u_texture"); >+ } >+ >+ m_client->backendCreated(); >+} >+ >+bool WPEQtViewBackend::initialize() >+{ >+ if (m_eglDisplay == EGL_NO_DISPLAY) >+ return false; >+ >+ eglInitialize(m_eglDisplay, nullptr, nullptr); >+ >+ if (!eglBindAPI(EGL_OPENGL_ES_API)) >+ return false; >+ >+ wpe_fdo_initialize_for_egl_display(m_eglDisplay); >+ >+ static const EGLint configAttributes[13] = { >+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT, >+ EGL_RED_SIZE, 1, >+ EGL_GREEN_SIZE, 1, >+ EGL_BLUE_SIZE, 1, >+ EGL_ALPHA_SIZE, 1, >+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, >+ EGL_NONE >+ }; >+ >+ { >+ EGLint count = 0; >+ if (!eglGetConfigs(m_eglDisplay, nullptr, 0, &count) || count < 1) >+ return false; >+ >+ EGLConfig* configs = g_new0(EGLConfig, count); >+ EGLint matched = 0; >+ if (eglChooseConfig(m_eglDisplay, configAttributes, configs, count, &matched) && !!matched) >+ m_eglConfig = configs[0]; >+ g_free(configs); >+ } >+ >+ static const EGLint contextAttributes[3] = { >+ EGL_CONTEXT_CLIENT_VERSION, 2, >+ EGL_NONE >+ }; >+ >+ m_eglContext = eglCreateContext(m_eglDisplay, m_eglConfig, nullptr, contextAttributes); >+ if (!m_eglContext) >+ return false; >+ >+ static struct wpe_view_backend_exportable_fdo_egl_client exportableClient = { >+ // export_buffer_resource >+ [](void* data, EGLImageKHR image) >+ { >+ static_cast<WPEQtViewBackend*>(data)->displayImage(image); >+ }, >+ // padding >+ nullptr, nullptr, nullptr, nullptr >+ }; >+ >+ m_exportable = wpe_view_backend_exportable_fdo_egl_create(&exportableClient, this, m_geometry.size().width(), m_geometry.size().height()); >+ >+#if defined(WPE_BACKEND_CHECK_VERSION) && WPE_BACKEND_CHECK_VERSION(1, 1, 0) >+ wpe_view_backend_add_activity_state(backend(), wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window); >+#endif >+ >+ return true; >+} >+ >+struct wpe_view_backend* WPEQtViewBackend::backend() const >+{ >+ return m_exportable ? wpe_view_backend_exportable_fdo_get_view_backend(m_exportable) : nullptr; >+} >+ >+void WPEQtViewBackend::resize(const QRectF& newGeometry) >+{ >+ if (!newGeometry.isValid()) >+ return; >+ >+ m_geometry = newGeometry; >+ >+ if (backend()) >+ wpe_view_backend_dispatch_set_size(backend(), m_geometry.size().width(), m_geometry.size().height()); >+} >+ >+GLuint WPEQtViewBackend::getTexture(QOpenGLContext* context) >+{ >+ if (!m_lockedImage || !hasValidSurface()) >+ return 0; >+ >+ context->makeCurrent(&m_surface); >+ >+ QOpenGLFunctions* f = context->functions(); >+ if (!m_textureId) { >+ f->glGenTextures(1, &m_textureId); >+ f->glBindTexture(GL_TEXTURE_2D, m_textureId); >+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); >+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); >+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); >+ f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); >+ f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_geometry.size().width(), m_geometry.size().height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); >+ f->glBindTexture(GL_TEXTURE_2D, 0); >+ } >+ >+ f->glClearColor(1, 0, 0, 1); >+ f->glClear(GL_COLOR_BUFFER_BIT); >+ >+ f->glUseProgram(m_program); >+ >+ f->glActiveTexture(GL_TEXTURE0); >+ f->glBindTexture(GL_TEXTURE_2D, m_textureId); >+ imageTargetTexture2DOES(GL_TEXTURE_2D, m_lockedImage); >+ f->glUniform1i(m_textureUniform, 0); >+ >+ static const GLfloat vertices[4][2] = { >+ { -1.0, 1.0 }, >+ { 1.0, 1.0 }, >+ { -1.0, -1.0 }, >+ { 1.0, -1.0 }, >+ }; >+ >+ static const GLfloat texturePos[4][2] = { >+ { 0, 0 }, >+ { 1, 0 }, >+ { 0, 1 }, >+ { 1, 1 }, >+ }; >+ >+ f->glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices); >+ f->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texturePos); >+ >+ f->glEnableVertexAttribArray(0); >+ f->glEnableVertexAttribArray(1); >+ >+ f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); >+ >+ f->glDisableVertexAttribArray(0); >+ f->glDisableVertexAttribArray(1); >+ >+ wpe_view_backend_exportable_fdo_dispatch_frame_complete(m_exportable); >+ wpe_view_backend_exportable_fdo_egl_dispatch_release_image(m_exportable, m_lockedImage); >+ m_lockedImage = EGL_NO_IMAGE_KHR; >+ >+ return m_textureId; >+} >+ >+void WPEQtViewBackend::initSurface(QOpenGLContext* context) >+{ >+ m_surface.setFormat(context->format()); >+ m_surface.create(); >+} >+ >+void WPEQtViewBackend::displayImage(EGLImageKHR image) >+{ >+ m_lockedImage = image; >+ m_client->triggerUpdate(); >+} >+ >+uint32_t WPEQtViewBackend::modifiers() const >+{ >+ uint32_t mask = m_keyboardModifiers; >+ if (m_mouseModifiers) >+ mask |= m_mouseModifiers; >+ return mask; >+} >+ >+void WPEQtViewBackend::dispatchHoverEnterEvent(QHoverEvent*) >+{ >+ m_hovering = true; >+ m_mouseModifiers = 0; >+} >+ >+void WPEQtViewBackend::dispatchHoverLeaveEvent(QHoverEvent*) >+{ >+ m_hovering = false; >+} >+ >+void WPEQtViewBackend::dispatchHoverMoveEvent(QHoverEvent* event) >+{ >+ if (!m_hovering) >+ return; >+ >+ uint32_t state = !!m_mousePressedButton; >+ struct wpe_input_pointer_event wpeEvent = { wpe_input_pointer_event_type_motion, >+ static_cast<uint32_t>(event->timestamp()), >+ event->pos().x(), event->pos().y(), >+ m_mousePressedButton, state, modifiers() }; >+ wpe_view_backend_dispatch_pointer_event(backend(), &wpeEvent); >+} >+ >+void WPEQtViewBackend::dispatchMousePressEvent(QMouseEvent* event) >+{ >+ uint32_t button = 0; >+ uint32_t modifier = 0; >+ switch (event->button()) { >+ case Qt::LeftButton: >+ button = 1; >+ modifier = wpe_input_pointer_modifier_button1; >+ break; >+ case Qt::RightButton: >+ button = 2; >+ modifier = wpe_input_pointer_modifier_button2; >+ break; >+ default: >+ break; >+ } >+ m_mousePressedButton = button; >+ uint32_t state = 1; >+ m_mouseModifiers |= modifier; >+ struct wpe_input_pointer_event wpeEvent = { wpe_input_pointer_event_type_button, >+ static_cast<uint32_t>(event->timestamp()), >+ event->x(), event->y(), button, state, modifiers() }; >+ wpe_view_backend_dispatch_pointer_event(backend(), &wpeEvent); >+} >+ >+void WPEQtViewBackend::dispatchMouseReleaseEvent(QMouseEvent* event) >+{ >+ uint32_t button = 0; >+ uint32_t modifier = 0; >+ switch (event->button()) { >+ case Qt::LeftButton: >+ button = 1; >+ modifier = wpe_input_pointer_modifier_button1; >+ break; >+ case Qt::RightButton: >+ button = 2; >+ modifier = wpe_input_pointer_modifier_button2; >+ break; >+ default: >+ break; >+ } >+ m_mousePressedButton = 0; >+ uint32_t state = 0; >+ m_mouseModifiers &= ~modifier; >+ struct wpe_input_pointer_event wpeEvent = { wpe_input_pointer_event_type_button, >+ static_cast<uint32_t>(event->timestamp()), >+ event->x(), event->y(), button, state, modifiers() }; >+ wpe_view_backend_dispatch_pointer_event(backend(), &wpeEvent); >+} >+ >+void WPEQtViewBackend::dispatchWheelEvent(QWheelEvent* event) >+{ >+ QPoint delta = event->angleDelta(); >+ uint32_t axis = delta.y() == event->y(); >+ QPoint numDegrees = delta / 8; >+ QPoint numSteps = numDegrees / 15; >+ int32_t length = numSteps.y() ? numSteps.y() : numSteps.x(); >+ struct wpe_input_axis_event wpeEvent = { wpe_input_axis_event_type_motion, >+ static_cast<uint32_t>(event->timestamp()), >+ event->x(), event->y(), axis, length, modifiers() }; >+ wpe_view_backend_dispatch_axis_event(backend(), &wpeEvent); >+} >+ >+void WPEQtViewBackend::dispatchKeyEvent(QKeyEvent* event, bool state) >+{ >+ uint32_t keysym = event->nativeVirtualKey(); >+ if (!keysym) >+ keysym = wpe_input_xkb_context_get_key_code(wpe_input_xkb_context_get_default(), event->key(), state); >+ >+ uint32_t modifiers = 0; >+ Qt::KeyboardModifiers qtModifiers = event->modifiers(); >+ if (!qtModifiers) >+ qtModifiers = QGuiApplication::keyboardModifiers(); >+ >+ if (qtModifiers & Qt::ShiftModifier) >+ modifiers |= wpe_input_keyboard_modifier_shift; >+ >+ if (qtModifiers & Qt::ControlModifier) >+ modifiers |= wpe_input_keyboard_modifier_control; >+ if (qtModifiers & Qt::MetaModifier) >+ modifiers |= wpe_input_keyboard_modifier_meta; >+ if (qtModifiers & Qt::AltModifier) >+ modifiers |= wpe_input_keyboard_modifier_alt; >+ >+ struct wpe_input_keyboard_event wpeEvent = { static_cast<uint32_t>(event->timestamp()), >+ keysym, event->nativeScanCode(), state, modifiers }; >+ wpe_view_backend_dispatch_keyboard_event(backend(), &wpeEvent); >+} >+ >+void WPEQtViewBackend::dispatchTouchEvent(QTouchEvent* event) >+{ >+ wpe_input_touch_event_type eventType; >+ switch (event->type()) { >+ case QEvent::TouchBegin: >+ eventType = wpe_input_touch_event_type_down; >+ break; >+ case QEvent::TouchUpdate: >+ eventType = wpe_input_touch_event_type_motion; >+ break; >+ case QEvent::TouchEnd: >+ eventType = wpe_input_touch_event_type_up; >+ break; >+ default: >+ eventType = wpe_input_touch_event_type_null; >+ break; >+ } >+ >+ int i = 0; >+ struct wpe_input_touch_event_raw* rawEvents = g_new0(wpe_input_touch_event_raw, event->touchPoints().length()); >+ for (auto& point : event->touchPoints()) { >+ rawEvents[i] = { eventType, static_cast<uint32_t>(event->timestamp()), >+ point.id(), static_cast<int32_t>(point.pos().x()), static_cast<int32_t>(point.pos().y()) }; >+ i++; >+ } >+ >+ struct wpe_input_touch_event wpeEvent = { rawEvents, static_cast<uint64_t>(i), eventType, >+ static_cast<int32_t>(rawEvents[0].id), >+ static_cast<uint32_t>(event->timestamp()), modifiers() }; >+ wpe_view_backend_dispatch_touch_event(backend(), &wpeEvent); >+ g_free(rawEvents); >+} >diff --git a/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewBackend.h b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewBackend.h >new file mode 100644 >index 0000000000000000000000000000000000000000..02508afcd9f2ca0aea5b392516d95f9133abd99b >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewBackend.h >@@ -0,0 +1,97 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L >+ * Copyright (C) 2018, 2019 Zodiac Inflight Innovations >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#pragma once >+ >+// This include order is necessary to enforce the GBM EGL platform. >+#include <gbm.h> >+#include <epoxy/egl.h> >+ >+#include <QHoverEvent> >+#include <QKeyEvent> >+#include <QMouseEvent> >+#include <QOffscreenSurface> >+#include <QOpenGLContext> >+#include <QWheelEvent> >+#include <wpe/fdo-egl.h> >+#include <wpe/fdo.h> >+ >+class WPEQtViewBackendClient { >+public: >+ virtual void triggerUpdate() = 0; >+ virtual void backendCreated() = 0; >+}; >+ >+class Q_DECL_EXPORT WPEQtViewBackend { >+public: >+ WPEQtViewBackend(WPEQtViewBackendClient*); >+ virtual ~WPEQtViewBackend(); >+ >+ void configureGlibEglDisplay(QOpenGLContext*, EGLDisplay); >+ void configureEglDisplay(QOpenGLContext*, EGLDisplay); >+ >+ QSizeF size() const { return m_geometry.size(); }; >+ void resize(const QRectF& newGeometry); >+ >+ GLuint getTexture(QOpenGLContext*); >+ void initSurface(QOpenGLContext*); >+ bool hasValidSurface() const { return m_surface.isValid(); }; >+ >+ void dispatchHoverEnterEvent(QHoverEvent*); >+ void dispatchHoverLeaveEvent(QHoverEvent*); >+ void dispatchHoverMoveEvent(QHoverEvent*); >+ >+ void dispatchMousePressEvent(QMouseEvent*); >+ void dispatchMouseReleaseEvent(QMouseEvent*); >+ void dispatchWheelEvent(QWheelEvent*); >+ >+ void dispatchKeyEvent(QKeyEvent*, bool state); >+ >+ void dispatchTouchEvent(QTouchEvent*); >+ >+ struct wpe_view_backend* backend() const; >+ >+ EGLContext eglContext() const { return m_eglContext; }; >+ >+private: >+ bool initialize(); >+ void displayImage(EGLImageKHR); >+ uint32_t modifiers() const; >+ >+ EGLDisplay m_eglDisplay { nullptr }; >+ EGLContext m_eglContext { nullptr }; >+ EGLConfig m_eglConfig; >+ struct wpe_view_backend_exportable_fdo* m_exportable { nullptr }; >+ >+ EGLImageKHR m_lockedImage; >+ >+ WPEQtViewBackendClient* m_client; >+ QOffscreenSurface m_surface; >+ QRectF m_geometry; >+ GLuint m_textureId { 0 }; >+ >+ unsigned m_program { 0 }; >+ unsigned m_textureUniform { 0 }; >+ >+ bool m_hovering { false }; >+ uint32_t m_mouseModifiers { 0 }; >+ uint32_t m_keyboardModifiers { 0 }; >+ uint32_t m_mousePressedButton { 0 }; >+}; >diff --git a/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewLoadRequest.cpp b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewLoadRequest.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..8f7713d950fff31c98f1de43f79a22b6f65d08bb >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewLoadRequest.cpp >@@ -0,0 +1,90 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L >+ * Copyright (C) 2018, 2019 Zodiac Inflight Innovations >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include "config.h" >+#include "WPEQtViewLoadRequest.h" >+ >+#include "WPEQtView.h" >+#include "WPEQtViewLoadRequestPrivate.h" >+ >+/*! >+ \qmltype WPEViewLoadRequest >+ \instantiates WPEQtViewLoadRequest >+ \inqmlmodule org.wpewebkit.qtwpe >+ >+ \brief A utility type for \l {WPEView}'s \l {WPEView::}{loadingChanged()} signal. >+ >+ The WPEViewLoadRequest type contains load status information for the requested URL. >+ >+ \sa {WPEView::loadingChanged()}{WPEView.loadingChanged()} >+*/ >+WPEQtViewLoadRequest::WPEQtViewLoadRequest(const WPEQtViewLoadRequestPrivate& d) >+ : d_ptr(new WPEQtViewLoadRequestPrivate(d)) >+{ >+ >+} >+ >+WPEQtViewLoadRequest::~WPEQtViewLoadRequest() >+{ >+ >+} >+ >+/*! >+ \qmlproperty url WPEView::WPEViewLoadRequest::url >+ \readonly >+ >+ The URL of the load request. >+*/ >+QUrl WPEQtViewLoadRequest::url() const >+{ >+ Q_D(const WPEQtViewLoadRequest); >+ return d->m_url; >+} >+ >+/*! >+ \qmlproperty enumeration WPEViewLoadRequest::status >+ \readonly >+ >+ This enumeration represents the load status of a web page load request. >+ >+ \value WPEView.LoadStartedStatus The page is currently loading. >+ \value WPEView.LoadStoppedStatus The page loading was interrupted. >+ \value WPEView.LoadSucceededStatus The page was loaded successfully. >+ \value WPEView.LoadFailedStatus The page could not be loaded. >+ >+ \sa {WPEView::loadingChanged()}{WPEView.loadingChanged} >+*/ >+WPEQtView::LoadStatus WPEQtViewLoadRequest::status() const >+{ >+ Q_D(const WPEQtViewLoadRequest); >+ return d->m_status; >+} >+ >+/*! >+ \qmlproperty string WPEView::WPEViewLoadRequest::errorString >+ \readonly >+ >+ Holds the error message if the load request failed. >+*/ >+QString WPEQtViewLoadRequest::errorString() const >+{ >+ Q_D(const WPEQtViewLoadRequest); >+ return d->m_errorString; >+} >diff --git a/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewLoadRequest.h b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewLoadRequest.h >new file mode 100644 >index 0000000000000000000000000000000000000000..aad0e067e6c8299f1565cd1d91d88b3bd1bae1da >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewLoadRequest.h >@@ -0,0 +1,50 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L >+ * Copyright (C) 2018, 2019 Zodiac Inflight Innovations >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#pragma once >+ >+#include "WPEQtView.h" >+ >+#include <QObject> >+ >+class WPEQtViewLoadRequestPrivate; >+ >+class WPEQtViewLoadRequest : public QObject { >+ Q_OBJECT >+ Q_PROPERTY(QUrl url READ url) >+ Q_PROPERTY(WPEQtView::LoadStatus status READ status) >+ Q_PROPERTY(QString errorString READ errorString) >+ >+public: >+ ~WPEQtViewLoadRequest(); >+ >+ QUrl url() const; >+ WPEQtView::LoadStatus status() const; >+ QString errorString() const; >+ >+ explicit WPEQtViewLoadRequest(const WPEQtViewLoadRequestPrivate&); >+ >+private: >+ friend class WPEQtView; >+ >+ Q_DECLARE_PRIVATE(WPEQtViewLoadRequest) >+ QScopedPointer<WPEQtViewLoadRequestPrivate> d_ptr; >+}; >+ >diff --git a/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewLoadRequestPrivate.h b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewLoadRequestPrivate.h >new file mode 100644 >index 0000000000000000000000000000000000000000..e8767710c571ac084cf553a624ec170c07b6ed7f >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/qt/WPEQtViewLoadRequestPrivate.h >@@ -0,0 +1,42 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L >+ * Copyright (C) 2018, 2019 Zodiac Inflight Innovations >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#pragma once >+ >+#include "WPEQtView.h" >+#include <QtCore/qstring.h> >+#include <QtCore/qurl.h> >+ >+class WPEQtViewLoadRequestPrivate { >+public: >+ WPEQtViewLoadRequestPrivate() { } >+ WPEQtViewLoadRequestPrivate(const QUrl& url, WPEQtView::LoadStatus status, const QString& errorString) >+ : m_url(url) >+ , m_status(status) >+ , m_errorString(errorString) >+ { } >+ ~WPEQtViewLoadRequestPrivate() { } >+ >+ QUrl m_url; >+ WPEQtView::LoadStatus m_status; >+ QString m_errorString; >+}; >+ >+Q_DECLARE_METATYPE(WPEQtViewLoadRequestPrivate) >diff --git a/Source/WebKit/UIProcess/API/wpe/qt/qmldir b/Source/WebKit/UIProcess/API/wpe/qt/qmldir >new file mode 100644 >index 0000000000000000000000000000000000000000..0d9300a97ca2b04b2ca99e2b0ff1e3b2c458dd0e >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/qt/qmldir >@@ -0,0 +1,2 @@ >+module org.wpewebkit.qtwpe >+plugin qtwpe >diff --git a/Source/cmake/OptionsWPE.cmake b/Source/cmake/OptionsWPE.cmake >index c7a259b99f54b77c9d5b0a1a6a1f63a91bb08f64..5f311b83c5ab98786f83b3ba50429374d0ab784d 100644 >--- a/Source/cmake/OptionsWPE.cmake >+++ b/Source/cmake/OptionsWPE.cmake >@@ -45,6 +45,7 @@ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_WEB_RTC PRIVATE ${ENABLE_EXPERIMENTAL_FE > # and the option is not relevant to any other WebKit ports. > WEBKIT_OPTION_DEFINE(ENABLE_GTKDOC "Whether or not to use generate gtkdoc." PUBLIC OFF) > WEBKIT_OPTION_DEFINE(USE_WOFF2 "Whether to enable support for WOFF2 Web Fonts." PUBLIC ON) >+WEBKIT_OPTION_DEFINE(ENABLE_WPE_QT_API "Whether to enable support for the Qt5/QML plugin" PUBLIC OFF) > > # Private options specific to the WPE port. > WEBKIT_OPTION_DEFINE(USE_OPENVR "Whether to use OpenVR as WebVR backend." PRIVATE ${ENABLE_EXPERIMENTAL_FEATURES}) >@@ -110,6 +111,13 @@ if (ENABLE_XSLT) > find_package(LibXslt 1.1.7 REQUIRED) > endif () > >+if (ENABLE_WPE_QT_API) >+ find_package(Qt5 REQUIRED COMPONENTS Core Quick Gui) >+ find_package(Qt5Test REQUIRED) >+ find_package(PkgConfig) >+ pkg_check_modules(WPE_BACKEND_FDO REQUIRED wpebackend-fdo-0.1) >+endif () >+ > add_definitions(-DBUILDING_WPE__=1) > add_definitions(-DGETTEXT_PACKAGE="WPE") > add_definitions(-DJSC_GLIB_API_ENABLED) >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 066feaa386c1fcb1d94d879df6f8e39174ff7492..53cd6e73c32aaa61327ea2ae16ac881d085ca2ad 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,68 @@ >+2019-01-09 Philippe Normand <pnormand@igalia.com> >+ >+ [WPE] Add Qt extension >+ https://bugs.webkit.org/show_bug.cgi?id=191464 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ MiniBrowser and API tests for the WPE Qt API. To run the >+ MiniBrowser a new script is introduced. Example invocation: >+ >+ $ run-qt-wpe-minibrowser -platform wayland https://webkit.org >+ >+ Also note-worthy is the introduction of the python2-subprocess32 >+ dependency to run the GLib API tests. >+ >+ * MiniBrowser/wpe/CMakeLists.txt: >+ * MiniBrowser/wpe/qt/CMakeLists.txt: Added. >+ * MiniBrowser/wpe/qt/main.cpp: Added. >+ (main): >+ * MiniBrowser/wpe/qt/main.qml: Added. >+ * MiniBrowser/wpe/qt/qml.qrc: Added. >+ * Scripts/run-gtk-tests: >+ (GtkTestRunner.is_google_test): >+ (GtkTestRunner): >+ (GtkTestRunner.is_qt_test): >+ * Scripts/run-qt-wpe-minibrowser: Added. >+ * Scripts/run-wpe-tests: >+ (WPETestRunner): >+ (WPETestRunner.is_google_test): >+ (WPETestRunner.is_qt_test): >+ * TestWebKitAPI/Tests/WPEQt/TestLoad.cpp: Added. >+ (TestLoad::main): >+ * TestWebKitAPI/Tests/WPEQt/TestLoadHtml.cpp: Added. >+ (TestLoadHtml::main): >+ * TestWebKitAPI/Tests/WPEQt/TestLoadRequest.cpp: Added. >+ (TestLoadRequest::main): >+ * TestWebKitAPI/Tests/WPEQt/TestRunJavaScript.cpp: Added. >+ (TestRunJavaScript::main): >+ * TestWebKitAPI/Tests/WPEQt/WPEQtTest.cpp: Added. >+ (waitForSignal): >+ * TestWebKitAPI/Tests/WPEQt/WPEQtTest.h: Added. >+ (LoadSpy::LoadSpy): >+ (LoadSpy::~LoadSpy): >+ (LoadSpy::onLoadingChanged): >+ (LoadStartedCatcher::LoadStartedCatcher): >+ (LoadStartedCatcher::~LoadStartedCatcher): >+ (LoadStartedCatcher::onLoadingChanged): >+ (waitForLoadSucceeded): >+ (waitForLoadFailed): >+ * TestWebKitAPI/glib/CMakeLists.txt: >+ * flatpak/flatpakutils.py: >+ (WebkitFlatpak.load_from_args): >+ (WebkitFlatpak.__init__): >+ (WebkitFlatpak.clean_args): >+ (WebkitFlatpak.run_in_sandbox): >+ * flatpak/org.webkit.CommonModules.yaml: >+ * flatpak/org.webkit.WPE.yaml: >+ * flatpak/org.webkit.WPEModules.yaml: >+ * flatpak/org.webkit.WPEQT.yaml: Copied from Tools/flatpak/org.webkit.WebKit.yaml. >+ * flatpak/org.webkit.WebKit.yaml: >+ * glib/api_test_runner.py: >+ (TestRunner._run_test_qt): >+ (TestRunner.is_qt_test): >+ (TestRunner._run_test): >+ > 2019-01-09 Philippe Normand <pnormand@igalia.com> > > [WPE] API tests can't run in flatpak environment >diff --git a/Tools/MiniBrowser/wpe/CMakeLists.txt b/Tools/MiniBrowser/wpe/CMakeLists.txt >index f261379683b43f5a7d7f4d968dc67ff456ab4137..74591ff508937e64be58e3425667e005dfa36a2a 100644 >--- a/Tools/MiniBrowser/wpe/CMakeLists.txt >+++ b/Tools/MiniBrowser/wpe/CMakeLists.txt >@@ -34,3 +34,7 @@ add_executable(MiniBrowser ${MiniBrowser_SOURCES}) > target_link_libraries(MiniBrowser ${MiniBrowser_LIBRARIES}) > > install(TARGETS MiniBrowser DESTINATION "${LIBEXEC_INSTALL_DIR}") >+ >+if (ENABLE_WPE_QT_API) >+ add_subdirectory(qt) >+endif () >diff --git a/Tools/MiniBrowser/wpe/qt/CMakeLists.txt b/Tools/MiniBrowser/wpe/qt/CMakeLists.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..518684358211d6a7263f89658effae8573e3303b >--- /dev/null >+++ b/Tools/MiniBrowser/wpe/qt/CMakeLists.txt >@@ -0,0 +1,13 @@ >+ >+if (ENABLE_WPE_QT_API) >+ set(CMAKE_AUTOMOC ON) >+ set(CMAKE_AUTORCC ON) >+ >+ if (DEVELOPER_MODE) >+ add_definitions(-DWEBKIT_INJECTED_BUNDLE_PATH="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") >+ endif () >+ >+ add_executable(qt-wpe-mini-browser "main.cpp" "qml.qrc") >+ target_link_libraries(qt-wpe-mini-browser Qt5::Core Qt5::Quick) >+ install(TARGETS qt-wpe-mini-browser DESTINATION "${LIBEXEC_INSTALL_DIR}") >+endif () >diff --git a/Tools/MiniBrowser/wpe/qt/main.cpp b/Tools/MiniBrowser/wpe/qt/main.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..050aedec6cd297fa2117c025279d976c88f26e7c >--- /dev/null >+++ b/Tools/MiniBrowser/wpe/qt/main.cpp >@@ -0,0 +1,58 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L >+ * Copyright (C) 2018, 2019 Zodiac Inflight Innovations >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Library General Public >+ * License as published by the Free Software Foundation; either >+ * version 2 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public >+ * License along with this library; if not, write to the >+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include <QCommandLineOption> >+#include <QCommandLineParser> >+#include <QGuiApplication> >+#include <QProcessEnvironment> >+#include <QQmlApplicationEngine> >+#include <QQmlContext> >+#include <QUrl> >+ >+int main(int argc, char* argv[]) >+{ >+#if defined(WEBKIT_INJECTED_BUNDLE_PATH) >+ setenv("WEBKIT_INJECTED_BUNDLE_PATH", WEBKIT_INJECTED_BUNDLE_PATH, 0); >+#endif >+ QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); >+ >+ QGuiApplication app(argc, argv); >+ >+ QCommandLineParser parser; >+ QCoreApplication::setApplicationVersion("0.1"); >+ parser.setApplicationDescription(QGuiApplication::applicationDisplayName()); >+ parser.addHelpOption(); >+ parser.addVersionOption(); >+ parser.addPositionalArgument("initialUrl", "The URL to open."); >+ QStringList arguments = app.arguments(); >+ parser.process(arguments); >+ const QString initialUrl = parser.positionalArguments().isEmpty() ? >+ QStringLiteral("https://wpewebkit.org") : parser.positionalArguments().first(); >+ >+ QQmlApplicationEngine engine; >+ QQmlContext* context = engine.rootContext(); >+ context->setContextProperty(QStringLiteral("initialUrl"), QUrl(initialUrl)); >+ >+ engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); >+ if (engine.rootObjects().isEmpty()) >+ return -1; >+ >+ return app.exec(); >+} >diff --git a/Tools/MiniBrowser/wpe/qt/main.qml b/Tools/MiniBrowser/wpe/qt/main.qml >new file mode 100644 >index 0000000000000000000000000000000000000000..a405d76c0e43e43bada3f1d0ef1c24bf4cc90951 >--- /dev/null >+++ b/Tools/MiniBrowser/wpe/qt/main.qml >@@ -0,0 +1,20 @@ >+import QtQuick 2.11 >+import QtQuick.Window 2.11 >+import org.wpewebkit.qtwpe 1.0 >+ >+Window { >+ id: main_window >+ visible: true >+ width: 1280 >+ height: 720 >+ title: qsTr("Hello WPE!") >+ >+ WPEView { >+ url: initialUrl >+ focus: true >+ anchors.fill: parent >+ onTitleChanged: { >+ main_window.title = title; >+ } >+ } >+} >diff --git a/Tools/MiniBrowser/wpe/qt/qml.qrc b/Tools/MiniBrowser/wpe/qt/qml.qrc >new file mode 100644 >index 0000000000000000000000000000000000000000..5f6483ac33f1881cc59e080e69bb033ebe2a7829 >--- /dev/null >+++ b/Tools/MiniBrowser/wpe/qt/qml.qrc >@@ -0,0 +1,5 @@ >+<RCC> >+ <qresource prefix="/"> >+ <file>main.qml</file> >+ </qresource> >+</RCC> >diff --git a/Tools/Scripts/run-gtk-tests b/Tools/Scripts/run-gtk-tests >index a9bcc187f054317891f67fa1b2d99c9c8be15f28..0b6741ca6343413365af24a46b2d6faf998994e4 100755 >--- a/Tools/Scripts/run-gtk-tests >+++ b/Tools/Scripts/run-gtk-tests >@@ -125,6 +125,9 @@ class GtkTestRunner(TestRunner): > def is_google_test(self, test_program): > return os.path.basename(os.path.dirname(test_program)) in ["WebKit", "WTF", "WebCore", "WebCoreGtk"] > >+ def is_qt_test(self, test_program): >+ return False >+ > if __name__ == "__main__": > flatpakutils.run_in_sandbox_if_available(sys.argv) > if not flatpakutils.is_sandboxed() and not jhbuildutils.enter_jhbuild_environment_if_available("gtk"): >diff --git a/Tools/Scripts/run-qt-wpe-minibrowser b/Tools/Scripts/run-qt-wpe-minibrowser >new file mode 100755 >index 0000000000000000000000000000000000000000..28e6c7f1728a1449b4f73d81134675368e5ea92c >--- /dev/null >+++ b/Tools/Scripts/run-qt-wpe-minibrowser >@@ -0,0 +1,60 @@ >+#!/usr/bin/env perl >+# Copyright (C) 2018, 2019 Igalia S.L. >+# >+# This program is free software; you can redistribute it and/or >+# modify it under the terms of the GNU Lesser General Public >+# License as published by the Free Software Foundation; either >+# version 2.1 of the License, or (at your option) any later version. >+# >+# This program is distributed in the hope that it will be useful, >+# but WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+# Lesser General Public License for more details. >+# >+# You should have received a copy of the GNU Lesser General Public >+# License along with this program; if not, write to the >+# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, >+# Boston, MA 02110-1301, USA. >+ >+# Simplified "run" script for launching the QtWPE MiniBrowser. >+ >+use strict; >+use warnings; >+use File::Spec::Functions qw/catdir/; >+use FindBin; >+use lib $FindBin::Bin; >+use webkitdirs; >+ >+my $launcherName; >+my $libPath; >+my $launcherPath; >+my @jhbuildWrapper; >+ >+prohibitUnknownPort(); >+setConfiguration(); >+ >+if (isWPE()) { >+ my $configuration = passedConfiguration(); >+ my $productDir = productDir(); >+ my $libPath; >+ $libPath = "/app/webkit/WebKitBuild/$configuration/lib/qml" if $configuration; >+ $ENV{"QML2_IMPORT_PATH"} = "$libPath" if $libPath; >+ runInFlatpakIfAvailable("/app/webkit/Tools/Scripts/run-qt-wpe-minibrowser"); >+ >+ # Check to see that all the frameworks are built. >+ checkFrameworks(); >+ >+ if (!inFlatpakSandbox()) { >+ $libPath = "$productDir/lib/qml" if $productDir; >+ $ENV{"QML2_IMPORT_PATH"} = "$libPath" if $libPath; >+ } >+ >+ $launcherPath = catdir($productDir, "bin", "qt-wpe-mini-browser"); >+ die "Can't find $launcherPath" unless -x $launcherPath; >+ @jhbuildWrapper = wrapperPrefixIfNeeded(); >+ >+ print "Starting MiniBrowser.\n"; >+ exec @jhbuildWrapper, $launcherPath, @ARGV or die; >+} else { >+ die "Unsupported platform." >+} >diff --git a/Tools/Scripts/run-wpe-tests b/Tools/Scripts/run-wpe-tests >index e77ebe994e7f35f8282cad620cfeeb539d58f8c7..cb7d7044ad02ae18aba27352bb44be3fc8dd5a5c 100755 >--- a/Tools/Scripts/run-wpe-tests >+++ b/Tools/Scripts/run-wpe-tests >@@ -26,12 +26,13 @@ top_level_directory = os.path.normpath(os.path.join(os.path.dirname(__file__), " > sys.path.insert(0, os.path.join(top_level_directory, "Tools", "jhbuild")) > sys.path.insert(0, os.path.join(top_level_directory, "Tools", "flatpak")) > sys.path.insert(0, os.path.join(top_level_directory, "Tools", "glib")) >+import common > import jhbuildutils > import flatpakutils > from api_test_runner import TestRunner, add_options > > class WPETestRunner(TestRunner): >- TestRunner.TEST_DIRS = [ "WPE", "WebKit", "JavaScriptCore", "WTF", "WebCore" ] >+ TestRunner.TEST_DIRS = [ "WPE", "WPEQt", "WebKit", "JavaScriptCore", "WTF", "WebCore" ] > > def __init__(self, options, tests=[]): > super(WPETestRunner, self).__init__("wpe", options, tests) >@@ -42,6 +43,8 @@ class WPETestRunner(TestRunner): > def is_google_test(self, test_program): > return os.path.basename(os.path.dirname(test_program)) in ["WebKit", "WTF", "WebCore"] > >+ def is_qt_test(self, test_program): >+ return os.path.basename(os.path.dirname(test_program)) == "WPEQt" > > if __name__ == "__main__": > flatpakutils.run_in_sandbox_if_available([sys.argv[0], "--wpe"] + sys.argv[1:]) >diff --git a/Tools/TestWebKitAPI/Tests/WPEQt/TestLoad.cpp b/Tools/TestWebKitAPI/Tests/WPEQt/TestLoad.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..2c9709312b8242d58ba9e2d041d051e924d3a0b7 >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WPEQt/TestLoad.cpp >@@ -0,0 +1,61 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L. >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Lesser General Public >+ * License as published by the Free Software Foundation; either >+ * version 2,1 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public License >+ * along with this library; see the file COPYING.LIB. If not, write to >+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include "config.h" >+ >+#include "WPEQtTest.h" >+ >+#include <QtCore/QTemporaryFile> >+#include <QtCore/qdir.h> >+#include <QtCore/qfileinfo.h> >+#include <QtCore/qstandardpaths.h> >+#include <QtCore/qtemporarydir.h> >+ >+class TestLoad : public WPEQtTest { >+Q_OBJECT >+private: >+ void main() override; >+}; >+ >+void TestLoad::main() >+{ >+ QString cacheLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); >+ static const char* testHTML = "<html><head><title>FooBar</title></head><body><p>This is a test</p></body></html>"; >+ >+ QTemporaryFile file(cacheLocation + QStringLiteral("/XXXXXXfile.html")); >+ QVERIFY2(file.open(), qPrintable(QStringLiteral("Cannot create temporary file:") + file.errorString())); >+ >+ file.write(testHTML); >+ const QString fileName(file.fileName()); >+ file.close(); >+ >+ const QUrl url(QUrl::fromLocalFile(fileName)); >+ m_view->setUrl(url); >+ >+ waitForLoadSucceeded(m_view); >+ QTRY_COMPARE(m_view->loadProgress(), 100); >+ QTRY_VERIFY(!m_view->isLoading()); >+ QCOMPARE(m_view->title(), QStringLiteral("FooBar")); >+ QVERIFY(!m_view->canGoBack()); >+ QVERIFY(!m_view->canGoForward()); >+ QCOMPARE(m_view->url(), url); >+} >+ >+QTEST_APPLESS_MAIN(TestLoad) >+#include "TestLoad.moc" >diff --git a/Tools/TestWebKitAPI/Tests/WPEQt/TestLoadHtml.cpp b/Tools/TestWebKitAPI/Tests/WPEQt/TestLoadHtml.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..7bc05fb3252dc98423b5ab787790a60645f0bbdd >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WPEQt/TestLoadHtml.cpp >@@ -0,0 +1,40 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L. >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Lesser General Public >+ * License as published by the Free Software Foundation; either >+ * version 2,1 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public License >+ * along with this library; see the file COPYING.LIB. If not, write to >+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include "config.h" >+ >+#include "WPEQtTest.h" >+ >+class TestLoadHtml : public WPEQtTest { >+Q_OBJECT >+private: >+ void main() override; >+}; >+ >+void TestLoadHtml::main() >+{ >+ m_view->loadHtml(QString("<html><head><title>WebViewTitle</title></head><body />")); >+ waitForLoadSucceeded(m_view); >+ QTRY_COMPARE(m_view->loadProgress(), 100); >+ QTRY_VERIFY(!m_view->isLoading()); >+ QCOMPARE(m_view->title(), QStringLiteral("WebViewTitle")); >+} >+ >+QTEST_APPLESS_MAIN(TestLoadHtml) >+#include "TestLoadHtml.moc" >diff --git a/Tools/TestWebKitAPI/Tests/WPEQt/TestLoadRequest.cpp b/Tools/TestWebKitAPI/Tests/WPEQt/TestLoadRequest.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..188671f1ea6f29fb3434f47726f8bf945c4ccd5f >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WPEQt/TestLoadRequest.cpp >@@ -0,0 +1,66 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L. >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Lesser General Public >+ * License as published by the Free Software Foundation; either >+ * version 2,1 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public License >+ * along with this library; see the file COPYING.LIB. If not, write to >+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include "config.h" >+ >+#include "WPEQtTest.h" >+ >+#include <QtCore/QTemporaryFile> >+#include <QtCore/qdir.h> >+#include <QtCore/qfileinfo.h> >+#include <QtCore/qstandardpaths.h> >+#include <QtCore/qtemporarydir.h> >+ >+class TestLoadRequest : public WPEQtTest { >+Q_OBJECT >+private: >+ void main() override; >+}; >+ >+void TestLoadRequest::main() >+{ >+ { >+ QString cacheLocation = QStandardPaths::writableLocation(QStandardPaths::CacheLocation); >+ QTemporaryFile file(cacheLocation + QStringLiteral("/XXXXXXfile.html")); >+ QVERIFY2(file.open(), qPrintable(QStringLiteral("Cannot create temporary file:") + file.errorString())); >+ >+ file.write("<html><head><title>FooBar</title></head><body />"); >+ const QString fileName = file.fileName(); >+ file.close(); >+ const QUrl url = QUrl::fromLocalFile(fileName); >+ QSignalSpy loadChangedSignalSpy(m_view, SIGNAL(loadingChanged(WPEQtViewLoadRequest*))); >+ m_view->setUrl(url); >+ waitForLoadSucceeded(m_view); >+ QVERIFY(!m_view->isLoading()); >+ QCOMPARE(m_view->loadProgress(), 100); >+ QCOMPARE(m_view->title(), QStringLiteral("FooBar")); >+ QCOMPARE(m_view->url(), url); >+ QCOMPARE(loadChangedSignalSpy.count(), 2); >+ } >+ >+ { >+ QSignalSpy loadChangedSignalSpy(m_view, SIGNAL(loadingChanged(WPEQtViewLoadRequest*))); >+ m_view->setUrl(QUrl("file://IDONTEXIST.html")); >+ waitForLoadFailed(m_view); >+ QCOMPARE(loadChangedSignalSpy.count(), 3); >+ } >+} >+ >+QTEST_APPLESS_MAIN(TestLoadRequest) >+#include "TestLoadRequest.moc" >diff --git a/Tools/TestWebKitAPI/Tests/WPEQt/TestRunJavaScript.cpp b/Tools/TestWebKitAPI/Tests/WPEQt/TestRunJavaScript.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..3137d3f85a484e0b51e5248e1c379c4a19e08083 >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WPEQt/TestRunJavaScript.cpp >@@ -0,0 +1,49 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L. >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Lesser General Public >+ * License as published by the Free Software Foundation; either >+ * version 2,1 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public License >+ * along with this library; see the file COPYING.LIB. If not, write to >+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include "config.h" >+ >+#include "WPEQtTest.h" >+ >+class TestRunJavaScript : public WPEQtTest { >+ Q_OBJECT >+private: >+ void main() override; >+}; >+ >+void TestRunJavaScript::main() >+{ >+ const QString title = QString(QLatin1String("WebViewTitle")); >+ m_view->loadHtml(QString("<html><head><title>%1</title></head><body /></html>").arg(title)); >+ >+ waitForLoadSucceeded(m_view); >+ g_assert_cmpint(m_view->loadProgress(), ==, 100); >+ g_assert(!m_view->isLoading()); >+ g_assert_cmpstr(m_view->title().toUtf8(), ==, title.toUtf8()); >+ const QString tstProperty = QString(QLatin1String("Qt.tst_data")); >+ QJSValue callback = m_engine.evaluate(QString("function(result) { %1 = result; }").arg(tstProperty)); >+ QVERIFY2(!callback.isError(), qPrintable(callback.toString())); >+ QVERIFY(!callback.isUndefined()); >+ QVERIFY(callback.isCallable()); >+ m_view->runJavaScript(QString(QLatin1String("document.title")), callback); >+ QTRY_COMPARE(m_engine.evaluate(tstProperty).toString(), title); >+} >+ >+QTEST_APPLESS_MAIN(TestRunJavaScript) >+#include "TestRunJavaScript.moc" >diff --git a/Tools/TestWebKitAPI/Tests/WPEQt/WPEQtTest.cpp b/Tools/TestWebKitAPI/Tests/WPEQt/WPEQtTest.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..92d61d21e700065c05febae35bd34ae70a9e9541 >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WPEQt/WPEQtTest.cpp >@@ -0,0 +1,38 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L. >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Lesser General Public >+ * License as published by the Free Software Foundation; either >+ * version 2,1 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public License >+ * along with this library; see the file COPYING.LIB. If not, write to >+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include "config.h" >+#include "WPEQtTest.h" >+ >+bool waitForSignal(QObject* obj, const char* signal, int timeout) >+{ >+ QEventLoop loop; >+ QObject::connect(obj, signal, &loop, SLOT(quit())); >+ QTimer timer; >+ QSignalSpy timeoutSpy(&timer, SIGNAL(timeout())); >+ if (timeout > 0) { >+ QObject::connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); >+ timer.setSingleShot(true); >+ timer.start(timeout); >+ } >+ loop.exec(); >+ return timeoutSpy.isEmpty(); >+} >+ >+#include "WPEQtTest.moc" >diff --git a/Tools/TestWebKitAPI/Tests/WPEQt/WPEQtTest.h b/Tools/TestWebKitAPI/Tests/WPEQt/WPEQtTest.h >new file mode 100644 >index 0000000000000000000000000000000000000000..d5a0cf5e8e43e8a85b4e4e34b7ea0a9b5fabf19f >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WPEQt/WPEQtTest.h >@@ -0,0 +1,156 @@ >+/* >+ * Copyright (C) 2018, 2019 Igalia S.L. >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Lesser General Public >+ * License as published by the Free Software Foundation; either >+ * version 2,1 of the License, or (at your option) any later version. >+ * >+ * This library is distributed in the hope that it will be useful, >+ * but WITHOUT ANY WARRANTY; without even the implied warranty of >+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public License >+ * along with this library; see the file COPYING.LIB. If not, write to >+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#pragma once >+ >+// WPEQt has to be included before the remaining Qt headers, because of epoxy. >+#include <wpe/qt/WPEQtView.h> >+#include <wpe/qt/WPEQtViewLoadRequest.h> >+ >+#include <QEventLoop> >+#include <QQmlApplicationEngine> >+#include <QQuickWindow> >+#include <QSignalSpy> >+#include <QTimer> >+#include <QtTest/QTest> >+#include <glib.h> >+ >+class LoadSpy : public QEventLoop { >+ Q_OBJECT >+ >+public: >+ LoadSpy(WPEQtView *webView) >+ { >+ connect(webView, SIGNAL(loadingChanged(WPEQtViewLoadRequest*)), SLOT(onLoadingChanged(WPEQtViewLoadRequest*))); >+ } >+ >+ ~LoadSpy() { } >+ >+Q_SIGNALS: >+ void loadSucceeded(); >+ void loadFailed(); >+ >+private Q_SLOTS: >+ void onLoadingChanged(WPEQtViewLoadRequest *loadRequest) >+ { >+ if (loadRequest->status() == WPEQtView::LoadSucceededStatus) >+ Q_EMIT loadSucceeded(); >+ else if (loadRequest->status() == WPEQtView::LoadFailedStatus) >+ Q_EMIT loadFailed(); >+ } >+}; >+ >+class LoadStartedCatcher : public QObject { >+ Q_OBJECT >+ >+public: >+ LoadStartedCatcher(WPEQtView *webView) >+ : m_webView(webView) >+ { >+ connect(m_webView, SIGNAL(loadingChanged(WPEQtViewLoadRequest*)), this, SLOT(onLoadingChanged(WPEQtViewLoadRequest*))); >+ } >+ >+ virtual ~LoadStartedCatcher() { } >+ >+public Q_SLOTS: >+ void onLoadingChanged(WPEQtViewLoadRequest *loadRequest) >+ { >+ if (loadRequest->status() == WPEQtView::LoadStartedStatus) >+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); >+ } >+ >+Q_SIGNALS: >+ void finished(); >+ >+private: >+ WPEQtView* m_webView; >+}; >+ >+bool waitForSignal(QObject*, const char* signal, int timeout = 10000); >+ >+inline bool waitForLoadSucceeded(WPEQtView* webView, int timeout = 10000) >+{ >+ LoadSpy loadSpy(webView); >+ return waitForSignal(&loadSpy, SIGNAL(loadSucceeded()), timeout); >+} >+ >+inline bool waitForLoadFailed(WPEQtView* webView, int timeout = 10000) >+{ >+ LoadSpy loadSpy(webView); >+ return waitForSignal(&loadSpy, SIGNAL(loadFailed()), timeout); >+} >+ >+class WPEQtTest: public QObject { >+ Q_OBJECT >+public: >+ WPEQtTest() >+ : m_argc(0) >+ , m_app(m_argc, nullptr) >+ , m_engine() >+ { >+ g_setenv("WEBKIT_EXEC_PATH", WEBKIT_EXEC_PATH, FALSE); >+ g_setenv("WEBKIT_INJECTED_BUNDLE_PATH", WEBKIT_INJECTED_BUNDLE_PATH, FALSE); >+ >+ QQmlComponent component(&m_engine); >+ component.setData("import QtQuick 2.11\n" >+ "import QtQuick.Window 2.11\n" >+ "import org.wpewebkit.qtwpe 1.0\n" >+ "Window {\n" >+ " id: main_window\n" >+ " visible: true\n" >+ " width: 1280\n" >+ " height: 720\n" >+ " WPEView {\n" >+ " objectName: \"wpeview\"\n" >+ " focus: true\n" >+ " anchors.fill: parent\n" >+ " }\n" >+ "}", QUrl()); >+ >+ QObject* object = component.create(); >+ m_view = object->findChild<WPEQtView*>("wpeview"); >+ >+ QTRY_COMPARE(m_view->loadProgress(), 0); >+ } >+ >+ virtual ~WPEQtTest() >+ { >+ delete m_view; >+ } >+ >+private Q_SLOTS: >+ void run() >+ { >+ QObject::connect(m_view, &WPEQtView::webViewCreated, this, [this] { >+ main(); >+ m_app.quit(); >+ }); >+ m_app.exec(); >+ } >+ >+private: >+ virtual void main() = 0; >+ >+ int m_argc; >+ QGuiApplication m_app; >+ >+protected: >+ WPEQtView* m_view { nullptr }; >+ QQmlEngine m_engine; >+}; >diff --git a/Tools/TestWebKitAPI/glib/CMakeLists.txt b/Tools/TestWebKitAPI/glib/CMakeLists.txt >index f4c1e69663ba2782cdeada7817b30ad26ba9977e..edb8a13610297c0d9a50599c887592c50087c663 100644 >--- a/Tools/TestWebKitAPI/glib/CMakeLists.txt >+++ b/Tools/TestWebKitAPI/glib/CMakeLists.txt >@@ -21,9 +21,13 @@ set(WebKitGLibAPITests_SYSTEM_INCLUDE_DIRECTORIES > ${LIBSOUP_INCLUDE_DIRS} > ) > >-set(WebKitGLibAPITest_LIBRARIES >+set(WebKitAPITest_LIBRARIES > JavaScriptCore > WebKit >+) >+ >+set(WebKitGLibAPITest_LIBRARIES >+ ${WebKitAPITest_LIBRARIES} > WebKitGLibAPITestsCore > ${GLIB_LIBRARIES} > ${LIBSOUP_LIBRARIES} >@@ -145,3 +149,32 @@ ADD_WK2_TEST(TestDOMElement ${TOOLS_DIR}/TestWebKitAPI/Tests/WebKitGLib/TestDOME > if (PORT STREQUAL "GTK") > ADD_WK2_TEST(TestCookieManager ${TOOLS_DIR}/TestWebKitAPI/Tests/WebKitGLib/TestCookieManager.cpp) > endif () >+ >+macro(ADD_WPE_QT_TEST test_name) >+ add_executable(${test_name} ${ARGN} ${TOOLS_DIR}/TestWebKitAPI/Tests/WPEQt/WPEQtTest.cpp) >+ set_target_properties(${test_name} PROPERTIES >+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/TestWebKitAPI/WPEQt >+ AUTOMOC ON >+ CXX_STANDARD 14 >+ ) >+ target_compile_definitions(${test_name} PUBLIC QT_NO_KEYWORDS=1) >+ target_link_libraries(${test_name} ${WPEQtAPITest_LIBRARIES}) >+ target_include_directories(${test_name} SYSTEM PRIVATE ${WPEQtAPITests_INCLUDE_DIRECTORIES}) >+ target_include_directories(${test_name} PRIVATE >+ ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/Source/WebKit/UIProcess/API/wpe/qt) >+endmacro() >+ >+if (PORT STREQUAL "WPE" AND ENABLE_WPE_QT_API) >+ set(WPEQtAPITests_INCLUDE_DIRECTORIES >+ ${Qt5_INCLUDE_DIRS} >+ ${Qt5Test_INCLUDE_DIRS} >+ ) >+ set(WPEQtAPITest_LIBRARIES >+ ${WebKitAPITest_LIBRARIES} >+ Qt5::Test qtwpe >+ ) >+ ADD_WPE_QT_TEST(TestLoad ${TOOLS_DIR}/TestWebKitAPI/Tests/WPEQt/TestLoad.cpp) >+ ADD_WPE_QT_TEST(TestLoadHtml ${TOOLS_DIR}/TestWebKitAPI/Tests/WPEQt/TestLoadHtml.cpp) >+ ADD_WPE_QT_TEST(TestLoadRequest ${TOOLS_DIR}/TestWebKitAPI/Tests/WPEQt/TestLoadRequest.cpp) >+ ADD_WPE_QT_TEST(TestRunJavaScript ${TOOLS_DIR}/TestWebKitAPI/Tests/WPEQt/TestRunJavaScript.cpp) >+endif () >diff --git a/Tools/flatpak/flatpakutils.py b/Tools/flatpak/flatpakutils.py >index 41440ed0d0c9da184557e5977d1f4f9e3c77a8bf..35d35d44c988726c2acf5bf9eefb6a2c1ade9516 100644 >--- a/Tools/flatpak/flatpakutils.py >+++ b/Tools/flatpak/flatpakutils.py >@@ -52,6 +52,10 @@ FLATPAK_REQ = [ > ("flatpak-builder", "0.10.0"), > ] > >+WPE_MANIFEST_MAP = { >+ "qt": "org.webkit.WPEQT.yaml", >+} >+ > scriptdir = os.path.abspath(os.path.dirname(__file__)) > _log = logging.getLogger(__name__) > >@@ -498,6 +502,7 @@ class WebkitFlatpak: > dest="user_command") > general.add_argument('--available', action='store_true', dest="check_available", help='Check if required dependencies are available.'), > general.add_argument("--use-icecream", help="Use the distributed icecream (icecc) compiler.", action="store_true") >+ general.add_argument("--wpe-extension", action="store", dest="wpe_extension", help="WPE Extension to enable") > > debugoptions = parser.add_argument_group("Debugging") > debugoptions.add_argument("--gdb", nargs="?", help="Activate gdb, passing extra args to it if wanted.") >@@ -553,6 +558,7 @@ class WebkitFlatpak: > self.app_module = None > self.flatpak_default_args = [] > self.check_available = False >+ self.wpe_extension = None > > # Default application to run in the sandbox > self.command = None >@@ -596,7 +602,13 @@ class WebkitFlatpak: > " --debug" if self.debug else " --release") > > self.name = "org.webkit.%s" % self.platform >- self.manifest_path = os.path.abspath(os.path.join(scriptdir, '../flatpak/org.webkit.WebKit.yaml')) >+ >+ if self.wpe_extension: >+ manifest_filename = WPE_MANIFEST_MAP[self.wpe_extension] >+ else: >+ manifest_filename = "org.webkit.WebKit.yaml" >+ self.manifest_path = os.path.abspath(os.path.join(scriptdir, '../flatpak/') + manifest_filename) >+ > self.build_name = self.name + "-generated" > > build_root = os.path.join(self.source_root, 'WebKitBuild') >@@ -679,6 +691,9 @@ class WebkitFlatpak: > "--bind-mount=/etc/perl=%s" % os.path.join(self.flatpak_build_path, "files/lib/perl"), > "--bind-mount=/run/host/%s=%s" % (tempfile.gettempdir(), tempfile.gettempdir()), > "--bind-mount=%s=%s" % (self.sandbox_source_root, self.source_root), >+ "--talk-name=org.a11y.Bus", >+ "--talk-name=org.gtk.vfs", >+ "--talk-name=org.gtk.vfs.*", > # We mount WebKitBuild/PORTNAME/BuildType to /app/webkit/WebKitBuild/BuildType > # so we can build WPE and GTK in a same source tree. > "--bind-mount=%s=%s" % (sandbox_build_path, self.build_path)] >@@ -708,6 +723,7 @@ class WebkitFlatpak: > "LANG", > "NUMBER_OF_PROCESSORS", > "CCACHE_PREFIX", >+ "QML2_IMPORT_PATH", > ] > > if self.use_icecream: >diff --git a/Tools/flatpak/org.webkit.CommonModules.yaml b/Tools/flatpak/org.webkit.CommonModules.yaml >index 247596e08dbc2c9dba48f272450cad39e21044d2..bb603a99398c7675b10a159d11438de71cf2b488 100644 >--- a/Tools/flatpak/org.webkit.CommonModules.yaml >+++ b/Tools/flatpak/org.webkit.CommonModules.yaml >@@ -15,7 +15,7 @@ > sources: > - type: git > url: https://github.com/apache/httpd.git >- branch: 2.4.33 >+ branch: 2.4.37 > - type : file > path : files/httpd-autogen.sh > dest-filename : autogen.sh >@@ -81,6 +81,15 @@ > url: https://files.pythonhosted.org/packages/9e/17/1d4ed6e1a4c0918a0357dfa2fdbe26bf63f6e616013c04a14bce9fd33e40/pyaml-17.12.1.tar.gz > sha256: 66623c52f34d83a2c0fc963e08e8b9d0c13d88404e3b43b1852ef71eda19afa3 > >+- name: python2-subprocess32 >+ buildsystem: simple >+ build-commands: >+ - pip2 install --target=/app/lib/python2.7/site-packages/ . >+ sources: >+ - type: archive >+ url: https://files.pythonhosted.org/packages/be/2b/beeba583e9877e64db10b52a96915afc0feabf7144dcbf2a0d0ea68bf73d/subprocess32-3.5.3.tar.gz >+ sha256: 6bc82992316eef3ccff319b5033809801c0c3372709c5f6985299c88ac7225c3 >+ > # GStreamer modules > - name: libvpx > no-autogen: true >@@ -90,7 +99,7 @@ > branch: v1.7.0 > config-opts: > - --enable-pic >- - --as=yasm >+ - --as=nasm > - --disable-unit-tests > - --size-limit=16384x16384 > - --enable-postproc >@@ -181,6 +190,7 @@ > - "--enable-static" > - "--enable-pic" > - "--disable-lavf" >+ - "--disable-asm" > sources: > - type: archive > url: http://download.videolan.org/pub/x264/snapshots/x264-snapshot-20140212-2245-stable.tar.bz2 >@@ -205,8 +215,61 @@ > path: ../gstreamer/patches/gst-plugins-bad-0002-aomenc-Handle-8-bit_depth-images-with-AOM_IMG_FMT_HI.patch > config-opts: > - -Ddisable_gtkdoc=true >+- name: ffmpeg >+ sources: >+ - type: archive >+ url: https://ffmpeg.org/releases/ffmpeg-3.4.5.tar.gz >+ sha256: 18f80cc9ca322134ed40d25d7489af954fa519b4e7e6289b7084f1b0a1cdf472 >+ config-opts: >+ - --enable-static >+ - --enable-pic >+ - --disable-avdevice >+ - --disable-postproc >+ - --disable-swscale >+ - --disable-programs >+ - --disable-ffplay >+ - --disable-ffprobe >+ - --disable-ffmpeg >+ - --disable-encoder=flac >+ - --disable-protocols >+ - --disable-devices >+ - --disable-network >+ - --disable-hwaccels >+ - --disable-dxva2 >+ - --disable-vdpau >+ - --disable-filters >+ - --enable-filter=yadif >+ - --disable-doc >+ - --disable-d3d11va >+ - --disable-dxva2 >+ - --disable-audiotoolbox >+ - --disable-videotoolbox >+ - --disable-vaapi >+ - --disable-crystalhd >+ - --disable-mediacodec >+ - --disable-nvenc >+ - --disable-mmal >+ - --disable-omx >+ - --disable-omx-rpi >+ - --disable-cuda >+ - --disable-cuvid >+ - --disable-libmfx >+ - --disable-libnpp >+ - --disable-iconv >+ - --disable-jni >+ - --disable-v4l2_m2m >+ - --enable-optimizations >+- name: gst-libav >+ buildsystem: meson >+ builddir: true >+ sources: >+ - type: archive >+ url: https://gstreamer.freedesktop.org/src/gst-libav/gst-libav-1.14.4.tar.xz >+ sha256: dfd78591901df7853eab7e56a86c34a1b03635da0d3d56b89aa577f1897865da >+ config-opts: >+ - -Ddisable_gtkdoc=true > >-- name: libgcrypt # Speedup libgrcypt >+- name: libgcrypt # Speedup libgcrypt > sources: > - type: git > url: https://dev.gnupg.org/source/libgcrypt.git >diff --git a/Tools/flatpak/org.webkit.WPE.yaml b/Tools/flatpak/org.webkit.WPE.yaml >index 3fa1c6bcb73518cba3fcfc0e08c62b22b9433d86..4cbabbaa0cb8e158ad4441f98b4d053a8cb3ba76 100644 >--- a/Tools/flatpak/org.webkit.WPE.yaml >+++ b/Tools/flatpak/org.webkit.WPE.yaml >@@ -1,15 +1,4 @@ >-- name: libwpe >- buildsystem: cmake-ninja >- sources: >- - type: archive >- url: https://wpewebkit.org/releases/libwpe-1.0.0.tar.xz >- sha256: aff11612123f9ab85a8b9a4bcdfb3a7503eba0a0d2d96f2cdecd30e911091719 >-- name: wpebackend-fdo >- buildsystem: cmake-ninja >- sources: >- - type: archive >- url: https://wpewebkit.org/releases/wpebackend-fdo-1.0.0.tar.xz >- sha256: 7a747f87a1ae46d30144369050e3ce348b58986d04e1a139ba75c198fa636729 >+- org.webkit.WPEModules.yaml > - name: webkitgtk-test-fonts > no-autogen: true > sources: >diff --git a/Tools/flatpak/org.webkit.WPEModules.yaml b/Tools/flatpak/org.webkit.WPEModules.yaml >index 3a4af780eeba28e7ea3d47df2b82feea6635912c..962c967e4a41f8ccbfddb241939f01fab582eb9e 100644 >--- a/Tools/flatpak/org.webkit.WPEModules.yaml >+++ b/Tools/flatpak/org.webkit.WPEModules.yaml >@@ -2,11 +2,11 @@ > buildsystem: cmake-ninja > sources: > - type: archive >- url: https://wpewebkit.org/releases/libwpe-1.0.0.tar.xz >- sha256: aff11612123f9ab85a8b9a4bcdfb3a7503eba0a0d2d96f2cdecd30e911091719 >+ url: https://wpewebkit.org/releases/libwpe-1.1.0.tar.xz >+ sha256: 72e34ad754be11abd1a438cfe195d8d644c52105ab2b1c3b39dec6228bc776ce > - name: wpebackend-fdo > buildsystem: cmake-ninja > sources: > - type: archive >- url: https://wpewebkit.org/releases/wpebackend-fdo-1.0.0.tar.xz >- sha256: 7a747f87a1ae46d30144369050e3ce348b58986d04e1a139ba75c198fa636729 >+ url: https://wpewebkit.org/releases/wpebackend-fdo-1.1.0.tar.xz >+ sha256: f6c72130d16e50860cb83eb0f6e109c76f1826d2c6bee39025fb3651941761e7 >diff --git a/Tools/flatpak/org.webkit.WPEQT.yaml b/Tools/flatpak/org.webkit.WPEQT.yaml >new file mode 100644 >index 0000000000000000000000000000000000000000..0c6919ea6d136a6a092c8fb59fc78b7b4add987e >--- /dev/null >+++ b/Tools/flatpak/org.webkit.WPEQT.yaml >@@ -0,0 +1,39 @@ >+app-id: org.webkit.WPEQT >+runtime: org.kde.Platform >+runtime-version: "5.11" >+# Control the exact version of the Sdk/Runtime that is being used. >+sdk-hash: dd9e5d3b3134c24fc191226f058fc78c6bdf1c25fd7be38bea977fcb15307e95 >+runtime-hash: 02ede84d3591a5ea8028204d86059bffaccb778159ec53c859bbc60d9e7025e8 >+sdk: org.kde.Sdk >+command: %(COMMAND)s >+finish-args: >+ # Basically no sandboxing, the goal here is to make it flexible >+ # for developers, not really to isolate (openning all devices >+ # to allow acces video cameras until we have a portal at least). >+ - --share=ipc >+ - --socket=x11 >+ - --socket=wayland >+ - --device=all >+ - --share=network >+ - --socket=pulseaudio >+ - --system-talk-name=org.freedesktop.GeoClue2 >+ - --system-talk-name=org.a11y.Bus >+ - --filesystem=host >+ - --socket=system-bus >+ - --talk-name=org.freedesktop.Flatpak >+ - --env=GST_PRESET_PATH=/app/share/gstreamer-1.0/presets/ >+build-options: >+ cflags: -O2 -g >+ cxxflags: -O2 -g >+ strip: false >+ no-debuginfo: true >+modules: >+ - org.webkit.CommonModules.yaml >+ - org.webkit.WPEModules.yaml >+ >+ # This module is not actually built. >+ - name: org.webkit.WPEQT >+ buildsystem: qmake >+ sources: >+ - type: dir >+ path: /app/webkit/Source/ThirdParty/WPE/QtWPE/ >diff --git a/Tools/flatpak/org.webkit.WebKit.yaml b/Tools/flatpak/org.webkit.WebKit.yaml >index 145ca0292900dd59d21ab78d922074a6db27521e..fe5b008f4be8a5e33f8bfaf7f2177c7ce22c24ee 100644 >--- a/Tools/flatpak/org.webkit.WebKit.yaml >+++ b/Tools/flatpak/org.webkit.WebKit.yaml >@@ -17,6 +17,7 @@ finish-args: > - --share=network > - --socket=pulseaudio > - --system-talk-name=org.freedesktop.GeoClue2 >+ - --system-talk-name=org.a11y.Bus > - --filesystem=host > - --socket=system-bus > - --talk-name=org.freedesktop.Flatpak >diff --git a/Tools/glib/api_test_runner.py b/Tools/glib/api_test_runner.py >index 4da894a212de3924028f6ead18731bb341ad6831..b4c4b97c920b26d8063b3cb96c30269da70634ea 100755 >--- a/Tools/glib/api_test_runner.py >+++ b/Tools/glib/api_test_runner.py >@@ -17,7 +17,6 @@ > # the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, > # Boston, MA 02110-1301, USA. > >-import subprocess > import os > import errno > import sys >@@ -32,6 +31,10 @@ from webkitpy.common.host import Host > from webkitpy.common.test_expectations import TestExpectations > from webkitpy.common.timeout_context import Timeout > >+if os.name == 'posix' and sys.version_info[0] < 3: >+ import subprocess32 as subprocess >+else: >+ import subprocess > > class TestRunner(object): > TEST_DIRS = [] >@@ -157,6 +160,31 @@ class TestRunner(object): > > return GLibTestRunner(test_program, timeout, is_slow_test, timeout * 10).run(skipped=self._test_cases_to_skip(test_program), env=self._test_env) > >+ def _run_test_qt(self, test_program): >+ env = self._test_env >+ env['XDG_SESSION_TYPE'] = 'wayland' >+ env['QML2_IMPORT_PATH'] = common.library_build_path('qml') >+ >+ try: >+ output = subprocess.check_output([test_program,], stderr=subprocess.STDOUT, >+ env=env, timeout=self._options.timeout) >+ except subprocess.CalledProcessError, exc: >+ print exc.output >+ if exc.returncode > 0: >+ result = "FAIL" >+ elif exc.returncode < 0: >+ result = "CRASH" >+ except subprocess.TimeoutExpired, exp: >+ result = "TIMEOUT" >+ else: >+ result = "PASS" >+ name = os.path.basename(test_program) >+ if result == "PASS": >+ print("**PASS** %s" % name) >+ else: >+ print(output) >+ return {name: result} >+ > def _get_tests_from_google_test_suite(self, test_program): > try: > output = subprocess.check_output([test_program, '--gtest_list_tests'], env=self._test_env) >@@ -222,6 +250,9 @@ class TestRunner(object): > def is_google_test(self, test_program): > raise NotImplementedError > >+ def is_qt_test(self, test_program): >+ raise NotImplementedError >+ > def _run_test(self, test_program): > if self.is_glib_test(test_program): > return self._run_test_glib(test_program) >@@ -229,6 +260,9 @@ class TestRunner(object): > if self.is_google_test(test_program): > return self._run_google_test_suite(test_program) > >+ if self.is_qt_test(test_program): >+ return self._run_test_qt(test_program) >+ > return {} > > def run_tests(self): >diff --git a/ChangeLog b/ChangeLog >index c996b340fe0efd6d8c72e2bbd7e3c2b17d076b4c..598d49afdcaab439f53cd615b4c4d279a628a955 100644 >--- a/ChangeLog >+++ b/ChangeLog >@@ -1,3 +1,12 @@ >+2019-01-09 Philippe Normand <pnormand@igalia.com> >+ >+ [WPE] Add Qt extension >+ https://bugs.webkit.org/show_bug.cgi?id=191464 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * Source/cmake/OptionsWPE.cmake: Add ENABLE_WPE_QT_API CMake option. Disabled by default. >+ > 2019-01-08 Carlos Garcia Campos <cgarcia@igalia.com> > > Unreviewed. Update OptionsGTK.cmake and NEWS for 2.23.2 release
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 191464
:
354328
|
356506
|
356602
|
356609
|
356610
|
356723
|
358693
|
359152
|
359380