Revert "xdg_shell_v6: Use ds_xdg_shell_v6" 92/300092/1
authorSeunghun Lee <shiin.lee@samsung.com>
Mon, 16 Oct 2023 10:28:14 +0000 (19:28 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Mon, 16 Oct 2023 22:55:51 +0000 (07:55 +0900)
This reverts commit fae1e58bc095580c648f4afc305f665770131e36.

Change-Id: I472de42ca93e8f24bccc081c15fcc307d45a3b49

configure.ac
packaging/enlightenment.spec
src/bin/e_comp_wl_shell.c
src/bin/e_xdg_shell_v6.c

index f9cdf97..943840f 100755 (executable)
@@ -291,7 +291,6 @@ e_requires="\
   libds \
   libds-tizen-tbm-server \
   libds-tizen-scaler \
-  libds-xdg-shell-v6 \
   "
 
 PKG_CHECK_MODULES(E_INFO, [
index b0f9a20..3fb7093 100644 (file)
@@ -79,7 +79,6 @@ BuildRequires:  pkgconfig(wayland-client)
 BuildRequires:  pkgconfig(capi-media-streamrecorder)
 
 BuildRequires:  pkgconfig(libds)
-BuildRequires:  pkgconfig(libds-xdg-shell-v6)
 BuildRequires:  pkgconfig(libds-tizen-tbm-server)
 BuildRequires:  pkgconfig(libds-tizen-scaler)
 
index 5893cdb..dea52c1 100644 (file)
@@ -98,24 +98,6 @@ e_shell_e_client_shsurface_api_set(E_Client *ec, E_Shell_Surface_Api *api)
    cdata->shell.unmap = api->unmap;
 }
 
-static void
-_e_shell_e_client_shsurface_api_reset(E_Client *ec)
-{
-   E_Comp_Wl_Client_Data *cdata;
-
-   EINA_SAFETY_ON_NULL_RETURN(ec);
-
-   cdata = ec->comp_data;
-   if (!cdata)
-     return;
-
-   cdata->shell.configure_send = NULL;
-   cdata->shell.configure = NULL;
-   cdata->shell.ping = NULL;
-   cdata->shell.map = NULL;
-   cdata->shell.unmap = NULL;
-}
-
 EINTERN void
 e_shell_e_client_toplevel_set(E_Client *ec)
 {
@@ -374,8 +356,6 @@ e_shell_e_client_destroy(E_Client *ec)
 
    ELOGF("SHELL", "Destroy shell surface", ec);
 
-   _e_shell_e_client_shsurface_api_reset(ec);
-
    if (e_policy_visibility_client_grab_cancel(ec))
      {
         ELOGF("POL_VIS", "CLIENT VIS ON(temp).", ec);
index 69442b2..11d3758 100644 (file)
@@ -1,7 +1,5 @@
 #include "e.h"
-
-#include <libds/types/ds_surface.h>
-#include <libds/types/ds_xdg_shell_v6.h>
+#include <xdg-shell-unstable-v6-server-protocol.h>
 
 #ifdef LOG
 #undef LOG
 #define LOG(f, e, x...)  ELOGF("XDG6 <LOG>", f, e, ##x)
 #define ERR(f, e, x...)  ELOGF("XDG6 <ERR>", f, e, ##x)
 
-typedef struct _E_Xdg_Shell_V6 E_Xdg_Shell_V6;
-typedef struct _E_Xdg_Toplevel_V6 E_Xdg_Toplevel_V6;
+#define e_xdg_surface_role_biggest_struct E_Xdg_Toplevel
+#define E_XDG_SURFACE_V6_TYPE (int)0xE0b06000
+
+const int WAIT_ACK_COUNT_MAX = 16;
 
-struct _E_Xdg_Shell_V6
+typedef enum   _E_Xdg_Surface_Role        E_Xdg_Surface_Role;
+typedef struct _E_Xdg_Size                E_Xdg_Size;
+typedef struct _E_Xdg_Shell               E_Xdg_Shell;
+typedef struct _E_Xdg_Surface             E_Xdg_Surface;
+typedef struct _E_Xdg_Toplevel            E_Xdg_Toplevel;
+typedef struct _E_Xdg_Popup               E_Xdg_Popup;
+typedef struct _E_Xdg_Positioner          E_Xdg_Positioner;
+typedef struct _E_Xdg_Toplevel_State      E_Xdg_Toplevel_State;
+typedef struct _E_Xdg_Surface_Configure   E_Xdg_Surface_Configure;
+
+enum _E_Xdg_Surface_Role
 {
-   struct ds_xdg_shell_v6 *ds_xdg_shell;
+   E_XDG_SURFACE_ROLE_NONE,
+   E_XDG_SURFACE_ROLE_TOPLEVEL,
+   E_XDG_SURFACE_ROLE_POPUP,
+};
 
-   struct wl_listener destroy;
-   struct wl_listener new_surface;
+struct _E_Xdg_Size
+{
+   int w, h;
 };
 
-struct _E_Xdg_Toplevel_V6
+struct _E_Xdg_Shell
 {
-   struct ds_xdg_toplevel_v6 *ds_toplevel;
-   E_Client *ec;
+   struct wl_client     *wclient;
+   struct wl_resource   *resource;     /* xdg_shell resource */
+   Eina_List            *surfaces;     /* list of all E_Xdg_Surface belonging to shell */
+   Eina_List            *positioners;  /* list of E_Xdg_Positioner */
+   uint32_t              ping_serial;
+};
 
-   struct wl_listener set_parent;
-   struct wl_listener set_title;
-   struct wl_listener set_app_id;
-   struct wl_listener request_move;
-   struct wl_listener request_resize;
-   struct wl_listener request_maximize;
-   struct wl_listener request_fullscreen;
-   struct wl_listener request_minimize;
-   struct wl_listener destroy;
-   struct wl_listener configure;
-   struct wl_listener ping_timeout;
-   struct wl_listener surface_commit;
+struct _E_Xdg_Toplevel_State
+{
+   Eina_Bool maximized;
+   Eina_Bool fullscreen;
+   Eina_Bool resizing;
+   Eina_Bool activated;
 };
 
-static void _e_xdg_shell_v6_cb_destroy(struct wl_listener *listener, void *data);
-static void _e_xdg_shell_v6_cb_new_surface(struct wl_listener *listener, void *data);
-static void _e_xdg_toplevel_v6_add(struct ds_xdg_surface_v6 *ds_xdg_surface);
-static void _e_xdg_toplevel_v6_cb_destroy(struct wl_listener *listener, void *data);
-static E_Xdg_Toplevel_V6 *_e_xdg_toplevel_v6_from_shell_surface_resource(struct wl_resource *shsurface_resource);
+struct _E_Xdg_Surface
+{
+   E_Object e_obj_inherit;
+   struct wl_resource   *resource;        /* wl_resource for Zxdg_Surface_V6 */
+   E_Client             *ec;              /* E_Client corresponding Xdg_Surface */
+   E_Xdg_Shell          *shell;           /* Xdg_Shell created Xdg_Surface */
+   Eina_List            *configure_list;  /* list of data being appended whenever configure send and remove by ack_configure */
+
+   Ecore_Idle_Enterer   *configure_idle;  /* Idle_Enterer for sending configure */
+   E_Comp_Wl_Hook       *commit_hook;  /* Handler raised when wl_surface is committed. */
+
+   E_Xdg_Surface_Role    role;
+   Eina_Rectangle        configured_geometry;   /* configured geometry by compositor */
+   Eina_Rectangle        window_geometry;       /* window geometry set by client */
+
+   Eina_Bool             configured :1;
+   Eina_Bool             has_window_geometry: 1;
+   Eina_Bool             wait_next_commit;
+};
 
-EINTERN Eina_Bool
-e_xdg_shell_v6_init(void)
+struct _E_Xdg_Toplevel
 {
-   static E_Xdg_Shell_V6 shell = { .ds_xdg_shell = NULL };
+   E_Xdg_Surface         base;
+   struct wl_resource   *resource;
+
+   struct
+   {
+      E_Xdg_Toplevel_State state;
+      E_Xdg_Size           size;
+      uint32_t             edges;
+   } pending;
+   struct
+   {
+      E_Xdg_Toplevel_State state;
+      E_Xdg_Size           size;
+      E_Xdg_Size           min_size, max_size;
+   } next;
+   struct
+   {
+      E_Xdg_Toplevel_State state;
+      E_Xdg_Size           min_size, max_size;
+   } current;
+};
 
-   LOG("Initializing Xdg_Shell_V6", NULL);
+struct _E_Xdg_Popup
+{
+   E_Xdg_Surface         base;
 
-   if (shell.ds_xdg_shell)
-     {
-        LOG("Xdg_Shell_V6 already initialized", NULL);
-        return EINA_TRUE;
-     }
+   struct wl_resource   *resource;
+   E_Xdg_Surface        *parent;
+
+   Eina_Rectangle        geometry;
+   Eina_Bool             committed;
+};
+
+struct _E_Xdg_Surface_Configure
+{
+   uint32_t serial;
+   E_Xdg_Toplevel_State state;
+   E_Xdg_Size size;
+};
+
+struct _E_Xdg_Positioner
+{
+   E_Xdg_Shell          *shell;
+   struct wl_resource   *resource;     /* xdg_positioner_v6 resources */
+   E_Xdg_Size            size;
+   Eina_Rectangle        anchor_rect;
+   enum zxdg_positioner_v6_anchor                  anchor;
+   enum zxdg_positioner_v6_gravity                 gravity;
+   enum zxdg_positioner_v6_constraint_adjustment   constraint_adjustment;
+   struct
+   {
+      int x, y;
+   } offset;
+};
+
+static struct wl_global *global_resource = NULL;
+
+static void             _e_xdg_shell_surface_add(E_Xdg_Shell *shell, E_Xdg_Surface *exsurf);
+static void             _e_xdg_shell_surface_remove(E_Xdg_Shell *shell, E_Xdg_Surface *exsurf);
+static void             _e_xdg_shell_ping(E_Xdg_Shell *shell);
+static Eina_Bool        _e_xdg_surface_cb_configure_send(void *data);
+static Eina_Rectangle   _e_xdg_positioner_geometry_get(E_Xdg_Positioner *p);
 
+/**********************************************************
+ * Implementation for Utility
+ **********************************************************/
+static Eina_Bool
+_e_client_shsurface_assignable_check(E_Client *ec)
+{
+   E_Comp_Wl_Client_Data *cdata;
 
-   shell.ds_xdg_shell = ds_xdg_shell_v6_create(e_comp_wl->wl.disp);
-   if (!shell.ds_xdg_shell)
+   if (!e_shell_e_client_shell_assignable_check(ec))
      {
-        ERR("Could not create ds_xdg_shell_v6", NULL);
+        ERR("Could not assign shell", ec);
+        cdata = e_client_cdata_get(ec);
+        wl_resource_post_error(cdata->surface,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "Could not assign shell surface to wl_surface");
         return EINA_FALSE;
      }
 
-   shell.destroy.notify = _e_xdg_shell_v6_cb_destroy;
-   ds_xdg_shell_v6_add_destroy_listener(shell.ds_xdg_shell, &shell.destroy);
+   return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_client_xdg_shell_v6_assigned_check(E_Client *ec)
+{
+   E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
+   return !!cdata->sh_v6.res_role;
+}
 
-   shell.new_surface.notify = _e_xdg_shell_v6_cb_new_surface;
-   ds_xdg_shell_v6_add_new_surface_listener(shell.ds_xdg_shell, &shell.new_surface);
+static void
+_e_client_xdg_shell_v6_assign(E_Client *ec,
+                              struct wl_resource *resource,
+                              E_Comp_Wl_Sh_Surf_Role role)
+{
+   E_Comp_Wl_Client_Data *cdata;
 
-   return EINA_TRUE;
+   if (!ec) return;
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   cdata = e_client_cdata_get(ec);
+   if (!cdata) return;
+
+   cdata->sh_v6.res_role = resource;
+   cdata->sh_v6.role = role;
 }
 
-EINTERN E_Client *
-e_xdg_shell_v6_xdg_surface_ec_get(struct wl_resource *resource)
+static void
+_e_client_xdg_shell_v6_role_assingment_unset(E_Client *ec)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Comp_Wl_Client_Data *cdata;
 
-   toplevel = _e_xdg_toplevel_v6_from_shell_surface_resource(resource);
-   if (!toplevel)
-     {
-        ERR("No E_Xdg_Toplevel_V6 in wl_resource", NULL);
-        return NULL;
-     }
+   if (!ec) return;
+   if (e_object_is_del(E_OBJECT(ec))) return;
+   cdata = e_client_cdata_get(ec);
+   if (!cdata) return;
 
-   return toplevel->ec;
+   _e_client_xdg_shell_v6_assign(ec, NULL, E_COMP_WL_SH_SURF_ROLE_NONE);
 }
 
 static void
-_e_xdg_shell_v6_cb_destroy(struct wl_listener *listener, void *data)
+_validate_size(struct wl_resource *resource, int32_t value)
 {
-   E_Xdg_Shell_V6 *shell;
+   if (value <= 0)
+     wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT, "Invalid size passed");
+}
+/* End of utility */
 
-   LOG("Destroy Xdg_Shell_V6", NULL);
+/**********************************************************
+ * Implementation for Xdg_popup
+ **********************************************************/
+static void
+_e_xdg_popup_positioner_apply(E_Xdg_Popup *popup, E_Xdg_Positioner *pos)
+{
+   popup->geometry = _e_xdg_positioner_geometry_get(pos);
 
-   shell = wl_container_of(listener, shell, destroy);
+   /* TODO apply geometry to popup */
 
-   wl_list_remove(&shell->destroy.link);
-   wl_list_remove(&shell->new_surface.link);
-   shell->ds_xdg_shell = NULL;
 }
 
 static void
-_e_xdg_shell_v6_cb_new_surface(struct wl_listener *listener, void *data)
+_e_xdg_popup_parent_set(E_Xdg_Popup *popup, E_Xdg_Surface *parent)
 {
-   struct ds_xdg_surface_v6 *ds_xdg_surface = data;
+   E_Comp_Wl_Client_Data *parent_cdata;
 
-   if (ds_xdg_surface->role == DS_XDG_SURFACE_V6_ROLE_TOPLEVEL)
-     _e_xdg_toplevel_v6_add(ds_xdg_surface);
-   else
-     ERR("Unexpected role of xdg_surface_v6: role(%d)", NULL, ds_xdg_surface->role);
+   popup->parent = parent;
+   parent_cdata = e_client_cdata_get(parent->ec);
+
+   /* set this client as a transient for parent */
+   e_shell_e_client_parent_set(popup->base.ec, parent_cdata->surface);
 }
 
-static E_Xdg_Toplevel_V6 *
-_e_xdg_toplevel_v6_from_shell_surface_resource(struct wl_resource *shsurface_resource)
+static void
+_e_xdg_popup_set(E_Xdg_Popup *popup, struct wl_resource *resource)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
-   struct ds_xdg_surface_v6 *ds_xdg_surface;
-   struct wl_listener *listener;
+   popup->resource = resource;
+   _e_client_xdg_shell_v6_assign(popup->base.ec, resource, E_COMP_WL_SH_SURF_ROLE_POPUP);
+   e_shell_e_client_popup_set(popup->base.ec);
+}
 
-   ds_xdg_surface = ds_xdg_surface_v6_from_resource(shsurface_resource);
-   if (!ds_xdg_surface)
-     return NULL;
+static void
+_e_xdg_popup_committed(E_Xdg_Popup *popup)
+{
+   if (!popup->committed)
+     {
+        if (!popup->base.configure_idle)
+          {
+             popup->base.configure_idle =
+                ecore_idle_enterer_add(_e_xdg_surface_cb_configure_send, popup);
+          }
+     }
 
-   listener = wl_signal_get(&ds_xdg_surface->events.destroy,
-                            _e_xdg_toplevel_v6_cb_destroy);
-   if (listener)
-     return wl_container_of(listener, toplevel, destroy);
+   popup->committed = EINA_TRUE;
 
-   return NULL;
+   /* TODO: Weston does update the position of popup here */
 }
 
 static void
-_e_xdg_toplevel_v6_fullscreen_send(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_popup_configure_send(E_Xdg_Popup *popup)
 {
-   struct ds_xdg_toplevel_v6 *ds_toplevel = toplevel->ds_toplevel;
-   E_Client *ec = toplevel->ec;
+   if (!popup) return;
+   if (!popup->resource) return;
+
+   zxdg_popup_v6_send_configure(popup->resource,
+                                popup->geometry.x,
+                                popup->geometry.y,
+                                popup->geometry.w,
+                                popup->geometry.h);
+}
 
-   if (ds_toplevel->scheduled.fullscreen == ec->fullscreen)
-     return;
+static void
+_e_xdg_popup_cb_resource_destroy(struct wl_resource *resource)
+{
+   E_Xdg_Popup *popup;
 
-   LOG("Send fullscreen(%d)", ec, ec->fullscreen);
+   popup = wl_resource_get_user_data(resource);
+   popup->resource = NULL;
+   _e_client_xdg_shell_v6_role_assingment_unset(popup->base.ec);
+   e_object_unref(E_OBJECT(popup));
+}
 
-   ds_xdg_toplevel_v6_set_fullscreen(ds_toplevel, ec->fullscreen);
+static void
+_e_xdg_popup_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
 }
 
 static void
-_e_xdg_toplevel_v6_maximized_send(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_popup_cb_grab(struct wl_client *client,
+                     struct wl_resource *resource,
+                     struct wl_resource *res_seat,
+                     uint32_t serial)
 {
-   struct ds_xdg_toplevel_v6 *ds_toplevel = toplevel->ds_toplevel;
-   E_Client *ec = toplevel->ec;
+   /* TODO no op */
+}
 
-   if (ds_toplevel->scheduled.maximized == !!ec->maximized)
-     return;
+static const struct zxdg_popup_v6_interface _e_xdg_popup_interface =
+{
+   _e_xdg_popup_cb_destroy,
+   _e_xdg_popup_cb_grab
+};
 
-   LOG("Send maximized(%d)", ec, ec->maximized);
+/* End of Xdg_Popup */
 
-   ds_xdg_toplevel_v6_set_maximized(ds_toplevel, ec->maximized);
+/**********************************************************
+ * Implementation for Xdg_toplevel
+ ***********************************************************/
+static void
+_e_xdg_toplevel_set(E_Xdg_Toplevel *toplevel, struct wl_resource *resource)
+{
+   toplevel->resource = resource;
+   _e_client_xdg_shell_v6_assign(toplevel->base.ec, resource, E_COMP_WL_SH_SURF_ROLE_TOPLV);
+   e_shell_e_client_toplevel_set(toplevel->base.ec);
+   e_comp_wl_shell_surface_ready(toplevel->base.ec);
 }
 
 static void
-_e_xdg_toplevel_v6_resizing_send(E_Xdg_Toplevel_V6 *toplevel, Eina_Bool resizing)
+_e_xdg_toplevel_committed(E_Xdg_Toplevel *toplevel)
 {
-   struct ds_xdg_toplevel_v6 *ds_toplevel = toplevel->ds_toplevel;
+   E_Client *ec;
+   E_Comp_Wl_Client_Data *cdata;
+   int pw, ph;
 
-   if (ds_toplevel->scheduled.resizing == resizing)
-     return;
+   ec = toplevel->base.ec;
+   if (!ec)
+     {
+        ERR("E_Xdg_Toplevel must have E_Client", NULL);
+        return;
+     }
+
+   cdata = e_client_cdata_get(ec);
+   if (!cdata)
+     {
+        ERR("E_Client must have E_Comp_Wl_Client_Data", ec);
+        return;
+     }
+
+   if (!toplevel->resource)
+     {
+        ERR("E_Client must have xdg_toplevel instance", ec);
+        return;
+     }
+
+   if (!e_pixmap_usable_get(ec->pixmap))
+     {
+        ERR("E_Pixmap should be valid here", ec);
+        return;
+     }
+
+   e_pixmap_size_get(ec->pixmap, &pw, &ph);
 
-   LOG("Send resizing(%d)", toplevel->ec, resizing);
+   if ((toplevel->next.state.maximized || toplevel->next.state.fullscreen) &&
+        (toplevel->next.size.w != cdata->shell.window.w ||
+        toplevel->next.size.h != cdata->shell.window.h ||
+        toplevel->next.size.w != pw ||
+        toplevel->next.size.h != ph))
+     {
+        ERR("Xdg_surface buffer does not match the configured state\nmaximized: "
+            "%d fullscreen: %d, size:expected(%d %d) shell.request(%d %d) pixmap(%d %d)",
+            ec,
+            toplevel->next.state.maximized,
+            toplevel->next.state.fullscreen,
+            toplevel->next.size.w, toplevel->next.size.h,
+            cdata->shell.window.w, cdata->shell.window.h,
+            pw, ph);
+        /* TODO Disable this part for now, but need to consider enabling it later.
+         * To enable this part, we first need to ensure that do not send configure
+         * with argument of size as 0, and make client ensure that set
+         * window geometry correctly so that match its commit buffer size, if
+         * its state is maximize or fullscreen.
+         */
+        /*
+           wl_resource_post_error(toplevel->base.shell->resource,
+           ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
+           "xdg_surface buffer does not match the configured state");
+           return;
+           */
+     }
+   toplevel->current.state = toplevel->next.state;
+   toplevel->current.min_size = toplevel->next.min_size;
+   toplevel->current.max_size = toplevel->next.max_size;
 
-   ds_xdg_toplevel_v6_set_resizing(ds_toplevel, resizing);
+   /* Now we can adjust size of its composite object corresponding client */
+   if (!ec->lock_client_size)
+      {
+         ec->icccm.min_w = toplevel->current.min_size.w;
+         ec->icccm.min_h = toplevel->current.min_size.h;
+         ec->icccm.max_w = toplevel->current.max_size.w;
+         ec->icccm.max_h = toplevel->current.max_size.h;
+      }
 }
 
 static void
-_e_xdg_toplevel_v6_activated_send(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_toplevel_configure_ack(E_Xdg_Toplevel *toplevel,
+                              E_Xdg_Surface_Configure *configure)
 {
-   struct ds_xdg_toplevel_v6 *ds_toplevel = toplevel->ds_toplevel;
-   E_Client *ec = toplevel->ec, *focused_ec;
-   Eina_Bool activated;
+   LOG("Ack configure TOPLEVEL size (%d %d) "
+       "state (f %d m %d r %d a %d)",
+       toplevel->base.ec,
+       configure->size.w, configure->size.h,
+       configure->state.fullscreen, configure->state.maximized,
+       configure->state.resizing, configure->state.activated);
+
+   toplevel->next.state = configure->state;
+   toplevel->next.size = configure->size;
+   toplevel->base.wait_next_commit = EINA_TRUE;
+}
 
-   focused_ec = e_client_focused_get();
-   activated = (focused_ec == ec);
+static void
+_e_xdg_toplevel_configure_send(E_Xdg_Toplevel *toplevel,
+                               E_Xdg_Surface_Configure *configure)
+{
+   uint32_t *s;
+   struct wl_array states;
+   Eina_Bool array_added = EINA_FALSE;
 
-   if (ds_toplevel->scheduled.activated == activated)
-     return;
+   if (!toplevel->resource) return;
+
+   configure->state = toplevel->pending.state;
+   configure->size = toplevel->pending.size;
+
+   wl_array_init(&states);
+   if (toplevel->pending.state.maximized)
+     {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        if (!s) goto err;
+        array_added = EINA_TRUE;
+        *s = ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED;
+     }
+   if (toplevel->pending.state.fullscreen)
+     {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        if (!s) goto err;
+        array_added = EINA_TRUE;
+        *s = ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN;
+     }
+   if (toplevel->pending.state.resizing)
+     {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        if (!s) goto err;
+        array_added = EINA_TRUE;
+        *s = ZXDG_TOPLEVEL_V6_STATE_RESIZING;
+     }
+   if (toplevel->pending.state.activated)
+     {
+        s = wl_array_add(&states, sizeof(uint32_t));
+        if (!s) goto err;
+        *s = ZXDG_TOPLEVEL_V6_STATE_ACTIVATED;
+     }
+
+   LOG("Send configure: Topevel size (%d %d) "
+       "state (f %d m %d r %d a %d)",
+       toplevel->base.ec,
+       toplevel->pending.size.w, toplevel->pending.size.h,
+       toplevel->pending.state.fullscreen, toplevel->pending.state.maximized,
+       toplevel->pending.state.resizing, toplevel->pending.state.activated);
+
+   zxdg_toplevel_v6_send_configure(toplevel->resource,
+                                   toplevel->pending.size.w,
+                                   toplevel->pending.size.h,
+                                   &states);
 
-   LOG("Send activated(%d)", ec, activated);
+   wl_array_release(&states);
 
-   ds_xdg_toplevel_v6_set_activated(ds_toplevel, activated);
+   // clear toplevel's pending size
+   toplevel->pending.size.w = 0;
+   toplevel->pending.size.h = 0;
+
+   return;
+
+err:
+   ERR("Failed on adding item to states !",  toplevel->base.ec);
+   if (array_added) wl_array_release(&states);
+   return;
 }
 
 static void
-_e_xdg_toplevel_v6_size_send(E_Xdg_Toplevel_V6 *toplevel, int32_t width, int32_t height)
+_e_xdg_toplevel_configure_pending_set(E_Xdg_Toplevel *toplevel,
+                                      uint32_t edges,
+                                      int32_t width,
+                                      int32_t height)
 {
-   E_Client *ec = toplevel->ec;
-   struct ds_xdg_toplevel_v6 *ds_toplevel = toplevel->ds_toplevel;
-   int32_t configure_width = 0, configure_height = 0;
+   E_Client *ec, *focused;
    int mw, mh;
 
+   ec = toplevel->base.ec;
+
+   toplevel->pending.state.fullscreen = ec->fullscreen;
+   toplevel->pending.state.maximized = !!ec->maximized;
+   toplevel->pending.state.resizing = !!edges;
+   toplevel->pending.edges = edges;
    if ((width != -1) && (height != -1))
      {
-        configure_width = width;
-        configure_height = height;
+        /* NOTE:
+         * Width and Height are -1 means that the configure event doesn't consider size value.
+         * So, we update pending size if the size are not -1.
+         */
+        toplevel->pending.size.w = width;
+        toplevel->pending.size.h = height;
      }
 
    if (ec->fullscreen)
@@ -217,551 +504,1602 @@ _e_xdg_toplevel_v6_size_send(E_Xdg_Toplevel_V6 *toplevel, int32_t width, int32_t
         LOG("FORCELY STAY current fullscreen size (%d %d) of E_Client, requested size "
             "is (%d %d), the state (maximize %d, fullscreen %d)",
             ec, mw, mh, width, height, ec->maximized, ec->fullscreen);
-        configure_width = mw;
-        configure_height = mh;
+        toplevel->pending.size.w = mw;
+        toplevel->pending.size.h = mh;
      }
    else if (ec->maximized)
      {
+        /* NOTE
+         * DO NOT configure maximized or fullscreen surface to (0x0) size.
+         * If the width or height arguments are zero, it means the client should
+         * decide its own window dimension. See xdg-shell-v6.xml
+         */
         e_client_maximized_geometry_get(ec, NULL, NULL, &mw, &mh);
         LOG("FORCELY STAY current maximized size (%d %d) of E_Client, requested size "
             "is (%d %d), the state (maximize %d, fullscreen %d)",
-            ec, mw, mh, width, height, ec->maximized, ec->fullscreen);
-        configure_width = mw;
-        configure_height = mh;
+            ec, mw, mh, width, height,
+            toplevel->pending.state.maximized,
+            toplevel->pending.state.fullscreen);
+        toplevel->pending.size.w = mw;
+        toplevel->pending.size.h = mh;
      }
 
-   LOG("Send size(%dx%d)", ec, configure_width, configure_height);
+   focused = e_client_focused_get();
+   toplevel->pending.state.activated = (ec == focused);
 
-   ds_xdg_toplevel_v6_set_size(ds_toplevel, configure_width, configure_height);
+   LOG("Set pending state: edges %d size (%d %d) "
+       "state (f %d m %d r %d a %d)",
+       ec,
+       toplevel->pending.edges,
+       toplevel->pending.size.w, toplevel->pending.size.h,
+       toplevel->pending.state.fullscreen, toplevel->pending.state.maximized,
+       toplevel->pending.state.resizing, toplevel->pending.state.activated);
 }
 
-static void
-_e_xdg_toplevel_v6_configure_send(struct wl_resource *shsurface_resource,
-                                  uint32_t edges, int32_t width, int32_t height)
+static Eina_Bool
+_e_xdg_toplevel_pending_state_compare(E_Xdg_Toplevel *toplevel)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Surface_Configure *configure;
+   int pw, ph;
+   int cw, ch;
 
-   toplevel = _e_xdg_toplevel_v6_from_shell_surface_resource(shsurface_resource);
-   if (!toplevel)
-     return;
+   struct {
+        E_Xdg_Toplevel_State state;
+        E_Xdg_Size size;
+   } configured;
 
-   _e_xdg_toplevel_v6_fullscreen_send(toplevel);
-   _e_xdg_toplevel_v6_maximized_send(toplevel);
-   _e_xdg_toplevel_v6_resizing_send(toplevel, !!edges);
-   _e_xdg_toplevel_v6_size_send(toplevel, width, height);
-   _e_xdg_toplevel_v6_activated_send(toplevel);
-}
+   /* must send configure at least once */
+   if (!toplevel->base.configured)
+     return EINA_FALSE;
 
-static void
-_e_xdg_toplevel_v6_configure(struct wl_resource *shsurface_resource,
-                             Evas_Coord x, Evas_Coord y,
-                             Evas_Coord w, Evas_Coord h)
-{
-   E_Xdg_Toplevel_V6 *toplevel;
+   if (!toplevel->base.configure_list)
+     {
+        /* if configure_list is empty, last configure is actually the current
+         * state */
+        e_pixmap_size_get(toplevel->base.ec->pixmap, &pw, &ph);
+        e_client_geometry_get(toplevel->base.ec, NULL, NULL, &cw, &ch);
+
+        if ((pw != cw) || (ph != ch))
+          {
+             ERR("The size of buffer is different with expected "
+                 "client size. So, here, let it compare with buffer size.",
+                 toplevel->base.ec);
+          }
+
+        configured.state = toplevel->current.state;
+        configured.size.w = pw;
+        configured.size.h = ph;
+     }
+   else
+     {
+        configure = eina_list_last_data_get(toplevel->base.configure_list);
+        configured.state = configure->state;
+        configured.size = configure->size;
+     }
 
-   toplevel = _e_xdg_toplevel_v6_from_shell_surface_resource(shsurface_resource);
-   if (!toplevel)
-     return;
+   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))
+     {
+        if (!toplevel->base.ec->changes.size)
+          return EINA_TRUE;
+     }
+
+   if ((toplevel->pending.size.w == 0) &&
+       (toplevel->pending.size.h == 0))
+     return EINA_TRUE;
 
-   e_client_util_move_resize_without_frame(toplevel->ec, x, y, w, h);
+   return EINA_FALSE;
 }
 
 static void
-_e_xdg_toplevel_v6_ping(struct wl_resource *shsurface_resource)
+_e_xdg_toplevel_cb_resource_destroy(struct wl_resource *resource)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Toplevel *toplevel;
 
-   toplevel = _e_xdg_toplevel_v6_from_shell_surface_resource(shsurface_resource);
-   if (!toplevel)
-     return;
-
-   LOG("Ping", toplevel->ec);
+   toplevel = wl_resource_get_user_data(resource);
+   toplevel->resource = NULL;
+   _e_client_xdg_shell_v6_role_assingment_unset(toplevel->base.ec);
+   e_object_unref(E_OBJECT(toplevel));
+}
 
-   ds_xdg_surface_v6_ping(toplevel->ds_toplevel->base);
+static void
+_e_xdg_toplevel_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+   wl_resource_destroy(resource);
 }
 
 static void
-_e_xdg_surface_v6_map(struct wl_resource *shsurface_resource)
+_e_xdg_toplevel_cb_parent_set(struct wl_client *client,
+                              struct wl_resource *resource,
+                              struct wl_resource *res_parent)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Toplevel *toplevel, *parent;
+   E_Client *pc;
+   E_Comp_Wl_Client_Data *pc_cdata;
+   struct wl_resource *parent_wsurface = NULL;
 
-   toplevel = _e_xdg_toplevel_v6_from_shell_surface_resource(shsurface_resource);
+   toplevel = wl_resource_get_user_data(resource);
    if (!toplevel)
      return;
 
-   LOG("Map", toplevel->ec);
+   if (res_parent)
+     {
+        parent = wl_resource_get_user_data(res_parent);
+        if (!parent)
+          {
+             ERR("No E_Xdg_Toplevel data in wl_resource", NULL);
+             wl_resource_post_error(res_parent,
+                                    WL_DISPLAY_ERROR_INVALID_OBJECT,
+                                    "No E_Xdg_Toplevel data in wl_resource");
+
+             return;
+          }
+
+        pc = parent->base.ec;
+        if (!pc)
+          {
+             ERR("Toplevel must have E_Client", NULL);
+             wl_resource_post_error(res_parent,
+                                    WL_DISPLAY_ERROR_INVALID_OBJECT,
+                                    "No E_Client data in wl_resource");
+             return;
+          }
+
+        pc_cdata = e_client_cdata_get(pc);
+        if (!pc_cdata) return;
+
+        parent_wsurface = pc_cdata->surface;
+     }
+
+   /* set this client as a transient for parent */
+   e_shell_e_client_parent_set(toplevel->base.ec, parent_wsurface);
 
-   toplevel->ds_toplevel->base->mapped = true;
-   e_shell_e_client_map(toplevel->ec);
+   EC_CHANGED(toplevel->base.ec);
 }
 
 static void
-_e_xdg_toplevel_v6_unmap(struct wl_resource *shsurface_resource)
+_e_xdg_toplevel_cb_title_set(struct wl_client *client,
+                             struct wl_resource *resource,
+                             const char *title)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Toplevel *toplevel;
 
-   toplevel = _e_xdg_toplevel_v6_from_shell_surface_resource(shsurface_resource);
+   toplevel = wl_resource_get_user_data(resource);
    if (!toplevel)
      return;
 
-   LOG("Unmap", toplevel->ec);
-
-   toplevel->ds_toplevel->base->mapped = false;
-   e_shell_e_client_unmap(toplevel->ec);
+   e_shell_e_client_name_title_set(toplevel->base.ec, title, title);
 }
 
-static E_Shell_Surface_Api shell_xdg_toplevel_v6_api = {
-     .configure_send = _e_xdg_toplevel_v6_configure_send,
-     .configure = _e_xdg_toplevel_v6_configure,
-     .ping = _e_xdg_toplevel_v6_ping,
-     .map = _e_xdg_surface_v6_map,
-     .unmap = _e_xdg_toplevel_v6_unmap,
-};
-
 static void
-_e_xdg_toplevel_v6_role_init(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_toplevel_cb_app_id_set(struct wl_client *client,
+                              struct wl_resource *resource,
+                              const char *app_id)
 {
-   E_Client *ec = toplevel->ec;
-   struct ds_xdg_surface_v6 *ds_xdg_surface = toplevel->ds_toplevel->base;
-   struct ds_xdg_toplevel_v6 *ds_toplevel = toplevel->ds_toplevel;
-   E_Comp_Wl_Client_Data *cdata;
+   E_Xdg_Toplevel *toplevel;
+   E_Client *ec;
 
-   e_shell_e_client_shsurface_assign(ec,
-                                     ds_xdg_surface->resource,
-                                     &shell_xdg_toplevel_v6_api);
+   toplevel = wl_resource_get_user_data(resource);
+   if (!toplevel)
+     return;
 
-   cdata = e_client_cdata_get(ec);
-   if (cdata)
+   ec = toplevel->base.ec;
+   if (!ec)
      {
-        cdata->sh_v6.res_role = ds_toplevel->resource;
-        cdata->sh_v6.role = E_COMP_WL_SH_SURF_ROLE_TOPLV;
+        ERR("Toplevel must have E_Client", NULL);
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Client data in wl_resource");
+        return;
      }
 
-   e_shell_e_client_toplevel_set(ec);
-   e_comp_wl_shell_surface_ready(toplevel->ec);
+   /* use the wl_client to get the pid * and set it in the netwm props */
+   wl_client_get_credentials(client, &ec->netwm.pid, NULL, NULL);
+
+   e_shell_e_client_app_id_set(ec, app_id);
 }
 
 static void
-_e_xdg_toplevel_v6_client_parent_update(E_Xdg_Toplevel_V6 *toplevel)
+_e_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)
 {
-   E_Client *ec = toplevel->ec;
-   struct ds_xdg_toplevel_v6 *parent = toplevel->ds_toplevel->parent;
-   struct wl_resource *parent_surface_resource = NULL;
-
-   if (parent)
-     parent_surface_resource = parent->base->ds_surface->resource;
-
-   LOG("Set parent: resource(%p)", ec, parent_surface_resource);
-
-   e_shell_e_client_parent_set(ec, parent_surface_resource);
-   EC_CHANGED(ec);
+   /* TODO no op */
 }
 
 static void
-_e_xdg_toplevel_v6_title_update(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_toplevel_cb_move(struct wl_client *client,
+                        struct wl_resource *resource,
+                        struct wl_resource *res_seat,
+                        uint32_t serial)
 {
-   E_Client *ec = toplevel->ec;
-   char *title = toplevel->ds_toplevel->title;
+   E_Xdg_Toplevel *toplevel;
 
-   LOG("Set title: %s", ec, title ? title : "(null)");
+   toplevel = wl_resource_get_user_data(resource);
+   if (!toplevel)
+     return;
 
-   e_shell_e_client_name_title_set(ec, title, title);
+   if (!e_shell_e_client_interactive_move(toplevel->base.ec, res_seat))
+     {
+        ERR("Failed to move this Toplevel", NULL);
+        return;
+     }
 }
 
 static void
-_e_xdg_toplevel_v6_app_id_update(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_toplevel_cb_resize(struct wl_client *client,
+                          struct wl_resource *resource,
+                          struct wl_resource *res_seat,
+                          uint32_t serial,
+                          uint32_t edges)
 {
-   E_Client *ec = toplevel->ec;
-   char *app_id = toplevel->ds_toplevel->app_id;
-   struct wl_client *client;
-
-   client = wl_resource_get_client(toplevel->ds_toplevel->resource);
-   wl_client_get_credentials(client, &ec->netwm.pid, NULL, NULL);
+   E_Xdg_Toplevel *toplevel;
 
-   LOG("Set app_id: %s, PID(%d)", ec, app_id ? app_id : "(null)", ec->netwm.pid);
+   toplevel = wl_resource_get_user_data(resource);
+   if (!toplevel)
+     return;
 
-   e_shell_e_client_app_id_set(ec, app_id);
+   if (!e_shell_e_client_interactive_resize(toplevel->base.ec, resource, res_seat, edges))
+     {
+        ERR("Failed to resize this Toplevel", NULL);
+        return;
+     }
 }
 
 static void
-_e_xdg_toplevel_v6_move_begin(E_Xdg_Toplevel_V6 *toplevel, struct wl_resource *seat_resource)
+_e_xdg_toplevel_cb_max_size_set(struct wl_client *client,
+                                struct wl_resource *resource,
+                                int32_t w,
+                                int32_t h)
 {
-   E_Client *ec = toplevel->ec;
+   E_Xdg_Toplevel *toplevel;
 
-   LOG("Begin interactive move", ec);
+   toplevel = wl_resource_get_user_data(resource);
+   if (!toplevel)
+     return;
 
-   if (!e_shell_e_client_interactive_move(ec, seat_resource))
-     ERR("Failed to move this Toplevel(%p)", ec, toplevel);
+   toplevel->next.max_size.w = w;
+   toplevel->next.max_size.h = h;
+   toplevel->base.wait_next_commit = EINA_TRUE;
 }
 
 static void
-_e_xdg_toplevel_v6_resize_begin(E_Xdg_Toplevel_V6 *toplevel, struct wl_resource *seat_resource, uint32_t edges)
+_e_xdg_toplevel_cb_min_size_set(struct wl_client *client,
+                                struct wl_resource *resource,
+                                int32_t w,
+                                int32_t h)
 {
-   E_Client *ec = toplevel->ec;
-   struct wl_resource *toplevel_resource = toplevel->ds_toplevel->resource;
+   E_Xdg_Toplevel *toplevel;
 
-   LOG("Begin interactive resize", ec);
+   toplevel = wl_resource_get_user_data(resource);
+   if (!toplevel)
+     return;
 
-   if (!e_shell_e_client_interactive_resize(ec, toplevel_resource, seat_resource, edges))
-     ERR("Failed to move this Toplevel(%p)", ec, toplevel);
+   toplevel->next.min_size.w = w;
+   toplevel->next.min_size.h = h;
+   toplevel->base.wait_next_commit = EINA_TRUE;
 }
 
 static void
-_e_xdg_toplevel_v6_maximize_set(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_toplevel_cb_maximized_set(struct wl_client *client, struct wl_resource *resource)
 {
-   E_Client *ec = toplevel->ec;
-   E_Maximize max = (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_BOTH;
-
-   LOG("Set maximize. lock_user_maximize:%d, dir:%d",
-       ec, ec->lock_user_maximize, ec->maximize_dir);
+   E_Xdg_Toplevel *toplevel;
+   E_Client *ec;
+   E_Maximize max;
 
-   if (ec->lock_user_maximize)
+   toplevel = wl_resource_get_user_data(resource);
+   if (!toplevel)
      return;
 
-   if ((ec->maximize_dir != E_MAXIMIZE_DIRECTION_ALL) &&
-       (ec->maximize_dir != E_MAXIMIZE_DIRECTION_NONE))
-     return;
+   ec = toplevel->base.ec;
+   if (!ec)
+     {
+        ERR("Toplevel must have E_Client", NULL);
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Client data in wl_resource");
+        return;
+     }
 
-   e_client_layout_apply(ec, EINA_FALSE);
-   e_client_maximize(ec, max);
+   ELOGF("XDG6", "Toplevel Maximized Set. res:%p, lock_user_maximize:%d, dir:%d", ec, resource, ec->lock_user_maximize, ec->maximize_dir);
+   if (!ec->lock_user_maximize)
+     {
+        if ((ec->maximize_dir == E_MAXIMIZE_DIRECTION_ALL) || (ec->maximize_dir == E_MAXIMIZE_DIRECTION_NONE))
+          {
+             e_client_layout_apply(ec, EINA_FALSE);
+
+             max = (e_config->maximize_policy & E_MAXIMIZE_TYPE) | E_MAXIMIZE_BOTH;
+             e_client_maximize(ec, max);
+          }
+     }
 }
 
 static void
-_e_xdg_toplevel_v6_maximize_unset(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_toplevel_cb_maximized_unset(struct wl_client *client, struct wl_resource *resource)
 {
-   E_Client *ec = toplevel->ec;
+   E_Xdg_Toplevel *toplevel;
+   E_Client *ec;
+
+   toplevel = wl_resource_get_user_data(resource);
+   if (!toplevel)
+     return;
 
-   LOG("Unset maximize. lock_user_maximize:%d", ec, ec->lock_user_maximize);
+   ec = toplevel->base.ec;
+   if (!ec)
+     {
+        ERR("Toplevel must have E_Client", NULL);
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Client data in wl_resource");
+        return;
+     }
 
    e_client_layout_apply(ec, EINA_FALSE);
 
+   ELOGF("XDG6", "Toplevel Maximized Unset. res:%p, lock_user_maximize:%d", ec, resource, ec->lock_user_maximize);
+
    ec->maximize_dir = E_MAXIMIZE_DIRECTION_NONE;
    /* it's doubtful */
    e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
 }
 
 static void
-_e_xdg_toplevel_v6_fullscreen_set(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_toplevel_cb_fullscreen_set(struct wl_client *client,
+                                  struct wl_resource *resource,
+                                  struct wl_resource *res_output)
 {
-   E_Client *ec = toplevel->ec;
-
-   LOG("Set fullscreen. lock_user_fullscreen:%d", ec, ec->lock_user_fullscreen);
+   E_Xdg_Toplevel *toplevel;
+   E_Client *ec;
 
-   if (ec->lock_user_fullscreen)
+   toplevel = wl_resource_get_user_data(resource);
+   if (!toplevel)
      return;
 
-   e_client_fullscreen(ec, e_config->fullscreen_policy);
+   ec = toplevel->base.ec;
+   if (!ec)
+     {
+        ERR("Toplevel must have E_Client", NULL);
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Client data in wl_resource");
+        return;
+     }
+
+   ELOGF("XDG6", "Toplevel Fullscreen Set. res:%p, lock_user_fullscreen:%d", ec, resource, ec->lock_user_fullscreen);
+   if (!ec->lock_user_fullscreen)
+     e_client_fullscreen(ec, e_config->fullscreen_policy);
 }
 
 static void
-_e_xdg_toplevel_v6_fullscreen_unset(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_toplevel_cb_fullscreen_unset(struct wl_client *client, struct wl_resource *resource)
 {
-   E_Client *ec = toplevel->ec;
-
-   LOG("Unset fullscreen. lock_user_fullscreen:%d", ec, ec->lock_user_fullscreen);
+   E_Xdg_Toplevel *toplevel;
+   E_Client *ec;
 
-   if (ec->lock_user_fullscreen)
+   toplevel = wl_resource_get_user_data(resource);
+   if (!toplevel)
      return;
 
-   e_client_unfullscreen(ec);
+   ec = toplevel->base.ec;
+   if (!ec)
+     {
+        ERR("Toplevel must have E_Client", NULL);
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Client data in wl_resource");
+        return;
+     }
+
+   ELOGF("XDG6", "Toplevel Fullscreen Unset. res:%p, lock_user_fullscreen:%d", ec, resource, ec->lock_user_fullscreen);
+   if (!ec->lock_user_fullscreen)
+     e_client_unfullscreen(ec);
 }
 
 static void
-_e_xdg_toplevel_v6_minimize_set(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_toplevel_cb_minimized_set(struct wl_client *client, struct wl_resource *resource)
 {
-   E_Client *ec = toplevel->ec;
-
-   LOG("Set minimize. lock_client_iconify:%d", ec, ec->lock_client_iconify);
+   E_Xdg_Toplevel *toplevel;
+   E_Client *ec;
 
-   if (ec->lock_client_iconify)
+   toplevel = wl_resource_get_user_data(resource);
+   if (!toplevel)
      return;
 
-   e_client_iconify(ec);
+   ec = toplevel->base.ec;
+   if (!ec)
+     {
+        ERR("Toplevel must have E_Client", NULL);
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Client data in wl_resource");
+        return;
+     }
+
+   ELOGF("XDG6", "Toplevel Minimized Set. res:%p, lock_client_iconify:%d", ec, resource, ec->lock_client_iconify);
+   if (!ec->lock_client_iconify)
+     e_client_iconify(ec);
 }
 
-static void
-_e_xdg_toplevel_v6_window_geometry_update(E_Xdg_Toplevel_V6 *toplevel)
+static const struct zxdg_toplevel_v6_interface _e_xdg_toplevel_interface =
 {
-   struct ds_xdg_surface_v6 *ds_xdg_surface = toplevel->ds_toplevel->base;
-   E_Comp_Wl_Client_Data *cdata;
-
-   cdata = e_client_cdata_get(toplevel->ec);
-   if (!cdata)
-     return;
+   _e_xdg_toplevel_cb_destroy,
+   _e_xdg_toplevel_cb_parent_set,
+   _e_xdg_toplevel_cb_title_set,
+   _e_xdg_toplevel_cb_app_id_set,
+   _e_xdg_toplevel_cb_win_menu_show,
+   _e_xdg_toplevel_cb_move,
+   _e_xdg_toplevel_cb_resize,
+   _e_xdg_toplevel_cb_max_size_set,
+   _e_xdg_toplevel_cb_min_size_set,
+   _e_xdg_toplevel_cb_maximized_set,
+   _e_xdg_toplevel_cb_maximized_unset,
+   _e_xdg_toplevel_cb_fullscreen_set,
+   _e_xdg_toplevel_cb_fullscreen_unset,
+   _e_xdg_toplevel_cb_minimized_set
+};
 
-   EINA_RECTANGLE_SET(&cdata->shell.window,
-                      ds_xdg_surface->current.geometry.x,
-                      ds_xdg_surface->current.geometry.y,
-                      ds_xdg_surface->current.geometry.width,
-                      ds_xdg_surface->current.geometry.height);
-}
+/* End of Xdg_toplevel */
 
-static void
-_e_xdg_toplevel_v6_min_max_size_update(E_Xdg_Toplevel_V6 *toplevel)
+/**********************************************************
+ * Implementation for Xdg_Positioner
+ **********************************************************/
+static Eina_Rectangle
+_e_xdg_positioner_geometry_get(E_Xdg_Positioner *p)
 {
-   E_Client *ec = toplevel->ec;
-   struct ds_xdg_toplevel_v6 *ds_toplevel = toplevel->ds_toplevel;
+   Eina_Rectangle geometry = {
+        .x = p->offset.x,
+        .y = p->offset.y,
+        .w = p->size.w,
+        .h = p->size.h,
+   };
+
+   if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_TOP)
+     geometry.y += p->anchor_rect.y;
+   else if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)
+     geometry.y += p->anchor_rect.y + p->anchor_rect.h;
+   else
+     geometry.y += p->anchor_rect.y + p->anchor_rect.h / 2;
 
-   if (!ec->lock_client_size)
-     return;
+   if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_LEFT)
+     geometry.x += p->anchor_rect.x;
+   else if (p->anchor & ZXDG_POSITIONER_V6_ANCHOR_RIGHT)
+     geometry.x += p->anchor_rect.x + p->anchor_rect.w;
+   else
+     geometry.x += p->anchor_rect.x + p->anchor_rect.w / 2;
+
+   if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_TOP)
+     geometry.y -= geometry.h;
+   else if (!(p->gravity & ZXDG_POSITIONER_V6_GRAVITY_BOTTOM))
+     geometry.y = geometry.h / 2;
+
+   if (p->gravity & ZXDG_POSITIONER_V6_GRAVITY_LEFT)
+     geometry.x -= geometry.w;
+   else if (!(p->gravity & ZXDG_POSITIONER_V6_GRAVITY_RIGHT))
+     geometry.x = geometry.w / 2;
+
+   if (p->constraint_adjustment == ZXDG_POSITIONER_V6_CONSTRAINT_ADJUSTMENT_NONE)
+     return geometry;
 
-   ec->icccm.min_w = ds_toplevel->current.min_width;
-   ec->icccm.min_h = ds_toplevel->current.min_height;
-   ec->icccm.max_w = ds_toplevel->current.max_width;
-   ec->icccm.max_h = ds_toplevel->current.max_height;
+   /* TODO: According to weston, add compositor policy configuration and the
+    * code here
+    */
+
+   return geometry;
 }
 
-static void
-_e_xdg_toplevel_v6_cb_set_parent(struct wl_listener *listener, void *data)
+static Eina_Bool
+_e_xdg_positioner_validation_check(E_Xdg_Positioner *p)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
-
-   toplevel = wl_container_of(listener, toplevel, set_parent);
-   _e_xdg_toplevel_v6_client_parent_update(toplevel);
+   return ((p->size.w != 0) && (p->anchor_rect.w != 0));
 }
 
 static void
-_e_xdg_toplevel_v6_cb_set_title(struct wl_listener *listener, void *data)
+_e_xdg_positioner_cb_resource_destroy(struct wl_resource *resource)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Positioner *p;
+
+   p = wl_resource_get_user_data(resource);
+   EINA_SAFETY_ON_NULL_RETURN(p);
 
-   toplevel = wl_container_of(listener, toplevel, set_title);
-   _e_xdg_toplevel_v6_title_update(toplevel);
+   if (!p->shell)
+     goto finish;
+
+   p->shell->positioners = eina_list_remove(p->shell->positioners, p);
+
+finish:
+   free(p);
 }
 
 static void
-_e_xdg_toplevel_v6_cb_set_app_id(struct wl_listener *listener, void *data)
+_e_xdg_positioner_cb_destroy(struct wl_client *client, struct wl_resource *resource)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
-
-   toplevel = wl_container_of(listener, toplevel, set_app_id);
-   _e_xdg_toplevel_v6_app_id_update(toplevel);
+   wl_resource_destroy(resource);
 }
 
 static void
-_e_xdg_toplevel_v6_cb_request_move(struct wl_listener *listener, void *data)
+_e_xdg_positioner_cb_size_set(struct wl_client *client,
+                              struct wl_resource *resource,
+                              int32_t w, int32_t h)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
-   struct ds_xdg_toplevel_v6_event_request_move *event = data;
+   E_Xdg_Positioner *p;
+
+   _validate_size(resource, w);
+   _validate_size(resource, h);
 
-   toplevel = wl_container_of(listener, toplevel, request_move);
-   _e_xdg_toplevel_v6_move_begin(toplevel, event->seat_resource);
+   p = wl_resource_get_user_data(resource);
+   p->size.w = w;
+   p->size.h = h;
 }
 
 static void
-_e_xdg_toplevel_v6_cb_request_resize(struct wl_listener *listener, void *data)
+_e_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)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
-   struct ds_xdg_toplevel_v6_event_request_resize *event = data;
+   E_Xdg_Positioner *p;
 
-   toplevel = wl_container_of(listener, toplevel, request_resize);
-   _e_xdg_toplevel_v6_resize_begin(toplevel, event->seat_resource, event->edges);
+   _validate_size(resource, w);
+   _validate_size(resource, h);
+
+   p = wl_resource_get_user_data(resource);
+   EINA_RECTANGLE_SET(&p->anchor_rect, x, y, w, h);
 }
 
 static void
-_e_xdg_toplevel_v6_cb_request_maximize(struct wl_listener *listener, void *data)
+_e_xdg_positioner_cb_anchor_set(struct wl_client *client,
+                                struct wl_resource *resource,
+                                enum zxdg_positioner_v6_anchor anchor)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Positioner *p;
 
-   toplevel = wl_container_of(listener, toplevel, request_maximize);
-   if (toplevel->ds_toplevel->requested.maximized)
-     _e_xdg_toplevel_v6_maximize_set(toplevel);
+   if ((anchor & (ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_BOTTOM)) ==
+       (ZXDG_POSITIONER_V6_ANCHOR_TOP | ZXDG_POSITIONER_V6_ANCHOR_BOTTOM))
+     {
+        wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+                               "Invalid anchor values passed");
+     }
+   else if ((anchor & (ZXDG_POSITIONER_V6_ANCHOR_LEFT | ZXDG_POSITIONER_V6_ANCHOR_RIGHT)) ==
+            (ZXDG_POSITIONER_V6_ANCHOR_LEFT | ZXDG_POSITIONER_V6_ANCHOR_RIGHT))
+     {
+        wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+                               "Invalid anchor values passed");
+     }
    else
-     _e_xdg_toplevel_v6_maximize_unset(toplevel);
+     {
+        p = wl_resource_get_user_data(resource);
+        p->anchor = anchor;
+     }
 }
 
 static void
-_e_xdg_toplevel_v6_cb_request_fullscreen(struct wl_listener *listener, void *data)
+_e_xdg_positioner_cb_gravity_set(struct wl_client *client,
+                                 struct wl_resource *resource,
+                                 enum zxdg_positioner_v6_gravity gravity)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Positioner *p;
 
-   toplevel = wl_container_of(listener, toplevel, request_fullscreen);
-   if (toplevel->ds_toplevel->requested.fullscreen)
-     _e_xdg_toplevel_v6_fullscreen_set(toplevel);
+   if ((gravity & (ZXDG_POSITIONER_V6_GRAVITY_TOP | ZXDG_POSITIONER_V6_GRAVITY_BOTTOM)) ==
+       (ZXDG_POSITIONER_V6_GRAVITY_TOP | ZXDG_POSITIONER_V6_GRAVITY_BOTTOM))
+     {
+        wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+                               "Invalid gravity values passed");
+     }
+   else if ((gravity & (ZXDG_POSITIONER_V6_GRAVITY_LEFT | ZXDG_POSITIONER_V6_GRAVITY_RIGHT)) ==
+            (ZXDG_POSITIONER_V6_GRAVITY_LEFT | ZXDG_POSITIONER_V6_GRAVITY_RIGHT))
+     {
+        wl_resource_post_error(resource, ZXDG_POSITIONER_V6_ERROR_INVALID_INPUT,
+                               "Invalid gravity values passed");
+     }
    else
-     _e_xdg_toplevel_v6_fullscreen_unset(toplevel);
+     {
+        p = wl_resource_get_user_data(resource);
+        p->gravity = gravity;
+     }
 }
 
 static void
-_e_xdg_toplevel_v6_cb_request_minimize(struct wl_listener *listener, void *data)
+_e_xdg_positioner_cb_constraint_adjustment_set(struct wl_client *client,
+                                               struct wl_resource *resource,
+                                               enum zxdg_positioner_v6_constraint_adjustment constraint_adjustment)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Positioner *p;
 
-   toplevel = wl_container_of(listener, toplevel, request_minimize);
-   _e_xdg_toplevel_v6_minimize_set(toplevel);
+   p = wl_resource_get_user_data(resource);
+   p->constraint_adjustment = constraint_adjustment;
 }
 
 static void
-_e_xdg_toplevel_v6_cb_configure(struct wl_listener *listener, void *data)
+_e_xdg_positioner_cb_offset_set(struct wl_client *client,
+                                struct wl_resource *resource,
+                                int32_t x, int32_t y)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
-   struct ds_xdg_surface_v6 *ds_xdg_surface;
-   struct ds_xdg_surface_v6_configure *oldest_configure;
-   const int WAIT_ACK_COUNT_MAX = 16;
-
-   toplevel = wl_container_of(listener, toplevel, configure);
-   ds_xdg_surface = toplevel->ds_toplevel->base;
-   if (wl_list_length(&ds_xdg_surface->configure_list) <= WAIT_ACK_COUNT_MAX)
-     return;
+   E_Xdg_Positioner *p;
 
-   oldest_configure = wl_container_of(ds_xdg_surface->configure_list.next,
-                                      oldest_configure,
-                                      link);
+   p = wl_resource_get_user_data(resource);
+   p->offset.x = x;
+   p->offset.y = y;
+}
 
-   LOG("Don't rececive Configure Ack. Remove oldest configure:%p, serial:%d",
-       toplevel->ec, oldest_configure, oldest_configure->serial);
+static const struct zxdg_positioner_v6_interface _e_xdg_positioner_interface =
+{
+   _e_xdg_positioner_cb_destroy,
+   _e_xdg_positioner_cb_size_set,
+   _e_xdg_positioner_cb_anchor_rect_set,
+   _e_xdg_positioner_cb_anchor_set,
+   _e_xdg_positioner_cb_gravity_set,
+   _e_xdg_positioner_cb_constraint_adjustment_set,
+   _e_xdg_positioner_cb_offset_set,
+};
+
+/* End of Xdg_positioner */
 
-   wl_list_remove(&oldest_configure->link);
-   free(oldest_configure);
+/**********************************************************
+ * Implementation for Xdg_Surface
+ **********************************************************/
+static const char *
+_e_xdg_surface_util_role_string_get(E_Xdg_Surface *exsurf)
+{
+   switch (exsurf->role)
+     {
+      case E_XDG_SURFACE_ROLE_TOPLEVEL:
+         return "TOPLEVEL";
+      case E_XDG_SURFACE_ROLE_POPUP:
+         return "POPUP";
+      default:
+      case E_XDG_SURFACE_ROLE_NONE:
+         return "NONE";
+     }
+}
+
+static Eina_Bool
+_e_xdg_surface_cb_configure_send(void *data)
+{
+   E_Xdg_Surface *exsurf;
+   E_Xdg_Surface_Configure *configure;
+   Eina_Bool wait_ack = EINA_FALSE;
+
+   exsurf = data;
+
+   EINA_SAFETY_ON_NULL_GOTO(exsurf, end);
+   EINA_SAFETY_ON_NULL_GOTO(exsurf->ec, end);
+   EINA_SAFETY_ON_NULL_GOTO(e_client_cdata_get(exsurf->ec), end);
+   EINA_SAFETY_ON_NULL_GOTO(exsurf->resource, end);
+
+   if (e_object_is_del(E_OBJECT(exsurf->ec)))
+     goto end;
+
+   /* Make configure */
+   configure = E_NEW(E_Xdg_Surface_Configure, 1);
+   if (!configure)
+     {
+        ERR("Failed to allocate memory: E_Xdg_Surface_Configure", NULL);
+        goto end;
+     }
+
+   configure->serial = wl_display_next_serial(e_comp_wl->wl.disp);
+
+   switch (exsurf->role)
+     {
+      case E_XDG_SURFACE_ROLE_NONE:
+         ERR("Cannot reach here", NULL);
+         break;
+      case E_XDG_SURFACE_ROLE_POPUP:
+         _e_xdg_popup_configure_send((E_Xdg_Popup *)exsurf);
+         wait_ack = EINA_TRUE;
+         break;
+      case E_XDG_SURFACE_ROLE_TOPLEVEL:
+         _e_xdg_toplevel_configure_send((E_Xdg_Toplevel *)exsurf, configure);
+         wait_ack = EINA_TRUE;
+         break;
+     }
+
+   zxdg_surface_v6_send_configure(exsurf->resource, configure->serial);
+
+   LOG("Send configure: %s serial %d", exsurf->ec,
+       _e_xdg_surface_util_role_string_get(exsurf), configure->serial);
+
+   if (wait_ack)
+     {
+        if (eina_list_count(exsurf->configure_list) > WAIT_ACK_COUNT_MAX)
+          {
+             E_Xdg_Surface_Configure *oldest_configure = NULL;
+             oldest_configure = eina_list_nth(exsurf->configure_list, 0);
+             if (oldest_configure)
+               {
+                  ELOGF("XDG6", "Don't receive Configure Ack. Remove oldest configure:%p, serial:%d",
+                        exsurf->ec, oldest_configure, oldest_configure->serial);
+                  exsurf->configure_list = eina_list_remove(exsurf->configure_list, oldest_configure);
+                  E_FREE(oldest_configure);
+               }
+          }
+        exsurf->configure_list = eina_list_append(exsurf->configure_list, configure);
+     }
+   else
+     E_FREE(configure);
+
+end:
+   if (exsurf)
+     exsurf->configure_idle = NULL;
+
+   return ECORE_CALLBACK_DONE;
 }
 
 static void
-_e_xdg_toplevel_v6_cb_ping_timeout(struct wl_listener *listener, void *data)
+_e_xdg_surface_configure_send(struct wl_resource *resource,
+                              uint32_t edges,
+                              int32_t width,
+                              int32_t height)
 {
-   // This is intentionally left blank.
+   E_Xdg_Surface *exsurf;
+   Eina_Bool pending_same = EINA_FALSE;
+
+   EINA_SAFETY_ON_NULL_RETURN(resource);
+
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
+     {
+        ERR("Invalid wl_resource", NULL);
+        return;
+     }
+
+   LOG("Scheduling task to send configure %s edges %d w %d h %d",
+       exsurf->ec,
+       _e_xdg_surface_util_role_string_get(exsurf), edges, width, height);
+
+   switch (exsurf->role)
+     {
+      case E_XDG_SURFACE_ROLE_NONE:
+      default:
+         ERR("Cannot reach here", exsurf->ec);
+         break;
+      case E_XDG_SURFACE_ROLE_TOPLEVEL:
+         _e_xdg_toplevel_configure_pending_set((E_Xdg_Toplevel *)exsurf,
+                                               edges, width, height);
+
+         pending_same = _e_xdg_toplevel_pending_state_compare((E_Xdg_Toplevel *)exsurf);
+         if (pending_same)
+           {
+              LOG("\tSKIP Configuring state is same with current state",
+                  exsurf->ec);
+           }
+         break;
+      case E_XDG_SURFACE_ROLE_POPUP:
+         break;
+     }
+
+   if (exsurf->configure_idle)
+     {
+        if (!pending_same)
+          return;
+
+        LOG("\tRemove configure idler", exsurf->ec);
+
+        E_FREE_FUNC(exsurf->configure_idle, ecore_idle_enterer_del);
+     }
+   else
+     {
+        if (pending_same)
+          return;
+
+        exsurf->configure_idle =
+           ecore_idle_enterer_add(_e_xdg_surface_cb_configure_send, exsurf);
+
+        LOG("\tAdd configure idler %p",
+            exsurf->ec, exsurf->configure_idle);
+     }
 }
 
 static void
-_e_xdg_toplevel_v6_cb_surface_commit(struct wl_listener *listener, void *data)
+_e_xdg_surface_configure(struct wl_resource *resource,
+                         Evas_Coord x, Evas_Coord y,
+                         Evas_Coord w, Evas_Coord h)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Surface *exsurf;
+
+   EINA_SAFETY_ON_NULL_RETURN(resource);
+
+   /* get the client for this resource */
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
+     {
+        ERR("No E_Xdg_Surface data in wl_resource", NULL);
+        return;
+     }
+
+   if (!exsurf->configured)
+     {
+        // any attempts by a client to attach or manipulate a buffer prior to the first xdg_surface.configure call must
+        // be treated as errors.
+        ERR("Could not handle %s prior to the first xdg_surface.configure",
+            exsurf->ec,
+            _e_xdg_surface_util_role_string_get(exsurf));
+
+        E_Client *provider_ec = NULL;
+        provider_ec = e_comp_wl_remote_surface_bound_provider_ec_get(exsurf->ec);
+        if (!provider_ec)
+          return;
+
+        ERR("This is bound the remote surface provider. So, set configure_ack by force", exsurf->ec);
+        exsurf->configured = EINA_TRUE;
+     }
 
-   toplevel = wl_container_of(listener, toplevel, surface_commit);
-   _e_xdg_toplevel_v6_window_geometry_update(toplevel);
-   _e_xdg_toplevel_v6_min_max_size_update(toplevel);
+   EINA_RECTANGLE_SET(&exsurf->configured_geometry, x, y, w, h);
+
+   e_client_util_move_resize_without_frame(exsurf->ec, x, y, w, h);
 }
 
 static void
-_e_xdg_toplevel_v6_listener_init(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_surface_ping(struct wl_resource *resource)
 {
-   struct ds_xdg_toplevel_v6 *ds_toplevel = toplevel->ds_toplevel;
-   struct ds_xdg_surface_v6 *ds_xdg_surface = toplevel->ds_toplevel->base;
-   struct ds_surface *ds_surface = ds_xdg_surface->ds_surface;
+   E_Xdg_Surface *exsurf;
+
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
+     {
+        ERR("No E_Xdg_Surface data in wl_resource", NULL);
+        return;
+     }
 
-   toplevel->set_parent.notify = _e_xdg_toplevel_v6_cb_set_parent;
-   ds_xdg_toplevel_v6_add_set_parent_listener(ds_toplevel, &toplevel->set_parent);
+   if (e_object_is_del(E_OBJECT(exsurf->ec)))
+     return;
+
+   _e_xdg_shell_ping(exsurf->shell);
+}
 
-   toplevel->set_title.notify = _e_xdg_toplevel_v6_cb_set_title;
-   ds_xdg_toplevel_v6_add_set_title_listener(ds_toplevel, &toplevel->set_title);
+static void
+_e_xdg_surface_map(struct wl_resource *resource)
+{
+   E_Xdg_Surface *exsurf;
 
-   toplevel->set_app_id.notify = _e_xdg_toplevel_v6_cb_set_app_id;
-   ds_xdg_toplevel_v6_add_set_app_id_listener(ds_toplevel, &toplevel->set_app_id);
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
+     {
+        ERR("No E_Xdg_Surface in wl_resource", NULL);
+        return;
+     }
 
-   toplevel->request_move.notify = _e_xdg_toplevel_v6_cb_request_move;
-   ds_xdg_toplevel_v6_add_request_move_listener(ds_toplevel, &toplevel->request_move);
+   e_shell_e_client_map(exsurf->ec);
+}
 
-   toplevel->request_resize.notify = _e_xdg_toplevel_v6_cb_request_resize;
-   ds_xdg_toplevel_v6_add_request_resize_listener(ds_toplevel, &toplevel->request_resize);
+static void
+_e_xdg_surface_unmap(struct wl_resource *resource)
+{
+   E_Xdg_Surface *exsurf;
 
-   toplevel->request_maximize.notify = _e_xdg_toplevel_v6_cb_request_maximize;
-   ds_xdg_toplevel_v6_add_request_maximize_listener(ds_toplevel, &toplevel->request_maximize);
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
+     {
+        ERR("No E_Xdg_Surface in wl_resource", NULL);
+        return;
+     }
 
-   toplevel->request_fullscreen.notify = _e_xdg_toplevel_v6_cb_request_fullscreen;
-   ds_xdg_toplevel_v6_add_request_fullscreen_listener(ds_toplevel, &toplevel->request_fullscreen);
+   e_shell_e_client_unmap(exsurf->ec);
+}
 
-   toplevel->request_minimize.notify = _e_xdg_toplevel_v6_cb_request_minimize;
-   ds_xdg_toplevel_v6_add_request_minimize_listener(ds_toplevel, &toplevel->request_minimize);
+static Eina_Bool
+_e_xdg_surface_role_assign(E_Xdg_Surface *exsurf,
+                           struct wl_resource *resource,
+                           E_Xdg_Surface_Role role)
+{
+   E_Shell_Surface_Api api = {
+        .configure_send = _e_xdg_surface_configure_send,
+        .configure = _e_xdg_surface_configure,
+        .ping = _e_xdg_surface_ping,
+        .map = _e_xdg_surface_map,
+        .unmap = _e_xdg_surface_unmap,
+   };
+
+   if (_e_client_xdg_shell_v6_assigned_check(exsurf->ec))
+     {
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "Client already has shell resource");
+        return EINA_FALSE;
+     }
 
-   toplevel->destroy.notify = _e_xdg_toplevel_v6_cb_destroy;
-   ds_xdg_surface_v6_add_destroy_listener(ds_xdg_surface, &toplevel->destroy);
+   exsurf->role = role;
 
-   toplevel->configure.notify = _e_xdg_toplevel_v6_cb_configure;
-   ds_xdg_surface_v6_add_configure_listener(ds_xdg_surface, &toplevel->configure);
+   e_shell_e_client_shsurface_api_set(exsurf->ec, &api);
 
-   toplevel->ping_timeout.notify = _e_xdg_toplevel_v6_cb_ping_timeout;
-   ds_xdg_surface_v6_add_ping_timeout_listener(ds_xdg_surface, &toplevel->ping_timeout);
+   switch (role)
+     {
+      case E_XDG_SURFACE_ROLE_NONE:
+      default:
+         ERR("Cannot reach here", exsurf->ec);
+         return EINA_FALSE;
+
+      case E_XDG_SURFACE_ROLE_TOPLEVEL:
+         _e_xdg_toplevel_set((E_Xdg_Toplevel *)exsurf, resource);
+         break;
+
+      case E_XDG_SURFACE_ROLE_POPUP:
+         _e_xdg_popup_set((E_Xdg_Popup *)exsurf, resource);
+         break;
+     }
 
-   toplevel->surface_commit.notify = _e_xdg_toplevel_v6_cb_surface_commit;
-   ds_surface_add_commit_listener(ds_surface, &toplevel->surface_commit);
+   return EINA_TRUE;
 }
 
 static void
-_e_xdg_toplevel_v6_listener_finish(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_surface_cb_destroy(struct wl_client *client, struct wl_resource *resource)
 {
-   wl_list_remove(&toplevel->set_parent.link);
-   wl_list_remove(&toplevel->set_title.link);
-   wl_list_remove(&toplevel->set_app_id.link);
-   wl_list_remove(&toplevel->request_move.link);
-   wl_list_remove(&toplevel->request_resize.link);
-   wl_list_remove(&toplevel->request_maximize.link);
-   wl_list_remove(&toplevel->request_fullscreen.link);
-   wl_list_remove(&toplevel->request_minimize.link);
-   wl_list_remove(&toplevel->destroy.link);
-   wl_list_remove(&toplevel->configure.link);
-   wl_list_remove(&toplevel->ping_timeout.link);
-   wl_list_remove(&toplevel->surface_commit.link);
+   wl_resource_destroy(resource);
 }
 
 static void
-_e_xdg_toplevel_v6_init(E_Xdg_Toplevel_V6 *toplevel)
+_e_xdg_surface_cb_toplevel_get(struct wl_client *client, struct wl_resource *resource, uint32_t id)
 {
-   struct ds_xdg_toplevel_v6 *ds_toplevel = toplevel->ds_toplevel;
+   E_Xdg_Surface *exsurf;
+   struct wl_resource *toplevel_resource;
 
-   _e_xdg_toplevel_v6_title_update(toplevel);
-   _e_xdg_toplevel_v6_app_id_update(toplevel);
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
+     {
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Xdg_Surface data in wl_resource");
+        return;
+     }
 
-   if (ds_toplevel->requested.maximized)
-     _e_xdg_toplevel_v6_maximize_set(toplevel);
+   toplevel_resource = wl_resource_create(client, &zxdg_toplevel_v6_interface, 1, id);
+   if (!toplevel_resource)
+     {
+        ERR("Could not create xdg toplevel resource", NULL);
+        wl_resource_post_no_memory(resource);
+        return;
+     }
+
+   wl_resource_set_implementation(toplevel_resource,
+                                  &_e_xdg_toplevel_interface,
+                                  exsurf,
+                                  _e_xdg_toplevel_cb_resource_destroy);
 
-   if (ds_toplevel->requested.fullscreen)
-     _e_xdg_toplevel_v6_fullscreen_set(toplevel);
+   if (!_e_xdg_surface_role_assign(exsurf, toplevel_resource, E_XDG_SURFACE_ROLE_TOPLEVEL))
+     {
+        ERR("Failed to assign TOPLEVEL role", exsurf->ec);
+        wl_resource_destroy(toplevel_resource);
+        return;
+     }
 
-   _e_xdg_toplevel_v6_role_init(toplevel);
+   e_object_ref(E_OBJECT(exsurf));
 }
 
 static void
-_e_xdg_toplevel_v6_finish(E_Xdg_Toplevel_V6 *toplevel)
+_e_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)
 {
-   E_Client *ec = toplevel->ec;
-   E_Comp_Wl_Client_Data *cdata;
+   struct wl_resource *popup_resource;
+   E_Xdg_Surface *exsurf, *parent;
+   E_Xdg_Positioner *p;
 
-   cdata = e_client_cdata_get(ec);
-   if (cdata)
+   if (!res_parent)
+     {
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "Popup requires a parent shell surface");
+        return;
+     }
+
+   parent = wl_resource_get_user_data(res_parent);
+   if (!parent)
+     {
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "xdg_popup must have parent");
+        return;
+     }
+
+   p = wl_resource_get_user_data(res_pos);
+   if (!p)
+     {
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "invalid positioner");
+        return;
+     }
+
+   if (!_e_xdg_positioner_validation_check(p))
+     {
+        wl_resource_post_error(resource,
+                               ZXDG_SHELL_V6_ERROR_INVALID_POSITIONER,
+                               "invalid positioner");
+        return;
+     }
+
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
      {
-        cdata->sh_v6.res_role = toplevel->ds_toplevel->resource;
-        cdata->sh_v6.role = E_COMP_WL_SH_SURF_ROLE_NONE;
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Xdg_Popup data in wl_resource");
+        return;
      }
 
-   e_shell_e_client_destroy(ec);
+   popup_resource = wl_resource_create(client, &zxdg_popup_v6_interface, 1, id);
+   if (!popup_resource)
+     {
+        ERR("Could not create xdg popup resource", NULL);
+        wl_resource_post_no_memory(resource);
+        return;
+     }
+
+   wl_resource_set_implementation(popup_resource,
+                                  &_e_xdg_popup_interface,
+                                  exsurf,
+                                  _e_xdg_popup_cb_resource_destroy);
+
+
+   if (!_e_xdg_surface_role_assign(exsurf, popup_resource, E_XDG_SURFACE_ROLE_POPUP))
+     {
+        ERR("Failed to assign role to surface", exsurf->ec);
+        wl_resource_destroy(popup_resource);
+        return;
+     }
+
+   _e_xdg_popup_parent_set((E_Xdg_Popup *)exsurf, parent);
+   _e_xdg_popup_positioner_apply((E_Xdg_Popup *)exsurf, p);
+
+   e_object_ref(E_OBJECT(exsurf));
 }
 
 static void
-_e_xdg_toplevel_v6_add(struct ds_xdg_surface_v6 *ds_xdg_surface)
+_e_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)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Surface *exsurf;
 
-   toplevel = E_NEW(E_Xdg_Toplevel_V6, 1);
-   if (!toplevel)
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
+     {
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Xdg_Surface data in wl_resource");
+        return;
+     }
+
+   LOG("Set window geometry: geometry(%d %d %d %d)",
+       exsurf->ec, x, y, w, h);
+
+   exsurf->has_window_geometry = EINA_TRUE;
+   EINA_RECTANGLE_SET(&exsurf->window_geometry, x, y, w, h);
+
+   exsurf->wait_next_commit = EINA_TRUE;
+}
+
+static void
+_e_xdg_surface_cb_configure_ack(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
+{
+   E_Xdg_Surface *exsurf;
+   E_Xdg_Surface_Configure *configure;
+   Eina_List *l, *ll;
+   Eina_Bool found = EINA_FALSE;
+
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
      {
-        ERR("Could not create E_Xdg_Toplevel_V6", NULL);
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Xdg_Surface data in wl_surface");
         return;
      }
 
-   toplevel->ds_toplevel = ds_xdg_surface->toplevel;
-   toplevel->ec = e_client_from_surface_resource(ds_xdg_surface->ds_surface->resource);
+   LOG("Ack configure", exsurf->ec);
 
-   _e_xdg_toplevel_v6_listener_init(toplevel);
-   _e_xdg_toplevel_v6_init(toplevel);
+   if ((exsurf->role != E_XDG_SURFACE_ROLE_TOPLEVEL) &&
+       (exsurf->role != E_XDG_SURFACE_ROLE_POPUP))
+     {
+        wl_resource_post_error(resource,
+                               ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+                               "xdg_surface must have a role");
+        return;
+     }
 
-   // FIXME HACK
-   // For wayland clients which don't follow the rule of
-   // xdg_shell_v6.configure, this sets `configured` variable as true to work
-   // with libds which does follow the rule of xdg_shell_v6 spec.
-   ds_xdg_surface->configured = EINA_TRUE;
+   EINA_LIST_FOREACH_SAFE(exsurf->configure_list, l, ll, configure)
+     {
+        if (configure->serial < serial)
+          {
+             exsurf->configure_list =
+                eina_list_remove_list(exsurf->configure_list, l);
+             free(configure);
+          }
+        else if (configure->serial == serial)
+          {
+             exsurf->configure_list =
+                eina_list_remove_list(exsurf->configure_list, l);
+             found = EINA_TRUE;
+             break;
+          }
+        else
+          break;
+     }
 
-   LOG("Created E_Xdg_Toplevel_V6(%p)", toplevel->ec, toplevel);
+   LOG("Ack configure %s first %d serial %d found %d",
+       exsurf->ec,
+       _e_xdg_surface_util_role_string_get(exsurf),
+       !exsurf->configured,
+       serial, found);
+
+   if (!found)
+     {
+        wl_resource_post_error(exsurf->shell->resource,
+                               ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
+                               "Wrong configure serial: %u", serial);
+        return;
+     }
+
+   exsurf->configured = EINA_TRUE;
+
+   switch (exsurf->role)
+     {
+      case E_XDG_SURFACE_ROLE_NONE:
+         ERR("Cannot reach here", exsurf->ec);
+         break;
+      case E_XDG_SURFACE_ROLE_TOPLEVEL:
+         _e_xdg_toplevel_configure_ack((E_Xdg_Toplevel *)exsurf, configure);
+         break;
+      case E_XDG_SURFACE_ROLE_POPUP:
+         break;
+     }
+
+   E_FREE_FUNC(configure, free);
 }
 
+static const struct zxdg_surface_v6_interface _e_xdg_surface_interface =
+{
+   _e_xdg_surface_cb_destroy,
+   _e_xdg_surface_cb_toplevel_get,
+   _e_xdg_surface_cb_popup_get,
+   _e_xdg_surface_cb_win_geometry_set,
+   _e_xdg_surface_cb_configure_ack
+};
+
 static void
-_e_xdg_toplevel_v6_cb_destroy(struct wl_listener *listener, void *data)
+_e_xdg_surface_cb_commit(void *data, E_Client *ec)
 {
-   E_Xdg_Toplevel_V6 *toplevel;
+   E_Xdg_Surface *exsurf;
+   E_Comp_Wl_Client_Data *exsurf_cdata;
+
+   exsurf = (E_Xdg_Surface *)data;
 
-   toplevel = wl_container_of(listener, toplevel, destroy);
+   if (exsurf->ec != ec)
+     return;
+
+   if (!exsurf->wait_next_commit)
+     return;
+
+   LOG("Wl_Surface Commit, Update Xdg_Surface state %s",
+       exsurf->ec,
+       _e_xdg_surface_util_role_string_get(exsurf));
+
+   exsurf->wait_next_commit = EINA_FALSE;
+
+   if (exsurf->has_window_geometry)
+     {
+        exsurf->has_window_geometry = EINA_FALSE;
+        exsurf_cdata = e_client_cdata_get(exsurf->ec);
+        EINA_RECTANGLE_SET(&exsurf_cdata->shell.window,
+                           exsurf->window_geometry.x,
+                           exsurf->window_geometry.y,
+                           exsurf->window_geometry.w,
+                           exsurf->window_geometry.h);
+     }
 
-   LOG("Destroy E_Xdg_Toplevel_V6(%p)", toplevel->ec, toplevel);
+   switch (exsurf->role)
+     {
+      case E_XDG_SURFACE_ROLE_NONE:
+         wl_resource_post_error(exsurf->resource,
+                                ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
+                                "xdg_surface must have a role");
+         break;
+      case E_XDG_SURFACE_ROLE_TOPLEVEL:
+         _e_xdg_toplevel_committed((E_Xdg_Toplevel *)exsurf);
+         break;
+      case E_XDG_SURFACE_ROLE_POPUP:
+         _e_xdg_popup_committed((E_Xdg_Popup *)exsurf);
+         break;
+     }
+}
+
+static void
+_e_xdg_surface_free(E_Xdg_Surface *exsurf)
+{
+   free(exsurf);
+}
+
+static void
+_e_xdg_surface_del(E_Xdg_Surface *exsurf)
+{
+   _e_xdg_shell_surface_remove(exsurf->shell, exsurf);
+
+   E_FREE_LIST(exsurf->configure_list, free);
+   if (exsurf->configure_idle)
+     ecore_idle_enterer_del(exsurf->configure_idle);
+   if (exsurf->commit_hook)
+     e_comp_wl_hook_del(exsurf->commit_hook);
+}
+
+static void
+_e_xdg_surface_cb_resource_destroy(struct wl_resource *resource)
+{
+   E_Xdg_Surface *exsurf;
+
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
+     {
+        ERR("No E_Xdg_Surface data in wl_resource", NULL);
+        return;
+
+     }
+
+   LOG("Destroy resource of Xdg_Surface %s",
+       exsurf->ec,
+       _e_xdg_surface_util_role_string_get(exsurf));
+
+   /* Although zxdg_toplevel_v6 or zxdg_popup_v6 are still existed, unset
+    * assignment at here anyway. once zxdg_surface_v6 is destroyed, the
+    * attribute 'toplevel and popup' is no longer meaningful. */
+   _e_client_xdg_shell_v6_role_assingment_unset(exsurf->ec);
+
+   e_shell_e_client_destroy(exsurf->ec);
+   /* set null after destroying shell of e_client, ec will be freed */
+   exsurf->ec = NULL;
+
+   e_object_del(E_OBJECT(exsurf));
+}
+
+static E_Xdg_Surface *
+_e_xdg_surface_create(E_Xdg_Shell *shell,
+                      struct wl_resource *wsurface,
+                      uint32_t id)
+{
+   E_Xdg_Surface *exsurf;
+   E_Client *ec;
+
+   ec = e_client_from_surface_resource(wsurface);
+   if (!ec)
+     {
+        ERR("No E_Client data in wl_resource", NULL);
+        wl_resource_post_error(wsurface,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No data in wl_resource");
+        return NULL;
+     }
+
+   LOG("Create Xdg_Surface", ec);
+
+   if (!_e_client_shsurface_assignable_check(ec))
+     {
+        ERR("Cannot get xdg_surface with this wl_surface", ec);
+        return NULL;
+     }
+
+   exsurf = E_OBJECT_ALLOC(e_xdg_surface_role_biggest_struct,
+                           E_XDG_SURFACE_V6_TYPE,
+                           _e_xdg_surface_free);
+   if (!exsurf)
+     {
+        wl_client_post_no_memory(shell->wclient);
+        return NULL;
+     }
+   e_object_del_func_set(E_OBJECT(exsurf), E_OBJECT_CLEANUP_FUNC(_e_xdg_surface_del));
+
+   exsurf->resource = wl_resource_create(shell->wclient,
+                                         &zxdg_surface_v6_interface,
+                                         1,
+                                         id);
+   if (!exsurf->resource)
+     {
+        ERR("Could not create wl_resource for xdg surface", ec);
+        wl_client_post_no_memory(shell->wclient);
+        e_object_del(E_OBJECT(exsurf));
+        return NULL;
+     }
+
+   wl_resource_set_implementation(exsurf->resource,
+                                  &_e_xdg_surface_interface,
+                                  exsurf,
+                                  _e_xdg_surface_cb_resource_destroy);
+
+   e_shell_e_client_shsurface_assign(ec, exsurf->resource, NULL);
+
+   exsurf->shell = shell;
+   exsurf->ec = ec;
+   exsurf->configured = EINA_FALSE;
+   exsurf->commit_hook =
+      e_comp_wl_hook_add(E_COMP_WL_HOOK_CLIENT_SURFACE_COMMIT,
+                         _e_xdg_surface_cb_commit,
+                         exsurf);
+
+   _e_xdg_shell_surface_add(shell, exsurf);
+
+   // base_output_resolution.
+   e_client_base_output_resolution_update(ec);
+
+   return exsurf;
+}
+/* End of Xdg_surface */
+
+/**********************************************************
+ * Implementation for Xdg_Shell
+ **********************************************************/
+static void
+_e_xdg_shell_surface_add(E_Xdg_Shell *shell, E_Xdg_Surface *exsurf)
+{
+   if (!shell) return;
+   shell->surfaces = eina_list_append(shell->surfaces, exsurf);
+}
+
+static void
+_e_xdg_shell_surface_remove(E_Xdg_Shell *shell, E_Xdg_Surface *exsurf)
+{
+   if (!shell) return;
+   shell->surfaces = eina_list_remove(shell->surfaces, exsurf);
+}
+
+static void
+_e_xdg_shell_ping(E_Xdg_Shell *shell)
+{
+   EINA_SAFETY_ON_NULL_RETURN(shell);
+   EINA_SAFETY_ON_NULL_RETURN(shell->resource);
+
+   if (shell->ping_serial != 0)
+     return;
+
+   ELOGF("XDG6", "Ping. res:%p", NULL, shell->resource);
+   shell->ping_serial = wl_display_next_serial(e_comp_wl->wl.disp);
+   zxdg_shell_v6_send_ping(shell->resource, shell->ping_serial);
+}
+
+static void
+_e_xdg_shell_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+   LOG("Destroy Xdg_Shell", NULL);
+
+   wl_resource_destroy(resource);
+}
+
+static void
+_e_xdg_shell_cb_positioner_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
+{
+   E_Xdg_Shell *shell;
+   E_Xdg_Positioner *p;
+   struct wl_resource *new_res;
+
+   LOG("Create Positioner", NULL);
+
+   shell = wl_resource_get_user_data(resource);
+   if (!shell)
+     {
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No resource for xdg_shell_v6");
+        return;
+     }
+
+   new_res = wl_resource_create(client, &zxdg_positioner_v6_interface, 1, id);
+   if (!new_res)
+     {
+        wl_resource_post_no_memory(resource);
+        return;
+     }
+
+   p = E_NEW(E_Xdg_Positioner, 1);
+   if (!p)
+     {
+        wl_resource_destroy(new_res);
+        wl_resource_post_no_memory(resource);
+        return;
+     }
+   p->shell = shell;
+   p->resource = new_res;
+
+   shell->positioners = eina_list_append(shell->positioners, p);
+
+   wl_resource_set_implementation(new_res,
+                                  &_e_xdg_positioner_interface,
+                                  p,
+                                  _e_xdg_positioner_cb_resource_destroy);
+}
+
+static void
+_e_xdg_shell_cb_surface_get(struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *wsurface)
+{
+   E_Xdg_Shell *shell;
+   E_Xdg_Surface *exsurf;
+
+   shell = wl_resource_get_user_data(resource);
+   if (!shell)
+     {
+        ERR("No E_Xdg_Shell data in wl_resource", NULL);
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No shell data in wl_resource");
+        return;
+     }
+
+   exsurf = _e_xdg_surface_create(shell, wsurface, id);
+   if (!exsurf)
+     {
+        ERR("Failed to create E_Xdg_Surface", NULL);
+        return;
+     }
+}
+
+static void
+_e_xdg_shell_cb_pong(struct wl_client *client, struct wl_resource *resource, uint32_t serial)
+{
+   E_Xdg_Shell *shell;
+   E_Xdg_Surface *exsurf;
+   Eina_List *l;
+
+   ELOGF("XDG6", "Pong. res:%p", NULL, resource);
+
+   shell = wl_resource_get_user_data(resource);
+   if (!shell)
+     {
+        ERR("No E_Xdg_Shell data in wl_resource", NULL);
+        wl_resource_post_error(resource,
+                               WL_DISPLAY_ERROR_INVALID_OBJECT,
+                               "No E_Xdg_Shell data in wl_resource");
+        return;
+     }
+
+   EINA_LIST_FOREACH(shell->surfaces, l, exsurf)
+      e_shell_e_client_pong(exsurf->ec);
+
+   shell->ping_serial = 0;
+}
+
+static const struct zxdg_shell_v6_interface _e_xdg_shell_interface =
+{
+   _e_xdg_shell_cb_destroy,
+   _e_xdg_shell_cb_positioner_create,
+   _e_xdg_shell_cb_surface_get,
+   _e_xdg_shell_cb_pong
+};
+
+static E_Xdg_Shell *
+_e_xdg_shell_create(struct wl_client *client, struct wl_resource *resource)
+{
+   E_Xdg_Shell *shell;
+
+   shell = E_NEW(E_Xdg_Shell, 1);
+   if (!shell)
+     return NULL;
+
+   shell->wclient = client;
+   shell->resource = resource;
+
+   return shell;
+}
+
+static void
+_e_xdg_shell_destroy(E_Xdg_Shell *shell)
+{
+   E_Xdg_Surface *exsurf;
+   E_Xdg_Positioner *p;
+
+   EINA_LIST_FREE(shell->surfaces, exsurf)
+     {
+        /* Do we need to do it even though shell is just about to be destroyed? */
+        e_shell_e_client_pong(exsurf->ec);
+        exsurf->shell = NULL;
+     }
+
+   EINA_LIST_FREE(shell->positioners, p)
+      p->shell = NULL;
+
+   free(shell);
+}
+
+static void
+_e_xdg_shell_cb_unbind(struct wl_resource *resource)
+{
+   E_Xdg_Shell *shell;
+
+   LOG("Unbind Xdg_Shell", NULL);
+
+   shell = wl_resource_get_user_data(resource);
+   if (!shell)
+     {
+        ERR("No E_Xdg_Shell in wl_resource", NULL);
+        return;
+     }
+
+   _e_xdg_shell_destroy(shell);
+}
+
+static void
+_e_xdg_shell_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
+{
+   E_Xdg_Shell *shell;
+   struct wl_resource *resource;
+
+   LOG("Bind Xdg_Shell", NULL);
+
+   /* Create resource for zxdg_shell_v6 */
+   resource = wl_resource_create(client,
+                                 &zxdg_shell_v6_interface,
+                                 version,
+                                 id);
+   if (!resource)
+     goto err_res;
+
+
+   shell = _e_xdg_shell_create(client, resource);
+   if (!shell)
+     {
+        ERR("Failed to create E_Xdg_Shell", NULL);
+        goto err_shell;
+     }
+
+   wl_resource_set_implementation(resource, &_e_xdg_shell_interface,
+                                  shell, _e_xdg_shell_cb_unbind);
+
+   return;
+err_shell:
+   wl_resource_destroy(resource);
+err_res:
+   wl_client_post_no_memory(client);
+}
+
+EINTERN Eina_Bool
+e_xdg_shell_v6_init(void)
+{
+   LOG("Initializing Xdg_Shell_V6", NULL);
+
+   /* try to create global xdg_shell interface */
+   global_resource = wl_global_create(e_comp_wl->wl.disp,
+                                      &zxdg_shell_v6_interface,
+                                      1,
+                                      e_comp->wl_comp_data,
+                                      _e_xdg_shell_cb_bind);
+   if (!global_resource)
+     {
+        ERR("Could not create zxdg_shell_v6 global: %m", NULL);
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+EINTERN void
+e_xdg_shell_v6_shutdown(void)
+{
+   E_FREE_FUNC(global_resource, wl_global_destroy);
+}
+
+EINTERN E_Client *
+e_xdg_shell_v6_xdg_surface_ec_get(struct wl_resource *resource)
+{
+   E_Xdg_Surface *exsurf = NULL;
+
+   exsurf = wl_resource_get_user_data(resource);
+   if (!exsurf)
+     {
+        ERR("No E_Xdg_Shell in wl_resource", NULL);
+        return NULL;
+     }
 
-   _e_xdg_toplevel_v6_listener_finish(toplevel);
-   _e_xdg_toplevel_v6_finish(toplevel);
-   free(toplevel);
+   return exsurf->ec;
 }
+/* End of Xdg_shell */