Title: [288814] trunk/Tools
Revision
288814
Author
[email protected]
Date
2022-01-31 07:14:28 -0800 (Mon, 31 Jan 2022)

Log Message

Support additional WPEToolingBackend types
https://bugs.webkit.org/show_bug.cgi?id=235745

Reviewed by Adrian Perez de Castro.

Split up code specific to the fdo backend to allow for additional WPE backend types to be
used. Add some platform defines based on the underlying backend.

This is a precursor to landing a PlayStation variant.

* wpe/backends/CMakeLists.txt:
* wpe/backends/HeadlessViewBackend.cpp:
(WPEToolingBackends::HeadlessInstance::singleton): Deleted.
(WPEToolingBackends::HeadlessViewBackend::HeadlessViewBackend): Deleted.
(WPEToolingBackends::HeadlessViewBackend::~HeadlessViewBackend): Deleted.
(WPEToolingBackends::HeadlessViewBackend::backend const): Deleted.
(WPEToolingBackends::HeadlessViewBackend::snapshot): Deleted.
(WPEToolingBackends::HeadlessViewBackend::updateSnapshot): Deleted.
(WPEToolingBackends::HeadlessViewBackend::vsync): Deleted.
* wpe/backends/HeadlessViewBackend.h:
* wpe/backends/PlatformWPE.cmake:
* wpe/backends/ViewBackend.cpp:
(WPEToolingBackends::ViewBackend::ViewBackend):
* wpe/backends/ViewBackend.h:
* wpe/backends/fdo/HeadlessViewBackendFdo.cpp: Copied from Tools/wpe/backends/HeadlessViewBackend.cpp.
(WPEToolingBackends::HeadlessInstance::singleton):
(WPEToolingBackends::HeadlessViewBackend::HeadlessViewBackend):
(WPEToolingBackends::HeadlessViewBackend::~HeadlessViewBackend):
(WPEToolingBackends::HeadlessViewBackend::backend const):
(WPEToolingBackends::HeadlessViewBackend::snapshot):
(WPEToolingBackends::HeadlessViewBackend::updateSnapshot):
(WPEToolingBackends::HeadlessViewBackend::vsync):
* wpe/backends/fdo/WindowViewBackend.cpp: Renamed from Tools/wpe/backends/WindowViewBackend.cpp.
* wpe/backends/fdo/WindowViewBackend.h: Renamed from Tools/wpe/backends/WindowViewBackend.h.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Tools/ChangeLog (288813 => 288814)


--- trunk/Tools/ChangeLog	2022-01-31 14:56:26 UTC (rev 288813)
+++ trunk/Tools/ChangeLog	2022-01-31 15:14:28 UTC (rev 288814)
@@ -1,3 +1,40 @@
+2022-01-31  Don Olmstead  <[email protected]>
+
+        Support additional WPEToolingBackend types
+        https://bugs.webkit.org/show_bug.cgi?id=235745
+
+        Reviewed by Adrian Perez de Castro.
+
+        Split up code specific to the fdo backend to allow for additional WPE backend types to be
+        used. Add some platform defines based on the underlying backend.
+
+        This is a precursor to landing a PlayStation variant.
+
+        * wpe/backends/CMakeLists.txt:
+        * wpe/backends/HeadlessViewBackend.cpp:
+        (WPEToolingBackends::HeadlessInstance::singleton): Deleted.
+        (WPEToolingBackends::HeadlessViewBackend::HeadlessViewBackend): Deleted.
+        (WPEToolingBackends::HeadlessViewBackend::~HeadlessViewBackend): Deleted.
+        (WPEToolingBackends::HeadlessViewBackend::backend const): Deleted.
+        (WPEToolingBackends::HeadlessViewBackend::snapshot): Deleted.
+        (WPEToolingBackends::HeadlessViewBackend::updateSnapshot): Deleted.
+        (WPEToolingBackends::HeadlessViewBackend::vsync): Deleted.
+        * wpe/backends/HeadlessViewBackend.h:
+        * wpe/backends/PlatformWPE.cmake:
+        * wpe/backends/ViewBackend.cpp:
+        (WPEToolingBackends::ViewBackend::ViewBackend):
+        * wpe/backends/ViewBackend.h:
+        * wpe/backends/fdo/HeadlessViewBackendFdo.cpp: Copied from Tools/wpe/backends/HeadlessViewBackend.cpp.
+        (WPEToolingBackends::HeadlessInstance::singleton):
+        (WPEToolingBackends::HeadlessViewBackend::HeadlessViewBackend):
+        (WPEToolingBackends::HeadlessViewBackend::~HeadlessViewBackend):
+        (WPEToolingBackends::HeadlessViewBackend::backend const):
+        (WPEToolingBackends::HeadlessViewBackend::snapshot):
+        (WPEToolingBackends::HeadlessViewBackend::updateSnapshot):
+        (WPEToolingBackends::HeadlessViewBackend::vsync):
+        * wpe/backends/fdo/WindowViewBackend.cpp: Renamed from Tools/wpe/backends/WindowViewBackend.cpp.
+        * wpe/backends/fdo/WindowViewBackend.h: Renamed from Tools/wpe/backends/WindowViewBackend.h.
+
 2022-01-31  Philippe Normand  <[email protected]>
 
         [Flatpak SDK] No longer updating due to expired GPG key

Modified: trunk/Tools/wpe/backends/CMakeLists.txt (288813 => 288814)


--- trunk/Tools/wpe/backends/CMakeLists.txt	2022-01-31 14:56:26 UTC (rev 288813)
+++ trunk/Tools/wpe/backends/CMakeLists.txt	2022-01-31 15:14:28 UTC (rev 288814)
@@ -7,13 +7,11 @@
 set(WPEToolingBackends_PUBLIC_HEADERS
     HeadlessViewBackend.h
     ViewBackend.h
-    WindowViewBackend.h
 )
 
 set(WPEToolingBackends_SOURCES
     HeadlessViewBackend.cpp
     ViewBackend.cpp
-    WindowViewBackend.cpp
 )
 
 set(WPEToolingBackends_PRIVATE_INCLUDE_DIRECTORIES
@@ -26,6 +24,10 @@
     WPE::libwpe
 )
 
+if (USE_CAIRO)
+    list(APPEND WPEToolingBackends_DEFINITIONS USE_CAIRO=1)
+endif ()
+
 set(WPEToolingBackends_INTERFACE_LIBRARIES WPEToolingBackends)
 set(WPEToolingBackends_INTERFACE_INCLUDE_DIRECTORIES ${WPEToolingBackends_FRAMEWORK_HEADERS_DIR})
 set(WPEToolingBackends_INTERFACE_DEPENDENCIES WPEToolingBackends_CopyHeaders)

Modified: trunk/Tools/wpe/backends/HeadlessViewBackend.cpp (288813 => 288814)


--- trunk/Tools/wpe/backends/HeadlessViewBackend.cpp	2022-01-31 14:56:26 UTC (rev 288813)
+++ trunk/Tools/wpe/backends/HeadlessViewBackend.cpp	2022-01-31 15:14:28 UTC (rev 288814)
@@ -25,182 +25,9 @@
 
 #include "HeadlessViewBackend.h"
 
-#include <cassert>
-#include <fcntl.h>
-#include <mutex>
-#include <unistd.h>
-
-#if WPE_FDO_CHECK_VERSION(1,7,0)
-#include <wayland-server.h>
-#include <wpe/unstable/fdo-shm.h>
-#endif
-
 namespace WPEToolingBackends {
 
-struct HeadlessInstance {
-    static const HeadlessInstance& singleton()
-    {
-        static std::once_flag s_onceFlag;
-        static HeadlessInstance s_instance;
-        std::call_once(s_onceFlag,
-            [] {
-#if WPE_FDO_CHECK_VERSION(1,7,0)
-                wpe_fdo_initialize_shm();
-#endif
-            });
-
-        return s_instance;
-    }
-};
-
-static cairo_user_data_key_t s_bufferKey;
-
-HeadlessViewBackend::HeadlessViewBackend(uint32_t width, uint32_t height)
-    : ViewBackend(width, height)
-{
-    // This should initialize the SHM mode.
-    HeadlessInstance::singleton();
-
-    static struct wpe_view_backend_exportable_fdo_client exportableClient = {
-        nullptr,
-        nullptr,
-#if WPE_FDO_CHECK_VERSION(1,7,0)
-        // export_shm_buffer
-        [](void* data, struct wpe_fdo_shm_exported_buffer* buffer)
-        {
-            auto& backend = *static_cast<HeadlessViewBackend*>(data);
-            backend.m_update.pending = true;
-
-            backend.updateSnapshot(buffer);
-            wpe_view_backend_exportable_fdo_dispatch_release_shm_exported_buffer(backend.m_exportable, buffer);
-        },
-#else
-        nullptr,
-#endif
-        nullptr,
-        nullptr,
-    };
-    m_exportable = wpe_view_backend_exportable_fdo_create(&exportableClient, this, width, height);
-
-    addActivityState(wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window);
-
-    {
-        uint32_t stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width);
-        uint8_t* buffer = new uint8_t[stride * m_height];
-        memset(buffer, 0, stride * m_height);
-
-        m_snapshot = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32,
-            m_width, m_height, stride);
-
-        cairo_surface_set_user_data(m_snapshot, &s_bufferKey, buffer,
-            [](void* data) {
-                auto* buffer = static_cast<uint8_t*>(data);
-                delete[] buffer;
-            });
-        cairo_surface_mark_dirty(m_snapshot);
-    }
-
 #if WPE_CHECK_VERSION(1, 11, 1)
-    wpe_view_backend_set_fullscreen_handler(backend(), onDOMFullScreenRequest, this);
-#endif
-
-    m_update.source = g_timeout_source_new(G_USEC_PER_SEC / 60000);
-    g_source_set_callback(m_update.source, [](gpointer data) -> gboolean {
-        static_cast<HeadlessViewBackend*>(data)->vsync();
-        return TRUE;
-    }, this, nullptr);
-    g_source_set_priority(m_update.source, G_PRIORITY_DEFAULT);
-    g_source_attach(m_update.source, g_main_context_default());
-}
-
-HeadlessViewBackend::~HeadlessViewBackend()
-{
-    if (m_update.source) {
-        g_source_destroy(m_update.source);
-        g_source_unref(m_update.source);
-    }
-
-    if (m_snapshot)
-        cairo_surface_destroy(m_snapshot);
-
-    if (m_exportable)
-        wpe_view_backend_exportable_fdo_destroy(m_exportable);
-}
-
-struct wpe_view_backend* HeadlessViewBackend::backend() const
-{
-    if (m_exportable)
-        return wpe_view_backend_exportable_fdo_get_view_backend(m_exportable);
-    return nullptr;
-}
-
-cairo_surface_t* HeadlessViewBackend::snapshot()
-{
-    return cairo_surface_reference(m_snapshot);
-}
-
-void HeadlessViewBackend::updateSnapshot(struct wpe_fdo_shm_exported_buffer* exportedBuffer)
-{
-#if WPE_FDO_CHECK_VERSION(1,7,0)
-    struct wl_shm_buffer* shmBuffer = wpe_fdo_shm_exported_buffer_get_shm_buffer(exportedBuffer);
-    {
-        auto format = wl_shm_buffer_get_format(shmBuffer);
-        if (format != WL_SHM_FORMAT_ARGB8888 && format != WL_SHM_FORMAT_XRGB8888)
-            return;
-    }
-
-    uint32_t bufferStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width);
-    uint8_t* buffer = new uint8_t[bufferStride * m_height];
-    memset(buffer, 0, bufferStride * m_height);
-
-    {
-        uint32_t width = std::min<uint32_t>(m_width, std::max(0, wl_shm_buffer_get_width(shmBuffer)));
-        uint32_t height = std::min<uint32_t>(m_height, std::max(0, wl_shm_buffer_get_height(shmBuffer)));
-        uint32_t stride = std::max(0, wl_shm_buffer_get_stride(shmBuffer));
-
-        wl_shm_buffer_begin_access(shmBuffer);
-        auto* data = ""
-
-        for (uint32_t y = 0; y < height; ++y) {
-            for (uint32_t x = 0; x < width; ++x) {
-                buffer[bufferStride * y + 4 * x + 0] = data[stride * y + 4 * x + 0];
-                buffer[bufferStride * y + 4 * x + 1] = data[stride * y + 4 * x + 1];
-                buffer[bufferStride * y + 4 * x + 2] = data[stride * y + 4 * x + 2];
-                buffer[bufferStride * y + 4 * x + 3] = data[stride * y + 4 * x + 3];
-            }
-        }
-
-        wl_shm_buffer_end_access(shmBuffer);
-    }
-
-    if (m_snapshot)
-        cairo_surface_destroy(m_snapshot);
-
-    m_snapshot = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32,
-        m_width, m_height, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width));
-
-    static cairo_user_data_key_t bufferKey;
-    cairo_surface_set_user_data(m_snapshot, &bufferKey, buffer,
-        [](void* data) {
-            auto* buffer = static_cast<uint8_t*>(data);
-            delete[] buffer;
-        });
-    cairo_surface_mark_dirty(m_snapshot);
-#else
-    (void)exportedBuffer;
-#endif
-}
-
-void HeadlessViewBackend::vsync()
-{
-#if WPE_FDO_CHECK_VERSION(1,7,0)
-    if (m_update.pending)
-        wpe_view_backend_exportable_fdo_dispatch_frame_complete(m_exportable);
-#endif
-    m_update.pending = false;
-}
-
-#if WPE_CHECK_VERSION(1, 11, 1)
 bool HeadlessViewBackend::onDOMFullScreenRequest(void* data, bool fullscreen)
 {
     auto& headless = *static_cast<HeadlessViewBackend*>(data);
@@ -224,5 +51,4 @@
 
 #endif
 
-
 } // namespace WPEToolingBackends

Modified: trunk/Tools/wpe/backends/HeadlessViewBackend.h (288813 => 288814)


--- trunk/Tools/wpe/backends/HeadlessViewBackend.h	2022-01-31 14:56:26 UTC (rev 288813)
+++ trunk/Tools/wpe/backends/HeadlessViewBackend.h	2022-01-31 15:14:28 UTC (rev 288814)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2016 Igalia S.L.
+ * Copyright (C) 2022 Sony Interactive Entertainment Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,8 +27,23 @@
 #pragma once
 
 #include "ViewBackend.h"
+
+#if defined(WPE_BACKEND_FDO)
+#include <wpe/fdo.h>
+
+using PlatformBuffer = struct wpe_fdo_shm_exported_buffer*;
+using PlatformViewBackend = struct wpe_view_backend_exportable_fdo*;
+#endif
+
+#if defined(USE_CAIRO) && USE_CAIRO
 #include <cairo.h>
+
+using PlatformImage = cairo_surface_t*;
+#endif
+
+#if defined(USE_GLIB) && USE_GLIB
 #include <glib.h>
+#endif
 
 namespace WPEToolingBackends {
 
@@ -38,10 +54,10 @@
 
     struct wpe_view_backend* backend() const override;
 
-    cairo_surface_t* snapshot();
+    PlatformImage snapshot();
 
 private:
-    void updateSnapshot(struct wpe_fdo_shm_exported_buffer*);
+    void updateSnapshot(PlatformBuffer);
     void vsync();
 
 #if WPE_CHECK_VERSION(1, 11, 1)
@@ -49,15 +65,15 @@
     void dispatchFullscreenEvent();
 #endif
 
+    PlatformViewBackend m_exportable { nullptr };
+    PlatformImage m_snapshot { nullptr };
 
-    struct wpe_view_backend_exportable_fdo* m_exportable { nullptr };
-
-    cairo_surface_t* m_snapshot { nullptr };
-
+#if defined(USE_GLIB) && USE_GLIB
     struct {
         GSource* source { nullptr };
         bool pending { false };
     } m_update;
+#endif
 
 #if WPE_CHECK_VERSION(1, 11, 1)
     bool m_is_fullscreen { false };

Modified: trunk/Tools/wpe/backends/PlatformWPE.cmake (288813 => 288814)


--- trunk/Tools/wpe/backends/PlatformWPE.cmake	2022-01-31 14:56:26 UTC (rev 288813)
+++ trunk/Tools/wpe/backends/PlatformWPE.cmake	2022-01-31 15:14:28 UTC (rev 288814)
@@ -5,16 +5,22 @@
 
 list(APPEND WPEToolingBackends_PUBLIC_HEADERS
     ${WPEToolingBackends_DERIVED_SOURCES_DIR}/xdg-shell-unstable-v6-client-protocol.h
+    fdo/WindowViewBackend.h
 )
 
 list(APPEND WPEToolingBackends_SOURCES
     ${WPEToolingBackends_DERIVED_SOURCES_DIR}/xdg-shell-unstable-v6-protocol.c
+
     atk/ViewBackendAtk.cpp
     atk/WebKitAccessibleApplication.cpp
+
+    fdo/HeadlessViewBackendFdo.cpp
+    fdo/WindowViewBackend.cpp
 )
 
 list(APPEND WPEToolingBackends_PRIVATE_INCLUDE_DIRECTORIES
     ${TOOLS_DIR}/wpe/backends/atk
+    ${TOOLS_DIR}/wpe/backends/fdo
 )
 
 list(APPEND WPEToolingBackends_SYSTEM_INCLUDE_DIRECTORIES
@@ -33,6 +39,7 @@
     ${WPEBACKEND_FDO_LIBRARIES}
 )
 
+list(APPEND WPEToolingBackends_DEFINITIONS USE_GLIB=1)
 list(APPEND WPEToolingBackends_PRIVATE_DEFINITIONS ${LIBEPOXY_DEFINITIONS})
 
 add_custom_command(
@@ -48,9 +55,12 @@
     COMMAND ${WAYLAND_SCANNER} client-header ${WAYLAND_PROTOCOLS_DATADIR}/unstable/xdg-shell/xdg-shell-unstable-v6.xml ${WPEToolingBackends_DERIVED_SOURCES_DIR}/xdg-shell-unstable-v6-client-protocol.h
     VERBATIM)
 
+list(APPEND WPEToolingBackends_DEFINITIONS WPE_BACKEND_FDO)
+list(APPEND WPEToolingBackends_PRIVATE_DEFINITIONS WPE_BACKEND="libWPEBackend-fdo-1.0.so")
+
 if (ENABLE_ACCESSIBILITY)
+    list(APPEND WPEToolingBackends_DEFINITIONS ENABLE_ACCESSIBILITY=1)
     list(APPEND WPEToolingBackends_PRIVATE_DEFINITIONS
-        ENABLE_ACCESSIBILITY=1
         GLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_40
     )
     list(APPEND WPEToolingBackends_LIBRARIES ATK::Bridge)

Modified: trunk/Tools/wpe/backends/ViewBackend.cpp (288813 => 288814)


--- trunk/Tools/wpe/backends/ViewBackend.cpp	2022-01-31 14:56:26 UTC (rev 288813)
+++ trunk/Tools/wpe/backends/ViewBackend.cpp	2022-01-31 15:14:28 UTC (rev 288814)
@@ -31,7 +31,7 @@
     : m_width(width)
     , m_height(height)
 {
-    wpe_loader_init("libWPEBackend-fdo-1.0.so");
+    wpe_loader_init(WPE_BACKEND);
 }
 
 ViewBackend::~ViewBackend() = default;

Modified: trunk/Tools/wpe/backends/ViewBackend.h (288813 => 288814)


--- trunk/Tools/wpe/backends/ViewBackend.h	2022-01-31 14:56:26 UTC (rev 288813)
+++ trunk/Tools/wpe/backends/ViewBackend.h	2022-01-31 15:14:28 UTC (rev 288814)
@@ -26,26 +26,12 @@
 #pragma once
 
 #include <memory>
-#include <wpe/fdo.h>
+#include <wpe/wpe.h>
 
 #if defined(ENABLE_ACCESSIBILITY) && ENABLE_ACCESSIBILITY
 typedef struct _AtkObject AtkObject;
 #endif
 
-typedef void* EGLConfig;
-typedef void* EGLContext;
-typedef void* EGLDisplay;
-struct wpe_fdo_egl_exported_image;
-
-#if WPE_FDO_CHECK_VERSION(1, 5, 0)
-struct wpe_fdo_shm_exported_buffer;
-#endif
-
-// Manually provide the EGL_CAST C++ definition in case eglplatform.h doesn't provide it.
-#ifndef EGL_CAST
-#define EGL_CAST(type, value) (static_cast<type>(value))
-#endif
-
 namespace WPEToolingBackends {
 
 class ViewBackend {

Deleted: trunk/Tools/wpe/backends/WindowViewBackend.cpp (288813 => 288814)


--- trunk/Tools/wpe/backends/WindowViewBackend.cpp	2022-01-31 14:56:26 UTC (rev 288813)
+++ trunk/Tools/wpe/backends/WindowViewBackend.cpp	2022-01-31 15:14:28 UTC (rev 288814)
@@ -1,984 +0,0 @@
-/*
- * 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. 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 APPLE INC. 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.
- */
-
-#include "WindowViewBackend.h"
-
-#include <cstdio>
-#include <cstring>
-#include <linux/input.h>
-#include <memory>
-#include <mutex>
-#include <sys/mman.h>
-#include <unistd.h>
-
-// This include order is necessary to enforce the Wayland EGL platform.
-#include <wayland-egl.h>
-#include <epoxy/egl.h>
-#include <wpe/fdo-egl.h>
-
-#ifndef EGL_WL_bind_wayland_display
-#define EGL_WL_bind_wayland_display 1
-typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, struct wl_resource* buffer, EGLint attribute, EGLint* value);
-
-#define EGL_WAYLAND_BUFFER_WL 0x31D5 // eglCreateImageKHR target
-#define EGL_WAYLAND_PLANE_WL  0x31D6 // eglCreateImageKHR target
-#endif
-
-namespace WPEToolingBackends {
-
-struct WaylandEGLConnection {
-    struct wl_display* display { nullptr };
-    EGLDisplay eglDisplay { EGL_NO_DISPLAY };
-
-    static const WaylandEGLConnection& singleton()
-    {
-        static std::once_flag s_onceFlag;
-        static WaylandEGLConnection s_connection;
-        std::call_once(s_onceFlag,
-            [] {
-                s_connection.display = wl_display_connect(nullptr);
-                if (!s_connection.display) {
-                    g_warning("WaylandEGLConnection: Could not connect to Wayland Display");
-                    return;
-                }
-
-                EGLDisplay eglDisplay = eglGetDisplay(s_connection.display);
-                if (eglDisplay == EGL_NO_DISPLAY) {
-                    g_warning("WaylandEGLConnection: No EGL Display available in this connection");
-                    return;
-                }
-
-                if (!eglInitialize(eglDisplay, nullptr, nullptr) || !eglBindAPI(EGL_OPENGL_ES_API)) {
-                    g_warning("WaylandEGLConnection: Failed to initialize and bind the EGL Display");
-                    return;
-                }
-
-                s_connection.eglDisplay = eglDisplay;
-                wpe_fdo_initialize_for_egl_display(s_connection.eglDisplay);
-            });
-
-        return s_connection;
-    }
-};
-
-static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC imageTargetTexture2DOES;
-
-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 WindowViewBackend::s_registryListener = {
-    // global
-    [](void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t)
-    {
-        auto* window = static_cast<WindowViewBackend*>(data);
-
-        if (!std::strcmp(interface, "wl_compositor"))
-            window->m_compositor = static_cast<struct wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 1));
-
-        if (!std::strcmp(interface, "zxdg_shell_v6"))
-            window->m_xdg = static_cast<struct zxdg_shell_v6*>(wl_registry_bind(registry, name, &zxdg_shell_v6_interface, 1));
-
-        if (!std::strcmp(interface, "wl_seat"))
-            window->m_seat = static_cast<struct wl_seat*>(wl_registry_bind(registry, name, &wl_seat_interface, 5));
-    },
-    // global_remove
-    [](void*, struct wl_registry*, uint32_t) { },
-};
-
-const struct zxdg_shell_v6_listener WindowViewBackend::s_xdgWmBaseListener = {
-    // ping
-    [](void*, struct zxdg_shell_v6* shell, uint32_t serial)
-    {
-        zxdg_shell_v6_pong(shell, serial);
-    },
-};
-
-const struct wl_pointer_listener WindowViewBackend::s_pointerListener = {
-    // enter
-    [](void* data, struct wl_pointer*, uint32_t /*serial*/, struct wl_surface* surface, wl_fixed_t, wl_fixed_t)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        if (window.m_surface == surface) {
-            window.m_seatData.pointer.target = surface;
-            window.m_seatData.pointer.modifiers = 0;
-        }
-    },
-    // leave
-    [](void* data, struct wl_pointer*, uint32_t /*serial*/, struct wl_surface* surface)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        if (window.m_surface == surface && window.m_seatData.pointer.target == surface)
-            window.m_seatData.pointer.target = nullptr;
-    },
-    // motion
-    [](void* data, struct wl_pointer*, uint32_t time, wl_fixed_t fixedX, wl_fixed_t fixedY)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        int x = wl_fixed_to_int(fixedX);
-        int y = wl_fixed_to_int(fixedY);
-        window.m_seatData.pointer.coords = { x, y };
-
-        if (window.m_seatData.pointer.target) {
-            struct wpe_input_pointer_event event = { wpe_input_pointer_event_type_motion,
-                time, x, y, window.m_seatData.pointer.button, window.m_seatData.pointer.state, window.modifiers() };
-            window.dispatchInputPointerEvent(&event);
-        }
-    },
-    // button
-    [](void* data, struct wl_pointer*, uint32_t /*serial*/, uint32_t time, uint32_t button, uint32_t state)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        if (button >= BTN_MOUSE)
-            button = button - BTN_MOUSE + 1;
-        else
-            button = 0;
-
-        window.m_seatData.pointer.button = !!state ? button : 0;
-        window.m_seatData.pointer.state = state;
-
-        uint32_t modifier = 0;
-        switch (button) {
-        case 1:
-            modifier = wpe_input_pointer_modifier_button1;
-            break;
-        case 2:
-            modifier = wpe_input_pointer_modifier_button2;
-            break;
-        case 3:
-            modifier = wpe_input_pointer_modifier_button3;
-            break;
-        case 4:
-            modifier = wpe_input_pointer_modifier_button4;
-            break;
-        case 5:
-            modifier = wpe_input_pointer_modifier_button5;
-            break;
-        default:
-            break;
-        }
-
-        if (state)
-            window.m_seatData.pointer.modifiers |= modifier;
-        else
-            window.m_seatData.pointer.modifiers &= ~modifier;
-
-        if (window.m_seatData.pointer.target) {
-            struct wpe_input_pointer_event event = { wpe_input_pointer_event_type_button,
-                time, window.m_seatData.pointer.coords.first, window.m_seatData.pointer.coords.second, button, state, window.modifiers() };
-            window.dispatchInputPointerEvent(&event);
-        }
-    },
-    // axis
-    [](void* data, struct wl_pointer*, uint32_t time, uint32_t axis, wl_fixed_t value)
-    {
-        if (axis != WL_POINTER_AXIS_HORIZONTAL_SCROLL && axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
-            return;
-
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        if (window.m_seatData.pointer.target) {
-            struct wpe_input_axis_event event = { wpe_input_axis_event_type_motion,
-                time, window.m_seatData.pointer.coords.first, window.m_seatData.pointer.coords.second, axis, -wl_fixed_to_int(value), window.modifiers() };
-            if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL && window.m_seatData.axis_discrete.horizontal)
-                event.value = window.m_seatData.axis_discrete.horizontal;
-            else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL && window.m_seatData.axis_discrete.vertical)
-                event.value = window.m_seatData.axis_discrete.vertical;
-#if WPE_CHECK_VERSION(1, 5, 0)
-            else {
-                struct wpe_input_axis_2d_event event2d = { event, 0, 0 };
-                event2d.base.type = static_cast<wpe_input_axis_event_type>(wpe_input_axis_event_type_mask_2d | wpe_input_axis_event_type_motion_smooth);
-
-                if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
-                    event2d.x_axis = wl_fixed_to_double(value);
-                else
-                    event2d.y_axis = -wl_fixed_to_double(value);
-
-                window.dispatchInputAxisEvent(&event2d.base);
-                return;
-            }
-#endif
-            window.dispatchInputAxisEvent(&event);
-            window.m_seatData.axis_discrete.horizontal = window.m_seatData.axis_discrete.vertical = 0;
-        }
-    },
-    // frame
-    [](void*, struct wl_pointer*) { },
-    // axis_source
-    [](void*, struct wl_pointer*, uint32_t) { },
-    // axis_stop
-    [](void* data, struct wl_pointer*, uint32_t time, uint32_t axis)
-    {
-        if (axis != WL_POINTER_AXIS_HORIZONTAL_SCROLL && axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
-            return;
-
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        if (window.m_seatData.pointer.target) {
-            struct wpe_input_axis_event event = { wpe_input_axis_event_type_motion,
-                time, window.m_seatData.pointer.coords.first, window.m_seatData.pointer.coords.second, axis, 0, window.modifiers() };
-            window.dispatchInputAxisEvent(&event);
-        }
-    },
-    // axis_discrete
-    [](void* data, struct wl_pointer*, uint32_t axis, int32_t discrete) {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        switch (axis) {
-        case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
-            window.m_seatData.axis_discrete.horizontal = discrete;
-            break;
-        case WL_POINTER_AXIS_VERTICAL_SCROLL:
-            window.m_seatData.axis_discrete.vertical = -discrete;
-            break;
-        }
-    },
-};
-
-const struct wl_keyboard_listener WindowViewBackend::s_keyboardListener = {
-    // keymap
-    [](void*, struct wl_keyboard*, uint32_t format, int fd, uint32_t size)
-    {
-        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 = wpe_input_xkb_context_get_default();
-        auto* keymap = xkb_keymap_new_from_string(wpe_input_xkb_context_get_context(xkb), static_cast<char*>(mapping),
-            XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
-        munmap(mapping, size);
-        close(fd);
-
-        wpe_input_xkb_context_set_keymap(xkb, keymap);
-        xkb_keymap_unref(keymap);
-    },
-    // enter
-    [](void* data, struct wl_keyboard*, uint32_t /*serial*/, struct wl_surface* surface, struct wl_array*)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        if (window.m_surface == surface)
-            window.m_seatData.keyboard.target = surface;
-    },
-    // leave
-    [](void* data, struct wl_keyboard*, uint32_t /*serial*/, struct wl_surface* surface)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        if (window.m_surface == surface && window.m_seatData.keyboard.target == surface)
-            window.m_seatData.keyboard.target = nullptr;
-    },
-    // key
-    [](void* data, struct wl_keyboard*, uint32_t /*serial*/, uint32_t time, uint32_t key, uint32_t state)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-
-        // IDK.
-        key += 8;
-
-        window.handleKeyEvent(key, state, time);
-
-        auto& seatData = window.m_seatData;
-        if (!seatData.repeatInfo.rate)
-            return;
-
-        auto* keymap = wpe_input_xkb_context_get_keymap(wpe_input_xkb_context_get_default());
-
-        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
-            && keymap && xkb_keymap_key_repeats(keymap, key)) {
-
-            if (seatData.repeatData.eventSource)
-                g_source_remove(seatData.repeatData.eventSource);
-
-            auto sourceID = g_timeout_add(seatData.repeatInfo.delay, [](void* data) -> gboolean {
-                auto& window = *static_cast<WindowViewBackend*>(data);
-                auto& seatData = window.m_seatData;
-                window.handleKeyEvent(seatData.repeatData.key, seatData.repeatData.state, seatData.repeatData.time);
-                seatData.repeatData.eventSource = g_timeout_add(seatData.repeatInfo.rate, [](void* data) -> gboolean {
-                    auto& window = *static_cast<WindowViewBackend*>(data);
-                    auto& seatData = window.m_seatData;
-                    window.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& keyboard = static_cast<WindowViewBackend*>(data)->m_seatData.keyboard;
-        keyboard.modifiers = wpe_input_xkb_context_get_modifiers(wpe_input_xkb_context_get_default(), depressedMods, latchedMods, lockedMods, group);
-    },
-    // repeat_info
-    [](void* data, struct wl_keyboard*, int32_t rate, int32_t delay)
-    {
-        auto& seatData = static_cast<WindowViewBackend*>(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_touch_listener WindowViewBackend::s_touchListener = {
-    // down
-    [](void* data, struct wl_touch*, uint32_t, uint32_t time, struct wl_surface* surface, int32_t id, wl_fixed_t x, wl_fixed_t y)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        if (window.m_surface != surface || id < 0 || id >= 10)
-            return;
-
-        auto& seatData = window.m_seatData;
-        seatData.touch.tracking = true;
-        struct wpe_input_touch_event_raw rawEvent = { wpe_input_touch_event_type_down,
-            time, id, wl_fixed_to_int(x), wl_fixed_to_int(y) };
-        memcpy(&seatData.touch.points[id], &rawEvent, sizeof(struct wpe_input_touch_event_raw));
-
-        struct wpe_input_touch_event event = { seatData.touch.points, 10,
-            rawEvent.type, rawEvent.id, rawEvent.time, window.modifiers() };
-        window.dispatchInputTouchEvent(&event);
-    },
-    // up
-    [](void* data, struct wl_touch*, uint32_t, uint32_t time, int32_t id)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        auto& seatData = window.m_seatData;
-        if (!seatData.touch.tracking || id < 0 || id >= 10)
-            return;
-
-        seatData.touch.tracking = false;
-
-        struct wpe_input_touch_event_raw rawEvent = { wpe_input_touch_event_type_up,
-            time, id, seatData.touch.points[id].x, seatData.touch.points[id].y };
-        memcpy(&seatData.touch.points[id], &rawEvent, sizeof(struct wpe_input_touch_event_raw));
-
-        struct wpe_input_touch_event event = { seatData.touch.points, 10,
-            rawEvent.type, rawEvent.id, rawEvent.time, window.modifiers() };
-        window.dispatchInputTouchEvent(&event);
-
-        memset(&seatData.touch.points[id], 0x00, sizeof(struct wpe_input_touch_event_raw));
-    },
-    // motion
-    [](void* data, struct wl_touch*, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        auto& seatData = window.m_seatData;
-        if (!seatData.touch.tracking || id < 0 || id >= 10)
-            return;
-
-        struct wpe_input_touch_event_raw rawEvent = { wpe_input_touch_event_type_motion,
-            time, id, wl_fixed_to_int(x), wl_fixed_to_int(y) };
-        memcpy(&seatData.touch.points[id], &rawEvent, sizeof(struct wpe_input_touch_event_raw));
-
-        struct wpe_input_touch_event event = { seatData.touch.points, 10,
-            rawEvent.type, rawEvent.id, rawEvent.time, window.modifiers() };
-        window.dispatchInputTouchEvent(&event);
-    },
-    // frame
-    [](void*, struct wl_touch*) { },
-    // cancel
-    [](void*, struct wl_touch*) { },
-    // shape
-    [](void*, struct wl_touch*, int32_t, wl_fixed_t, wl_fixed_t) { },
-    // orientation
-    [](void*, struct wl_touch*, int32_t, wl_fixed_t) { },
-};
-
-const struct wl_seat_listener WindowViewBackend::s_seatListener = {
-    // capabilities
-    [](void* data, struct wl_seat* seat, uint32_t capabilities)
-    {
-        auto* window = static_cast<WindowViewBackend*>(data);
-        auto& seatData = window->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, window);
-        }
-        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, window);
-        }
-        if (!hasKeyboardCap && seatData.keyboard.object) {
-            wl_keyboard_destroy(seatData.keyboard.object);
-            seatData.keyboard.object = nullptr;
-        }
-
-        // WL_SEAT_CAPABILITY_TOUCH
-        const bool hasTouchCap = capabilities & WL_SEAT_CAPABILITY_TOUCH;
-        if (hasTouchCap && !seatData.touch.object) {
-            seatData.touch.object = wl_seat_get_touch(seat);
-            wl_touch_add_listener(seatData.touch.object, &s_touchListener, window);
-        }
-        if (!hasTouchCap && seatData.touch.object) {
-            wl_touch_destroy(seatData.touch.object);
-            seatData.touch.object = nullptr;
-        }
-    },
-    // name
-    [](void*, struct wl_seat*, const char*) { }
-};
-
-const struct zxdg_surface_v6_listener WindowViewBackend::s_xdgSurfaceListener = {
-    // configure
-    [](void*, struct zxdg_surface_v6* surface, uint32_t serial)
-    {
-        zxdg_surface_v6_ack_configure(surface, serial);
-    },
-};
-
-const struct zxdg_toplevel_v6_listener WindowViewBackend::s_xdgToplevelListener = {
-    // configure
-    [](void* data, struct zxdg_toplevel_v6*, int32_t width, int32_t height, struct wl_array* states)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        window.resize(std::max(0, width), std::max(0, height));
-
-        bool isFocused = false;
-        bool isFullscreen = false;
-        // FIXME: It would be nice if the following loop could use
-        // wl_array_for_each, but at the time of writing it relies on
-        // GCC specific extension to work properly:
-        // https://gitlab.freedesktop.org/wayland/wayland/issues/34
-        uint32_t* pos = static_cast<uint32_t*>(states->data);
-        uint32_t* end = static_cast<uint32_t*>(states->data) + states->size;
-
-        for (; pos < end; pos++) {
-            uint32_t state = *pos;
-
-            switch (state) {
-            case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED:
-                isFocused = true;
-                break;
-            case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
-                isFullscreen = true;
-                break;
-            case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED:
-            case ZXDG_TOPLEVEL_V6_STATE_RESIZING:
-            default:
-                break;
-            }
-        }
-
-        if (isFocused)
-            window.addActivityState(wpe_view_activity_state_focused);
-        else
-            window.removeActivityState(wpe_view_activity_state_focused);
-
-        if (window.m_is_fullscreen != isFullscreen)
-            window.onFullscreenChanged(isFullscreen);
-    },
-    // close
-    [](void* data, struct zxdg_toplevel_v6*)
-    {
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        window.removeActivityState(wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window);
-    },
-};
-
-#if WPE_CHECK_VERSION(1, 11, 1)
-
-bool WindowViewBackend::onDOMFullscreenRequest(void* data, bool fullscreen)
-{
-    auto& window = *static_cast<WindowViewBackend*>(data);
-    if (window.m_waiting_fullscreen_notify)
-        return false;
-
-    if (fullscreen == window.m_is_fullscreen) {
-        // Handle situations where DOM fullscreen requests are mixed with system fullscreen commands (e.g F11)
-        window.dispatchFullscreenEvent();
-        return true;
-    }
-
-    window.m_waiting_fullscreen_notify = true;
-    if (fullscreen)
-        zxdg_toplevel_v6_set_fullscreen(window.m_xdgToplevel, nullptr);
-    else
-        zxdg_toplevel_v6_unset_fullscreen(window.m_xdgToplevel);
-
-    return true;
-}
-
-void WindowViewBackend::dispatchFullscreenEvent()
-{
-    if (m_is_fullscreen)
-        wpe_view_backend_dispatch_did_enter_fullscreen(backend());
-    else
-        wpe_view_backend_dispatch_did_exit_fullscreen(backend());
-}
-
-void WindowViewBackend::onFullscreenChanged(bool fullscreen)
-{
-    bool wasRequestedFromDOM = m_waiting_fullscreen_notify;
-    m_waiting_fullscreen_notify= false;
-    m_is_fullscreen = fullscreen;
-
-    if (!fullscreen && !wasRequestedFromDOM)
-        wpe_view_backend_dispatch_request_exit_fullscreen(backend());
-    else if (wasRequestedFromDOM)
-        dispatchFullscreenEvent();
-}
-
-#else
-
-void WindowViewBackend::onFullscreenChanged(bool fullscreen)
-{
-    m_is_fullscreen = fullscreen;
-}
-
-#endif // WPE_CHECK_VERSION(1, 11, 1)
-
-WindowViewBackend::WindowViewBackend(uint32_t width, uint32_t height)
-    : ViewBackend(width, height)
-{
-    m_initialSize.width = width;
-    m_initialSize.height = height;
-
-    auto& connection = WaylandEGLConnection::singleton();
-    if (!connection.display) {
-        g_warning("WindowViewBackend: No Wayland EGL connection available");
-        return;
-    }
-
-    if (connection.eglDisplay == EGL_NO_DISPLAY || !initialize(connection.eglDisplay)) {
-        g_warning("WindowViewBackend: Could not initialize EGL display");
-        return;
-    }
-
-    {
-        auto* registry = wl_display_get_registry(connection.display);
-        wl_registry_add_listener(registry, &s_registryListener, this);
-        wl_display_roundtrip(connection.display);
-
-        if (m_xdg)
-            zxdg_shell_v6_add_listener(m_xdg, &s_xdgWmBaseListener, nullptr);
-
-        if (m_seat)
-            wl_seat_add_listener(m_seat, &s_seatListener, this);
-    }
-
-    m_eventSource = g_source_new(&EventSource::sourceFuncs, sizeof(EventSource));
-    {
-        auto& source = *reinterpret_cast<EventSource*>(m_eventSource);
-        source.display = connection.display;
-
-        source.pfd.fd = wl_display_get_fd(connection.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_DEFAULT);
-        g_source_set_can_recurse(&source.source, TRUE);
-        g_source_attach(&source.source, g_main_context_get_thread_default());
-    }
-
-    m_surface = wl_compositor_create_surface(m_compositor);
-    if (m_xdg) {
-        m_xdgSurface = zxdg_shell_v6_get_xdg_surface(m_xdg, m_surface);
-        zxdg_surface_v6_add_listener(m_xdgSurface, &s_xdgSurfaceListener, nullptr);
-        m_xdgToplevel = zxdg_surface_v6_get_toplevel(m_xdgSurface);
-        if (m_xdgToplevel) {
-            zxdg_toplevel_v6_add_listener(m_xdgToplevel, &s_xdgToplevelListener, this);
-            zxdg_toplevel_v6_set_title(m_xdgToplevel, "WPE");
-            wl_surface_commit(m_surface);
-            addActivityState(wpe_view_activity_state_visible | wpe_view_activity_state_in_window);
-        }
-    }
-
-    m_eglWindow = wl_egl_window_create(m_surface, m_width, m_height);
-
-    auto createPlatformWindowSurface =
-        reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
-    m_eglSurface = createPlatformWindowSurface(connection.eglDisplay, m_eglConfig, m_eglWindow, nullptr);
-    if (!m_eglSurface) {
-        g_warning("WindowViewBackend: Could not create EGL platform window surface");
-        return;
-    }
-
-    if (!eglMakeCurrent(connection.eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)) {
-        g_warning("WindowViewBackend: Could not make EGL surface current");
-        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";
-
-        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");
-    }
-
-    createViewTexture();
-}
-
-WindowViewBackend::~WindowViewBackend()
-{
-    auto& connection = WaylandEGLConnection::singleton();
-
-    if (m_eventSource) {
-        g_source_destroy(m_eventSource);
-        g_source_unref(m_eventSource);
-    }
-
-    if (m_xdgToplevel)
-        zxdg_toplevel_v6_destroy(m_xdgToplevel);
-
-    if (m_xdgSurface)
-        zxdg_surface_v6_destroy(m_xdgSurface);
-
-    if (m_surface)
-        wl_surface_destroy(m_surface);
-
-    if (m_eglWindow)
-        wl_egl_window_destroy(m_eglWindow);
-
-    if (m_xdg)
-        zxdg_shell_v6_destroy(m_xdg);
-
-    if (m_seat)
-        wl_seat_destroy(m_seat);
-
-    if (m_compositor)
-        wl_compositor_destroy(m_compositor);
-
-    if (m_eglSurface)
-        eglDestroySurface(connection.eglDisplay, m_eglSurface);
-
-    if (m_display)
-        wl_display_disconnect(m_display);
-
-    deinitialize(connection.eglDisplay);
-}
-
-const struct wl_callback_listener WindowViewBackend::s_frameListener = {
-    // frame
-    [](void* data, struct wl_callback* callback, uint32_t)
-    {
-        if (callback)
-            wl_callback_destroy(callback);
-
-        auto& window = *static_cast<WindowViewBackend*>(data);
-        wpe_view_backend_exportable_fdo_dispatch_frame_complete(window.m_exportable);
-
-        if (window.m_committedImage)
-            wpe_view_backend_exportable_fdo_egl_dispatch_release_exported_image(window.m_exportable, window.m_committedImage);
-        window.m_committedImage = nullptr;
-    }
-};
-
-struct wpe_view_backend* WindowViewBackend::backend() const
-{
-    return m_exportable ? wpe_view_backend_exportable_fdo_get_view_backend(m_exportable) : nullptr;
-}
-
-void WindowViewBackend::createViewTexture()
-{
-    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, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
-    glBindTexture(GL_TEXTURE_2D, 0);
-}
-
-void WindowViewBackend::resize(uint32_t width, uint32_t height)
-{
-    if (!width)
-        width = m_initialSize.width;
-    if (!height)
-        height = m_initialSize.height;
-
-    if (width == m_width && height == m_height)
-        return;
-
-    m_width = width;
-    m_height = height;
-
-    wl_egl_window_resize(m_eglWindow, m_width, m_height, 0, 0);
-    wpe_view_backend_dispatch_set_size(backend(), m_width, m_height);
-
-    if (m_viewTexture)
-        glDeleteTextures(1, &m_viewTexture);
-    createViewTexture();
-}
-
-bool WindowViewBackend::initialize(EGLDisplay 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(eglDisplay, nullptr, 0, &count) || count < 1)
-            return false;
-
-        EGLConfig* configs = g_new0(EGLConfig, count);
-        EGLint matched = 0;
-        if (eglChooseConfig(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(eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttributes);
-    if (!m_eglContext)
-        return false;
-
-    static struct wpe_view_backend_exportable_fdo_egl_client exportableClient = {
-        // export_egl_image
-        nullptr,
-        // export_fdo_egl_image
-        [](void* data, struct wpe_fdo_egl_exported_image* image)
-        {
-            static_cast<WindowViewBackend*>(data)->displayBuffer(image);
-        },
-#if WPE_FDO_CHECK_VERSION(1, 5, 0)
-        // export_shm_buffer
-        [](void* data, struct wpe_fdo_shm_exported_buffer* buffer)
-        {
-            static_cast<WindowViewBackend*>(data)->displayBuffer(buffer);
-        },
-        // padding
-        nullptr, nullptr
-#else
-        // padding
-        nullptr, nullptr, nullptr
-#endif
-
-    };
-    m_exportable = wpe_view_backend_exportable_fdo_egl_create(&exportableClient, this, m_width, m_height);
-
-#if WPE_CHECK_VERSION(1, 11, 1)
-    wpe_view_backend_set_fullscreen_handler(backend(), onDOMFullscreenRequest, this);
-#endif
-
-    initializeAccessibility();
-
-    return true;
-}
-
-void WindowViewBackend::deinitialize(EGLDisplay eglDisplay)
-{
-    m_inputClient = nullptr;
-
-    if (m_eglContext)
-        eglDestroyContext(eglDisplay, m_eglContext);
-
-    if (m_exportable)
-        wpe_view_backend_exportable_fdo_destroy(m_exportable);
-}
-
-void WindowViewBackend::displayBuffer(struct wpe_fdo_egl_exported_image* image)
-{
-    if (!m_eglContext)
-        return;
-
-    auto& connection = WaylandEGLConnection::singleton();
-    eglMakeCurrent(connection.eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
-
-    glViewport(0, 0, m_width, m_height);
-    glClearColor(1, 0, 0, 1);
-    glClear(GL_COLOR_BUFFER_BIT);
-
-    glUseProgram(m_program);
-
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, m_viewTexture);
-    imageTargetTexture2DOES(GL_TEXTURE_2D, wpe_fdo_egl_exported_image_get_egl_image(image));
-    glUniform1i(m_textureUniform, 0);
-
-    m_committedImage = image;
-
-    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 },
-    };
-
-    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
-    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 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(connection.eglDisplay, m_eglSurface);
-}
-
-#if WPE_FDO_CHECK_VERSION(1, 5, 0)
-void WindowViewBackend::displayBuffer(struct wpe_fdo_shm_exported_buffer*)
-{
-    g_warning("WindowViewBackend: cannot yet handle wpe_fdo_shm_exported_buffer.");
-}
-#endif
-
-void WindowViewBackend::handleKeyEvent(uint32_t key, uint32_t state, uint32_t time)
-{
-    uint32_t keysym = wpe_input_xkb_context_get_key_code(wpe_input_xkb_context_get_default(), key, state == WL_KEYBOARD_KEY_STATE_PRESSED);
-    if (!keysym)
-        return;
-
-    if (m_seatData.keyboard.target) {
-        struct wpe_input_keyboard_event event = { time, keysym, key, !!state, modifiers() };
-        dispatchInputKeyboardEvent(&event);
-    }
-}
-
-uint32_t WindowViewBackend::modifiers() const
-{
-    uint32_t mask = m_seatData.keyboard.modifiers;
-    if (m_seatData.pointer.object)
-        mask |= m_seatData.pointer.modifiers;
-    return mask;
-}
-
-} // namespace WPEToolingBackends

Deleted: trunk/Tools/wpe/backends/WindowViewBackend.h (288813 => 288814)


--- trunk/Tools/wpe/backends/WindowViewBackend.h	2022-01-31 14:56:26 UTC (rev 288813)
+++ trunk/Tools/wpe/backends/WindowViewBackend.h	2022-01-31 15:14:28 UTC (rev 288814)
@@ -1,146 +0,0 @@
-/*
- * 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. 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 APPLE INC. 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.
- */
-
-#pragma once
-
-#include "ViewBackend.h"
-#include "xdg-shell-unstable-v6-client-protocol.h"
-#include <glib.h>
-#include <unordered_map>
-
-typedef void* EGLSurface;
-typedef struct wl_egl_window  *EGLNativeWindowType;
-
-namespace WPEToolingBackends {
-
-class WindowViewBackend final : public ViewBackend {
-public:
-    WindowViewBackend(uint32_t width, uint32_t height);
-    virtual ~WindowViewBackend();
-
-    struct wpe_view_backend* backend() const override;
-
-private:
-    void createViewTexture();
-    void resize(uint32_t width, uint32_t height);
-
-    bool initialize(EGLDisplay);
-    void deinitialize(EGLDisplay);
-
-    void displayBuffer(struct wpe_fdo_egl_exported_image*);
-#if WPE_FDO_CHECK_VERSION(1, 5, 0)
-    void displayBuffer(struct wpe_fdo_shm_exported_buffer*);
-#endif
-
-    static const struct wl_registry_listener s_registryListener;
-    static const struct zxdg_shell_v6_listener s_xdgWmBaseListener;
-    static const struct wl_pointer_listener s_pointerListener;
-    static const struct wl_keyboard_listener s_keyboardListener;
-    static const struct wl_touch_listener s_touchListener;
-    static const struct wl_seat_listener s_seatListener;
-    static const struct wl_callback_listener s_frameListener;
-    static const struct zxdg_surface_v6_listener s_xdgSurfaceListener;
-    static const struct zxdg_toplevel_v6_listener s_xdgToplevelListener;
-
-#if WPE_CHECK_VERSION(1, 11, 1)
-    static bool onDOMFullscreenRequest(void* data, bool fullscreen);
-    void dispatchFullscreenEvent();
-#endif
-    void onFullscreenChanged(bool fullscreen);
-
-    void handleKeyEvent(uint32_t key, uint32_t state, uint32_t time);
-    uint32_t modifiers() const;
-
-    struct SeatData {
-        struct {
-            struct wl_pointer* object { nullptr };
-            struct wl_surface* target { nullptr };
-            std::pair<int, int> coords { 0, 0 };
-            uint32_t button { 0 };
-            uint32_t state { 0 };
-            uint32_t modifiers { 0 };
-        } pointer;
-
-        struct {
-            struct wl_keyboard* object { nullptr };
-            struct wl_surface* target { nullptr };
-            uint32_t modifiers { 0 };
-        } keyboard;
-
-        struct {
-            struct wl_touch* object { nullptr };
-            struct wpe_input_touch_event_raw points[10];
-            bool tracking { false };
-        } touch;
-
-        struct {
-            int32_t horizontal { 0 };
-            int32_t vertical { 0 };
-        } axis_discrete;
-
-        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 {
-        uint32_t width;
-        uint32_t height;
-    } m_initialSize;
-
-    struct wpe_view_backend_exportable_fdo* m_exportable { nullptr };
-
-    struct wl_display* m_display { nullptr };
-    struct wl_compositor* m_compositor { nullptr };
-    struct zxdg_shell_v6* m_xdg { nullptr };
-    struct wl_seat* m_seat { nullptr };
-    GSource* m_eventSource { nullptr };
-    struct wl_surface* m_surface { nullptr };
-    struct zxdg_surface_v6* m_xdgSurface { nullptr };
-    struct zxdg_toplevel_v6* m_xdgToplevel { nullptr };
-    struct wl_egl_window* m_eglWindow { nullptr };
-    EGLContext m_eglContext { nullptr };
-    EGLConfig m_eglConfig;
-    EGLSurface m_eglSurface { nullptr };
-    unsigned m_program { 0 };
-    unsigned m_textureUniform { 0 };
-    unsigned m_viewTexture { 0 };
-    struct wpe_fdo_egl_exported_image* m_committedImage { nullptr };
-    bool m_is_fullscreen { false };
-#if WPE_CHECK_VERSION(1, 11, 1)
-    bool m_waiting_fullscreen_notify { false };
-#endif
-};
-
-} // WPEToolingBackends

Copied: trunk/Tools/wpe/backends/fdo/HeadlessViewBackendFdo.cpp (from rev 288813, trunk/Tools/wpe/backends/HeadlessViewBackend.cpp) (0 => 288814)


--- trunk/Tools/wpe/backends/fdo/HeadlessViewBackendFdo.cpp	                        (rev 0)
+++ trunk/Tools/wpe/backends/fdo/HeadlessViewBackendFdo.cpp	2022-01-31 15:14:28 UTC (rev 288814)
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2016 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. 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 APPLE INC. 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.
+ */
+
+#include "HeadlessViewBackend.h"
+
+#include <cassert>
+#include <fcntl.h>
+#include <mutex>
+#include <unistd.h>
+
+#if WPE_FDO_CHECK_VERSION(1,7,0)
+#include <wayland-server.h>
+#include <wpe/unstable/fdo-shm.h>
+#endif
+
+namespace WPEToolingBackends {
+
+struct HeadlessInstance {
+    static const HeadlessInstance& singleton()
+    {
+        static std::once_flag s_onceFlag;
+        static HeadlessInstance s_instance;
+        std::call_once(s_onceFlag,
+            [] {
+#if WPE_FDO_CHECK_VERSION(1,7,0)
+                wpe_fdo_initialize_shm();
+#endif
+            });
+
+        return s_instance;
+    }
+};
+
+static cairo_user_data_key_t s_bufferKey;
+
+HeadlessViewBackend::HeadlessViewBackend(uint32_t width, uint32_t height)
+    : ViewBackend(width, height)
+{
+    // This should initialize the SHM mode.
+    HeadlessInstance::singleton();
+
+    static struct wpe_view_backend_exportable_fdo_client exportableClient = {
+        nullptr,
+        nullptr,
+#if WPE_FDO_CHECK_VERSION(1,7,0)
+        // export_shm_buffer
+        [](void* data, struct wpe_fdo_shm_exported_buffer* buffer)
+        {
+            auto& backend = *static_cast<HeadlessViewBackend*>(data);
+            backend.m_update.pending = true;
+
+            backend.updateSnapshot(buffer);
+            wpe_view_backend_exportable_fdo_dispatch_release_shm_exported_buffer(backend.m_exportable, buffer);
+        },
+#else
+        nullptr,
+#endif
+        nullptr,
+        nullptr,
+    };
+    m_exportable = wpe_view_backend_exportable_fdo_create(&exportableClient, this, width, height);
+
+    addActivityState(wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window);
+
+    {
+        uint32_t stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width);
+        uint8_t* buffer = new uint8_t[stride * m_height];
+        memset(buffer, 0, stride * m_height);
+
+        m_snapshot = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32,
+            m_width, m_height, stride);
+
+        cairo_surface_set_user_data(m_snapshot, &s_bufferKey, buffer,
+            [](void* data) {
+                auto* buffer = static_cast<uint8_t*>(data);
+                delete[] buffer;
+            });
+        cairo_surface_mark_dirty(m_snapshot);
+    }
+
+#if WPE_CHECK_VERSION(1, 11, 1)
+    wpe_view_backend_set_fullscreen_handler(backend(), onDOMFullScreenRequest, this);
+#endif
+
+    m_update.source = g_timeout_source_new(G_USEC_PER_SEC / 60000);
+    g_source_set_callback(m_update.source, [](gpointer data) -> gboolean {
+        static_cast<HeadlessViewBackend*>(data)->vsync();
+        return TRUE;
+    }, this, nullptr);
+    g_source_set_priority(m_update.source, G_PRIORITY_DEFAULT);
+    g_source_attach(m_update.source, g_main_context_default());
+}
+
+HeadlessViewBackend::~HeadlessViewBackend()
+{
+    if (m_update.source) {
+        g_source_destroy(m_update.source);
+        g_source_unref(m_update.source);
+    }
+
+    if (m_snapshot)
+        cairo_surface_destroy(m_snapshot);
+
+    if (m_exportable)
+        wpe_view_backend_exportable_fdo_destroy(m_exportable);
+}
+
+struct wpe_view_backend* HeadlessViewBackend::backend() const
+{
+    if (m_exportable)
+        return wpe_view_backend_exportable_fdo_get_view_backend(m_exportable);
+    return nullptr;
+}
+
+PlatformImage HeadlessViewBackend::snapshot()
+{
+    return cairo_surface_reference(m_snapshot);
+}
+
+void HeadlessViewBackend::updateSnapshot(PlatformBuffer exportedBuffer)
+{
+#if WPE_FDO_CHECK_VERSION(1,7,0)
+    struct wl_shm_buffer* shmBuffer = wpe_fdo_shm_exported_buffer_get_shm_buffer(exportedBuffer);
+    {
+        auto format = wl_shm_buffer_get_format(shmBuffer);
+        if (format != WL_SHM_FORMAT_ARGB8888 && format != WL_SHM_FORMAT_XRGB8888)
+            return;
+    }
+
+    uint32_t bufferStride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width);
+    uint8_t* buffer = new uint8_t[bufferStride * m_height];
+    memset(buffer, 0, bufferStride * m_height);
+
+    {
+        uint32_t width = std::min<uint32_t>(m_width, std::max(0, wl_shm_buffer_get_width(shmBuffer)));
+        uint32_t height = std::min<uint32_t>(m_height, std::max(0, wl_shm_buffer_get_height(shmBuffer)));
+        uint32_t stride = std::max(0, wl_shm_buffer_get_stride(shmBuffer));
+
+        wl_shm_buffer_begin_access(shmBuffer);
+        auto* data = ""
+
+        for (uint32_t y = 0; y < height; ++y) {
+            for (uint32_t x = 0; x < width; ++x) {
+                buffer[bufferStride * y + 4 * x + 0] = data[stride * y + 4 * x + 0];
+                buffer[bufferStride * y + 4 * x + 1] = data[stride * y + 4 * x + 1];
+                buffer[bufferStride * y + 4 * x + 2] = data[stride * y + 4 * x + 2];
+                buffer[bufferStride * y + 4 * x + 3] = data[stride * y + 4 * x + 3];
+            }
+        }
+
+        wl_shm_buffer_end_access(shmBuffer);
+    }
+
+    if (m_snapshot)
+        cairo_surface_destroy(m_snapshot);
+
+    m_snapshot = cairo_image_surface_create_for_data(buffer, CAIRO_FORMAT_ARGB32,
+        m_width, m_height, cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, m_width));
+
+    static cairo_user_data_key_t bufferKey;
+    cairo_surface_set_user_data(m_snapshot, &bufferKey, buffer,
+        [](void* data) {
+            auto* buffer = static_cast<uint8_t*>(data);
+            delete[] buffer;
+        });
+    cairo_surface_mark_dirty(m_snapshot);
+#else
+    (void)exportedBuffer;
+#endif
+}
+
+void HeadlessViewBackend::vsync()
+{
+#if WPE_FDO_CHECK_VERSION(1,7,0)
+    if (m_update.pending)
+        wpe_view_backend_exportable_fdo_dispatch_frame_complete(m_exportable);
+#endif
+    m_update.pending = false;
+}
+
+} // namespace WPEToolingBackends

Copied: trunk/Tools/wpe/backends/fdo/WindowViewBackend.cpp (from rev 288813, trunk/Tools/wpe/backends/WindowViewBackend.cpp) (0 => 288814)


--- trunk/Tools/wpe/backends/fdo/WindowViewBackend.cpp	                        (rev 0)
+++ trunk/Tools/wpe/backends/fdo/WindowViewBackend.cpp	2022-01-31 15:14:28 UTC (rev 288814)
@@ -0,0 +1,984 @@
+/*
+ * 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. 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 APPLE INC. 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.
+ */
+
+#include "WindowViewBackend.h"
+
+#include <cstdio>
+#include <cstring>
+#include <linux/input.h>
+#include <memory>
+#include <mutex>
+#include <sys/mman.h>
+#include <unistd.h>
+
+// This include order is necessary to enforce the Wayland EGL platform.
+#include <wayland-egl.h>
+#include <epoxy/egl.h>
+#include <wpe/fdo-egl.h>
+
+#ifndef EGL_WL_bind_wayland_display
+#define EGL_WL_bind_wayland_display 1
+typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, struct wl_resource* buffer, EGLint attribute, EGLint* value);
+
+#define EGL_WAYLAND_BUFFER_WL 0x31D5 // eglCreateImageKHR target
+#define EGL_WAYLAND_PLANE_WL  0x31D6 // eglCreateImageKHR target
+#endif
+
+namespace WPEToolingBackends {
+
+struct WaylandEGLConnection {
+    struct wl_display* display { nullptr };
+    EGLDisplay eglDisplay { EGL_NO_DISPLAY };
+
+    static const WaylandEGLConnection& singleton()
+    {
+        static std::once_flag s_onceFlag;
+        static WaylandEGLConnection s_connection;
+        std::call_once(s_onceFlag,
+            [] {
+                s_connection.display = wl_display_connect(nullptr);
+                if (!s_connection.display) {
+                    g_warning("WaylandEGLConnection: Could not connect to Wayland Display");
+                    return;
+                }
+
+                EGLDisplay eglDisplay = eglGetDisplay(s_connection.display);
+                if (eglDisplay == EGL_NO_DISPLAY) {
+                    g_warning("WaylandEGLConnection: No EGL Display available in this connection");
+                    return;
+                }
+
+                if (!eglInitialize(eglDisplay, nullptr, nullptr) || !eglBindAPI(EGL_OPENGL_ES_API)) {
+                    g_warning("WaylandEGLConnection: Failed to initialize and bind the EGL Display");
+                    return;
+                }
+
+                s_connection.eglDisplay = eglDisplay;
+                wpe_fdo_initialize_for_egl_display(s_connection.eglDisplay);
+            });
+
+        return s_connection;
+    }
+};
+
+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC imageTargetTexture2DOES;
+
+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 WindowViewBackend::s_registryListener = {
+    // global
+    [](void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t)
+    {
+        auto* window = static_cast<WindowViewBackend*>(data);
+
+        if (!std::strcmp(interface, "wl_compositor"))
+            window->m_compositor = static_cast<struct wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 1));
+
+        if (!std::strcmp(interface, "zxdg_shell_v6"))
+            window->m_xdg = static_cast<struct zxdg_shell_v6*>(wl_registry_bind(registry, name, &zxdg_shell_v6_interface, 1));
+
+        if (!std::strcmp(interface, "wl_seat"))
+            window->m_seat = static_cast<struct wl_seat*>(wl_registry_bind(registry, name, &wl_seat_interface, 5));
+    },
+    // global_remove
+    [](void*, struct wl_registry*, uint32_t) { },
+};
+
+const struct zxdg_shell_v6_listener WindowViewBackend::s_xdgWmBaseListener = {
+    // ping
+    [](void*, struct zxdg_shell_v6* shell, uint32_t serial)
+    {
+        zxdg_shell_v6_pong(shell, serial);
+    },
+};
+
+const struct wl_pointer_listener WindowViewBackend::s_pointerListener = {
+    // enter
+    [](void* data, struct wl_pointer*, uint32_t /*serial*/, struct wl_surface* surface, wl_fixed_t, wl_fixed_t)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        if (window.m_surface == surface) {
+            window.m_seatData.pointer.target = surface;
+            window.m_seatData.pointer.modifiers = 0;
+        }
+    },
+    // leave
+    [](void* data, struct wl_pointer*, uint32_t /*serial*/, struct wl_surface* surface)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        if (window.m_surface == surface && window.m_seatData.pointer.target == surface)
+            window.m_seatData.pointer.target = nullptr;
+    },
+    // motion
+    [](void* data, struct wl_pointer*, uint32_t time, wl_fixed_t fixedX, wl_fixed_t fixedY)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        int x = wl_fixed_to_int(fixedX);
+        int y = wl_fixed_to_int(fixedY);
+        window.m_seatData.pointer.coords = { x, y };
+
+        if (window.m_seatData.pointer.target) {
+            struct wpe_input_pointer_event event = { wpe_input_pointer_event_type_motion,
+                time, x, y, window.m_seatData.pointer.button, window.m_seatData.pointer.state, window.modifiers() };
+            window.dispatchInputPointerEvent(&event);
+        }
+    },
+    // button
+    [](void* data, struct wl_pointer*, uint32_t /*serial*/, uint32_t time, uint32_t button, uint32_t state)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        if (button >= BTN_MOUSE)
+            button = button - BTN_MOUSE + 1;
+        else
+            button = 0;
+
+        window.m_seatData.pointer.button = !!state ? button : 0;
+        window.m_seatData.pointer.state = state;
+
+        uint32_t modifier = 0;
+        switch (button) {
+        case 1:
+            modifier = wpe_input_pointer_modifier_button1;
+            break;
+        case 2:
+            modifier = wpe_input_pointer_modifier_button2;
+            break;
+        case 3:
+            modifier = wpe_input_pointer_modifier_button3;
+            break;
+        case 4:
+            modifier = wpe_input_pointer_modifier_button4;
+            break;
+        case 5:
+            modifier = wpe_input_pointer_modifier_button5;
+            break;
+        default:
+            break;
+        }
+
+        if (state)
+            window.m_seatData.pointer.modifiers |= modifier;
+        else
+            window.m_seatData.pointer.modifiers &= ~modifier;
+
+        if (window.m_seatData.pointer.target) {
+            struct wpe_input_pointer_event event = { wpe_input_pointer_event_type_button,
+                time, window.m_seatData.pointer.coords.first, window.m_seatData.pointer.coords.second, button, state, window.modifiers() };
+            window.dispatchInputPointerEvent(&event);
+        }
+    },
+    // axis
+    [](void* data, struct wl_pointer*, uint32_t time, uint32_t axis, wl_fixed_t value)
+    {
+        if (axis != WL_POINTER_AXIS_HORIZONTAL_SCROLL && axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
+            return;
+
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        if (window.m_seatData.pointer.target) {
+            struct wpe_input_axis_event event = { wpe_input_axis_event_type_motion,
+                time, window.m_seatData.pointer.coords.first, window.m_seatData.pointer.coords.second, axis, -wl_fixed_to_int(value), window.modifiers() };
+            if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL && window.m_seatData.axis_discrete.horizontal)
+                event.value = window.m_seatData.axis_discrete.horizontal;
+            else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL && window.m_seatData.axis_discrete.vertical)
+                event.value = window.m_seatData.axis_discrete.vertical;
+#if WPE_CHECK_VERSION(1, 5, 0)
+            else {
+                struct wpe_input_axis_2d_event event2d = { event, 0, 0 };
+                event2d.base.type = static_cast<wpe_input_axis_event_type>(wpe_input_axis_event_type_mask_2d | wpe_input_axis_event_type_motion_smooth);
+
+                if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
+                    event2d.x_axis = wl_fixed_to_double(value);
+                else
+                    event2d.y_axis = -wl_fixed_to_double(value);
+
+                window.dispatchInputAxisEvent(&event2d.base);
+                return;
+            }
+#endif
+            window.dispatchInputAxisEvent(&event);
+            window.m_seatData.axis_discrete.horizontal = window.m_seatData.axis_discrete.vertical = 0;
+        }
+    },
+    // frame
+    [](void*, struct wl_pointer*) { },
+    // axis_source
+    [](void*, struct wl_pointer*, uint32_t) { },
+    // axis_stop
+    [](void* data, struct wl_pointer*, uint32_t time, uint32_t axis)
+    {
+        if (axis != WL_POINTER_AXIS_HORIZONTAL_SCROLL && axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
+            return;
+
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        if (window.m_seatData.pointer.target) {
+            struct wpe_input_axis_event event = { wpe_input_axis_event_type_motion,
+                time, window.m_seatData.pointer.coords.first, window.m_seatData.pointer.coords.second, axis, 0, window.modifiers() };
+            window.dispatchInputAxisEvent(&event);
+        }
+    },
+    // axis_discrete
+    [](void* data, struct wl_pointer*, uint32_t axis, int32_t discrete) {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        switch (axis) {
+        case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
+            window.m_seatData.axis_discrete.horizontal = discrete;
+            break;
+        case WL_POINTER_AXIS_VERTICAL_SCROLL:
+            window.m_seatData.axis_discrete.vertical = -discrete;
+            break;
+        }
+    },
+};
+
+const struct wl_keyboard_listener WindowViewBackend::s_keyboardListener = {
+    // keymap
+    [](void*, struct wl_keyboard*, uint32_t format, int fd, uint32_t size)
+    {
+        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 = wpe_input_xkb_context_get_default();
+        auto* keymap = xkb_keymap_new_from_string(wpe_input_xkb_context_get_context(xkb), static_cast<char*>(mapping),
+            XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
+        munmap(mapping, size);
+        close(fd);
+
+        wpe_input_xkb_context_set_keymap(xkb, keymap);
+        xkb_keymap_unref(keymap);
+    },
+    // enter
+    [](void* data, struct wl_keyboard*, uint32_t /*serial*/, struct wl_surface* surface, struct wl_array*)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        if (window.m_surface == surface)
+            window.m_seatData.keyboard.target = surface;
+    },
+    // leave
+    [](void* data, struct wl_keyboard*, uint32_t /*serial*/, struct wl_surface* surface)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        if (window.m_surface == surface && window.m_seatData.keyboard.target == surface)
+            window.m_seatData.keyboard.target = nullptr;
+    },
+    // key
+    [](void* data, struct wl_keyboard*, uint32_t /*serial*/, uint32_t time, uint32_t key, uint32_t state)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+
+        // IDK.
+        key += 8;
+
+        window.handleKeyEvent(key, state, time);
+
+        auto& seatData = window.m_seatData;
+        if (!seatData.repeatInfo.rate)
+            return;
+
+        auto* keymap = wpe_input_xkb_context_get_keymap(wpe_input_xkb_context_get_default());
+
+        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
+            && keymap && xkb_keymap_key_repeats(keymap, key)) {
+
+            if (seatData.repeatData.eventSource)
+                g_source_remove(seatData.repeatData.eventSource);
+
+            auto sourceID = g_timeout_add(seatData.repeatInfo.delay, [](void* data) -> gboolean {
+                auto& window = *static_cast<WindowViewBackend*>(data);
+                auto& seatData = window.m_seatData;
+                window.handleKeyEvent(seatData.repeatData.key, seatData.repeatData.state, seatData.repeatData.time);
+                seatData.repeatData.eventSource = g_timeout_add(seatData.repeatInfo.rate, [](void* data) -> gboolean {
+                    auto& window = *static_cast<WindowViewBackend*>(data);
+                    auto& seatData = window.m_seatData;
+                    window.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& keyboard = static_cast<WindowViewBackend*>(data)->m_seatData.keyboard;
+        keyboard.modifiers = wpe_input_xkb_context_get_modifiers(wpe_input_xkb_context_get_default(), depressedMods, latchedMods, lockedMods, group);
+    },
+    // repeat_info
+    [](void* data, struct wl_keyboard*, int32_t rate, int32_t delay)
+    {
+        auto& seatData = static_cast<WindowViewBackend*>(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_touch_listener WindowViewBackend::s_touchListener = {
+    // down
+    [](void* data, struct wl_touch*, uint32_t, uint32_t time, struct wl_surface* surface, int32_t id, wl_fixed_t x, wl_fixed_t y)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        if (window.m_surface != surface || id < 0 || id >= 10)
+            return;
+
+        auto& seatData = window.m_seatData;
+        seatData.touch.tracking = true;
+        struct wpe_input_touch_event_raw rawEvent = { wpe_input_touch_event_type_down,
+            time, id, wl_fixed_to_int(x), wl_fixed_to_int(y) };
+        memcpy(&seatData.touch.points[id], &rawEvent, sizeof(struct wpe_input_touch_event_raw));
+
+        struct wpe_input_touch_event event = { seatData.touch.points, 10,
+            rawEvent.type, rawEvent.id, rawEvent.time, window.modifiers() };
+        window.dispatchInputTouchEvent(&event);
+    },
+    // up
+    [](void* data, struct wl_touch*, uint32_t, uint32_t time, int32_t id)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        auto& seatData = window.m_seatData;
+        if (!seatData.touch.tracking || id < 0 || id >= 10)
+            return;
+
+        seatData.touch.tracking = false;
+
+        struct wpe_input_touch_event_raw rawEvent = { wpe_input_touch_event_type_up,
+            time, id, seatData.touch.points[id].x, seatData.touch.points[id].y };
+        memcpy(&seatData.touch.points[id], &rawEvent, sizeof(struct wpe_input_touch_event_raw));
+
+        struct wpe_input_touch_event event = { seatData.touch.points, 10,
+            rawEvent.type, rawEvent.id, rawEvent.time, window.modifiers() };
+        window.dispatchInputTouchEvent(&event);
+
+        memset(&seatData.touch.points[id], 0x00, sizeof(struct wpe_input_touch_event_raw));
+    },
+    // motion
+    [](void* data, struct wl_touch*, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        auto& seatData = window.m_seatData;
+        if (!seatData.touch.tracking || id < 0 || id >= 10)
+            return;
+
+        struct wpe_input_touch_event_raw rawEvent = { wpe_input_touch_event_type_motion,
+            time, id, wl_fixed_to_int(x), wl_fixed_to_int(y) };
+        memcpy(&seatData.touch.points[id], &rawEvent, sizeof(struct wpe_input_touch_event_raw));
+
+        struct wpe_input_touch_event event = { seatData.touch.points, 10,
+            rawEvent.type, rawEvent.id, rawEvent.time, window.modifiers() };
+        window.dispatchInputTouchEvent(&event);
+    },
+    // frame
+    [](void*, struct wl_touch*) { },
+    // cancel
+    [](void*, struct wl_touch*) { },
+    // shape
+    [](void*, struct wl_touch*, int32_t, wl_fixed_t, wl_fixed_t) { },
+    // orientation
+    [](void*, struct wl_touch*, int32_t, wl_fixed_t) { },
+};
+
+const struct wl_seat_listener WindowViewBackend::s_seatListener = {
+    // capabilities
+    [](void* data, struct wl_seat* seat, uint32_t capabilities)
+    {
+        auto* window = static_cast<WindowViewBackend*>(data);
+        auto& seatData = window->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, window);
+        }
+        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, window);
+        }
+        if (!hasKeyboardCap && seatData.keyboard.object) {
+            wl_keyboard_destroy(seatData.keyboard.object);
+            seatData.keyboard.object = nullptr;
+        }
+
+        // WL_SEAT_CAPABILITY_TOUCH
+        const bool hasTouchCap = capabilities & WL_SEAT_CAPABILITY_TOUCH;
+        if (hasTouchCap && !seatData.touch.object) {
+            seatData.touch.object = wl_seat_get_touch(seat);
+            wl_touch_add_listener(seatData.touch.object, &s_touchListener, window);
+        }
+        if (!hasTouchCap && seatData.touch.object) {
+            wl_touch_destroy(seatData.touch.object);
+            seatData.touch.object = nullptr;
+        }
+    },
+    // name
+    [](void*, struct wl_seat*, const char*) { }
+};
+
+const struct zxdg_surface_v6_listener WindowViewBackend::s_xdgSurfaceListener = {
+    // configure
+    [](void*, struct zxdg_surface_v6* surface, uint32_t serial)
+    {
+        zxdg_surface_v6_ack_configure(surface, serial);
+    },
+};
+
+const struct zxdg_toplevel_v6_listener WindowViewBackend::s_xdgToplevelListener = {
+    // configure
+    [](void* data, struct zxdg_toplevel_v6*, int32_t width, int32_t height, struct wl_array* states)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        window.resize(std::max(0, width), std::max(0, height));
+
+        bool isFocused = false;
+        bool isFullscreen = false;
+        // FIXME: It would be nice if the following loop could use
+        // wl_array_for_each, but at the time of writing it relies on
+        // GCC specific extension to work properly:
+        // https://gitlab.freedesktop.org/wayland/wayland/issues/34
+        uint32_t* pos = static_cast<uint32_t*>(states->data);
+        uint32_t* end = static_cast<uint32_t*>(states->data) + states->size;
+
+        for (; pos < end; pos++) {
+            uint32_t state = *pos;
+
+            switch (state) {
+            case ZXDG_TOPLEVEL_V6_STATE_ACTIVATED:
+                isFocused = true;
+                break;
+            case ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN:
+                isFullscreen = true;
+                break;
+            case ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED:
+            case ZXDG_TOPLEVEL_V6_STATE_RESIZING:
+            default:
+                break;
+            }
+        }
+
+        if (isFocused)
+            window.addActivityState(wpe_view_activity_state_focused);
+        else
+            window.removeActivityState(wpe_view_activity_state_focused);
+
+        if (window.m_is_fullscreen != isFullscreen)
+            window.onFullscreenChanged(isFullscreen);
+    },
+    // close
+    [](void* data, struct zxdg_toplevel_v6*)
+    {
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        window.removeActivityState(wpe_view_activity_state_visible | wpe_view_activity_state_focused | wpe_view_activity_state_in_window);
+    },
+};
+
+#if WPE_CHECK_VERSION(1, 11, 1)
+
+bool WindowViewBackend::onDOMFullscreenRequest(void* data, bool fullscreen)
+{
+    auto& window = *static_cast<WindowViewBackend*>(data);
+    if (window.m_waiting_fullscreen_notify)
+        return false;
+
+    if (fullscreen == window.m_is_fullscreen) {
+        // Handle situations where DOM fullscreen requests are mixed with system fullscreen commands (e.g F11)
+        window.dispatchFullscreenEvent();
+        return true;
+    }
+
+    window.m_waiting_fullscreen_notify = true;
+    if (fullscreen)
+        zxdg_toplevel_v6_set_fullscreen(window.m_xdgToplevel, nullptr);
+    else
+        zxdg_toplevel_v6_unset_fullscreen(window.m_xdgToplevel);
+
+    return true;
+}
+
+void WindowViewBackend::dispatchFullscreenEvent()
+{
+    if (m_is_fullscreen)
+        wpe_view_backend_dispatch_did_enter_fullscreen(backend());
+    else
+        wpe_view_backend_dispatch_did_exit_fullscreen(backend());
+}
+
+void WindowViewBackend::onFullscreenChanged(bool fullscreen)
+{
+    bool wasRequestedFromDOM = m_waiting_fullscreen_notify;
+    m_waiting_fullscreen_notify= false;
+    m_is_fullscreen = fullscreen;
+
+    if (!fullscreen && !wasRequestedFromDOM)
+        wpe_view_backend_dispatch_request_exit_fullscreen(backend());
+    else if (wasRequestedFromDOM)
+        dispatchFullscreenEvent();
+}
+
+#else
+
+void WindowViewBackend::onFullscreenChanged(bool fullscreen)
+{
+    m_is_fullscreen = fullscreen;
+}
+
+#endif // WPE_CHECK_VERSION(1, 11, 1)
+
+WindowViewBackend::WindowViewBackend(uint32_t width, uint32_t height)
+    : ViewBackend(width, height)
+{
+    m_initialSize.width = width;
+    m_initialSize.height = height;
+
+    auto& connection = WaylandEGLConnection::singleton();
+    if (!connection.display) {
+        g_warning("WindowViewBackend: No Wayland EGL connection available");
+        return;
+    }
+
+    if (connection.eglDisplay == EGL_NO_DISPLAY || !initialize(connection.eglDisplay)) {
+        g_warning("WindowViewBackend: Could not initialize EGL display");
+        return;
+    }
+
+    {
+        auto* registry = wl_display_get_registry(connection.display);
+        wl_registry_add_listener(registry, &s_registryListener, this);
+        wl_display_roundtrip(connection.display);
+
+        if (m_xdg)
+            zxdg_shell_v6_add_listener(m_xdg, &s_xdgWmBaseListener, nullptr);
+
+        if (m_seat)
+            wl_seat_add_listener(m_seat, &s_seatListener, this);
+    }
+
+    m_eventSource = g_source_new(&EventSource::sourceFuncs, sizeof(EventSource));
+    {
+        auto& source = *reinterpret_cast<EventSource*>(m_eventSource);
+        source.display = connection.display;
+
+        source.pfd.fd = wl_display_get_fd(connection.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_DEFAULT);
+        g_source_set_can_recurse(&source.source, TRUE);
+        g_source_attach(&source.source, g_main_context_get_thread_default());
+    }
+
+    m_surface = wl_compositor_create_surface(m_compositor);
+    if (m_xdg) {
+        m_xdgSurface = zxdg_shell_v6_get_xdg_surface(m_xdg, m_surface);
+        zxdg_surface_v6_add_listener(m_xdgSurface, &s_xdgSurfaceListener, nullptr);
+        m_xdgToplevel = zxdg_surface_v6_get_toplevel(m_xdgSurface);
+        if (m_xdgToplevel) {
+            zxdg_toplevel_v6_add_listener(m_xdgToplevel, &s_xdgToplevelListener, this);
+            zxdg_toplevel_v6_set_title(m_xdgToplevel, "WPE");
+            wl_surface_commit(m_surface);
+            addActivityState(wpe_view_activity_state_visible | wpe_view_activity_state_in_window);
+        }
+    }
+
+    m_eglWindow = wl_egl_window_create(m_surface, m_width, m_height);
+
+    auto createPlatformWindowSurface =
+        reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
+    m_eglSurface = createPlatformWindowSurface(connection.eglDisplay, m_eglConfig, m_eglWindow, nullptr);
+    if (!m_eglSurface) {
+        g_warning("WindowViewBackend: Could not create EGL platform window surface");
+        return;
+    }
+
+    if (!eglMakeCurrent(connection.eglDisplay, m_eglSurface, m_eglSurface, m_eglContext)) {
+        g_warning("WindowViewBackend: Could not make EGL surface current");
+        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";
+
+        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");
+    }
+
+    createViewTexture();
+}
+
+WindowViewBackend::~WindowViewBackend()
+{
+    auto& connection = WaylandEGLConnection::singleton();
+
+    if (m_eventSource) {
+        g_source_destroy(m_eventSource);
+        g_source_unref(m_eventSource);
+    }
+
+    if (m_xdgToplevel)
+        zxdg_toplevel_v6_destroy(m_xdgToplevel);
+
+    if (m_xdgSurface)
+        zxdg_surface_v6_destroy(m_xdgSurface);
+
+    if (m_surface)
+        wl_surface_destroy(m_surface);
+
+    if (m_eglWindow)
+        wl_egl_window_destroy(m_eglWindow);
+
+    if (m_xdg)
+        zxdg_shell_v6_destroy(m_xdg);
+
+    if (m_seat)
+        wl_seat_destroy(m_seat);
+
+    if (m_compositor)
+        wl_compositor_destroy(m_compositor);
+
+    if (m_eglSurface)
+        eglDestroySurface(connection.eglDisplay, m_eglSurface);
+
+    if (m_display)
+        wl_display_disconnect(m_display);
+
+    deinitialize(connection.eglDisplay);
+}
+
+const struct wl_callback_listener WindowViewBackend::s_frameListener = {
+    // frame
+    [](void* data, struct wl_callback* callback, uint32_t)
+    {
+        if (callback)
+            wl_callback_destroy(callback);
+
+        auto& window = *static_cast<WindowViewBackend*>(data);
+        wpe_view_backend_exportable_fdo_dispatch_frame_complete(window.m_exportable);
+
+        if (window.m_committedImage)
+            wpe_view_backend_exportable_fdo_egl_dispatch_release_exported_image(window.m_exportable, window.m_committedImage);
+        window.m_committedImage = nullptr;
+    }
+};
+
+struct wpe_view_backend* WindowViewBackend::backend() const
+{
+    return m_exportable ? wpe_view_backend_exportable_fdo_get_view_backend(m_exportable) : nullptr;
+}
+
+void WindowViewBackend::createViewTexture()
+{
+    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, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+void WindowViewBackend::resize(uint32_t width, uint32_t height)
+{
+    if (!width)
+        width = m_initialSize.width;
+    if (!height)
+        height = m_initialSize.height;
+
+    if (width == m_width && height == m_height)
+        return;
+
+    m_width = width;
+    m_height = height;
+
+    wl_egl_window_resize(m_eglWindow, m_width, m_height, 0, 0);
+    wpe_view_backend_dispatch_set_size(backend(), m_width, m_height);
+
+    if (m_viewTexture)
+        glDeleteTextures(1, &m_viewTexture);
+    createViewTexture();
+}
+
+bool WindowViewBackend::initialize(EGLDisplay 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(eglDisplay, nullptr, 0, &count) || count < 1)
+            return false;
+
+        EGLConfig* configs = g_new0(EGLConfig, count);
+        EGLint matched = 0;
+        if (eglChooseConfig(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(eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttributes);
+    if (!m_eglContext)
+        return false;
+
+    static struct wpe_view_backend_exportable_fdo_egl_client exportableClient = {
+        // export_egl_image
+        nullptr,
+        // export_fdo_egl_image
+        [](void* data, struct wpe_fdo_egl_exported_image* image)
+        {
+            static_cast<WindowViewBackend*>(data)->displayBuffer(image);
+        },
+#if WPE_FDO_CHECK_VERSION(1, 5, 0)
+        // export_shm_buffer
+        [](void* data, struct wpe_fdo_shm_exported_buffer* buffer)
+        {
+            static_cast<WindowViewBackend*>(data)->displayBuffer(buffer);
+        },
+        // padding
+        nullptr, nullptr
+#else
+        // padding
+        nullptr, nullptr, nullptr
+#endif
+
+    };
+    m_exportable = wpe_view_backend_exportable_fdo_egl_create(&exportableClient, this, m_width, m_height);
+
+#if WPE_CHECK_VERSION(1, 11, 1)
+    wpe_view_backend_set_fullscreen_handler(backend(), onDOMFullscreenRequest, this);
+#endif
+
+    initializeAccessibility();
+
+    return true;
+}
+
+void WindowViewBackend::deinitialize(EGLDisplay eglDisplay)
+{
+    m_inputClient = nullptr;
+
+    if (m_eglContext)
+        eglDestroyContext(eglDisplay, m_eglContext);
+
+    if (m_exportable)
+        wpe_view_backend_exportable_fdo_destroy(m_exportable);
+}
+
+void WindowViewBackend::displayBuffer(struct wpe_fdo_egl_exported_image* image)
+{
+    if (!m_eglContext)
+        return;
+
+    auto& connection = WaylandEGLConnection::singleton();
+    eglMakeCurrent(connection.eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
+
+    glViewport(0, 0, m_width, m_height);
+    glClearColor(1, 0, 0, 1);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glUseProgram(m_program);
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, m_viewTexture);
+    imageTargetTexture2DOES(GL_TEXTURE_2D, wpe_fdo_egl_exported_image_get_egl_image(image));
+    glUniform1i(m_textureUniform, 0);
+
+    m_committedImage = image;
+
+    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 },
+    };
+
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices);
+    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 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(connection.eglDisplay, m_eglSurface);
+}
+
+#if WPE_FDO_CHECK_VERSION(1, 5, 0)
+void WindowViewBackend::displayBuffer(struct wpe_fdo_shm_exported_buffer*)
+{
+    g_warning("WindowViewBackend: cannot yet handle wpe_fdo_shm_exported_buffer.");
+}
+#endif
+
+void WindowViewBackend::handleKeyEvent(uint32_t key, uint32_t state, uint32_t time)
+{
+    uint32_t keysym = wpe_input_xkb_context_get_key_code(wpe_input_xkb_context_get_default(), key, state == WL_KEYBOARD_KEY_STATE_PRESSED);
+    if (!keysym)
+        return;
+
+    if (m_seatData.keyboard.target) {
+        struct wpe_input_keyboard_event event = { time, keysym, key, !!state, modifiers() };
+        dispatchInputKeyboardEvent(&event);
+    }
+}
+
+uint32_t WindowViewBackend::modifiers() const
+{
+    uint32_t mask = m_seatData.keyboard.modifiers;
+    if (m_seatData.pointer.object)
+        mask |= m_seatData.pointer.modifiers;
+    return mask;
+}
+
+} // namespace WPEToolingBackends

Copied: trunk/Tools/wpe/backends/fdo/WindowViewBackend.h (from rev 288813, trunk/Tools/wpe/backends/WindowViewBackend.h) (0 => 288814)


--- trunk/Tools/wpe/backends/fdo/WindowViewBackend.h	                        (rev 0)
+++ trunk/Tools/wpe/backends/fdo/WindowViewBackend.h	2022-01-31 15:14:28 UTC (rev 288814)
@@ -0,0 +1,157 @@
+/*
+ * 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. 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 APPLE INC. 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.
+ */
+
+#pragma once
+
+#include "ViewBackend.h"
+#include "xdg-shell-unstable-v6-client-protocol.h"
+#include <glib.h>
+#include <unordered_map>
+#include <wpe/fdo.h>
+
+typedef void* EGLConfig;
+typedef void* EGLContext;
+typedef void* EGLDisplay;
+typedef void* EGLSurface;
+typedef struct wl_egl_window *EGLNativeWindowType;
+
+// Manually provide the EGL_CAST C++ definition in case eglplatform.h doesn't provide it.
+#ifndef EGL_CAST
+#define EGL_CAST(type, value) (static_cast<type>(value))
+#endif
+
+struct wpe_fdo_egl_exported_image;
+
+namespace WPEToolingBackends {
+
+class WindowViewBackend final : public ViewBackend {
+public:
+    WindowViewBackend(uint32_t width, uint32_t height);
+    virtual ~WindowViewBackend();
+
+    struct wpe_view_backend* backend() const override;
+
+private:
+    void createViewTexture();
+    void resize(uint32_t width, uint32_t height);
+
+    bool initialize(EGLDisplay);
+    void deinitialize(EGLDisplay);
+
+    void displayBuffer(struct wpe_fdo_egl_exported_image*);
+#if WPE_FDO_CHECK_VERSION(1, 5, 0)
+    void displayBuffer(struct wpe_fdo_shm_exported_buffer*);
+#endif
+
+    static const struct wl_registry_listener s_registryListener;
+    static const struct zxdg_shell_v6_listener s_xdgWmBaseListener;
+    static const struct wl_pointer_listener s_pointerListener;
+    static const struct wl_keyboard_listener s_keyboardListener;
+    static const struct wl_touch_listener s_touchListener;
+    static const struct wl_seat_listener s_seatListener;
+    static const struct wl_callback_listener s_frameListener;
+    static const struct zxdg_surface_v6_listener s_xdgSurfaceListener;
+    static const struct zxdg_toplevel_v6_listener s_xdgToplevelListener;
+
+#if WPE_CHECK_VERSION(1, 11, 1)
+    static bool onDOMFullscreenRequest(void* data, bool fullscreen);
+    void dispatchFullscreenEvent();
+#endif
+    void onFullscreenChanged(bool fullscreen);
+
+    void handleKeyEvent(uint32_t key, uint32_t state, uint32_t time);
+    uint32_t modifiers() const;
+
+    struct SeatData {
+        struct {
+            struct wl_pointer* object { nullptr };
+            struct wl_surface* target { nullptr };
+            std::pair<int, int> coords { 0, 0 };
+            uint32_t button { 0 };
+            uint32_t state { 0 };
+            uint32_t modifiers { 0 };
+        } pointer;
+
+        struct {
+            struct wl_keyboard* object { nullptr };
+            struct wl_surface* target { nullptr };
+            uint32_t modifiers { 0 };
+        } keyboard;
+
+        struct {
+            struct wl_touch* object { nullptr };
+            struct wpe_input_touch_event_raw points[10];
+            bool tracking { false };
+        } touch;
+
+        struct {
+            int32_t horizontal { 0 };
+            int32_t vertical { 0 };
+        } axis_discrete;
+
+        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 {
+        uint32_t width;
+        uint32_t height;
+    } m_initialSize;
+
+    struct wpe_view_backend_exportable_fdo* m_exportable { nullptr };
+
+    struct wl_display* m_display { nullptr };
+    struct wl_compositor* m_compositor { nullptr };
+    struct zxdg_shell_v6* m_xdg { nullptr };
+    struct wl_seat* m_seat { nullptr };
+    GSource* m_eventSource { nullptr };
+    struct wl_surface* m_surface { nullptr };
+    struct zxdg_surface_v6* m_xdgSurface { nullptr };
+    struct zxdg_toplevel_v6* m_xdgToplevel { nullptr };
+    struct wl_egl_window* m_eglWindow { nullptr };
+    EGLContext m_eglContext { nullptr };
+    EGLConfig m_eglConfig;
+    EGLSurface m_eglSurface { nullptr };
+    unsigned m_program { 0 };
+    unsigned m_textureUniform { 0 };
+    unsigned m_viewTexture { 0 };
+    struct wpe_fdo_egl_exported_image* m_committedImage { nullptr };
+    bool m_is_fullscreen { false };
+#if WPE_CHECK_VERSION(1, 11, 1)
+    bool m_waiting_fullscreen_notify { false };
+#endif
+};
+
+} // WPEToolingBackends
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to