WebKit Bugzilla
Attachment 342043 Details for
Bug 186345
: [WPE] Add a MiniBrowser and use it to run WebDriver tests
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
wpe-mini-browser.diff (text/plain), 60.17 KB, created by
Carlos Garcia Campos
on 2018-06-06 05:06:08 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Carlos Garcia Campos
Created:
2018-06-06 05:06:08 PDT
Size:
60.17 KB
patch
obsolete
>diff --git a/ChangeLog b/ChangeLog >index 3557d94ff42..601bf2b1c68 100644 >--- a/ChangeLog >+++ b/ChangeLog >@@ -1,3 +1,15 @@ >+2018-06-06 Carlos Garcia Campos <cgarcia@igalia.com> >+ >+ [WPE] Add a MiniBrowser and use it to run WebDriver tests >+ https://bugs.webkit.org/show_bug.cgi?id=186345 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add an option to enable building the MiniBrowser. >+ >+ * Source/cmake/FindWaylandProtocols.cmake: Added. >+ * Source/cmake/OptionsWPE.cmake: >+ > 2018-05-28 Carlos Garcia Campos <cgarcia@igalia.com> > > Unreviewed. Update OptionsGTK.cmake and NEWS for 2.21.3 release. >diff --git a/Source/WebDriver/ChangeLog b/Source/WebDriver/ChangeLog >index e0a28bb8fb6..abc2c44ecc7 100644 >--- a/Source/WebDriver/ChangeLog >+++ b/Source/WebDriver/ChangeLog >@@ -1,3 +1,15 @@ >+2018-06-06 Carlos Garcia Campos <cgarcia@igalia.com> >+ >+ [WPE] Add a MiniBrowser and use it to run WebDriver tests >+ https://bugs.webkit.org/show_bug.cgi?id=186345 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Use MiniBrowser instead of dyz as the default WebDriver browser for WPE. >+ >+ * wpe/WebDriverServiceWPE.cpp: >+ (WebDriver::WebDriverService::platformParseCapabilities const): >+ > 2018-06-04 Carlos Garcia Campos <cgarcia@igalia.com> > > [WPE] WebDriver: stop making mandatory to provide a browser path if wpe:browserOptions is present in capabilities >diff --git a/Source/WebDriver/wpe/WebDriverServiceWPE.cpp b/Source/WebDriver/wpe/WebDriverServiceWPE.cpp >index 0aaac3dffa0..d63f5a4ba23 100644 >--- a/Source/WebDriver/wpe/WebDriverServiceWPE.cpp >+++ b/Source/WebDriver/wpe/WebDriverServiceWPE.cpp >@@ -81,7 +81,7 @@ bool WebDriverService::platformMatchCapability(const String&, const RefPtr<JSON: > > void WebDriverService::platformParseCapabilities(const JSON::Object& matchedCapabilities, Capabilities& capabilities) const > { >- capabilities.browserBinary = String("dyz"); >+ capabilities.browserBinary = String("MiniBrowser"); > capabilities.browserArguments = Vector<String> { ASCIILiteral("--automation") }; > > RefPtr<JSON::Object> browserOptions; >diff --git a/Source/cmake/FindWaylandProtocols.cmake b/Source/cmake/FindWaylandProtocols.cmake >new file mode 100644 >index 00000000000..e7e76da1a14 >--- /dev/null >+++ b/Source/cmake/FindWaylandProtocols.cmake >@@ -0,0 +1,53 @@ >+# - Try to find WaylandProtocols >+# Once done, this will define >+# >+# WAYLAND_PROTOCOLS_FOUND - system has WaylandProtocols. >+# WAYLAND_PROTOCOLS_DATADIR - the WaylandProtocols data directory >+# WAYLAND_SCANNER - the path to the wayland-scanner command. >+# >+# Copyright (C) 2018 Igalia S.L. >+# >+# Redistribution and use in source and binary forms, with or without >+# modification, are permitted provided that the following conditions >+# are met: >+# 1. Redistributions of source code must retain the above copyright >+# notice, this list of conditions and the following disclaimer. >+# 2. Redistributions in binary form must reproduce the above copyright >+# notice, this list of conditions and the following disclaimer in the >+# documentation and/or other materials provided with the distribution. >+# >+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS >+# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS >+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; >+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, >+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR >+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF >+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ >+find_package(PkgConfig) >+pkg_check_modules(WAYLAND_PROTOCOLS wayland-protocols) >+ >+macro(_WP_GET_PKGCONFIG_VAR _outvar _varname) >+ execute_process( >+ COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=${_varname} wayland-protocols >+ OUTPUT_VARIABLE _result >+ RESULT_VARIABLE _null >+ ) >+ >+ if (_null) >+ else () >+ string(REGEX REPLACE "[\r\n]" " " _result "${_result}") >+ string(REGEX REPLACE " +$" "" _result "${_result}") >+ separate_arguments(_result) >+ set(${_outvar} ${_result} CACHE INTERNAL "") >+ endif () >+endmacro(_WP_GET_PKGCONFIG_VAR) >+ >+if (WAYLAND_PROTOCOLS_FOUND) >+ _wp_get_pkgconfig_var(WAYLAND_PROTOCOLS_DATADIR "pkgdatadir") >+ find_program(WAYLAND_SCANNER NAMES wayland-scanner) >+endif () >diff --git a/Source/cmake/OptionsWPE.cmake b/Source/cmake/OptionsWPE.cmake >index 8b0cd1f8195..ebf93bcf120 100644 >--- a/Source/cmake/OptionsWPE.cmake >+++ b/Source/cmake/OptionsWPE.cmake >@@ -60,6 +60,7 @@ endif () > SET_AND_EXPOSE_TO_BUILD(ENABLE_DEVELOPER_MODE ${DEVELOPER_MODE}) > if (DEVELOPER_MODE) > WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_API_TESTS PRIVATE ON) >+ WEBKIT_OPTION_DEFAULT_PORT_VALUE(ENABLE_MINIBROWSER PUBLIC ON) > endif () > > include(GStreamerDependencies) >@@ -109,6 +110,16 @@ if (ENABLE_XSLT) > find_package(LibXslt 1.1.7 REQUIRED) > endif () > >+if (ENABLE_MINIBROWSER) >+ find_package(EGL) >+ find_package(OpenGLES2) >+ find_package(Wayland REQUIRED) >+ find_package(WaylandProtocols 1.12 REQUIRED) >+ if (NOT WAYLAND_PROTOCOLS_FOUND) >+ message(FATAL_ERROR "WaylandProtocols is required to enabled WPE MiniBrowser.") >+ endif () >+endif () >+ > add_definitions(-DBUILDING_WPE__=1) > add_definitions(-DGETTEXT_PACKAGE="WPE") > add_definitions(-DJSC_GLIB_API_ENABLED) >diff --git a/Tools/CMakeLists.txt b/Tools/CMakeLists.txt >index 0a481184b2e..4509710f2b7 100644 >--- a/Tools/CMakeLists.txt >+++ b/Tools/CMakeLists.txt >@@ -29,6 +29,10 @@ elseif ("${PORT}" STREQUAL "WPE") > add_subdirectory(TestWebKitAPI/glib) > endif () > endif () >+ >+ if (ENABLE_MINIBROWSER) >+ add_subdirectory(MiniBrowser/wpe) >+ endif () > elseif ("${PORT}" STREQUAL "Win") > add_subdirectory(DumpRenderTree) > add_subdirectory(ImageDiff) >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index afd96e3c0f1..26811d63d74 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,44 @@ >+2018-06-06 Carlos Garcia Campos <cgarcia@igalia.com> >+ >+ [WPE] Add a MiniBrowser and use it to run WebDriver tests >+ https://bugs.webkit.org/show_bug.cgi?id=186345 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Most of the code is based on dyz and gtk MiniBrowser. It includes a headless mode, using the headless backend, >+ to be used when running WebDriver tests in the bots. >+ >+ * CMakeLists.txt: >+ * MiniBrowser/wpe/CMakeLists.txt: Added. >+ * MiniBrowser/wpe/WlGlueHost.cpp: Added. >+ (WlGlue::Host::Host): >+ (WlGlue::Host::~Host): >+ (WlGlue::Host::handleKeyEvent): >+ (WlGlue::Host::addWindowClient): >+ * MiniBrowser/wpe/WlGlueHost.h: Added. >+ (WlGlue::Host::eglDisplay const): >+ (WlGlue::Host::compositor const): >+ (WlGlue::Host::xdgV6 const): >+ * MiniBrowser/wpe/WlGlueWindow.cpp: Added. >+ (WlGlue::Window::Window): >+ (WlGlue::Window::displayBuffer): >+ * MiniBrowser/wpe/WlGlueWindow.h: Added. >+ * MiniBrowser/wpe/main.cpp: Added. >+ (automationStartedCallback): >+ (main): >+ * Scripts/run-minibrowser: Remove WPE specific code. >+ * Scripts/run-webdriver-tests: Add headless display-server option. >+ * Scripts/webkitdirs.pm: >+ (launcherName): Remove WPE specific code. >+ * Scripts/webkitpy/webdriver_tests/webdriver_driver_wpe.py: >+ (WebDriverWPE.browser_name): Return MiniBrowser. >+ (WebDriverWPE.browser_path): Return the path to the MiniBrowser in build dir. >+ (WebDriverWPE.browser_args): Add --headless when running in headless mode. >+ (WebDriverWPE.capabilities): Use the full browser path. >+ * Scripts/webkitpy/webdriver_tests/webdriver_test_runner_selenium.py: >+ (WebDriverTestRunnerSelenium.collect_tests): Fix early return value. >+ * wpe/jhbuild.modules: Remove dyz and add wayland-protocols. >+ > 2018-06-04 Dan Bernstein <mitz@apple.com> > > Fixed building ImageDiff with the default build system in the Xcode 10 developer beta. >diff --git a/Tools/MiniBrowser/wpe/CMakeLists.txt b/Tools/MiniBrowser/wpe/CMakeLists.txt >new file mode 100644 >index 00000000000..f5211646517 >--- /dev/null >+++ b/Tools/MiniBrowser/wpe/CMakeLists.txt >@@ -0,0 +1,63 @@ >+set(MINIBROWSER_DIR "${TOOLS_DIR}/MiniBrowser/wpe") >+set(DERIVED_SOURCES_MINIBROWSER_DIR "${CMAKE_BINARY_DIR}/DerivedSources/MiniBrowser") >+ >+file(MAKE_DIRECTORY ${DERIVED_SOURCES_MINIBROWSER_DIR}) >+ >+set(MiniBrowser_SOURCES >+ ${DERIVED_SOURCES_MINIBROWSER_DIR}/xdg-shell-unstable-v6-protocol.c >+ ${MINIBROWSER_DIR}/WlGlueHost.cpp >+ ${MINIBROWSER_DIR}/WlGlueWindow.cpp >+ ${MINIBROWSER_DIR}/main.cpp >+ ${TOOLS_DIR}/wpe/HeadlessViewBackend/HeadlessViewBackend.cpp >+) >+ >+set(MiniBrowser_INCLUDE_DIRECTORIES >+ ${DERIVED_SOURCES_MINIBROWSER_DIR} >+ ${DERIVED_SOURCES_WPE_API_DIR} >+ ${FORWARDING_HEADERS_WPE_DIR} >+ ${TOOLS_DIR}/wpe/HeadlessViewBackend >+) >+ >+set(MiniBrowser_SYSTEM_INCLUDE_DIRECTORIES >+ ${EGL_INCLUDE_DIRS} >+ ${LIBXKBCOMMON_INCLUDE_DIRS} >+ ${OPENGLES2_INCLUDE_DIRS} >+ ${WAYLAND_INCLUDE_DIRS} >+ ${WPE_INCLUDE_DIRS} >+ ${WPEBACKEND_FDO_INCLUDE_DIRS} >+) >+ >+set(MiniBrowser_LIBRARIES >+ ${JavaScriptCore_LIBRARY_NAME} >+ WebKit >+ ${EGL_LIBRARIES} >+ ${LIBXKBCOMMON_LIBRARIES} >+ ${OPENGLES2_LIBRARIES} >+ ${WAYLAND_LIBRARIES} >+ ${WPE_LIBRARIES} >+ ${WPEBACKEND_FDO_LIBRARIES} >+) >+ >+add_custom_command( >+ OUTPUT ${DERIVED_SOURCES_MINIBROWSER_DIR}/xdg-shell-unstable-v6-protocol.c >+ MAIN_DEPENDENCY ${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/xdg-shell-unstable-v6.xml >+ DEPENDS ${DERIVED_SOURCES_MINIBROWSER_DIR}/xdg-shell-unstable-v6-client-protocol.h >+ COMMAND ${WAYLAND_SCANNER} code ${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/xdg-shell-unstable-v6.xml ${DERIVED_SOURCES_MINIBROWSER_DIR}/xdg-shell-unstable-v6-protocol.c >+ VERBATIM) >+ >+add_custom_command( >+ OUTPUT ${DERIVED_SOURCES_MINIBROWSER_DIR}/xdg-shell-unstable-v6-client-protocol.h >+ MAIN_DEPENDENCY ${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/xdg-shell-unstable-v6.xml >+ COMMAND ${WAYLAND_SCANNER} client-header ${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/xdg-shell-unstable-v6.xml ${DERIVED_SOURCES_MINIBROWSER_DIR}/xdg-shell-unstable-v6-client-protocol.h >+ VERBATIM) >+ >+if (DEVELOPER_MODE) >+ add_definitions(-DWEBKIT_INJECTED_BUNDLE_PATH="${CMAKE_LIBRARY_OUTPUT_DIRECTORY}") >+endif () >+ >+include_directories(${MiniBrowser_INCLUDE_DIRECTORIES}) >+include_directories(SYSTEM ${MiniBrowser_SYSTEM_INCLUDE_DIRECTORIES}) >+add_executable(MiniBrowser ${MiniBrowser_SOURCES}) >+target_link_libraries(MiniBrowser ${MiniBrowser_LIBRARIES}) >+ >+install(TARGETS MiniBrowser DESTINATION "${LIBEXEC_INSTALL_DIR}") >diff --git a/Tools/MiniBrowser/wpe/WlGlueHost.cpp b/Tools/MiniBrowser/wpe/WlGlueHost.cpp >new file mode 100644 >index 00000000000..bfd00774cad >--- /dev/null >+++ b/Tools/MiniBrowser/wpe/WlGlueHost.cpp >@@ -0,0 +1,444 @@ >+/* >+ * Copyright (C) 2018 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "cmakeconfig.h" >+#include "WlGlueHost.h" >+ >+#include "WlGlueWindow.h" >+#include <GLES2/gl2.h> >+#include <GLES2/gl2ext.h> >+#include <cstdio> >+#include <cstring> >+#include <linux/input.h> >+#include <memory> >+#include <sys/mman.h> >+#include <unistd.h> >+ >+namespace WlGlue { >+ >+struct EventSource { >+ static GSourceFuncs sourceFuncs; >+ >+ GSource source; >+ GPollFD pfd; >+ struct wl_display* display; >+}; >+ >+GSourceFuncs EventSource::sourceFuncs = { >+ // prepare >+ [](GSource* base, gint* timeout) -> gboolean >+ { >+ auto* source = reinterpret_cast<EventSource*>(base); >+ struct wl_display* display = source->display; >+ >+ *timeout = -1; >+ >+ wl_display_dispatch_pending(display); >+ wl_display_flush(display); >+ >+ return FALSE; >+ }, >+ // check >+ [](GSource* base) -> gboolean >+ { >+ auto* source = reinterpret_cast<EventSource*>(base); >+ return !!source->pfd.revents; >+ }, >+ // dispatch >+ [](GSource* base, GSourceFunc, gpointer) -> gboolean >+ { >+ auto* source = reinterpret_cast<EventSource*>(base); >+ struct wl_display* display = source->display; >+ >+ if (source->pfd.revents & G_IO_IN) >+ wl_display_dispatch(display); >+ >+ if (source->pfd.revents & (G_IO_ERR | G_IO_HUP)) >+ return FALSE; >+ >+ source->pfd.revents = 0; >+ return TRUE; >+ }, >+ nullptr, // finalize >+ nullptr, // closure_callback >+ nullptr, // closure_marshall >+}; >+ >+const struct wl_registry_listener Host::s_registryListener = { >+ // global >+ [](void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t) >+ { >+ auto* host = static_cast<Host*>(data); >+ >+ if (!std::strcmp(interface, "wl_compositor")) >+ host->m_compositor = static_cast<struct wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 1)); >+ >+ if (!std::strcmp(interface, "zxdg_shell_v6")) >+ host->m_xdgV6 = static_cast<struct zxdg_shell_v6*>(wl_registry_bind(registry, name, &zxdg_shell_v6_interface, 1)); >+ >+ if (!std::strcmp(interface, "wl_seat")) >+ host->m_seat = static_cast<struct wl_seat*>(wl_registry_bind(registry, name, &wl_seat_interface, 4)); >+ }, >+ // global_remove >+ [](void*, struct wl_registry*, uint32_t) { }, >+}; >+ >+const struct zxdg_shell_v6_listener Host::s_xdg6ShellListener = { >+ // ping >+ [](void*, struct zxdg_shell_v6* shell, uint32_t serial) >+ { >+ zxdg_shell_v6_pong(shell, serial); >+ }, >+}; >+ >+const struct wl_pointer_listener Host::s_pointerListener = { >+ // enter >+ [](void* data, struct wl_pointer*, uint32_t /*serial*/, struct wl_surface* surface, wl_fixed_t, wl_fixed_t) >+ { >+ auto& seatData = static_cast<Host*>(data)->m_seatData; >+ >+ auto it = seatData.clients.find(surface); >+ if (it != seatData.clients.end()) >+ seatData.pointer.target = *it; >+ }, >+ // leave >+ [](void* data, struct wl_pointer*, uint32_t /*serial*/, struct wl_surface* surface) >+ { >+ auto& seatData = static_cast<Host*>(data)->m_seatData; >+ >+ auto it = seatData.clients.find(surface); >+ if (it != seatData.clients.end() && seatData.pointer.target.first == it->first) >+ seatData.pointer.target = { }; >+ }, >+ // motion >+ [](void* data, struct wl_pointer*, uint32_t time, wl_fixed_t fixedX, wl_fixed_t fixedY) >+ { >+ auto& seatData = static_cast<Host*>(data)->m_seatData; >+ >+ int x = wl_fixed_to_int(fixedX); >+ int y = wl_fixed_to_int(fixedY); >+ seatData.pointer.coords = { x, y }; >+ >+ if (seatData.pointer.target.first) { >+ struct wpe_input_pointer_event event = { wpe_input_pointer_event_type_motion, >+ time, x, y, seatData.pointer.button, seatData.pointer.state }; >+ seatData.pointer.target.second->dispatchInputPointerEvent(&event); >+ } >+ }, >+ // button >+ [](void* data, struct wl_pointer*, uint32_t /*serial*/, uint32_t time, uint32_t button, uint32_t state) >+ { >+ auto& seatData = static_cast<Host*>(data)->m_seatData; >+ >+ if (button >= BTN_MOUSE) >+ button = button - BTN_MOUSE + 1; >+ else >+ button = 0; >+ >+ seatData.pointer.button = !!state ? button : 0; >+ seatData.pointer.state = state; >+ >+ if (seatData.pointer.target.first) { >+ struct wpe_input_pointer_event event = { wpe_input_pointer_event_type_button, >+ time, seatData.pointer.coords.first, seatData.pointer.coords.second, button, state }; >+ seatData.pointer.target.second->dispatchInputPointerEvent(&event); >+ } >+ }, >+ // axis >+ [](void* data, struct wl_pointer*, uint32_t time, uint32_t axis, wl_fixed_t value) >+ { >+ auto& seatData = static_cast<Host*>(data)->m_seatData; >+ >+ if (seatData.pointer.target.first) { >+ struct wpe_input_axis_event event = { wpe_input_axis_event_type_motion, >+ time, seatData.pointer.coords.first, seatData.pointer.coords.second, axis, -wl_fixed_to_int(value) }; >+ seatData.pointer.target.second->dispatchInputAxisEvent(&event); >+ } >+ }, >+}; >+ >+const struct wl_keyboard_listener Host::s_keyboardListener = { >+ // keymap >+ [](void* data, struct wl_keyboard*, uint32_t format, int fd, uint32_t size) >+ { >+ auto& seatData = static_cast<Host*>(data)->m_seatData; >+ >+ if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { >+ close(fd); >+ return; >+ } >+ >+ void* mapping = mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0); >+ if (mapping == MAP_FAILED) { >+ close(fd); >+ return; >+ } >+ >+ auto& xkb = seatData.xkb; >+ xkb.keymap = xkb_keymap_new_from_string(xkb.context, static_cast<char*>(mapping), >+ XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); >+ munmap(mapping, size); >+ close(fd); >+ >+ if (!xkb.keymap) >+ return; >+ >+ xkb.state = xkb_state_new(xkb.keymap); >+ if (!xkb.state) >+ return; >+ >+ xkb.indexes.control = xkb_keymap_mod_get_index(xkb.keymap, XKB_MOD_NAME_CTRL); >+ xkb.indexes.alt = xkb_keymap_mod_get_index(xkb.keymap, XKB_MOD_NAME_ALT); >+ xkb.indexes.shift = xkb_keymap_mod_get_index(xkb.keymap, XKB_MOD_NAME_SHIFT); >+ }, >+ // enter >+ [](void* data, struct wl_keyboard*, uint32_t /*serial*/, struct wl_surface* surface, struct wl_array*) >+ { >+ auto& seatData = static_cast<Host*>(data)->m_seatData; >+ >+ auto it = seatData.clients.find(surface); >+ if (it != seatData.clients.end()) >+ seatData.keyboard.target = *it; >+ }, >+ // leave >+ [](void* data, struct wl_keyboard*, uint32_t /*serial*/, struct wl_surface* surface) >+ { >+ auto& seatData = static_cast<Host*>(data)->m_seatData; >+ >+ auto it = seatData.clients.find(surface); >+ if (it != seatData.clients.end() && seatData.keyboard.target.first == it->first) >+ seatData.keyboard.target = { nullptr, nullptr }; >+ }, >+ // key >+ [](void* data, struct wl_keyboard*, uint32_t /*serial*/, uint32_t time, uint32_t key, uint32_t state) >+ { >+ auto& host = *static_cast<Host*>(data); >+ >+ // IDK. >+ key += 8; >+ >+ host.handleKeyEvent(key, state, time); >+ >+ auto& seatData = host.m_seatData; >+ if (!seatData.repeatInfo.rate) >+ return; >+ >+ if (state == WL_KEYBOARD_KEY_STATE_RELEASED >+ && seatData.repeatData.key == key) { >+ if (seatData.repeatData.eventSource) >+ g_source_remove(seatData.repeatData.eventSource); >+ seatData.repeatData = { 0, 0, 0, 0 }; >+ } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED >+ && xkb_keymap_key_repeats(seatData.xkb.keymap, key)) { >+ >+ if (seatData.repeatData.eventSource) >+ g_source_remove(seatData.repeatData.eventSource); >+ >+ auto sourceID = g_timeout_add(seatData.repeatInfo.delay, [](void* data) -> gboolean { >+ auto& host = *static_cast<Host*>(data); >+ auto& seatData = host.m_seatData; >+ host.handleKeyEvent(seatData.repeatData.key, seatData.repeatData.state, seatData.repeatData.time); >+ seatData.repeatData.eventSource = g_timeout_add(seatData.repeatInfo.rate, [](void* data) -> gboolean { >+ auto& host = *static_cast<Host*>(data); >+ auto& seatData = host.m_seatData; >+ host.handleKeyEvent(seatData.repeatData.key, seatData.repeatData.state, seatData.repeatData.time); >+ return G_SOURCE_CONTINUE; >+ }, data); >+ return G_SOURCE_REMOVE; >+ }, data); >+ seatData.repeatData = { key, time, state, sourceID }; >+ } >+ }, >+ // modifiers >+ [](void* data, struct wl_keyboard*, uint32_t /*serial*/, uint32_t depressedMods, uint32_t latchedMods, uint32_t lockedMods, uint32_t group) >+ { >+ auto& xkb = static_cast<Host*>(data)->m_seatData.xkb; >+ >+ xkb_state_update_mask(xkb.state, depressedMods, latchedMods, lockedMods, 0, 0, group); >+ >+ auto& modifiers = xkb.modifiers; >+ modifiers = 0; >+ auto component = static_cast<xkb_state_component>(XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); >+ if (xkb_state_mod_index_is_active(xkb.state, xkb.indexes.control, component)) >+ modifiers |= wpe_input_keyboard_modifier_control; >+ if (xkb_state_mod_index_is_active(xkb.state, xkb.indexes.alt, component)) >+ modifiers |= wpe_input_keyboard_modifier_alt; >+ if (xkb_state_mod_index_is_active(xkb.state, xkb.indexes.shift, component)) >+ modifiers |= wpe_input_keyboard_modifier_shift; >+ }, >+ // repeat_info >+ [](void* data, struct wl_keyboard*, int32_t rate, int32_t delay) >+ { >+ auto& seatData = static_cast<Host*>(data)->m_seatData; >+ >+ auto& repeatInfo = seatData.repeatInfo; >+ repeatInfo = { rate, delay }; >+ >+ // A rate of zero disables any repeating. >+ if (!rate) { >+ auto& repeatData = seatData.repeatData; >+ if (repeatData.eventSource) { >+ g_source_remove(repeatData.eventSource); >+ repeatData = { 0, 0, 0, 0 }; >+ } >+ } >+ }, >+}; >+ >+const struct wl_seat_listener Host::s_seatListener = { >+ // capabilities >+ [](void* data, struct wl_seat* seat, uint32_t capabilities) >+ { >+ auto* host = static_cast<Host*>(data); >+ auto& seatData = host->m_seatData; >+ >+ // WL_SEAT_CAPABILITY_POINTER >+ const bool hasPointerCap = capabilities & WL_SEAT_CAPABILITY_POINTER; >+ if (hasPointerCap && !seatData.pointer.object) { >+ seatData.pointer.object = wl_seat_get_pointer(seat); >+ wl_pointer_add_listener(seatData.pointer.object, &s_pointerListener, host); >+ } >+ if (!hasPointerCap && seatData.pointer.object) { >+ wl_pointer_destroy(seatData.pointer.object); >+ seatData.pointer.object = nullptr; >+ } >+ >+ // WL_SEAT_CAPABILITY_KEYBOARD >+ const bool hasKeyboardCap = capabilities & WL_SEAT_CAPABILITY_KEYBOARD; >+ if (hasKeyboardCap && !seatData.keyboard.object) { >+ seatData.keyboard.object = wl_seat_get_keyboard(seat); >+ wl_keyboard_add_listener(seatData.keyboard.object, &s_keyboardListener, host); >+ } >+ if (!hasKeyboardCap && seatData.keyboard.object) { >+ wl_keyboard_destroy(seatData.keyboard.object); >+ seatData.keyboard.object = nullptr; >+ } >+ }, >+ // name >+ [](void*, struct wl_seat*, const char*) { } >+}; >+ >+static const struct zxdg_surface_v6_listener s_xdg6SurfaceListener = { >+ // configure >+ [](void*, struct zxdg_surface_v6* surface, uint32_t serial) >+ { >+ zxdg_surface_v6_ack_configure(surface, serial); >+ }, >+}; >+ >+static const struct zxdg_toplevel_v6_listener s_xdg6ToplevelListener = { >+ // configure >+ [](void*, struct zxdg_toplevel_v6*, int32_t /*width*/, int32_t /*height*/, struct wl_array*) >+ { >+ // FIXME: dispatch the size against wpe_view_backend. >+ }, >+ // close >+ [](void*, struct zxdg_toplevel_v6*) { }, >+}; >+ >+Host::Host() >+{ >+ m_display = wl_display_connect(nullptr); >+ if (!m_display) >+ return; >+ >+ { >+ auto* registry = wl_display_get_registry(m_display); >+ wl_registry_add_listener(registry, &s_registryListener, this); >+ wl_display_roundtrip(m_display); >+ >+ if (m_xdgV6) >+ zxdg_shell_v6_add_listener(m_xdgV6, &s_xdg6ShellListener, nullptr); >+ >+ if (m_seat) >+ wl_seat_add_listener(m_seat, &s_seatListener, this); >+ >+ m_seatData.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); >+ m_seatData.xkb.composeTable = xkb_compose_table_new_from_locale(m_seatData.xkb.context, setlocale(LC_CTYPE, nullptr), XKB_COMPOSE_COMPILE_NO_FLAGS); >+ if (m_seatData.xkb.composeTable) >+ m_seatData.xkb.composeState = xkb_compose_state_new(m_seatData.xkb.composeTable, XKB_COMPOSE_STATE_NO_FLAGS); >+ } >+ >+ m_eventSource = g_source_new(&EventSource::sourceFuncs, sizeof(EventSource)); >+ { >+ auto& source = *reinterpret_cast<EventSource*>(m_eventSource); >+ source.display = m_display; >+ >+ source.pfd.fd = wl_display_get_fd(m_display); >+ source.pfd.events = G_IO_IN | G_IO_ERR | G_IO_HUP; >+ source.pfd.revents = 0; >+ g_source_add_poll(&source.source, &source.pfd); >+ >+ g_source_set_priority(&source.source, G_PRIORITY_HIGH + 30); >+ g_source_set_can_recurse(&source.source, TRUE); >+ g_source_attach(&source.source, g_main_context_get_thread_default()); >+ } >+ >+ m_eglDisplay = eglGetDisplay(m_display); >+ if (m_eglDisplay == EGL_NO_DISPLAY) >+ return; >+ eglInitialize(m_eglDisplay, nullptr, nullptr); >+} >+ >+Host::~Host() >+{ >+ if (m_eventSource) { >+ g_source_destroy(m_eventSource); >+ g_source_unref(m_eventSource); >+ } >+ >+ if (m_eglDisplay != EGL_NO_DISPLAY) >+ eglTerminate(m_eglDisplay); >+ >+ if (m_display) >+ wl_display_disconnect(m_display); >+} >+ >+void Host::handleKeyEvent(uint32_t key, uint32_t state, uint32_t time) >+{ >+ auto& xkb = m_seatData.xkb; >+ uint32_t keysym = xkb_state_key_get_one_sym(xkb.state, key); >+ uint32_t unicode = xkb_state_key_get_utf32(xkb.state, key); >+ >+ if (xkb.composeState >+ && state == WL_KEYBOARD_KEY_STATE_PRESSED >+ && xkb_compose_state_feed(xkb.composeState, keysym) == XKB_COMPOSE_FEED_ACCEPTED >+ && xkb_compose_state_get_status(xkb.composeState) == XKB_COMPOSE_COMPOSED) { >+ keysym = xkb_compose_state_get_one_sym(xkb.composeState); >+ unicode = xkb_keysym_to_utf32(keysym); >+ } >+ >+ if (m_seatData.keyboard.target.first) { >+ struct wpe_input_keyboard_event event = { time, keysym, unicode, !!state, xkb.modifiers }; >+ m_seatData.keyboard.target.second->dispatchInputKeyboardEvent(&event); >+ } >+} >+ >+void Host::addWindowClient(struct wl_surface* surface, WindowClient& client) >+{ >+ m_seatData.clients.insert({ surface, &client }); >+} >+ >+} // namespace WlGlue >diff --git a/Tools/MiniBrowser/wpe/WlGlueHost.h b/Tools/MiniBrowser/wpe/WlGlueHost.h >new file mode 100644 >index 00000000000..782b00e62dc >--- /dev/null >+++ b/Tools/MiniBrowser/wpe/WlGlueHost.h >@@ -0,0 +1,114 @@ >+/* >+ * Copyright (C) 2018 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include "xdg-shell-unstable-v6-client-protocol.h" >+#include <glib.h> >+#include <wayland-egl.h> >+#include <EGL/egl.h> >+#include <EGL/eglext.h> >+#include <unordered_map> >+#include <wpe/wpe.h> >+#include <xkbcommon/xkbcommon.h> >+#include <xkbcommon/xkbcommon-compose.h> >+ >+namespace WlGlue { >+ >+class WindowClient; >+ >+class Host { >+public: >+ Host(); >+ ~Host(); >+ >+ EGLDisplay eglDisplay() const { return m_eglDisplay; } >+ struct wl_compositor* compositor() const { return m_compositor; } >+ struct zxdg_shell_v6* xdgV6() const { return m_xdgV6; } >+ >+ void addWindowClient(struct wl_surface*, WindowClient&); >+ >+private: >+ static const struct wl_registry_listener s_registryListener; >+ static const struct zxdg_shell_v6_listener s_xdg6ShellListener; >+ static const struct wl_pointer_listener s_pointerListener; >+ static const struct wl_keyboard_listener s_keyboardListener; >+ static const struct wl_seat_listener s_seatListener; >+ >+ void handleKeyEvent(uint32_t key, uint32_t state, uint32_t time); >+ >+ struct SeatData { >+ std::unordered_map<struct wl_surface*, WindowClient*> clients; >+ >+ struct { >+ struct wl_pointer* object { nullptr }; >+ std::pair<struct wl_surface*, WindowClient*> target; >+ std::pair<int, int> coords { 0, 0 }; >+ uint32_t button { 0 }; >+ uint32_t state { 0 }; >+ } pointer; >+ >+ struct { >+ struct wl_keyboard* object { nullptr }; >+ std::pair<struct wl_surface*, struct WindowClient*> target; >+ } keyboard; >+ >+ struct { >+ struct xkb_context* context { nullptr }; >+ struct xkb_keymap* keymap { nullptr }; >+ struct xkb_state* state { nullptr }; >+ struct { >+ xkb_mod_index_t control { 0 }; >+ xkb_mod_index_t alt { 0 }; >+ xkb_mod_index_t shift { 0 }; >+ } indexes; >+ uint8_t modifiers { 0 }; >+ struct xkb_compose_table* composeTable { nullptr }; >+ struct xkb_compose_state* composeState { nullptr }; >+ } xkb; >+ >+ struct { >+ int32_t rate { 0 }; >+ int32_t delay { 0 }; >+ } repeatInfo; >+ >+ struct { >+ uint32_t key { 0 }; >+ uint32_t time { 0 }; >+ uint32_t state { 0 }; >+ uint32_t eventSource { 0 }; >+ } repeatData; >+ >+ } m_seatData; >+ >+ struct wl_display* m_display { nullptr }; >+ struct wl_compositor* m_compositor { nullptr }; >+ struct zxdg_shell_v6* m_xdgV6 { nullptr }; >+ struct wl_seat* m_seat { nullptr }; >+ GSource* m_eventSource { nullptr }; >+ EGLDisplay m_eglDisplay { nullptr }; >+}; >+ >+} // namespace WlGlue >diff --git a/Tools/MiniBrowser/wpe/WlGlueWindow.cpp b/Tools/MiniBrowser/wpe/WlGlueWindow.cpp >new file mode 100644 >index 00000000000..3a9c82ee207 >--- /dev/null >+++ b/Tools/MiniBrowser/wpe/WlGlueWindow.cpp >@@ -0,0 +1,246 @@ >+/* >+ * Copyright (C) 2018 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "cmakeconfig.h" >+#include "WlGlueWindow.h" >+ >+#include <GLES2/gl2ext.h> >+ >+namespace WlGlue { >+ >+static EGLint s_configAttributes[] = { >+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT, >+ EGL_RED_SIZE, 1, >+ EGL_GREEN_SIZE, 1, >+ EGL_BLUE_SIZE, 1, >+ EGL_ALPHA_SIZE, 0, >+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, >+ EGL_NONE >+}; >+ >+static EGLint s_contextAttributes[] = { >+ EGL_CONTEXT_CLIENT_VERSION, 2, >+ EGL_NONE >+}; >+ >+static PFNEGLCREATEIMAGEKHRPROC createImage; >+static PFNEGLDESTROYIMAGEKHRPROC destroyImage; >+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC imageTargetTexture2D; >+ >+const struct zxdg_surface_v6_listener Window::s_xdg6SurfaceListener = { >+ // configure >+ [](void*, struct zxdg_surface_v6* surface, uint32_t serial) >+ { >+ zxdg_surface_v6_ack_configure(surface, serial); >+ }, >+}; >+ >+const struct zxdg_toplevel_v6_listener Window::s_xdg6ToplevelListener = { >+ // configure >+ [](void*, struct zxdg_toplevel_v6*, int32_t /*width*/, int32_t /*height*/, struct wl_array*) >+ { >+ // FIXME: dispatch the size against wpe_view_backend. >+ }, >+ // close >+ [](void*, struct zxdg_toplevel_v6*) { }, >+}; >+ >+Window::Window(Host& host, WindowClient& client) >+ : m_host(host) >+ , m_client(client) >+{ >+ EGLConfig eglConfig; >+ { >+ EGLint count = 0; >+ if (!eglGetConfigs(m_host.eglDisplay(), nullptr, 0, &count) || count < 1) >+ return; >+ >+ EGLConfig* configs = g_new0(EGLConfig, count); >+ EGLint matched = 0; >+ if (eglChooseConfig(m_host.eglDisplay(), s_configAttributes, configs, count, &matched) && !!matched) >+ eglConfig = configs[0]; >+ g_free(configs); >+ } >+ >+ if (!eglBindAPI(EGL_OPENGL_ES_API)) >+ return; >+ >+ m_eglContext = eglCreateContext(m_host.eglDisplay(), eglConfig, EGL_NO_CONTEXT, s_contextAttributes); >+ if (!m_eglContext) >+ return; >+ >+ m_surface = wl_compositor_create_surface(m_host.compositor()); >+ if (m_host.xdgV6()) { >+ m_xdg6Surface = zxdg_shell_v6_get_xdg_surface(m_host.xdgV6(), m_surface); >+ zxdg_surface_v6_add_listener(m_xdg6Surface, &s_xdg6SurfaceListener, nullptr); >+ m_xdg6Toplevel = zxdg_surface_v6_get_toplevel(m_xdg6Surface); >+ if (m_xdg6Toplevel) { >+ zxdg_toplevel_v6_add_listener(m_xdg6Toplevel, &s_xdg6ToplevelListener, nullptr); >+ zxdg_toplevel_v6_set_title(m_xdg6Toplevel, "WPE"); >+ wl_surface_commit(m_surface); >+ } >+ } >+ >+ m_eglWindow = wl_egl_window_create(m_surface, 1280, 720); >+ >+ auto createPlatformWindowSurface = >+ reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT")); >+ m_eglSurface = createPlatformWindowSurface(m_host.eglDisplay(), eglConfig, m_eglWindow, nullptr); >+ if (!m_eglSurface) >+ return; >+ >+ eglMakeCurrent(m_host.eglDisplay(), m_eglSurface, m_eglSurface, m_eglContext); >+ >+ { >+ 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"; >+ >+ GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); >+ glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr); >+ glCompileShader(vertexShader); >+ >+ GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); >+ glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr); >+ glCompileShader(fragmentShader); >+ >+ m_program = glCreateProgram(); >+ glAttachShader(m_program, vertexShader); >+ glAttachShader(m_program, fragmentShader); >+ glLinkProgram(m_program); >+ >+ glBindAttribLocation(m_program, 0, "pos"); >+ glBindAttribLocation(m_program, 1, "texture"); >+ m_textureUniform = glGetUniformLocation(m_program, "u_texture"); >+ } >+ { >+ glGenTextures(1, &m_viewTexture); >+ glBindTexture(GL_TEXTURE_2D, m_viewTexture); >+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); >+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); >+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); >+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); >+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1280, 720, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); >+ glBindTexture(GL_TEXTURE_2D, 0); >+ } >+ >+ m_host.addWindowClient(m_surface, m_client); >+} >+ >+const struct wl_callback_listener Window::s_frameListener = { >+ // frame >+ [](void* data, struct wl_callback* callback, uint32_t) >+ { >+ if (callback) >+ wl_callback_destroy(callback); >+ >+ auto& window = *static_cast<Window*>(data); >+ window.m_client.frameDisplayed(); >+ >+ if (window.m_committed.image) >+ destroyImage(window.m_host.eglDisplay(), window.m_committed.image); >+ if (window.m_committed.bufferResource) >+ window.m_client.releaseBufferResource(window.m_committed.bufferResource); >+ window.m_committed = { nullptr, nullptr }; >+ } >+}; >+ >+void Window::displayBuffer(struct wl_resource* bufferResource) >+{ >+ if (!m_eglContext) >+ return; >+ >+ eglMakeCurrent(m_host.eglDisplay(), m_eglSurface, m_eglSurface, m_eglContext); >+ >+ glClearColor(1, 0, 0, 1); >+ glClear(GL_COLOR_BUFFER_BIT); >+ >+ if (!createImage) { >+ createImage = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR")); >+ destroyImage = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR")); >+ imageTargetTexture2D = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES")); >+ } >+ >+ glUseProgram(m_program); >+ >+ { >+ static EGLint s_imageAttributes[] = { >+ EGL_WAYLAND_PLANE_WL, 0, >+ EGL_NONE >+ }; >+ EGLImageKHR image = createImage(m_host.eglDisplay(), EGL_NO_CONTEXT, EGL_WAYLAND_BUFFER_WL, bufferResource, s_imageAttributes); >+ >+ glActiveTexture(GL_TEXTURE0); >+ glBindTexture(GL_TEXTURE_2D, m_viewTexture); >+ imageTargetTexture2D(GL_TEXTURE_2D, image); >+ glUniform1i(m_textureUniform, 0); >+ >+ m_committed = { bufferResource, image }; >+ } >+ >+ static const GLfloat s_vertices[4][2] = { >+ { -1.0, 1.0 }, >+ { 1.0, 1.0 }, >+ { -1.0, -1.0 }, >+ { 1.0, -1.0 }, >+ }; >+ >+ static const GLfloat s_texturePos[4][2] = { >+ { 0, 0 }, >+ { 1, 0 }, >+ { 0, 1 }, >+ { 1, 1 }, >+ }; >+ >+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, s_vertices); >+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, s_texturePos); >+ >+ glEnableVertexAttribArray(0); >+ glEnableVertexAttribArray(1); >+ >+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); >+ >+ glDisableVertexAttribArray(0); >+ glDisableVertexAttribArray(1); >+ >+ struct wl_callback* callback = wl_surface_frame(m_surface); >+ wl_callback_add_listener(callback, &s_frameListener, this); >+ >+ eglSwapBuffers(m_host.eglDisplay(), m_eglSurface); >+} >+ >+} // namespace WlGlue >diff --git a/Tools/MiniBrowser/wpe/WlGlueWindow.h b/Tools/MiniBrowser/wpe/WlGlueWindow.h >new file mode 100644 >index 00000000000..d58401555a7 >--- /dev/null >+++ b/Tools/MiniBrowser/wpe/WlGlueWindow.h >@@ -0,0 +1,77 @@ >+/* >+ * Copyright (C) 2018 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#pragma once >+ >+#include "WlGlueHost.h" >+#include <GLES2/gl2.h> >+ >+namespace WlGlue { >+ >+class WindowClient { >+public: >+ virtual ~WindowClient() = default; >+ >+ virtual void frameDisplayed() = 0; >+ virtual void releaseBufferResource(struct wl_resource*) = 0; >+ virtual void dispatchInputPointerEvent(struct wpe_input_pointer_event*) = 0; >+ virtual void dispatchInputAxisEvent(struct wpe_input_axis_event*) = 0; >+ virtual void dispatchInputKeyboardEvent(struct wpe_input_keyboard_event*) = 0; >+}; >+ >+class Window { >+public: >+ Window(Host&, WindowClient&); >+ ~Window() = default; >+ >+ void displayBuffer(struct wl_resource*); >+ >+private: >+ static const struct wl_callback_listener s_frameListener; >+ static const struct zxdg_surface_v6_listener s_xdg6SurfaceListener; >+ static const struct zxdg_toplevel_v6_listener s_xdg6ToplevelListener; >+ >+ Host& m_host; >+ WindowClient& m_client; >+ >+ struct wl_surface* m_surface { nullptr }; >+ struct zxdg_surface_v6* m_xdg6Surface { nullptr }; >+ struct zxdg_toplevel_v6* m_xdg6Toplevel { nullptr }; >+ >+ struct wl_egl_window* m_eglWindow { nullptr }; >+ EGLContext m_eglContext { nullptr }; >+ EGLSurface m_eglSurface { nullptr }; >+ >+ GLuint m_program { 0 }; >+ GLuint m_textureUniform { 0 }; >+ GLuint m_viewTexture { 0 }; >+ >+ struct { >+ struct wl_resource* bufferResource { nullptr }; >+ EGLImageKHR image; >+ } m_committed; >+}; >+ >+} // namespace WlGlue >diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp >new file mode 100644 >index 00000000000..e553c2e136d >--- /dev/null >+++ b/Tools/MiniBrowser/wpe/main.cpp >@@ -0,0 +1,251 @@ >+/* >+ * Copyright (C) 2018 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "cmakeconfig.h" >+ >+#include "HeadlessViewBackend.h" >+#include "WlGlueHost.h" >+#include "WlGlueWindow.h" >+#include <gst/gst.h> >+#include <memory> >+#include <wpe/fdo.h> >+#include <wpe/fdo-egl.h> >+#include <wpe/webkit.h> >+ >+static const char** uriArguments; >+static const char** ignoreHosts; >+static gboolean headlessMode; >+static gboolean privateMode; >+static gboolean automationMode; >+static const char* cookiesFile; >+static const char* cookiesPolicy; >+static const char* proxy; >+ >+static const GOptionEntry commandLineOptions[] = >+{ >+ { "headless", 'h', 0, G_OPTION_ARG_NONE, &headlessMode, "Run in headless mode", nullptr }, >+ { "private", 'p', 0, G_OPTION_ARG_NONE, &privateMode, "Run in private browsing mode", nullptr }, >+ { "automation", 0, 0, G_OPTION_ARG_NONE, &automationMode, "Run in automation mode", nullptr }, >+ { "cookies-file", 'c', 0, G_OPTION_ARG_FILENAME, &cookiesFile, "Persistent cookie storage database file", "FILE" }, >+ { "cookies-policy", 0, 0, G_OPTION_ARG_STRING, &cookiesPolicy, "Cookies accept policy (always, never, no-third-party). Default: no-third-party", "POLICY" }, >+ { "proxy", 0, 0, G_OPTION_ARG_STRING, &proxy, "Set proxy", "PROXY" }, >+ { "ignore-host", 0, 0, G_OPTION_ARG_STRING_ARRAY, &ignoreHosts, "Set proxy ignore hosts", "HOSTS" }, >+ { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, nullptr, "[URL]" }, >+ { nullptr, 0, 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr } >+}; >+ >+class FdoBackend final : public WlGlue::WindowClient { >+public: >+ FdoBackend(GMainLoop* loop) >+ : m_loop(loop) >+ , m_host(std::make_unique<WlGlue::Host>()) >+ { >+ if (!m_host->eglDisplay()) >+ return; >+ >+ wpe_fdo_initialize_for_egl_display(m_host->eglDisplay()); >+ >+ m_window = std::make_unique<WlGlue::Window>(*m_host, *this); >+ >+ static struct wpe_view_backend_exportable_fdo_client exportableClient = { >+ // export_buffer_resource >+ [](void* data, struct wl_resource* bufferResource) >+ { >+ static_cast<FdoBackend*>(data)->m_window->displayBuffer(bufferResource); >+ }, >+ // padding >+ nullptr, nullptr, nullptr, nullptr >+ }; >+ m_exportable = wpe_view_backend_exportable_fdo_create(&exportableClient, this, 1280, 720); >+ } >+ >+ ~FdoBackend() >+ { >+ if (m_exportable) >+ wpe_view_backend_exportable_fdo_destroy(m_exportable); >+ } >+ >+ struct wpe_view_backend* viewBackend() const >+ { >+ return m_exportable ? wpe_view_backend_exportable_fdo_get_view_backend(m_exportable) : nullptr; >+ } >+ >+private: >+ void frameDisplayed() override >+ { >+ wpe_view_backend_exportable_fdo_dispatch_frame_complete(m_exportable); >+ } >+ >+ void releaseBufferResource(struct wl_resource* bufferResource) override >+ { >+ wpe_view_backend_exportable_fdo_dispatch_release_buffer(m_exportable, bufferResource); >+ } >+ >+ void dispatchInputPointerEvent(struct wpe_input_pointer_event* event) override >+ { >+ wpe_view_backend_dispatch_pointer_event(viewBackend(), event); >+ } >+ >+ void dispatchInputAxisEvent(struct wpe_input_axis_event* event) override >+ { >+ wpe_view_backend_dispatch_axis_event(viewBackend(), event); >+ } >+ >+ void dispatchInputKeyboardEvent(struct wpe_input_keyboard_event* event) override >+ { >+ if (event->pressed && event->modifiers & wpe_input_keyboard_modifier_control && event->keyCode == 'q') { >+ g_main_loop_quit(m_loop); >+ return; >+ } >+ >+ wpe_view_backend_dispatch_keyboard_event(viewBackend(), event); >+ } >+ >+ GMainLoop* m_loop { nullptr }; >+ std::unique_ptr<WlGlue::Host> m_host; >+ std::unique_ptr<WlGlue::Window> m_window; >+ struct wpe_view_backend_exportable_fdo* m_exportable { nullptr }; >+}; >+ >+static WebKitWebView* createWebViewForAutomationCallback(WebKitAutomationSession*, WebKitWebView* view) >+{ >+ return view; >+} >+ >+static void automationStartedCallback(WebKitWebContext*, WebKitAutomationSession* session, WebKitWebView* view) >+{ >+ auto* info = webkit_application_info_new(); >+ // FIXME: add version info when wpe has WebKitVersion.h >+ // webkit_application_info_set_version(info, WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION, WEBKIT_MICRO_VERSION); >+ webkit_automation_session_set_application_info(session, info); >+ webkit_application_info_unref(info); >+ >+ g_signal_connect(session, "create-web-view", G_CALLBACK(createWebViewForAutomationCallback), view); >+} >+ >+int main(int argc, char *argv[]) >+{ >+ // MiniBrowser only works with WPEBackend-fdo, so ensure no other backend is used, >+ // either by passing the WPE_BACKEND_LIBRARY env var or loading the default symlink. >+ g_setenv("WPE_BACKEND_LIBRARY", "libWPEBackend-fdo-0.1.so", TRUE); >+#if ENABLE_DEVELOPER_MODE >+ g_setenv("WEBKIT_INJECTED_BUNDLE_PATH", WEBKIT_INJECTED_BUNDLE_PATH, FALSE); >+#endif >+ >+ GOptionContext* context = g_option_context_new(nullptr); >+ g_option_context_add_main_entries(context, commandLineOptions, nullptr); >+ g_option_context_add_group(context, gst_init_get_option_group()); >+ >+ GError* error = nullptr; >+ if (!g_option_context_parse(context, &argc, &argv, &error)) { >+ g_printerr("Cannot parse arguments: %s\n", error->message); >+ g_error_free(error); >+ g_option_context_free(context); >+ >+ return 1; >+ } >+ g_option_context_free(context); >+ >+ auto* loop = g_main_loop_new(nullptr, FALSE); >+ >+ std::unique_ptr<FdoBackend> backend; >+ std::unique_ptr<HeadlessViewBackend> headless; >+ struct wpe_view_backend* wpeBackend = nullptr; >+ if (headlessMode) { >+ headless = std::make_unique<HeadlessViewBackend>(); >+ wpeBackend = headless->backend(); >+ } else { >+ backend = std::make_unique<FdoBackend>(loop); >+ wpeBackend = backend->viewBackend(); >+ } >+ >+ if (!wpeBackend) { >+ g_warning("Failed to create WPE view backend"); >+ g_main_loop_unref(loop); >+ return 1; >+ } >+ >+ auto* viewBackend = webkit_web_view_backend_new(wpeBackend, [](gpointer data) { >+ delete static_cast<FdoBackend*>(data); >+ }, backend.release()); >+ >+ auto* webContext = (privateMode || automationMode) ? webkit_web_context_new_ephemeral() : webkit_web_context_get_default(); >+ >+ if (cookiesPolicy) { >+ auto* cookieManager = webkit_web_context_get_cookie_manager(webContext); >+ auto* enumClass = static_cast<GEnumClass*>(g_type_class_ref(WEBKIT_TYPE_COOKIE_ACCEPT_POLICY)); >+ GEnumValue* enumValue = g_enum_get_value_by_nick(enumClass, cookiesPolicy); >+ if (enumValue) >+ webkit_cookie_manager_set_accept_policy(cookieManager, static_cast<WebKitCookieAcceptPolicy>(enumValue->value)); >+ g_type_class_unref(enumClass); >+ } >+ >+ if (cookiesFile && !webkit_web_context_is_ephemeral(webContext)) { >+ auto* cookieManager = webkit_web_context_get_cookie_manager(webContext); >+ auto storageType = g_str_has_suffix(cookiesFile, ".txt") ? WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT : WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE; >+ webkit_cookie_manager_set_persistent_storage(cookieManager, cookiesFile, storageType); >+ } >+ >+ if (proxy) { >+ auto* webkitProxySettings = webkit_network_proxy_settings_new(proxy, ignoreHosts); >+ webkit_web_context_set_network_proxy_settings(webContext, WEBKIT_NETWORK_PROXY_MODE_CUSTOM, webkitProxySettings); >+ webkit_network_proxy_settings_free(webkitProxySettings); >+ } >+ >+ const char* singleprocess = g_getenv("MINIBROWSER_SINGLEPROCESS"); >+ webkit_web_context_set_process_model(webContext, (singleprocess && *singleprocess) ? >+ WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS : WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES); >+ >+ auto* settings = webkit_settings_new_with_settings( >+ "enable-developer-extras", TRUE, >+ "enable-webgl", TRUE, >+ "enable-media-stream", TRUE, >+ nullptr); >+ >+ auto* webView = WEBKIT_WEB_VIEW(g_object_new(WEBKIT_TYPE_WEB_VIEW, >+ "backend", viewBackend, >+ "web-context", webContext, >+ "settings", settings, >+ "is-controlled-by-automation", automationMode, >+ nullptr)); >+ g_object_unref(settings); >+ >+ webkit_web_context_set_automation_allowed(webContext, automationMode); >+ g_signal_connect(webContext, "automation-started", G_CALLBACK(automationStartedCallback), webView); >+ >+ if (uriArguments) >+ webkit_web_view_load_uri(webView, uriArguments[0]); >+ else if (!automationMode) >+ webkit_web_view_load_uri(webView, "https://wpewebkit.org"); >+ >+ g_main_loop_run(loop); >+ >+ g_object_unref(webView); >+ if (privateMode) >+ g_object_unref(webContext); >+ g_main_loop_unref(loop); >+ >+ return 0; >+} >diff --git a/Tools/Scripts/run-minibrowser b/Tools/Scripts/run-minibrowser >index 86ccca0e33f..495440531ae 100755 >--- a/Tools/Scripts/run-minibrowser >+++ b/Tools/Scripts/run-minibrowser >@@ -44,7 +44,7 @@ my @jhbuildWrapper; > prohibitUnknownPort(); > setConfiguration(); > >-if (isGtk()) { >+if (isGtk() || isWPE()) { > # Check to see that all the frameworks are built. > checkFrameworks(); > >@@ -53,17 +53,6 @@ if (isGtk()) { > @jhbuildWrapper = wrapperPrefixIfNeeded(); > print "Starting MiniBrowser.\n"; > exec @jhbuildWrapper, $launcherPath, @ARGV or die; >-} elsif (isWPE()) { >- # Check to see that all the frameworks are built. >- checkFrameworks(); >- >- $launcherName = launcherName(); >- @jhbuildWrapper = wrapperPrefixIfNeeded(); >- $ENV{"WEBKIT_EXEC_PATH"} = catdir(productDir(), "bin"); >- $ENV{"WEBKIT_INJECTED_BUNDLE_PATH"} = catdir(productDir(), "lib"); >- $ENV{"LD_LIBRARY_PATH"} = catdir(productDir(), "lib") . (defined $ENV{"LD_LIBRARY_PATH"} ? ":" . $ENV{"LD_LIBRARY_PATH"} : "" ); >- print "Starting $launcherName \n"; >- exec @jhbuildWrapper, $launcherName, @ARGV or die; > } elsif (isAppleCocoaWebKit()) { > printHelpAndExitForRunAndDebugWebKitAppIfNeeded(); > exit exitStatus(runMiniBrowser()); >diff --git a/Tools/Scripts/run-webdriver-tests b/Tools/Scripts/run-webdriver-tests >index 4051a1a26fb..10f7fede66f 100755 >--- a/Tools/Scripts/run-webdriver-tests >+++ b/Tools/Scripts/run-webdriver-tests >@@ -49,9 +49,10 @@ option_parser.add_option('--timeout', action='store', type='int', dest='timeout' > help='Time in seconds until a test times out (use 0 to disable)') > option_parser.add_option('--json-output', action='store', metavar="FILE", > help='Write results to JSON file at the given path') >-option_parser.add_option('--display-server', choices=['xvfb', 'xorg', 'weston', 'wayland'], default='xvfb', >+option_parser.add_option('--display-server', choices=['xvfb', 'xorg', 'weston', 'wayland', 'headless'], default='xvfb', > help='"xvfb": Use a virtualized X11 server. "xorg": Use the current X11 session. ' >- '"weston": Use a virtualized Weston server. "wayland": Use the current wayland session.') >+ '"weston": Use a virtualized Weston server. "wayland": Use the current wayland session.' >+ '"headless": Headless mode in current session') > > options, args = option_parser.parse_args() > >diff --git a/Tools/Scripts/webkitdirs.pm b/Tools/Scripts/webkitdirs.pm >index 30700b625f3..357ddd4e08b 100755 >--- a/Tools/Scripts/webkitdirs.pm >+++ b/Tools/Scripts/webkitdirs.pm >@@ -1650,14 +1650,12 @@ sub launcherPath() > > sub launcherName() > { >- if (isGtk()) { >+ if (isGtk() || isWPE()) { > return "MiniBrowser"; > } elsif (isAppleMacWebKit()) { > return "Safari"; > } elsif (isAppleWinWebKit()) { > return "MiniBrowser"; >- } elsif (isWPE()) { >- return "dyz"; > } > } > >diff --git a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_driver_wpe.py b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_driver_wpe.py >index f025731b9ab..3ce48b0b7a5 100644 >--- a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_driver_wpe.py >+++ b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_driver_wpe.py >@@ -33,27 +33,21 @@ class WebDriverWPE(WebDriver): > return self._port._build_path('bin', 'WPEWebDriver') > > def browser_name(self): >- return 'dyz' >+ return 'MiniBrowser' >+ >+ def browser_path(self): >+ return self._port._build_path('bin', 'MiniBrowser') > > def browser_args(self): >- return ['--automation'] >+ args = ['--automation'] >+ if self._port._display_server == 'headless': >+ args.append('--headless') >+ return args > > def capabilities(self): > return {'wpe:browserOptions': { >- 'binary': self.browser_name(), >+ 'binary': self.browser_path(), > 'args': self.browser_args()}} > >- def browser_env(self): >- env = {} >- env['WEBKIT_EXEC_PATH'] = self._port._build_path('bin') >- try: >- ld_library_path = os.environ['LD_LIBRARY_PATH'] >- except KeyError: >- ld_library_path = None >- env['LD_LIBRARY_PATH'] = self._port._build_path('lib') >- if ld_library_path: >- env['LD_LIBRARY_PATH'] += ':' + ld_library_path >- return env >- > > register_driver('wpe', WebDriverWPE) >diff --git a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_test_runner_selenium.py b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_test_runner_selenium.py >index 4e58a3d252c..48f11124a14 100644 >--- a/Tools/Scripts/webkitpy/webdriver_tests/webdriver_test_runner_selenium.py >+++ b/Tools/Scripts/webkitpy/webdriver_tests/webdriver_test_runner_selenium.py >@@ -44,7 +44,7 @@ class WebDriverTestRunnerSelenium(object): > > def collect_tests(self, tests): > if self._driver.selenium_name() is None: >- return 0 >+ return [] > > skipped = [os.path.join(self._tests_dir, test) for test in self._expectations.skipped_tests()] > relative_tests_dir = os.path.join('imported', 'selenium', 'py', 'test') >diff --git a/Tools/wpe/jhbuild.modules b/Tools/wpe/jhbuild.modules >index 85d91455d47..f08621cac02 100644 >--- a/Tools/wpe/jhbuild.modules >+++ b/Tools/wpe/jhbuild.modules >@@ -23,7 +23,7 @@ > <dep package="libgpg-error"/> > <dep package="libgcrypt"/> > <dep package="libepoxy"/> >- <dep package="dyz"/> >+ <dep package="wayland-protocols"/> > </dependencies> > </metamodule> > >@@ -36,6 +36,8 @@ > href="http://cairographics.org"/> > <repository type="tarball" name="freedesktop.org" > href="http://www.freedesktop.org"/> >+ <repository type="tarball" name="wayland.freedesktop.org" >+ href="http://wayland.freedesktop.org"/> > <repository type="git" name="github.com" > href="https://github.com"/> > <repository type="tarball" name="github-tarball" >@@ -202,8 +204,11 @@ > version="1.4.3" repo="github-tarball"/> > </autotools> > >- <autotools id="dyz" supports-non-srcdir-builds="no"> >- <branch repo="github.com" module="Igalia/dyz" tag="4f196778c82ed72095e72c9d401cd2ff8ba36c60"/> >+ <autotools id="wayland-protocols" autogen-sh="configure"> >+ <branch module="releases/wayland-protocols-${version}.tar.xz" >+ version="1.12" >+ repo="wayland.freedesktop.org" >+ hash="sha256:3b19e8a9e1e19474756a7069db23b90ca9b8ebb438448c6063b4a7fc89b7c8b2"/> > </autotools> > > <meson id="graphene">
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
Flags:
ews-watchlist
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186345
:
342043
|
342246
|
342249
|
342250
|
342254