OSDN Git Service

wayland: Implement registry remove handler
authorPhilipp Kerling <pkerling@casix.org>
Wed, 16 Aug 2017 10:37:27 +0000 (12:37 +0200)
committerXiang, Haihao <haihao.xiang@intel.com>
Thu, 17 Aug 2017 03:06:29 +0000 (11:06 +0800)
Wayland event handlers are never optional. libwayland-client will abort
the program if events for unbound handlers are to be dispatched.
Although the event queue is only dispatched a few times during
initialization for getting the wl_drm global and authenticating the DRM
device, in rare circumstances it can happen that another global such as
a wl_output - or even wl_drm itself - is removed during that time, which
would crash the program. Implement the handler to fix this.

Fixes: #99

Signed-off-by: Philipp Kerling <pkerling@casix.org>
va/wayland/va_wayland_drm.c

index a4d3ebb..552f243 100644 (file)
@@ -41,6 +41,7 @@ typedef struct va_wayland_drm_context {
     struct va_wayland_context   base;
     struct wl_event_queue      *queue;
     struct wl_drm              *drm;
+    uint32_t                    drm_name;
     struct wl_registry         *registry;
     unsigned int                is_authenticated        : 1;
 } VADisplayContextWaylandDRM;
@@ -148,7 +149,7 @@ static void
 registry_handle_global(
     void               *data,
     struct wl_registry *registry,
-    uint32_t            id,
+    uint32_t            name,
     const char         *interface,
     uint32_t            version
 )
@@ -159,15 +160,31 @@ registry_handle_global(
         /* bind to at most version 2, but also support version 1 if
          * compositor does not have v2
          */
+        wl_drm_ctx->drm_name = name;
         wl_drm_ctx->drm =
-            wl_registry_bind(wl_drm_ctx->registry, id, &wl_drm_interface,
+            wl_registry_bind(wl_drm_ctx->registry, name, &wl_drm_interface,
                              (version < 2) ? version : 2);
     }
 }
 
+static void
+registry_handle_global_remove(
+    void               *data,
+    struct wl_registry *registry,
+    uint32_t            name
+)
+{
+    struct va_wayland_drm_context *wl_drm_ctx = data;
+
+    if (wl_drm_ctx->drm && name == wl_drm_ctx->drm_name) {
+        wl_drm_destroy(wl_drm_ctx->drm);
+        wl_drm_ctx->drm = NULL;
+    }
+}
+
 static const struct wl_registry_listener registry_listener = {
     registry_handle_global,
-    NULL,
+    registry_handle_global_remove
 };
 
 static bool