From 6379e54847a149abce35ac895785a107ea4ecee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Thu, 29 Jul 2021 18:14:20 +0200 Subject: [PATCH] wayland/surface: Prepare for decoupled surface & resource lifetimes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to deal with surface->resource == NULL and surface->pending_state == NULL in some places. v2: * Avoid expanding conditions to multiple lines. (Georges Basile Stavracas Neto) v3: * Use a single bailout condition in meta_wayland_client_owns_window as well. v4: * Remove spare empty line in meta_wayland_surface_apply_state. (Robert Mader) * Add wl_resource_post_error calls in xdg-shell request handlers. (Robert Mader) * Drop checks in functions which can only be called if there's a valid resource. * Drop more checks which are unnecessary due to leaving the SURFACE_DESTROY signal emission in wl_surface_destructor later. v5: * Move resource = surface->resource assignments to if (!resource) tests. (Jonas Ã…dahl) v6: * Fix style issue per check-style.py. Part-of: --- src/wayland/meta-wayland-client.c | 2 +- src/wayland/meta-wayland-surface.c | 33 +++++++++++++-------- src/wayland/meta-wayland-tablet-pad.c | 2 +- src/wayland/meta-wayland-text-input.c | 2 +- src/wayland/meta-wayland-touch.c | 2 +- src/wayland/meta-wayland-viewporter.c | 27 +++++++++++++++--- src/wayland/meta-wayland-xdg-shell.c | 41 +++++++++++++++++++++++++-- src/wayland/meta-window-wayland.c | 12 ++++++-- src/wayland/meta-xwayland.c | 3 +- 9 files changed, 98 insertions(+), 26 deletions(-) diff --git a/src/wayland/meta-wayland-client.c b/src/wayland/meta-wayland-client.c index 2081d14a9..2d623caca 100644 --- a/src/wayland/meta-wayland-client.c +++ b/src/wayland/meta-wayland-client.c @@ -298,7 +298,7 @@ meta_wayland_client_owns_window (MetaWaylandClient *client, g_return_val_if_fail (client->process_running, FALSE); surface = meta_window_get_wayland_surface (window); - if (surface == NULL) + if (surface == NULL || surface->resource == NULL) return FALSE; return wl_resource_get_client (surface->resource) == client->wayland_client; diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 803a3e179..3696a2786 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -769,10 +769,13 @@ meta_wayland_surface_apply_state (MetaWaylandSurface *surface, &error)) { g_warning ("Could not import pending buffer: %s", error->message); - wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_NO_MEMORY, - "Failed to attach buffer to surface %i: %s", - wl_resource_get_id (surface->resource), - error->message); + if (surface->resource) + { + wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_NO_MEMORY, + "Failed to attach buffer to surface %i: %s", + wl_resource_get_id (surface->resource), + error->message); + } g_error_free (error); goto cleanup; } @@ -1330,21 +1333,24 @@ static void surface_entered_output (MetaWaylandSurface *surface, MetaWaylandOutput *wayland_output) { - const GList *l; - g_signal_connect (wayland_output, "output-destroyed", G_CALLBACK (handle_output_destroyed), surface); - for (l = meta_wayland_output_get_resources (wayland_output); l; l = l->next) + if (surface->resource) { - struct wl_resource *resource = l->data; + const GList *l; - if (wl_resource_get_client (resource) != - wl_resource_get_client (surface->resource)) - continue; + for (l = meta_wayland_output_get_resources (wayland_output); l; l = l->next) + { + struct wl_resource *resource = l->data; - wl_surface_send_enter (surface->resource, resource); + if (wl_resource_get_client (resource) != + wl_resource_get_client (surface->resource)) + continue; + + wl_surface_send_enter (surface->resource, resource); + } } g_signal_connect (wayland_output, "output-bound", @@ -1366,6 +1372,9 @@ surface_left_output (MetaWaylandSurface *surface, G_CALLBACK (handle_output_bound), surface); + if (!surface->resource) + return; + for (l = meta_wayland_output_get_resources (wayland_output); l; l = l->next) { struct wl_resource *resource = l->data; diff --git a/src/wayland/meta-wayland-tablet-pad.c b/src/wayland/meta-wayland-tablet-pad.c index fc108b795..92c36fa80 100644 --- a/src/wayland/meta-wayland-tablet-pad.c +++ b/src/wayland/meta-wayland-tablet-pad.c @@ -466,7 +466,7 @@ meta_wayland_tablet_pad_set_focus (MetaWaylandTabletPad *pad, tablet = meta_wayland_tablet_seat_lookup_paired_tablet (pad->tablet_seat, pad); - if (tablet != NULL && surface != NULL) + if (tablet != NULL && surface != NULL && surface->resource != NULL) { struct wl_client *client; diff --git a/src/wayland/meta-wayland-text-input.c b/src/wayland/meta-wayland-text-input.c index 1cfeb3577..c12fe2024 100644 --- a/src/wayland/meta-wayland-text-input.c +++ b/src/wayland/meta-wayland-text-input.c @@ -371,7 +371,7 @@ meta_wayland_text_input_set_focus (MetaWaylandTextInput *text_input, text_input->surface = NULL; } - if (surface) + if (surface && surface->resource) { struct wl_resource *focus_surface_resource; diff --git a/src/wayland/meta-wayland-touch.c b/src/wayland/meta-wayland-touch.c index 5824e229d..6d45b4b7b 100644 --- a/src/wayland/meta-wayland-touch.c +++ b/src/wayland/meta-wayland-touch.c @@ -227,7 +227,7 @@ meta_wayland_touch_update (MetaWaylandTouch *touch, if (META_IS_SURFACE_ACTOR_WAYLAND (actor)) surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor)); - if (!surface) + if (!surface || !surface->resource) return; touch_info = touch_get_info (touch, sequence, TRUE); diff --git a/src/wayland/meta-wayland-viewporter.c b/src/wayland/meta-wayland-viewporter.c index 619f3177c..85b1c77ed 100644 --- a/src/wayland/meta-wayland-viewporter.c +++ b/src/wayland/meta-wayland-viewporter.c @@ -46,10 +46,13 @@ wp_viewport_destructor (struct wl_resource *resource) g_clear_signal_handler (&surface->viewport.destroy_handler_id, surface); pending = meta_wayland_surface_get_pending_state (surface); - pending->viewport_src_rect.size.width = -1; - pending->viewport_dst_width = -1; - pending->has_new_viewport_src_rect = TRUE; - pending->has_new_viewport_dst_size = TRUE; + if (pending) + { + pending->viewport_src_rect.size.width = -1; + pending->viewport_dst_width = -1; + pending->has_new_viewport_src_rect = TRUE; + pending->has_new_viewport_dst_size = TRUE; + } surface->viewport.resource = NULL; } @@ -103,6 +106,14 @@ wp_viewport_set_source (struct wl_client *client, MetaWaylandSurfaceState *pending; pending = meta_wayland_surface_get_pending_state (surface); + if (!pending) + { + wl_resource_post_error (resource, + WP_VIEWPORT_ERROR_NO_SURFACE, + "wl_surface for this viewport no longer exists"); + return; + } + pending->viewport_src_rect.origin.x = new_x; pending->viewport_src_rect.origin.y = new_y; pending->viewport_src_rect.size.width = new_width; @@ -142,6 +153,14 @@ wp_viewport_set_destination (struct wl_client *client, MetaWaylandSurfaceState *pending; pending = meta_wayland_surface_get_pending_state (surface); + if (!pending) + { + wl_resource_post_error (resource, + WP_VIEWPORT_ERROR_NO_SURFACE, + "wl_surface for this viewport no longer exists"); + return; + } + pending->viewport_dst_width = dst_width; pending->viewport_dst_height = dst_height; pending->has_new_viewport_dst_size = TRUE; diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c index 485aa01f5..bb68e5ecb 100644 --- a/src/wayland/meta-wayland-xdg-shell.c +++ b/src/wayland/meta-wayland-xdg-shell.c @@ -391,6 +391,14 @@ xdg_toplevel_set_max_size (struct wl_client *client, pending = meta_wayland_surface_get_pending_state (surface); + if (!pending) + { + wl_resource_post_error (resource, + XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, + "underlying wl_surface already destroyed"); + return; + } + pending->has_new_max_size = TRUE; pending->new_max_width = width; pending->new_max_height = height; @@ -416,6 +424,14 @@ xdg_toplevel_set_min_size (struct wl_client *client, pending = meta_wayland_surface_get_pending_state (surface); + if (!pending) + { + wl_resource_post_error (resource, + XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, + "underlying wl_surface already destroyed"); + return; + } + pending->has_new_min_size = TRUE; pending->new_min_width = width; pending->new_min_height = height; @@ -873,9 +889,12 @@ meta_wayland_xdg_toplevel_post_apply_state (MetaWaylandSurfaceRole *surface_rol } else { - wl_resource_post_error (surface->resource, - XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, - "Invalid min/max size"); + if (surface->resource) + { + wl_resource_post_error (surface->resource, + XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, + "Invalid min/max size"); + } } } } @@ -1556,6 +1575,14 @@ xdg_surface_set_window_geometry (struct wl_client *client, } pending = meta_wayland_surface_get_pending_state (surface); + if (!pending) + { + wl_resource_post_error (resource, + XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, + "underlying wl_surface already destroyed"); + return; + } + pending->has_new_geometry = TRUE; pending->new_geometry.x = x; pending->new_geometry.y = y; @@ -1572,6 +1599,14 @@ xdg_surface_ack_configure (struct wl_client *client, MetaWaylandSurfaceState *pending; pending = meta_wayland_surface_get_pending_state (surface); + if (!pending) + { + wl_resource_post_error (resource, + XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE, + "underlying wl_surface already destroyed"); + return; + } + pending->has_acked_configure_serial = TRUE; pending->acked_configure_serial = serial; } diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c index 3886ae9e2..c7608a612 100644 --- a/src/wayland/meta-window-wayland.c +++ b/src/wayland/meta-window-wayland.c @@ -162,7 +162,11 @@ static void meta_window_wayland_kill (MetaWindow *window) { MetaWaylandSurface *surface = meta_window_get_wayland_surface (window); - struct wl_resource *resource = surface->resource; + struct wl_resource *resource; + + resource = surface->resource; + if (!resource) + return; /* Send the client an unrecoverable error to kill the client. */ wl_resource_post_error (resource, @@ -659,9 +663,13 @@ static pid_t meta_window_wayland_get_client_pid (MetaWindow *window) { MetaWaylandSurface *surface = meta_window_get_wayland_surface (window); - struct wl_resource *resource = surface->resource; + struct wl_resource *resource; pid_t pid; + resource = surface->resource; + if (!resource) + return 0; + wl_client_get_credentials (wl_resource_get_client (resource), &pid, NULL, NULL); return pid; } diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c index c9d94b2e3..44229eac0 100644 --- a/src/wayland/meta-xwayland.c +++ b/src/wayland/meta-xwayland.c @@ -137,7 +137,8 @@ meta_xwayland_is_xwayland_surface (MetaWaylandSurface *surface) MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); MetaXWaylandManager *manager = &compositor->xwayland_manager; - return wl_resource_get_client (surface->resource) == manager->client; + return surface->resource != NULL && + wl_resource_get_client (surface->resource) == manager->client; } static gboolean