Weston's desktop shell increments the ref_count on the surfaces so that
when the wl_resource of the wl_surface is destroyed the weston_surface
keeps living. In that case, the weston_desktop_surface keeps living too
but the shell resource doesn't. In the xdg_shell case it is destroyed
by the client with the destroy request, in the wl_shell case it needs
to be destroyed by the server when the wl_surface is destroyed.
That means that a weston_desktop_surface can have no active shell
implementation, and we need to guard that.
---
 libweston-desktop/client.c  |  2 +-
 libweston-desktop/surface.c | 63 +++++++++++++++++++++++++++++++++++----------
 2 files changed, 51 insertions(+), 14 deletions(-)

diff --git a/libweston-desktop/client.c b/libweston-desktop/client.c
index 810b6ba..a8968b8 100644
--- a/libweston-desktop/client.c
+++ b/libweston-desktop/client.c
@@ -186,7 +186,7 @@ weston_desktop_client_ping(struct weston_desktop_client 
*client)
        void *implementation_data =
                weston_desktop_surface_get_implementation_data(surface);
 
-       if (implementation->ping == NULL)
+       if (implementation == NULL || implementation->ping == NULL)
                return -1;
 
        if (client->ping_serial != 0)
diff --git a/libweston-desktop/surface.c b/libweston-desktop/surface.c
index 2205107..103f34f 100644
--- a/libweston-desktop/surface.c
+++ b/libweston-desktop/surface.c
@@ -54,6 +54,7 @@ struct weston_desktop_surface {
        struct weston_position buffer_move;
        struct wl_listener surface_commit_listener;
        struct wl_listener surface_destroy_listener;
+       struct wl_listener wl_surface_resource_destroy_listener;
        struct wl_listener client_destroy_listener;
        struct wl_list children_list;
 
@@ -130,6 +131,7 @@ weston_desktop_surface_destroy(struct 
weston_desktop_surface *surface)
 
        wl_list_remove(&surface->surface_commit_listener.link);
        wl_list_remove(&surface->surface_destroy_listener.link);
+       wl_list_remove(&surface->wl_surface_resource_destroy_listener.link);
        wl_list_remove(&surface->client_destroy_listener.link);
 
        if (!wl_list_empty(&surface->resource_list)) {
@@ -140,7 +142,9 @@ weston_desktop_surface_destroy(struct 
weston_desktop_surface *surface)
                }
        }
 
-       surface->implementation->destroy(surface, surface->implementation_data);
+       if (surface->implementation)
+               surface->implementation->destroy(surface,
+                                                surface->implementation_data);
 
        surface->surface->committed = NULL;
        surface->surface->committed_private = NULL;
@@ -169,6 +173,9 @@ weston_desktop_surface_surface_committed(struct wl_listener 
*listener,
        struct weston_desktop_surface *surface =
                wl_container_of(listener, surface, surface_commit_listener);
 
+       /* committed cannot be called if the resource for the wl_surface does
+        * not exist anymore, so we don't need to check if implementation is
+        * valid here. */
        if (surface->implementation->committed != NULL)
                surface->implementation->committed(surface,
                                                   surface->implementation_data,
@@ -218,6 +225,20 @@ weston_desktop_surface_resource_destroy(struct wl_resource 
*resource)
 }
 
 static void
+weston_desktop_wl_surface_resource_destroyed(struct wl_listener *listener,
+                                            void *data)
+{
+       struct weston_desktop_surface *surface =
+               wl_container_of(listener, surface,
+                               wl_surface_resource_destroy_listener);
+
+       wl_list_init(&surface->wl_surface_resource_destroy_listener.link);
+
+       surface->implementation->destroy(surface, surface->implementation_data);
+       surface->implementation = NULL;
+}
+
+static void
 weston_desktop_surface_committed(struct weston_surface *wsurface,
                                 int32_t sx, int32_t sy)
 {
@@ -277,6 +298,10 @@ weston_desktop_surface_create(struct weston_desktop 
*desktop,
                weston_desktop_surface_surface_destroyed;
        wl_signal_add(&surface->surface->destroy_signal,
                      &surface->surface_destroy_listener);
+       surface->wl_surface_resource_destroy_listener.notify =
+               weston_desktop_wl_surface_resource_destroyed;
+       wl_resource_add_destroy_listener(wsurface->resource,
+                                        
&surface->wl_surface_resource_destroy_listener);
 
        wl_list_init(&surface->client_link);
        wl_list_init(&surface->resource_list);
@@ -459,7 +484,8 @@ weston_desktop_surface_propagate_layer(struct 
weston_desktop_surface *surface)
 WL_EXPORT void
 weston_desktop_surface_set_activated(struct weston_desktop_surface *surface, 
bool activated)
 {
-       if (surface->implementation->set_activated != NULL)
+       if (surface->implementation != NULL &&
+           surface->implementation->set_activated != NULL)
                surface->implementation->set_activated(surface,
                                                       
surface->implementation_data,
                                                       activated);
@@ -468,7 +494,8 @@ weston_desktop_surface_set_activated(struct 
weston_desktop_surface *surface, boo
 WL_EXPORT void
 weston_desktop_surface_set_fullscreen(struct weston_desktop_surface *surface, 
bool fullscreen)
 {
-       if (surface->implementation->set_fullscreen != NULL)
+       if (surface->implementation != NULL &&
+           surface->implementation->set_fullscreen != NULL)
                surface->implementation->set_fullscreen(surface,
                                                        
surface->implementation_data,
                                                        fullscreen);
@@ -477,7 +504,8 @@ weston_desktop_surface_set_fullscreen(struct 
weston_desktop_surface *surface, bo
 WL_EXPORT void
 weston_desktop_surface_set_maximized(struct weston_desktop_surface *surface, 
bool maximized)
 {
-       if (surface->implementation->set_maximized != NULL)
+       if (surface->implementation != NULL &&
+           surface->implementation->set_maximized != NULL)
                surface->implementation->set_maximized(surface,
                                                       
surface->implementation_data,
                                                       maximized);
@@ -486,7 +514,8 @@ weston_desktop_surface_set_maximized(struct 
weston_desktop_surface *surface, boo
 WL_EXPORT void
 weston_desktop_surface_set_resizing(struct weston_desktop_surface *surface, 
bool resizing)
 {
-       if (surface->implementation->set_resizing != NULL)
+       if (surface->implementation != NULL &&
+           surface->implementation->set_resizing != NULL)
                surface->implementation->set_resizing(surface,
                                                      
surface->implementation_data,
                                                      resizing);
@@ -495,7 +524,8 @@ weston_desktop_surface_set_resizing(struct 
weston_desktop_surface *surface, bool
 WL_EXPORT void
 weston_desktop_surface_set_size(struct weston_desktop_surface *surface, 
int32_t width, int32_t height)
 {
-       if (surface->implementation->set_size != NULL)
+       if (surface->implementation != NULL &&
+           surface->implementation->set_size != NULL)
                surface->implementation->set_size(surface,
                                                  surface->implementation_data,
                                                  width, height);
@@ -504,7 +534,8 @@ weston_desktop_surface_set_size(struct 
weston_desktop_surface *surface, int32_t
 WL_EXPORT void
 weston_desktop_surface_close(struct weston_desktop_surface *surface)
 {
-       if (surface->implementation->close != NULL)
+       if (surface->implementation != NULL &&
+           surface->implementation->close != NULL)
                surface->implementation->close(surface,
                                               surface->implementation_data);
 }
@@ -606,7 +637,8 @@ weston_desktop_surface_get_pid(struct 
weston_desktop_surface *surface)
 WL_EXPORT bool
 weston_desktop_surface_get_activated(struct weston_desktop_surface *surface)
 {
-       if (surface->implementation->get_activated == NULL)
+       if (surface->implementation == NULL ||
+           surface->implementation->get_activated == NULL)
                return false;
        return surface->implementation->get_activated(surface,
                                                      
surface->implementation_data);
@@ -615,7 +647,8 @@ weston_desktop_surface_get_activated(struct 
weston_desktop_surface *surface)
 WL_EXPORT bool
 weston_desktop_surface_get_resizing(struct weston_desktop_surface *surface)
 {
-       if (surface->implementation->get_resizing == NULL)
+       if (surface->implementation == NULL ||
+           surface->implementation->get_resizing == NULL)
                return false;
        return surface->implementation->get_resizing(surface,
                                                     
surface->implementation_data);
@@ -624,7 +657,8 @@ weston_desktop_surface_get_resizing(struct 
weston_desktop_surface *surface)
 WL_EXPORT bool
 weston_desktop_surface_get_maximized(struct weston_desktop_surface *surface)
 {
-       if (surface->implementation->get_maximized == NULL)
+       if (surface->implementation == NULL ||
+           surface->implementation->get_maximized == NULL)
                return false;
        return surface->implementation->get_maximized(surface,
                                                      
surface->implementation_data);
@@ -633,7 +667,8 @@ weston_desktop_surface_get_maximized(struct 
weston_desktop_surface *surface)
 WL_EXPORT bool
 weston_desktop_surface_get_fullscreen(struct weston_desktop_surface *surface)
 {
-       if (surface->implementation->get_fullscreen == NULL)
+       if (surface->implementation == NULL ||
+           surface->implementation->get_fullscreen == NULL)
                return false;
        return surface->implementation->get_fullscreen(surface,
                                                       
surface->implementation_data);
@@ -652,7 +687,8 @@ weston_desktop_surface_get_max_size(struct 
weston_desktop_surface *surface)
 {
        struct weston_size size = { 0, 0 };
 
-       if (surface->implementation->get_max_size == NULL)
+       if (surface->implementation == NULL ||
+           surface->implementation->get_max_size == NULL)
                return size;
        return surface->implementation->get_max_size(surface,
                                                     
surface->implementation_data);
@@ -663,7 +699,8 @@ weston_desktop_surface_get_min_size(struct 
weston_desktop_surface *surface)
 {
        struct weston_size size = { 0, 0 };
 
-       if (surface->implementation->get_min_size == NULL)
+       if (surface->implementation == NULL ||
+           surface->implementation->get_min_size == NULL)
                return size;
        return surface->implementation->get_min_size(surface,
                                                     
surface->implementation_data);
-- 
2.10.0

_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to