e_service_launcher : supports multiple launchers 64/210564/6
authorMinJeong Kim <minjjj.kim@samsung.com>
Mon, 22 Jul 2019 10:06:42 +0000 (19:06 +0900)
committerGwanglim Lee <gl77.lee@samsung.com>
Thu, 25 Jul 2019 04:39:14 +0000 (04:39 +0000)
Enlightenment has to handle multiple launchers to support not only
home-to-app but also app-to-app launching animation.
This patch includes below features to support that.

1. E_Service_Launcher_Handler object added
 - provides 'launcher_hansh' to store multiple launcher data
 - manages hooks and event handlers.
 - manages runner, pre_runner launchers.
2. runner/pre_runner
 - 'runner' is a pointer of launcher object currently proccessed by enlightenment now.
 - 'pre_runner' is a pointer of launcher object previously proccessed by enlightenment.
 - runner and pre_runner are able to exist as only single instance(or no instance)
 - A launcher that send the latest 'launch' request is 'runner'.
   If there is 'runner' already. the 'runner' is changed to  'pre_runner'.
 - TODO: grouping runner and pre-runner to support multiple launchers running animation.

Change-Id: Ic54d073b9d42ac6e65782f73ddbf99e3d2867cb7
Signed-off-by: MinJeong Kim <minjjj.kim@samsung.com>
src/bin/services/e_service_launcher.c

index dbe68b9..eab9caf 100644 (file)
@@ -2,7 +2,8 @@
 #include <tzsh_server.h>
 #include "services/e_service_launcher.h"
 
-typedef struct _E_Service_Launcher E_Service_Launcher;
+typedef struct _E_Service_Launcher         E_Service_Launcher;
+typedef struct _E_Service_Launcher_Handler E_Service_Launcher_Handler;
 
 typedef enum
 {
@@ -17,35 +18,65 @@ typedef enum
 
 struct _E_Service_Launcher
 {
-   struct wl_resource *res;      //tizen_window_transition_launcher resource
-   Launcher_State      state;    //current state of launcher
+   Launcher_State                       state;          //current state of launcher
 
-   E_Client           *ec;       //launcher E_Client
-   E_Vis_Grab         *vis_grab; //grab of launcher visibility
-   uint32_t            serial;   //identifier
-   enum tws_service_launcher_direction direction; //direction of transition
+   struct wl_resource                  *res;            //tizen_window_transition_launcher resource
+   E_Client                            *ec;             //launcher E_Client
+
+   E_Vis_Grab                          *vis_grab;       //grab of launcher visibility
+   uint32_t                             serial;         //identifier
+   enum tws_service_launcher_direction  direction;      //direction of transition
 
    struct
      {
-        E_Client   *ec;        //target E_Client
-        pid_t       pid;       //pid
-        E_Vis_Grab *vis_grab;  //grab of target client's visibility
-        Eina_Bool   delay_del; //refered delay_del
+        E_Client                       *ec;             //target E_Client
+        pid_t                           pid;            //pid
+        E_Vis_Grab                     *vis_grab;       //grab of target client's visibility
+
+        Eina_Bool                       delay_del;      //refered delay_del
+        E_Object_Delfn                 *delfn;          //del callback of target E_Client
      } target; //target window information for transition
 
-   E_Client            *launched_ec;     //E_Client was launched by launcher
+   E_Client                            *launched_ec;    //E_Client was launched by launcher
+   E_Object_Delfn                      *launched_delfn;  //del callback of launched_ec
+
+   Ecore_Event_Handler                 *buff_attach;    //event handler for BUFFER_CHANGE
+};
+
+struct _E_Service_Launcher_Handler
+{
+   Eina_Hash           *launcher_hash;  //hash key:launcher_ec, data:E_Service_Launcher
+   unsigned int         launcher_count; //count of launcher object
+
+   Eina_List           *hooks_ec;       //hook list for E_CLIENT_HOOK_*
+   Eina_List           *hooks_vis;      //hook list for E_POL_VIS_HOOK_TYPE_*
+   Eina_List           *hooks_co;       //hook list for E_COMP_OBJECT_INTERCEPT_HOOK_*
+   Eina_List           *hdlrs_ev;       //handler list for ecore events
 
-   Ecore_Event_Handler *buf_attach;      //event handler for BUFFER_CHANGE
-   Eina_List           *hooks_ec;        //hook list for E_CLIENT_HOOK_*
-   Eina_List           *hooks_co;        //hook list for E_COMP_OBJECT_INTERCEPT_*
-   Eina_List           *hooks_vis;       //hook list for E_POL_VIS_HOOK_TYPE_*
-   Eina_List           *handlers;        //ecore event handlers
+   E_Service_Launcher  *runner;         //current runner(running launcher)
+   E_Service_Launcher  *pre_runner;     //previous runner
 };
+
 ////////////////////////////////////////////////////////////////////
-static E_Service_Launcher  *_e_srv_launcher = NULL; //only one instance is allowed
+static E_Service_Launcher_Handler *_laundler = NULL;
+
+static void                _launcher_launched_ec_set(E_Service_Launcher *lc, E_Client *launched_ec);
+static void                _launcher_target_ec_set(E_Service_Launcher *lc, E_Client *target_ec);
+
+static E_Service_Launcher *_launcher_handler_launcher_find(E_Client *ec);
+static Eina_Bool           _launcher_handler_launcher_add(E_Service_Launcher *lc);
+static Eina_Bool           _launcher_handler_launcher_del(E_Service_Launcher *lc);
+
+static E_Service_Launcher *_launcher_handler_launcher_runner_get(void);
+static void                _launcher_handler_launcher_runner_set(E_Service_Launcher *lc);
+static void                _launcher_handler_launcher_runner_unset(E_Service_Launcher *lc);
+static E_Service_Launcher *_launcher_handler_launcher_pre_runner_get(void);
+static void                _launcher_handler_launcher_pre_runner_set(E_Service_Launcher *lc);
+static void                _launcher_handler_launcher_pre_runner_unset(E_Service_Launcher *lc);
+
 ////////////////////////////////////////////////////////////////////
 static Eina_List *
-_e_srv_launcher_clients_find_by_pid(pid_t pid)
+_launcher_clients_find_by_pid(pid_t pid)
 {
    E_Client *ec;
    Eina_List *clients = NULL, *l;
@@ -61,7 +92,7 @@ _e_srv_launcher_clients_find_by_pid(pid_t pid)
 }
 
 static const char*
-_e_srv_launcher_state_to_str(Launcher_State state)
+_launcher_state_to_str(Launcher_State state)
 {
    switch (state)
      {
@@ -84,7 +115,7 @@ _e_srv_launcher_state_to_str(Launcher_State state)
 }
 
 static void
-_e_srv_launcher_state_set(E_Service_Launcher *lc,
+_launcher_state_set(E_Service_Launcher *lc,
                           Launcher_State state)
 {
    EINA_SAFETY_ON_NULL_RETURN(lc);
@@ -93,14 +124,99 @@ _e_srv_launcher_state_set(E_Service_Launcher *lc,
 
    ELOGF("LAUNCHER_SRV", "Set state  %s --> %s",
          lc->ec,
-         _e_srv_launcher_state_to_str(lc->state),
-         _e_srv_launcher_state_to_str(state));
+         _launcher_state_to_str(lc->state),
+         _launcher_state_to_str(state));
 
    lc->state = state;
 }
 
 static void
-_e_srv_launcher_stop_send(E_Service_Launcher *lc)
+_launcher_post_forward(E_Service_Launcher *lc, Eina_Bool success)
+{
+   E_Client *target_ec = NULL;
+
+   if ((lc->target.ec) && (!e_object_is_del(E_OBJECT(lc->target.ec))))
+     target_ec = lc->target.ec;
+
+   _launcher_target_ec_set(lc, NULL);
+
+   lc->serial = 0;
+   lc->target.pid = -1;
+
+   //if forward animation is failed, enlightenment can run animation instead.
+   if ((!success) && (target_ec))
+     e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
+
+   if (lc->vis_grab)
+     e_policy_visibility_client_grab_release(lc->vis_grab);
+   if (lc->target.vis_grab)
+     e_policy_visibility_client_grab_release(lc->target.vis_grab);
+
+   lc->vis_grab = NULL;
+   lc->target.vis_grab = NULL;
+
+   if (!target_ec) return;
+
+   if (success)
+     _launcher_launched_ec_set(lc, target_ec);
+
+   //show target_ec
+   e_comp_object_damage(target_ec->frame, 0, 0, target_ec->w, target_ec->h);
+   e_comp_object_dirty(target_ec->frame);
+   e_comp_object_render(target_ec->frame);
+   evas_object_show(target_ec->frame);
+
+   e_comp_client_override_del(target_ec);
+}
+
+static void
+_launcher_post_backward(E_Service_Launcher *lc, Eina_Bool success)
+{
+   E_Client *target_ec = NULL;
+
+   target_ec = lc->target.ec;
+   _launcher_target_ec_set(lc, NULL);
+
+   lc->serial = 0;
+   lc->target.pid = -1;
+   lc->direction = 0;
+
+   E_FREE_FUNC(lc->buff_attach, ecore_event_handler_del);
+
+   if (target_ec)
+     {
+        Eina_Bool is_del;
+        is_del = e_object_is_del(E_OBJECT(target_ec));
+        if (lc->target.delay_del)
+          e_object_delay_del_unref(E_OBJECT(target_ec));
+
+        if (is_del)
+          target_ec = NULL;
+     }
+   lc->target.delay_del = EINA_FALSE;
+
+   //if forward animation is failed, enlightenment can run animation instead.
+   if ((!success) && (target_ec))
+     e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
+
+   if (lc->vis_grab)
+     e_policy_visibility_client_grab_release(lc->vis_grab);
+   if (lc->target.vis_grab)
+     e_policy_visibility_client_grab_release(lc->target.vis_grab);
+
+   lc->vis_grab = NULL;
+   lc->target.vis_grab = NULL;
+
+   if (!target_ec) return;
+
+   if (success)
+     e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
+
+   e_comp_client_override_del(target_ec);
+}
+
+static void
+_launcher_stop_send(E_Service_Launcher *lc)
 {
    EINA_SAFETY_ON_NULL_RETURN(lc);
 
@@ -111,7 +227,7 @@ _e_srv_launcher_stop_send(E_Service_Launcher *lc)
 }
 
 static Eina_Bool
-_e_srv_launcher_prepare_send(E_Service_Launcher *lc,
+_launcher_prepare_send(E_Service_Launcher *lc,
                              E_Client *target_ec,
                              int x, int y)
 {
@@ -119,12 +235,18 @@ _e_srv_launcher_prepare_send(E_Service_Launcher *lc,
 
    E_Comp_Object_Content_Type content_type = 0;
    enum tws_service_launcher_target_type target_type = 0;
-   const char *target_path = NULL;
+   const char *target_path = NULL, *target_group = NULL;
    Evas_Object *content = NULL;
+   struct wl_array info_array;
+
+   int len;
+   char *p_char;
+   uint32_t *p_u32;
 
    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
    EINA_SAFETY_ON_NULL_RETURN_VAL(target_ec, EINA_FALSE);
 
+   wl_array_init(&info_array);
    if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
      {
         content_type = e_comp_object_content_type_get(target_ec->frame);
@@ -132,31 +254,59 @@ _e_srv_launcher_prepare_send(E_Service_Launcher *lc,
           {
            case E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE:
               content = e_comp_object_content_get(target_ec->frame);
-              EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
+              EINA_SAFETY_ON_NULL_GOTO(content, fail);
 
               target_type = TWS_SERVICE_LAUNCHER_TARGET_TYPE_IMAGE;
               evas_object_image_file_get(content, &target_path, NULL);
-              EINA_SAFETY_ON_NULL_RETURN_VAL(target_path, EINA_FALSE);
+              EINA_SAFETY_ON_NULL_GOTO(target_path, fail);
 
+              len = strlen(target_path) + 1;
+              p_char = wl_array_add(&info_array, len);
+              EINA_SAFETY_ON_NULL_GOTO(p_char, fail);
+
+              strncpy(p_char, target_path, len);
               break;
            case E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE:
               content = e_comp_object_content_get(target_ec->frame);
-              EINA_SAFETY_ON_NULL_RETURN_VAL(content, EINA_FALSE);
+              EINA_SAFETY_ON_NULL_GOTO(content, fail);
 
               target_type = TWS_SERVICE_LAUNCHER_TARGET_TYPE_EDJE;
-              edje_object_file_get(content, &target_path, NULL);
-              EINA_SAFETY_ON_NULL_RETURN_VAL(target_path, EINA_FALSE);
+              edje_object_file_get(content, &target_path, &target_group);
+              EINA_SAFETY_ON_NULL_GOTO(target_path, fail);
+              EINA_SAFETY_ON_NULL_GOTO(target_group, fail);
+
+              len = strlen(target_path) + 1;
+              p_char = wl_array_add(&info_array, len);
+              EINA_SAFETY_ON_NULL_GOTO(p_char, fail);
+
+              strncpy(p_char, target_path, len);
+
+              len = strlen(target_group) + 1;
+              p_char = wl_array_add(&info_array, len);
+              EINA_SAFETY_ON_NULL_GOTO(p_char, fail);
+
+              strncpy(p_char, target_group, len);
 
               break;
            default:
               target_type = TWS_SERVICE_LAUNCHER_TARGET_TYPE_REMOTE_SURFACE;
               res_id = e_pixmap_res_id_get(target_ec->pixmap);
+
+              p_u32 = wl_array_add(&info_array, sizeof(uint32_t));
+              EINA_SAFETY_ON_NULL_GOTO(p_u32, fail);
+
+              *p_u32 = res_id;
           }
      }
    else
      {
         target_type = TWS_SERVICE_LAUNCHER_TARGET_TYPE_REMOTE_SURFACE;
         res_id = e_pixmap_res_id_get(target_ec->pixmap);
+
+        p_u32 = wl_array_add(&info_array, sizeof(uint32_t));
+        EINA_SAFETY_ON_NULL_GOTO(p_u32, fail);
+
+        *p_u32 = res_id;
      }
 
 
@@ -165,15 +315,19 @@ _e_srv_launcher_prepare_send(E_Service_Launcher *lc,
 
    tws_service_launcher_send_prepare(lc->res,
                                      target_type,
-                                     res_id, target_path,
+                                     &info_array,
                                      lc->direction,
                                      x, y, lc->serial);
 
+   wl_array_release(&info_array);
    return EINA_TRUE;
+fail:
+   wl_array_release(&info_array);
+   return EINA_FALSE;
 }
 
 static Eina_Bool
-_e_srv_launcher_prepare_forward_send(E_Service_Launcher *lc,
+_launcher_prepare_forward_send(E_Service_Launcher *lc,
                                      E_Client *target_ec)
 {
    Eina_Bool sent = EINA_FALSE;
@@ -194,37 +348,27 @@ _e_srv_launcher_prepare_forward_send(E_Service_Launcher *lc,
                                                                          E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY),
                                                                         __func__);
 
-   lc->launched_ec = NULL;
-   lc->target.ec = target_ec;
-   lc->direction = TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD;
-   lc->serial = wl_display_next_serial(e_comp_wl->wl.disp);
+   _launcher_launched_ec_set(lc, NULL);
+   _launcher_target_ec_set(lc, target_ec);
 
+   lc->direction = TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD;
+   lc->serial = wl_display_next_serial(e_comp_wl->wl.disp);\
    e_client_pos_get(target_ec, &x, &y);
 
-   sent = _e_srv_launcher_prepare_send(lc, target_ec, x, y);
+   sent = _launcher_prepare_send(lc, target_ec, x, y);
 
+   //fail to send protocol event
    if (!sent)
      {
         ELOGF("LAUNCHER_SRV", "Failed to send event(PREPARE:FORWARD)", lc->ec);
-
-        lc->launched_ec = NULL;
-        lc->target.ec = NULL;
-        lc->direction = 0;
-        lc->serial = 0;
-
-        if (lc->target.vis_grab)
-          e_policy_visibility_client_grab_release(lc->target.vis_grab);
-        lc->target.vis_grab = NULL;
-
-        e_comp_client_override_del(target_ec);
-        e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
+        _launcher_post_forward(lc, EINA_FALSE);
      }
 
    return sent;
 }
 
 static Eina_Bool
-_e_srv_launcher_prepare_backward_send(E_Service_Launcher *lc,
+_launcher_prepare_backward_send(E_Service_Launcher *lc,
                                       E_Client *activity,
                                       E_Client *target_ec,
                                       E_Vis_Job_Type job_type)
@@ -259,224 +403,551 @@ _e_srv_launcher_prepare_backward_send(E_Service_Launcher *lc,
         lc->target.vis_grab = e_policy_visibility_client_filtered_grab_get(target_ec, job_type, __func__);
      }
 
-   lc->launched_ec = NULL;
-   lc->target.ec = target_ec;
+   _launcher_launched_ec_set(lc, NULL);
+   _launcher_target_ec_set(lc, target_ec);
+
    lc->serial = wl_display_next_serial(e_comp_wl->wl.disp);
    lc->direction = TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD;
    e_client_pos_get(target_ec, &x, &y);
 
-   sent = _e_srv_launcher_prepare_send(lc, target_ec, x, y);
+   sent = _launcher_prepare_send(lc, target_ec, x, y);
 
+   //fail to send protocol event
    if (!sent)
      {
         ELOGF("LAUNCHER_SRV", "Failed to send event(PREPARE:BACKWARD)", lc->ec);
-
-        lc->launched_ec = NULL;
-        lc->target.ec = NULL;
-        lc->serial = 0;
-        lc->direction = 0;
-
-        if (lc->vis_grab)
-          e_policy_visibility_client_grab_release(lc->vis_grab);
-        if (lc->target.vis_grab)
-          e_policy_visibility_client_grab_release(lc->target.vis_grab);
-
-        e_comp_client_override_del(target_ec);
-        e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
-
-        e_object_delay_del_unref(E_OBJECT(target_ec));
-        lc->target.delay_del = EINA_FALSE;
+        _launcher_post_backward(lc, EINA_FALSE);
      }
 
    return sent;
 }
 
+/* Reset lc data */
 static void
-_e_srv_launcher_post_forward(E_Service_Launcher *lc,
-                             Eina_Bool success)
+_launcher_data_reset(E_Service_Launcher *lc)
 {
-   E_Client *target_ec = NULL;
+   EINA_SAFETY_ON_NULL_RETURN(lc);
 
-   if ((lc->target.ec) && (!e_object_is_del(E_OBJECT(lc->target.ec))))
-     target_ec = lc->target.ec;
+   ELOGF("LAUNCHER_SRV", "Reset Launcher Data", lc->ec);
 
-   lc->serial = 0;
-   lc->target.ec = NULL;
-   lc->target.pid = -1;
+   //clear resource and send 'DISQUALIFIED' msg
+   if (lc->res)
+     {
+        tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_DISQUALIFIED, lc->serial);
+        wl_resource_set_user_data(lc->res, NULL);
+        lc->res = NULL;
+     }
 
-   //if forward animation is failed, enlightenment can run animation instead.
-   if ((!success) && (target_ec))
-     e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
+   if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
+     _launcher_post_forward(lc, EINA_FALSE);
+   else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
+     _launcher_post_backward(lc, EINA_FALSE);
 
-   if (lc->vis_grab)
-     e_policy_visibility_client_grab_release(lc->vis_grab);
-   if (lc->target.vis_grab)
-     e_policy_visibility_client_grab_release(lc->target.vis_grab);
+   _launcher_state_set(lc, LAUNCHER_STATE_IDLE);
+   _launcher_launched_ec_set(lc, NULL);
 
-   lc->vis_grab = NULL;
-   lc->target.vis_grab = NULL;
+   _launcher_handler_launcher_runner_unset(lc);
+   _launcher_handler_launcher_pre_runner_unset(lc);
 
-   if (!target_ec) return;
+   lc->direction = 0;
+}
 
-   if (success)
-     lc->launched_ec = target_ec;
 
-   //show target_ec
-   e_comp_object_damage(target_ec->frame, 0, 0, target_ec->w, target_ec->h);
-   e_comp_object_dirty(target_ec->frame);
-   e_comp_object_render(target_ec->frame);
-   evas_object_show(target_ec->frame);
+static Eina_Bool
+_launcher_cb_event_buff_attach(void *data, int type EINA_UNUSED, void *event)
+{
+   E_Service_Launcher *lc;
+   E_Client *ec;
+   E_Event_Client *ev;
 
-   e_comp_client_override_del(target_ec);
-}
+   lc = (E_Service_Launcher*)data;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(lc, ECORE_CALLBACK_PASS_ON);
 
-static void
-_e_srv_launcher_post_backward(E_Service_Launcher *lc,
-                              Eina_Bool success)
-{
-   E_Client *target_ec = NULL;
+   ev = (E_Event_Client *)event;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
 
-   target_ec = lc->target.ec;
+   ec = ev->ec;
+   if (ec != lc->ec) return ECORE_CALLBACK_PASS_ON;
 
-   lc->serial = 0;
-   lc->target.ec = NULL;
-   lc->target.pid = -1;
+   ELOGF("LAUNCHER_SRV", "Event cb(BUFFER_CHANGE)", ec);
 
-   E_FREE_FUNC(lc->buf_attach, ecore_event_handler_del);
+   if (lc->state == LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER)
+     _launcher_state_set(lc, LAUNCHER_STATE_LAUNCHING);
 
-   if (target_ec)
+   if (lc->vis_grab)
      {
-        Eina_Bool is_del;
-        is_del = e_object_is_del(E_OBJECT(target_ec));
-        if (lc->target.delay_del)
-          e_object_delay_del_unref(E_OBJECT(target_ec));
-
-        if (is_del)
-          target_ec = NULL;
+        e_policy_visibility_client_grab_release(lc->vis_grab);
+        lc->vis_grab = NULL;
      }
-   lc->target.delay_del = EINA_FALSE;
-
-   //if forward animation is failed, enlightenment can run animation instead.
-   if ((!success) && (target_ec))
-     e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
 
-   if (lc->vis_grab)
-     e_policy_visibility_client_grab_release(lc->vis_grab);
    if (lc->target.vis_grab)
-     e_policy_visibility_client_grab_release(lc->target.vis_grab);
+     {
+        e_policy_visibility_client_grab_release(lc->target.vis_grab);
+        lc->target.vis_grab = NULL;
+     }
 
-   lc->vis_grab = NULL;
-   lc->target.vis_grab = NULL;
+   E_FREE_FUNC(lc->buff_attach, ecore_event_handler_del);
 
-   if (!target_ec) return;
+   return ECORE_CALLBACK_PASS_ON;
+}
 
-   if (success)
-     e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
+static void
+_launcher_cb_launched_ec_del(void *data, void *obj)
+{
+   E_Service_Launcher *lc = (E_Service_Launcher *)data;
+   E_Client *launched_ec = (E_Client *)obj;
 
-   e_comp_client_override_del(target_ec);
+   EINA_SAFETY_ON_NULL_RETURN(launched_ec);
+   EINA_SAFETY_ON_NULL_RETURN(lc);
+   EINA_SAFETY_ON_TRUE_RETURN(lc->launched_ec != launched_ec);
+
+   lc->launched_ec = NULL;
+   lc->launched_delfn = NULL;
 }
 
-/* Reset lc data except for reusable hooks and handlers. */
 static void
-_e_srv_launcher_data_reset(E_Service_Launcher *lc)
+_launcher_cb_target_ec_del(void *data, void *obj)
 {
+   E_Service_Launcher *lc = (E_Service_Launcher *)data;
+   E_Client *target_ec = (E_Client *)obj;
+
+   EINA_SAFETY_ON_NULL_RETURN(target_ec);
    EINA_SAFETY_ON_NULL_RETURN(lc);
+   EINA_SAFETY_ON_TRUE_RETURN(lc->target.ec != target_ec);
 
-   ELOGF("LAUNCHER_SRV", "Reset Launcher Data", lc->ec);
+   lc->target.ec = NULL;
+   lc->target.delfn = NULL;
 
-   //clear resource and send 'DISQUALIFIED' msg
-   if (lc->res)
+   switch (lc->state)
      {
-        tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_DISQUALIFIED);
-        wl_resource_set_user_data(lc->res, NULL);
-        lc->res = NULL;
-     }
+      case LAUNCHER_STATE_PREPARING:
+      case LAUNCHER_STATE_LAUNCHING:
+      case LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER:
+         _launcher_stop_send(lc);
+         if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
+           _launcher_post_forward(lc, EINA_FALSE);
+         else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
+           _launcher_post_backward(lc, EINA_FALSE);
 
-   if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
-     _e_srv_launcher_post_forward(lc, EINA_FALSE);
-   else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
-     _e_srv_launcher_post_backward(lc, EINA_FALSE);
+         _launcher_handler_launcher_runner_unset(lc);
+         _launcher_handler_launcher_pre_runner_unset(lc);
 
-   _e_srv_launcher_state_set(lc, LAUNCHER_STATE_IDLE);
-   lc->direction = 0;
-   lc->launched_ec = NULL;
+         _launcher_state_set(lc, LAUNCHER_STATE_IDLE);
+         break;
+      default:
+         break;
+     }
 }
 
 static void
-_e_srv_launcher_data_free(E_Service_Launcher *lc)
+_launcher_launched_ec_set(E_Service_Launcher *lc, E_Client *launched_ec)
 {
    EINA_SAFETY_ON_NULL_RETURN(lc);
+   if (lc->launched_ec == launched_ec) return;
 
-   E_FREE_FUNC(lc->buf_attach, ecore_event_handler_del);
-   E_FREE_LIST(lc->handlers,   ecore_event_handler_del);
-   E_FREE_LIST(lc->hooks_ec,   e_client_hook_del);
-   E_FREE_LIST(lc->hooks_co,   e_comp_object_intercept_hook_del);
-   E_FREE_LIST(lc->hooks_vis,  e_policy_visibility_hook_del);
-
-   _e_srv_launcher_data_reset(lc);
+   if (lc->launched_ec)
+     {
+        e_object_delfn_del(E_OBJECT(lc->launched_ec), lc->launched_delfn);
+        lc->launched_ec = NULL;
+        lc->launched_delfn = NULL;
+     }
 
-   E_FREE(lc);
+   if (launched_ec)
+     {
+        lc->launched_ec = launched_ec;
+        lc->launched_delfn = e_object_delfn_add(E_OBJECT(launched_ec),
+                                                _launcher_cb_launched_ec_del, lc);
+     }
 }
 
-static Eina_Bool
-_e_srv_launcher_cb_hook_intercept_show_helper(void *data, E_Client *ec)
+static void
+_launcher_target_ec_set(E_Service_Launcher *lc, E_Client *target_ec)
 {
-   E_Service_Launcher *lc;
-   Eina_Bool sent = EINA_FALSE;
-
-   lc = (E_Service_Launcher*)data;
-
-   EINA_SAFETY_ON_NULL_GOTO(lc, show_allow);
-   EINA_SAFETY_ON_NULL_GOTO(ec, show_allow);
+   EINA_SAFETY_ON_NULL_RETURN(lc);
+   if (lc->target.ec == target_ec) return;
 
-   if (ec->new_client) goto show_allow;
+   if (lc->target.ec)
+     {
+        e_object_delfn_del(E_OBJECT(lc->target.ec), lc->target.delfn);
+        lc->target.ec = NULL;
+        lc->target.delfn = NULL;
+     }
 
-   switch (lc->state)
+   if (target_ec)
      {
-      case LAUNCHER_STATE_IDLE:
-      case LAUNCHER_STATE_DONE:
-      case LAUNCHER_STATE_CANCELED:               //animation ended or didn't start
-         goto show_allow;
-      case LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER:  //waiting buffer change
-         goto show_deny;
-      case LAUNCHER_STATE_PREPARING:              //waiting launcher client's preparation
-         if (ec == lc->target.ec) goto show_deny;
-         break;
-      case LAUNCHER_STATE_LAUNCHING:              //doing animation
-         if (ec == lc->target.ec) goto show_deny; //don't show launched app window
-         else if (ec == lc->ec) goto show_allow;  //show launcher
-         break;
-      case LAUNCHER_STATE_MONITORING:             //waiting creation of target window
-         if (lc->target.pid != ec->netwm.pid) goto show_allow;
-         if (e_object_is_del(E_OBJECT(ec))) goto show_allow;
+        lc->target.ec = target_ec;
+        lc->target.delfn = e_object_delfn_add(E_OBJECT(target_ec),
+                                              _launcher_cb_target_ec_del, lc);
+     }
+}
 
-         sent = _e_srv_launcher_prepare_forward_send(lc, ec);
-         EINA_SAFETY_ON_FALSE_GOTO(sent, send_stop);
+static void
+_launcher_cb_resource_destroy(struct wl_resource *res_tws_lc)
+{
+   E_Service_Launcher *lc;
 
-         _e_srv_launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
-         goto show_deny;
-      default:
-         goto show_allow;
+   lc = wl_resource_get_user_data(res_tws_lc);
+   if (!lc) return;
+
+   ELOGF("LAUNCHER_SRV", "Start Resource Destroy tws_service_launcher", lc->ec);
+
+   _launcher_handler_launcher_del(lc);
+
+   lc->res = NULL;
+   _launcher_data_reset(lc);
+
+   E_FREE(lc);
+
+   ELOGF("LAUNCHER_SRV", "End Resource Destroy tws_service_launcher", NULL);
+}
+
+static void
+_launcher_cb_destroy(struct wl_client *client EINA_UNUSED,
+                           struct wl_resource *res_tws_lc)
+{
+   ELOGF("LAUNCHER_SRV", "Received request(launcher_destroy)", NULL);
+   wl_resource_destroy(res_tws_lc);
+}
+
+static void
+_launcher_cb_launch(struct wl_client *client EINA_UNUSED,
+                          struct wl_resource *res_tws_lc,
+                          const char *app_id,
+                          const char *instance_id,
+                          int32_t pid)
+{
+   E_Service_Launcher *lc;
+   E_Service_Launcher *runner, *pre_runner;
+   E_Client *target_ec;
+   Eina_List *ecs, *l;
+   Eina_Bool sent = EINA_FALSE;
+
+   lc = wl_resource_get_user_data(res_tws_lc);
+   EINA_SAFETY_ON_NULL_RETURN(lc);
+   EINA_SAFETY_ON_NULL_RETURN(lc->ec);
+
+   ELOGF("LAUNCHER_SRV",
+         "Recieved request(launcher_launch) appid:%s instance id:%s pid:%d",
+         lc->ec, app_id?:"NONE", instance_id?:"NONE", pid);
+
+   EINA_SAFETY_ON_TRUE_GOTO(lc->ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED, send_stop);
+   EINA_SAFETY_ON_TRUE_GOTO(pid < 0, send_stop);
+
+   //check current state of lc
+   runner =  _launcher_handler_launcher_runner_get();
+   if (runner == lc)
+     {
+        ELOGF("LAUNCHER_SRV",
+              "Launcher(%s) requests LAUNCH again without cancel, ignore this.",
+              lc->ec, _launcher_state_to_str(lc->state));
+
+        tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_WRONG_REQUEST, lc->serial);
+        return;
      }
 
-show_allow:
-   return EINA_TRUE;
-show_deny:
-   return EINA_FALSE;
+   pre_runner = _launcher_handler_launcher_pre_runner_get();
+   if (pre_runner == lc)
+     {
+        _launcher_handler_launcher_pre_runner_set(NULL);
+        _launcher_launched_ec_set(lc, NULL);
+     }
+
+   lc->target.pid = pid;
+
+   ecs = _launcher_clients_find_by_pid(pid);
+   EINA_LIST_FOREACH(ecs, l, target_ec)
+     {
+        if (e_object_is_del(E_OBJECT(target_ec))) continue;
+        if (e_client_util_ignored_get(target_ec)) continue;
+
+        ELOGF("LAUNCHER_SRV", "Found target_ec:%p", lc->ec, target_ec);
+
+        sent = _launcher_prepare_forward_send(lc, target_ec);
+        EINA_SAFETY_ON_FALSE_GOTO(sent, send_stop);
+
+        _launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
+        break;
+     }
+   eina_list_free(ecs);
+
+   if (!lc->target.ec)
+     {
+        ELOGF("LAUNCHER_SRV", "Can't find target_ec, Start Monitoring", lc->ec);
+        _launcher_state_set(lc, LAUNCHER_STATE_MONITORING);
+     }
+
+   _launcher_handler_launcher_runner_set(lc);
+
+   return;
+
 send_stop:
-   lc->target.pid = -1;
-   _e_srv_launcher_stop_send(lc);
-   _e_srv_launcher_state_set(lc, LAUNCHER_STATE_IDLE);
-   return EINA_TRUE;
+   ELOGF("LAUNCHER_SRV", "can't process request(launcher_launch)", lc->ec);
+   _launcher_stop_send(lc);
 }
 
-static Eina_Bool
-_e_srv_launcher_cb_hook_vis_uniconify_render_running(void *data EINA_UNUSED, E_Client *ec)
+static void
+_launcher_cb_launching(struct wl_client *client EINA_UNUSED,
+                             struct wl_resource *res_tws_lc,
+                             uint32_t serial)
+{
+   E_Service_Launcher *lc;
+   E_Service_Launcher *runner;
+
+   lc = wl_resource_get_user_data(res_tws_lc);
+   EINA_SAFETY_ON_NULL_RETURN(lc);
+
+   ELOGF("LAUNCHER_SRV", "LAUNCHING(%d) %s",
+         lc->ec, serial, lc->direction?"backward":"forward");
+
+   //check current state of lc
+   runner = _launcher_handler_launcher_runner_get();
+   if (runner != lc)
+     {
+        ELOGF("LAUNCHER_SRV", "lc(%p) runner(%p), lc is not runner, ignore LAUNCHING",
+              lc->ec, lc, runner);
+        tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_WRONG_REQUEST, lc->serial);
+        return;
+     }
+
+   _launcher_state_set(lc, LAUNCHER_STATE_LAUNCHING);
+
+   if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
+     {
+        _launcher_state_set(lc, LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER);
+        lc->buff_attach = ecore_event_handler_add(E_EVENT_CLIENT_BUFFER_CHANGE,
+                                                 _launcher_cb_event_buff_attach, lc);
+     }
+}
+
+static void
+_launcher_cb_launch_done(struct wl_client *client EINA_UNUSED,
+                               struct wl_resource *res_tws_lc,
+                               uint32_t serial)
+{
+   E_Service_Launcher *lc;
+   E_Service_Launcher *runner;
+
+   lc = wl_resource_get_user_data(res_tws_lc);
+   EINA_SAFETY_ON_NULL_RETURN(lc);
+
+   ELOGF("LAUNCHER_SRV", "LAUNCH_DONE(%d) target:%p", lc->ec, serial, lc->target.ec);
+
+   //check current state of lc
+   runner = _launcher_handler_launcher_runner_get();
+   if (runner != lc)
+     {
+        ELOGF("LAUNCHER_SRV", "lc(%p) runner(%p), lc is not runner, ignore LAUNCH_DONE",
+              lc->ec, lc, runner);
+        tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_WRONG_REQUEST, lc->serial);
+        return;
+     }
+
+   if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
+     _launcher_post_forward(lc, EINA_TRUE);
+   else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
+     _launcher_post_backward(lc, EINA_TRUE);
+
+   _launcher_handler_launcher_runner_unset(lc);
+   _launcher_handler_launcher_pre_runner_set(lc);
+   _launcher_state_set(lc, LAUNCHER_STATE_DONE);
+}
+
+static void
+_launcher_cb_launch_cancel(struct wl_client *client EINA_UNUSED,
+                                 struct wl_resource *res_tws_lc,
+                                 uint32_t serial)
 {
    E_Service_Launcher *lc;
+   E_Service_Launcher *runner;
+
+   lc = wl_resource_get_user_data(res_tws_lc);
+   EINA_SAFETY_ON_NULL_RETURN(lc);
+
+   ELOGF("LAUNCHER_SRV", "LAUNCH_CANCEL(%d) target_ec:%p",
+         lc->ec, serial, lc->target.ec);
+
+   //check state of lc
+   runner = _launcher_handler_launcher_runner_get();
+   if (runner != lc)
+     {
+        ELOGF("LAUNCHER_SRV", "lc(%p) runner(%p), lc is not runner, ignore LAUNCH_CANCEL",
+              lc->ec, lc, runner);
+        tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_WRONG_REQUEST, lc->serial);
+        return;
+     }
+
+   if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
+     _launcher_post_forward(lc, EINA_FALSE);
+   else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
+     _launcher_post_backward(lc, EINA_FALSE);
+
+   _launcher_handler_launcher_runner_unset(lc);
+   _launcher_handler_launcher_pre_runner_set(lc);
+   _launcher_state_set(lc, LAUNCHER_STATE_CANCELED);
+}
+
+static const struct tws_service_launcher_interface _launcher_iface =
+{
+   _launcher_cb_destroy,
+   _launcher_cb_launch,
+   _launcher_cb_launching,
+   _launcher_cb_launch_done,
+   _launcher_cb_launch_cancel,
+};
+
+static E_Service_Launcher *
+_launcher_handler_launcher_find(E_Client *ec)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler->launcher_hash, NULL);
+
+   return eina_hash_find(_laundler->launcher_hash, &ec);
+}
+
+static Eina_Bool
+_launcher_handler_launcher_add(E_Service_Launcher *lc)
+{
+   Eina_Bool ret;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(lc->ec, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler->launcher_hash, EINA_FALSE);
+
+   ret = eina_hash_add(_laundler->launcher_hash, &lc->ec, lc);
+   if (ret)
+     _laundler->launcher_count++;
+
+   return ret;
+}
+
+static Eina_Bool
+_launcher_handler_launcher_del(E_Service_Launcher *lc)
+{
+   Eina_Bool ret;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(lc->ec, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler->launcher_hash, EINA_FALSE);
+
+   ret = eina_hash_del(_laundler->launcher_hash, &lc->ec, lc);
+   if (ret) _laundler->launcher_count--;
+
+   return ret;
+}
+
+static void
+_launcher_handler_launcher_runner_set(E_Service_Launcher *lc)
+{
+   E_Service_Launcher *runner = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(_laundler);
+   if (_laundler->runner == lc) return;
+
+   //reset previous runner
+   runner = _laundler->runner;
+   if (runner)
+     {
+        switch (runner->state)
+          {
+           case LAUNCHER_STATE_PREPARING:
+           case LAUNCHER_STATE_LAUNCHING:
+           case LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER:
+              _launcher_state_set(runner, LAUNCHER_STATE_CANCELED);
+              _launcher_stop_send(runner);
+              if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
+                _launcher_post_forward(runner, EINA_FALSE);
+              else if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
+                _launcher_post_backward(runner, EINA_FALSE);
+              break;
+           case LAUNCHER_STATE_MONITORING:
+              _launcher_state_set(runner, LAUNCHER_STATE_CANCELED);
+              _launcher_stop_send(runner);
+              runner->target.pid = -1;
+              break;
+           default:
+              break;
+          }
+        _launcher_handler_launcher_pre_runner_set(runner);
+     }
+
+   ELOGF("LAUNCHER_SRV", "runner change %p(ec:%p) to %p(ec:%p)",
+         NULL, runner, runner?runner->ec:NULL, lc, lc?lc->ec:NULL);
+
+   _laundler->runner = lc;
+}
+
+static void
+_launcher_handler_launcher_runner_unset(E_Service_Launcher *lc)
+{
+   EINA_SAFETY_ON_NULL_RETURN(_laundler);
+   if (_laundler->runner != lc) return;
+
+   _laundler->runner = NULL;
+
+   ELOGF("LAUNCHER_SRV", "runner unset %p(ec:%p)",
+         NULL, lc, lc?lc->ec:NULL);
+}
+
+static E_Service_Launcher *
+_launcher_handler_launcher_runner_get(void)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler, NULL);
+   return _laundler->runner;
+}
+
+static void
+_launcher_handler_launcher_pre_runner_set(E_Service_Launcher *lc)
+{
+   E_Service_Launcher *pre_runner = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN(_laundler);
+
+   pre_runner = _laundler->pre_runner;
+   if (pre_runner == lc) return;
+   if (pre_runner)
+     {
+        if (pre_runner->launched_ec)
+          e_policy_animatable_lock(pre_runner->launched_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
+        _launcher_state_set(pre_runner, LAUNCHER_STATE_IDLE);
+     }
+
+   _laundler->pre_runner = lc;
+
+   ELOGF("LAUNCHER_SRV", "pre_runner change %p(ec:%p) to %p(ec:%p)",
+         NULL, pre_runner, pre_runner?pre_runner->ec:NULL, lc, lc?lc->ec:NULL);
+}
+
+static void
+_launcher_handler_launcher_pre_runner_unset(E_Service_Launcher *lc)
+{
+   EINA_SAFETY_ON_NULL_RETURN(_laundler);
+   if (_laundler->pre_runner != lc) return;
+
+   _laundler->pre_runner = NULL;
+
+   ELOGF("LAUNCHER_SRV", "pre_runner unset %p(ec:%p)",
+         NULL, lc, lc?lc->ec:NULL);
+}
+
+static E_Service_Launcher *
+_launcher_handler_launcher_pre_runner_get(void)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler, NULL);
+   return _laundler->pre_runner;
+}
+
+static Eina_Bool
+_launcher_handler_cb_hook_vis_uniconify_render_running(void *data EINA_UNUSED, E_Client *ec)
+{
+   E_Service_Launcher *lc = NULL;
+   E_Service_Launcher *runner, *pre_runner = NULL;
    E_Client *activity = NULL;
 
-   lc = (E_Service_Launcher*)data;
+   lc = _launcher_handler_launcher_find(ec);
    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_TRUE);
 
    activity = e_policy_visibility_main_activity_get();
@@ -494,11 +965,29 @@ _e_srv_launcher_cb_hook_vis_uniconify_render_running(void *data EINA_UNUSED, E_C
              ELOGF("LAUNCHER_SRV", "Current activity(%p, is_del:%d) was launched by launcher.",
                    ec, activity, e_object_is_del(E_OBJECT(activity)));
 
-             sent = _e_srv_launcher_prepare_backward_send(lc, activity, activity,
+             //check state of lc
+             runner =  _launcher_handler_launcher_runner_get();
+             if (runner == lc)
+               {
+                  ELOGF("LAUNCHER_SRV",
+                        "Launcher(%s) is already runner, do nothing",
+                        lc->ec, _launcher_state_to_str(lc->state));
+                  return EINA_TRUE;
+               }
+
+             pre_runner = _launcher_handler_launcher_pre_runner_get();
+             if (pre_runner ==  lc)
+               {
+                  _launcher_handler_launcher_pre_runner_set(NULL);
+               }
+
+             sent = _launcher_prepare_backward_send(lc, activity, activity,
                                                           (E_VIS_JOB_TYPE_UNICONIFY |
                                                            E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY));
              if (!sent) return EINA_FALSE;
-             _e_srv_launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
+
+             _launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
+             _launcher_handler_launcher_runner_set(lc);
           }
      }
 
@@ -506,19 +995,18 @@ _e_srv_launcher_cb_hook_vis_uniconify_render_running(void *data EINA_UNUSED, E_C
 }
 
 static Eina_Bool
-_e_srv_launcher_cb_hook_vis_lower(void *data, E_Client *ec)
+_launcher_handler_cb_hook_vis_lower(void *data EINA_UNUSED, E_Client *ec)
 {
-   E_Service_Launcher *lc;
+   E_Service_Launcher *lc = NULL;
+   E_Service_Launcher *runner, *pre_runner;
    E_Client *activity = NULL;
 
-   lc = (E_Service_Launcher*)data;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
-
    activity = e_policy_visibility_main_activity_get();
    EINA_SAFETY_ON_NULL_RETURN_VAL(activity, EINA_FALSE);
 
-   if (activity != lc->ec) return EINA_FALSE;
+   lc = _launcher_handler_launcher_find(activity);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
+
    if (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED) return EINA_FALSE;
 
    if (ec == lc->launched_ec)
@@ -526,29 +1014,44 @@ _e_srv_launcher_cb_hook_vis_lower(void *data, E_Client *ec)
         Eina_Bool sent = EINA_FALSE;
         ELOGF("LAUNCHER_SRV", "Lower hook of launched_ec(%p)", lc->ec, ec);
 
-        sent = _e_srv_launcher_prepare_backward_send(lc, activity, ec, E_VIS_JOB_TYPE_LOWER);
+        //check state of lc
+        runner =  _launcher_handler_launcher_runner_get();
+        if (runner == lc)
+          {
+             ELOGF("LAUNCHER_SRV",
+                   "Launcher(%s) is already runner, do nothing",
+                   lc->ec, _launcher_state_to_str(lc->state));
+             return EINA_FALSE;
+          }
+
+        pre_runner = _launcher_handler_launcher_pre_runner_get();
+        if (pre_runner ==  lc)
+          {
+             _launcher_handler_launcher_pre_runner_set(NULL);
+          }
+
+        sent = _launcher_prepare_backward_send(lc, activity, ec, E_VIS_JOB_TYPE_LOWER);
         if (!sent) return EINA_FALSE;
 
-        _e_srv_launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
+        _launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
      }
 
    return EINA_TRUE;
 }
 
 static Eina_Bool
-_e_srv_launcher_cb_hook_vis_hide(void *data, E_Client *ec)
+_launcher_handler_cb_hook_vis_hide(void *data EINA_UNUSED, E_Client *ec)
 {
-   E_Service_Launcher *lc;
+   E_Service_Launcher *lc = NULL;
+   E_Service_Launcher *runner, *pre_runner;
    E_Client *activity = NULL;
 
-   lc = (E_Service_Launcher*)data;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
-
    activity = e_policy_visibility_main_activity_get();
    EINA_SAFETY_ON_NULL_RETURN_VAL(activity, EINA_FALSE);
 
-   if (activity != lc->ec) return EINA_FALSE;
+   lc = _launcher_handler_launcher_find(activity);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
+
    if (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED) return EINA_FALSE;
 
    if (ec == lc->launched_ec)
@@ -556,305 +1059,251 @@ _e_srv_launcher_cb_hook_vis_hide(void *data, E_Client *ec)
         Eina_Bool sent = EINA_FALSE;
         ELOGF("LAUNCHER_SRV", "Hide hook of launched_ec(%p)", lc->ec, ec);
 
-        sent = _e_srv_launcher_prepare_backward_send(lc, activity, ec, E_VIS_JOB_TYPE_HIDE);
+        //check state of lc
+        runner =  _launcher_handler_launcher_runner_get();
+        if (runner == lc)
+          {
+             ELOGF("LAUNCHER_SRV",
+                   "Launcher(%s) is already runner, do nothing",
+                   lc->ec, _launcher_state_to_str(lc->state));
+             return EINA_FALSE;
+          }
+
+        pre_runner = _launcher_handler_launcher_pre_runner_get();
+        if (pre_runner ==  lc)
+          {
+             _launcher_handler_launcher_pre_runner_set(NULL);
+          }
+
+        sent = _launcher_prepare_backward_send(lc, activity, ec, E_VIS_JOB_TYPE_HIDE);
         if (!sent) return EINA_FALSE;
 
-        _e_srv_launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
+        _launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
      }
 
    return EINA_TRUE;
 }
 
-
-static Eina_Bool
-_e_srv_launcher_cb_event_buff_attach(void *data, int type EINA_UNUSED, void *event)
+static void
+_launcher_handler_cb_hook_client_del(void *data EINA_UNUSED, E_Client *ec)
 {
    E_Service_Launcher *lc;
-   E_Client *ec;
-   E_Event_Client *ev;
 
-   lc = (E_Service_Launcher*)data;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(lc, ECORE_CALLBACK_PASS_ON);
+   EINA_SAFETY_ON_NULL_RETURN(ec);
 
-   ev = (E_Event_Client *)event;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
-   EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
+   lc = _launcher_handler_launcher_find(ec);
+   EINA_SAFETY_ON_NULL_RETURN(lc);
 
-   ec = ev->ec;
-   if (ec != lc->ec) return ECORE_CALLBACK_PASS_ON;
+   if (lc->ec == ec) //launcher surface is gone.
+     {
+        _launcher_handler_launcher_del(lc);
+        _launcher_data_reset(lc);
+        E_FREE(lc);
+     }
+}
 
-   ELOGF("LAUNCHER_SRV", "Event cb(BUFFER_CHANGE)", ec);
+static Eina_Bool
+_launcher_handler_cb_hook_intercept_show_helper(void *data, E_Client *ec)
+{
+   E_Service_Launcher *runner;
+   Eina_Bool sent = EINA_FALSE;
 
-   if (lc->state == LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER)
-     _e_srv_launcher_state_set(lc, LAUNCHER_STATE_LAUNCHING);
+   runner = _launcher_handler_launcher_runner_get();
 
-   if (lc->vis_grab)
-     {
-        e_policy_visibility_client_grab_release(lc->vis_grab);
-        lc->vis_grab = NULL;
-     }
+   EINA_SAFETY_ON_NULL_GOTO(runner, show_allow);
+   EINA_SAFETY_ON_NULL_GOTO(ec, show_allow);
 
-   if (lc->target.vis_grab)
+   if (ec->new_client) goto show_allow;
+
+   switch (runner->state)
      {
-        e_policy_visibility_client_grab_release(lc->target.vis_grab);
-        lc->target.vis_grab = NULL;
-     }
+      case LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER:  //waiting buffer change
+         if (ec == runner->ec)
+           goto show_deny;
+      case LAUNCHER_STATE_PREPARING:              //waiting launcher client's preparation
+         if (ec  == runner->target.ec) goto show_deny;
+         break;
+      case LAUNCHER_STATE_LAUNCHING:              //doing animation
+         if (ec == runner->target.ec) goto show_deny; //don't show launched app window
+         else if (ec == runner->ec) goto show_allow;  //show launcher
+         break;
+      case LAUNCHER_STATE_MONITORING:             //waiting creation of target window
+         if (ec->netwm.pid != runner->target.pid) goto show_allow;
+         if (e_object_is_del(E_OBJECT(ec))) goto show_allow;
 
-   E_FREE_FUNC(lc->buf_attach, ecore_event_handler_del);
+         sent = _launcher_prepare_forward_send(runner, ec);
+         EINA_SAFETY_ON_FALSE_GOTO(sent, send_stop);
 
-   return ECORE_CALLBACK_PASS_ON;
+         _launcher_state_set(runner, LAUNCHER_STATE_PREPARING);
+         goto show_deny;
+      default:
+         goto show_allow;
+     }
+
+show_allow:
+   return EINA_TRUE;
+show_deny:
+   return EINA_FALSE;
+send_stop:
+   runner->target.pid = -1;
+   _launcher_stop_send(runner);
+   _launcher_state_set(runner, LAUNCHER_STATE_IDLE);
+   _launcher_handler_launcher_runner_unset(runner);
+   return EINA_TRUE;
 }
 
 static Eina_Bool
-_e_srv_launcher_cb_event_client_show(void *data, int type EINA_UNUSED, void *event)
+_launcher_handler_cb_event_client_show(void *data, int type EINA_UNUSED, void *event)
 {
-   E_Service_Launcher *lc;
+   E_Service_Launcher *runner, *pre_runner;
    E_Client *ec;
    E_Event_Client *ev;
 
-   lc = (E_Service_Launcher*)data;
-   EINA_SAFETY_ON_NULL_RETURN_VAL(lc, ECORE_CALLBACK_PASS_ON);
-
-   if ((lc->state == LAUNCHER_STATE_IDLE) ||
-       (lc->state == LAUNCHER_STATE_MONITORING) ||
-       (lc->state == LAUNCHER_STATE_LAUNCHING) ||
-       (lc->state == LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER))
-     return ECORE_CALLBACK_PASS_ON;
+   runner = _launcher_handler_launcher_runner_get();
+   EINA_SAFETY_ON_NULL_RETURN_VAL(runner, ECORE_CALLBACK_PASS_ON);
 
    ev = (E_Event_Client *)event;
    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
    EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
 
    ec = ev->ec;
-   if ((ec != lc->launched_ec) && (ec != lc->ec)) return ECORE_CALLBACK_PASS_ON;
-
-   ELOGF("LAUNCHER_SRV", "Event cb(CLIENT_SHOW)", ec);
 
-   if (ec == lc->launched_ec)
-     e_policy_animatable_lock(ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
-
-   //failure case
-   if (lc->state == LAUNCHER_STATE_PREPARING)
+   switch (runner->state)
      {
-        _e_srv_launcher_stop_send(lc);
-        if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
-          _e_srv_launcher_post_backward(lc, EINA_FALSE);
+      case LAUNCHER_STATE_MONITORING:
+         if (ec->netwm.pid == runner->target.pid)
+           goto send_stop;
+         break;
+      case LAUNCHER_STATE_PREPARING:
+         if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
+           {
+              if (ec == runner->target.ec)  goto send_stop;
+           }
+         else if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
+           {
+              if (ec == runner->ec) goto send_stop;
+           }
+         break;
+      case LAUNCHER_STATE_LAUNCHING:
+         if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
+           {
+              if (ec == runner->target.ec) goto send_stop;
+           }
+         break;
+      default:
+         break;
      }
 
-   _e_srv_launcher_state_set(lc, LAUNCHER_STATE_IDLE);
-
-   return ECORE_CALLBACK_PASS_ON;
-}
-
-static void
-_e_srv_launcher_cb_hook_client_del(void *data, E_Client *ec)
-{
-   E_Service_Launcher *lc;
-
-   lc = (E_Service_Launcher*)data;
-   EINA_SAFETY_ON_NULL_RETURN(lc);
-   EINA_SAFETY_ON_NULL_RETURN(ec);
-
-   if (lc->launched_ec == ec)
-     lc->launched_ec = NULL;
-   else if (lc->ec == ec) //launcher surface is gone.
+   pre_runner = _launcher_handler_launcher_pre_runner_get();
+   if (pre_runner)
      {
-        if (_e_srv_launcher == lc)
-          _e_srv_launcher = NULL;
-
-        _e_srv_launcher_data_free(lc);
-     }
-   else if (lc->target.ec == ec) //target surface is gone.
-     {
-        switch (lc->state)
+        switch (pre_runner->state)
           {
-           case LAUNCHER_STATE_PREPARING:
-           case LAUNCHER_STATE_LAUNCHING:
-           case LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER:
-              _e_srv_launcher_stop_send(lc);
-              if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
-                _e_srv_launcher_post_forward(lc, EINA_FALSE);
-              else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
-                _e_srv_launcher_post_backward(lc, EINA_FALSE);
+           case LAUNCHER_STATE_DONE:
+              if (ec == pre_runner->launched_ec)
+                _launcher_handler_launcher_pre_runner_set(NULL);
+              break;
+           case LAUNCHER_STATE_CANCELED:
+              _launcher_handler_launcher_pre_runner_set(NULL);
               break;
            default:
               break;
           }
      }
-}
 
-static void
-_e_srv_launcher_cb_resource_destroy(struct wl_resource *res_tws_lc)
-{
-   E_Service_Launcher *lc;
-
-   lc = wl_resource_get_user_data(res_tws_lc);
-   if (!lc) return;
+   return ECORE_CALLBACK_PASS_ON;
 
-   ELOGF("LAUNCHER_SRV", "Start Resource Destroy tws_service_launcher", lc->ec);
+send_stop:
+   ELOGF("LAUNCHER_SRV", "CLIENT SHOW: Failure Case runner:%p", ec, runner);
 
-   if (_e_srv_launcher == lc)
-     _e_srv_launcher = NULL;
+   _launcher_stop_send(runner);
 
-   lc->res = NULL;
-   _e_srv_launcher_data_free(lc);
+   if (runner->state == LAUNCHER_STATE_MONITORING)
+     runner->target.pid = -1;
+   else if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
+     _launcher_post_forward(runner, EINA_FALSE);
+   else if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
+     _launcher_post_backward(runner, EINA_FALSE);
 
-   ELOGF("LAUNCHER_SRV", "End Resource Destroy tws_service_launcher", NULL);
-}
+   _launcher_state_set(runner, LAUNCHER_STATE_IDLE);
+   _launcher_handler_launcher_runner_unset(runner);
 
-static void
-_e_srv_launcher_cb_destroy(struct wl_client *client EINA_UNUSED,
-                           struct wl_resource *res_tws_lc)
-{
-   ELOGF("LAUNCHER_SRV", "Received request(launcher_destroy)", NULL);
-   wl_resource_destroy(res_tws_lc);
+   return ECORE_CALLBACK_PASS_ON;
 }
 
-static void
-_e_srv_launcher_cb_launch(struct wl_client *client EINA_UNUSED,
-                          struct wl_resource *res_tws_lc,
-                          const char *app_id,
-                          const char *instance_id,
-                          int32_t pid)
-{
-   E_Service_Launcher *lc;
-   E_Client *target_ec;
-   Eina_List *ecs, *l;
-   Eina_Bool sent = EINA_FALSE;
-
-   lc = wl_resource_get_user_data(res_tws_lc);
-   EINA_SAFETY_ON_NULL_RETURN(lc);
-   EINA_SAFETY_ON_NULL_RETURN(lc->ec);
-
-   ELOGF("LAUNCHER_SRV",
-         "Recieved request(launcher_launch) appid:%s instance id:%s pid:%d",
-         lc->ec, app_id?:"NONE", instance_id?:"NONE", pid);
-
-   EINA_SAFETY_ON_TRUE_GOTO(lc->ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED, send_stop);
-   EINA_SAFETY_ON_TRUE_GOTO(pid < 0, send_stop);
-
-   lc->target.pid = pid;
-
-   //if we received launch without idle state
-   if ((lc->state == LAUNCHER_STATE_DONE) ||
-       (lc->state == LAUNCHER_STATE_CANCELED))
-     {
-        if (lc->launched_ec)
-          {
-             e_policy_animatable_lock(lc->launched_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
-             lc->launched_ec = NULL;
-          }
-
-        _e_srv_launcher_state_set(lc, LAUNCHER_STATE_IDLE);
-     }
-
-   ecs = _e_srv_launcher_clients_find_by_pid(pid);
-   EINA_LIST_FOREACH(ecs, l, target_ec)
-     {
-        if (e_object_is_del(E_OBJECT(target_ec))) continue;
-        if (e_client_util_ignored_get(target_ec)) continue;
-
-        ELOGF("LAUNCHER_SRV", "Found target_ec:%p", lc->ec, target_ec);
-
-        sent = _e_srv_launcher_prepare_forward_send(lc, target_ec);
-        EINA_SAFETY_ON_FALSE_GOTO(sent, send_stop);
-
-        _e_srv_launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
-        break;
-     }
-   eina_list_free(ecs);
+#undef  LAUNCHER_HANDLER_CB_ADD
+#define LAUNCHER_HANDLER_CB_ADD(l, appender, event_type, cb, data)  \
+  do                                                                \
+    {                                                               \
+       void *_h;                                                    \
+       _h = appender(event_type, cb, data);                         \
+       assert(_h);                                                  \
+       l = eina_list_append(l, _h);                                 \
+    }                                                               \
+  while (0)
 
-   if (!lc->target.ec)
-     {
-        ELOGF("LAUNCHER_SRV", "Can't find target_ec, Start Monitoring", lc->ec);
-        _e_srv_launcher_state_set(lc, LAUNCHER_STATE_MONITORING);
-     }
 
-   return;
+static E_Service_Launcher_Handler *
+_launcher_handler_create(void)
+{
+   E_Service_Launcher_Handler *laundler = NULL;
 
-send_stop:
-   ELOGF("LAUNCHER_SRV", "can't process request(launcher_launch)", lc->ec);
-   _e_srv_launcher_stop_send(lc);
-}
+   laundler = E_NEW(E_Service_Launcher_Handler, 1);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(laundler, NULL);
 
-static void
-_e_srv_launcher_cb_launching(struct wl_client *client EINA_UNUSED,
-                             struct wl_resource *res_tws_lc,
-                             uint32_t serial)
-{
-   E_Service_Launcher *lc;
+   laundler->launcher_count = 0;
+   laundler->launcher_hash = eina_hash_pointer_new(NULL);
 
-   lc = wl_resource_get_user_data(res_tws_lc);
-   EINA_SAFETY_ON_NULL_RETURN(lc);
+   LAUNCHER_HANDLER_CB_ADD(laundler->hooks_vis,
+                           e_policy_visibility_hook_add,
+                           E_POL_VIS_HOOK_TYPE_UNICONIFY_RENDER_RUNNING,
+                           _launcher_handler_cb_hook_vis_uniconify_render_running, NULL);
 
-   ELOGF("LAUNCHER_SRV", "LAUNCHING(%d) %s",
-         lc->ec, serial, lc->direction?"backward":"forward");
+   LAUNCHER_HANDLER_CB_ADD(laundler->hooks_vis,
+                           e_policy_visibility_hook_add,
+                           E_POL_VIS_HOOK_TYPE_LOWER,
+                           _launcher_handler_cb_hook_vis_lower, NULL);
 
-   _e_srv_launcher_state_set(lc, LAUNCHER_STATE_LAUNCHING);
+   LAUNCHER_HANDLER_CB_ADD(laundler->hooks_vis,
+                           e_policy_visibility_hook_add,
+                           E_POL_VIS_HOOK_TYPE_HIDE,
+                           _launcher_handler_cb_hook_vis_hide, NULL);
 
-   if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
-     {
-        _e_srv_launcher_state_set(lc, LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER);
-        lc->buf_attach = ecore_event_handler_add(E_EVENT_CLIENT_BUFFER_CHANGE,
-                                                 _e_srv_launcher_cb_event_buff_attach, lc);
-     }
-}
+   LAUNCHER_HANDLER_CB_ADD(laundler->hooks_ec,
+                           e_client_hook_add,
+                           E_CLIENT_HOOK_DEL,
+                           _launcher_handler_cb_hook_client_del, NULL);
 
-static void
-_e_srv_launcher_cb_launch_done(struct wl_client *client EINA_UNUSED,
-                               struct wl_resource *res_tws_lc,
-                               uint32_t serial)
-{
-   E_Service_Launcher *lc;
+   LAUNCHER_HANDLER_CB_ADD(laundler->hooks_co,
+                           e_comp_object_intercept_hook_add,
+                           E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER,
+                           _launcher_handler_cb_hook_intercept_show_helper, NULL);
 
-   lc = wl_resource_get_user_data(res_tws_lc);
-   EINA_SAFETY_ON_NULL_RETURN(lc);
 
-   ELOGF("LAUNCHER_SRV", "LAUNCH_DONE(%d) target:%p", lc->ec, serial, lc->target.ec);
+   LAUNCHER_HANDLER_CB_ADD(laundler->hdlrs_ev,
+                           ecore_event_handler_add,
+                           E_EVENT_CLIENT_SHOW,
+                           _launcher_handler_cb_event_client_show, NULL);
 
-   if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
-     _e_srv_launcher_post_forward(lc, EINA_TRUE);
-   else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
-     _e_srv_launcher_post_backward(lc, EINA_TRUE);
+   ELOGF("LAUNCHER_SRV", "new launcher handler(%p) created", NULL, laundler);
 
-   if ((lc->state == LAUNCHER_STATE_LAUNCHING) ||
-       (lc->state == LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER))
-     _e_srv_launcher_state_set(lc, LAUNCHER_STATE_DONE);
+   return laundler;
 }
 
 static void
-_e_srv_launcher_cb_launch_cancel(struct wl_client *client EINA_UNUSED,
-                                 struct wl_resource *res_tws_lc,
-                                 uint32_t serial)
+_launcher_handler_destroy(E_Service_Launcher_Handler *laundler)
 {
-   E_Service_Launcher *lc;
-
-   lc = wl_resource_get_user_data(res_tws_lc);
-   EINA_SAFETY_ON_NULL_RETURN(lc);
+   EINA_SAFETY_ON_NULL_RETURN(laundler);
 
-   ELOGF("LAUNCHER_SRV", "LAUNCH_CANCEL(%d) target_ec:%p",
-         lc->ec, serial, lc->target.ec);
+   E_FREE_LIST(laundler->hdlrs_ev, ecore_event_handler_del);
+   E_FREE_LIST(laundler->hooks_co, e_comp_object_intercept_hook_del);
+   E_FREE_LIST(laundler->hooks_ec, e_client_hook_del);
+   E_FREE_LIST(laundler->hooks_vis, e_policy_visibility_hook_del);
 
-   if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
-     _e_srv_launcher_post_forward(lc, EINA_FALSE);
-   else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
-     _e_srv_launcher_post_backward(lc, EINA_FALSE);
-
-   if ((lc->state == LAUNCHER_STATE_PREPARING) ||
-       (lc->state == LAUNCHER_STATE_LAUNCHING) ||
-       (lc->state == LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER))
-     _e_srv_launcher_state_set(lc, LAUNCHER_STATE_CANCELED);
+   E_FREE_FUNC(laundler->launcher_hash, eina_hash_free);
+   E_FREE(laundler);
 }
 
-static const struct tws_service_launcher_interface _e_srv_launcher_iface =
-{
-   _e_srv_launcher_cb_destroy,
-   _e_srv_launcher_cb_launch,
-   _e_srv_launcher_cb_launching,
-   _e_srv_launcher_cb_launch_done,
-   _e_srv_launcher_cb_launch_cancel,
-};
-
 EINTERN void
 e_service_launcher_resource_set(E_Client *ec, struct wl_resource *res_tws_lc)
 {
@@ -863,26 +1312,15 @@ e_service_launcher_resource_set(E_Client *ec, struct wl_resource *res_tws_lc)
    EINA_SAFETY_ON_NULL_RETURN(ec);
    EINA_SAFETY_ON_NULL_RETURN(res_tws_lc);
 
-   lc = _e_srv_launcher;
+   lc = _launcher_handler_launcher_find(ec);
    EINA_SAFETY_ON_NULL_RETURN(lc);
    EINA_SAFETY_ON_TRUE_RETURN(lc->ec != ec);
 
    lc->res = res_tws_lc;
    wl_resource_set_implementation(res_tws_lc,
-                                  &_e_srv_launcher_iface, lc,
-                                  _e_srv_launcher_cb_resource_destroy);
-}
-
-#undef  LAUNCHER_CB_ADD
-#define LAUNCHER_CB_ADD(l, appender, event_type, cb, data)  \
-  do                                                        \
-    {                                                       \
-       void *_h;                                            \
-       _h = appender(event_type, cb, data);                 \
-       assert(_h);                                          \
-       l = eina_list_append(l, _h);                         \
-    }                                                       \
-  while (0)
+                                  &_launcher_iface, lc,
+                                  _launcher_cb_resource_destroy);
+}
 
 EINTERN void
 e_service_launcher_client_set(E_Client *ec)
@@ -892,32 +1330,32 @@ e_service_launcher_client_set(E_Client *ec)
    EINA_SAFETY_ON_NULL_RETURN(ec);
    EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(ec)));
 
-   if (_e_srv_launcher)
+   if ((lc = _launcher_handler_launcher_find(ec)))
      {
-        lc = _e_srv_launcher;
-        _e_srv_launcher_data_reset(lc);
+        ELOGF("LAUNCHER_SRV", "ec(%p) is already set as launcher(%p)",
+              ec, ec, lc);
+        return;
      }
 
-   if (!lc)
+   if (!_laundler)
      {
-
-        lc = E_NEW(E_Service_Launcher, 1);
-        EINA_SAFETY_ON_NULL_RETURN(lc);
-
-        /* hook, event handler add */
-        LAUNCHER_CB_ADD(lc->hooks_co,  e_comp_object_intercept_hook_add, E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER, _e_srv_launcher_cb_hook_intercept_show_helper, lc);
-        LAUNCHER_CB_ADD(lc->hooks_vis, e_policy_visibility_hook_add, E_POL_VIS_HOOK_TYPE_UNICONIFY_RENDER_RUNNING, _e_srv_launcher_cb_hook_vis_uniconify_render_running, lc);
-        LAUNCHER_CB_ADD(lc->hooks_vis, e_policy_visibility_hook_add, E_POL_VIS_HOOK_TYPE_LOWER, _e_srv_launcher_cb_hook_vis_lower, lc);
-        LAUNCHER_CB_ADD(lc->hooks_vis, e_policy_visibility_hook_add, E_POL_VIS_HOOK_TYPE_HIDE, _e_srv_launcher_cb_hook_vis_hide, lc);
-        LAUNCHER_CB_ADD(lc->hooks_ec,  e_client_hook_add, E_CLIENT_HOOK_DEL, _e_srv_launcher_cb_hook_client_del, lc);
-        LAUNCHER_CB_ADD(lc->handlers,  ecore_event_handler_add, E_EVENT_CLIENT_SHOW, _e_srv_launcher_cb_event_client_show, lc);
-
-        _e_srv_launcher = lc;
+        _laundler = _launcher_handler_create();
+        EINA_SAFETY_ON_NULL_RETURN(_laundler);
      }
 
+   lc = E_NEW(E_Service_Launcher, 1);
+   EINA_SAFETY_ON_NULL_RETURN(lc);
+
    lc->ec = ec;
+   if (!_launcher_handler_launcher_add(lc))
+     {
+        E_FREE(lc);
+        ELOGF("LAUNCHER_SRV", "Fail to add launcher", ec);
+        return;
+     }
 
    ELOGF("LAUNCHER_SRV", "client set|Created New Launcher(%p)", ec, lc);
+   _launcher_state_set(lc, LAUNCHER_STATE_IDLE);
 
    return;
 }
@@ -928,11 +1366,22 @@ e_service_launcher_client_unset(E_Client *ec)
    E_Service_Launcher *lc;
 
    EINA_SAFETY_ON_NULL_RETURN(ec);
-   EINA_SAFETY_ON_NULL_RETURN(_e_srv_launcher);
-   EINA_SAFETY_ON_TRUE_RETURN(_e_srv_launcher->ec != ec);
 
-   lc = _e_srv_launcher;
-   _e_srv_launcher_data_reset(lc);
+   lc = _launcher_handler_launcher_find(ec);
+   EINA_SAFETY_ON_NULL_RETURN(lc);
+
+   _launcher_handler_launcher_del(lc);
+   _launcher_data_reset(lc);
+   E_FREE(lc);
 
    ELOGF("LAUNCHER_SRV", "client unset", ec);
+
+   if ((_laundler) && (_laundler->launcher_count == 0))
+     {
+        ELOGF("LAUNCHER_SRV", "No launcher available, Destroy Launcher Handler(%p)",
+              NULL, _laundler);
+
+        _launcher_handler_destroy(_laundler);
+        _laundler = NULL;
+     }
 }