video_shell: Handle protocol errors about video viewport 10/316210/1
authorSeunghun Lee <shiin.lee@samsung.com>
Thu, 8 Aug 2024 23:36:41 +0000 (08:36 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Fri, 16 Aug 2024 02:57:37 +0000 (11:57 +0900)
The subsurface exported as video viewport cannot have a child
subsurface.

Change-Id: I50b5543044c018d3d4d2c9bb0be242f4d07e10a5

src/bin/server/e_compositor.c
src/bin/server/e_compositor_intern.h
src/bin/server/e_video_shell.c

index 67bb23c74e9417cf93e1c51da7ad71bb4d1f4767..9ce89e6a35074ad129a40d6aa9bdc9eaeaebcccc 100644 (file)
@@ -58,6 +58,7 @@ struct _E_Surface
         struct wl_signal precommit_from_cache;
         struct wl_signal precommit_from_pending;
         struct wl_signal commit;
+        struct wl_signal new_subsurface;
      } events;
 };
 
@@ -395,6 +396,12 @@ e_surface_unmap_listener_add(E_Surface *surface, struct wl_listener *listener)
    ds_surface_add_unmap_listener(surface->ds_surface, listener);
 }
 
+EINTERN void
+e_surface_new_subsurface_listener_add(E_Surface *surface, struct wl_listener *listener)
+{
+   wl_signal_add(&surface->events.new_subsurface, listener);
+}
+
 EINTERN void
 e_surface_map(E_Surface *surface)
 {
@@ -638,6 +645,16 @@ e_surface_has_buffer(E_Surface *surface)
    return !!surface->base.buffer_ref.buffer;
 }
 
+EINTERN Eina_Bool
+e_surface_has_subsurfaces(E_Surface *surface)
+{
+   if (!surface->ds_surface)
+     return EINA_FALSE;
+
+   return !wl_list_empty(&surface->ds_surface->current.subsurfaces_above) ||
+      !wl_list_empty(&surface->ds_surface->current.subsurfaces_below);
+}
+
 EINTERN E_Subsurface *
 e_subsurface_try_from_surface(E_Surface *surface)
 {
@@ -877,6 +894,7 @@ _e_surface_create(E_Client *ec)
    wl_signal_init(&surface->events.precommit_from_cache);
    wl_signal_init(&surface->events.precommit_from_pending);
    wl_signal_init(&surface->events.commit);
+   wl_signal_init(&surface->events.new_subsurface);
    wl_signal_init(&surface->base.destroy_signal);
    wl_signal_init(&surface->base.apply_viewport_signal);
    wl_signal_init(&surface->base.state_commit_signal);
@@ -1549,14 +1567,18 @@ _e_surface_cb_new_subsurface(struct wl_listener *listener, void *data)
 {
    struct ds_subsurface *ds_subsurface = data;
    E_Surface *surface;
+   E_Subsurface *subsurface;
 
    surface = wl_container_of(listener, surface, new_subsurface);
 
-   if (!_e_subsurface_create(ds_subsurface, surface))
+   subsurface = _e_subsurface_create(ds_subsurface, surface);
+   if (!subsurface)
      {
         ELOGF("COMPOSITOR", "Could not create E_Subsurface", surface->ec);
         return;
      }
+
+   wl_signal_emit(&surface->events.new_subsurface, subsurface);
 }
 
 static void
index dfdfae7bcc61a47c9f1559fb741e5cd3ae098b5d..3ec3e6e79b01bf3d98b364f1e126721c8dfc851e 100644 (file)
@@ -23,6 +23,7 @@ void e_surface_precommit_from_pending_listener_add(E_Surface *surface, struct wl
 void e_surface_commit_listener_add(E_Surface *surface, struct wl_listener *listener);
 void e_surface_map_listener_add(E_Surface *surface, struct wl_listener *listener);
 void e_surface_unmap_listener_add(E_Surface *surface, struct wl_listener *listener);
+void e_surface_new_subsurface_listener_add(E_Surface *surface, struct wl_listener *listener);
 struct wl_listener *e_surface_destroy_listener_get(E_Surface *surface, wl_notify_func_t notify);
 Eina_Bool e_surface_role_set(E_Surface *surface, const char *role_name, struct wl_resource *error_resource, uint32_t error_code);
 void e_surface_role_unset(E_Surface *surface);
@@ -42,6 +43,7 @@ Eina_Bool e_surface_has_buffer(E_Surface *surface);
 void e_surface_map(E_Surface *surface);
 void e_surface_unmap(E_Surface *surface);
 Eina_Bool e_surface_is_mapped(E_Surface *surface);
+Eina_Bool e_surface_has_subsurfaces(E_Surface *surface);
 
 E_Subsurface *e_subsurface_create(struct wl_resource *factory_resource, uint32_t id, E_Surface *surface, E_Surface *parent);
 E_Subsurface *e_subsurface_from_resource(struct wl_resource *resource);
index 17533b1c2a17095aefaa06b8f451a9d0b3ffdee8..d1b6e98ea6280118b7d593fd4b38754d03e795fd 100644 (file)
@@ -90,6 +90,7 @@ typedef struct
    struct wl_listener parent_unmap;
    struct wl_listener source_destroy;
    struct wl_listener reposition;
+   struct wl_listener new_subsurface;
 
    Eina_Bool parent_mapped;
    Eina_Bool mapped;
@@ -360,6 +361,7 @@ _viewport_destroy(E_Video_Viewport *viewport)
 
    _viewport_border_finish(viewport);
    wl_resource_set_user_data(viewport->resource, NULL);
+   wl_list_remove(&viewport->new_subsurface.link);
    wl_list_remove(&viewport->parent_map.link);
    wl_list_remove(&viewport->parent_unmap.link);
    wl_list_remove(&viewport->precommit_from_cache.link);
@@ -534,6 +536,20 @@ _viewport_cb_parent_unmap(struct wl_listener *listener, void *data)
    _viewport_unmap(viewport);
 }
 
+static void
+_viewport_cb_new_subsurface(struct wl_listener *listener, void *data)
+{
+   E_Video_Viewport *viewport = wl_container_of(listener, viewport, new_subsurface);
+   E_Subsurface *subsurface = data;
+
+   VS_ERR("VIEWPORT %p| The video viewport subsurface cannot have a child subsurface(%p)",
+          viewport, subsurface);
+
+   wl_resource_post_error(viewport->resource,
+                          WTZ_VIDEO_EXPORTED_VIEWPORT_ERROR_CHILD_ADDED,
+                          "The video viewport subsurface cannot have a child subsurface");
+}
+
 static void
 _viewport_state_init(E_Video_Viewport_State *state)
 {
@@ -573,8 +589,18 @@ _viewport_name_init(E_Video_Viewport *viewport)
 static void
 _video_shell_cb_export_viewport(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *subsurface_resource)
 {
+   E_Subsurface *subsurface = e_subsurface_from_resource(subsurface_resource);
+   E_Surface *surface = e_subsurface_surface_get(subsurface);
+   E_Surface *parent_surface = e_subsurface_parent_try_get(subsurface);
    E_Video_Viewport *viewport;
-   E_Surface *surface, *parent_surface;
+
+   if (e_surface_has_subsurfaces(surface))
+     {
+        wl_resource_post_error(resource,
+                               WTZ_VIDEO_SHELL_ERROR_CHILD_EXISTS,
+                               "The subsurface to export as video viewport cannot have a child subsurface");
+        return;
+     }
 
    viewport = calloc(1, sizeof(*viewport));
    if (!viewport)
@@ -596,12 +622,14 @@ _video_shell_cb_export_viewport(struct wl_client *client, struct wl_resource *re
    _viewport_state_init(&viewport->cache);
    _viewport_state_init(&viewport->current);
 
-   viewport->subsurface = e_subsurface_from_resource(subsurface_resource);
+   viewport->subsurface = subsurface;
 
    viewport->destroy.notify = _viewport_cb_subsurface_destroy;
-   e_subsurface_destroy_listener_add(viewport->subsurface, &viewport->destroy);
+   e_subsurface_destroy_listener_add(subsurface, &viewport->destroy);
+
+   viewport->reposition.notify = _viewport_cb_reposition;
+   e_subsurface_reposition_listener_add(subsurface, &viewport->reposition);
 
-   surface = e_subsurface_surface_get(viewport->subsurface);
    viewport->precommit_to_cache.notify = _viewport_cb_precommit_to_cache;
    e_surface_precommit_to_cache_listener_add(surface, &viewport->precommit_to_cache);
 
@@ -611,10 +639,8 @@ _video_shell_cb_export_viewport(struct wl_client *client, struct wl_resource *re
    viewport->precommit_from_pending.notify = _viewport_cb_precommit_from_pending;
    e_surface_precommit_from_pending_listener_add(surface, &viewport->precommit_from_pending);
 
-   viewport->reposition.notify = _viewport_cb_reposition;
-   e_subsurface_reposition_listener_add(viewport->subsurface, &viewport->reposition);
-
-   parent_surface = e_subsurface_parent_try_get(viewport->subsurface);
+   viewport->new_subsurface.notify = _viewport_cb_new_subsurface;
+   e_surface_new_subsurface_listener_add(surface, &viewport->new_subsurface);
 
    viewport->parent_map.notify = _viewport_cb_parent_map;
    e_surface_map_listener_add(parent_surface, &viewport->parent_map);
@@ -631,7 +657,7 @@ _video_shell_cb_export_viewport(struct wl_client *client, struct wl_resource *re
    if (border_enabled)
      _viewport_border_init(viewport);
 
-   VS_INF("VIEWPORT %p| Created with E_Subsurface(%p)", viewport, viewport->subsurface);
+   VS_INF("VIEWPORT %p| Created with E_Subsurface(%p)", viewport, subsurface);
 }
 
 static void