desktop-shell: Implement popup
authorJaehoon Jeong <jh01.j@samsung.com>
Mon, 20 Jul 2015 06:32:46 +0000 (15:32 +0900)
committerJaehoon Jeong <jh01.j@samsung.com>
Mon, 20 Jul 2015 06:32:46 +0000 (15:32 +0900)
    - wl_shell_surface.set_popup()
    - xdg_shell.get_xdg_popup()
    - TODO: add popup grab

Change-Id: Icfb8dd8d50405b8d57c734e4bb11dad28cf7353d

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

index 38a345b..0b78d13 100644 (file)
@@ -77,6 +77,13 @@ struct shell_surface
     /* Data structures per surface type */
     shell_surface_type_t     type;
 
+    struct
+    {
+        int32_t              x, y;
+        uint32_t             flags;
+        pepper_seat_t       *seat;
+    } popup;
+
     /* (*map) */
     void (*shell_surface_map)(shell_surface_t *shsurf);
     pepper_bool_t            mapped;
@@ -133,5 +140,9 @@ shell_surface_set_class(shell_surface_t *shsurf, const char* class_);
 void
 shell_surface_set_toplevel(shell_surface_t *shsurf);
 
+void
+shell_surface_set_popup(shell_surface_t *shsurf, pepper_seat_t *seat, pepper_surface_t *parent,
+                        int32_t x, int32_t y, uint32_t flags);
+
 pepper_bool_t
 init_wl_shell(desktop_shell_t *shell);
index 5859a4c..68a6d55 100644 (file)
@@ -238,6 +238,24 @@ shell_surface_set_toplevel(shell_surface_t *shsurf)
     shsurf->mapped = PEPPER_FALSE;
 }
 
+void
+shell_surface_set_popup(shell_surface_t     *shsurf,
+                        pepper_seat_t       *seat,
+                        pepper_surface_t    *parent,
+                        int32_t              x,
+                        int32_t              y,
+                        uint32_t             flags)
+{
+    shell_surface_set_parent(shsurf, parent);
+
+    shsurf->popup.x     = x;
+    shsurf->popup.y     = y;
+    shsurf->popup.flags = flags;
+    shsurf->popup.seat  = seat;
+
+    shell_surface_set_type(shsurf, SHELL_SURFACE_TYPE_POPUP);
+}
+
 static void
 shell_surface_set_position(shell_surface_t *shsurf, int32_t x, int32_t y)
 {
@@ -261,6 +279,20 @@ shell_surface_map_toplevel(shell_surface_t *shsurf)
     shsurf->mapped = PEPPER_TRUE;
 }
 
+static void
+shell_surface_map_popup(shell_surface_t *shsurf)
+{
+    shell_surface_t *parent = get_shsurf_from_surface(shsurf->parent, shsurf->shell);
+
+    /* Set position as relatively */
+    pepper_view_set_parent(shsurf->view, parent->view);
+    shell_surface_set_position(shsurf, shsurf->popup.x, shsurf->popup.y);
+
+    pepper_view_map(shsurf->view);
+
+    /* TODO: add_popup_grab(), but how? */
+}
+
 void
 shell_surface_set_type(shell_surface_t *shsurf, shell_surface_type_t type)
 {
@@ -274,6 +306,9 @@ shell_surface_set_type(shell_surface_t *shsurf, shell_surface_type_t type)
     case SHELL_SURFACE_TYPE_TOPLEVEL:
         shsurf->shell_surface_map = shell_surface_map_toplevel;
         break;
+    case SHELL_SURFACE_TYPE_POPUP:
+        shsurf->shell_surface_map = shell_surface_map_popup;
+        break;
     default :
         /* XXX: Maybe some logs be needed */
         break;
index b109d82..1a42a74 100644 (file)
@@ -45,11 +45,36 @@ wl_shell_surface_set_fullscreen(struct wl_client *client, struct wl_resource *re
 }
 
 static void
-wl_shell_surface_set_popup(struct wl_client *client, struct wl_resource *resource,
-                        struct wl_resource *seat, uint32_t serial, struct wl_resource *parent,
-                        int32_t x, int32_t y, uint32_t flags)
-{
-    /* TODO */
+wl_shell_surface_set_popup(struct wl_client     *client,
+                           struct wl_resource   *resource,
+                           struct wl_resource   *seat_res,
+                           uint32_t              serial,
+                           struct wl_resource   *parent_res,
+                           int32_t               x,
+                           int32_t               y,
+                           uint32_t              flags)
+{
+    shell_surface_t     *shsurf = wl_resource_get_user_data(resource);
+    pepper_seat_t       *seat;
+    pepper_surface_t    *parent;
+
+    if (!seat_res)
+    {
+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "Invalid seat");
+        return ;
+    }
+    seat = wl_resource_get_user_data(seat_res);
+
+    if (!parent_res)
+    {
+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "Invalid parent surface");
+        return ;
+    }
+    parent = wl_resource_get_user_data(parent_res);
+
+    shell_surface_set_popup(shsurf, seat, parent, x, y, flags);
 }
 
 static void
index 4c4f13c..4a87f58 100644 (file)
@@ -205,10 +205,52 @@ xdg_shell_get_xdg_popup(struct wl_client    *client,
                         int32_t              x,
                         int32_t              y)
 {
-    shell_client_t     *shell_client = wl_resource_get_user_data(resource);
-    pepper_surface_t   *surface      = wl_resource_get_user_data(surface_resource);
-    shell_surface_t    *shsurf;
+    shell_client_t      *shell_client = wl_resource_get_user_data(resource);
+    pepper_surface_t    *surface;
+    pepper_seat_t       *seat;
+    pepper_surface_t    *parent;
+    shell_surface_t     *shsurf;
+
+    /* Check parameters */
+    if (!surface_resource)
+    {
+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "Invalid surface");
+        return ;
+    }
+    surface = wl_resource_get_user_data(surface_resource);
 
+    if (!seat_resource)
+    {
+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "Invalid seat");
+        return ;
+    }
+    seat = wl_resource_get_user_data(seat_resource);
+
+    if (!parent_resource)
+    {
+        wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, "Invalid parent surface");
+        return ;
+    }
+    parent = wl_resource_get_user_data(parent_resource);
+
+    /**
+     * TODO: check parent state
+     *       1. Parent must have either a xdg_surface or xdg_popup role
+     *       2. If there is an existing popup when creating a new popup, the
+     *          parent must be the current topmost popup.
+     */
+    {
+        const char *role = pepper_surface_get_role(parent);
+
+        if (strcmp(role, "xdg_surface") && strcmp(role, "xdg_popup"))
+        {
+            wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+                                   "Invalid xdg_popup parent");
+            return ;
+        }
+    }
+
+    /* Set role */
     if (!pepper_surface_set_role(surface, "xdg_popup"))
     {
         wl_resource_post_error(resource, XDG_SHELL_ERROR_ROLE,
@@ -222,6 +264,8 @@ xdg_shell_get_xdg_popup(struct wl_client    *client,
                                   &xdg_popup_implementation, 1, id);
     if (!shsurf)
         wl_client_post_no_memory(client);
+
+    shell_surface_set_popup(shsurf, seat, parent, x, y, 0);
 }
 
 static void