From 5ebdb45d72cd73ba1e8aaac702068e9223c9dc2d Mon Sep 17 00:00:00 2001 From: Adrian Perez de Castro Date: Thu, 2 Nov 2023 17:07:24 +0200 Subject: [PATCH] wl: Support multiple web views Replace the single view saved in the CogWlPlatform by the viewport being used by the shell, taking care that only the visible view gets to update the contents of the Wayland surface and that input events get sent to the visible view as well. There are some locations where the visible view is assumed to be also the focused one, which may not be true later on when multiple viewports are supported. This compromise is okay for the time being and may need to be revisited later on. --- platform/wayland/cog-platform-wl.c | 125 +++++++++++++++++---------- platform/wayland/cog-platform-wl.h | 2 +- platform/wayland/cog-view-wl.c | 134 ++++++++++++++--------------- platform/wayland/cog-view-wl.h | 4 +- 4 files changed, 145 insertions(+), 120 deletions(-) diff --git a/platform/wayland/cog-platform-wl.c b/platform/wayland/cog-platform-wl.c index 748d61cb..cd7efa60 100644 --- a/platform/wayland/cog-platform-wl.c +++ b/platform/wayland/cog-platform-wl.c @@ -97,7 +97,7 @@ cog_wl_platform_configure_geometry(CogWlPlatform *platform, int32_t width, int32 platform->window.width = width; platform->window.height = height; - cog_wl_view_resize(platform->view); + cog_viewport_foreach(platform->viewport, (GFunc) cog_wl_view_resize, NULL); } } @@ -106,6 +106,11 @@ static void resize_to_largest_output(CogWlPlatform *); static void cog_wl_platform_enter_fullscreen(CogWlPlatform *platform) { + if (!cog_viewport_get_n_views(platform->viewport)) { + g_debug("%s: No views in viewport, will not fullscreen.", G_STRFUNC); + return; + } + CogWlDisplay *display = platform->display; CogWlWindow *window = &platform->window; @@ -122,13 +127,17 @@ cog_wl_platform_enter_fullscreen(CogWlPlatform *platform) g_assert_not_reached(); } + // XXX: Do we need to set all views as fullscreened? // Wait until a new exported image is reveived. See cog_wl_view_enter_fullscreen(). - cog_wl_view_enter_fullscreen(platform->view); + cog_wl_view_enter_fullscreen(COG_WL_VIEW(cog_viewport_get_visible_view(platform->viewport))); } static void cog_wl_platform_exit_fullscreen(CogWlPlatform *platform) { + // The surface was not fullscreened if there were no views. + g_assert(cog_viewport_get_n_views(platform->viewport) > 0); + CogWlDisplay *display = platform->display; CogWlWindow *window = &platform->window; @@ -146,7 +155,7 @@ cog_wl_platform_exit_fullscreen(CogWlPlatform *platform) #if HAVE_FULLSCREEN_HANDLING if (window->was_fullscreen_requested_from_dom) { - cog_wl_view_exit_fullscreen(platform->view); + cog_wl_view_exit_fullscreen(COG_WL_VIEW(cog_viewport_get_visible_view(platform->viewport))); } window->was_fullscreen_requested_from_dom = false; #endif @@ -294,7 +303,7 @@ output_handle_done(void *data, struct wl_output *output) // Forces a View resize since the output changed so the device // scale factor could be different and the scale of the exported // image should be also updated. - cog_wl_view_resize(platform->view); + cog_viewport_foreach(platform->viewport, (GFunc) cog_wl_view_resize, NULL); } if (platform->window.should_resize_to_largest_output) { @@ -349,26 +358,32 @@ surface_on_enter(void *data, struct wl_surface *surface, struct wl_output *outpu CogWlPlatform *platform = data; CogWlDisplay *display = platform->display; - struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(platform->view)); - if (display->current_output->output != output) { g_debug("%s: Surface %p output changed %p -> %p", G_STRFUNC, surface, display->current_output->output, output); display->current_output = find_output(platform->display, output); g_assert(display->current_output); } + uint32_t output_scale = 0; #ifdef WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION if (wl_surface_get_version(surface) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION) { wl_surface_set_buffer_scale(surface, display->current_output->scale); - wpe_view_backend_dispatch_set_device_scale_factor(backend, display->current_output->scale); + output_scale = display->current_output->scale; } else { g_debug("%s: Surface %p uses old protocol version, cannot set scale factor", G_STRFUNC, surface); } #endif /* WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION */ + for (unsigned i = 0; i < cog_viewport_get_n_views(platform->viewport); i++) { + struct wpe_view_backend *backend = cog_view_get_backend(cog_viewport_get_nth_view(platform->viewport, i)); + #if HAVE_REFRESH_RATE_HANDLING - wpe_view_backend_set_target_refresh_rate(backend, display->current_output->refresh); + wpe_view_backend_set_target_refresh_rate(backend, display->current_output->refresh); #endif /* HAVE_REFRESH_RATE_HANDLING */ + + if (output_scale) + wpe_view_backend_dispatch_set_device_scale_factor(backend, display->current_output->scale); + } } static const struct wl_surface_listener surface_listener = { @@ -515,9 +530,9 @@ pointer_on_motion(void *data, struct wl_pointer *pointer, uint32_t time, wl_fixe seat->pointer.button, seat->pointer.state}; - CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); - struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(platform->view)); - wpe_view_backend_dispatch_pointer_event(backend, &event); + CogView *view = cog_viewport_get_visible_view(((CogWlPlatform *) cog_platform_get_default())->viewport); + if (view) + wpe_view_backend_dispatch_pointer_event(cog_view_get_backend(view), &event); } static void @@ -573,8 +588,9 @@ pointer_on_button(void *data, } } - struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(platform->view)); - wpe_view_backend_dispatch_pointer_event(backend, &event); + CogView *view = cog_viewport_get_visible_view(((CogWlPlatform *) cog_platform_get_default())->viewport); + if (view) + wpe_view_backend_dispatch_pointer_event(cog_view_get_backend(view), &event); } static void @@ -596,9 +612,9 @@ dispatch_axis_event(CogWlSeat *seat) event.x_axis = wl_fixed_to_double(seat->axis.x_delta) * display->current_output->scale; event.y_axis = -wl_fixed_to_double(seat->axis.y_delta) * display->current_output->scale; - CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); - struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(platform->view)); - wpe_view_backend_dispatch_axis_event(backend, &event.base); + CogView *view = cog_viewport_get_visible_view(((CogWlPlatform *) cog_platform_get_default())->viewport); + if (view) + wpe_view_backend_dispatch_axis_event(cog_view_get_backend(view), &event.base); seat->axis.has_delta = false; seat->axis.time = 0; @@ -745,19 +761,20 @@ static void handle_key_event(CogWlSeat *seat, uint32_t key, uint32_t state, uint32_t time) { CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); + CogView *view = cog_viewport_get_visible_view(platform->viewport); - if (seat->xkb.state == NULL) + if (!view || seat->xkb.state == NULL) return; uint32_t keysym = xkb_state_key_get_one_sym(seat->xkb.state, key); uint32_t unicode = xkb_state_key_get_utf32(seat->xkb.state, key); /* TODO: Move as much as possible from fullscreen handling to common code. */ - if (cog_view_get_use_key_bindings(COG_VIEW(platform->view)) && state == WL_KEYBOARD_KEY_STATE_PRESSED && - seat->xkb.modifiers == 0 && unicode == 0 && keysym == XKB_KEY_F11) { + if (cog_view_get_use_key_bindings(view) && state == WL_KEYBOARD_KEY_STATE_PRESSED && seat->xkb.modifiers == 0 && + unicode == 0 && keysym == XKB_KEY_F11) { #if HAVE_FULLSCREEN_HANDLING if (platform->window.is_fullscreen && platform->window.was_fullscreen_requested_from_dom) { - struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(platform->view)); + struct wpe_view_backend *backend = cog_view_get_backend(view); wpe_view_backend_dispatch_request_exit_fullscreen(backend); return; } @@ -774,7 +791,7 @@ handle_key_event(CogWlSeat *seat, uint32_t key, uint32_t state, uint32_t time) struct wpe_input_keyboard_event event = {time, keysym, key, state == true, seat->xkb.modifiers}; - cog_view_handle_key_event(COG_VIEW(platform->view), &event); + cog_view_handle_key_event(view, &event); } static gboolean @@ -956,8 +973,9 @@ touch_on_down(void *data, struct wpe_input_touch_event event = {seat->touch.points, 10, raw_event.type, raw_event.id, raw_event.time}; - struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(platform->view)); - wpe_view_backend_dispatch_touch_event(backend, &event); + CogView *view = cog_viewport_get_visible_view(platform->viewport); + if (view) + wpe_view_backend_dispatch_touch_event(cog_view_get_backend(view), &event); } static void @@ -999,8 +1017,9 @@ touch_on_up(void *data, struct wl_touch *touch, uint32_t serial, uint32_t time, struct wpe_input_touch_event event = {seat->touch.points, 10, raw_event.type, raw_event.id, raw_event.time}; - struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(platform->view)); - wpe_view_backend_dispatch_touch_event(backend, &event); + CogView *view = cog_viewport_get_visible_view(platform->viewport); + if (view) + wpe_view_backend_dispatch_touch_event(cog_view_get_backend(view), &event); memset(&seat->touch.points[id], 0x00, sizeof(struct wpe_input_touch_event_raw)); } @@ -1031,9 +1050,9 @@ touch_on_motion(void *data, struct wl_touch *touch, uint32_t time, int32_t id, w struct wpe_input_touch_event event = {seat->touch.points, 10, raw_event.type, raw_event.id, raw_event.time}; - CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); - struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(platform->view)); - wpe_view_backend_dispatch_touch_event(backend, &event); + CogView *view = cog_viewport_get_visible_view(((CogWlPlatform *) cog_platform_get_default())->viewport); + if (view) + wpe_view_backend_dispatch_touch_event(cog_view_get_backend(view), &event); } static void @@ -1560,16 +1579,44 @@ static struct wpe_view_backend * gamepad_provider_get_view_backend_for_gamepad(void *provider G_GNUC_UNUSED, void *gamepad G_GNUC_UNUSED) { CogWlPlatform *platform = COG_WL_PLATFORM(cog_platform_get_default()); - CogWlView *view = platform->view; + + CogWlView *view = (CogWlView *) cog_viewport_get_visible_view(platform->viewport); g_assert(view); return wpe_view_backend_exportable_fdo_get_view_backend(view->exportable); } +static void +cog_wl_platform_on_notify_visible_view(CogWlPlatform *self) +{ + CogWlView *view = (CogWlView *) cog_viewport_get_visible_view(self->viewport); + g_debug("%s: Visible view %p.", G_STRFUNC, view); + + if (!view) + return; + + /* + * TODO: Once we support multiple viewports, a view may be visible + * without having focus. At that point the input events will + * need to go to the *focused* view instead. + * + * For now add the flag and assume that visible == focused. + */ + wpe_view_backend_add_activity_state(cog_view_get_backend((CogView *) view), wpe_view_activity_state_focused); + + if (!view->image) + return g_debug("%s: No image to show, skipping update.", G_STRFUNC); + + cog_wl_view_update_surface_contents(view); +} + static gboolean cog_wl_platform_setup(CogPlatform *platform, CogShell *shell G_GNUC_UNUSED, const char *params, GError **error) { g_return_val_if_fail(COG_IS_SHELL(shell), FALSE); + CogWlPlatform *self = COG_WL_PLATFORM(platform); + self->viewport = cog_shell_get_viewport(shell); + if (!wpe_loader_init("libWPEBackend-fdo-1.0.so")) { g_set_error_literal(error, COG_PLATFORM_WPE_ERROR, @@ -1602,6 +1649,9 @@ cog_wl_platform_setup(CogPlatform *platform, CogShell *shell G_GNUC_UNUSED, cons cog_gamepad_setup(gamepad_provider_get_view_backend_for_gamepad); + g_signal_connect_object(self->viewport, "notify::visible-view", G_CALLBACK(cog_wl_platform_on_notify_visible_view), + self, G_CONNECT_AFTER | G_CONNECT_SWAPPED); + return TRUE; } @@ -1610,23 +1660,6 @@ cog_wl_platform_finalize(GObject *object) { CogWlPlatform *platform = COG_WL_PLATFORM(object); - /* free WPE view data */ - if (platform->view->frame_callback != NULL) - wl_callback_destroy(platform->view->frame_callback); - if (platform->view->image != NULL) { - wpe_view_backend_exportable_fdo_egl_dispatch_release_exported_image(platform->view->exportable, - platform->view->image); - } - - /* @FIXME: check why this segfaults - wpe_view_backend_destroy (wpe_view_data.backend); - */ - - /* free WPE host data */ - /* @FIXME: check why this segfaults - wpe_view_backend_exportable_wl_destroy (wpe_host_data.exportable); - */ - cog_wl_text_input_clear(platform); if (platform->popup) cog_wl_platform_popup_destroy(platform); diff --git a/platform/wayland/cog-platform-wl.h b/platform/wayland/cog-platform-wl.h index b22a914f..60dabb81 100644 --- a/platform/wayland/cog-platform-wl.h +++ b/platform/wayland/cog-platform-wl.h @@ -27,7 +27,7 @@ struct _CogWlPlatform { CogPlatform parent; CogWlDisplay *display; CogWlPopup *popup; - CogWlView *view; + CogViewport *viewport; // TODO: Support multiple viewports. CogWlWindow window; }; diff --git a/platform/wayland/cog-view-wl.c b/platform/wayland/cog-view-wl.c index 9613d6f4..2251829d 100644 --- a/platform/wayland/cog-view-wl.c +++ b/platform/wayland/cog-view-wl.c @@ -108,10 +108,6 @@ cog_wl_view_init(CogWlView *self) self->should_update_opaque_region = true; self->image = NULL; self->frame_callback = NULL; - self->platform = COG_WL_PLATFORM(cog_platform_get_default()); - - // Only one view is managed by the Wayland Platform nowadays. - self->platform->view = self; wl_list_init(&self->shm_buffer_list); @@ -139,6 +135,8 @@ cog_wl_view_dispose(GObject *object) g_clear_pointer(&self->frame_callback, wl_callback_destroy); if (self->image) { + g_assert(self->exportable); + wpe_view_backend_exportable_fdo_egl_dispatch_release_exported_image(self->exportable, self->image); self->image = NULL; } @@ -178,6 +176,7 @@ cog_wl_view_clear_buffers(CogWlView *view) static WebKitWebViewBackend * cog_wl_view_create_backend(CogView *view) { + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); CogWlView *self = COG_WL_VIEW(view); static const struct wpe_view_backend_exportable_fdo_egl_client client = { @@ -187,17 +186,15 @@ cog_wl_view_create_backend(CogView *view) #endif }; - self->exportable = wpe_view_backend_exportable_fdo_egl_create(&client, self, self->platform->window.width, - self->platform->window.height); + self->exportable = + wpe_view_backend_exportable_fdo_egl_create(&client, self, platform->window.width, platform->window.height); /* init WPE view backend */ struct wpe_view_backend *view_backend = wpe_view_backend_exportable_fdo_get_view_backend(self->exportable); g_assert(view_backend); - CogWlDisplay *display = self->platform->display; - if (display->text_input_manager_v1 != NULL) { + if (platform->display->text_input_manager_v1) cog_im_context_wl_v1_set_view_backend(view_backend); - } WebKitWebViewBackend *wk_view_backend = webkit_web_view_backend_new(view_backend, @@ -215,9 +212,9 @@ cog_wl_view_create_backend(CogView *view) bool cog_wl_view_does_image_match_win_size(CogWlView *view) { - struct wpe_fdo_egl_exported_image *image = view->image; - return image && wpe_fdo_egl_exported_image_get_width(image) == view->platform->window.width && - wpe_fdo_egl_exported_image_get_height(image) == view->platform->window.height; + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); + return view->image && wpe_fdo_egl_exported_image_get_width(view->image) == platform->window.width && + wpe_fdo_egl_exported_image_get_height(view->image) == platform->window.height; } void @@ -228,8 +225,8 @@ cog_wl_view_enter_fullscreen(CogWlView *view) return; #if HAVE_FULLSCREEN_HANDLING - g_assert(view->platform); - if (view->platform->window.was_fullscreen_requested_from_dom) + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); + if (platform->window.was_fullscreen_requested_from_dom) wpe_view_backend_dispatch_did_enter_fullscreen(cog_view_get_backend(COG_VIEW(view))); #endif @@ -249,15 +246,14 @@ cog_wl_view_exit_fullscreen(CogWlView *view) static bool cog_wl_view_handle_dom_fullscreen_request(void *data, bool fullscreen) { - CogWlView *view = data; - CogWlWindow window = view->platform->window; + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); - window.was_fullscreen_requested_from_dom = true; - if (fullscreen != window.is_fullscreen) - return cog_wl_platform_set_fullscreen(view->platform, fullscreen); + platform->window.was_fullscreen_requested_from_dom = true; + if (fullscreen != platform->window.is_fullscreen) + return cog_wl_platform_set_fullscreen(platform, fullscreen); // Handle situations where DOM fullscreen requests are mixed with system fullscreen commands (e.g F11) - struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(view)); + struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(data)); if (fullscreen) wpe_view_backend_dispatch_did_enter_fullscreen(backend); else @@ -276,24 +272,21 @@ cog_wl_view_on_buffer_release(void *data G_GNUC_UNUSED, struct wl_buffer *buffer static void cog_wl_view_request_frame(CogWlView *view) { - CogWlDisplay *display = view->platform->display; - g_assert(display); - - CogWlWindow window = view->platform->window; + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); if (!view->frame_callback) { static const struct wl_callback_listener listener = {.done = on_wl_surface_frame}; - view->frame_callback = wl_surface_frame(window.wl_surface); + view->frame_callback = wl_surface_frame(platform->window.wl_surface); wl_callback_add_listener(view->frame_callback, &listener, view); } - if (display->presentation != NULL) { + if (platform->display->presentation != NULL) { static const struct wp_presentation_feedback_listener presentation_feedback_listener = { .sync_output = presentation_feedback_on_sync_output, .presented = presentation_feedback_on_presented, .discarded = presentation_feedback_on_discarded}; struct wp_presentation_feedback *presentation_feedback = - wp_presentation_feedback(display->presentation, window.wl_surface); + wp_presentation_feedback(platform->display->presentation, platform->window.wl_surface); wp_presentation_feedback_add_listener(presentation_feedback, &presentation_feedback_listener, NULL); } } @@ -301,36 +294,32 @@ cog_wl_view_request_frame(CogWlView *view) void cog_wl_view_resize(CogWlView *view) { - g_assert(view->platform); - CogWlPlatform *platform = view->platform; - CogWlDisplay *display = platform->display; - CogWlWindow *window = &platform->window; + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); view->should_update_opaque_region = true; - int32_t pixel_width = window->width * display->current_output->scale; - int32_t pixel_height = window->height * display->current_output->scale; + int32_t pixel_width = platform->window.width * platform->display->current_output->scale; + int32_t pixel_height = platform->window.height * platform->display->current_output->scale; struct wpe_view_backend *backend = cog_view_get_backend(COG_VIEW(view)); - wpe_view_backend_dispatch_set_size(backend, window->width, window->height); - wpe_view_backend_dispatch_set_device_scale_factor(backend, display->current_output->scale); + wpe_view_backend_dispatch_set_size(backend, platform->window.width, platform->window.height); + wpe_view_backend_dispatch_set_device_scale_factor(backend, platform->display->current_output->scale); g_debug("Resized EGL buffer to: (%" PRIi32 ", %" PRIi32 ") @%" PRIi32 "x", pixel_width, pixel_height, - display->current_output->scale); + platform->display->current_output->scale); } void cog_wl_view_update_surface_contents(CogWlView *view) { + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); g_assert(view); - CogWlWindow *window = &view->platform->window; - CogWlDisplay *display = view->platform->display; - g_assert(display); - struct wl_surface *surface = window->wl_surface; + + struct wl_surface *surface = platform->window.wl_surface; g_assert(surface); - const uint32_t surface_pixel_width = display->current_output->scale * window->width; - const uint32_t surface_pixel_height = display->current_output->scale * window->height; + const uint32_t surface_pixel_width = platform->display->current_output->scale * platform->window.width; + const uint32_t surface_pixel_height = platform->display->current_output->scale * platform->window.height; if (view->should_update_opaque_region) { view->should_update_opaque_region = false; @@ -338,9 +327,9 @@ cog_wl_view_update_surface_contents(CogWlView *view) WebKitColor bg_color; webkit_web_view_get_background_color(WEBKIT_WEB_VIEW(view), &bg_color); - if (window->is_fullscreen || !cog_wl_view_background_has_alpha(COG_WL_VIEW(view))) { - struct wl_region *region = wl_compositor_create_region(display->compositor); - wl_region_add(region, 0, 0, window->width, window->height); + if (platform->window.is_fullscreen || !cog_wl_view_background_has_alpha(COG_WL_VIEW(view))) { + struct wl_region *region = wl_compositor_create_region(platform->display->compositor); + wl_region_add(region, 0, 0, platform->window.width, platform->window.height); wl_surface_set_opaque_region(surface, region); wl_region_destroy(region); } else { @@ -356,7 +345,7 @@ cog_wl_view_update_surface_contents(CogWlView *view) } struct wl_buffer *buffer = s_eglCreateWaylandBufferFromImageWL( - display->egl_display, wpe_fdo_egl_exported_image_get_egl_image(view->image)); + platform->display->egl_display, wpe_fdo_egl_exported_image_get_egl_image(view->image)); g_assert(buffer); static const struct wl_buffer_listener buffer_listener = {.release = cog_wl_view_on_buffer_release}; @@ -374,13 +363,12 @@ cog_wl_view_update_surface_contents(CogWlView *view) } static bool -validate_exported_geometry(CogWlView *view, uint32_t width, uint32_t height) +validate_exported_geometry(uint32_t width, uint32_t height) { - CogWlDisplay *display = view->platform->display; - CogWlWindow window = view->platform->window; + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); - const uint32_t surface_pixel_width = display->current_output->scale * window.width; - const uint32_t surface_pixel_height = display->current_output->scale * window.height; + const uint32_t surface_pixel_width = platform->display->current_output->scale * platform->window.width; + const uint32_t surface_pixel_height = platform->display->current_output->scale * platform->window.height; if (surface_pixel_width != width || surface_pixel_height != height) { g_debug("Image geometry %" PRIu32 "x%" PRIu32 ", does not match surface geometry %" PRIu32 "x%" PRIu32 @@ -396,15 +384,15 @@ validate_exported_geometry(CogWlView *view, uint32_t width, uint32_t height) static void on_export_shm_buffer(void *data, struct wpe_fdo_shm_exported_buffer *exported_buffer) { - CogWlView *view = data; - CogWlWindow window = view->platform->window; + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); + CogWlView *view = data; struct wl_resource *exported_resource = wpe_fdo_shm_exported_buffer_get_resource(exported_buffer); struct wl_shm_buffer *exported_shm_buffer = wpe_fdo_shm_exported_buffer_get_shm_buffer(exported_buffer); uint32_t image_width = wl_shm_buffer_get_width(exported_shm_buffer); uint32_t image_height = wl_shm_buffer_get_height(exported_shm_buffer); - if (!validate_exported_geometry(view, image_width, image_height)) { + if (!validate_exported_geometry(image_width, image_height)) { wpe_view_backend_exportable_fdo_dispatch_frame_complete(view->exportable); wpe_view_backend_exportable_fdo_egl_dispatch_release_shm_exported_buffer(view->exportable, exported_buffer); return; @@ -414,9 +402,9 @@ on_export_shm_buffer(void *data, struct wpe_fdo_shm_exported_buffer *exported_bu if (!buffer) { int32_t width; int32_t height; - if (window.is_fullscreen) { - width = window.width; - height = window.height; + if (platform->window.is_fullscreen) { + width = platform->window.width; + height = platform->window.height; } else { width = wl_shm_buffer_get_width(exported_shm_buffer); height = wl_shm_buffer_get_height(exported_shm_buffer); @@ -441,10 +429,13 @@ on_export_shm_buffer(void *data, struct wpe_fdo_shm_exported_buffer *exported_bu buffer->exported_buffer = exported_buffer; shm_buffer_copy_contents(buffer, exported_shm_buffer); - wl_surface_attach(window.wl_surface, buffer->buffer, 0, 0); - wl_surface_damage(window.wl_surface, 0, 0, INT32_MAX, INT32_MAX); - cog_wl_view_request_frame(view); - wl_surface_commit(window.wl_surface); + const int32_t state = wpe_view_backend_get_activity_state(cog_view_get_backend((CogView *) view)); + if (state & wpe_view_activity_state_visible) { + wl_surface_attach(platform->window.wl_surface, buffer->buffer, 0, 0); + wl_surface_damage(platform->window.wl_surface, 0, 0, INT32_MAX, INT32_MAX); + cog_wl_view_request_frame(view); + wl_surface_commit(platform->window.wl_surface); + } } #endif @@ -455,7 +446,7 @@ on_export_wl_egl_image(void *data, struct wpe_fdo_egl_exported_image *image) uint32_t image_width = wpe_fdo_egl_exported_image_get_width(image); uint32_t image_height = wpe_fdo_egl_exported_image_get_height(image); - if (!validate_exported_geometry(self, image_width, image_height)) { + if (!validate_exported_geometry(image_width, image_height)) { wpe_view_backend_exportable_fdo_dispatch_frame_complete(self->exportable); wpe_view_backend_exportable_fdo_egl_dispatch_release_exported_image(self->exportable, image); return; @@ -466,14 +457,16 @@ on_export_wl_egl_image(void *data, struct wpe_fdo_egl_exported_image *image) self->image = image; - cog_wl_view_update_surface_contents(self); + const int32_t state = wpe_view_backend_get_activity_state(cog_view_get_backend((CogView *) self)); + if (state & wpe_view_activity_state_visible) + cog_wl_view_update_surface_contents(self); } static void on_mouse_target_changed(WebKitWebView *view, WebKitHitTestResult *hitTestResult, guint mouseModifiers) { #ifdef COG_USE_WAYLAND_CURSOR - CogWlPlatform *platform = COG_WL_VIEW(view)->platform; + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); if (webkit_hit_test_result_context_is_link(hitTestResult)) { cog_wl_seat_set_cursor(platform->display->seat_default, CURSOR_HAND); } else if (webkit_hit_test_result_context_is_editable(hitTestResult)) { @@ -490,12 +483,11 @@ on_mouse_target_changed(WebKitWebView *view, WebKitHitTestResult *hitTestResult, static void on_run_file_chooser(WebKitWebView *view, WebKitFileChooserRequest *request) { - g_autoptr(XdpParent) xdp_parent = NULL; - - CogWlPlatform *platform = COG_WL_VIEW(view)->platform; + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); + g_autoptr(XdpParent) xdp_parent = NULL; if (platform->window.xdp_parent_wl_data.zxdg_exporter && platform->window.xdp_parent_wl_data.wl_surface) { - xdp_parent = xdp_parent_new_wl(&COG_WL_VIEW(view)->platform->window.xdp_parent_wl_data); + xdp_parent = xdp_parent_new_wl(&platform->window.xdp_parent_wl_data); } run_file_chooser(view, request, xdp_parent); @@ -505,7 +497,8 @@ on_run_file_chooser(WebKitWebView *view, WebKitFileChooserRequest *request) static void on_show_option_menu(WebKitWebView *view, WebKitOptionMenu *menu, WebKitRectangle *rectangle, gpointer *data) { - cog_wl_platform_popup_create(COG_WL_VIEW(view)->platform, g_object_ref(menu)); + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); + cog_wl_platform_popup_create(platform, g_object_ref(menu)); } static void @@ -584,7 +577,8 @@ shm_buffer_create(CogWlView *view, struct wl_resource *buffer_resource, size_t s buffer->buffer_resource = buffer_resource; wl_resource_add_destroy_listener(buffer_resource, &buffer->destroy_listener); - buffer->shm_pool = wl_shm_create_pool(view->platform->display->shm, fd, size); + CogWlPlatform *platform = (CogWlPlatform *) cog_platform_get_default(); + buffer->shm_pool = wl_shm_create_pool(platform->display->shm, fd, size); buffer->data = data; buffer->size = size; diff --git a/platform/wayland/cog-view-wl.h b/platform/wayland/cog-view-wl.h index 0d329598..619be80e 100644 --- a/platform/wayland/cog-view-wl.h +++ b/platform/wayland/cog-view-wl.h @@ -23,8 +23,6 @@ typedef struct _CogWlPlatform CogWlPlatform; struct _CogWlView { CogView parent; - CogWlPlatform *platform; - struct wpe_view_backend_exportable_fdo *exportable; struct wpe_fdo_egl_exported_image *image; @@ -44,9 +42,9 @@ G_DECLARE_FINAL_TYPE(CogWlView, cog_wl_view, COG, WL_VIEW, CogView) * Method declarations. */ +void cog_wl_view_update_surface_contents(CogWlView *); void cog_wl_view_enter_fullscreen(CogWlView *); void cog_wl_view_exit_fullscreen(CogWlView *); - void cog_wl_view_resize(CogWlView *); void cog_wl_view_register_type_exported(GTypeModule *type_module);