desktop-shell: implement xdg_shell, fullscreen, maximized
authorJaehoon Jeong <jh01.j@samsung.com>
Wed, 22 Jul 2015 11:44:40 +0000 (20:44 +0900)
committerGerrit Code Review <root@ap3>
Mon, 27 Jul 2015 03:44:26 +0000 (12:44 +0900)
    - Add init_xdg_shell() in pepper_desktop_shell_init()
    - Implement fullscreen, maximized related types
    - Handle client_destroy in shell_client

Change-Id: Ibfa25b4b4cd871414721cf153393fd73b035fbfb

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

index ea511a1..4169620 100644 (file)
@@ -51,7 +51,8 @@ typedef enum
     SHELL_SURFACE_TYPE_TRANSIENT,
     SHELL_SURFACE_TYPE_FULLSCREEN,
     SHELL_SURFACE_TYPE_POPUP,
-    SHELL_SURFACE_TYPE_MAXIMIZED
+    SHELL_SURFACE_TYPE_MAXIMIZED,
+    SHELL_SURFACE_TYPE_MINIMIZED,
 } shell_surface_type_t;
 
 struct shell_surface
@@ -75,7 +76,8 @@ struct shell_surface
     char                    *title, *class_;
 
     /* Data structures per surface type */
-    shell_surface_type_t     type;
+    shell_surface_type_t     type;          /* Current surface type */
+    shell_surface_type_t     next_type;     /* Requested surface type */
 
     struct
     {
@@ -90,12 +92,38 @@ struct shell_surface
         uint32_t             flags;
     } transient;
 
-    /* (*map) */
+    struct
+    {
+        pepper_output_t     *output;
+    } maximized;
+
+    struct
+    {
+        uint32_t             method;
+        uint32_t             framerate;
+        pepper_surface_t    *background_surface;
+        pepper_view_t       *background_view;
+        pepper_output_t     *output;
+    } fullscreen;
+
+    struct
+    {
+        int32_t              x, y, w, h;
+        uint32_t             framerate;
+    } saved;
+
+    /* map */
     void (*shell_surface_map)(shell_surface_t *shsurf);
+
+    /* (*map) was called */
     pepper_bool_t            mapped;
 
+    /* configure */
+    void (*send_configure)(shell_surface_t *shsurf, int32_t width, int32_t height);
+
+    pepper_bool_t           ack_configure;
+
     /* Listeners */
-    struct wl_listener      client_destroy_listener;
     struct wl_listener      surface_destroy_listener;
     struct wl_listener      surface_commit_listener;
 
index 59e1d7e..754e2e4 100644 (file)
@@ -24,7 +24,7 @@ handle_surface_commit(struct wl_listener *listener, void *data)
     shell_surface_t *shsurf =
         pepper_container_of(listener, shell_surface_t, surface_commit_listener);
 
-    if (!shsurf->mapped && shsurf->shell_surface_map)
+    if (!shsurf->mapped && shsurf->ack_configure && shsurf->shell_surface_map)
         shsurf->shell_surface_map(shsurf);
 }
 
@@ -37,26 +37,12 @@ shsurf_start_listen_commit_event(shell_surface_t *shsurf)
 }
 
 static void
-handle_client_destroy(struct wl_listener *listener, void *data)
-{
-    shell_surface_t *shsurf =
-        pepper_container_of(listener, shell_surface_t, client_destroy_listener);
-
-    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);
-}
-
-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);
 
-    if (!wl_list_empty(&shsurf->client_destroy_listener.link))
-        wl_list_remove(&shsurf->client_destroy_listener.link);
-
     wl_list_remove(&shsurf->surface_destroy_listener.link);
 
     shsurf_stop_listen_commit_event(shsurf);
@@ -76,6 +62,13 @@ handle_surface_destroy(struct wl_listener *listener, void *data)
         shell_surface_set_parent(child, NULL);
 
     wl_list_remove(&shsurf->link);
+
+    if (shsurf->fullscreen.background_surface)
+        /* TODO: pepper_surface_destroy(shsurf->fullscreen.background_surface); */;
+
+    if (shsurf->fullscreen.background_view)
+        pepper_view_destroy(shsurf->fullscreen.background_view);
+
     free(shsurf);
 }
 
@@ -87,12 +80,89 @@ handle_resource_destroy(struct wl_resource *resource)
     shsurf->resource = NULL;
 }
 
+static void
+shsurf_wl_shell_surface_send_configure(shell_surface_t *shsurf, int32_t width, int32_t height)
+{
+    uint32_t edges = 0; /* FIXME */
+
+    wl_shell_surface_send_configure(shsurf->resource,
+                                    edges,
+                                    width,
+                                    height);
+
+    /* wl_shell_surface dont need this */
+    shsurf->ack_configure = PEPPER_TRUE;
+}
+
+static void
+shsurf_xdg_surface_send_configure(shell_surface_t *shsurf, int32_t width, int32_t height)
+{
+    struct wl_display   *display;
+    struct wl_array      states;
+    uint32_t            *state;
+    uint32_t             serial;
+
+    wl_array_init(&states);
+
+    if (shsurf->next_type == SHELL_SURFACE_TYPE_MAXIMIZED)
+    {
+        state  = wl_array_add(&states, sizeof(uint32_t));
+        *state = XDG_SURFACE_STATE_MAXIMIZED;
+    }
+    else if (shsurf->next_type == SHELL_SURFACE_TYPE_FULLSCREEN)
+    {
+        state  = wl_array_add(&states, sizeof(uint32_t));
+        *state = XDG_SURFACE_STATE_FULLSCREEN;
+    }
+
+    /* TODO: XDG_SURFACE_STATE_RESIZING, XDG_SURFACE_STATE_ACTIVATED */
+
+    /* Send configure event */
+    display = pepper_compositor_get_display(shsurf->shell->compositor);
+    serial  = wl_display_next_serial(display);
+
+    xdg_surface_send_configure(shsurf->resource,
+                               width,
+                               height,
+                               &states,
+                               serial);
+
+    wl_array_release(&states);
+
+    shsurf->ack_configure = PEPPER_FALSE;
+}
+
+static void
+shsurf_xdg_popup_send_configure(shell_surface_t *shsurf, int32_t width, int32_t height)
+{
+    /* Do nothing */
+}
+
+static pepper_bool_t
+shsurf_is_wl_shell_surface(shell_surface_t *shsurf)
+{
+    return (shsurf->send_configure == shsurf_wl_shell_surface_send_configure);
+}
+
+static pepper_bool_t
+shsurf_is_xdg_surface(shell_surface_t *shsurf)
+{
+    return (shsurf->send_configure == shsurf_xdg_surface_send_configure);
+}
+
+static pepper_bool_t
+shsurf_is_xdg_popup(shell_surface_t *shsurf)
+{
+    return (shsurf->send_configure == shsurf_xdg_popup_send_configure);
+}
+
 shell_surface_t *
 shell_surface_create(shell_client_t *shell_client, pepper_surface_t *surface,
                      struct wl_client *client, const struct wl_interface *interface,
                      const void *implementation, uint32_t version, uint32_t id)
 {
     shell_surface_t     *shsurf = NULL;
+    const char          *role = NULL;
 
     shsurf = calloc(1, sizeof(shell_surface_t));
     if (!shsurf)
@@ -125,9 +195,6 @@ shell_surface_create(shell_client_t *shell_client, pepper_surface_t *surface,
 
     wl_resource_set_implementation(shsurf->resource, implementation, shsurf, handle_resource_destroy);
 
-    shsurf->client_destroy_listener.notify = handle_client_destroy;
-    wl_client_add_destroy_listener(client, &shsurf->client_destroy_listener);
-
     shsurf->surface_destroy_listener.notify = handle_surface_destroy;
     pepper_object_add_destroy_listener((pepper_object_t *)surface, &shsurf->surface_destroy_listener);
 
@@ -140,6 +207,15 @@ shell_surface_create(shell_client_t *shell_client, pepper_surface_t *surface,
     wl_list_init(&shsurf->link);
     wl_list_insert(&shsurf->shell->shell_surface_list, &shsurf->link);
 
+    role = pepper_surface_get_role(shsurf->surface);
+
+    if (!strcmp(role, "wl_shell_surface"))
+        shsurf->send_configure = shsurf_wl_shell_surface_send_configure;
+    else if (!strcmp(role, "xdg_surface"))
+        shsurf->send_configure = shsurf_xdg_surface_send_configure;
+    else if (!strcmp(role, "xdg_popup"))
+        shsurf->send_configure = shsurf_xdg_popup_send_configure;
+
     return shsurf;
 
 error:
@@ -166,7 +242,6 @@ shell_surface_ping(shell_surface_t *shsurf)
 {
     shell_client_t      *shell_client = shsurf->shell_client;
     struct wl_display   *display;
-    const char          *role;
 
     /* Already stucked, do not send another ping */
     if (shell_client->irresponsive)
@@ -195,14 +270,10 @@ shell_surface_ping(shell_surface_t *shsurf)
     shell_client->ping_serial = wl_display_next_serial(display);
     shell_client->need_pong   = PEPPER_TRUE;
 
-    role = pepper_surface_get_role(shsurf->surface);
-
-    if (!strcmp(role, "wl_shell_surface"))
+    if (shsurf_is_wl_shell_surface(shsurf))
         wl_shell_surface_send_ping(shsurf->resource, shell_client->ping_serial);
-    else if (!strcmp(role, "xdg_surface") || !strcmp(role, "xdg_popup"))
+    else if (shsurf_is_xdg_surface(shsurf) || shsurf_is_xdg_popup(shsurf))
         xdg_shell_send_ping(shell_client->resource, shell_client->ping_serial);
-    else
-        PEPPER_ASSERT(0);
 }
 
 void
@@ -227,6 +298,10 @@ shell_surface_handle_pong(shell_surface_t *shsurf, uint32_t serial)
     shell_client_handle_pong(shsurf->shell_client, serial);
 }
 
+/* XXX: Temporary code for test, to be deleted */
+static void
+shell_surface_map_toplevel(shell_surface_t *shsurf);
+
 void
 shell_surface_set_toplevel(shell_surface_t *shsurf)
 {
@@ -235,7 +310,8 @@ shell_surface_set_toplevel(shell_surface_t *shsurf)
     shell_surface_set_type(shsurf, SHELL_SURFACE_TYPE_TOPLEVEL);
 
     /* Need to map in later */
-    shsurf->mapped = PEPPER_FALSE;
+    /* XXX: Temporary code for test, to be deleted */
+    shell_surface_map_toplevel(shsurf);
 }
 
 void
@@ -272,90 +348,125 @@ shell_surface_set_transient(shell_surface_t     *shsurf,
     shell_surface_set_type(shsurf, SHELL_SURFACE_TYPE_TRANSIENT);
 }
 
-static void
-shell_surface_set_position(shell_surface_t *shsurf, int32_t x, int32_t y)
+static pepper_output_t *
+shell_surface_get_output(shell_surface_t *shsurf)
 {
-    pepper_view_set_position(shsurf->view, x, y);
-}
+    pepper_output_t *output = NULL;
 
-static void
-shell_surface_map_toplevel(shell_surface_t *shsurf)
-{
-    int32_t x = 0, y = 0;
+    /* TODO: Find the output on which the surface has the biggest surface area */
 
-    /**
-     * TODO: To placing view, need to get output's size, position and seat->pointer's position
-     *       or, read from config file
-     */
+    return output;
+}
 
-    shell_surface_set_position(shsurf, x, y);
+void
+shell_surface_get_geometry(shell_surface_t *shsurf, pixman_rectangle32_t *geometry)
+{
+    double x, y;
+    int    w, h;
 
-    pepper_view_map(shsurf->view);
+    pepper_view_get_position(shsurf->view, &x, &y);
+    pepper_view_get_size(shsurf->view, &w, &h);
 
-    shsurf->mapped = PEPPER_TRUE;
+    geometry->x      = (int32_t)x;
+    geometry->y      = (int32_t)y;
+    geometry->width  = (uint32_t)w;
+    geometry->height = (uint32_t)h;
 }
 
-static void
-shell_surface_map_popup(shell_surface_t *shsurf)
+void
+shell_surface_set_maximized(shell_surface_t     *shsurf,
+                            pepper_output_t     *output)
 {
-    shell_surface_t *parent = get_shsurf_from_surface(shsurf->parent, shsurf->shell);
+    pixman_rectangle32_t area;
 
-    /* Set position as relatively */
-    pepper_view_set_parent(shsurf->view, parent->view);
-    shell_surface_set_position(shsurf, shsurf->popup.x, shsurf->popup.y);
+    /* XXX: If the given shell_surface has a parent, what's the corrent behavior? */
+    shell_surface_set_parent(shsurf, NULL);
 
-    pepper_view_map(shsurf->view);
+    /*  If the client does not specify the output then the compositor will apply its policy */
+    if (!output)
+        output = shell_surface_get_output(shsurf);
 
-    pepper_view_stack_top(shsurf->view, PEPPER_TRUE);
+    shsurf->maximized.output = output;
 
-    /* TODO: add_popup_grab(), but how? */
+    /* Save current position and size for unset_maximized */
+    shell_surface_get_geometry(shsurf, &area);
+    shsurf->saved.x = area.x;
+    shsurf->saved.y = area.y;
+    shsurf->saved.w = area.width;
+    shsurf->saved.h = area.height;
+
+    shell_get_output_workarea(shsurf->shell, output, &area);
+
+    shell_surface_set_type(shsurf, SHELL_SURFACE_TYPE_MAXIMIZED);
+
+    /* Send configure */
+    shsurf->send_configure(shsurf, area.width, area.height);
 }
 
-static void
-shell_surface_map_transient(shell_surface_t *shsurf)
+void
+shell_surface_unset_maximized(shell_surface_t *shsurf)
 {
-    shell_surface_t *parent = get_shsurf_from_surface(shsurf->parent, shsurf->shell);
-    double x, y;
+    /* TODO */
+    shell_surface_set_toplevel(shsurf);
+}
 
-    pepper_view_get_position(parent->view, &x, &y);
+void
+shell_surface_set_fullscreen(shell_surface_t    *shsurf,
+                             pepper_output_t    *output,
+                             uint32_t            method,
+                             uint32_t            framerate)
+{
+    const pepper_output_geometry_t      *geom;
+    pixman_rectangle32_t                 area;
 
-    pepper_view_set_parent(shsurf->view, parent->view);
+    /* XXX: If the given shell_surface has a parent, what's the corrent behavior? */
+    shell_surface_set_parent(shsurf, NULL);
 
-    shell_surface_set_position(shsurf,
-                               x + shsurf->transient.x,
-                               y + shsurf->transient.y);
+    /*  If the client does not specify the output then the compositor will apply its policy */
+    if (!output)
+        output = shell_surface_get_output(shsurf);
 
-    if (shsurf->transient.flags != WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
-    {
-        /* TODO: set keyboard focus to view */
-    }
+    shsurf->fullscreen.output    = output;
+    shsurf->fullscreen.method    = method;
+    shsurf->fullscreen.framerate = framerate;
 
-    pepper_view_map(shsurf->view);
+    shell_surface_set_type(shsurf, SHELL_SURFACE_TYPE_FULLSCREEN);
+
+    /* Save current position and size for unset_fullscreen */
+    shell_surface_get_geometry(shsurf, &area);
+    shsurf->saved.x = area.x;
+    shsurf->saved.y = area.y;
+    shsurf->saved.w = area.width;
+    shsurf->saved.h = area.height;
+
+    geom = pepper_output_get_geometry(output);
+
+    /* Send configure */
+    shsurf->send_configure(shsurf, geom->w, geom->h);
 }
 
 void
-shell_surface_set_type(shell_surface_t *shsurf, shell_surface_type_t type)
+shell_surface_unset_fullscreen(shell_surface_t *shsurf)
 {
-    shsurf->type = type;
+    shell_surface_set_toplevel(shsurf);
+}
 
-    switch (type)
-    {
-    case SHELL_SURFACE_TYPE_NONE:
-        shsurf->shell_surface_map = NULL;
-        break;
-    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;
-    case SHELL_SURFACE_TYPE_TRANSIENT:
-        shsurf->shell_surface_map = shell_surface_map_transient;
-        break;
-    default :
-        /* XXX: Maybe some logs be needed */
-        break;
-    }
+void
+shell_surface_set_minimized(shell_surface_t *shsurf)
+{
+    shell_surface_set_type(shsurf, SHELL_SURFACE_TYPE_MINIMIZED);
+}
+
+void
+shell_surface_ack_configure(shell_surface_t *shsurf, uint32_t serial)
+{
+    shsurf->ack_configure = PEPPER_TRUE;
+}
+
+static void
+shell_surface_set_position(shell_surface_t *shsurf, int32_t x, int32_t y)
+{
+    pepper_view_set_position(shsurf->view, x, y);
 }
 
 shell_surface_t *
@@ -384,10 +495,24 @@ shell_surface_set_parent(shell_surface_t *shsurf, pepper_surface_t *parent)
     {
         parent_shsurf = get_shsurf_from_surface(parent, shsurf->shell);
         if (parent_shsurf)
+        {
             wl_list_insert(&parent_shsurf->child_list, &shsurf->parent_link);
+            pepper_view_set_parent(shsurf->view, parent_shsurf->view);
+        }
+    }
+    else
+    {
+        pepper_view_set_parent(shsurf->view, NULL);
     }
 }
 
+void
+shell_surface_set_geometry(shell_surface_t *shsurf, int32_t x, int32_t y, int32_t w, int32_t h)
+{
+    pepper_view_set_position(shsurf->view, (double)x, (double)y);
+    pepper_view_resize(shsurf->view, w, h);
+}
+
 pepper_bool_t
 shell_surface_set_title(shell_surface_t *shsurf, const char* title)
 {
@@ -415,3 +540,274 @@ shell_surface_set_class(shell_surface_t *shsurf, const char* class_)
 
     return PEPPER_TRUE;
 }
+
+static void
+shell_surface_map_toplevel(shell_surface_t *shsurf)
+{
+    int32_t x = 0, y = 0, w = 0, h = 0;
+
+    /* Restore original geometry */
+    if (shsurf->type == SHELL_SURFACE_TYPE_FULLSCREEN ||
+        shsurf->type == SHELL_SURFACE_TYPE_MAXIMIZED  ||
+        shsurf->type == SHELL_SURFACE_TYPE_MINIMIZED)
+    {
+        x = shsurf->saved.x;
+        y = shsurf->saved.y;
+
+        pepper_view_resize(shsurf->view, shsurf->saved.w, shsurf->saved.h);
+
+        if (shsurf->type == SHELL_SURFACE_TYPE_FULLSCREEN)
+        {
+            /* TODO: pepper_surface_destroy(shsurf->fullscreen.background_surface); */
+            pepper_view_destroy(shsurf->fullscreen.background_view);
+
+            shsurf->fullscreen.background_surface = NULL;
+            shsurf->fullscreen.background_view    = NULL;
+        }
+    }
+    else
+    {
+        /**
+         * TODO: To get view's initial position, need to know output's size, position
+         *       seat->pointer's position, or read from config file
+         */
+    }
+
+    shell_surface_set_position(shsurf, x, y);
+
+    pepper_view_map(shsurf->view);
+
+    shsurf->mapped    = PEPPER_TRUE;
+    shsurf->type      = SHELL_SURFACE_TYPE_TOPLEVEL;
+    shsurf->next_type = SHELL_SURFACE_TYPE_NONE;
+}
+
+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);
+
+    pepper_view_stack_top(shsurf->view, PEPPER_TRUE);
+
+    /* TODO: add_popup_grab(), but how? */
+
+    shsurf->mapped    = PEPPER_TRUE;
+    shsurf->type      = SHELL_SURFACE_TYPE_POPUP;
+    shsurf->next_type = SHELL_SURFACE_TYPE_NONE;
+}
+
+static void
+shell_surface_map_transient(shell_surface_t *shsurf)
+{
+    shell_surface_t *parent = get_shsurf_from_surface(shsurf->parent, shsurf->shell);
+    double x, y;
+
+    pepper_view_get_position(parent->view, &x, &y);
+
+    pepper_view_set_parent(shsurf->view, parent->view);
+
+    shell_surface_set_position(shsurf,
+                               x + shsurf->transient.x,
+                               y + shsurf->transient.y);
+
+    if (shsurf->transient.flags != WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
+    {
+        /* TODO: set keyboard focus to view */
+    }
+
+    pepper_view_map(shsurf->view);
+
+    shsurf->mapped    = PEPPER_TRUE;
+    shsurf->type      = SHELL_SURFACE_TYPE_TRANSIENT;
+    shsurf->next_type = SHELL_SURFACE_TYPE_NONE;
+}
+
+static void
+shell_surface_map_maximized(shell_surface_t *shsurf)
+{
+    pixman_rectangle32_t area;
+
+    shell_get_output_workarea(shsurf->shell, shsurf->maximized.output, &area);
+
+    shell_surface_set_position(shsurf, area.x, area.y);
+
+    pepper_view_map(shsurf->view);
+
+    /* Set top of z-order */
+    pepper_view_stack_top(shsurf->view, PEPPER_TRUE /*FIXME:*/);
+}
+
+static void
+shell_surface_map_minimized(shell_surface_t *shsurf)
+{
+    /* TODO */
+    pepper_view_unmap(shsurf->view);
+
+    shsurf->mapped    = PEPPER_TRUE;
+    shsurf->type      = SHELL_SURFACE_TYPE_MINIMIZED;
+    shsurf->next_type = SHELL_SURFACE_TYPE_NONE;
+}
+
+static float
+get_scale(float output_w, float output_h, float view_w, float view_h)
+{
+    float scale, output_aspect, view_aspect;
+
+    output_aspect = output_w / output_h;
+
+    view_aspect = view_w / view_h;
+
+    if (output_aspect < view_aspect)
+        scale = output_w / view_w;
+    else
+        scale = output_h / view_h;
+
+    return scale;
+}
+
+static void
+shell_surface_center_on_output_by_scale(shell_surface_t                 *shsurf,
+                                        const pepper_output_geometry_t  *output,
+                                        pixman_rectangle32_t            *surface_geom,
+                                        float                            scale)
+{
+    float x, y;
+
+    x = output->x + (output->w - surface_geom->width  * scale) / 2 - surface_geom->x;
+    y = output->y + (output->h - surface_geom->height * scale) / 2 - surface_geom->y;
+
+    shell_surface_set_position(shsurf, x, y);
+}
+
+static void
+switch_output_mode(pepper_output_t *output, pepper_output_mode_t *mode)
+{
+    pepper_output_mode_t *new_mode;
+
+    /* TODO: Find the output mode to the smallest mode that can fit */
+
+    pepper_output_set_mode(output, new_mode);
+}
+
+static void
+shell_surface_map_fullscreen(shell_surface_t *shsurf)
+{
+    pepper_output_t                     *output;
+    const pepper_output_geometry_t      *output_geom;
+    pixman_rectangle32_t                 shsurf_geom;
+    float                                scale = 0.f;
+
+    output      = shsurf->fullscreen.output;
+    output_geom = pepper_output_get_geometry(output);
+
+    /* Get current geometry */
+    shell_surface_get_geometry(shsurf, &shsurf_geom);
+
+    switch (shsurf->fullscreen.method)
+    {
+    case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
+        {
+            scale = get_scale(output_geom->w, output_geom->h, shsurf_geom.width, shsurf_geom.height);
+        }
+        break;
+    case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
+        {
+            pepper_output_mode_t mode;
+            int32_t              buffer_scale;
+
+            buffer_scale = pepper_surface_get_buffer_scale(shsurf->surface);
+
+            mode.w       = shsurf_geom.width  * buffer_scale;
+            mode.h       = shsurf_geom.height * buffer_scale;
+            mode.refresh = shsurf->fullscreen.framerate;
+
+            switch_output_mode(output, &mode);
+
+            /* Recalculate output geometry */
+            output_geom = pepper_output_get_geometry(output);
+
+            scale = 1.f;
+        }
+        break;
+    case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
+    case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
+        {
+            scale = 1.f;
+        }
+        break;
+    default:
+        PEPPER_ERROR("invalid method type = 0x%x\n", shsurf->fullscreen.method);
+        break;
+    }
+
+    /* TODO: Create background black view */
+    {
+        pepper_surface_t *surface;
+
+        /**
+         * surface->x = output_geom->w;
+         * surface->y = output_geom->y;
+         */
+
+        shsurf->fullscreen.background_surface = surface;
+        shsurf->fullscreen.background_view =
+            pepper_compositor_add_surface_view(shsurf->shell->compositor, surface);
+    }
+
+    /* Place background black view */
+    pepper_view_set_position(shsurf->fullscreen.background_view, output_geom->x, output_geom->y);
+    pepper_view_map(shsurf->fullscreen.background_view);
+    pepper_view_stack_top(shsurf->fullscreen.background_view, PEPPER_TRUE /*FIXME*/ );
+
+    /* Place target view */
+    shell_surface_center_on_output_by_scale(shsurf, output_geom, &shsurf_geom, scale);
+    pepper_view_map(shsurf->view);
+    pepper_view_stack_top(shsurf->view, PEPPER_TRUE /*FIXME*/ );
+}
+
+void
+shell_surface_set_type(shell_surface_t *shsurf, shell_surface_type_t type)
+{
+    if (shsurf->type == type )
+        return;
+
+    if (shsurf->next_type == type)
+        return ;
+
+    switch (type)
+    {
+    case SHELL_SURFACE_TYPE_NONE:
+        shsurf->shell_surface_map = NULL;
+        break;
+    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;
+    case SHELL_SURFACE_TYPE_TRANSIENT:
+        shsurf->shell_surface_map = shell_surface_map_transient;
+        break;
+    case SHELL_SURFACE_TYPE_MAXIMIZED:
+        shsurf->shell_surface_map = shell_surface_map_maximized;
+        break;
+    case SHELL_SURFACE_TYPE_FULLSCREEN:
+        shsurf->shell_surface_map = shell_surface_map_fullscreen;
+        break;
+    case SHELL_SURFACE_TYPE_MINIMIZED:
+        shsurf->shell_surface_map = shell_surface_map_minimized;
+        break;
+    default :
+        PEPPER_ERROR("invalid surface type = 0x%x\n", type);
+        return ;
+    }
+
+    shsurf->next_type = type;
+    shsurf->mapped    = PEPPER_FALSE;
+}
index 9ef24af..9720b7d 100644 (file)
@@ -1,6 +1,29 @@
 #include "desktop-shell-internal.h"
 #include <stdlib.h>
 
+void
+shell_get_output_workarea(desktop_shell_t       *shell,
+                          pepper_output_t       *output,
+                          pixman_rectangle32_t  *area)
+{
+    const pepper_output_geometry_t *geom;
+
+    /**
+     ** TODO: Get given output's workarea size and position in global coordinate
+     **      return (output_size - (panel_size + margin + caption + ... ));
+     **/
+
+    geom = pepper_output_get_geometry(output);
+
+    if (area)
+    {
+        area->x = geom->x;
+        area->y = geom->y;
+        area->width = geom->w;
+        area->height = geom->h;
+    }
+}
+
 static void
 handle_shell_client_destroy(struct wl_listener *listener, void *data)
 {
@@ -74,5 +97,13 @@ pepper_desktop_shell_init(pepper_compositor_t *compositor)
         return PEPPER_FALSE;
     }
 
+    if (!init_xdg_shell(shell))
+    {
+        PEPPER_ERROR("wl_shell initialize failed\n");
+        fini_wl_shell(shell);
+        free(shell);
+        return PEPPER_FALSE;
+    }
+
     return PEPPER_TRUE;
 }
index e4d037b..0d9b5e9 100644 (file)
@@ -45,10 +45,19 @@ wl_shell_surface_set_transient(struct wl_client     *client,
 }
 
 static void
-wl_shell_surface_set_fullscreen(struct wl_client *client, struct wl_resource *resource,
-                             uint32_t method, uint32_t framerate, struct wl_resource *output)
+wl_shell_surface_set_fullscreen(struct wl_client    *client,
+                                struct wl_resource  *resource,
+                                uint32_t             method,
+                                uint32_t             framerate,
+                                struct wl_resource  *output_resource)
 {
-    /* TODO */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+    pepper_output_t *output = NULL;
+
+    if (output_resource)
+        output = wl_resource_get_user_data(output_resource);
+
+    shell_surface_set_fullscreen(shsurf, output, method, framerate);
 }
 
 static void
@@ -88,7 +97,13 @@ static void
 wl_shell_surface_set_maximized(struct wl_client *client, struct wl_resource *resource,
                             struct wl_resource *output_res)
 {
-    /* TODO */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+    pepper_output_t *output = NULL;
+
+    if (output_res)
+        output = wl_resource_get_user_data(output_res);
+
+    shell_surface_set_maximized(shsurf, output);
 }
 
 static void
index 4a87f58..fe4c380 100644 (file)
@@ -5,7 +5,7 @@ static void
 xdg_surface_destroy(struct wl_client    *client,
                     struct wl_resource  *resource)
 {
-    /* TODO: */
+    wl_resource_destroy(resource);
 }
 
 static void
@@ -13,7 +13,18 @@ xdg_surface_set_parent(struct wl_client     *client,
                        struct wl_resource   *resource,
                        struct wl_resource   *parent_resource)
 {
-    /* TODO: */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+    shell_surface_t *parent = NULL;
+
+    if (parent_resource)
+    {
+        parent = wl_resource_get_user_data(resource);
+        shell_surface_set_parent(shsurf, parent->surface);
+    }
+    else
+    {
+        shell_surface_set_parent(shsurf, NULL);
+    }
 }
 
 static void
@@ -71,7 +82,9 @@ xdg_surface_ack_configure(struct wl_client      *client,
                           struct wl_resource    *resource,
                           uint32_t               serial)
 {
-    /* TODO: */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+    shell_surface_ack_configure(shsurf, serial);
 }
 
 static void
@@ -82,21 +95,27 @@ xdg_surface_set_window_geometry(struct wl_client    *client,
                                 int32_t              width,
                                 int32_t              height)
 {
-    /* TODO: */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+    shell_surface_set_geometry(shsurf, x, y, width, height);
 }
 
 static void
 xdg_surface_set_maximized(struct wl_client      *client,
                           struct wl_resource    *resource)
 {
-    /* TODO: */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+    shell_surface_set_maximized(shsurf, NULL);
 }
 
 static void
 xdg_surface_unset_maximized(struct wl_client    *client,
                             struct wl_resource  *resource)
 {
-    /* TODO: */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+    shell_surface_unset_maximized(shsurf);
 }
 
 static void
@@ -104,21 +123,31 @@ xdg_surface_set_fullscreen(struct wl_client     *client,
                            struct wl_resource   *resource,
                            struct wl_resource   *output_resource)
 {
-    /* TODO: */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+    pepper_output_t *output = NULL;
+
+    if (output_resource)
+        output = wl_resource_get_user_data(output_resource);
+
+    shell_surface_set_fullscreen(shsurf, output, 0, 0);
 }
 
 static void
 xdg_surface_unset_fullscreen(struct wl_client   *client,
                              struct wl_resource *resource)
 {
-    /* TODO: */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+    shell_surface_unset_fullscreen(shsurf);
 }
 
 static void
 xdg_surface_set_minimized(struct wl_client      *client,
                           struct wl_resource    *resource)
 {
-    /* TODO: */
+    shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+
+    shell_surface_set_minimized(shsurf);
 }
 
 static const struct xdg_surface_interface xdg_surface_implementation =
@@ -144,6 +173,7 @@ xdg_shell_destroy(struct wl_client   *client,
                   struct wl_resource *resource)
 {
     /* TODO: */
+    wl_resource_destroy(resource);
 }
 
 static void
@@ -185,7 +215,6 @@ static void
 xdg_popup_destroy(struct wl_client *client,
                   struct wl_resource *resource)
 {
-    /* TODO: */
     wl_resource_destroy(resource);
 }