desktop-shell: implement wl_shell::get_shell_surface, wl_shell_surface::set_toplevel
authorJaehoon Jeong <jh01.j@samsung.com>
Thu, 18 Jun 2015 07:45:50 +0000 (16:45 +0900)
committerTaekyun Kim <tkq.kim@samsung.com>
Tue, 7 Jul 2015 06:56:50 +0000 (15:56 +0900)
    - a little implementation

Change-Id: I72ea10abcdc781ba1c3e0141d6203cbb894aea77

desktop-shell/src/desktop-shell-internal.h
desktop-shell/src/shell-surface.c
desktop-shell/src/shell.c
desktop-shell/src/wl-shell.c

index 50c89b6..7dc1e2b 100644 (file)
@@ -15,6 +15,16 @@ struct shell
 {
     pepper_object_t    *compositor;
     struct wl_resource *resource;
+    struct wl_list      shell_surface_list;
+};
+
+enum shell_surface_type
+{
+    SHELL_SURFACE_TYPE_NONE,
+    SHELL_SURFACE_TYPE_TOPLEVEL,
+    SHELL_SURFACE_TYPE_FULLSCREEN,
+    SHELL_SURFACE_TYPE_POPUP,
+    SHELL_SURFACE_TYPE_MAXIMIZED
 };
 
 struct shell_surface
@@ -24,11 +34,28 @@ struct shell_surface
     struct wl_client       *client;
     struct wl_resource     *resource;
 
-    struct wl_listener      client_destroy_listener;
-    struct wl_listener      surface_destroy_listener;
+    pepper_object_t        *parent;
+    struct wl_list          child_list;   /* children surfaces of this */
+    struct wl_list          parent_link;
+
+    pepper_object_t        *view;
+
+    enum shell_surface_type type;
+
+    char                   *title, *class_;
+
+    struct
+    {
+        int32_t x, y, width, height;
+    } geometry, saved;
 
     struct wl_event_source *ping_timer;
     pepper_bool_t           need_pong;
+
+    struct wl_listener      client_destroy_listener;
+    struct wl_listener      surface_destroy_listener;
+
+    struct wl_list          link;       /* link */
 };
 
 shell_t *
@@ -38,11 +65,24 @@ shell_create(pepper_object_t *compositor, struct wl_client *client,
 
 shell_surface_t *
 shell_surface_create(shell_t *shell, pepper_object_t *surface, struct wl_client *client,
-                     const char *role_name, const struct wl_interface *interface,
+                     const struct wl_interface *interface,
                      const void *implemenetation, uint32_t version, uint32_t id);
 
 void
 shell_surface_ping(shell_surface_t *shsurf);
 
+void
+shell_surface_set_type(shell_surface_t *shsurf, enum shell_surface_type type);
+
+void
+shell_surface_set_parent(shell_surface_t *shsurf, pepper_object_t *parent_surface);
+
+/* */
+shell_surface_t *
+get_shsurf_from_surface(pepper_object_t *surface, shell_t *shell);
+
+void
+set_shsurf_to_surface(pepper_object_t *surface, shell_surface_t *shsurf);
+
 pepper_bool_t
 init_wl_shell(pepper_object_t *compositor);
index 602ce59..1d6d703 100644 (file)
@@ -17,15 +17,19 @@ handle_client_destroy(struct wl_listener *listener, void *data)
     shell_surface_t *shsurf =
         pepper_container_of(listener, shell_surface_t, client_destroy_listener);
 
-    wl_list_remove(&shsurf->client_destroy_listener.link);
+    if (!wl_list_empty(&shsurf->client_destroy_listener.link))
+        wl_list_remove(&shsurf->client_destroy_listener.link);
     wl_list_init(&shsurf->client_destroy_listener.link);
 
     remove_ping_timer(shsurf);
+
+    /* client_destroy -> client's surface destroy -> handle_surface_destroy */
 }
 
 static void
 handle_surface_destroy(struct wl_listener *listener, void *data)
 {
+    shell_surface_t *child, *tmp;
     shell_surface_t *shsurf =
         pepper_container_of(listener, shell_surface_t, surface_destroy_listener);
 
@@ -34,10 +38,25 @@ handle_surface_destroy(struct wl_listener *listener, void *data)
 
     wl_list_remove(&shsurf->surface_destroy_listener.link);
 
+    /* We don't need to destroy pepper_view_t */
+
     if (shsurf->resource)
         wl_resource_destroy(shsurf->resource);
 
+    if (shsurf->title)
+        free(shsurf->title);
+
+    if (shsurf->class_)
+        free(shsurf->class_);
+
     remove_ping_timer(shsurf);
+
+    wl_list_remove(&shsurf->parent_link);
+
+    wl_list_for_each_safe(child, tmp, &shsurf->child_list, parent_link)
+        shell_surface_set_parent(child, NULL);
+
+    wl_list_remove(&shsurf->link);
     free(shsurf);
 }
 
@@ -45,33 +64,55 @@ static void
 handle_resource_destroy(struct wl_resource *resource)
 {
     shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
     shsurf->resource = NULL;
 }
 
 shell_surface_t *
 shell_surface_create(shell_t *shell, pepper_object_t *surface, struct wl_client *client,
-                     const char *role_name, const struct wl_interface *interface,
+                     const struct wl_interface *interface,
                      const void *implementation, uint32_t version, uint32_t id)
 {
-    shell_surface_t *shsurf;
-
-    if (pepper_surface_get_role(surface))
-        return NULL;
+    shell_surface_t *shsurf = NULL;
 
     shsurf = calloc(1, sizeof(shell_surface_t));
     if (!shsurf)
-        return NULL;
+    {
+        PEPPER_ERROR("Memory allocation faiiled\n");
+        goto error;
+    }
 
     shsurf->resource = wl_resource_create(client, interface, version, id);
     if (!shsurf->resource)
     {
-        free(shsurf);
-        return NULL;
+        PEPPER_ERROR("wl_resource_create failed\n");
+        goto error;
     }
 
-    shsurf->shell = shell;
+    shsurf->shell  = shell;
     shsurf->client = client;
 
+    shsurf->view = pepper_compositor_add_view(shell->compositor, NULL, NULL, surface);
+    if (!shsurf->view)
+    {
+        PEPPER_ERROR("pepper_compositor_add_view failed\n");
+        goto error;
+    }
+
+    /* TODO: Need to know about output size */
+    shsurf->geometry.x = rand()%10;
+    shsurf->geometry.y = rand()%10;
+    pepper_view_set_position(shsurf->view, shsurf->geometry.x, shsurf->geometry.y);
+
+    wl_list_init(&shsurf->link);
+    wl_list_insert(&shell->shell_surface_list, &shsurf->link);
+
+    wl_list_init(&shsurf->child_list);
+    wl_list_init(&shsurf->parent_link);
+
+    /* Set shell_surface_t to pepper_surface_t */
+    set_shsurf_to_surface(surface, shsurf);
+
     wl_resource_set_implementation(shsurf->resource, implementation, shsurf, handle_resource_destroy);
 
     shsurf->client_destroy_listener.notify = handle_client_destroy;
@@ -81,6 +122,13 @@ shell_surface_create(shell_t *shell, pepper_object_t *surface, struct wl_client
     pepper_object_add_destroy_listener(surface, &shsurf->surface_destroy_listener);
 
     return shsurf;
+
+error:
+    if (shsurf)
+        free(shsurf);
+
+    wl_client_post_no_memory(client);
+    return NULL;
 }
 
 static int
@@ -115,3 +163,39 @@ shell_surface_ping(shell_surface_t *shsurf)
 
     /* TODO: Do protocol specific ping. */
 }
+
+void
+shell_surface_set_type(shell_surface_t *shsurf, enum shell_surface_type type)
+{
+    shsurf->type = type;
+}
+
+shell_surface_t *
+get_shsurf_from_surface(pepper_object_t *surface, shell_t *shell)
+{
+    return pepper_object_get_user_data(surface, shell);
+}
+
+void
+set_shsurf_to_surface(pepper_object_t *surface, shell_surface_t *shsurf)
+{
+    pepper_object_set_user_data(surface, shsurf->shell, shsurf, NULL);
+}
+
+void
+shell_surface_set_parent(shell_surface_t *shsurf, pepper_object_t *parent)
+{
+    shell_surface_t *parent_shsurf;
+
+    wl_list_remove(&shsurf->parent_link);
+    wl_list_init(&shsurf->parent_link);
+
+    shsurf->parent = parent;
+
+    if (parent)
+    {
+        parent_shsurf = get_shsurf_from_surface(parent, shsurf->shell);
+        if (parent_shsurf)
+            wl_list_insert(&parent_shsurf->child_list, &shsurf->parent_link);
+    }
+}
index 5981393..7100f81 100644 (file)
@@ -26,6 +26,9 @@ shell_create(pepper_object_t *compositor, struct wl_client *client,
     wl_resource_set_implementation(shell->resource, implementation, shell, NULL);
 
     shell->compositor = compositor;
+
+    wl_list_init(&shell->shell_surface_list);
+
     return shell;
 }
 
index 37ed9ba..875389c 100644 (file)
@@ -23,7 +23,13 @@ shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
 static void
 shell_surface_set_toplevel(struct wl_client *client, struct wl_resource *resource)
 {
-    /* TODO */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+    shell_surface_set_parent(shsurf, NULL);
+
+    shell_surface_set_type(shsurf, SHELL_SURFACE_TYPE_TOPLEVEL);
+
+    pepper_view_set_visibility(shsurf->view, PEPPER_TRUE);
 }
 
 static void
@@ -50,7 +56,7 @@ shell_surface_set_popup(struct wl_client *client, struct wl_resource *resource,
 
 static void
 shell_surface_set_maximized(struct wl_client *client, struct wl_resource *resource,
-                            struct wl_resource *output)
+                            struct wl_resource *output_res)
 {
     /* TODO */
 }
@@ -59,14 +65,30 @@ static void
 shell_surface_set_title(struct wl_client *client, struct wl_resource *resource,
                         const char *title)
 {
-    /* TODO */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+    if (shsurf->title)
+        free(shsurf->title);
+
+    shsurf->title = strdup(title);
+
+    if (!shsurf->title)
+        wl_client_post_no_memory(client);
 }
 
 static void
 shell_surface_set_class(struct wl_client *client, struct wl_resource *resource,
                         const char *class_)
 {
-    /* TODO */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+    if (shsurf->class_)
+        free(shsurf->class_);
+
+    shsurf->class_ = strdup(class_);
+
+    if (!shsurf->class_)
+        wl_client_post_no_memory(client);
 }
 
 static const struct wl_shell_surface_interface shell_surface_implementation =
@@ -88,9 +110,16 @@ shell_get_shell_surface(struct wl_client *client, struct wl_resource *resource,
                         uint32_t id, struct wl_resource *surface_resource)
 {
     pepper_object_t    *surface = wl_resource_get_user_data(surface_resource);
-    shell_t            *shell = wl_resource_get_user_data(resource);
+    shell_t            *shell   = wl_resource_get_user_data(resource);
+
+    if (!pepper_surface_set_role(surface, "wl_shell_surface"))
+    {
+        wl_resource_post_error(resource, WL_SHELL_ERROR_ROLE,
+                               "Assign \"wl_shell_surface\" to wl_surface failed\n");
+        return ;
+    }
 
-    shell_surface_create(shell, surface, client, "wl_shell_surface", &wl_shell_surface_interface,
+    shell_surface_create(shell, surface, client, &wl_shell_surface_interface,
                          &shell_surface_implementation, 1, id);
 }