foreign_shell: Associate E_Client instead of wl_surface 99/261599/1
authorSeunghun Lee <shiin.lee@samsung.com>
Wed, 21 Jul 2021 09:31:30 +0000 (18:31 +0900)
committerSeunghun Lee <shiin.lee@samsung.com>
Thu, 22 Jul 2021 02:56:18 +0000 (11:56 +0900)
Knowing when the comp_data is deleted, it's better to associate the
foreign shell with E_Client instead of wl_surface, because E_Client is a
user data of the resource of wl_surface.
The foreign shell becomes inert when the comp_data gets deleted, then
the comp_data must be valid during the lifetime of the foreign shell.

When it comes to ec->frame, we can be sure that it's alive, because it's
supposed to be freed in _e_client_free().

Change-Id: I653df916cf36dfe6f8cc082dee37106e11703fba

src/bin/e_foreign_shell.c

index b61377aae50ead368e925c15915e2cb1002b3c1e..cc0262de88f48cd770ebb65118cb773a299dcc31 100644 (file)
@@ -1,10 +1,10 @@
 #include "e_foreign_private.h"
 
 #define ESINF(obj, fmt, x...) \
-   FINF("EShell:%p| "fmt, wl_resource_get_user_data(obj->surface), obj, ##x)
+   FINF("EShell:%p| "fmt, es->ec, obj, ##x)
 
 #define FSINF(obj, fmt, x...) \
-   FINF("FShell:%p| "fmt, wl_resource_get_user_data(obj->surface), obj, ##x)
+   FINF("FShell:%p| "fmt, fs->ec, obj, ##x)
 
 typedef struct _E_Exported_Shell_State E_Exported_Shell_State;
 typedef struct _E_Exported_Shell       E_Exported_Shell;
@@ -28,7 +28,7 @@ struct _E_Exported_Shell_State
 struct _E_Exported_Shell
 {
    struct wl_resource *resource;
-   struct wl_resource *surface;
+   E_Client *ec;
    E_Foreign_Handle *handle;
    E_Util_Transform *transform;
    E_Foreign_Shell *foreign;
@@ -36,24 +36,29 @@ struct _E_Exported_Shell
    E_Exported_Shell_State pending, cache, stage;
 
    E_Comp_Wl_Hook *commit_to_cache_hook;
-   struct wl_listener surface_destroy_listener;
    struct wl_listener surface_commit_listener;
    struct wl_signal destroy_signal;
 
    int x, y;
 
+   struct
+     {
+        E_Comp_Wl_Hook *commit_to_cache;
+        E_Comp_Wl_Hook *del;
+     } comp_hook;
+
    Eina_Bool has_cache_data;
 };
 
 struct _E_Foreign_Shell
 {
    struct wl_resource *resource;
-   struct wl_resource *surface;
+   E_Client *ec;
    E_Util_Transform *transform;
    E_Exported_Shell *exported;
 
    E_Client_Hook *transform_change_hook;
-   struct wl_listener surface_destroy_listener;
+   E_Comp_Wl_Hook *comp_del_hook;
    struct wl_listener surface_commit_listener;
    struct wl_listener shell_destroy_listener;
 
@@ -66,20 +71,20 @@ struct _E_Foreign_Shell
 
 Eina_Hash *_exported_shell_hash = NULL;
 
-static E_Exported_Shell *_e_exported_shell_create(struct wl_resource *resource, struct wl_resource *surface);
+static E_Exported_Shell *_e_exported_shell_create(struct wl_resource *resource, E_Client *ec);
 static void              _e_exported_shell_destroy(E_Exported_Shell *es);
 static E_Exported_Shell *_e_exported_shell_find_by_surface(struct wl_resource *surface);
 static E_Exported_Shell *_e_exported_shell_find_by_handle(const char *handle);
-static void              _e_exported_shell_surface_link(E_Exported_Shell *es, struct wl_resource *surface);
-static void              _e_exported_shell_surface_unlink(E_Exported_Shell *es);
+static void              _e_exported_shell_ec_link(E_Exported_Shell *es, E_Client *ec);
+static void              _e_exported_shell_ec_unlink(E_Exported_Shell *es);
 static void              _e_exported_shell_visible_set(E_Exported_Shell *es, Eina_Bool visible);
 static void              _e_exported_shell_destination_set(E_Exported_Shell *es, int w, int h);
 static void              _e_exported_shell_transform_set(E_Exported_Shell *es, enum wtz_exported_shell_transform transform);
 
-static E_Foreign_Shell  *_e_foreign_shell_create(struct wl_resource *resource, struct wl_resource *surface, E_Exported_Shell *es);
+static E_Foreign_Shell  *_e_foreign_shell_create(struct wl_resource *resource, E_Client *ec, E_Exported_Shell *es);
 static void              _e_foreign_shell_destroy(E_Foreign_Shell *fs);
-static void              _e_foreign_shell_surface_link(E_Foreign_Shell *fs, struct wl_resource *surface);
-static void              _e_foreign_shell_surface_unlink(E_Foreign_Shell *fs);
+static void              _e_foreign_shell_ec_link(E_Foreign_Shell *fs, E_Client *ec);
+static void              _e_foreign_shell_ec_unlink(E_Foreign_Shell *fs);
 static void              _e_foreign_shell_exported_link(E_Foreign_Shell *fs, E_Exported_Shell *es);
 static void              _e_foreign_shell_exported_unlink(E_Foreign_Shell *fs);
 static void              _e_foreign_shell_visible_set(E_Foreign_Shell *fs, Eina_Bool visible);
@@ -119,12 +124,16 @@ EINTERN Eina_Bool
 e_foreign_shell_export(struct wl_resource *exporter, struct wl_resource *resource, struct wl_resource *surface)
 {
    E_Exported_Shell *es;
-   E_Client *esc;
+   E_Client *ec;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(exporter, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(resource, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
 
+   ec = wl_resource_get_user_data(surface);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(!e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
+
    es = _e_exported_shell_find_by_surface(surface);
    if (es)
      {
@@ -135,8 +144,7 @@ e_foreign_shell_export(struct wl_resource *exporter, struct wl_resource *resourc
         return EINA_FALSE;
      }
 
-   esc = wl_resource_get_user_data(surface);
-   if (!e_comp_wl_subsurface_check(esc))
+   if (!e_comp_wl_subsurface_check(ec))
      {
         wl_resource_post_error(exporter,
                                WTZ_EXPORTER_ERROR_INVALID_ROLE,
@@ -145,7 +153,7 @@ e_foreign_shell_export(struct wl_resource *exporter, struct wl_resource *resourc
         return EINA_FALSE;
      }
 
-   es = _e_exported_shell_create(resource, surface);
+   es = _e_exported_shell_create(resource, ec);
    if (!es)
      {
         wl_resource_post_no_memory(exporter);
@@ -162,11 +170,16 @@ e_foreign_shell_import(struct wl_resource *importer, struct wl_resource *resourc
 {
    E_Foreign_Shell *fs;
    E_Exported_Shell *es;
+   E_Client *ec;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(importer, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(resource, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(handle, EINA_FALSE);
 
+   ec = wl_resource_get_user_data(surface);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(!e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
+
    es = _e_exported_shell_find_by_handle(handle);
    if ((es) && (es->foreign))
      {
@@ -180,7 +193,7 @@ e_foreign_shell_import(struct wl_resource *importer, struct wl_resource *resourc
         return EINA_FALSE;
      }
 
-   fs = _e_foreign_shell_create(resource, surface, es);
+   fs = _e_foreign_shell_create(resource, ec, es);
    if (!fs)
      {
         wl_resource_post_no_memory(importer);
@@ -196,14 +209,17 @@ static E_Exported_Shell *
 _e_exported_shell_find_by_surface(struct wl_resource *surface)
 {
    E_Exported_Shell *es;
+   E_Client *ec;
    Eina_Iterator *it;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, NULL);
 
+   ec = wl_resource_get_user_data(surface);
+
    it = eina_hash_iterator_data_new(_exported_shell_hash);
    EINA_ITERATOR_FOREACH(it, es)
      {
-        if (es->surface == surface)
+        if (es->ec == ec)
           return es;
      }
    eina_iterator_free(it);
@@ -354,7 +370,7 @@ _e_exported_shell_cb_resource_destroy(struct wl_resource *resource)
 }
 
 static E_Exported_Shell *
-_e_exported_shell_create(struct wl_resource *resource, struct wl_resource *surface)
+_e_exported_shell_create(struct wl_resource *resource, E_Client *ec)
 {
    E_Exported_Shell *es;
 
@@ -389,7 +405,7 @@ _e_exported_shell_create(struct wl_resource *resource, struct wl_resource *surfa
                                   &_e_exported_shell_impl,
                                   es,
                                   _e_exported_shell_cb_resource_destroy);
-   _e_exported_shell_surface_link(es, surface);
+   _e_exported_shell_ec_link(es, ec);
 
    /* Add exported surface with handle string to hash */
    eina_hash_add(_exported_shell_hash,
@@ -414,7 +430,7 @@ _e_exported_shell_destroy(E_Exported_Shell *es)
    wl_signal_emit(&es->destroy_signal, es);
 
    _e_exported_shell_visible_set(es, EINA_FALSE);
-   _e_exported_shell_surface_unlink(es);
+   _e_exported_shell_ec_unlink(es);
 
    e_util_transform_del(es->transform);
    e_foreign_handle_destroy(es->handle);
@@ -425,11 +441,9 @@ static void
 _e_exported_shell_cb_eo_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj, void *event EINA_UNUSED)
 {
    E_Exported_Shell *es;
-   E_Client *esc;
 
    es = data;
-   esc = wl_resource_get_user_data(es->surface);
-   evas_object_geometry_get(esc->frame, &es->x, &es->y, NULL, NULL);
+   evas_object_geometry_get(es->ec->frame, &es->x, &es->y, NULL, NULL);
 
    if (es->foreign)
      {
@@ -442,21 +456,7 @@ _e_exported_shell_cb_eo_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *ob
                                  es->x, es->y,
                                  es->stage.width,
                                  es->stage.height);
-   e_client_transform_core_update(esc);
-}
-
-static void
-_e_exported_shell_cb_surface_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
-{
-   E_Exported_Shell *es;
-
-   es = wl_container_of(listener, es, surface_destroy_listener);
-
-   ESINF(es, "wl_surface has been destroyed");
-
-   wl_resource_set_user_data(es->resource, NULL);
-
-   _e_exported_shell_destroy(es);
+   e_client_transform_core_update(es->ec);
 }
 
 static void
@@ -497,12 +497,10 @@ static void
 _e_exported_shell_cb_commit_to_cache(void *data, E_Client *ec)
 {
    E_Exported_Shell *es;
-   E_Client *esc;
    E_Exported_Shell_State_Flag change = 0;
 
    es = data;
-   esc = wl_resource_get_user_data(es->surface);
-   if (ec != esc)
+   if (es->ec != ec)
      return;
 
    /* It's for flag of the cache changes to keep from being overwritten by
@@ -519,84 +517,89 @@ _e_exported_shell_cb_commit_to_cache(void *data, E_Client *ec)
 }
 
 static void
-_e_exported_shell_surface_link(E_Exported_Shell *es, struct wl_resource *surface)
+_e_exported_shell_cb_comp_del(void *data, E_Client *ec)
 {
-   E_Client *esc;
+   E_Exported_Shell *es;
+
+   es = data;
+   if (es->ec != ec)
+     return;
+
+   ESINF(es, "The comp_data of E_Client is deleted.");
 
-   esc = wl_resource_get_user_data(surface);
+   wl_resource_set_user_data(es->resource, NULL);
 
-   e_client_transform_core_add(esc, es->transform);
+   _e_exported_shell_destroy(es);
+}
+
+static void
+_e_exported_shell_ec_link(E_Exported_Shell *es, E_Client *ec)
+{
+   e_client_transform_core_add(ec, es->transform);
 
    /* It's to update transform whenever position of comp object changes by
     * sub-surface. Otherwise, final viewport by transform wouldn't represent
     * changed position. */
-   evas_object_event_callback_add(esc->frame, EVAS_CALLBACK_MOVE,
+   evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE,
                                   _e_exported_shell_cb_eo_move,
                                   es);
 
-   es->surface_destroy_listener.notify = _e_exported_shell_cb_surface_destroy;
-   wl_resource_add_destroy_listener(surface, &es->surface_destroy_listener);
-
    /* FIXME workaround
     * Use apply_viewport_signal due to the absence of commit signal for now. */
    es->surface_commit_listener.notify = _e_exported_shell_cb_surface_commit;
-   wl_signal_add(&esc->comp_data->apply_viewport_signal,
+   wl_signal_add(&ec->comp_data->apply_viewport_signal,
                  &es->surface_commit_listener);
 
    /* Listening to committing to cache */
-   es->commit_to_cache_hook =
+   es->comp_hook.commit_to_cache =
       e_comp_wl_hook_add(E_COMP_WL_HOOK_SUBSURFACE_COMMIT_TO_CACHE,
                          _e_exported_shell_cb_commit_to_cache,
                          es);
 
-   es->surface = surface;
+   es->comp_hook.del = e_comp_wl_hook_add(E_COMP_WL_HOOK_DEL,
+                                          _e_exported_shell_cb_comp_del,
+                                          es);
+
+   es->ec = ec;
 }
 
 static void
-_e_exported_shell_surface_unlink(E_Exported_Shell *es)
+_e_exported_shell_ec_unlink(E_Exported_Shell *es)
 {
-   E_Client *esc;
-
-   esc = wl_resource_get_user_data(es->surface);
+   e_client_transform_core_remove(es->ec, es->transform);
 
-   e_client_transform_core_remove(esc, es->transform);
-
-   evas_object_event_callback_del(esc->frame, EVAS_CALLBACK_MOVE,
+   evas_object_event_callback_del(es->ec->frame, EVAS_CALLBACK_MOVE,
                                   _e_exported_shell_cb_eo_move);
 
    wl_list_remove(&es->surface_commit_listener.link);
-   wl_list_remove(&es->surface_destroy_listener.link);
 
-   E_FREE_FUNC(es->commit_to_cache_hook, e_comp_wl_hook_del);
+   E_FREE_FUNC(es->comp_hook.commit_to_cache, e_comp_wl_hook_del);
+   E_FREE_FUNC(es->comp_hook.del, e_comp_wl_hook_del);
 
-   es->surface = NULL;
+   es->ec = NULL;
 }
 
 static void
 _e_exported_shell_visible_set(E_Exported_Shell *es, Eina_Bool visible)
 {
-   E_Client *esc;
-
-   esc = wl_resource_get_user_data(es->surface);
-
    ESINF(es, "Set visible(%d)", visible);
 
    if (visible)
      {
-        if (!evas_object_visible_get(esc->frame))
+        if (!evas_object_visible_get(es->ec->frame))
           {
-             esc->comp_data->mapped = 1;
-             esc->visible = EINA_TRUE;
-             evas_object_show(esc->frame);
+             es->ec->comp_data->mapped = 1;
+             es->ec->visible = EINA_TRUE;
+             evas_object_show(es->ec->frame);
           }
      }
    else
      {
-        if (evas_object_visible_get(esc->frame))
+        if (evas_object_visible_get(es->ec->frame))
           {
-             esc->comp_data->mapped = 0;
-             esc->visible = EINA_FALSE;
-             evas_object_hide(esc->frame);
+             es->ec->comp_data->mapped = 0;
+             es->ec->visible = EINA_FALSE;
+             evas_object_hide(es->ec->frame);
           }
      }
 
@@ -607,27 +610,24 @@ _e_exported_shell_visible_set(E_Exported_Shell *es, Eina_Bool visible)
 static void
 _e_exported_shell_destination_set(E_Exported_Shell *es, int w, int h)
 {
-   E_Client *esc;
    E_Comp_Wl_Buffer_Viewport *vp;
    int x, y;
 
-   esc = wl_resource_get_user_data(es->surface);
-
    ESINF(es, "Set destination(%dx%d)", w, h);
 
-   esc->client.w = w;
-   esc->client.h = h;
-   e_client_size_set(esc, w, h);
-   evas_object_resize(esc->frame, w, h);
+   es->ec->client.w = w;
+   es->ec->client.h = h;
+   e_client_size_set(es->ec, w, h);
+   evas_object_resize(es->ec->frame, w, h);
 
-   vp = &esc->comp_data->scaler.buffer_viewport;
+   vp = &es->ec->comp_data->scaler.buffer_viewport;
    vp->surface.width = w;
    vp->surface.height = h;
    vp->changed = EINA_TRUE;
 
-   evas_object_geometry_get(esc->frame, &x, &y, NULL, NULL);
+   evas_object_geometry_get(es->ec->frame, &x, &y, NULL, NULL);
    e_util_transform_viewport_set(es->transform, x, y, w, h);
-   e_client_transform_core_update(esc);
+   e_client_transform_core_update(es->ec);
 
    if (es->foreign)
      _e_foreign_shell_destination_set(es->foreign, x, y, w, h);
@@ -668,7 +668,7 @@ _e_foreign_shell_cb_resource_destroy(struct wl_resource *resource)
 }
 
 static E_Foreign_Shell *
-_e_foreign_shell_create(struct wl_resource *resource, struct wl_resource *surface, E_Exported_Shell *es)
+_e_foreign_shell_create(struct wl_resource *resource, E_Client *ec, E_Exported_Shell *es)
 {
    E_Foreign_Shell *fs;
 
@@ -683,7 +683,7 @@ _e_foreign_shell_create(struct wl_resource *resource, struct wl_resource *surfac
         return NULL;
      }
 
-   _e_foreign_shell_surface_link(fs, surface);
+   _e_foreign_shell_ec_link(fs, ec);
 
    if (!es)
      {
@@ -711,60 +711,44 @@ _e_foreign_shell_destroy(E_Foreign_Shell *fs)
    if (fs->exported)
      _e_foreign_shell_exported_unlink(fs);
 
-   _e_foreign_shell_surface_unlink(fs);
+   _e_foreign_shell_ec_unlink(fs);
 
    e_util_transform_del(fs->transform);
    free(fs);
 }
 
-static void
-_e_foreign_shell_cb_surface_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
-{
-   E_Foreign_Shell *fs;
-
-   fs = wl_container_of(listener, fs, surface_destroy_listener);
-
-   FSINF(fs, "wl_surface has been destroyed");
-
-   wl_resource_set_user_data(fs->resource, NULL);
-
-   _e_foreign_shell_destroy(fs);
-}
-
 static void
 _e_foreign_shell_cb_surface_commit(struct wl_listener *listener, void *data EINA_UNUSED)
 {
    E_Foreign_Shell *fs;
-   E_Client *fsc;
 
    fs = wl_container_of(listener, fs, surface_commit_listener);
-   fsc = wl_resource_get_user_data(fs->surface);
 
    /* e_comp_wl has been setting e_client to unignore only for xdg_shell
     * or internal client. */
-   if (fsc->ignored)
+   if (fs->ec->ignored)
      {
-        EC_CHANGED(fsc);
-        fsc->new_client = 1;
+        EC_CHANGED(fs->ec);
+        fs->ec->new_client = 1;
         e_comp->new_clients++;
-        e_client_unignore(fsc);
+        e_client_unignore(fs->ec);
      }
 
    /* e_comp_wl has been setting pixmap of e_client to usable only for
     * xdg_shell */
-   e_pixmap_usable_set(fsc->pixmap, !!e_pixmap_resource_get(fsc->pixmap));
+   e_pixmap_usable_set(fs->ec->pixmap, !!e_pixmap_resource_get(fs->ec->pixmap));
 
    /* It's supposed to be called in e_comp_wl_surface_attach, but call it
     * again just in case. */
-   e_pixmap_dirty(fsc->pixmap);
+   e_pixmap_dirty(fs->ec->pixmap);
 
    /* It's to update pixmap size. It's supposed to be called by
     * e_comp_wl_surface_attach but it failed due to e_pixmap_usable_get. */
-   e_pixmap_refresh(fsc->pixmap);
+   e_pixmap_refresh(fs->ec->pixmap);
 
-   e_comp_wl_map_size_cal_from_buffer(fsc);
+   e_comp_wl_map_size_cal_from_buffer(fs->ec);
 
-   if (fsc->new_client)
+   if (fs->ec->new_client)
      _e_foreign_shell_state_sync_with_exported(fs);
 }
 
@@ -792,14 +776,26 @@ _e_foreign_shell_cb_hook_transform_change(void *data, E_Client *ec)
 }
 #endif
 
-static void 
-_e_foreign_shell_surface_link(E_Foreign_Shell *fs, struct wl_resource *surface)
+static void
+_e_foreign_shell_cb_comp_del(void *data, E_Client *ec)
 {
-   E_Client *fsc;
+   E_Foreign_Shell *fs;
 
-   fsc = wl_resource_get_user_data(surface);
+   fs = data;
+   if (fs->ec != ec)
+     return;
 
-   e_client_transform_core_add(fsc, fs->transform);      
+   FSINF(fs, "The comp_data of E_Client is deleted.");
+
+   wl_resource_set_user_data(fs->resource, NULL);
+
+   _e_foreign_shell_destroy(fs);
+}
+
+static void 
+_e_foreign_shell_ec_link(E_Foreign_Shell *fs, E_Client *ec)
+{
+   e_client_transform_core_add(ec, fs->transform);      
 
    /* TODO */
 #if 0
@@ -809,54 +805,52 @@ _e_foreign_shell_surface_link(E_Foreign_Shell *fs, struct wl_resource *surface)
                         fs);
 #endif
 
-   fs->surface_destroy_listener.notify = _e_foreign_shell_cb_surface_destroy;
-   wl_resource_add_destroy_listener(surface, &fs->surface_destroy_listener);
-
    /* FIXME workaround 
     * Use apply_viewport_signal due to the absence of commit signal for now. */
    fs->surface_commit_listener.notify = _e_foreign_shell_cb_surface_commit;
-   wl_signal_add(&fsc->comp_data->apply_viewport_signal,
+   wl_signal_add(&ec->comp_data->apply_viewport_signal,
                  &fs->surface_commit_listener);
 
    /* To allow changing geometry */
-   fsc->netwm.type = E_WINDOW_TYPE_UTILITY;
-   fsc->lock_focus_in = fsc->lock_focus_out = EINA_TRUE;
-   fsc->netwm.state.skip_taskbar = EINA_TRUE;
-   fsc->netwm.state.skip_pager = EINA_TRUE;
-   fsc->no_shape_cut = EINA_TRUE;
-   fsc->border_size = 0;
-   fsc->lock_user_location = 0;
-   fsc->lock_client_location = 0;
-   fsc->lock_user_size = 0;
-   fsc->lock_client_size = 0;
-   fsc->lock_client_stacking = 0;
-   fsc->lock_user_shade = 0;
-   fsc->lock_client_shade = 0;
-   fsc->lock_user_maximize = 0;
-   fsc->lock_client_maximize = 0;
-   fsc->changes.need_maximize = 0;
-   fsc->maximized = E_MAXIMIZE_NONE;
-
-   fs->surface = surface;
+   ec->netwm.type = E_WINDOW_TYPE_UTILITY;
+   ec->lock_focus_in = ec->lock_focus_out = EINA_TRUE;
+   ec->netwm.state.skip_taskbar = EINA_TRUE;
+   ec->netwm.state.skip_pager = EINA_TRUE;
+   ec->no_shape_cut = EINA_TRUE;
+   ec->border_size = 0;
+   ec->lock_user_location = 0;
+   ec->lock_client_location = 0;
+   ec->lock_user_size = 0;
+   ec->lock_client_size = 0;
+   ec->lock_client_stacking = 0;
+   ec->lock_user_shade = 0;
+   ec->lock_client_shade = 0;
+   ec->lock_user_maximize = 0;
+   ec->lock_client_maximize = 0;
+   ec->changes.need_maximize = 0;
+   ec->maximized = E_MAXIMIZE_NONE;
+
+   fs->comp_del_hook = e_comp_wl_hook_add(E_COMP_WL_HOOK_DEL,
+                                          _e_foreign_shell_cb_comp_del,
+                                          fs);
+
+   fs->ec = ec;
 }
 
 static void
-_e_foreign_shell_surface_unlink(E_Foreign_Shell *fs)
+_e_foreign_shell_ec_unlink(E_Foreign_Shell *fs)
 {
-   E_Client *fsc;
+   e_client_transform_core_remove(fs->ec, fs->transform);
 
-   fsc = wl_resource_get_user_data(fs->surface);
-
-   e_client_transform_core_remove(fsc, fs->transform);
-
-   wl_list_remove(&fs->surface_destroy_listener.link);
    wl_list_remove(&fs->surface_commit_listener.link);
 
 #if 0
    E_FREE_FUNC(fs->transform_change_hook, e_client_hook_del);
 #endif
 
-   fs->surface = NULL;
+   E_FREE_FUNC(fs->comp_del_hook, e_comp_wl_hook_del);
+
+   fs->ec = NULL;
 }
 
 static void
@@ -874,16 +868,12 @@ _e_foreign_shell_cb_exported_shell_destroy(struct wl_listener *listener, void *d
 static void
 _e_foreign_shell_place_under_exported(E_Foreign_Shell *fs)
 {
-   E_Client *fsc, *esc;
    E_Layer layer;
 
-   fsc = wl_resource_get_user_data(fs->surface);
-   esc = wl_resource_get_user_data(fs->exported->surface);
-
-   layer = e_client_layer_get(esc);
-   e_client_layer_set(fsc, layer);
+   layer = e_client_layer_get(fs->exported->ec);
+   e_client_layer_set(fs->ec, layer);
 
-   evas_object_stack_below(fsc->frame, esc->frame);
+   evas_object_stack_below(fs->ec->frame, fs->exported->ec->frame);
 }
 
 static void
@@ -899,11 +889,7 @@ _e_foreign_shell_cb_exported_object_restack(void *data, Evas *e EINA_UNUSED, Eva
 static void
 _e_foreign_shell_exported_restack_handler_add(E_Foreign_Shell *fs)
 {
-   E_Client *esc;
-
-   esc = wl_resource_get_user_data(fs->exported->surface);
-
-   evas_object_event_callback_add(esc->frame,
+   evas_object_event_callback_add(fs->exported->ec->frame,
                                   EVAS_CALLBACK_RESTACK,
                                   _e_foreign_shell_cb_exported_object_restack,
                                   fs);
@@ -912,11 +898,7 @@ _e_foreign_shell_exported_restack_handler_add(E_Foreign_Shell *fs)
 static void
 _e_foreign_shell_exported_restack_handler_remove(E_Foreign_Shell *fs)
 {
-   E_Client *esc;
-
-   esc = wl_resource_get_user_data(fs->exported->surface);
-
-   evas_object_event_callback_del_full(esc->frame,
+   evas_object_event_callback_del_full(fs->exported->ec->frame,
                                        EVAS_CALLBACK_RESTACK,
                                        _e_foreign_shell_cb_exported_object_restack,
                                        fs);
@@ -961,54 +943,47 @@ _e_foreign_shell_exported_unlink(E_Foreign_Shell *fs)
 static void
 _e_foreign_shell_visible_set(E_Foreign_Shell *fs, Eina_Bool visible)
 {
-   E_Client *fsc;
-
-   fsc = wl_resource_get_user_data(fs->surface);
-
    FSINF(fs, "Set visible(%d)", visible);
 
    if ((visible) &&
-       (e_pixmap_usable_get(fsc->pixmap)))
+       (e_pixmap_usable_get(fs->ec->pixmap)))
      {
-        if (!fsc->comp_data->mapped)
+        if (!fs->ec->comp_data->mapped)
           {
-             fsc->comp_data->mapped = 1;
-             fsc->visible = EINA_TRUE;
-             evas_object_show(fsc->frame);
+             fs->ec->comp_data->mapped = 1;
+             fs->ec->visible = EINA_TRUE;
+             evas_object_show(fs->ec->frame);
           }
      }
-   else if (fsc->comp_data->mapped)
+   else if (fs->ec->comp_data->mapped)
      {
-        fsc->comp_data->mapped = 0;
-        fsc->visible = EINA_FALSE;
-        evas_object_hide(fsc->frame);
+        fs->ec->comp_data->mapped = 0;
+        fs->ec->visible = EINA_FALSE;
+        evas_object_hide(fs->ec->frame);
      }
 }
 
 static void
 _e_foreign_shell_viewport_update(E_Foreign_Shell *fs)
 {
-   E_Client *fsc;
    E_Comp_Wl_Buffer_Viewport *vp;
    int x, y, w, h;
 
-   fsc = wl_resource_get_user_data(fs->surface);
-
    x = fs->state.x;
    y = fs->state.y;
    w = fs->state.w;
    h = fs->state.h;
 
-   fsc->client.w = w;
-   fsc->client.h = h;
-   e_client_size_set(fsc, w, h);
-   evas_object_resize(fsc->frame, w, h);
+   fs->ec->client.w = w;
+   fs->ec->client.h = h;
+   e_client_size_set(fs->ec, w, h);
+   evas_object_resize(fs->ec->frame, w, h);
 
-   vp = &fsc->comp_data->scaler.buffer_viewport;
+   vp = &fs->ec->comp_data->scaler.buffer_viewport;
    vp->surface.width = w;
    vp->surface.height = h;
    vp->changed = EINA_TRUE;
-   fsc->comp_data->pending.buffer_viewport = *vp;
+   fs->ec->comp_data->pending.buffer_viewport = *vp;
 
    e_util_transform_viewport_set(fs->transform, x, y, w, h);
 }
@@ -1086,13 +1061,10 @@ _e_foreign_shell_rotation_update(E_Foreign_Shell *fs)
 static void
 _e_foreign_shell_transform_update(E_Foreign_Shell *fs)
 {
-   E_Client *fsc;
-
    _e_foreign_shell_viewport_update(fs);
    _e_foreign_shell_rotation_update(fs);
 
-   fsc = wl_resource_get_user_data(fs->surface);
-   e_client_transform_core_update(fsc);
+   e_client_transform_core_update(fs->ec);
 }
 
 static void