Replace shell interface, 'zxdg_shell_v6 interface' 17/186417/5 accepted/tizen_5.0_unified tizen_5.0 accepted/tizen/5.0/unified/20181102.023719 accepted/tizen/unified/20180810.031357 submit/tizen/20180810.014726 submit/tizen_5.0/20181101.000005
authorSeunghun Lee <shiin.lee@samsung.com>
Thu, 9 Aug 2018 11:17:12 +0000 (20:17 +0900)
committerSeunghun Lee <shiin.lee@samsung.com>
Fri, 10 Aug 2018 01:45:56 +0000 (10:45 +0900)
'Ecore_Wl2' uses zxdg_shell_v6_interface.

Change-Id: Ie42ddcbb8816e4ecf0321d170f4f5d49e1c14070

configure.ac
packaging/libpepper-efl.spec
src/lib/object.c
src/lib/private.h
src/lib/shell.c
src/lib/shell.h

index 15918679c7f80644f61b5e74ba22babb4d7624dc..025b854028016ba8226fdf0ff2cf85b1469ee2cf 100644 (file)
@@ -14,7 +14,7 @@ AC_PROG_LIBTOOL
 
 # Checks for libraries.
 PKG_CHECK_MODULES([PEPPER], [pepper pepper-xkb])
-PKG_CHECK_MODULES([WAYLAND], [wayland-server xdg-shell-unstable-v5-server tizen-extension-client])
+PKG_CHECK_MODULES([WAYLAND], [wayland-server xdg-shell-unstable-v6-server tizen-extension-client])
 PKG_CHECK_MODULES([EFL], [eina ecore ecore-input evas ecore-wl2])
 PKG_CHECK_MODULES([WAYLAND_TBM], [wayland-tbm-server])
 
index ae3ce2dadbb6e21760451efdeac8af9bebe46d86..187707171605a0396717d8dd9d5365110542a491 100644 (file)
@@ -12,12 +12,13 @@ BuildRequires: pkgconfig(wayland-server)
 BuildRequires: pkgconfig(pepper)
 BuildRequires: pkgconfig(pepper-xkb)
 BuildRequires: pkgconfig(elementary)
-BuildRequires: pkgconfig(xdg-shell-unstable-v5-server)
+BuildRequires: pkgconfig(xdg-shell-unstable-v6-server)
 BuildRequires: pkgconfig(xkbcommon)
 BuildRequires: pkgconfig(tizen-extension-client)
 BuildRequires: pkgconfig(ecore-wl2)
 BuildRequires: pkgconfig(wayland-tbm-server)
 BuildRequires: pkgconfig(wayland-tbm-client)
+
 Requires: libwayland-extension-server
 Requires: pepper-xkb
 
index 80b9afe7f3139478be12439bdd13ad6e120554e6..72fa1052ff0caba1a53ebbb9cd348a04d62258b1 100644 (file)
@@ -78,8 +78,6 @@ _pepper_efl_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
 static void
 _pepper_efl_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
 {
-   pepper_efl_shell_surface_t *shsurf = NULL;
-
    OBJ_DATA_GET;
 
    DBG("[OBJECT] Resize: obj: %p, w %d, h %d", obj, w, h);
@@ -90,20 +88,12 @@ _pepper_efl_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
    if (!po->surface)
      return;
 
-   shsurf =
-      pepper_object_get_user_data((pepper_object_t *)po->surface,
-                                  pepper_surface_get_role(po->surface));
-   if (!shsurf)
-     return;
-
-   pepper_efl_shell_configure(shsurf, w, h, NULL, NULL);
+   pepper_efl_shell_configure(po->surface, w, h);
 }
 
 static void
 _pepper_efl_smart_show(Evas_Object *obj)
 {
-   pepper_efl_shell_surface_t *shsurf;
-
    OBJ_DATA_GET;
 
    DBG("[OBJECT] Show: obj %p", obj);
@@ -111,17 +101,7 @@ _pepper_efl_smart_show(Evas_Object *obj)
    if (!po->surface)
      return;
 
-   shsurf = pepper_object_get_user_data((pepper_object_t *)po->surface,
-                                        pepper_surface_get_role(po->surface));
-   if (!shsurf)
-     return;
-
-   if (!shsurf->mapped)
-     {
-        shsurf->mapped = EINA_TRUE;
-        pepper_view_map(shsurf->view);
-     }
-
+   pepper_efl_shell_map(po->surface);
    evas_object_show(po->img);
    evas_object_show(po->clip);
 }
@@ -129,8 +109,6 @@ _pepper_efl_smart_show(Evas_Object *obj)
 static void
 _pepper_efl_smart_hide(Evas_Object *obj)
 {
-   pepper_efl_shell_surface_t *shsurf;
-
    OBJ_DATA_GET;
 
    DBG("[OBJECT] Hide: obj %p", obj);
@@ -138,17 +116,7 @@ _pepper_efl_smart_hide(Evas_Object *obj)
    if (!po->surface)
      return;
 
-   shsurf = pepper_object_get_user_data((pepper_object_t *)po->surface,
-                                        pepper_surface_get_role(po->surface));
-   if (!shsurf)
-     return;
-
-   if (shsurf->mapped)
-     {
-        shsurf->mapped = EINA_FALSE;
-        pepper_view_unmap(shsurf->view);
-     }
-
+   pepper_efl_shell_unmap(po->surface);
    evas_object_hide(po->img);
    evas_object_hide(po->clip);
 }
@@ -219,7 +187,7 @@ _pepper_efl_smart_init(void)
 static void
 _touch_down(pepper_efl_object_t *po, unsigned int timestamp, int device, int x, int y)
 {
-   pepper_efl_shell_surface_t *shsurf;
+   pepper_view_t *view;
    int rel_x, rel_y;
 
    rel_x = x - po->x;
@@ -230,38 +198,36 @@ _touch_down(pepper_efl_object_t *po, unsigned int timestamp, int device, int x,
    if (!po->surface)
      return;
 
-   shsurf = pepper_object_get_user_data((pepper_object_t *)po->surface,
-                                        pepper_surface_get_role(po->surface));
-   if (!shsurf)
+   view = pepper_efl_shell_pepper_view_get(po->surface);
+   if (!view)
      return;
 
    pepper_touch_add_point(po->input.touch, device, rel_x, rel_y);
-   pepper_touch_send_down(po->input.touch, shsurf->view, timestamp, device, rel_x, rel_y);
+   pepper_touch_send_down(po->input.touch, view, timestamp, device, rel_x, rel_y);
 }
 
 static void
 _touch_up(pepper_efl_object_t *po, unsigned int timestamp, int device)
 {
-   pepper_efl_shell_surface_t *shsurf;
+   pepper_view_t *view;
 
    DBG("Touch (%d) Up: obj %p", device, po->smart_obj);
 
    if (!po->surface)
      return;
 
-   shsurf = pepper_object_get_user_data((pepper_object_t *)po->surface,
-                                        pepper_surface_get_role(po->surface));
-   if (!shsurf)
+   view = pepper_efl_shell_pepper_view_get(po->surface);
+   if (!view)
      return;
 
-   pepper_touch_send_up(po->input.touch, shsurf->view, timestamp, device);
+   pepper_touch_send_up(po->input.touch, view, timestamp, device);
    pepper_touch_remove_point(po->input.touch, device);
 }
 
 static void
 _touch_move(pepper_efl_object_t *po, unsigned int timestamp, int device, int x, int y)
 {
-   pepper_efl_shell_surface_t *shsurf;
+   pepper_view_t *view;
    int rel_x, rel_y;
 
    rel_x = x - po->x;
@@ -271,9 +237,8 @@ _touch_move(pepper_efl_object_t *po, unsigned int timestamp, int device, int x,
    if (!po->surface)
      return;
 
-   shsurf = pepper_object_get_user_data((pepper_object_t *)po->surface,
-                                        pepper_surface_get_role(po->surface));
-   if (!shsurf)
+   view = pepper_efl_shell_pepper_view_get(po->surface);
+   if (!view)
      return;
 
    if ((!_need_send_motion) && (!_need_send_released))
@@ -288,7 +253,7 @@ _touch_move(pepper_efl_object_t *po, unsigned int timestamp, int device, int x,
     * point will be removed when touch up or cancel is happen.
     */
    pepper_touch_add_point(po->input.touch, device, rel_x, rel_y);
-   pepper_touch_send_motion(po->input.touch, shsurf->view, timestamp, device, rel_x, rel_y);
+   pepper_touch_send_motion(po->input.touch, view, timestamp, device, rel_x, rel_y);
 }
 
 static void
@@ -398,22 +363,20 @@ static void
 _pepper_efl_object_evas_cb_focus_in(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    pepper_efl_object_t *po = data;
-   pepper_efl_shell_surface_t *shsurf;
-   pepper_view_t *focused_view;
+   pepper_view_t *view, *focused_view;
 
    if (!po->surface)
      return;
 
-   shsurf = pepper_object_get_user_data((pepper_object_t *)po->surface,
-                                        pepper_surface_get_role(po->surface));
-   if ((!shsurf) || (!shsurf->view))
+   view = pepper_efl_shell_pepper_view_get(po->surface);
+   if (!view)
      return;
 
-   DBG("[OBJECT] Focus In: obj %p, shsurf %p", obj, shsurf);
+   DBG("[OBJECT] Focus In: obj %p", obj);
 
    focused_view = pepper_keyboard_get_focus(po->input.kbd);
 
-   if (shsurf->view == focused_view)
+   if (view == focused_view)
      {
         // already focused view.
         return;
@@ -426,30 +389,28 @@ _pepper_efl_object_evas_cb_focus_in(void *data, Evas *evas EINA_UNUSED, Evas_Obj
      }
 
    // replace focused view.
-   pepper_keyboard_set_focus(po->input.kbd, shsurf->view);
+   pepper_keyboard_set_focus(po->input.kbd, view);
    // send enter message for newly focused view.
-   pepper_keyboard_send_enter(po->input.kbd, shsurf->view);
+   pepper_keyboard_send_enter(po->input.kbd, view);
 }
 
 static void
 _pepper_efl_object_evas_cb_focus_out(void *data EINA_UNUSED, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
 {
    pepper_efl_object_t *po = data;
-   pepper_efl_shell_surface_t *shsurf;
-   pepper_view_t *view;
+   pepper_view_t *view, *focused_view;
 
    if (!po->surface)
      return;
 
-   shsurf = pepper_object_get_user_data((pepper_object_t *)po->surface,
-                                        pepper_surface_get_role(po->surface));
-   if (!shsurf)
+   view = pepper_efl_shell_pepper_view_get(po->surface);
+   if (!view)
      return;
 
-   DBG("[OBJECT] Focus Out: obj %p, shsurf %p", obj, shsurf);
+   DBG("[OBJECT] Focus Out: obj %p", obj);
 
-   view = pepper_keyboard_get_focus(po->input.kbd);
-   if ((!view) || (shsurf->view != view))
+   focused_view = pepper_keyboard_get_focus(po->input.kbd);
+   if ((!focused_view) || (view != focused_view))
      {
         // I expect that already sends 'leave' message to this view,
         // when focus view is changed in _cb_focus_in().
@@ -458,7 +419,7 @@ _pepper_efl_object_evas_cb_focus_out(void *data EINA_UNUSED, Evas *evas EINA_UNU
      }
 
    // send leave message for pre-focused view.
-   pepper_keyboard_send_leave(po->input.kbd, view);
+   pepper_keyboard_send_leave(po->input.kbd, focused_view);
    // unset focus view.
    pepper_keyboard_set_focus(po->input.kbd, NULL);
 }
@@ -714,20 +675,13 @@ pepper_efl_object_title_get(Evas_Object *obj)
 {
    OBJ_DATA_GET NULL;
 
-   pepper_efl_shell_surface_t *shsurf = NULL;
    pepper_surface_t *surface = NULL;
    const char *title = NULL;
 
    surface = po->surface;
 
    if (surface)
-     {
-        shsurf = pepper_object_get_user_data((pepper_object_t *)surface,
-                                             pepper_surface_get_role(surface));
-
-        if (shsurf)
-          title = shsurf->title;
-     }
+     title = pepper_efl_shell_title_get(surface);
 
    if (title)
      DBG("[OBJECT] Title Get : %s", title);
@@ -740,20 +694,13 @@ pepper_efl_object_app_id_get(Evas_Object *obj)
 {
    OBJ_DATA_GET NULL;
 
-   pepper_efl_shell_surface_t *shsurf = NULL;
    pepper_surface_t *surface = NULL;
    const char *app_id = NULL;
 
    surface = po->surface;
 
    if (surface)
-     {
-        shsurf = pepper_object_get_user_data((pepper_object_t *)surface,
-                                             pepper_surface_get_role(surface));
-
-        if (shsurf)
-          app_id = shsurf->app_id;
-     }
+     app_id = pepper_efl_shell_app_id_get(surface);
 
    if (app_id)
      DBG("[OBJECT] App_id Get : %s", app_id);
@@ -766,7 +713,7 @@ pepper_efl_object_touch_cancel(Evas_Object *obj)
 {
    OBJ_DATA_GET EINA_FALSE;
 
-   pepper_efl_shell_surface_t *shsurf;
+   pepper_view_t *view;
 
    DBG("Touch Cancel: obj %p", po->smart_obj);
 
@@ -776,14 +723,13 @@ pepper_efl_object_touch_cancel(Evas_Object *obj)
    if (!po->surface)
      return EINA_FALSE;
 
-   shsurf = pepper_object_get_user_data((pepper_object_t *)po->surface,
-                                        pepper_surface_get_role(po->surface));
-   if (!shsurf)
+   view = pepper_efl_shell_pepper_view_get(po->surface);
+   if (!view)
      return EINA_FALSE;
 
    if ((_mouse_in_po) && (_need_send_released))
      {
-        pepper_touch_send_cancel(po->input.touch, shsurf->view);
+        pepper_touch_send_cancel(po->input.touch, view);
         pepper_touch_remove_point(po->input.touch, 0);
         _need_send_released = EINA_FALSE;
         _need_send_motion = EINA_FALSE;
index b6a33a90cabd094acd18373da2ddfa92ae622418..f39843fca96651f7b4a61b514b9924ce60889085 100644 (file)
@@ -31,7 +31,6 @@ struct pepper_efl_comp
    Eina_Hash *output_hash;
 
    pepper_efl_input_t *input;
-   pepper_efl_shell_t *shell;
 
    struct
    {
index 5babb386d8d323a5ba96ed39c13a9606dab232b2..9a22cb61d619b893b66939087fee9c3fb4669987 100644 (file)
 #include "private.h"
+#include "shell.h"
 
-#include <xdg-shell-unstable-v5-server-protocol.h>
+#include <xdg-shell-unstable-v6-server-protocol.h>
+
+#define xdg_surface_role_biggest_struct xdg_toplevel_t
+
+typedef enum
+{
+   XDG_SURFACE_ROLE_NONE,
+   XDG_SURFACE_ROLE_TOPLEVEL,
+   XDG_SURFACE_ROLE_POPUP,
+} xdg_surface_role_e;
+
+typedef struct
+{
+   int w, h;
+} xdg_size_t;
+
+typedef struct
+{
+   struct wl_client *wclient;
+   struct wl_resource *resource; /* xdg_shell resource */
+
+   pepper_efl_comp_t *comp;
+
+   Eina_List *surfaces;          /* list of all E_Xdg_Surface belonging to shell */
+   Eina_List *positioners;       /* list of E_Xdg_Positioner */
+   uint32_t ping_serial;
+} xdg_shell_t;
+
+typedef struct
+{
+   Eina_Bool maximized;
+   Eina_Bool fullscreen;
+   Eina_Bool resizing;
+   Eina_Bool activated;
+} xdg_toplevel_state_t;
+
+typedef struct
+{
+   struct wl_resource *resource;
+
+   xdg_shell_t *shell;
+
+   enum zxdg_positioner_v6_anchor anchor;
+   enum zxdg_positioner_v6_gravity gravity;
+   enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment;
+
+   xdg_size_t size;
+   Eina_Rectangle anchor_rect;
+   struct
+     {
+        int x, y;
+     } offset;
+} xdg_positioner_t;
+
+typedef struct
+{
+   struct wl_resource *resource; /* wl_resource for Zxdg_Surface_V6 */
+   xdg_shell_t *shell;
+
+   pepper_efl_comp_t *comp;
+   pepper_surface_t *psurf;
+   pepper_view_t *view;
+
+   Eina_List *configure_list; /* list of data being appended whenever configure send and remove by ack_configure */
+
+   /* Listeners */
+   pepper_event_listener_t *surface_destroy_listener;
+   pepper_event_listener_t *surface_commit_listener;
+   Ecore_Idle_Enterer *configure_idle; /* Idle_Enterer for sending configure */
+
+   xdg_surface_role_e role;
+   Eina_Rectangle configured_geometry; /* configured geometry by compositor */
+   Eina_Rectangle window_geometry;     /* window geometry set by client */
+
+   int ref_count;
+
+   Eina_Bool mapped : 1;
+   Eina_Bool configured : 1;
+   Eina_Bool has_window_geometry : 1;
+   Eina_Bool wait_next_commit;
+} xdg_surface_t;
+
+typedef struct
+{
+   xdg_surface_t base;
+   struct wl_resource *resource;
+
+   const char *title;
+   const char *app_id;
+
+   struct
+     {
+        xdg_toplevel_state_t state;
+        xdg_size_t size;
+        uint32_t edges;
+     } pending;
+   struct
+     {
+        xdg_toplevel_state_t state;
+        xdg_size_t size;
+        xdg_size_t min_size, max_size;
+     } next;
+   struct
+     {
+        xdg_toplevel_state_t state;
+        xdg_size_t min_size, max_size;
+     } current;
+} xdg_toplevel_t;
+
+typedef struct
+{
+   xdg_surface_t base;
+   struct wl_resource *resource;
+   xdg_surface_t *parent;
+   xdg_positioner_t *positioner;
+
+   Eina_Rectangle geometry;
+   Eina_Bool committed;
+} xdg_popup_t;
+
+typedef struct
+{
+   uint32_t serial;
+   xdg_toplevel_state_t state;
+   xdg_size_t size;
+} xdg_configure_t;
+
+static void       xdg_surface_ref(xdg_surface_t *shsurf);
+static void       xdg_surface_unref(xdg_surface_t *shsurf);
+static Eina_Bool  xdg_surface_ecore_cb_configure_idle(void *data);
+
+static struct wl_global *global_resource = NULL;
 
 static void
-pepper_efl_shell_surface_destroy(pepper_efl_shell_surface_t *shsurf)
+xdg_popup_committed(xdg_popup_t *popup)
 {
-   pepper_efl_shell_client_t *sc;
+   if (!popup->committed)
+     {
+        if (!popup->base.configure_idle)
+          {
+             popup->base.configure_idle =
+                ecore_idle_enterer_add(xdg_surface_ecore_cb_configure_idle, popup);
+          }
+     }
 
-   sc = shsurf->shell_client;
-   if (sc)
-     sc->shsurf_list = eina_list_remove(sc->shsurf_list, shsurf);
+   popup->committed = EINA_TRUE;
 
-   if (shsurf->surface_destroy_listener)
+   /* TODO: Weston does update the position of popup here */
+}
+
+static void
+xdg_popup_configure_send(xdg_popup_t *popup)
+{
+   zxdg_popup_v6_send_configure(popup->resource,
+                                popup->geometry.x,
+                                popup->geometry.y,
+                                popup->geometry.w,
+                                popup->geometry.h);
+}
+
+static void
+xdg_popup_cb_resource_destroy(struct wl_resource *resource)
+{
+   xdg_popup_t *popup;
+
+   popup = wl_resource_get_user_data(resource);
+   popup->resource = NULL;
+   popup->base.role = XDG_SURFACE_ROLE_NONE;
+   xdg_surface_unref((xdg_surface_t *)popup);
+}
+
+static void
+xdg_popup_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static void
+xdg_popup_cb_grab(struct wl_client *client,
+                  struct wl_resource *resource,
+                  struct wl_resource *res_seat,
+                  uint32_t serial)
+{
+   /* TODO */
+}
+
+static const struct zxdg_popup_v6_interface xdg_popup_implementation =
+{
+   xdg_popup_cb_destroy,
+   xdg_popup_cb_grab
+};
+
+static void
+xdg_toplevel_committed(xdg_toplevel_t *toplevel)
+{
+   toplevel->current.state = toplevel->next.state;
+   toplevel->current.min_size = toplevel->next.min_size;
+   toplevel->current.max_size = toplevel->next.max_size;
+}
+
+static void
+xdg_toplevel_configure_ack(xdg_toplevel_t *toplevel, xdg_configure_t *configure)
+{
+   toplevel->next.state = configure->state;
+   toplevel->next.size = configure->size;
+}
+
+static void
+xdg_toplevel_configure_send(xdg_toplevel_t *toplevel, xdg_configure_t *configure)
+{
+   uint32_t *s;
+   struct wl_array states;
+
+   configure->state = toplevel->pending.state;
+   configure->size = toplevel->pending.size;
+
+   wl_array_init(&states);
+   if (toplevel->pending.state.maximized)
      {
-        pepper_event_listener_remove(shsurf->surface_destroy_listener);
-        shsurf->surface_destroy_listener = NULL;
+        s = wl_array_add(&states, sizeof(uint32_t));
+        *s = ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED;
+     }
+   if (toplevel->pending.state.fullscreen)
+     {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        *s = ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN;
+     }
+   if (toplevel->pending.state.resizing)
+     {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        *s = ZXDG_TOPLEVEL_V6_STATE_RESIZING;
+     }
+   if (toplevel->pending.state.activated)
+     {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        *s = ZXDG_TOPLEVEL_V6_STATE_ACTIVATED;
      }
 
-   if (shsurf->title)
-     eina_stringshare_del(shsurf->title);
+   zxdg_toplevel_v6_send_configure(toplevel->resource,
+                                   toplevel->pending.size.w,
+                                   toplevel->pending.size.h,
+                                   &states);
+   wl_array_release(&states);
+}
 
-   if (shsurf->app_id)
-     eina_stringshare_del(shsurf->app_id);
+static Eina_Bool
+xdg_toplevel_pending_state_compare(xdg_toplevel_t *toplevel)
+{
+   xdg_configure_t *configure;
 
-   if (shsurf->surface)
-     pepper_object_set_user_data((pepper_object_t *)shsurf->surface,
-                                 pepper_surface_get_role((pepper_surface_t *)shsurf->surface),
-                                 NULL, NULL);
+   struct {
+        xdg_toplevel_state_t state;
+        xdg_size_t size;
+   } configured;
 
-   free(shsurf);
+   /* must send configure at least once */
+   if (!toplevel->base.configured)
+     return EINA_FALSE;
+
+   if (!toplevel->base.configure_list)
+     {
+        configured.state = toplevel->current.state;
+        configured.size.w = toplevel->next.size.w;
+        configured.size.h = toplevel->next.size.h;
+     }
+   else
+     {
+        configure = eina_list_last_data_get(toplevel->base.configure_list);
+        configured.state = configure->state;
+        configured.size = configure->size;
+     }
+
+   if (toplevel->pending.state.activated != configured.state.activated)
+     return EINA_FALSE;
+   if (toplevel->pending.state.fullscreen != configured.state.fullscreen)
+     return EINA_FALSE;
+   if (toplevel->pending.state.maximized != configured.state.maximized)
+     return EINA_FALSE;
+   if (toplevel->pending.state.resizing != configured.state.resizing)
+     return EINA_FALSE;
+
+   if ((toplevel->pending.size.w == configured.size.w) &&
+       (toplevel->pending.size.h == configured.size.h))
+     return EINA_TRUE;
+
+   if ((toplevel->pending.size.w == 0) &&
+       (toplevel->pending.size.h == 0))
+     return EINA_TRUE;
+
+   return EINA_FALSE;
+}
+
+static void
+xdg_toplevel_cb_resource_destroy(struct wl_resource *resource)
+{
+   xdg_toplevel_t *toplevel;
+
+   toplevel = wl_resource_get_user_data(resource);
+
+   if (toplevel->title)
+     {
+        eina_stringshare_del(toplevel->title);
+        toplevel->title = NULL;
+     }
+
+   if (toplevel->app_id)
+     {
+        eina_stringshare_del(toplevel->app_id);
+        toplevel->app_id = NULL;
+     }
+
+   toplevel->resource = NULL;
+   toplevel->base.role = XDG_SURFACE_ROLE_NONE;
+   xdg_surface_unref((xdg_surface_t *)toplevel);
+}
+
+static void
+xdg_toplevel_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
+}
+
+static void
+xdg_toplevel_cb_parent_set(struct wl_client *client,
+                           struct wl_resource *resource,
+                           struct wl_resource *res_parent)
+{
+   /* TODO */
+}
+
+static void
+xdg_toplevel_cb_title_set(struct wl_client *client,
+                          struct wl_resource *resource,
+                          const char *title)
+{
+   xdg_toplevel_t *toplevel;
+
+   toplevel = wl_resource_get_user_data(resource);
+   eina_stringshare_replace(&toplevel->title, title);
+}
+
+static void
+xdg_toplevel_cb_app_id_set(struct wl_client *client,
+                           struct wl_resource *resource,
+                           const char *app_id)
+{
+   xdg_toplevel_t *toplevel;
+
+   toplevel = wl_resource_get_user_data(resource);
+   eina_stringshare_replace(&toplevel->app_id, app_id);
+}
+
+static void
+xdg_toplevel_cb_win_menu_show(struct wl_client *client,
+                              struct wl_resource *resource,
+                              struct wl_resource *res_seat,
+                              uint32_t serial,
+                              int32_t x,
+                              int32_t y)
+{
+   /* TODO */
+}
+
+static void
+xdg_toplevel_cb_move(struct wl_client *client,
+                     struct wl_resource *resource,
+                     struct wl_resource *res_seat,
+                     uint32_t serial)
+{
+   /* TODO */
+}
+
+static void
+xdg_toplevel_cb_resize(struct wl_client *client,
+                       struct wl_resource *resource,
+                       struct wl_resource *res_seat,
+                       uint32_t serial,
+                       uint32_t edges)
+{
+   /* TODO */
+}
+
+static void
+xdg_toplevel_cb_max_size_set(struct wl_client *client,
+                             struct wl_resource *resource,
+                             int32_t w,
+                             int32_t h)
+{
+   xdg_toplevel_t *toplevel;
+
+   toplevel = wl_resource_get_user_data(resource);
+   toplevel->next.max_size.w = w;
+   toplevel->next.max_size.h = h;
+}
+
+static void
+xdg_toplevel_cb_min_size_set(struct wl_client *client,
+                             struct wl_resource *resource,
+                             int32_t w,
+                             int32_t h)
+{
+   xdg_toplevel_t *toplevel;
+
+   toplevel = wl_resource_get_user_data(resource);
+   toplevel->next.min_size.w = w;
+   toplevel->next.min_size.h = h;
+}
+
+static void
+xdg_toplevel_cb_maximized_set(struct wl_client *client, struct wl_resource *resource)
+{
+   /* TODO */
+}
+
+static void
+xdg_toplevel_cb_maximized_unset(struct wl_client *client, struct wl_resource *resource)
+{
+   /* TODO */
+}
+
+static void
+xdg_toplevel_cb_fullscreen_set(struct wl_client *client,
+                               struct wl_resource *resource,
+                               struct wl_resource *res_output)
+{
+   /* TODO */
+}
+
+static void
+xdg_toplevel_cb_fullscreen_unset(struct wl_client *client, struct wl_resource *resource)
+{
+   /* TODO */
+}
+
+static void
+xdg_toplevel_cb_minimized_set(struct wl_client *client, struct wl_resource *resource)
+{
+   /* TODO */
+}
+
+static const struct zxdg_toplevel_v6_interface xdg_toplevel_implementation =
+{
+   xdg_toplevel_cb_destroy,
+   xdg_toplevel_cb_parent_set,
+   xdg_toplevel_cb_title_set,
+   xdg_toplevel_cb_app_id_set,
+   xdg_toplevel_cb_win_menu_show,
+   xdg_toplevel_cb_move,
+   xdg_toplevel_cb_resize,
+   xdg_toplevel_cb_max_size_set,
+   xdg_toplevel_cb_min_size_set,
+   xdg_toplevel_cb_maximized_set,
+   xdg_toplevel_cb_maximized_unset,
+   xdg_toplevel_cb_fullscreen_set,
+   xdg_toplevel_cb_fullscreen_unset,
+   xdg_toplevel_cb_minimized_set};
+
+static void
+xdg_surface_ref(xdg_surface_t *shsurf)
+{
+   shsurf->ref_count++;
+}
+
+static void
+xdg_surface_unref(xdg_surface_t *shsurf)
+{
+   shsurf->ref_count--;
+   if (shsurf->ref_count <= 0)
+     free(shsurf);
 }
 
 static void
-handle_resource_destroy(struct wl_resource *resource)
+xdg_surface_cb_resource_destroy(struct wl_resource *resource)
 {
-   pepper_efl_shell_surface_t *shsurf;
+   xdg_shell_t *shell;
+   xdg_surface_t *shsurf;
 
    shsurf = wl_resource_get_user_data(resource);
-   PE_CHECK(shsurf);
+   shell = shsurf->shell;
+
+   if (shell)
+     shell->surfaces = eina_list_remove(shell->surfaces, shsurf);
+
+   if (shsurf->surface_destroy_listener)
+     pepper_event_listener_remove(shsurf->surface_destroy_listener);
+
+   if (shsurf->psurf)
+     pepper_object_set_user_data((pepper_object_t *)shsurf->psurf,
+                                 pepper_surface_get_role((pepper_surface_t *)shsurf->psurf),
+                                 NULL, NULL);
+
+   /* 'shsurf->view' need to be freed? */
+      if (shsurf->view)
+      pepper_view_destroy(shsurf->view);
 
-   wl_resource_set_user_data(resource, NULL);
-   pepper_efl_shell_surface_destroy(shsurf);
+   xdg_surface_unref(shsurf);
 }
 
 static void
-handle_surface_destroy(pepper_event_listener_t *listener, pepper_object_t *surface, uint32_t id, void *info, void *data)
+xdg_surface_pepper_surface_cb_destroy(pepper_event_listener_t *listener,
+                                      pepper_object_t *surface,
+                                      uint32_t id,
+                                      void *info,
+                                      void *data)
 {
-   pepper_efl_shell_surface_t *shsurf;
+   xdg_surface_t *shsurf;
 
    DBG("Destroy Shell Surface");
 
    shsurf = data;
-   PE_CHECK(shsurf);
 
    /* 'surface_destroy_listener' and 'user_data' of surface will be freed
     * by caller. should be set null to avoid double free. */
    shsurf->surface_destroy_listener = NULL;
-
-   shsurf->surface = NULL;
+   shsurf->psurf = NULL;
 }
 
 static void
-handle_surface_commit(pepper_event_listener_t *listener, pepper_object_t *surface, uint32_t id, void *info, void *data)
+xdg_surface_pepper_surface_cb_commit(pepper_event_listener_t *listener,
+                                     pepper_object_t *surface,
+                                     uint32_t id,
+                                     void *info,
+                                     void *data)
 {
-   pepper_efl_shell_surface_t *shsurf;
+   xdg_surface_t *shsurf;
 
    shsurf = data;
-   PE_CHECK(shsurf);
 
    if ((shsurf->mapped) &&
        (!pepper_view_is_mapped(shsurf->view)))
      pepper_view_map(shsurf->view);
-}
 
-static void
-shsurf_xdg_surface_map(pepper_efl_shell_surface_t *shsurf)
-{
-   DBG("Map XDG surface");
+   if (shsurf->wait_next_commit)
+     return;
 
-   pepper_view_map(shsurf->view);
+   shsurf->wait_next_commit = EINA_FALSE;
+   if (shsurf->has_window_geometry)
+     {
+        shsurf->has_window_geometry = EINA_FALSE;
+        /* TODO */
+     }
 
-   shsurf->mapped = EINA_TRUE;
+   switch (shsurf->role)
+     {
+      case XDG_SURFACE_ROLE_NONE:
+      default:
+         wl_resource_post_error(shsurf->resource,
+                                ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+                                "xdg_surface must have a role");
+         break;
+      case XDG_SURFACE_ROLE_TOPLEVEL:
+         xdg_toplevel_committed((xdg_toplevel_t *)shsurf);
+         break;
+      case XDG_SURFACE_ROLE_POPUP:
+         xdg_popup_committed((xdg_popup_t *)shsurf);
+         break;
+     }
 }
 
-static void
-shsurf_xdg_surface_send_configure(pepper_efl_shell_surface_t *shsurf, int32_t width, int32_t height)
+static Eina_Bool
+xdg_surface_ecore_cb_configure_idle(void *data)
 {
+   xdg_surface_t *shsurf;
+   xdg_configure_t *configure;
    struct wl_display *display;
-   struct wl_array states;
-   uint32_t *state;
-   uint32_t serial;
 
-   wl_array_init(&states);
+   shsurf = data;
 
-   state = wl_array_add(&states, sizeof(uint32_t));
-   *state = XDG_SURFACE_STATE_ACTIVATED; // this is arbitary.
+   configure = calloc(1, sizeof(*configure));
+   if (!configure)
+     {
+        ERR("Failed to allocate memory");
+        goto end;
+     }
+
+   shsurf->configure_list = eina_list_append(shsurf->configure_list, configure);
 
    display = pepper_compositor_get_display(shsurf->comp->pepper.comp);
-   serial = wl_display_next_serial(display);
+   configure->serial = wl_display_next_serial(display);
 
-   xdg_surface_send_configure(shsurf->resource, width, height, &states, serial);
+   switch (shsurf->role)
+     {
+      case XDG_SURFACE_ROLE_NONE:
+      default:
+         ERR("Cannot reach here");
+         break;
+      case XDG_SURFACE_ROLE_TOPLEVEL:
+         xdg_toplevel_configure_send((xdg_toplevel_t *)shsurf, configure);
+         break;
+      case XDG_SURFACE_ROLE_POPUP:
+         xdg_popup_configure_send((xdg_popup_t *)shsurf);
+         break;
+     }
 
-   wl_array_release(&states);
+   zxdg_surface_v6_send_configure(shsurf->resource, configure->serial);
 
-   shsurf->ack_configure = EINA_FALSE;
+end:
+   shsurf->configure_idle = NULL;
+   return ECORE_CALLBACK_DONE;
 }
 
 static void
-xdg_surface_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+xdg_surface_configure_schedule(xdg_surface_t *shsurf)
 {
-   DBG("client %p", client);
+   Eina_Bool pending_same = EINA_FALSE;
 
-   wl_resource_destroy(resource);
+   switch (shsurf->role)
+     {
+      case XDG_SURFACE_ROLE_NONE:
+      default:
+         ERR("Cannot reach here");
+         break;
+      case XDG_SURFACE_ROLE_TOPLEVEL:
+         pending_same = xdg_toplevel_pending_state_compare((xdg_toplevel_t *)shsurf);
+         break;
+      case XDG_SURFACE_ROLE_POPUP:
+         break;
+     }
+
+   if (shsurf->configure_idle)
+     {
+        if (!pending_same)
+          return;
+
+        ecore_idle_enterer_del(shsurf->configure_idle);
+        shsurf->configure_idle = NULL;
+     }
+   else
+     {
+        if (pending_same)
+          return;
+
+        shsurf->configure_idle =
+           ecore_idle_enterer_add(xdg_surface_ecore_cb_configure_idle, shsurf);
+     }
 }
 
 static void
-xdg_surface_cb_set_parent(struct wl_client *client, struct wl_resource *resource, struct wl_resource *parent_resource)
+xdg_surface_cb_destroy(struct wl_client *client, struct wl_resource *resource)
 {
    DBG("client %p", client);
+
+   wl_resource_destroy(resource);
 }
 
 static void
-xdg_surface_cb_set_title(struct wl_client *client, struct wl_resource *resource, const char *title)
+xdg_surface_cb_toplevel_get(struct wl_client *client,
+                            struct wl_resource *resource,
+                            uint32_t id)
 {
-   pepper_efl_shell_surface_t *shsurf = wl_resource_get_user_data(resource);
-   DBG("client %p", client);
+   xdg_toplevel_t *toplevel;
+
+   toplevel = wl_resource_get_user_data(resource);
 
-   if (shsurf->title)
-     eina_stringshare_del(shsurf->title);
-   shsurf->title = eina_stringshare_add(title);
+   if (toplevel->base.role != XDG_SURFACE_ROLE_NONE)
+     {
+        DBG("role is already assigned");
+        return;
+     }
+
+   toplevel->base.role = XDG_SURFACE_ROLE_TOPLEVEL;
+   toplevel->resource = wl_resource_create(client, &zxdg_toplevel_v6_interface, 1, id);
+   if (!toplevel->resource)
+     {
+        ERR("could not create xdg_toplevel reousrce");
+        wl_resource_post_no_memory(resource);
+        return;
+     }
+
+   wl_resource_set_implementation(toplevel->resource,
+                                  &xdg_toplevel_implementation,
+                                  toplevel,
+                                  xdg_toplevel_cb_resource_destroy);
+
+   xdg_surface_ref((xdg_surface_t *)toplevel);
+
+   /* FIXME workaround */
+   xdg_surface_configure_schedule((xdg_surface_t *)toplevel);
 }
 
 static void
-xdg_surface_cb_set_app_id(struct wl_client *client, struct wl_resource *resource, const char *app_id)
+xdg_surface_cb_popup_get(struct wl_client *client,
+                         struct wl_resource *resource,
+                         uint32_t id,
+                         struct wl_resource *res_parent,
+                         struct wl_resource *res_pos)
 {
-   pepper_efl_shell_surface_t *shsurf = wl_resource_get_user_data(resource);
-   DBG("client %p", client);
+   xdg_popup_t *popup;
 
-   if (shsurf->app_id)
-     eina_stringshare_del(shsurf->app_id);
-   shsurf->app_id = eina_stringshare_add(app_id);
+   popup = wl_resource_get_user_data(resource);
+   popup->resource = wl_resource_create(client, &zxdg_popup_v6_interface, 1, id);
+   if (!popup->resource)
+     {
+        ERR("Could not create xdg_popup resource");
+        wl_resource_post_no_memory(resource);
+        return;
+     }
+
+   popup->parent = wl_resource_get_user_data(res_parent);
+   popup->positioner = wl_resource_get_user_data(res_pos);
+   popup->base.role = XDG_SURFACE_ROLE_POPUP;
+
+   wl_resource_set_implementation(popup->resource,
+                                  &xdg_popup_implementation,
+                                  popup,
+                                  xdg_popup_cb_resource_destroy);
+
+   xdg_surface_ref((xdg_surface_t *)popup);
 }
 
 static void
-xdg_surface_cb_show_window_menu(struct wl_client *client, struct wl_resource *surface_resource, struct wl_resource *seat_resource, uint32_t serial, int32_t x, int32_t y)
+xdg_surface_cb_win_geometry_set(struct wl_client *client,
+                                struct wl_resource *resource,
+                                int32_t x,
+                                int32_t y,
+                                int32_t w,
+                                int32_t h)
 {
-   DBG("client %p", client);
 }
 
 static void
-xdg_surface_cb_move(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial)
+xdg_surface_cb_configure_ack(struct wl_client *client,
+                             struct wl_resource *resource,
+                             uint32_t serial)
 {
-   DBG("client %p", client);
+   xdg_surface_t *shsurf;
+   xdg_configure_t *configure;
+   Eina_List *l, *ll;
+   Eina_Bool found = EINA_FALSE;
+
+   shsurf = wl_resource_get_user_data(resource);
+   if (shsurf->role == XDG_SURFACE_ROLE_NONE)
+     {
+        wl_resource_post_error(resource,
+                               ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+                               "xdg_surface must have a role");
+        return;
+     }
+
+   EINA_LIST_FOREACH_SAFE(shsurf->configure_list, l, ll, configure)
+     {
+        if (configure->serial < serial)
+          {
+             shsurf->configure_list =
+                eina_list_remove_list(shsurf->configure_list, l);
+             free(configure);
+          }
+        else if (configure->serial == serial)
+          {
+             shsurf->configure_list =
+                eina_list_remove_list(shsurf->configure_list, l);
+             found = EINA_TRUE;
+             break;
+          }
+        else
+          break;
+     }
+
+   if (!found)
+     {
+        wl_resource_post_error(shsurf->shell->resource,
+                               ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
+                               "wrong configure serial: %u", serial);
+     }
+
+   switch (shsurf->role)
+     {
+      case XDG_SURFACE_ROLE_NONE:
+      default:
+         ERR("Cannot reach here");
+         break;
+      case XDG_SURFACE_ROLE_TOPLEVEL:
+         xdg_toplevel_configure_ack((xdg_toplevel_t *)shsurf, configure);
+         break;
+      case XDG_SURFACE_ROLE_POPUP:
+         break;
+     }
+
+   shsurf->configured = EINA_TRUE;
+   shsurf->wait_next_commit = EINA_TRUE;
+
+   free(configure);
 }
 
-static void
-xdg_surface_cb_resize(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial, uint32_t edges)
+static const struct zxdg_surface_v6_interface xdg_surface_implementation =
 {
-   DBG("client %p", client);
-}
+   xdg_surface_cb_destroy,
+   xdg_surface_cb_toplevel_get,
+   xdg_surface_cb_popup_get,
+   xdg_surface_cb_win_geometry_set,
+   xdg_surface_cb_configure_ack};
 
 static void
-xdg_surface_cb_ack_configure(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
+xdg_positioner_cb_resource_destroy(struct wl_resource *resource)
 {
-   pepper_efl_shell_surface_t *shsurf = wl_resource_get_user_data(resource);
+   xdg_positioner_t *p;
 
-   DBG("client %p", client);
-
-   shsurf->ack_configure = EINA_TRUE;
-   if (shsurf->configure_done.func)
-     {
-        shsurf->configure_done.func(shsurf->configure_done.data,
-                                    shsurf->configure_done.width,
-                                    shsurf->configure_done.height);
-        shsurf->configure_done.func = NULL;
-        shsurf->configure_done.data = NULL;
-     }
+   p = wl_resource_get_user_data(resource);
+   p->shell->positioners = eina_list_remove(p->shell->positioners, p);
+   free(p);
 }
 
 static void
-xdg_surface_cb_set_window_geometry(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
+xdg_positioner_cb_destroy(struct wl_client *client, struct wl_resource *resource)
 {
-   DBG("-");
+   wl_resource_destroy(resource);
 }
 
 static void
-xdg_surface_cb_set_maximized(struct wl_client *client, struct wl_resource *resource)
+xdg_positioner_cb_size_set(struct wl_client *client,
+                           struct wl_resource *resource,
+                           int32_t w, int32_t h)
 {
-   DBG("-");
+   /* TODO */
+}
+static void
+xdg_positioner_cb_anchor_rect_set(struct wl_client *client,
+                                  struct wl_resource *resource,
+                                  int32_t x, int32_t y, int32_t w, int32_t h)
+{
+   /* TODO */
 }
 
 static void
-xdg_surface_cb_unset_maximized(struct wl_client *client, struct wl_resource *resource)
+xdg_positioner_cb_anchor_set(struct wl_client *client,
+                             struct wl_resource *resource,
+                             enum zxdg_positioner_v6_anchor anchor)
 {
-   DBG("-");
+   /* TODO */
 }
 
 static void
-xdg_surface_cb_set_fullscreen(struct wl_client *client, struct wl_resource *resource, struct wl_resource *output_resource)
+xdg_positioner_cb_gravity_set(struct wl_client *client,
+                              struct wl_resource *resource,
+                              enum zxdg_positioner_v6_gravity gravity)
 {
-   DBG("-");
+   /* TODO */
 }
 
 static void
-xdg_surface_cb_unset_fullscreen(struct wl_client *client, struct wl_resource *resource)
+xdg_positioner_cb_constraint_adjustment_set(struct wl_client *client,
+                                            struct wl_resource *resource,
+                                            enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment)
 {
-   DBG("-");
+   /* TODO */
 }
 
 static void
-xdg_surface_cb_set_minimized(struct wl_client *client, struct wl_resource *resource)
+xdg_positioner_cb_offet_set(struct wl_client *client,
+                            struct wl_resource *resource,
+                            int32_t x, int32_t y)
 {
-   DBG("-");
+   /* TODO */
 }
 
-static const struct xdg_surface_interface xdg_surface_implementation =
+static const struct zxdg_positioner_v6_interface xdg_positioner_implementation =
 {
-   xdg_surface_cb_destroy,
-   xdg_surface_cb_set_parent,
-   xdg_surface_cb_set_title,
-   xdg_surface_cb_set_app_id,
-   xdg_surface_cb_show_window_menu,
-   xdg_surface_cb_move,
-   xdg_surface_cb_resize,
-   xdg_surface_cb_ack_configure,
-   xdg_surface_cb_set_window_geometry,
-   xdg_surface_cb_set_maximized,
-   xdg_surface_cb_unset_maximized,
-   xdg_surface_cb_set_fullscreen,
-   xdg_surface_cb_unset_fullscreen,
-   xdg_surface_cb_set_minimized,
+   xdg_positioner_cb_destroy,
+   xdg_positioner_cb_size_set,
+   xdg_positioner_cb_anchor_rect_set,
+   xdg_positioner_cb_anchor_set,
+   xdg_positioner_cb_gravity_set,
+   xdg_positioner_cb_constraint_adjustment_set,
+   xdg_positioner_cb_offet_set,
 };
 
 static void xdg_shell_cb_destroy(struct wl_client *client,
                                  struct wl_resource *resource)
 {
    DBG("-");
+   wl_resource_destroy(resource);
 }
 
 static void
-xdg_shell_cb_use_unstable_version(struct wl_client *client, struct wl_resource *resource, int32_t version)
+xdg_shell_cb_positioner_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
 {
+   xdg_shell_t *shell;
+   xdg_positioner_t *p;
+
    DBG("-");
+
+   shell = wl_resource_get_user_data(resource);
+   if (!shell)
+     {
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "no user data in shell resource");
+        return;
+     }
+
+   p = calloc(1, sizeof(*p));
+   if (!p)
+     {
+        wl_resource_post_no_memory(resource);
+        return;
+     }
+
+   p->resource = wl_resource_create(client, &zxdg_positioner_v6_interface, 1, id);
+   if (!p->resource)
+     {
+        free(p);
+        wl_resource_post_no_memory(resource);
+        return;
+     }
+
+   p->shell = shell;
+   wl_resource_set_implementation(p->resource, &xdg_positioner_implementation, p,
+                                  xdg_positioner_cb_resource_destroy);
 }
 
 static void
 xdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource)
 {
-   pepper_surface_t *surface = wl_resource_get_user_data(surface_resource);
-   pepper_efl_shell_client_t *sc = wl_resource_get_user_data(resource);
-   pepper_efl_shell_surface_t *shsurf;
+   pepper_surface_t *psurf;
+   xdg_shell_t *shell;
+   xdg_surface_t *shsurf;
 
    DBG("Get XDG surface");
 
-   shsurf = calloc(1, sizeof(*shsurf));
+   shell = wl_resource_get_user_data(resource);
+   psurf = wl_resource_get_user_data(surface_resource);
+
+   if (!pepper_surface_set_role(psurf, "xdg_surface"))
+     {
+        ERR("failed to set role to pepper_surface");
+        return;
+     }
+
+   shsurf = calloc(1, sizeof(xdg_surface_role_biggest_struct));
    if (!shsurf)
      {
         ERR("out of memory");
-        goto err;
+        return;
      }
 
-   shsurf->resource = wl_resource_create(client, &xdg_surface_interface, 1, id);
+   shsurf->resource = wl_resource_create(client, &zxdg_surface_v6_interface, 1, id);
    if (!shsurf->resource)
      {
         ERR("failed to create resource for xdg_surface");
-        goto err;
+        goto err_res;
      }
 
-   shsurf->comp = sc->comp;
-   shsurf->shell_client = sc;
-   shsurf->surface = surface;
-   shsurf->view = pepper_compositor_add_view(sc->comp->pepper.comp);
+   shsurf->comp = shell->comp;
+   shsurf->shell = shell;
+   shsurf->psurf = psurf;
+   shsurf->mapped = EINA_FALSE;
+   shsurf->view = pepper_compositor_add_view(shsurf->comp->pepper.comp);
    if (!shsurf->view)
      {
         ERR("failed to add pepper_view");
-        goto err;
+        goto err_view;
      }
 
-   if (!pepper_view_set_surface(shsurf->view, surface))
+   if (!pepper_view_set_surface(shsurf->view, psurf))
      {
         ERR("failed to set surface to view");
-        goto err;
+        goto err_set_view;
      }
 
    wl_resource_set_implementation(shsurf->resource, &xdg_surface_implementation,
-                                  shsurf, handle_resource_destroy);
+                                  shsurf, xdg_surface_cb_resource_destroy);
 
    shsurf->surface_destroy_listener =
-      pepper_object_add_event_listener((pepper_object_t *)surface, PEPPER_EVENT_OBJECT_DESTROY, 0,
-                                       handle_surface_destroy, shsurf);
+      pepper_object_add_event_listener((pepper_object_t *)psurf, PEPPER_EVENT_OBJECT_DESTROY, 0,
+                                       xdg_surface_pepper_surface_cb_destroy, shsurf);
    shsurf->surface_commit_listener =
-      pepper_object_add_event_listener((pepper_object_t *)surface, PEPPER_EVENT_SURFACE_COMMIT, 0,
-                                       handle_surface_commit, shsurf);
-
-   shsurf->send_configure = shsurf_xdg_surface_send_configure;
-   shsurf->shell_surface_map = shsurf_xdg_surface_map;
+      pepper_object_add_event_listener((pepper_object_t *)psurf, PEPPER_EVENT_SURFACE_COMMIT, 0,
+                                       xdg_surface_pepper_surface_cb_commit, shsurf);
 
-   shsurf->mapped = EINA_FALSE;
-
-   sc->shsurf_list = eina_list_append(sc->shsurf_list, shsurf);
+   pepper_object_set_user_data((pepper_object_t *)psurf,
+                               pepper_surface_get_role(psurf), shsurf, NULL);
 
-   pepper_surface_set_role(surface, "xdg_surface");
+   shell->surfaces = eina_list_append(shell->surfaces, shsurf);
 
-   pepper_object_set_user_data((pepper_object_t *)surface,
-                               pepper_surface_get_role(surface), shsurf, NULL);
+   xdg_surface_ref(shsurf);
 
    return;
-err:
-   if (shsurf)
-     free(shsurf);
+err_set_view:
+   pepper_view_destroy(shsurf->view);
+err_view:
+   wl_resource_destroy(shsurf->resource);
+err_res:
+   free(shsurf);
 
    wl_client_post_no_memory(client);
 }
 
-static void
-xdg_shell_cb_popup_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource, struct wl_resource *seat_resource, uint32_t serial, int32_t x, int32_t y)
-{
-   DBG("-");
-}
-
 static void
 xdg_shell_cb_pong(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
 {
-   DBG("-");
+   /* TODO */
 }
 
-static const struct xdg_shell_interface xdg_implementation = {
+static const struct zxdg_shell_v6_interface xdg_shell_implementation = {
      xdg_shell_cb_destroy,
-     xdg_shell_cb_use_unstable_version,
+     xdg_shell_cb_positioner_create,
      xdg_shell_cb_surface_get,
-     xdg_shell_cb_popup_get,
-     xdg_shell_cb_pong
-};
+     xdg_shell_cb_pong};
 
 static void
 shell_client_destroy_handle(struct wl_resource *resource)
 {
-   pepper_efl_shell_client_t *sc;
-   pepper_efl_shell_surface_t *shsurf;
+   xdg_shell_t *shell;
+   xdg_surface_t *surface;
 
-   sc = wl_resource_get_user_data(resource);
+   shell = wl_resource_get_user_data(resource);
    DBG("Destroy shell client");
 
-   EINA_LIST_FREE(sc->shsurf_list, shsurf)
-      shsurf->shell_client = NULL;
+   EINA_LIST_FREE(shell->surfaces, surface)
+      surface->shell = NULL;
 
-   free(sc);
+   free(shell);
 }
 
 static void
 xdg_shell_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 {
    pepper_efl_comp_t *comp = data;
-   pepper_efl_shell_client_t *sc;
+   xdg_shell_t *shell;
 
    DBG("Bind Shell - client %p version %d", client, version);
 
-   sc = calloc(1, sizeof(pepper_efl_shell_client_t));
-   if (!sc)
+   shell = calloc(1, sizeof(xdg_shell_t));
+   if (!shell)
      {
         wl_client_post_no_memory(client);
         return;
      }
 
-   sc->resource = wl_resource_create(client, &xdg_shell_interface, version, id);
-   if (!sc->resource)
+   shell->comp = comp;
+   shell->wclient = client;
+   shell->resource = wl_resource_create(client, &zxdg_shell_v6_interface, version, id);
+   if (!shell->resource)
      {
         wl_client_post_no_memory(client);
-        free(sc);
+        free(shell);
         return;
      }
 
-   wl_resource_set_implementation(sc->resource, &xdg_implementation, sc, shell_client_destroy_handle);
-
-   sc->comp  = comp;
+   wl_resource_set_implementation(shell->resource,
+                                  &xdg_shell_implementation,
+                                  shell,
+                                  shell_client_destroy_handle);
 }
 
 Eina_Bool
@@ -383,8 +1053,12 @@ pepper_efl_shell_init(pepper_efl_comp_t *comp)
 
    DBG("Init Shell");
 
+   if (global_resource)
+     return EINA_TRUE;
+
    wl_disp = pepper_compositor_get_display(comp->pepper.comp);
-   if (!wl_global_create(wl_disp, &xdg_shell_interface, 1, comp, xdg_shell_bind))
+   global_resource = wl_global_create(wl_disp, &zxdg_shell_v6_interface, 1, comp, xdg_shell_bind);
+   if (!global_resource)
      {
         ERR("failed to create global for xdg_shell");
         return EINA_FALSE;
@@ -393,21 +1067,122 @@ pepper_efl_shell_init(pepper_efl_comp_t *comp)
    return EINA_TRUE;
 }
 
-void
-pepper_efl_shell_shutdown(void)
+void pepper_efl_shell_shutdown(void)
 {
    DBG("Shutdown Shell");
+   wl_global_destroy(global_resource);
+   global_resource = NULL;
+}
+
+void pepper_efl_shell_configure(pepper_surface_t *psurf, int width, int height)
+{
+   xdg_toplevel_t *toplevel;
+
+   DBG("shell - configure (%d x %d)", width, height);
+
+   toplevel =
+      pepper_object_get_user_data((pepper_object_t *)psurf,
+                                  pepper_surface_get_role(psurf));
+   if (!toplevel)
+     return;
+
+   if (toplevel->base.role != XDG_SURFACE_ROLE_TOPLEVEL)
+     {
+        ERR("Not defined for another role yet");
+        return;
+     }
+
+   toplevel->pending.size.w = width;
+   toplevel->pending.size.h = height;
+   xdg_surface_configure_schedule((xdg_surface_t *)toplevel);
 }
 
 void
-pepper_efl_shell_configure(pepper_efl_shell_surface_t *shsurf, int width, int height, void (*configure_done)(void *data, int w, int h), void *data)
+pepper_efl_shell_map(pepper_surface_t *psurf)
 {
-   DBG("shell - configure send (%d x %d)", width, height);
+   xdg_surface_t *shsurf;
+
+   shsurf =
+      pepper_object_get_user_data((pepper_object_t *)psurf,
+                                  pepper_surface_get_role(psurf));
+   if (!shsurf)
+     return;
+
+   if (shsurf->mapped)
+     return;
+
+   shsurf->mapped = EINA_TRUE;
+   pepper_view_map(shsurf->view);
+}
+
+void
+pepper_efl_shell_unmap(pepper_surface_t *psurf)
+{
+   xdg_surface_t *shsurf;
+
+   shsurf =
+      pepper_object_get_user_data((pepper_object_t *)psurf,
+                                  pepper_surface_get_role(psurf));
+   if (!shsurf)
+     return;
+
+   if (!shsurf->mapped)
+     return;
 
-   shsurf->send_configure(shsurf, width, height);
+   shsurf->mapped = EINA_FALSE;
+   pepper_view_unmap(shsurf->view);
+}
+
+const char *
+pepper_efl_shell_title_get(pepper_surface_t *psurf)
+{
+   xdg_toplevel_t *toplevel;
+
+   toplevel =
+      pepper_object_get_user_data((pepper_object_t *)psurf,
+                                  pepper_surface_get_role(psurf));
+   if (!toplevel)
+     return NULL;
+
+   if (toplevel->base.role != XDG_SURFACE_ROLE_TOPLEVEL)
+     {
+        ERR("Only defined for toplevel");
+        return NULL;
+     }
+
+   return toplevel->title;
+}
+
+const char *
+pepper_efl_shell_app_id_get(pepper_surface_t *psurf)
+{
+   xdg_toplevel_t *toplevel;
+
+   toplevel =
+      pepper_object_get_user_data((pepper_object_t *)psurf,
+                                  pepper_surface_get_role(psurf));
+   if (!toplevel)
+     return NULL;
+
+   if (toplevel->base.role != XDG_SURFACE_ROLE_TOPLEVEL)
+     {
+        ERR("Only defined for toplevel");
+        return NULL;
+     }
+
+   return toplevel->app_id;
+}
+
+pepper_view_t *
+pepper_efl_shell_pepper_view_get(pepper_surface_t *psurf)
+{
+   xdg_surface_t *shsurf;
+
+   shsurf =
+      pepper_object_get_user_data((pepper_object_t *)psurf,
+                                  pepper_surface_get_role(psurf));
+   if (!shsurf)
+     return NULL;
 
-   shsurf->configure_done.width = width;
-   shsurf->configure_done.height = height;
-   shsurf->configure_done.func = configure_done;
-   shsurf->configure_done.data = data;
+   return shsurf->view;
 }
index 1766a41142b6818f62b93476df8509cb4c3f7ef4..e3af3754d1326cd7b1436dbf286dde323b99b2a8 100644 (file)
@@ -1,51 +1,13 @@
 #ifndef _PEPPER_EFL_SHELL_H_
 #define _PEPPER_EFL_SHELL_H_
 
-typedef struct pepper_efl_shell pepper_efl_shell_t;
-typedef struct pepper_efl_shell_client pepper_efl_shell_client_t;
-typedef struct pepper_efl_shell_surface pepper_efl_shell_surface_t;
-
-struct pepper_efl_shell_client {
-   pepper_efl_comp_t *comp;
-
-   Eina_List *shsurf_list;
-
-   struct wl_resource *resource;
-   struct wl_listener destroy_listener;
-};
-
-struct pepper_efl_shell_surface
-{
-   pepper_efl_comp_t *comp;
-   pepper_efl_shell_client_t *shell_client;
-
-   pepper_surface_t *surface;
-   pepper_view_t *view;
-   /* Listeners */
-   pepper_event_listener_t *surface_destroy_listener;
-   pepper_event_listener_t *surface_commit_listener;
-
-   struct wl_resource *resource;
-
-   void (*send_configure)(pepper_efl_shell_surface_t *shsurf, int32_t width, int32_t height);
-   void (*shell_surface_map)(pepper_efl_shell_surface_t *shsurf);
-
-   struct
-   {
-      void (*func)(void *data, int w, int h);
-      void *data;
-      int width, height;
-   } configure_done;
-
-   Eina_Bool mapped;
-   Eina_Bool ack_configure;
-
-   const char *title;
-   const char *app_id;
-};
-
-Eina_Bool   pepper_efl_shell_init(pepper_efl_comp_t *comp);
-void        pepper_efl_shell_shutdown(void);
-void        pepper_efl_shell_configure(pepper_efl_shell_surface_t *shsurf, int width, int height, void (*configure_done)(void *data, int w, int h), void *data);
+Eina_Bool       pepper_efl_shell_init(pepper_efl_comp_t *comp);
+void            pepper_efl_shell_shutdown(void);
+void            pepper_efl_shell_configure(pepper_surface_t *psurf, int width, int height);
+void            pepper_efl_shell_map(pepper_surface_t *psurf);
+void            pepper_efl_shell_unmap(pepper_surface_t *psurf);
+const char*     pepper_efl_shell_title_get(pepper_surface_t *psurf);
+const char*     pepper_efl_shell_app_id_get(pepper_surface_t *psurf);
+pepper_view_t*  pepper_efl_shell_pepper_view_get(pepper_surface_t *psurf);
 
 #endif