From e56bdcaefd4479e23668a11a45fe48d17d587767 Mon Sep 17 00:00:00 2001 From: Nasah-Kuma Date: Mon, 20 Sep 2021 20:59:24 +0100 Subject: [PATCH 01/17] Enhancement-Factored out switcheroos for the different wayland shell protocols --- platform/wayland/cog-platform-wl.c | 586 +++++++++++++++++++---------- 1 file changed, 390 insertions(+), 196 deletions(-) diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index 72bc561d..3ae9f26a 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,281 @@ 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() +{ + win_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); +} + +wl_shell_data wayland_data = {.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}}; + +// 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 +654,6 @@ static struct { .should_update_opaque_region = true, /* Force initial update. */ }; - struct wl_event_source { GSource source; GPollFD pfd; @@ -460,11 +801,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 +822,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 +837,13 @@ 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) { + if (win_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 +864,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 +875,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 +956,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 +983,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 +1059,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_data); + popup_data.shell_context = (shell_context *) (&wayland_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 +2278,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 +2441,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 +2461,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 +2482,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 +2498,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; } From 52f804fc277a4a902b810156463763adc530c3a0 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Wed, 3 Nov 2021 14:21:49 +0200 Subject: [PATCH 02/17] Release version 0.11.1 --- CMakeLists.txt | 4 ++-- NEWS | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 30491a18..6726954b 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 11 1) # 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 6 0 5) project(cog VERSION "${PROJECT_VERSION}" LANGUAGES C) include(DistTargets) 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 ====================== From 35f7697041beca39cd810f62bf9e3f18ee9123f0 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Wed, 3 Nov 2021 14:58:35 +0200 Subject: [PATCH 03/17] docs: Rename platform fdo to wl after #351 Change text mentioning the "fdo" platform plug-in to "wl", which was missing from #351. --- docs/cog.toml.in | 2 +- docs/platform-fdo.md | 14 -------------- docs/platform-wl.md | 14 ++++++++++++++ docs/webdriver.md | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) delete mode 100644 docs/platform-fdo.md create mode 100644 docs/platform-wl.md 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"], } } From 60dcf6d0fd087d8e3569b565b09afe203f67d4da Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Sat, 6 Nov 2021 00:14:39 +0200 Subject: [PATCH 04/17] drm: Avoid leaking array of devices during check Arrange to call drmFreeDevices() inside check_drm() and init_drm() to avoid leaking the arrays of devices returned by drmGetDevices2(). --- platform/drm/cog-platform-drm.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/platform/drm/cog-platform-drm.c b/platform/drm/cog-platform-drm.c index fca1678b..6b0a9e27 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; From 19be4ecf719ca8ef816517bb91f2ad25f21f1743 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Sat, 6 Nov 2021 14:52:51 +0200 Subject: [PATCH 05/17] docs: Fix building documentation with libsoup3 Pass the correct pkg-config module name to gi-docgen depending on the version of libsoup in use: WPE WebKit builds with libsoup2 have API version 1.0, and builds with libsoup3 have API version 1.1. --- CMakeLists.txt | 2 ++ docs/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6726954b..124a0fbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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/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 From 0f9afa1ac099bc63f28b5219f53a5f227a7621ca Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Mon, 8 Nov 2021 16:28:04 +0200 Subject: [PATCH 06/17] CI: Change file name of cross-ARM toolchain --- .github/toolchain.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/toolchain.sh b/.github/toolchain.sh index b8578456..6630dba7 100755 --- a/.github/toolchain.sh +++ b/.github/toolchain.sh @@ -3,7 +3,7 @@ set -e 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 +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 From 90b5500592f2d2c04b7f8132f90bab0701816a99 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Mon, 8 Nov 2021 16:29:13 +0200 Subject: [PATCH 07/17] CI: Link to page with toolchain info from script --- .github/toolchain.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/toolchain.sh b/.github/toolchain.sh index 6630dba7..572a0892 100755 --- a/.github/toolchain.sh +++ b/.github/toolchain.sh @@ -1,6 +1,7 @@ #! /bin/bash set -e +# 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-cortexa9t2hf-neon-wandboard-mesa-toolchain-1.0.sh From c8756bd074fdc936a722052e4775424aaecb32a0 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Mon, 8 Nov 2021 16:35:19 +0200 Subject: [PATCH 08/17] CI: Do not hardcode the CPU type when sourcing env script This avoids not finding any environment setup script due to the CPU name and features changing when SDKs are updated: use a wildcard to make sure at least one gets picked. --- .github/workflows/ci-cross.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cross.yml b/.github/workflows/ci-cross.yml index b8223eb0..fc16dfd1 100644 --- a/.github/workflows/ci-cross.yml +++ b/.github/workflows/ci-cross.yml @@ -29,7 +29,7 @@ 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 \ -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ -DCOG_PLATFORM_FDO=ON \ From 12d1a491222cecad515f8d34e0107b516acbb074 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Sun, 7 Nov 2021 13:21:42 +0200 Subject: [PATCH 09/17] core: Remove unneeded CogPlatformClass.teardown vfunc Use GObjectClass.finalize instead of CogPlatformClass.teardown. Now that CogPlatform derives from GObject, it is possible to reuse its functionality instead of having an ad-hoc vfunc that gets called immediately before destroying an instance. As a bonus, not only the implementations follow a more idiomatic GObject approach, but also it is not possible anymore to forget a call to cog_platform_teardown() before destruction. --- cog.c | 8 +------- core/cog-platform.c | 10 ---------- core/cog-platform.h | 3 --- platform/drm/cog-platform-drm.c | 11 ++++++----- platform/gtk4/cog-platform-gtk4.c | 7 ------- platform/headless/cog-platform-headless.c | 8 ++++++-- platform/wayland/cog-platform-wl.c | 10 ++++++---- platform/x11/cog-platform-x11.c | 10 ++++++---- 8 files changed, 25 insertions(+), 42 deletions(-) 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/platform/drm/cog-platform-drm.c b/platform/drm/cog-platform-drm.c index 6b0a9e27..8c51fe23 100644 --- a/platform/drm/cog-platform-drm.c +++ b/platform/drm/cog-platform-drm.c @@ -1827,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 * @@ -1880,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..f62faad4 100644 --- a/platform/wayland/cog-platform-wl.c +++ b/platform/wayland/cog-platform-wl.c @@ -2451,10 +2451,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 +2478,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 +2547,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; } From 92bb890f0518b0e6661fbf468d83bfa7d0ab89c9 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Mon, 8 Nov 2021 18:22:11 +0200 Subject: [PATCH 10/17] CI: Switch to clang-format version 13 Update the check-style script and the CI job to use clang-format 13, which is the first version that supports combining The "PointerAlignment: Right" with "AlignConsecutiveDeclarations: true". This was unimplemented until recently, see https://reviews.llvm.org/D103245 While at it, do not let clang-format choose a different way of doing pointer alignment by setting "DerivePointerAlignment: false". --- .clang-format | 2 +- .github/workflows/codestyle.yml | 4 ++-- data/check-style | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) 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/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/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. From 97c8936df7f7da2d279c9420da4ed875d037b037 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Thu, 11 Nov 2021 11:03:44 +0200 Subject: [PATCH 11/17] CI: Make curl downloads more reliable Retry the curl command up to ten times in case of download failures. This should alleviate build issues like the following, where the server sometimes seems to wrongly close HTTP/2 streams, or when some connection issue results in partial downloads: https://github.com/Igalia/cog/runs/4176134469 https://github.com/Igalia/cog/runs/4176255670 While at it, pass "-C -" to let curl determine from which point to retry the download. As the toolchain packages are big, this should help avoid timeouts. Finally, use HTTP/1.1; because using HTTP/2 seems to be a source of sporadic issues, and for a big, bulky download, the gains from HTTP/2 (like multiple streams and faster connection open) are basically none due to the transfer itself taking most of the time. --- .github/toolchain.sh | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/.github/toolchain.sh b/.github/toolchain.sh index 572a0892..3dd50a36 100755 --- a/.github/toolchain.sh +++ b/.github/toolchain.sh @@ -1,5 +1,5 @@ #! /bin/bash -set -e +set -eu -o pipefail # Info on available toolchains: https://wk-contrib.igalia.com/ INSTALL_DIR=${1:-${HOME}/toolchain} @@ -9,12 +9,43 @@ FILE=wandboard-mesa/browsers-glibc-x86_64-core-image-weston-browsers-cortexa9t2h 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...' From 5b343357e48d5663626ff38ca70bef2d33c4cf27 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Thu, 11 Nov 2021 11:20:18 +0200 Subject: [PATCH 12/17] CI: Use system-provided wayland-scanner binary --- .github/workflows/ci-cross.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-cross.yml b/.github/workflows/ci-cross.yml index fc16dfd1..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 @@ -31,6 +31,7 @@ jobs: run: |- . ~/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 From 90145513ae253ba666fdde426ca22306a3c305e2 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Thu, 11 Nov 2021 14:05:48 +0200 Subject: [PATCH 13/17] CI: Use stable ARM cross-toolchain --- .github/toolchain.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/toolchain.sh b/.github/toolchain.sh index 3dd50a36..c1533c1a 100755 --- a/.github/toolchain.sh +++ b/.github/toolchain.sh @@ -3,7 +3,7 @@ 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 +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 From 80b9013cb739a1f99c408532db7e2710ff4ebcd6 Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Fri, 12 Nov 2021 00:45:50 +0200 Subject: [PATCH 14/17] Bump version numbers after release from stable branch --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 124a0fbc..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 11 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 11 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 6 0 5) +calculate_library_versions_from_libtool_triple(COGCORE 8 0 1) project(cog VERSION "${PROJECT_VERSION}" LANGUAGES C) include(DistTargets) From c98f6ab8c3653798b4992e4d8caeb1fcfe40a0ff Mon Sep 17 00:00:00 2001 From: Nasah-Kuma Date: Mon, 20 Sep 2021 20:59:24 +0100 Subject: [PATCH 15/17] Enhancement-Factored out switcheroos for the different wayland shell protocols --- platform/wayland/cog-platform-wl.c | 586 +++++++++++++++++++---------- 1 file changed, 390 insertions(+), 196 deletions(-) diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index f62faad4..06d1e7a4 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,281 @@ 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() +{ + win_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); +} + +wl_shell_data wayland_data = {.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}}; + +// 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 +654,6 @@ static struct { .should_update_opaque_region = true, /* Force initial update. */ }; - struct wl_event_source { GSource source; GPollFD pfd; @@ -460,11 +801,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 +822,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 +837,13 @@ 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) { + if (win_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 +864,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 +875,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 +956,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 +983,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 +1059,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_data); + popup_data.shell_context = (shell_context *) (&wayland_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 +2278,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 +2441,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 +2461,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 +2482,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 +2498,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; } From 10883030cabeabb54a0165cfc85c2000ae9d692b Mon Sep 17 00:00:00 2001 From: Nasah-Kuma Date: Fri, 19 Nov 2021 01:49:12 +0100 Subject: [PATCH 16/17] more updates --- platform/wayland/cog-platform-wl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index 15edadef..d281a70b 100644 --- a/platform/wayland/cog-platform-wl.c +++ b/platform/wayland/cog-platform-wl.c @@ -838,7 +838,7 @@ xdg_surface_on_configure(void *data, struct xdg_surface *surface, uint32_t seria xdg_surface_ack_configure(surface, serial); if (popup_data.shell_context->xdg_shell_data.xdg_surface == surface && !popup_data.configured) { - if (win_data.shell_context->xdg_shell_data.xdg_surface == surface && !popup_data.configured) { + //if (win_data.shell_context->xdg_shell_data.xdg_surface == surface && !popup_data.configured) { popup_data.configured = true; display_popup(); } From c59ed5d6a51ae96cefdf90a17510a16543f41ffe Mon Sep 17 00:00:00 2001 From: Nasah-Kuma Date: Mon, 22 Nov 2021 20:38:00 +0100 Subject: [PATCH 17/17] more updates --- platform/wayland/cog-platform-wl.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index d281a70b..60d1fa81 100644 --- a/platform/wayland/cog-platform-wl.c +++ b/platform/wayland/cog-platform-wl.c @@ -575,14 +575,17 @@ wl_shell_destroy_popup() g_clear_pointer(&popup_data.shell_context->wl_shell_data.shell_surface, wl_shell_surface_destroy); } -wl_shell_data wayland_data = {.functions = {.enter_fullscreen = &wl_shell_enter_fullscreen, +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}}; + .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 @@ -838,7 +841,6 @@ xdg_surface_on_configure(void *data, struct xdg_surface *surface, uint32_t seria xdg_surface_ack_configure(surface, serial); if (popup_data.shell_context->xdg_shell_data.xdg_surface == surface && !popup_data.configured) { - //if (win_data.shell_context->xdg_shell_data.xdg_surface == surface && !popup_data.configured) { popup_data.configured = true; display_popup(); } @@ -1059,8 +1061,8 @@ 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_data); - popup_data.shell_context = (shell_context *) (&wayland_data); + 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) {