diff --git a/.clang-format b/.clang-format index c0649c0f..8269e189 100644 --- a/.clang-format +++ b/.clang-format @@ -61,7 +61,7 @@ ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DeriveLineEnding: true -DerivePointerAlignment: true +DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: true FixNamespaceComments: true diff --git a/.github/toolchain.sh b/.github/toolchain.sh index b8578456..c1533c1a 100755 --- a/.github/toolchain.sh +++ b/.github/toolchain.sh @@ -1,19 +1,51 @@ #! /bin/bash -set -e +set -eu -o pipefail +# Info on available toolchains: https://wk-contrib.igalia.com/ INSTALL_DIR=${1:-${HOME}/toolchain} -BASEURL=https://wk-contrib.igalia.com/yocto/meta-perf-browser/browsers/nightly/sdk -FILE=wandboard-mesa/browsers-glibc-x86_64-core-image-weston-browsers-armv7at2hf-neon-wandboard-mesa-toolchain-1.0.sh +BASEURL=https://wk-contrib.igalia.com/yocto/meta-perf-browser/browsers/stable/sdk +FILE=wandboard-mesa/browsers-glibc-x86_64-core-image-weston-browsers-cortexa9t2hf-neon-wandboard-mesa-toolchain-1.0.sh declare -r INSTALL_DIR BASEURL FILE rm -f ~/toolchain.sh -declare -a curl_opts=( --retry 3 -L ) +declare -a curl_opts=( --http1.1 --retry 3 -L -C - ) if [[ -r ${INSTALL_DIR}/.installed ]] ; then curl_opts+=( --time-cond "${INSTALL_DIR}/.installed" ) fi -curl "${curl_opts[@]}" -o ~/toolchain.sh "${BASEURL}/${FILE}" +declare -i tries=0 + +function fetch_installer { + if [[ $(( tries++ )) -ge 10 ]] ; then + echo 'Maximum amount of retries reached, bailing out.' 1>&2 + return 1 + fi + + local exit_code=0 + if curl "${curl_opts[@]}" -o ~/toolchain.sh "${BASEURL}/${FILE}" ; then + return 0 + else + exit_code=$? + + if [[ ${exit_code} -eq 36 ]] ; then + echo "Bad resume (${exit_code}), restarting download from scratch..." 1>&2 + rm -f ~/toolchain.sh + else + echo "Download error (${exit_code}), retrying download..." 1>&2 + fi + local seconds=$(( RANDOM % 10 + 5 )) + printf 'Waiting... %i' "${seconds}" + while [[ $(( seconds-- )) -gt 0 ]] ; do + sleep 1 + printf ' %i' "${seconds}" + done + echo '.' + fetch_installer + fi +} + +fetch_installer if [[ -r ~/toolchain.sh ]] ; then echo 'Installing toolchain...' diff --git a/.github/workflows/ci-cross.yml b/.github/workflows/ci-cross.yml index b8223eb0..69442ad1 100644 --- a/.github/workflows/ci-cross.yml +++ b/.github/workflows/ci-cross.yml @@ -14,7 +14,7 @@ jobs: - name: Install Debian Packages run: | sudo apt update - sudo apt install -y cmake ninja-build + sudo apt install -y cmake ninja-build libwayland-bin - name: Cache uses: actions/cache@v2 id: cache @@ -29,8 +29,9 @@ jobs: env: BUILD_TYPE: ${{ matrix.buildtype }} run: |- - . ~/toolchain/environment-setup-armv7at2hf-neon-poky-linux-gnueabi + . ~/toolchain/environment-setup-*-poky-linux-gnueabi cmake -GNinja -S. -Bbuild \ + -DWAYLAND_SCANNER=/usr/bin/wayland-scanner \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ -DCOG_PLATFORM_FDO=ON \ -DCOG_PLATFORM_DRM=ON diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml index 3e6da18c..ac4d5431 100644 --- a/.github/workflows/codestyle.yml +++ b/.github/workflows/codestyle.yml @@ -17,9 +17,9 @@ jobs: curl -sL https://apt.llvm.org/llvm-snapshot.gpg.key | \ sudo apt-key add - sudo add-apt-repository \ - 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main' + 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-13 main' sudo apt update - sudo apt install -y clang-format-11 diffutils + sudo apt install -y clang-format-13 diffutils - name: Check run: | data/check-style -ocode-style.diff origin/master diff --git a/CMakeLists.txt b/CMakeLists.txt index 30491a18..93799104 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required (VERSION 3.3) list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_SOURCE_DIR}/cmake") include(VersioningUtils) -set_project_version(0 9 1) +set_project_version(0 13 0) # Before making a release, the LT_VERSION string should be modified. # The string is of the form C:R:A. @@ -12,7 +12,7 @@ set_project_version(0 9 1) # - If binary compatibility has been broken (eg removed or changed interfaces) # change to C+1:0:0 # - If the interface is the same as the previous version, change to C:R+1:A -calculate_library_versions_from_libtool_triple(COGCORE 5 0 4) +calculate_library_versions_from_libtool_triple(COGCORE 8 0 1) project(cog VERSION "${PROJECT_VERSION}" LANGUAGES C) include(DistTargets) @@ -126,11 +126,13 @@ set(COGCORE_SOURCES ) if (USE_SOUP2) + set(WPEWEBKIT_PC_NAME "wpe-webkit-1.0") set(REQUIRED_GIO_VERSION "gio-2.0>=2.44") set(REQUIRED_SOUP_VERSION "libsoup-2.4") set(REQUIRED_WEBKIT_VERSION "wpe-webkit-1.0>=2.28.0") add_definitions("-DCOG_USE_SOUP2=1") else() + set(WPEWEBKIT_PC_NAME "wpe-webkit-1.1") set(REQUIRED_GIO_VERSION "gio-2.0>=2.67.4") set(REQUIRED_SOUP_VERSION "libsoup-3.0>=2.99.7") set(REQUIRED_WEBKIT_VERSION "wpe-webkit-1.1>=2.33.1") diff --git a/NEWS b/NEWS index c8ae5a0c..c72aaa03 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,26 @@ +========================= +0.11.1 - November 3, 2021 +========================= + +- core: Changed platform plug-ins to be able to automatically detect which + one should be used. Passing the "--platform=" command line option to the + launcher is now optional. +- core: Added support for building against libsoup3. +- core: Added CogHostRoutesHandler, which can route URI scheme requests + with different host parts to other handlers. +- core, cog: Added support for running in WebDriver automation mode. +- cog: New "--enable-sandbox" command line option, which allows isolating + rendering processes from the rest of the system. +- cog: New "--content-filter=" command line option, which allows loading + a content blocker (WebKitUserContentFilter) JSON rule set. +- drm: Implemented handling of pointer axis/wheel/finger/continuous events + and absolute motion events. +- wl: Renamed "fdo" platform module to "wl" (Wayland) as it better reflects + its usage; the old name still works e.g. when using "cog --platform=fdo" + but it is considered deprecated and will cause a warning. +- wl, gtk4: Added support for fullscreening web views. +- gtk4: Honor the CogShell.device-scale-factor property. + ====================== 0.9.1 - March 16, 2021 ====================== diff --git a/cog.c b/cog.c index c88236cd..618b6c93 100644 --- a/cog.c +++ b/cog.c @@ -342,13 +342,7 @@ platform_setup (CogShell *shell) static void on_shutdown (CogLauncher *launcher G_GNUC_UNUSED, void *user_data G_GNUC_UNUSED) { - g_debug ("%s: Platform = %p", __func__, s_options.platform); - - if (s_options.platform) { - cog_platform_teardown (s_options.platform); - g_clear_object(&s_options.platform); - g_debug ("%s: Platform teardown completed.", __func__); - } + g_clear_object(&s_options.platform); } static void* diff --git a/core/cog-platform.c b/core/cog-platform.c index 516de59b..57b16a51 100644 --- a/core/cog-platform.c +++ b/core/cog-platform.c @@ -93,16 +93,6 @@ cog_platform_new(const char *name, GError **error) return g_steal_pointer(&self); } -void -cog_platform_teardown(CogPlatform *platform) -{ - g_return_if_fail(COG_IS_PLATFORM(platform)); - - CogPlatformClass *klass = COG_PLATFORM_GET_CLASS(platform); - if (klass->teardown) - klass->teardown(platform); -} - gboolean cog_platform_setup (CogPlatform *platform, CogShell *shell, diff --git a/core/cog-platform.h b/core/cog-platform.h index 635931a8..28e708d6 100644 --- a/core/cog-platform.h +++ b/core/cog-platform.h @@ -47,7 +47,6 @@ struct _CogPlatformClass { /*< public >*/ gboolean (*is_supported)(void); gboolean (*setup)(CogPlatform *, CogShell *shell, const char *params, GError **); - void (*teardown)(CogPlatform *); WebKitWebViewBackend *(*get_view_backend)(CogPlatform *, WebKitWebView *related_view, GError **); void (*init_web_view)(CogPlatform *, WebKitWebView *); WebKitInputMethodContext *(*create_im_context)(CogPlatform *); @@ -59,8 +58,6 @@ CogPlatform *cog_platform_new(const char *name, GError **); gboolean cog_platform_setup(CogPlatform *platform, CogShell *shell, const char *params, GError **error); -void cog_platform_teardown (CogPlatform *platform); - WebKitWebViewBackend *cog_platform_get_view_backend (CogPlatform *platform, WebKitWebView *related_view, GError **error); diff --git a/data/check-style b/data/check-style index 77572c59..bdfb101c 100755 --- a/data/check-style +++ b/data/check-style @@ -52,8 +52,8 @@ declare -r BASE HEAD declare -ra clang_format_diff_candidates=( # Search in $PATH (Ubuntu, Debian, maybe others) - clang-format-diff-11 - clang-format-diff-11.py + clang-format-diff-13 + clang-format-diff-13.py clang-format-diff clang-format-diff.py # Arch Linux, Fedora. diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index c3fa17d7..1975fab1 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -63,7 +63,7 @@ add_custom_command( --identifier-prefix=Cog --symbol-prefix=cog --pkg-export=cogcore - --pkg=wpe-webkit-1.0 + --pkg=${WPEWEBKIT_PC_NAME} --pkg=gobject-2.0 --pkg=gio-2.0 --pkg=glib-2.0 diff --git a/docs/cog.toml.in b/docs/cog.toml.in index f6990c01..72bcf356 100644 --- a/docs/cog.toml.in +++ b/docs/cog.toml.in @@ -43,7 +43,7 @@ base_url = "https://github.com/Igalia/cog/blob/master/" content_files = [ "overview.md", "contributing.md", - "platform-fdo.md", + "platform-wl.md", "platform-drm.md", "platform-x11.md", "platform-headless.md", diff --git a/docs/platform-fdo.md b/docs/platform-fdo.md deleted file mode 100644 index 58ffd8e8..00000000 --- a/docs/platform-fdo.md +++ /dev/null @@ -1,14 +0,0 @@ -Title: Platform: FDO - -# FDO Platform - -## Requirements - -The FDO platform plug-in additionally requires the following libraries and -packages: - -- **WPEBackend-fdo**: -- **Wayland**: -- **libxkbcommon**: -- **wayland-protocols**: -- **wayland-scanner**: diff --git a/docs/platform-wl.md b/docs/platform-wl.md new file mode 100644 index 00000000..0c0d98ab --- /dev/null +++ b/docs/platform-wl.md @@ -0,0 +1,14 @@ +Title: Platform: WL + +# Wayland Platform + +## Requirements + +The `wl` (Wayland) platform plug-in additionally requires the following +libraries and packages: + +- **WPEBackend-fdo**: +- **Wayland**: +- **libxkbcommon**: +- **wayland-protocols**: +- **wayland-scanner**: diff --git a/docs/webdriver.md b/docs/webdriver.md index b359ed73..6c9c7022 100644 --- a/docs/webdriver.md +++ b/docs/webdriver.md @@ -33,7 +33,7 @@ def capabilities(): return { "wpe:browserOptions": { "binary": "/usr/bin/cog", - "args": ["--automation", "--platform=fdo"], + "args": ["--automation", "--platform=wl"], } } diff --git a/platform/drm/cog-platform-drm.c b/platform/drm/cog-platform-drm.c index fca1678b..8c51fe23 100644 --- a/platform/drm/cog-platform-drm.c +++ b/platform/drm/cog-platform-drm.c @@ -353,13 +353,16 @@ check_drm(void) if (num_devices < 0) return FALSE; - for (int i = 0; i < num_devices; ++i) { - drmDevice *device = devices[i]; - if (!!(device->available_nodes & (1 << DRM_NODE_PRIMARY))) - return TRUE; + gboolean supported = FALSE; + for (int i = 0; !supported && i < num_devices; ++i) { + if (devices[i]->available_nodes & (1 << DRM_NODE_PRIMARY)) { + supported = TRUE; + break; + } } - return FALSE; + drmFreeDevices(devices, num_devices); + return supported; } static gboolean @@ -405,6 +408,8 @@ init_drm(void) drm_data.fd = -1; } + drmFreeDevices(devices, num_devices); + if (!drm_data.base_resources) return FALSE; @@ -1822,18 +1827,17 @@ cog_drm_platform_setup(CogPlatform *platform, CogShell *shell, const char *param } static void -cog_drm_platform_teardown(CogPlatform *platform) +cog_drm_platform_finalize(GObject *object) { - g_assert (platform); - clear_buffers (); - clear_glib (); clear_input (); clear_egl (); clear_gbm (); clear_cursor (); clear_drm (); + + G_OBJECT_CLASS(cog_drm_platform_parent_class)->finalize(object); } static WebKitWebViewBackend * @@ -1875,10 +1879,12 @@ cog_drm_platform_init_web_view(CogPlatform *platform, WebKitWebView *view) static void cog_drm_platform_class_init(CogDrmPlatformClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + object_class->finalize = cog_drm_platform_finalize; + CogPlatformClass *platform_class = COG_PLATFORM_CLASS(klass); platform_class->is_supported = cog_drm_platform_is_supported; platform_class->setup = cog_drm_platform_setup; - platform_class->teardown = cog_drm_platform_teardown; platform_class->get_view_backend = cog_drm_platform_get_view_backend; platform_class->init_web_view = cog_drm_platform_init_web_view; } diff --git a/platform/gtk4/cog-platform-gtk4.c b/platform/gtk4/cog-platform-gtk4.c index 20944d05..ce8dc82a 100644 --- a/platform/gtk4/cog-platform-gtk4.c +++ b/platform/gtk4/cog-platform-gtk4.c @@ -772,12 +772,6 @@ cog_gtk4_platform_setup(CogPlatform* platform, CogShell* shell, const char* para return TRUE; } -static void -cog_gtk4_platform_teardown(CogPlatform* platform) -{ - g_assert_nonnull(platform); -} - static WebKitWebViewBackend* cog_gtk4_platform_get_view_backend(CogPlatform* platform, WebKitWebView* related_view, GError** error) { @@ -865,7 +859,6 @@ cog_gtk4_platform_class_init(CogGtk4PlatformClass* klass) CogPlatformClass* platform_class = COG_PLATFORM_CLASS(klass); platform_class->is_supported = cog_gtk4_platform_is_supported; platform_class->setup = cog_gtk4_platform_setup; - platform_class->teardown = cog_gtk4_platform_teardown; platform_class->get_view_backend = cog_gtk4_platform_get_view_backend; platform_class->init_web_view = cog_gtk4_platform_init_web_view; } diff --git a/platform/headless/cog-platform-headless.c b/platform/headless/cog-platform-headless.c index 80439f19..22e3cf0b 100644 --- a/platform/headless/cog-platform-headless.c +++ b/platform/headless/cog-platform-headless.c @@ -81,10 +81,12 @@ cog_headless_platform_setup(CogPlatform* platform, CogShell* shell G_GNUC_UNUSED } static void -cog_headless_platform_teardown(CogPlatform* platform) +cog_headless_platform_finalize(GObject* object) { g_source_remove(win.tick_source); wpe_view_backend_exportable_fdo_destroy(win.exportable); + + G_OBJECT_CLASS(cog_headless_platform_parent_class)->finalize(object); } static WebKitWebViewBackend* @@ -97,9 +99,11 @@ cog_headless_platform_get_view_backend(CogPlatform* platform, WebKitWebView* rel static void cog_headless_platform_class_init(CogHeadlessPlatformClass* klass) { + GObjectClass* object_class = G_OBJECT_CLASS(klass); + object_class->finalize = cog_headless_platform_finalize; + CogPlatformClass* platform_class = COG_PLATFORM_CLASS(klass); platform_class->setup = cog_headless_platform_setup; - platform_class->teardown = cog_headless_platform_teardown; platform_class->get_view_backend = cog_headless_platform_get_view_backend; } diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index 72bc561d..60d1fa81 100644 --- a/platform/wayland/cog-platform-wl.c +++ b/platform/wayland/cog-platform-wl.c @@ -72,8 +72,8 @@ #endif #if defined(WAYLAND_VERSION_MAJOR) && defined(WAYLAND_VERSION_MINOR) -# define WAYLAND_1_10_OR_GREATER ((WAYLAND_VERSION_MAJOR >= 2) || \ - (WAYLAND_VERSION_MAJOR == 1 && WAYLAND_VERSION_MINOR >= 10)) +# define WAYLAND_1_10_OR_GREATER \ + ((WAYLAND_VERSION_MAJOR >= 2) || (WAYLAND_VERSION_MAJOR == 1 && WAYLAND_VERSION_MINOR >= 10)) #else # define WAYLAND_1_10_OR_GREATER 0 #endif @@ -85,6 +85,34 @@ struct _CogWlPlatformClass { struct _CogWlPlatform { CogPlatform parent; }; +static void resize_to_largest_output(); +static void resize_window(); + +static void configure_surface_geometry(); +static void xdg_surface_on_configure(void *data, struct xdg_surface *surface, uint32_t serial); +static void xdg_toplevel_on_configure(void * data, + struct xdg_toplevel *toplevel, + int32_t width, + int32_t height, + struct wl_array * states); +static void xdg_toplevel_on_close(void *data, struct xdg_toplevel *xdg_toplevel); +static void shell_surface_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial); +static void shell_surface_configure(void * data, + struct wl_shell_surface *shell_surface, + uint32_t edges, + int32_t width, + int32_t height); +static void +xdg_popup_on_configure(void *data, struct xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height); +static void xdg_popup_on_popup_done(void *data, struct xdg_popup *xdg_popup); +static void shell_popup_surface_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial); +static void shell_popup_surface_configure(void * data, + struct wl_shell_surface *shell_surface, + uint32_t edges, + int32_t width, + int32_t height); +static void shell_popup_surface_popup_done(void *data, struct wl_shell_surface *shell_surface); +static void display_popup(void); G_DECLARE_FINAL_TYPE(CogWlPlatform, cog_wl_platform, COG, WL_PLATFORM, CogPlatform) @@ -132,9 +160,62 @@ struct shm_buffer { #endif #ifndef EGL_WL_create_wayland_buffer_from_image -typedef struct wl_buffer * (EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL) (EGLDisplay dpy, EGLImageKHR image); +typedef struct wl_buffer *(EGLAPIENTRYP PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL)(EGLDisplay dpy, EGLImageKHR image); #endif +typedef struct { + void (*enter_fullscreen)(); + void (*exit_fullscreen)(); + void (*maximize_surface)(); + void (*destroy_shell)(); + void (*create_window)(); + void (*create_popup)(); + void (*destroy_window)(); + void (*destroy_popup)(); +} shell_functions; + +typedef struct { + shell_functions functions; + struct xdg_surface * xdg_surface; + struct xdg_toplevel * xdg_toplevel; + struct xdg_popup * xdg_popup; + struct xdg_positioner *xdg_positioner; +} xdg_shell_data; + +typedef struct { + shell_functions functions; + struct wl_shell_surface *shell_surface; +} wl_shell_data; + +typedef struct { + shell_functions functions; +} f_shell_data; + +typedef union { + shell_functions functions; + f_shell_data f_shell_data; + wl_shell_data wl_shell_data; + xdg_shell_data xdg_shell_data; +} shell_context; + +static void no_shell_enter_fullscreen(); +static void no_shell_exit_fullscreen(); +static void no_shell_maximize(); +static void no_shell_destroy_shell(); +static void no_shell_create_window(); +static void no_shell_create_popup(); +static void no_shell_destroy_window(); +static void no_shell_destroy_popup(); + +static const shell_functions no_shell_functions_window = {.enter_fullscreen = &no_shell_enter_fullscreen, + .exit_fullscreen = &no_shell_exit_fullscreen, + .maximize_surface = &no_shell_maximize, + .destroy_shell = &no_shell_destroy_shell, + .create_window = &no_shell_create_window, + .create_popup = &no_shell_create_popup, + .destroy_window = &no_shell_destroy_window, + .destroy_popup = &no_shell_destroy_popup}; +static const shell_functions no_shell_functions_popup = no_shell_functions_window; typedef struct output_metrics { struct wl_output *output; @@ -232,15 +313,11 @@ static struct { } egl_data; static struct { - struct wl_surface *wl_surface; - #if COG_ENABLE_WESTON_DIRECT_DISPLAY GHashTable *video_surfaces; #endif - - struct xdg_surface *xdg_surface; - struct xdg_toplevel *xdg_toplevel; - struct wl_shell_surface *shell_surface; + shell_context * shell_context; + struct wl_surface *wl_surface; uint32_t width; uint32_t height; @@ -254,22 +331,16 @@ static struct { bool is_resizing_fullscreen; bool is_maximized; bool should_resize_to_largest_output; -} win_data = { - .width = DEFAULT_WIDTH, - .height = DEFAULT_HEIGHT, - .width_before_fullscreen = DEFAULT_WIDTH, - .height_before_fullscreen = DEFAULT_HEIGHT, -}; +} win_data = {.width = DEFAULT_WIDTH, + .height = DEFAULT_HEIGHT, + .width_before_fullscreen = DEFAULT_WIDTH, + .height_before_fullscreen = DEFAULT_HEIGHT, + .shell_context = (shell_context *) (&no_shell_functions_window)}; static struct { + shell_context * shell_context; struct wl_surface *wl_surface; - struct xdg_positioner *xdg_positioner; - struct xdg_surface *xdg_surface; - struct xdg_popup *xdg_popup; - - struct wl_shell_surface *shell_surface; - uint32_t width; uint32_t height; @@ -277,10 +348,284 @@ static struct { WebKitOptionMenu *option_menu; bool configured; -} popup_data = { - .configured = false, +} popup_data = {.configured = false, .shell_context = (shell_context *) (&no_shell_functions_popup)}; + +//default executed when no shell exist +static void +no_shell_enter_fullscreen() +{ + g_warning("No available shell capable of fullscreening."); + win_data.is_fullscreen = false; +} +static void +no_shell_exit_fullscreen() +{ + g_assert_not_reached(); +} +static void +no_shell_maximize() +{ + g_warning("No available shell capable of maximizing."); + win_data.is_maximized = false; +} +static void +no_shell_destroy_shell() +{ + g_warning("No available shell to be destroyed."); +} +static void +no_shell_create_window() +{ + g_warning("No available shell to allow you create a window."); +} +static void +no_shell_create_popup() +{ + g_warning("No available shell to allow you create a popup."); +} +static void +no_shell_destroy_window() +{ + g_warning("No available shell whose window can be destroyed"); +} +static void +no_shell_destroy_popup() +{ + g_warning("No available shell to allow you destroy a popup."); +} + +//shell operation functions +//TODO: put in a separate file +static void +xdg_shell_enter_fullscreen() +{ + xdg_toplevel_set_fullscreen(win_data.shell_context->xdg_shell_data.xdg_toplevel, NULL); +} +static void +xdg_shell_exit_fullscreen() +{ + xdg_toplevel_unset_fullscreen(win_data.shell_context->xdg_shell_data.xdg_toplevel); +} +static void +xdg_shell_destroy_shell() +{ + xdg_wm_base_destroy(wl_data.xdg_shell); +} +static void +xdg_shell_maximize_surface() +{ + xdg_toplevel_set_maximized(win_data.shell_context->xdg_shell_data.xdg_toplevel); +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + .configure = xdg_toplevel_on_configure, + .close = xdg_toplevel_on_close, }; +static const struct xdg_surface_listener xdg_surface_listener = {.configure = xdg_surface_on_configure}; + +static const struct xdg_popup_listener xdg_popup_listener = { + .configure = xdg_popup_on_configure, + .popup_done = xdg_popup_on_popup_done, +}; + +static void +xdg_shell_create_window() +{ + xdg_shell_data *data = &win_data.shell_context->xdg_shell_data; + data->xdg_surface = xdg_wm_base_get_xdg_surface(wl_data.xdg_shell, win_data.wl_surface); + g_assert(data->xdg_surface); + + xdg_surface_add_listener(data->xdg_surface, &xdg_surface_listener, NULL); + data->xdg_toplevel = xdg_surface_get_toplevel(data->xdg_surface); + g_assert(data->xdg_toplevel); + + xdg_toplevel_add_listener(data->xdg_toplevel, &xdg_toplevel_listener, NULL); + xdg_toplevel_set_title(data->xdg_toplevel, COG_DEFAULT_APPNAME); + + const char *app_id = g_application_get_application_id(g_application_get_default()); + if (!app_id) + app_id = COG_DEFAULT_APPID; + + xdg_toplevel_set_app_id(data->xdg_toplevel, app_id); + wl_surface_commit(win_data.wl_surface); +} +static void +xdg_shell_create_popup() +{ + xdg_shell_data *data = &popup_data.shell_context->xdg_shell_data; + + data->xdg_positioner = xdg_wm_base_create_positioner(wl_data.xdg_shell); + g_assert(data->xdg_positioner); + + xdg_positioner_set_size(data->xdg_positioner, popup_data.width, popup_data.height); + xdg_positioner_set_anchor_rect(data->xdg_positioner, 0, (win_data.height - popup_data.height), popup_data.width, + popup_data.height); + + data->xdg_surface = xdg_wm_base_get_xdg_surface(wl_data.xdg_shell, popup_data.wl_surface); + g_assert(data->xdg_surface); + + xdg_surface_add_listener(data->xdg_surface, &xdg_surface_listener, NULL); + data->xdg_popup = xdg_surface_get_popup(data->xdg_surface, data->xdg_surface, data->xdg_positioner); + g_assert(data->xdg_popup); + + xdg_popup_add_listener(data->xdg_popup, &xdg_popup_listener, NULL); + xdg_popup_grab(data->xdg_popup, wl_data.seat, wl_data.event_serial); + wl_surface_commit(popup_data.wl_surface); +} + +static void +xdg_shell_destroy_window() +{ + g_clear_pointer(&win_data.shell_context->xdg_shell_data.xdg_toplevel, xdg_toplevel_destroy); + g_clear_pointer(&win_data.shell_context->xdg_shell_data.xdg_surface, xdg_surface_destroy); +} + +static void +xdg_shell_destroy_popup() +{ + g_clear_pointer(&popup_data.shell_context->xdg_shell_data.xdg_surface, xdg_surface_destroy); + g_clear_pointer(&popup_data.shell_context->xdg_shell_data.xdg_popup, xdg_popup_destroy); + g_clear_pointer(&popup_data.shell_context->xdg_shell_data.xdg_positioner, xdg_positioner_destroy); +} + +xdg_shell_data xdg_data = {.functions = {.enter_fullscreen = &xdg_shell_enter_fullscreen, + .exit_fullscreen = &xdg_shell_exit_fullscreen, + .destroy_shell = &xdg_shell_destroy_shell, + .maximize_surface = &xdg_shell_maximize_surface, + .create_window = &xdg_shell_create_window, + .create_popup = &xdg_shell_create_popup, + .destroy_window = &xdg_shell_destroy_window, + .destroy_popup = &xdg_shell_destroy_popup}}; + +// wl shell operations +static void +wl_shell_enter_fullscreen() +{ + wl_shell_surface_set_fullscreen(win_data.shell_context->wl_shell_data.shell_surface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE, 0, NULL); +} +static void +wl_shell_exit_fullscreen() +{ + wl_shell_surface_set_toplevel(win_data.shell_context->wl_shell_data.shell_surface); + configure_surface_geometry(win_data.width_before_fullscreen, win_data.height_before_fullscreen); + resize_window(); +} +static void +wl_shell_destroy_shell() +{ + wl_shell_destroy(wl_data.shell); +} +static void +wl_shell_maximize_surface() +{ + wl_shell_surface_set_maximized(win_data.shell_context->wl_shell_data.shell_surface, NULL); +} + +static const struct wl_shell_surface_listener shell_surface_listener = { + .ping = shell_surface_ping, + .configure = shell_surface_configure, +}; + +static void +wl_shell_create_window() +{ + win_data.shell_context->wl_shell_data.shell_surface = + wl_shell_get_shell_surface(wl_data.shell, win_data.wl_surface); + g_assert(win_data.shell_context->wl_shell_data.shell_surface); + + wl_shell_surface_add_listener(win_data.shell_context->wl_shell_data.shell_surface, &shell_surface_listener, 0); + wl_shell_surface_set_toplevel(win_data.shell_context->wl_shell_data.shell_surface); + + /* wl_shell needs an initial surface configuration. */ + configure_surface_geometry(0, 0); +} + +static const struct wl_shell_surface_listener shell_popup_surface_listener = { + .ping = shell_popup_surface_ping, + .configure = shell_popup_surface_configure, + .popup_done = shell_popup_surface_popup_done, +}; + +static void +wl_shell_create_popup() +{ + popup_data.shell_context->wl_shell_data.shell_surface = + wl_shell_get_shell_surface(wl_data.shell, popup_data.wl_surface); + g_assert(win_data.shell_context->wl_shell_data.shell_surface); + + wl_shell_surface_add_listener(win_data.shell_context->wl_shell_data.shell_surface, &shell_popup_surface_listener, + NULL); + wl_shell_surface_set_popup(win_data.shell_context->wl_shell_data.shell_surface, wl_data.seat, wl_data.event_serial, + win_data.wl_surface, 0, (win_data.height - popup_data.height), 0); + + display_popup(); +} + +static void +wl_shell_destroy_window() +{ + g_clear_pointer(&win_data.shell_context->wl_shell_data.shell_surface, wl_shell_surface_destroy); +} + +static void +wl_shell_destroy_popup() +{ + g_clear_pointer(&popup_data.shell_context->wl_shell_data.shell_surface, wl_shell_surface_destroy); +} + +static const shell_functions wayland_functions = {.enter_fullscreen = &wl_shell_enter_fullscreen, + .exit_fullscreen = &wl_shell_exit_fullscreen, + .destroy_shell = &wl_shell_destroy_shell, + .maximize_surface = &wl_shell_maximize_surface, + .create_window = &wl_shell_create_window, + .create_popup = &wl_shell_create_popup, + .destroy_window = &wl_shell_destroy_window, + .destroy_popup = &wl_shell_destroy_popup}; + +wl_shell_data wayland_window_data = {.functions = wayland_functions}; +wl_shell_data wayland_popup_data = {.functions = wayland_functions}; + +// f shell operations +static void +f_shell_enter_fullscreen() +{ + win_data.should_resize_to_largest_output = true; + resize_to_largest_output(); +} +static void +f_shell_exit_fullscreen() +{ + configure_surface_geometry(win_data.width_before_fullscreen, win_data.height_before_fullscreen); + resize_window(); +} +static void +f_shell_destroy_shell() +{ + zwp_fullscreen_shell_v1_destroy(wl_data.fshell); +} +static void +f_shell_create_window() +{ + zwp_fullscreen_shell_v1_present_surface(wl_data.fshell, + win_data.wl_surface, + ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT, + NULL); + + /* Configure the surface so that it respects the width and height + * environment variables */ + configure_surface_geometry(0, 0); +} + +f_shell_data f_data = {.functions = {.exit_fullscreen = &f_shell_exit_fullscreen, + .destroy_shell = &f_shell_destroy_shell, + .create_window = &f_shell_create_window, + .enter_fullscreen = &f_shell_enter_fullscreen, + .create_popup = &no_shell_create_popup, + .maximize_surface = &no_shell_maximize, + .destroy_window = &no_shell_destroy_window, + .destroy_popup = &no_shell_destroy_popup}}; static struct { struct xkb_context* context; @@ -312,7 +657,6 @@ static struct { .should_update_opaque_region = true, /* Force initial update. */ }; - struct wl_event_source { GSource source; GPollFD pfd; @@ -460,11 +804,6 @@ shell_surface_configure(void *data, resize_window(); } -static const struct wl_shell_surface_listener shell_surface_listener = { - .ping = shell_surface_ping, - .configure = shell_surface_configure, -}; - static void shell_popup_surface_ping(void *data, struct wl_shell_surface *shell_surface, uint32_t serial) { @@ -486,12 +825,6 @@ shell_popup_surface_popup_done (void *data, { } -static const struct wl_shell_surface_listener shell_popup_surface_listener = { - .ping = shell_popup_surface_ping, - .configure = shell_popup_surface_configure, - .popup_done = shell_popup_surface_popup_done, -}; - static void xdg_shell_ping(void *data, struct xdg_wm_base *shell, uint32_t serial) { @@ -507,14 +840,12 @@ xdg_surface_on_configure(void *data, struct xdg_surface *surface, uint32_t seria { xdg_surface_ack_configure(surface, serial); - if (popup_data.xdg_surface == surface && !popup_data.configured) { + if (popup_data.shell_context->xdg_shell_data.xdg_surface == surface && !popup_data.configured) { popup_data.configured = true; display_popup(); } } -static const struct xdg_surface_listener xdg_surface_listener = {.configure = xdg_surface_on_configure}; - static void xdg_toplevel_on_configure(void *data, struct xdg_toplevel *toplevel, @@ -535,11 +866,6 @@ xdg_toplevel_on_close(void *data, struct xdg_toplevel *xdg_toplevel) g_application_quit(g_application_get_default()); } -static const struct xdg_toplevel_listener xdg_toplevel_listener = { - .configure = xdg_toplevel_on_configure, - .close = xdg_toplevel_on_close, -}; - static void xdg_popup_on_configure(void *data, struct xdg_popup *xdg_popup, int32_t x, int32_t y, int32_t width, int32_t height) { @@ -551,11 +877,6 @@ xdg_popup_on_popup_done(void *data, struct xdg_popup *xdg_popup) destroy_popup(); } -static const struct xdg_popup_listener xdg_popup_listener = { - .configure = xdg_popup_on_configure, - .popup_done = xdg_popup_on_popup_done, -}; - static void resize_to_largest_output() { @@ -637,13 +958,7 @@ cog_wl_does_image_match_win_size(struct wpe_fdo_egl_exported_image *image) static void cog_wl_fullscreen_image_ready() { - if (wl_data.xdg_shell) { - xdg_toplevel_set_fullscreen(win_data.xdg_toplevel, NULL); - } else if (wl_data.shell) { - wl_shell_surface_set_fullscreen(win_data.shell_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE, 0, NULL); - } else if (wl_data.fshell == NULL) { - g_assert_not_reached(); - } + win_data.shell_context->functions.enter_fullscreen(); win_data.is_resizing_fullscreen = false; #if HAVE_FULLSCREEN_HANDLING @@ -670,18 +985,7 @@ cog_wl_set_fullscreen(void *unused, bool fullscreen) if (cog_wl_does_image_match_win_size(wpe_view_data.image)) cog_wl_fullscreen_image_ready(); } else { - if (wl_data.xdg_shell != NULL) { - xdg_toplevel_unset_fullscreen(win_data.xdg_toplevel); - } else if (wl_data.fshell != NULL) { - configure_surface_geometry(win_data.width_before_fullscreen, win_data.height_before_fullscreen); - resize_window(); - } else if (wl_data.shell != NULL) { - wl_shell_surface_set_toplevel(win_data.shell_surface); - configure_surface_geometry(win_data.width_before_fullscreen, win_data.height_before_fullscreen); - resize_window(); - } else { - g_assert_not_reached(); - } + win_data.shell_context->functions.exit_fullscreen(); #if HAVE_FULLSCREEN_HANDLING if (win_data.was_fullscreen_requested_from_dom) wpe_view_backend_dispatch_did_exit_fullscreen(wpe_view_data.backend); @@ -757,14 +1061,20 @@ registry_global (void *data, wl_data.subcompositor = wl_registry_bind(registry, name, &wl_subcompositor_interface, version); } else if (strcmp(interface, wl_shell_interface.name) == 0) { wl_data.shell = wl_registry_bind(registry, name, &wl_shell_interface, version); + win_data.shell_context = (shell_context *) (&wayland_window_data); + popup_data.shell_context = (shell_context *) (&wayland_popup_data); } else if (strcmp(interface, wl_shm_interface.name) == 0) { wl_data.shm = wl_registry_bind(registry, name, &wl_shm_interface, version); } else if (strcmp(interface, xdg_wm_base_interface.name) == 0) { wl_data.xdg_shell = wl_registry_bind(registry, name, &xdg_wm_base_interface, version); g_assert(wl_data.xdg_shell); xdg_wm_base_add_listener(wl_data.xdg_shell, &xdg_shell_listener, NULL); + win_data.shell_context = (shell_context *) (&xdg_data); + popup_data.shell_context = (shell_context *) (&xdg_data); } else if (strcmp(interface, zwp_fullscreen_shell_v1_interface.name) == 0) { wl_data.fshell = wl_registry_bind(registry, name, &zwp_fullscreen_shell_v1_interface, version); + win_data.shell_context = (shell_context *) (&f_data); + popup_data.shell_context = (shell_context *) (&f_data); } else if (strcmp(interface, wl_seat_interface.name) == 0) { wl_data.seat = wl_registry_bind(registry, name, &wl_seat_interface, version); #if COG_ENABLE_WESTON_DIRECT_DISPLAY @@ -1970,14 +2280,11 @@ init_wayland (GError **error) static void clear_wayland (void) { + win_data.shell_context->functions.destroy_shell(); + win_data.shell_context = NULL; + g_clear_pointer(&win_data.shell_context, g_free); g_clear_pointer(&wl_data.event_src, g_source_destroy); - if (wl_data.xdg_shell != NULL) - xdg_wm_base_destroy (wl_data.xdg_shell); - if (wl_data.fshell != NULL) - zwp_fullscreen_shell_v1_destroy (wl_data.fshell); - if (wl_data.shell != NULL) - wl_shell_destroy (wl_data.shell); g_clear_pointer (&wl_data.shm, wl_shm_destroy); g_clear_pointer (&wl_data.subcompositor, wl_subcompositor_destroy); @@ -2136,82 +2443,18 @@ create_window (GError **error) win_data.video_surfaces = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, destroy_video_surface); #endif - wl_surface_add_listener (win_data.wl_surface, &surface_listener, NULL); - - if (wl_data.xdg_shell != NULL) { - win_data.xdg_surface = - xdg_wm_base_get_xdg_surface (wl_data.xdg_shell, - win_data.wl_surface); - g_assert(win_data.xdg_surface); - - xdg_surface_add_listener (win_data.xdg_surface, &xdg_surface_listener, - NULL); - win_data.xdg_toplevel = - xdg_surface_get_toplevel (win_data.xdg_surface); - g_assert(win_data.xdg_toplevel); - - xdg_toplevel_add_listener (win_data.xdg_toplevel, - &xdg_toplevel_listener, NULL); - xdg_toplevel_set_title (win_data.xdg_toplevel, COG_DEFAULT_APPNAME); - - const char *app_id = NULL; - GApplication *app = g_application_get_default (); - if (app) { - app_id = g_application_get_application_id (app); - } - if (!app_id) { - app_id = COG_DEFAULT_APPID; - } - xdg_toplevel_set_app_id (win_data.xdg_toplevel, app_id); - wl_surface_commit(win_data.wl_surface); - } else if (wl_data.fshell != NULL) { - zwp_fullscreen_shell_v1_present_surface (wl_data.fshell, - win_data.wl_surface, - ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT, - NULL); - - /* Configure the surface so that it respects the width and height - * environment variables */ - configure_surface_geometry(0, 0); - } else if (wl_data.shell != NULL) { - win_data.shell_surface = wl_shell_get_shell_surface(wl_data.shell, win_data.wl_surface); - g_assert(win_data.shell_surface); - - wl_shell_surface_add_listener(win_data.shell_surface, &shell_surface_listener, 0); - wl_shell_surface_set_toplevel(win_data.shell_surface); - - /* wl_shell needs an initial surface configuration. */ - configure_surface_geometry(0, 0); - } + wl_surface_add_listener(win_data.wl_surface, &surface_listener, NULL); + win_data.shell_context->functions.create_window(); const char *env_var; if ((env_var = g_getenv("COG_PLATFORM_WL_VIEW_FULLSCREEN")) && g_ascii_strtoll(env_var, NULL, 10) > 0) { win_data.is_maximized = false; win_data.is_fullscreen = true; - - if (wl_data.xdg_shell != NULL) { - xdg_toplevel_set_fullscreen(win_data.xdg_toplevel, NULL); - } else if (wl_data.fshell != NULL) { - win_data.should_resize_to_largest_output = true; - resize_to_largest_output(); - } else if (wl_data.shell != NULL) { - wl_shell_surface_set_fullscreen(win_data.shell_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE, 0, NULL); - } else { - g_warning("No available shell capable of fullscreening."); - win_data.is_fullscreen = false; - } + win_data.shell_context->functions.enter_fullscreen(); } else if ((env_var = g_getenv("COG_PLATFORM_WL_VIEW_MAXIMIZE")) && g_ascii_strtoll(env_var, NULL, 10) > 0) { win_data.is_maximized = true; win_data.is_fullscreen = false; - - if (wl_data.xdg_shell != NULL) { - xdg_toplevel_set_maximized (win_data.xdg_toplevel); - } else if (wl_data.shell != NULL) { - wl_shell_surface_set_maximized (win_data.shell_surface, NULL); - } else { - g_warning ("No available shell capable of maximizing."); - win_data.is_maximized = false; - } + win_data.shell_context->functions.maximize_surface(); } return TRUE; @@ -2220,10 +2463,8 @@ create_window (GError **error) static void destroy_window (void) { - g_clear_pointer (&win_data.xdg_toplevel, xdg_toplevel_destroy); - g_clear_pointer (&win_data.xdg_surface, xdg_surface_destroy); - g_clear_pointer (&win_data.shell_surface, wl_shell_surface_destroy); - g_clear_pointer (&win_data.wl_surface, wl_surface_destroy); + win_data.shell_context->functions.destroy_window(); + g_clear_pointer(&win_data.wl_surface, wl_surface_destroy); #if COG_ENABLE_WESTON_DIRECT_DISPLAY g_clear_pointer (&win_data.video_surfaces, g_hash_table_destroy); @@ -2243,52 +2484,10 @@ create_popup (WebKitOptionMenu *option_menu) popup_data.height, wl_data.current_output.scale); - popup_data.wl_surface = wl_compositor_create_surface (wl_data.compositor); - g_assert (popup_data.wl_surface); - wl_surface_set_buffer_scale (popup_data.wl_surface, wl_data.current_output.scale); - - if (wl_data.xdg_shell != NULL) { - popup_data.xdg_positioner = xdg_wm_base_create_positioner (wl_data.xdg_shell); - g_assert(popup_data.xdg_positioner); - - xdg_positioner_set_size (popup_data.xdg_positioner, - popup_data.width, - popup_data.height); - xdg_positioner_set_anchor_rect(popup_data.xdg_positioner, 0, (win_data.height - popup_data.height), - popup_data.width, popup_data.height); - - popup_data.xdg_surface = xdg_wm_base_get_xdg_surface (wl_data.xdg_shell, - popup_data.wl_surface); - g_assert (popup_data.xdg_surface); - - xdg_surface_add_listener (popup_data.xdg_surface, - &xdg_surface_listener, - NULL); - popup_data.xdg_popup = xdg_surface_get_popup (popup_data.xdg_surface, - win_data.xdg_surface, - popup_data.xdg_positioner); - g_assert (popup_data.xdg_popup); - - xdg_popup_add_listener (popup_data.xdg_popup, - &xdg_popup_listener, - NULL); - xdg_popup_grab (popup_data.xdg_popup, wl_data.seat, wl_data.event_serial); - wl_surface_commit (popup_data.wl_surface); - } else if (wl_data.shell != NULL) { - popup_data.shell_surface = wl_shell_get_shell_surface (wl_data.shell, - popup_data.wl_surface); - g_assert(popup_data.shell_surface); - - wl_shell_surface_add_listener (popup_data.shell_surface, - &shell_popup_surface_listener, - NULL); - wl_shell_surface_set_popup (popup_data.shell_surface, - wl_data.seat, wl_data.event_serial, - win_data.wl_surface, - 0, (win_data.height - popup_data.height), 0); - - display_popup(); - } + popup_data.wl_surface = wl_compositor_create_surface(wl_data.compositor); + g_assert(popup_data.wl_surface); + wl_surface_set_buffer_scale(popup_data.wl_surface, wl_data.current_output.scale); + win_data.shell_context->functions.create_popup(); } static void @@ -2301,11 +2500,8 @@ destroy_popup (void) g_clear_pointer (&popup_data.popup_menu, cog_popup_menu_destroy); g_clear_object (&popup_data.option_menu); - g_clear_pointer (&popup_data.xdg_popup, xdg_popup_destroy); - g_clear_pointer (&popup_data.xdg_surface, xdg_surface_destroy); - g_clear_pointer (&popup_data.xdg_positioner, xdg_positioner_destroy); - g_clear_pointer (&popup_data.shell_surface, wl_shell_surface_destroy); - g_clear_pointer (&popup_data.wl_surface, wl_surface_destroy); + win_data.shell_context->functions.destroy_popup(); + g_clear_pointer(&popup_data.wl_surface, wl_surface_destroy); popup_data.configured = false; } @@ -2451,10 +2647,8 @@ cog_wl_platform_setup(CogPlatform *platform, CogShell *shell G_GNUC_UNUSED, cons } static void -cog_wl_platform_teardown(CogPlatform *platform) +cog_wl_platform_finalize(GObject *object) { - g_assert (platform); - /* free WPE view data */ if (wpe_view_data.frame_callback != NULL) wl_callback_destroy(wpe_view_data.frame_callback); @@ -2480,6 +2674,8 @@ cog_wl_platform_teardown(CogPlatform *platform) destroy_window (); clear_egl(); clear_wayland (); + + G_OBJECT_CLASS(cog_wl_platform_parent_class)->finalize(object); } static WebKitWebViewBackend * @@ -2547,10 +2743,12 @@ cog_wl_platform_create_im_context(CogPlatform *platform) static void cog_wl_platform_class_init(CogWlPlatformClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + object_class->finalize = cog_wl_platform_finalize; + CogPlatformClass *platform_class = COG_PLATFORM_CLASS(klass); platform_class->is_supported = cog_wl_platform_is_supported; platform_class->setup = cog_wl_platform_setup; - platform_class->teardown = cog_wl_platform_teardown; platform_class->get_view_backend = cog_wl_platform_get_view_backend; platform_class->init_web_view = cog_wl_platform_init_web_view; platform_class->create_im_context = cog_wl_platform_create_im_context; diff --git a/platform/x11/cog-platform-x11.c b/platform/x11/cog-platform-x11.c index 3f0fa3a8..50423d93 100644 --- a/platform/x11/cog-platform-x11.c +++ b/platform/x11/cog-platform-x11.c @@ -863,10 +863,8 @@ cog_x11_platform_setup(CogPlatform *platform, CogShell *shell G_GNUC_UNUSED, con } static void -cog_x11_platform_teardown(CogPlatform *platform) +cog_x11_platform_finalize(GObject *object) { - g_assert (platform); - clear_glib (); clear_gl (); clear_egl (); @@ -875,6 +873,8 @@ cog_x11_platform_teardown(CogPlatform *platform) g_clear_pointer (&s_window, free); g_clear_pointer (&s_display, free); + + G_OBJECT_CLASS(cog_x11_platform_parent_class)->finalize(object); } static WebKitWebViewBackend * @@ -931,10 +931,12 @@ cog_x11_platform_is_supported(void) static void cog_x11_platform_class_init(CogX11PlatformClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + object_class->finalize = cog_x11_platform_finalize; + CogPlatformClass *platform_class = COG_PLATFORM_CLASS(klass); platform_class->is_supported = cog_x11_platform_is_supported; platform_class->setup = cog_x11_platform_setup; - platform_class->teardown = cog_x11_platform_teardown; platform_class->get_view_backend = cog_x11_platform_get_view_backend; }