914049a211562ba0c137d52e6fce096464dafbe4
[platform/upstream/enlightenment.git] / src / bin / services / e_service_launcher.c
1 #include "services/e_service_launcher_intern.h"
2 #include "e_comp_wl_rsm_intern.h"
3 #include "e_comp_wl_tbm_intern.h"
4 #include "e_devicemgr_intern.h"
5 #include "e_policy_intern.h"
6 #include "e_policy_wl_intern.h"
7 #include "e_policy_private_data.h"
8 #include "e_policy_visibility_intern.h"
9 #include "e_client_intern.h"
10 #include "e_comp_object_intern.h"
11 #include "e_utils_intern.h"
12 #include "e_appinfo_intern.h"
13
14 #include <tzsh_server.h>
15 #include <wayland-tbm-server.h>
16
17 typedef struct _E_Service_Launcher          E_Service_Launcher;
18 typedef struct _E_Service_Launcher_Handler  E_Service_Launcher_Handler;
19 typedef struct _E_Service_Launcher_Consumer E_Service_Launcher_Consumer;
20
21 typedef enum
22 {
23    LAUNCHER_STATE_IDLE,
24    LAUNCHER_STATE_MONITORING,
25    LAUNCHER_STATE_PREPARING,
26    LAUNCHER_STATE_LAUNCHING,
27    LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER,
28    LAUNCHER_STATE_DONE,
29    LAUNCHER_STATE_CANCELED,
30    LAUNCHER_STATE_WAIT_RESPONSE_FROM_CALLEE,
31 } Launcher_State;
32
33 struct _E_Service_Launcher_Consumer
34 {
35    E_Service_Launcher                  *lc;
36    E_Vis_Grab                          *vis_grab;       //grab of client's visibility
37
38    E_Client                            *ec;
39    E_Object_Delfn                      *delfn;          //del callback of E_Client
40
41    Ecore_Event_Handler                 *buff_attach;    //event handler for BUFFER_CHANGE
42    int                                  buff_attach_count;
43 };
44
45 struct _E_Service_Launcher
46 {
47    Launcher_State                       state;          //current state of launcher
48
49    struct wl_resource                  *res;            //tizen_window_transition_launcher resource
50    E_Client                            *ec;             //launcher E_Client
51
52    E_Vis_Grab                          *vis_grab;       //grab of launcher visibility
53    uint32_t                             serial;         //identifier
54    enum tws_service_launcher_direction  direction;      //direction of transition
55
56    struct
57      {
58         E_Client                       *ec;             //target E_Client
59         pid_t                           pid;            //pid
60         const char                     *appid;          //appid
61         E_Vis_Grab                     *vis_grab;       //grab of target client's visibility
62
63         Eina_Bool                       delay_del;      //refered delay_del
64         E_Object_Delfn                 *delfn;          //del callback of target E_Client
65
66         const char                     *splash_path;    //path of file for splash
67         const char                     *splash_group;   //group name for splash
68      } target; //target window information for transition
69
70    E_Client                            *launched_ec;    //E_Client was launched by launcher
71    E_Object_Delfn                      *launched_delfn;  //del callback of launched_ec
72
73    Ecore_Event_Handler                 *buff_attach;    //event handler for BUFFER_CHANGE
74
75    Eina_Bool                            with_swl;       //it's for shared widget launch
76    Eina_Bool                            swl_done;       //flag indicating done of callee
77
78    Eina_Bool                            block_input;    //input is blocked(1) or not(0) while running client side animation
79
80    Eina_List                           *consumers;      //list launcher consumer of launcher ec
81 };
82
83 struct _E_Service_Launcher_Handler
84 {
85    Eina_Hash           *launcher_hash;  //hash key:launcher_ec, data:E_Service_Launcher
86    unsigned int         launcher_count; //count of launcher object
87
88    Eina_List           *hooks_ec;       //hook list for E_CLIENT_HOOK_*
89    Eina_List           *hooks_vis;      //hook list for E_POL_VIS_HOOK_TYPE_*
90    Eina_List           *hooks_co;       //hook list for E_COMP_OBJECT_INTERCEPT_HOOK_*
91    Eina_List           *hooks_appinfo;  //hook list for E_APPINFO_HOOK_*
92    Eina_List           *hdlrs_ev;       //handler list for ecore event
93
94    E_Service_Launcher  *runner;         //current runner(running launcher)
95    E_Service_Launcher  *pre_runner;     //previous runner
96 };
97
98 ////////////////////////////////////////////////////////////////////
99 static E_Service_Launcher_Handler *_laundler = NULL;
100
101 static void                _launcher_launched_ec_set(E_Service_Launcher *lc, E_Client *launched_ec);
102 static void                _launcher_target_ec_set(E_Service_Launcher *lc, E_Client *target_ec);
103
104 static E_Service_Launcher *_launcher_handler_launcher_find(E_Client *ec);
105 static Eina_Bool           _launcher_handler_launcher_add(E_Service_Launcher *lc);
106 static Eina_Bool           _launcher_handler_launcher_del(E_Service_Launcher *lc);
107
108 static E_Service_Launcher *_launcher_handler_launcher_runner_get(void);
109 static void                _launcher_handler_launcher_runner_set(E_Service_Launcher *lc);
110 static void                _launcher_handler_launcher_runner_unset(E_Service_Launcher *lc);
111 static E_Service_Launcher *_launcher_handler_launcher_pre_runner_get(void);
112 static void                _launcher_handler_launcher_pre_runner_set(E_Service_Launcher *lc);
113 static void                _launcher_handler_launcher_pre_runner_unset(E_Service_Launcher *lc);
114
115 ////////////////////////////////////////////////////////////////////
116 static Eina_List *
117 _launcher_clients_find_by_pid(pid_t pid)
118 {
119    E_Client *ec;
120    Eina_List *clients = NULL, *l;
121
122    EINA_LIST_FOREACH(e_comp->clients, l, ec)
123      {
124         if (e_object_is_del(E_OBJECT(ec))) continue;
125         if (ec->netwm.pid != pid) continue;
126         clients = eina_list_append(clients, ec);
127      }
128
129    return clients;
130 }
131
132
133 static void
134 _launcher_cb_input_block_expired(void *data)
135 {
136    E_Service_Launcher *lc = (E_Service_Launcher*)data;
137    EINA_SAFETY_ON_NULL_RETURN(lc);
138
139    lc->block_input = EINA_FALSE;
140
141    ELOGF("LAUNCHER_SRV", "Input block EXPIRED", lc->ec);
142 }
143
144 static Eina_Bool
145 _launcher_input_block_set(E_Service_Launcher *lc, Eina_Bool set)
146 {
147    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
148
149    if (set)
150      {
151         //request for block all input
152         lc->block_input = e_devicemgr_block_internal_add(ECORE_DEVICE_CLASS_NONE,
153                                                          EINA_TRUE,
154                                                          (uint32_t)(e_policy_visibility_timeout_get() * 1000),
155                                                          _launcher_cb_input_block_expired, lc);
156         return lc->block_input;
157      }
158    else
159      {
160         return e_devicemgr_block_internal_remove(_launcher_cb_input_block_expired, lc);
161      }
162 }
163
164 static const char*
165 _launcher_state_to_str(Launcher_State state)
166 {
167    switch (state)
168      {
169       case LAUNCHER_STATE_IDLE:
170          return "IDLE";
171       case LAUNCHER_STATE_MONITORING:
172          return "PID_MONITORING";
173       case LAUNCHER_STATE_PREPARING:
174          return "PREPARING";
175       case LAUNCHER_STATE_LAUNCHING:
176          return "LAUNCHING";
177       case LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER:
178          return "LAUNCHING_BUT_WAITING_BUFFER";
179       case LAUNCHER_STATE_DONE:
180          return "LAUNCH_DONE";
181       case LAUNCHER_STATE_CANCELED:
182          return "LAUNCH_CANCELED";
183       case LAUNCHER_STATE_WAIT_RESPONSE_FROM_CALLEE:
184          return "WAIT_FOR_RESPONSE_FROM_CALLEE";
185      }
186    return "UNKNOWN";
187 }
188
189 static void
190 _launcher_state_set(E_Service_Launcher *lc,
191                     Launcher_State state)
192 {
193    EINA_SAFETY_ON_NULL_RETURN(lc);
194
195    if (state == lc->state) return;
196
197    ELOGF("LAUNCHER_SRV", "Set state  %s --> %s",
198          lc->ec,
199          _launcher_state_to_str(lc->state),
200          _launcher_state_to_str(state));
201
202    lc->state = state;
203 }
204
205 static void
206 _launcher_consumer_del(E_Service_Launcher_Consumer *consumer)
207 {
208    E_Service_Launcher *lc;
209
210    EINA_SAFETY_ON_NULL_RETURN(consumer);
211
212    lc = consumer->lc;
213
214    ELOGF("LAUNCHER_SRV", "Del launcher_consumer ec:%p", lc ? lc->ec : NULL, consumer->ec);
215
216    if (consumer->ec)
217      {
218         e_object_delfn_del(E_OBJECT(consumer->ec), consumer->delfn);
219         consumer->ec = NULL;
220         consumer->delfn = NULL;
221      }
222
223    if (consumer->vis_grab)
224      {
225         e_policy_visibility_client_grab_release(consumer->vis_grab);
226         consumer->vis_grab = NULL;
227      }
228
229    if (consumer->buff_attach)
230      E_FREE_FUNC(consumer->buff_attach, ecore_event_handler_del);
231
232    if (lc)
233      lc->consumers = eina_list_remove(lc->consumers, consumer);
234
235    free(consumer);
236 }
237
238 static void
239 _launcher_cb_consumer_ec_del(void *data, void *obj)
240 {
241    E_Service_Launcher_Consumer *consumer;
242    E_Client *ec;
243
244    ec = (E_Client *)obj;
245    EINA_SAFETY_ON_NULL_RETURN(ec);
246
247    consumer= (E_Service_Launcher_Consumer *)data;
248    EINA_SAFETY_ON_NULL_RETURN(consumer);
249    EINA_SAFETY_ON_TRUE_RETURN(consumer->ec != ec);
250
251    consumer->ec = NULL;
252    consumer->delfn = NULL;
253
254    _launcher_consumer_del(consumer);
255 }
256
257 static E_Service_Launcher_Consumer *
258 _launcher_consumer_create(E_Service_Launcher *lc, E_Client *ec)
259 {
260    E_Service_Launcher_Consumer *consumer;
261
262    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, NULL);
263    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
264
265    consumer = E_NEW(E_Service_Launcher_Consumer, 1);
266    EINA_SAFETY_ON_NULL_RETURN_VAL(consumer, NULL);
267
268    consumer->ec = ec;
269    consumer->delfn = e_object_delfn_add(E_OBJECT(ec),
270                                         _launcher_cb_consumer_ec_del, consumer);
271
272    consumer->lc = lc;
273    lc->consumers = eina_list_append(lc->consumers, consumer);
274
275    ELOGF("LAUNCHER_SRV", "Create launcher_consumer ec:%p", lc->ec, ec);
276
277    return consumer;
278 }
279
280 static void
281 _launcher_consumers_reset(E_Service_Launcher *lc)
282 {
283    E_Service_Launcher_Consumer *consumer;
284    Eina_List *l, *ll;
285
286    EINA_SAFETY_ON_NULL_RETURN(lc);
287
288    EINA_LIST_FOREACH_SAFE(lc->consumers, l, ll, consumer)
289      _launcher_consumer_del(consumer);
290 }
291
292 static void
293 _launcher_post_forward(E_Service_Launcher *lc, Eina_Bool success)
294 {
295    E_Client *target_ec = NULL;
296
297    if ((lc->target.ec) && (!e_object_is_del(E_OBJECT(lc->target.ec))))
298      target_ec = lc->target.ec;
299
300    _launcher_target_ec_set(lc, NULL);
301
302    lc->serial = 0;
303    lc->target.pid = -1;
304
305    E_FREE_FUNC(lc->target.appid, eina_stringshare_del);
306    E_FREE_FUNC(lc->target.splash_path, eina_stringshare_del);
307    E_FREE_FUNC(lc->target.splash_group, eina_stringshare_del);
308    E_FREE_FUNC(lc->buff_attach, ecore_event_handler_del);
309
310    //if forward animation is failed, enlightenment can run animation instead.
311    if ((!success) && (target_ec))
312      e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
313
314    if (!_launcher_input_block_set(lc, EINA_FALSE))
315      ELOGF("LAUNCHER_SRV", "Input block remove FAIL...", lc->ec);
316
317    if (lc->vis_grab)
318      e_policy_visibility_client_grab_release(lc->vis_grab);
319    if (lc->target.vis_grab)
320      e_policy_visibility_client_grab_release(lc->target.vis_grab);
321
322    lc->vis_grab = NULL;
323    lc->target.vis_grab = NULL;
324
325    if (!target_ec) return;
326
327    if (success)
328      _launcher_launched_ec_set(lc, target_ec);
329
330    //show target_ec
331    e_comp_object_damage(target_ec->frame, 0, 0, target_ec->w, target_ec->h);
332    e_comp_object_dirty(target_ec->frame);
333    e_comp_object_render(target_ec->frame);
334    evas_object_show(target_ec->frame);
335
336    e_comp_client_override_del(target_ec);
337 }
338
339 static void
340 _launcher_post_backward(E_Service_Launcher *lc, Eina_Bool success)
341 {
342    E_Client *target_ec = NULL;
343
344    target_ec = lc->target.ec;
345    _launcher_target_ec_set(lc, NULL);
346
347    lc->serial = 0;
348    lc->target.pid = -1;
349    lc->direction = 0;
350
351    E_FREE_FUNC(lc->target.appid, eina_stringshare_del);
352    E_FREE_FUNC(lc->target.splash_path, eina_stringshare_del);
353    E_FREE_FUNC(lc->target.splash_group, eina_stringshare_del);
354    E_FREE_FUNC(lc->buff_attach, ecore_event_handler_del);
355
356    if (target_ec)
357      {
358         Eina_Bool is_del;
359         is_del = e_object_is_del(E_OBJECT(target_ec));
360         if (lc->target.delay_del)
361           e_object_delay_del_unref(E_OBJECT(target_ec));
362
363         if (is_del)
364           target_ec = NULL;
365      }
366    lc->target.delay_del = EINA_FALSE;
367
368    //if forward animation is failed, enlightenment can run animation instead.
369    if ((!success) && (target_ec))
370      e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
371
372    if (!_launcher_input_block_set(lc, EINA_FALSE))
373      ELOGF("LAUNCHER_SRV", "Input block remove FAIL...", lc->ec);
374
375    if (lc->vis_grab)
376      e_policy_visibility_client_grab_release(lc->vis_grab);
377    if (lc->target.vis_grab)
378      e_policy_visibility_client_grab_release(lc->target.vis_grab);
379
380    lc->vis_grab = NULL;
381    lc->target.vis_grab = NULL;
382
383    _launcher_consumers_reset(lc);
384
385    if (!target_ec) return;
386
387    if (success)
388      e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
389
390    e_comp_client_override_del(target_ec);
391 }
392
393 static void
394 _launcher_stop_send(E_Service_Launcher *lc)
395 {
396    EINA_SAFETY_ON_NULL_RETURN(lc);
397
398    ELOGF("LAUNCHER_SRV", "Send STOP event(%d) target(ec:%p)",
399          lc->ec, lc->serial, lc->target.ec);
400
401    tws_service_launcher_send_stop(lc->res, lc->serial);
402 }
403
404 static Eina_Bool
405 _launcher_prepare_send(E_Service_Launcher *lc,
406                        E_Client *target_ec,
407                        int x, int y,
408                        const char *shared_widget_info)
409 {
410    uint32_t res_id = 0;
411
412    E_Comp_Object_Content_Type content_type = 0;
413    enum tws_service_launcher_target_type target_type = 0;
414    const char *target_path = NULL, *target_group = NULL;
415    Evas_Object *content = NULL;
416    struct wl_array info_array;
417
418    int len;
419    char *p_char;
420    uint32_t *p_u32;
421
422    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
423    EINA_SAFETY_ON_NULL_RETURN_VAL(target_ec, EINA_FALSE);
424
425    wl_array_init(&info_array);
426    if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
427      {
428         content_type = e_comp_object_content_type_get(target_ec->frame);
429         switch (content_type)
430           {
431            case E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE:
432               content = e_comp_object_content_get(target_ec->frame);
433               EINA_SAFETY_ON_NULL_GOTO(content, fail);
434
435               target_type = TWS_SERVICE_LAUNCHER_TARGET_TYPE_IMAGE;
436               evas_object_image_file_get(content, &target_path, NULL);
437               EINA_SAFETY_ON_NULL_GOTO(target_path, fail);
438
439               len = strlen(target_path) + 1;
440               p_char = wl_array_add(&info_array, len);
441               EINA_SAFETY_ON_NULL_GOTO(p_char, fail);
442
443               strncpy(p_char, target_path, len);
444               break;
445            case E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE:
446               content = e_comp_object_content_get(target_ec->frame);
447               EINA_SAFETY_ON_NULL_GOTO(content, fail);
448
449               target_type = TWS_SERVICE_LAUNCHER_TARGET_TYPE_EDJE;
450               target_path = lc->target.splash_path;
451               target_group = lc->target.splash_group;
452               if ((!target_path) || (!target_group))
453                 edje_object_file_get(content, &target_path, &target_group);
454               EINA_SAFETY_ON_NULL_GOTO(target_path, fail);
455               EINA_SAFETY_ON_NULL_GOTO(target_group, fail);
456
457               len = strlen(target_path) + 1;
458               p_char = wl_array_add(&info_array, len);
459               EINA_SAFETY_ON_NULL_GOTO(p_char, fail);
460
461               strncpy(p_char, target_path, len);
462
463               len = strlen(target_group) + 1;
464               p_char = wl_array_add(&info_array, len);
465               EINA_SAFETY_ON_NULL_GOTO(p_char, fail);
466
467               strncpy(p_char, target_group, len);
468
469               break;
470            default:
471               target_type = TWS_SERVICE_LAUNCHER_TARGET_TYPE_REMOTE_SURFACE;
472               res_id = e_pixmap_res_id_get(target_ec->pixmap);
473
474               p_u32 = wl_array_add(&info_array, sizeof(uint32_t));
475               EINA_SAFETY_ON_NULL_GOTO(p_u32, fail);
476
477               *p_u32 = res_id;
478           }
479      }
480    else
481      {
482         target_type = TWS_SERVICE_LAUNCHER_TARGET_TYPE_REMOTE_SURFACE;
483         res_id = e_pixmap_res_id_get(target_ec->pixmap);
484
485         p_u32 = wl_array_add(&info_array, sizeof(uint32_t));
486         EINA_SAFETY_ON_NULL_GOTO(p_u32, fail);
487
488         *p_u32 = res_id;
489      }
490
491
492    ELOGF("LAUNCHER_SRV", "Send PREPARE event(%d) direction:%s target(ec:%p type:%d res:%d path:%s pos(%d,%d) widget:%s)",
493          lc->ec, lc->serial, lc->direction?"BACKWARD":"FORWARD", target_ec, target_type, res_id, target_path?:"N/A", x, y, shared_widget_info);
494
495    tws_service_launcher_send_prepare(lc->res,
496                                      target_type,
497                                      &info_array,
498                                      lc->direction,
499                                      x, y,
500                                      shared_widget_info ? shared_widget_info : "None",
501                                      lc->serial);
502
503    wl_array_release(&info_array);
504    return EINA_TRUE;
505 fail:
506    wl_array_release(&info_array);
507    return EINA_FALSE;
508 }
509
510 static Eina_Bool
511 _launcher_prepare_shared_widget_forward_send(E_Service_Launcher *lc,
512                                              E_Client *target_ec)
513 {
514    Eina_Bool sent = EINA_FALSE;
515
516    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
517    EINA_SAFETY_ON_NULL_RETURN_VAL(target_ec, EINA_FALSE);
518    if(e_object_is_del(E_OBJECT(target_ec))) return EINA_FALSE;
519
520    e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 1);
521    e_comp_client_override_add(target_ec);
522
523    // grab uniconify job of target_ec
524    if (target_ec->iconic)
525      {
526         lc->target.vis_grab =
527           e_policy_visibility_client_filtered_grab_get
528             (target_ec,
529              (E_VIS_JOB_TYPE_UNICONIFY | E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY),
530              __func__);
531      }
532
533    if (!_launcher_input_block_set(lc, EINA_TRUE))
534      ELOGF("LAUNCHER_SRV", "Input block add FAIL...", lc->ec);
535
536    _launcher_launched_ec_set(lc, NULL);
537    _launcher_target_ec_set(lc, target_ec);
538
539    lc->direction = TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD;
540
541    sent = e_tzsh_shared_widget_launch_prepare_send(target_ec,
542                                                    TWS_SHARED_WIDGET_LAUNCH_PREPARE_STATE_WIDGET_HIDE,
543                                                    lc->serial);
544    if (!sent)
545      {
546         ELOGF("LAUNCHER_SRV", "Failed to send event(PREPARE:FORWARD)", lc->ec);
547         _launcher_post_forward(lc, EINA_FALSE);
548      }
549
550    return sent;
551 }
552
553 static Eina_Bool
554 _launcher_prepare_shared_widget_backward_send(E_Service_Launcher *lc,
555                                               E_Client *activity,
556                                               E_Client *target_ec,
557                                               E_Vis_Job_Type job_type)
558 {
559    Eina_Bool sent = EINA_FALSE;
560
561    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
562    EINA_SAFETY_ON_NULL_RETURN_VAL(activity, EINA_FALSE);
563    EINA_SAFETY_ON_NULL_RETURN_VAL(target_ec, EINA_FALSE);
564
565    if (e_object_is_del(E_OBJECT(target_ec)))
566      {
567         if (lc->with_swl) return EINA_FALSE;
568         // do nothing if ec is deleted and there's no delay_del_ref as well.
569         if (!e_object_delay_del_ref_get(E_OBJECT(target_ec)))
570           return EINA_FALSE;
571      }
572
573    e_object_delay_del_ref(E_OBJECT(target_ec));
574    lc->target.delay_del = EINA_TRUE;
575
576    e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 1);
577    e_comp_client_override_add(target_ec);
578
579    if (activity == target_ec)
580      {
581         lc->vis_grab = e_policy_visibility_client_filtered_grab_get(lc->ec, job_type, __func__);
582         lc->target.vis_grab = e_policy_visibility_client_filtered_grab_get(target_ec, E_VIS_JOB_TYPE_ALL, __func__);
583      }
584    else
585      {
586         lc->target.vis_grab = e_policy_visibility_client_filtered_grab_get(target_ec, job_type, __func__);
587      }
588
589    if (!_launcher_input_block_set(lc, EINA_TRUE))
590      ELOGF("LAUNCHER_SRV", "Input block add FAIL...", lc->ec);
591
592    _launcher_launched_ec_set(lc, NULL);
593    _launcher_target_ec_set(lc, target_ec);
594
595    lc->direction = TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD;
596    lc->serial = wl_display_next_serial(e_comp_wl->wl.disp);
597
598    sent = e_tzsh_shared_widget_launch_prepare_send(target_ec,
599                                                    TWS_SHARED_WIDGET_LAUNCH_PREPARE_STATE_WIDGET_HIDE,
600                                                    lc->serial);
601
602    // fail to send protocol event
603    if (!sent)
604      {
605         ELOGF("LAUNCHER_SRV", "Failed to send event(PREPARE:BACKWARD)", lc->ec);
606         _launcher_post_backward(lc, EINA_FALSE);
607      }
608
609    return sent;
610 }
611
612 static Eina_Bool
613 _launcher_prepare_forward_send(E_Service_Launcher *lc,
614                                E_Client *target_ec)
615 {
616    Eina_Bool sent = EINA_FALSE;
617    int x, y;
618
619    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
620    EINA_SAFETY_ON_NULL_RETURN_VAL(target_ec, EINA_FALSE);
621
622    if(e_object_is_del(E_OBJECT(target_ec))) return EINA_FALSE;
623
624    e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 1);
625    e_comp_client_override_add(target_ec);
626
627    //grab uniconify job of target_ec
628    if (target_ec->iconic)
629      lc->target.vis_grab = e_policy_visibility_client_filtered_grab_get(target_ec,
630                                                                         (E_VIS_JOB_TYPE_UNICONIFY |
631                                                                          E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY),
632                                                                         __func__);
633
634    if (!_launcher_input_block_set(lc, EINA_TRUE))
635      ELOGF("LAUNCHER_SRV", "Input block add FAIL...", lc->ec);
636
637    _launcher_launched_ec_set(lc, NULL);
638    _launcher_target_ec_set(lc, target_ec);
639
640    lc->direction = TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD;
641    e_client_pos_get(target_ec, &x, &y);
642
643    sent = _launcher_prepare_send(lc, target_ec, x, y, NULL);
644
645    //fail to send protocol event
646    if (!sent)
647      {
648         ELOGF("LAUNCHER_SRV", "Failed to send event(PREPARE:FORWARD)", lc->ec);
649         _launcher_post_forward(lc, EINA_FALSE);
650      }
651
652    return sent;
653 }
654
655 static Eina_Bool
656 _launcher_prepare_backward_send(E_Service_Launcher *lc,
657                                 E_Client *activity,
658                                 E_Client *target_ec,
659                                 E_Vis_Job_Type job_type)
660 {
661    int x, y;
662    Eina_Bool sent = EINA_FALSE;
663    Eina_List *consumers;
664    Eina_List *l;
665    E_Client *ec;
666    E_Service_Launcher_Consumer *consumer;
667
668    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
669    EINA_SAFETY_ON_NULL_RETURN_VAL(activity, EINA_FALSE);
670    EINA_SAFETY_ON_NULL_RETURN_VAL(target_ec, EINA_FALSE);
671
672    if (e_object_is_del(E_OBJECT(target_ec)))
673      {
674         //can't do nothing if ec is deleted and there's no delay_del_ref as well.
675         if (!e_object_delay_del_ref_get(E_OBJECT(target_ec)))
676           return EINA_FALSE;
677      }
678
679    e_object_delay_del_ref(E_OBJECT(target_ec));
680    lc->target.delay_del = EINA_TRUE;
681
682    e_policy_animatable_lock(target_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 1);
683    e_comp_client_override_add(target_ec);
684
685    if ((lc->ec) && (lc->ec->remote_surface.provider))
686      {
687         consumers = e_comp_wl_remote_surface_consumers_get(lc->ec);
688         EINA_LIST_FOREACH(consumers, l, ec)
689           {
690              if (e_object_is_del(E_OBJECT(ec))) continue;
691              if (!e_policy_visibility_client_is_uniconify_render_running(ec)) continue;
692
693              consumer = _launcher_consumer_create(lc, ec);
694              consumer->vis_grab = e_policy_visibility_client_filtered_grab_get(ec,
695                                                                                (E_VIS_JOB_TYPE_UNICONIFY |
696                                                                                 E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY),
697                                                                                 __func__);
698           }
699         eina_list_free(consumers);
700      }
701
702    if (activity == target_ec)
703      {
704         lc->vis_grab = e_policy_visibility_client_filtered_grab_get(lc->ec, job_type, __func__);
705         lc->target.vis_grab = e_policy_visibility_client_filtered_grab_get(target_ec, E_VIS_JOB_TYPE_ALL, __func__);
706      }
707    else
708      {
709         lc->target.vis_grab = e_policy_visibility_client_filtered_grab_get(target_ec, job_type, __func__);
710      }
711
712    if (!_launcher_input_block_set(lc, EINA_TRUE))
713      ELOGF("LAUNCHER_SRV", "Input block add FAIL...", lc->ec);
714
715    _launcher_launched_ec_set(lc, NULL);
716    _launcher_target_ec_set(lc, target_ec);
717
718    lc->serial = wl_display_next_serial(e_comp_wl->wl.disp);
719    lc->direction = TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD;
720    e_client_pos_get(target_ec, &x, &y);
721
722    sent = _launcher_prepare_send(lc, target_ec, x, y, NULL);
723
724    //fail to send protocol event
725    if (!sent)
726      {
727         ELOGF("LAUNCHER_SRV", "Failed to send event(PREPARE:BACKWARD)", lc->ec);
728         _launcher_post_backward(lc, EINA_FALSE);
729      }
730
731    return sent;
732 }
733
734 /* Reset lc data */
735 static void
736 _launcher_data_reset(E_Service_Launcher *lc)
737 {
738    EINA_SAFETY_ON_NULL_RETURN(lc);
739
740    ELOGF("LAUNCHER_SRV", "Reset Launcher Data", lc->ec);
741
742    //clear resource and send 'DISQUALIFIED' msg
743    if (lc->res)
744      {
745         tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_DISQUALIFIED, lc->serial);
746         wl_resource_set_user_data(lc->res, NULL);
747         lc->res = NULL;
748      }
749
750    if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
751      _launcher_post_forward(lc, EINA_FALSE);
752    else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
753      _launcher_post_backward(lc, EINA_FALSE);
754
755    _launcher_state_set(lc, LAUNCHER_STATE_IDLE);
756    _launcher_launched_ec_set(lc, NULL);
757    _launcher_consumers_reset(lc);
758
759    _launcher_handler_launcher_runner_unset(lc);
760    _launcher_handler_launcher_pre_runner_unset(lc);
761
762    lc->direction = 0;
763    lc->with_swl = 0;
764 }
765
766 static Eina_Bool
767 _launcher_cb_done_buff_attach(void *data, int type EINA_UNUSED, void *event)
768 {
769    E_Service_Launcher *lc;
770    E_Client *ec;
771    E_Event_Client *ev;
772
773    lc = (E_Service_Launcher*)data;
774    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, ECORE_CALLBACK_PASS_ON);
775    if (!lc->with_swl) goto clean;
776    if (lc->direction != TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD) goto clean;
777
778    ev = (E_Event_Client *)event;
779    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
780    EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
781
782    ec = ev->ec;
783    if (ec != lc->target.ec) return ECORE_CALLBACK_PASS_ON;
784    if (!lc->swl_done) goto clean;
785
786    ELOGF("LAUNCHER_SRV", "Event cb(BUFFER_CHANGE) for LAUNCH_DONE", ec);
787
788    lc->swl_done = EINA_FALSE;
789
790    _launcher_post_forward(lc, EINA_TRUE);
791
792    _launcher_handler_launcher_runner_unset(lc);
793    _launcher_handler_launcher_pre_runner_set(lc);
794    _launcher_state_set(lc, LAUNCHER_STATE_DONE);
795
796 clean:
797    E_FREE_FUNC(lc->buff_attach, ecore_event_handler_del);
798
799    return ECORE_CALLBACK_DONE;
800 }
801
802 static Eina_Bool
803 _launcher_cb_launching_consumer_buff_attach(void *data, int type EINA_UNUSED, void *event)
804 {
805    E_Service_Launcher *lc;
806    E_Service_Launcher_Consumer *consumer;
807    E_Client *ec;
808    E_Event_Client *ev;
809
810    consumer = (E_Service_Launcher_Consumer*)data;
811    EINA_SAFETY_ON_NULL_RETURN_VAL(consumer, ECORE_CALLBACK_PASS_ON);
812    lc = consumer->lc;
813    EINA_SAFETY_ON_NULL_GOTO(lc, clean);
814    EINA_SAFETY_ON_FALSE_GOTO(lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD, clean);
815
816    ev = (E_Event_Client *)event;
817    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
818    EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
819
820    ec = ev->ec;
821    if (ec != consumer->ec) return ECORE_CALLBACK_PASS_ON;
822
823    ELOGF("LAUNCHER_SRV", "Event cb(BUFFER_CHANGE) for WAIT_CONSUMER_LAUNCHING count:%d",
824           ec, consumer->buff_attach_count);
825
826    consumer->buff_attach_count++;
827    if (consumer->buff_attach_count < 2) return ECORE_CALLBACK_PASS_ON;
828
829    if (consumer->vis_grab)
830      {
831         e_policy_visibility_client_grab_release(consumer->vis_grab);
832         consumer->vis_grab = NULL;
833      }
834
835 clean:
836    _launcher_consumer_del(consumer);
837
838    return ECORE_CALLBACK_PASS_ON;
839 }
840
841 static void
842 _launcher_consumers_buffer_change_wait(E_Service_Launcher *lc)
843 {
844    E_Service_Launcher_Consumer *consumer;
845    Eina_List *l;
846
847    EINA_LIST_FOREACH(lc->consumers, l, consumer)
848      consumer->buff_attach = ecore_event_handler_add(E_EVENT_CLIENT_BUFFER_CHANGE,
849                                                      _launcher_cb_launching_consumer_buff_attach,
850                                                      consumer);
851 }
852
853 static Eina_Bool
854 _launcher_cb_launching_buff_attach(void *data, int type EINA_UNUSED, void *event)
855 {
856    E_Service_Launcher *lc;
857    E_Client *ec;
858    E_Event_Client *ev;
859
860    lc = (E_Service_Launcher*)data;
861    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, ECORE_CALLBACK_PASS_ON);
862    if (lc->direction != TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD) goto clean;
863
864    ev = (E_Event_Client *)event;
865    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
866    EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
867
868    ec = ev->ec;
869    if (ec != lc->ec) return ECORE_CALLBACK_PASS_ON;
870
871    ELOGF("LAUNCHER_SRV", "Event cb(BUFFER_CHANGE) for LAUNCHING", ec);
872
873    if (lc->state == LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER)
874      {
875         _launcher_consumers_buffer_change_wait(lc);
876         _launcher_state_set(lc, LAUNCHER_STATE_LAUNCHING);
877      }
878
879    if (lc->vis_grab)
880      {
881         e_policy_visibility_client_grab_release(lc->vis_grab);
882         lc->vis_grab = NULL;
883      }
884
885    if (lc->target.vis_grab)
886      {
887         e_policy_visibility_client_grab_release(lc->target.vis_grab);
888         lc->target.vis_grab = NULL;
889      }
890
891 clean:
892    E_FREE_FUNC(lc->buff_attach, ecore_event_handler_del);
893
894    return ECORE_CALLBACK_PASS_ON;
895 }
896
897 static void
898 _launcher_buffer_change_wait(E_Service_Launcher *lc)
899 {
900    if (!lc) return;
901    if (lc->buff_attach) return;
902
903    if (lc->state == LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER)
904      lc->buff_attach = ecore_event_handler_add(E_EVENT_CLIENT_BUFFER_CHANGE,
905                                                _launcher_cb_launching_buff_attach,
906                                                lc);
907    else if ((lc->with_swl) && (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD))
908      lc->buff_attach = ecore_event_handler_add(E_EVENT_CLIENT_BUFFER_CHANGE,
909                                                _launcher_cb_done_buff_attach,
910                                                lc);
911 }
912
913
914 static void
915 _launcher_cb_launched_ec_del(void *data, void *obj)
916 {
917    E_Service_Launcher *lc = (E_Service_Launcher *)data;
918    E_Client *launched_ec = (E_Client *)obj;
919
920    EINA_SAFETY_ON_NULL_RETURN(launched_ec);
921    EINA_SAFETY_ON_NULL_RETURN(lc);
922    EINA_SAFETY_ON_TRUE_RETURN(lc->launched_ec != launched_ec);
923
924    lc->launched_ec = NULL;
925    lc->launched_delfn = NULL;
926 }
927
928 static void
929 _launcher_cb_target_ec_del(void *data, void *obj)
930 {
931    E_Service_Launcher *lc = (E_Service_Launcher *)data;
932    E_Client *target_ec = (E_Client *)obj;
933
934    EINA_SAFETY_ON_NULL_RETURN(target_ec);
935    EINA_SAFETY_ON_NULL_RETURN(lc);
936    EINA_SAFETY_ON_TRUE_RETURN(lc->target.ec != target_ec);
937
938    lc->target.ec = NULL;
939    lc->target.delfn = NULL;
940
941    switch (lc->state)
942      {
943       case LAUNCHER_STATE_PREPARING:
944       case LAUNCHER_STATE_LAUNCHING:
945       case LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER:
946          _launcher_stop_send(lc);
947          if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
948            _launcher_post_forward(lc, EINA_FALSE);
949          else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
950            _launcher_post_backward(lc, EINA_FALSE);
951
952          _launcher_handler_launcher_runner_unset(lc);
953          _launcher_handler_launcher_pre_runner_unset(lc);
954
955          _launcher_state_set(lc, LAUNCHER_STATE_IDLE);
956          break;
957       default:
958          break;
959      }
960 }
961
962 static void
963 _launcher_launched_ec_set(E_Service_Launcher *lc, E_Client *launched_ec)
964 {
965    EINA_SAFETY_ON_NULL_RETURN(lc);
966    if (lc->launched_ec == launched_ec) return;
967
968    if (lc->launched_ec)
969      {
970         e_object_delfn_del(E_OBJECT(lc->launched_ec), lc->launched_delfn);
971         lc->launched_ec = NULL;
972         lc->launched_delfn = NULL;
973      }
974
975    if (launched_ec)
976      {
977         lc->launched_ec = launched_ec;
978         lc->launched_delfn = e_object_delfn_add(E_OBJECT(launched_ec),
979                                                 _launcher_cb_launched_ec_del, lc);
980      }
981 }
982
983 static void
984 _launcher_target_ec_set(E_Service_Launcher *lc, E_Client *target_ec)
985 {
986    EINA_SAFETY_ON_NULL_RETURN(lc);
987    if (lc->target.ec == target_ec) return;
988
989    if (lc->target.ec)
990      {
991         e_object_delfn_del(E_OBJECT(lc->target.ec), lc->target.delfn);
992         lc->target.ec = NULL;
993         lc->target.delfn = NULL;
994      }
995
996    if (target_ec)
997      {
998         lc->target.ec = target_ec;
999         lc->target.delfn = e_object_delfn_add(E_OBJECT(target_ec),
1000                                               _launcher_cb_target_ec_del, lc);
1001      }
1002 }
1003
1004 static void
1005 _launcher_cb_resource_destroy(struct wl_resource *res_tws_lc)
1006 {
1007    E_Service_Launcher *lc;
1008
1009    lc = wl_resource_get_user_data(res_tws_lc);
1010    if (!lc) return;
1011
1012    ELOGF("LAUNCHER_SRV", "Start Resource Destroy tws_service_launcher", lc->ec);
1013
1014    _launcher_handler_launcher_del(lc);
1015
1016    lc->res = NULL;
1017    _launcher_data_reset(lc);
1018
1019    E_FREE(lc);
1020
1021    ELOGF("LAUNCHER_SRV", "End Resource Destroy tws_service_launcher", NULL);
1022 }
1023
1024 static void
1025 _launcher_cb_destroy(struct wl_client *client EINA_UNUSED,
1026                      struct wl_resource *res_tws_lc)
1027 {
1028    ELOGF("LAUNCHER_SRV", "Received request(launcher_destroy)", NULL);
1029    wl_resource_destroy(res_tws_lc);
1030 }
1031
1032 static void
1033 _launcher_cb_launch(struct wl_client *client EINA_UNUSED,
1034                     struct wl_resource *res_tws_lc,
1035                     const char *app_id,
1036                     const char *instance_id,
1037                     int32_t pid,
1038                     uint32_t serial)
1039 {
1040    E_Service_Launcher *lc;
1041    E_Service_Launcher *runner, *pre_runner;
1042    E_Client *target_ec;
1043    Eina_List *ecs, *l;
1044    Eina_Bool sent = EINA_FALSE;
1045
1046    lc = wl_resource_get_user_data(res_tws_lc);
1047    EINA_SAFETY_ON_NULL_RETURN(lc);
1048    EINA_SAFETY_ON_NULL_RETURN(lc->ec);
1049
1050    ELOGF("LAUNCHER_SRV",
1051          "Recieved request(launcher_launch) appid:%s instance id:%s pid:%d",
1052          lc->ec, app_id?:"NONE", instance_id?:"NONE", pid);
1053
1054    EINA_SAFETY_ON_TRUE_GOTO(lc->ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED, send_stop);
1055    EINA_SAFETY_ON_TRUE_GOTO((pid < 0) && !(app_id) , send_stop);
1056
1057    //check current state of lc
1058    runner =  _launcher_handler_launcher_runner_get();
1059    if (runner == lc)
1060      {
1061         ELOGF("LAUNCHER_SRV",
1062               "Launcher(%s) requests LAUNCH again without cancel, ignore this.",
1063               lc->ec, _launcher_state_to_str(lc->state));
1064
1065         tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_WRONG_REQUEST, lc->serial);
1066         return;
1067      }
1068
1069    pre_runner = _launcher_handler_launcher_pre_runner_get();
1070    if (pre_runner == lc)
1071      {
1072         _launcher_handler_launcher_pre_runner_set(NULL);
1073         _launcher_launched_ec_set(lc, NULL);
1074      }
1075
1076    lc->serial = serial;
1077    lc->target.pid = pid;
1078
1079    if (pid >= 0 )
1080      {
1081         ecs = _launcher_clients_find_by_pid(pid);
1082         EINA_LIST_FOREACH(ecs, l, target_ec)
1083           {
1084              if (e_object_is_del(E_OBJECT(target_ec))) continue;
1085              if (e_client_util_ignored_get(target_ec)) continue;
1086
1087              ELOGF("LAUNCHER_SRV", "Found target_ec:%p", lc->ec, target_ec);
1088
1089              sent = _launcher_prepare_forward_send(lc, target_ec);
1090              EINA_SAFETY_ON_FALSE_GOTO(sent, send_stop);
1091
1092              _launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
1093              break;
1094           }
1095         eina_list_free(ecs);
1096      }
1097
1098    if (app_id)
1099      {
1100         lc->target.appid = eina_stringshare_add(app_id);
1101      }
1102
1103    if (!lc->target.ec)
1104      {
1105         ELOGF("LAUNCHER_SRV", "Can't find target_ec, Start Monitoring", lc->ec);
1106         _launcher_state_set(lc, LAUNCHER_STATE_MONITORING);
1107      }
1108
1109    _launcher_handler_launcher_runner_set(lc);
1110
1111    return;
1112
1113 send_stop:
1114    ELOGF("LAUNCHER_SRV", "can't process request(launcher_launch)", lc->ec);
1115    _launcher_stop_send(lc);
1116 }
1117
1118 static void
1119 _launcher_cb_launch_with_shared_widget(struct wl_client *client EINA_UNUSED,
1120                                        struct wl_resource *res_tws_lc,
1121                                        const char *app_id,
1122                                        const char *instance_id,
1123                                        int32_t pid,
1124                                        uint32_t serial)
1125 {
1126    E_Service_Launcher *lc;
1127    E_Service_Launcher *runner, *pre_runner;
1128    E_Client *target_ec;
1129    Eina_List *ecs, *l;
1130    Eina_Bool sent = EINA_FALSE;
1131
1132    lc = wl_resource_get_user_data(res_tws_lc);
1133    EINA_SAFETY_ON_NULL_RETURN(lc);
1134    EINA_SAFETY_ON_NULL_RETURN(lc->ec);
1135
1136    ELOGF("LAUNCHER_SRV",
1137          "Recieved request(launcher_launch_with_shared_widget) appid:%s instance id:%s pid:%d",
1138          lc->ec, app_id?:"NONE", instance_id?:"NONE", pid);
1139
1140    EINA_SAFETY_ON_TRUE_GOTO(lc->ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED, send_stop);
1141    EINA_SAFETY_ON_TRUE_GOTO((pid < 0) && !(app_id), send_stop);
1142
1143    // check current state of lc
1144    runner = _launcher_handler_launcher_runner_get();
1145    if (runner == lc)
1146      {
1147         ELOGF("LAUNCHER_SRV",
1148               "Launcher(%s) requests LAUNCH again without cancel, ignore this.",
1149               lc->ec, _launcher_state_to_str(lc->state));
1150
1151         tws_service_launcher_send_error(lc->res,
1152                                         TWS_SERVICE_LAUNCHER_ERROR_WRONG_REQUEST,
1153                                         lc->serial);
1154         return;
1155      }
1156
1157    pre_runner = _launcher_handler_launcher_pre_runner_get();
1158    if (pre_runner == lc)
1159      {
1160         _launcher_handler_launcher_pre_runner_set(NULL);
1161         _launcher_launched_ec_set(lc, NULL);
1162      }
1163
1164    lc->with_swl = EINA_TRUE; /* set swl flag */
1165    lc->serial = serial;
1166    lc->target.pid = pid;
1167
1168    if (pid >= 0)
1169      {
1170         ecs = _launcher_clients_find_by_pid(pid);
1171         EINA_LIST_FOREACH(ecs, l, target_ec)
1172           {
1173              if (e_object_is_del(E_OBJECT(target_ec))) continue;
1174              if (e_client_util_ignored_get(target_ec)) continue;
1175
1176              ELOGF("LAUNCHER_SRV", "Found target_ec:%p", lc->ec, target_ec);
1177
1178              // send prepare_shared_widget event to callee
1179              sent = _launcher_prepare_shared_widget_forward_send(lc, target_ec);
1180              EINA_SAFETY_ON_FALSE_GOTO(sent, send_stop);
1181
1182              _launcher_state_set(lc, LAUNCHER_STATE_WAIT_RESPONSE_FROM_CALLEE);
1183              break;
1184           }
1185         eina_list_free(ecs);
1186      }
1187
1188    if (app_id)
1189      {
1190         lc->target.appid = eina_stringshare_add(app_id);
1191      }
1192
1193    if (!lc->target.ec)
1194      {
1195         ELOGF("LAUNCHER_SRV", "Can't find target_ec, Start Monitoring", lc->ec);
1196         _launcher_state_set(lc, LAUNCHER_STATE_MONITORING);
1197      }
1198
1199    _launcher_handler_launcher_runner_set(lc);
1200
1201    return;
1202
1203 send_stop:
1204    ELOGF("LAUNCHER_SRV", "can't process request(launcher_launch)", lc->ec);
1205    _launcher_stop_send(lc);
1206 }
1207
1208 static void
1209 _launcher_cb_launching(struct wl_client *client EINA_UNUSED,
1210                        struct wl_resource *res_tws_lc,
1211                        uint32_t serial)
1212 {
1213    E_Service_Launcher *lc;
1214    E_Service_Launcher *runner;
1215
1216    lc = wl_resource_get_user_data(res_tws_lc);
1217    EINA_SAFETY_ON_NULL_RETURN(lc);
1218
1219    ELOGF("LAUNCHER_SRV", "LAUNCHING(%d) %s",
1220          lc->ec, serial, lc->direction?"backward":"forward");
1221
1222    //check current state of lc
1223    runner = _launcher_handler_launcher_runner_get();
1224    if (runner != lc)
1225      {
1226         ELOGF("LAUNCHER_SRV", "lc(%p) runner(%p), lc is not runner, ignore LAUNCHING",
1227               lc->ec, lc, runner);
1228         tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_WRONG_REQUEST, lc->serial);
1229         return;
1230      }
1231
1232    _launcher_state_set(lc, LAUNCHER_STATE_LAUNCHING);
1233
1234    if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
1235      {
1236         _launcher_state_set(lc, LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER);
1237         _launcher_buffer_change_wait(lc);
1238      }
1239 }
1240
1241 static void
1242 _launcher_target_ec_queue_flush(E_Service_Launcher *lc)
1243 {
1244    struct wayland_tbm_client_queue *cqueue;
1245
1246    if (!e_comp_wl) return;
1247    if (!lc) return;
1248    if (!lc->target.ec) return;
1249    if (e_object_is_del(E_OBJECT(lc->target.ec))) return;
1250
1251    cqueue = e_comp_wl_tbm_client_queue_get(lc->target.ec);
1252    if (cqueue)
1253      wayland_tbm_server_client_queue_flush(cqueue);
1254 }
1255
1256 static void
1257 _launcher_cb_launch_done(struct wl_client *client EINA_UNUSED,
1258                          struct wl_resource *res_tws_lc,
1259                          uint32_t serial)
1260 {
1261    E_Service_Launcher *lc;
1262    E_Service_Launcher *runner;
1263    E_Client *target_ec = NULL;
1264    enum tws_service_launcher_direction launch_direction = 0;
1265
1266    lc = wl_resource_get_user_data(res_tws_lc);
1267    EINA_SAFETY_ON_NULL_RETURN(lc);
1268
1269    ELOGF("LAUNCHER_SRV", "LAUNCH_DONE(%d) target:%p", lc->ec, serial, lc->target.ec);
1270
1271    target_ec = lc->target.ec;
1272    launch_direction = lc->direction;
1273
1274    //check current state of lc
1275    runner = _launcher_handler_launcher_runner_get();
1276    if (runner != lc)
1277      {
1278         ELOGF("LAUNCHER_SRV", "lc(%p) runner(%p), lc is not runner, ignore LAUNCH_DONE",
1279               lc->ec, lc, runner);
1280         tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_WRONG_REQUEST, lc->serial);
1281         return;
1282      }
1283
1284    //shared widget launch case
1285    if (lc->with_swl)
1286      {
1287         if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
1288           {
1289              Eina_Bool sent;
1290
1291              sent = e_tzsh_shared_widget_launch_prepare_send(lc->target.ec,
1292                                                              TWS_SHARED_WIDGET_LAUNCH_PREPARE_STATE_WIDGET_SHOW,
1293                                                              lc->serial);
1294
1295              //TODO : handle failure case
1296              if (sent)
1297                {
1298                   _launcher_buffer_change_wait(lc);
1299                   lc->swl_done = 0;
1300                }
1301
1302              return;
1303           }
1304         else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
1305           {
1306              e_tzsh_shared_widget_launch_prepare_send(lc->target.ec,
1307                                                       TWS_SHARED_WIDGET_LAUNCH_PREPARE_STATE_WIDGET_SHOW,
1308                                                       lc->serial);
1309              _launcher_post_backward(lc, EINA_TRUE);
1310           }
1311      }
1312    else //normal launcher
1313      {
1314         _launcher_target_ec_queue_flush(lc);
1315         if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
1316           _launcher_post_forward(lc, EINA_TRUE);
1317         else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
1318           _launcher_post_backward(lc, EINA_TRUE);
1319      }
1320
1321    _launcher_handler_launcher_runner_unset(lc);
1322    _launcher_handler_launcher_pre_runner_set(lc);
1323    _launcher_state_set(lc, LAUNCHER_STATE_DONE);
1324
1325    if (launch_direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
1326      {
1327         if (target_ec && !e_object_is_del(E_OBJECT(target_ec)))
1328           {
1329              if (target_ec->launching == EINA_TRUE)
1330                {
1331                   ELOGF("COMP", "Un-Set launching flag..", target_ec);
1332                   target_ec->launching = EINA_FALSE;
1333
1334                   if (target_ec->first_mapped)
1335                     {
1336                        E_Comp_Wl_Client_Data *target_cdata = e_client_cdata_get(target_ec);
1337                        ELOGF("LAUNCH", "SHOW real win (target->frame:%p, map:%d) by launcher service (win:0x%08zx, ec:%p).", target_ec, target_ec->frame, target_cdata->mapped, e_client_util_win_get(lc->ec), lc->ec);
1338                        e_comp_object_signal_emit(target_ec->frame, "e,action,launch_real,done", "e");
1339                     }
1340                   e_comp_object_signal_emit(target_ec->frame, "e,action,launch,done", "e");
1341                }
1342           }
1343      }
1344 }
1345
1346 static void
1347 _launcher_cb_launch_cancel(struct wl_client *client EINA_UNUSED,
1348                            struct wl_resource *res_tws_lc,
1349                            uint32_t serial)
1350 {
1351    E_Service_Launcher *lc;
1352    E_Service_Launcher *runner;
1353
1354    lc = wl_resource_get_user_data(res_tws_lc);
1355    EINA_SAFETY_ON_NULL_RETURN(lc);
1356
1357    ELOGF("LAUNCHER_SRV", "LAUNCH_CANCEL(%d) target_ec:%p",
1358          lc->ec, serial, lc->target.ec);
1359
1360    //check state of lc
1361    runner = _launcher_handler_launcher_runner_get();
1362    if (runner != lc)
1363      {
1364         ELOGF("LAUNCHER_SRV", "lc(%p) runner(%p), lc is not runner, ignore LAUNCH_CANCEL",
1365               lc->ec, lc, runner);
1366         tws_service_launcher_send_error(lc->res, TWS_SERVICE_LAUNCHER_ERROR_WRONG_REQUEST, lc->serial);
1367         return;
1368      }
1369
1370    if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
1371      _launcher_post_forward(lc, EINA_FALSE);
1372    else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
1373      _launcher_post_backward(lc, EINA_FALSE);
1374
1375    _launcher_handler_launcher_runner_unset(lc);
1376    _launcher_handler_launcher_pre_runner_set(lc);
1377    _launcher_state_set(lc, LAUNCHER_STATE_CANCELED);
1378 }
1379
1380 static const struct tws_service_launcher_interface _launcher_iface =
1381 {
1382    _launcher_cb_destroy,
1383    _launcher_cb_launch,
1384    _launcher_cb_launch_with_shared_widget,
1385    _launcher_cb_launching,
1386    _launcher_cb_launch_done,
1387    _launcher_cb_launch_cancel,
1388 };
1389
1390 static E_Client *
1391 _launcher_handler_rsm_provider_client_find(E_Client *rsm_consumer_ec)
1392 {
1393    E_Client *prov_ec = NULL;
1394    E_Comp_Wl_Client_Data *prov_cdata = NULL;
1395    Eina_List *tzrs_provs, *l;
1396    E_Service_Launcher *lc;
1397
1398    if (!rsm_consumer_ec->remote_surface.consumer) return NULL;
1399
1400    tzrs_provs = e_comp_wl_remote_surface_providers_get(rsm_consumer_ec);
1401    if (!tzrs_provs) return NULL;
1402
1403    EINA_LIST_FOREACH(tzrs_provs, l, prov_ec)
1404      {
1405         /* check remote surface provider */
1406         if (!prov_ec->remote_surface.provider) continue;
1407         if (prov_ec->visible) continue;
1408         if (evas_object_visible_get(prov_ec->frame)) continue;
1409         prov_cdata = e_client_cdata_get(prov_ec);
1410         if (prov_cdata->mapped) continue;
1411         if (!(lc = _launcher_handler_launcher_find(prov_ec))) continue;
1412         if (!lc->launched_ec) continue;
1413
1414         ELOGF("LAUNCHER_SRV", "Found prov_ec:%p", rsm_consumer_ec, prov_ec);
1415         break;
1416      }
1417    eina_list_free(tzrs_provs);
1418
1419    return prov_ec;
1420 }
1421
1422 static E_Service_Launcher *
1423 _launcher_handler_launcher_find(E_Client *ec)
1424 {
1425    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
1426    EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler, NULL);
1427    EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler->launcher_hash, NULL);
1428
1429    return eina_hash_find(_laundler->launcher_hash, &ec);
1430 }
1431
1432 static Eina_Bool
1433 _launcher_handler_launcher_add(E_Service_Launcher *lc)
1434 {
1435    Eina_Bool ret;
1436
1437    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
1438    EINA_SAFETY_ON_NULL_RETURN_VAL(lc->ec, EINA_FALSE);
1439    EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler, EINA_FALSE);
1440    EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler->launcher_hash, EINA_FALSE);
1441
1442    ret = eina_hash_add(_laundler->launcher_hash, &lc->ec, lc);
1443    if (ret)
1444      _laundler->launcher_count++;
1445
1446    return ret;
1447 }
1448
1449 static Eina_Bool
1450 _launcher_handler_launcher_del(E_Service_Launcher *lc)
1451 {
1452    Eina_Bool ret;
1453
1454    EINA_SAFETY_ON_NULL_RETURN_VAL(lc, EINA_FALSE);
1455    EINA_SAFETY_ON_NULL_RETURN_VAL(lc->ec, EINA_FALSE);
1456    EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler, EINA_FALSE);
1457    EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler->launcher_hash, EINA_FALSE);
1458
1459    ret = eina_hash_del(_laundler->launcher_hash, &lc->ec, lc);
1460    if (ret) _laundler->launcher_count--;
1461
1462    return ret;
1463 }
1464
1465 static void
1466 _launcher_handler_launcher_runner_set(E_Service_Launcher *lc)
1467 {
1468    E_Service_Launcher *runner = NULL;
1469
1470    EINA_SAFETY_ON_NULL_RETURN(_laundler);
1471    if (_laundler->runner == lc) return;
1472
1473    //reset previous runner
1474    runner = _laundler->runner;
1475    if (runner)
1476      {
1477         switch (runner->state)
1478           {
1479            case LAUNCHER_STATE_PREPARING:
1480            case LAUNCHER_STATE_LAUNCHING:
1481            case LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER:
1482               _launcher_state_set(runner, LAUNCHER_STATE_CANCELED);
1483               _launcher_stop_send(runner);
1484               if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
1485                 _launcher_post_forward(runner, EINA_FALSE);
1486               else if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
1487                 _launcher_post_backward(runner, EINA_FALSE);
1488               break;
1489            case LAUNCHER_STATE_MONITORING:
1490               _launcher_state_set(runner, LAUNCHER_STATE_CANCELED);
1491               _launcher_stop_send(runner);
1492               runner->target.pid = -1;
1493               runner->target.ec = NULL;
1494               E_FREE_FUNC(runner->target.appid, eina_stringshare_del);
1495               E_FREE_FUNC(runner->target.splash_path, eina_stringshare_del);
1496               E_FREE_FUNC(runner->target.splash_group, eina_stringshare_del);
1497               break;
1498            default:
1499               break;
1500           }
1501         _launcher_handler_launcher_pre_runner_set(runner);
1502      }
1503
1504    ELOGF("LAUNCHER_SRV", "runner change %p(ec:%p) to %p(ec:%p)",
1505          NULL, runner, runner?runner->ec:NULL, lc, lc?lc->ec:NULL);
1506
1507    _laundler->runner = lc;
1508 }
1509
1510 static void
1511 _launcher_handler_launcher_runner_unset(E_Service_Launcher *lc)
1512 {
1513    EINA_SAFETY_ON_NULL_RETURN(_laundler);
1514    if (_laundler->runner != lc) return;
1515
1516    _laundler->runner = NULL;
1517
1518    ELOGF("LAUNCHER_SRV", "runner unset %p(ec:%p)",
1519          NULL, lc, lc?lc->ec:NULL);
1520 }
1521
1522 static E_Service_Launcher *
1523 _launcher_handler_launcher_runner_get(void)
1524 {
1525    EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler, NULL);
1526    return _laundler->runner;
1527 }
1528
1529 static void
1530 _launcher_handler_launcher_pre_runner_set(E_Service_Launcher *lc)
1531 {
1532    E_Service_Launcher *pre_runner = NULL;
1533
1534    EINA_SAFETY_ON_NULL_RETURN(_laundler);
1535
1536    pre_runner = _laundler->pre_runner;
1537    if (pre_runner == lc) return;
1538    if (pre_runner)
1539      {
1540         if (pre_runner->launched_ec)
1541           e_policy_animatable_lock(pre_runner->launched_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
1542         _launcher_state_set(pre_runner, LAUNCHER_STATE_IDLE);
1543      }
1544
1545    _laundler->pre_runner = lc;
1546
1547    ELOGF("LAUNCHER_SRV", "pre_runner change %p(ec:%p) to %p(ec:%p)",
1548          NULL, pre_runner, pre_runner?pre_runner->ec:NULL, lc, lc?lc->ec:NULL);
1549 }
1550
1551 static void
1552 _launcher_handler_launcher_pre_runner_unset(E_Service_Launcher *lc)
1553 {
1554    EINA_SAFETY_ON_NULL_RETURN(_laundler);
1555    if (_laundler->pre_runner != lc) return;
1556
1557    _laundler->pre_runner = NULL;
1558
1559    ELOGF("LAUNCHER_SRV", "pre_runner unset %p(ec:%p)",
1560          NULL, lc, lc?lc->ec:NULL);
1561 }
1562
1563 static E_Service_Launcher *
1564 _launcher_handler_launcher_pre_runner_get(void)
1565 {
1566    EINA_SAFETY_ON_NULL_RETURN_VAL(_laundler, NULL);
1567    return _laundler->pre_runner;
1568 }
1569
1570 static Eina_Bool
1571 _launcher_handler_cb_hook_vis_uniconify_render_running(void *data EINA_UNUSED, E_Client *ec)
1572 {
1573    E_Service_Launcher *lc = NULL;
1574    E_Service_Launcher *runner, *pre_runner = NULL;
1575    E_Client *activity = NULL, *prov_ec = NULL;
1576    Launcher_State new_state;
1577
1578    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1579
1580    lc = _launcher_handler_launcher_find(ec);
1581    if (!lc)
1582      {
1583         prov_ec = _launcher_handler_rsm_provider_client_find(ec);
1584         if (prov_ec)
1585           {
1586              /* find launcher handler again with provider ec */
1587              lc = _launcher_handler_launcher_find(prov_ec);
1588              /* set rsm provider ec pointer value to given ec (rsm consumer) */
1589              ec = prov_ec;
1590           }
1591      }
1592    if (!lc) return EINA_TRUE;
1593
1594    activity = e_policy_visibility_main_activity_get();
1595    EINA_SAFETY_ON_NULL_RETURN_VAL(activity, EINA_TRUE);
1596
1597    if (ec == lc->ec)
1598      {
1599         ELOGF("LAUNCHER_SRV", "Hook uniconify render begin target.ec:%p activity:%p launched_ec:%p",
1600               ec, lc->target.ec, activity, lc->launched_ec);
1601
1602         if (activity == lc->launched_ec)
1603           {
1604              int sent = EINA_FALSE;
1605
1606              ELOGF("LAUNCHER_SRV", "Current activity(%p, is_del:%d) was launched by launcher.",
1607                    ec, activity, e_object_is_del(E_OBJECT(activity)));
1608
1609              //check state of lc
1610              runner =  _launcher_handler_launcher_runner_get();
1611              if (runner == lc)
1612                {
1613                   ELOGF("LAUNCHER_SRV",
1614                         "Launcher(%s) is already runner, do nothing",
1615                         lc->ec, _launcher_state_to_str(lc->state));
1616                   return EINA_TRUE;
1617                }
1618
1619              pre_runner = _launcher_handler_launcher_pre_runner_get();
1620              if (pre_runner ==  lc)
1621                {
1622                   _launcher_handler_launcher_pre_runner_set(NULL);
1623                }
1624
1625              if (lc->with_swl)
1626                {
1627                   sent = _launcher_prepare_shared_widget_backward_send
1628                      (lc, activity, activity,
1629                       (E_VIS_JOB_TYPE_UNICONIFY |
1630                        E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY));
1631
1632                   new_state = LAUNCHER_STATE_WAIT_RESPONSE_FROM_CALLEE;
1633                }
1634              else
1635                {
1636                   sent = _launcher_prepare_backward_send
1637                      (lc, activity, activity,
1638                       (E_VIS_JOB_TYPE_UNICONIFY |
1639                        E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY));
1640
1641                   new_state = LAUNCHER_STATE_PREPARING;
1642                }
1643
1644
1645              if (!sent) return EINA_FALSE;
1646
1647              _launcher_state_set(lc, new_state);
1648              _launcher_handler_launcher_runner_set(lc);
1649           }
1650      }
1651
1652    return EINA_TRUE;
1653 }
1654
1655 static Eina_Bool
1656 _launcher_handler_cb_hook_vis_lower(void *data EINA_UNUSED, E_Client *ec)
1657 {
1658    E_Service_Launcher *lc = NULL;
1659    E_Service_Launcher *runner, *pre_runner;
1660    E_Client *activity = NULL, *prov_ec = NULL;
1661    Launcher_State new_state;
1662
1663    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1664
1665    activity = e_policy_visibility_main_activity_get();
1666    EINA_SAFETY_ON_NULL_RETURN_VAL(activity, EINA_FALSE);
1667
1668    lc = _launcher_handler_launcher_find(activity);
1669    if (!lc)
1670      {
1671         prov_ec = _launcher_handler_rsm_provider_client_find(activity);
1672         if (prov_ec)
1673           {
1674              /* find launcher handler again with provider activity */
1675              lc = _launcher_handler_launcher_find(prov_ec);
1676           }
1677      }
1678    if (!lc) return EINA_FALSE;
1679
1680    if (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED) return EINA_FALSE;
1681
1682    if (ec == lc->launched_ec)
1683      {
1684         Eina_Bool sent = EINA_FALSE;
1685         ELOGF("LAUNCHER_SRV", "Lower hook of launched_ec(%p)", lc->ec, ec);
1686
1687         //check state of lc
1688         runner =  _launcher_handler_launcher_runner_get();
1689         if (runner == lc)
1690           {
1691              ELOGF("LAUNCHER_SRV",
1692                    "Launcher(%s) is already runner, do nothing",
1693                    lc->ec, _launcher_state_to_str(lc->state));
1694              return EINA_FALSE;
1695           }
1696
1697         pre_runner = _launcher_handler_launcher_pre_runner_get();
1698         if (pre_runner ==  lc)
1699           {
1700              _launcher_handler_launcher_pre_runner_set(NULL);
1701           }
1702
1703         if (lc->with_swl)
1704           {
1705              sent = _launcher_prepare_shared_widget_backward_send(lc, activity, ec, E_VIS_JOB_TYPE_LOWER);
1706              new_state = LAUNCHER_STATE_WAIT_RESPONSE_FROM_CALLEE;
1707           }
1708         else
1709           {
1710              sent = _launcher_prepare_backward_send(lc, activity, ec, E_VIS_JOB_TYPE_LOWER);
1711              new_state = LAUNCHER_STATE_PREPARING;
1712           }
1713
1714         if (!sent) return EINA_FALSE;
1715
1716         _launcher_state_set(lc, new_state);
1717         _launcher_handler_launcher_runner_set(lc);
1718      }
1719
1720    return EINA_TRUE;
1721 }
1722
1723 static Eina_Bool
1724 _launcher_handler_cb_hook_vis_hide(void *data EINA_UNUSED, E_Client *ec)
1725 {
1726    E_Service_Launcher *lc = NULL;
1727    E_Service_Launcher *runner, *pre_runner;
1728    E_Client *activity = NULL, *prov_ec = NULL;
1729    Launcher_State new_state;
1730
1731    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1732
1733    activity = e_policy_visibility_main_activity_get();
1734    EINA_SAFETY_ON_NULL_RETURN_VAL(activity, EINA_FALSE);
1735
1736    lc = _launcher_handler_launcher_find(activity);
1737    if (!lc)
1738      {
1739         prov_ec = _launcher_handler_rsm_provider_client_find(activity);
1740         if (prov_ec)
1741           {
1742              /* find launcher handler again with provider ec */
1743              lc = _launcher_handler_launcher_find(prov_ec);
1744           }
1745         else
1746           {
1747              /* Backward case
1748               *
1749               * activity: callee ec
1750               * given ec: callee ec (transient_for child)  <-- destroying by back key
1751               *           caller ec (transient_for parent) <-- will be shown
1752               *
1753               * In this case, the given ec is a callee ec and is transient_for with caller ec (lc) by
1754               * group launching. Also, because of transient_for, caller ec is not iconified.
1755               * Since the given ec is destroyed by the back key, we can't find out caller ec(lc) with activity and given ec.
1756               * We have to use transient_for to find caller ec(lc).
1757               */
1758              if (ec->parent)
1759                {
1760                   ELOGF("LAUNCHER_SRV", "Hide hook of ec->parent(%p)", ec, ec->parent);
1761                   lc = _launcher_handler_launcher_find(ec->parent);
1762                   if ((lc) && (lc->launched_ec != ec)) lc = NULL;
1763                }
1764              else
1765                {
1766                   ELOGF("LAUNCHER_SRV", "Hide hook of ec->parent(NULL)", ec);
1767                }
1768           }
1769      }
1770    if (!lc) return EINA_FALSE;
1771
1772    if (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED) return EINA_FALSE;
1773
1774    if (ec == lc->launched_ec)
1775      {
1776         Eina_Bool sent = EINA_FALSE;
1777         ELOGF("LAUNCHER_SRV", "Hide hook of launched_ec(%p)", lc->ec, ec);
1778
1779         //check state of lc
1780         runner =  _launcher_handler_launcher_runner_get();
1781         if (runner == lc)
1782           {
1783              ELOGF("LAUNCHER_SRV",
1784                    "Launcher(%s) is already runner, do nothing",
1785                    lc->ec, _launcher_state_to_str(lc->state));
1786              return EINA_FALSE;
1787           }
1788
1789         pre_runner = _launcher_handler_launcher_pre_runner_get();
1790         if (pre_runner ==  lc)
1791           {
1792              _launcher_handler_launcher_pre_runner_set(NULL);
1793           }
1794
1795         if (lc->with_swl)
1796           {
1797              sent = _launcher_prepare_shared_widget_backward_send(lc, activity, ec, E_VIS_JOB_TYPE_HIDE);
1798              new_state = LAUNCHER_STATE_WAIT_RESPONSE_FROM_CALLEE;
1799           }
1800         else
1801           {
1802              sent = _launcher_prepare_backward_send(lc, activity, ec, E_VIS_JOB_TYPE_HIDE);
1803              new_state = LAUNCHER_STATE_PREPARING;
1804           }
1805         if (!sent) return EINA_FALSE;
1806
1807         _launcher_state_set(lc, new_state);
1808         _launcher_handler_launcher_runner_set(lc);
1809      }
1810
1811    return EINA_TRUE;
1812 }
1813
1814 static void
1815 _launcher_handler_cb_hook_client_del(void *data EINA_UNUSED, E_Client *ec)
1816 {
1817    E_Service_Launcher *lc;
1818
1819    EINA_SAFETY_ON_NULL_RETURN(ec);
1820
1821    lc = _launcher_handler_launcher_find(ec);
1822    if (!lc) return;
1823
1824    if (lc->ec == ec) //launcher surface is gone.
1825      {
1826         _launcher_handler_launcher_del(lc);
1827         _launcher_data_reset(lc);
1828         E_FREE(lc);
1829      }
1830 }
1831
1832 static Eina_Bool
1833 _launcher_handler_cb_hook_intercept_show_helper(void *data, E_Client *ec)
1834 {
1835    E_Service_Launcher *runner;
1836    Eina_Bool sent = EINA_FALSE;
1837
1838    runner = _launcher_handler_launcher_runner_get();
1839
1840    if (!runner) goto show_allow;
1841    EINA_SAFETY_ON_NULL_GOTO(ec, show_allow);
1842
1843    if (ec->new_client) goto show_allow;
1844
1845    switch (runner->state)
1846      {
1847       case LAUNCHER_STATE_LAUNCHING_WAIT_BUFFER:  //waiting buffer change
1848          if (ec == runner->ec)
1849            goto show_deny;
1850          break;
1851       case LAUNCHER_STATE_PREPARING:              //waiting launcher client's preparation
1852       case LAUNCHER_STATE_WAIT_RESPONSE_FROM_CALLEE:
1853          if (ec  == runner->target.ec) goto show_deny;
1854          break;
1855       case LAUNCHER_STATE_LAUNCHING:              //doing animation
1856          if (ec == runner->target.ec) goto show_deny; //don't show launched app window
1857          else if (ec == runner->ec) goto show_allow;  //show launcher
1858          break;
1859       case LAUNCHER_STATE_MONITORING:             //waiting creation of target window
1860          if ((runner->target.pid >= 0) && (ec->netwm.pid != runner->target.pid)) goto show_allow; //detect by pid
1861          if ((runner->target.appid) && (runner->target.ec) && (runner->target.ec != ec)) goto show_allow; //detect by appid
1862          if ((runner->target.appid) && (runner->target.pid < 0) && (!runner->target.ec)) goto show_allow; //not enough info
1863          if (e_object_is_del(E_OBJECT(ec))) goto show_allow;
1864
1865          if (runner->with_swl)
1866            {
1867               sent = _launcher_prepare_shared_widget_forward_send(runner, ec);
1868               EINA_SAFETY_ON_FALSE_GOTO(sent, send_stop);
1869
1870               _launcher_state_set(runner, LAUNCHER_STATE_WAIT_RESPONSE_FROM_CALLEE);
1871            }
1872          else
1873            {
1874               sent = _launcher_prepare_forward_send(runner, ec);
1875               EINA_SAFETY_ON_FALSE_GOTO(sent, send_stop);
1876
1877               _launcher_state_set(runner, LAUNCHER_STATE_PREPARING);
1878            }
1879          goto show_deny;
1880       default:
1881          goto show_allow;
1882      }
1883
1884 show_allow:
1885    return EINA_TRUE;
1886 show_deny:
1887    return EINA_FALSE;
1888 send_stop:
1889    runner->target.pid = -1;
1890    runner->serial = 0;
1891    runner->target.ec = NULL;
1892    E_FREE_FUNC(runner->target.appid, eina_stringshare_del);
1893    E_FREE_FUNC(runner->target.splash_path, eina_stringshare_del);
1894    E_FREE_FUNC(runner->target.splash_group, eina_stringshare_del);
1895
1896    _launcher_stop_send(runner);
1897    _launcher_state_set(runner, LAUNCHER_STATE_IDLE);
1898    _launcher_handler_launcher_runner_unset(runner);
1899    return EINA_TRUE;
1900 }
1901
1902 static void _launcher_handler_cb_hook_appinfo_pid_set(const char *appid, pid_t pid, void *data)
1903 {
1904    E_Service_Launcher *runner;
1905
1906    EINA_SAFETY_ON_NULL_RETURN(appid);
1907    EINA_SAFETY_ON_TRUE_RETURN(pid < 0);
1908
1909    runner = _launcher_handler_launcher_runner_get();
1910    if (!runner) return;
1911    if (runner->state != LAUNCHER_STATE_MONITORING) return;
1912
1913    if (runner->target.appid)
1914      {
1915         if (!e_util_strcmp(appid, runner->target.appid))
1916           {
1917              runner->target.pid = pid;
1918
1919              ELOGF("LAUNCHER_SRV", "Register callee pid:%d by appid(%s)",
1920                    runner->ec, pid, runner->target.appid);
1921           }
1922      }
1923 }
1924
1925 static Eina_Bool
1926 _launcher_handler_cb_event_client_show(void *data, int type EINA_UNUSED, void *event)
1927 {
1928    E_Service_Launcher *runner, *pre_runner;
1929    E_Client *ec;
1930    E_Event_Client *ev;
1931
1932    runner = _launcher_handler_launcher_runner_get();
1933    if (!runner) return ECORE_CALLBACK_PASS_ON;
1934
1935    ev = (E_Event_Client *)event;
1936    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
1937    EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
1938
1939    ec = ev->ec;
1940
1941    switch (runner->state)
1942      {
1943       case LAUNCHER_STATE_MONITORING:
1944          if (ec->netwm.pid == runner->target.pid)
1945            goto send_stop;
1946          break;
1947       case LAUNCHER_STATE_PREPARING:
1948          if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
1949            {
1950               if (ec == runner->target.ec)  goto send_stop;
1951            }
1952          else if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
1953            {
1954               if (ec == runner->ec) goto send_stop;
1955            }
1956          break;
1957       case LAUNCHER_STATE_LAUNCHING:
1958          if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
1959            {
1960               if (ec == runner->target.ec) goto send_stop;
1961            }
1962          break;
1963       default:
1964          break;
1965      }
1966
1967    pre_runner = _launcher_handler_launcher_pre_runner_get();
1968    if (pre_runner)
1969      {
1970         switch (pre_runner->state)
1971           {
1972            case LAUNCHER_STATE_DONE:
1973               if (ec == pre_runner->launched_ec)
1974                 _launcher_handler_launcher_pre_runner_set(NULL);
1975               break;
1976            case LAUNCHER_STATE_CANCELED:
1977               _launcher_handler_launcher_pre_runner_set(NULL);
1978               break;
1979            default:
1980               break;
1981           }
1982      }
1983
1984    return ECORE_CALLBACK_PASS_ON;
1985
1986 send_stop:
1987    ELOGF("LAUNCHER_SRV", "CLIENT SHOW: Failure Case runner:%p", ec, runner);
1988
1989    _launcher_stop_send(runner);
1990
1991    if (runner->state == LAUNCHER_STATE_MONITORING)
1992      {
1993         runner->target.pid = -1;
1994         runner->serial = 0;
1995      }
1996    else if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
1997      _launcher_post_forward(runner, EINA_FALSE);
1998    else if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
1999      _launcher_post_backward(runner, EINA_FALSE);
2000
2001    _launcher_state_set(runner, LAUNCHER_STATE_IDLE);
2002    _launcher_handler_launcher_runner_unset(runner);
2003
2004    return ECORE_CALLBACK_PASS_ON;
2005 }
2006
2007 static Eina_Bool
2008 _launcher_handler_cb_event_client_visibility_change(void *data, int type EINA_UNUSED, void *event)
2009 {
2010    E_Service_Launcher *pre_runner;
2011    E_Client *ec;
2012    E_Event_Client *ev;
2013
2014    ev = (E_Event_Client *)event;
2015    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
2016    EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
2017
2018    ec = ev->ec;
2019    if (ec->visibility.obscured != E_VISIBILITY_UNOBSCURED)
2020      return ECORE_CALLBACK_PASS_ON;
2021
2022    pre_runner = _launcher_handler_launcher_pre_runner_get();
2023    if (pre_runner)
2024      {
2025         switch (pre_runner->state)
2026           {
2027            case LAUNCHER_STATE_DONE:
2028            case LAUNCHER_STATE_CANCELED:
2029               if (pre_runner->launched_ec)
2030                 {
2031                    if (pre_runner->launched_ec == ec)
2032                      {
2033                         e_policy_animatable_lock(pre_runner->launched_ec, E_POLICY_ANIMATABLE_CUSTOMIZED, 0);
2034                      }
2035                 }
2036               break;
2037            default:
2038               break;
2039           }
2040      }
2041
2042    return ECORE_CALLBACK_PASS_ON;
2043 }
2044
2045 #undef  LAUNCHER_HANDLER_CB_ADD
2046 #define LAUNCHER_HANDLER_CB_ADD(l, appender, event_type, cb, data)  \
2047   do                                                                \
2048     {                                                               \
2049        void *_h;                                                    \
2050        _h = appender(event_type, cb, data);                         \
2051        assert(_h);                                                  \
2052        l = eina_list_append(l, _h);                                 \
2053     }                                                               \
2054   while (0)
2055
2056
2057 static E_Service_Launcher_Handler *
2058 _launcher_handler_create(void)
2059 {
2060    E_Service_Launcher_Handler *laundler = NULL;
2061
2062    laundler = E_NEW(E_Service_Launcher_Handler, 1);
2063    EINA_SAFETY_ON_NULL_RETURN_VAL(laundler, NULL);
2064
2065    laundler->launcher_count = 0;
2066    laundler->launcher_hash = eina_hash_pointer_new(NULL);
2067
2068    LAUNCHER_HANDLER_CB_ADD(laundler->hooks_vis,
2069                            e_policy_visibility_hook_add,
2070                            E_POL_VIS_HOOK_TYPE_UNICONIFY_RENDER_RUNNING,
2071                            _launcher_handler_cb_hook_vis_uniconify_render_running, NULL);
2072
2073    LAUNCHER_HANDLER_CB_ADD(laundler->hooks_vis,
2074                            e_policy_visibility_hook_add,
2075                            E_POL_VIS_HOOK_TYPE_LOWER,
2076                            _launcher_handler_cb_hook_vis_lower, NULL);
2077
2078    LAUNCHER_HANDLER_CB_ADD(laundler->hooks_vis,
2079                            e_policy_visibility_hook_add,
2080                            E_POL_VIS_HOOK_TYPE_HIDE,
2081                            _launcher_handler_cb_hook_vis_hide, NULL);
2082
2083    LAUNCHER_HANDLER_CB_ADD(laundler->hooks_ec,
2084                            e_client_hook_add,
2085                            E_CLIENT_HOOK_DEL,
2086                            _launcher_handler_cb_hook_client_del, NULL);
2087
2088    LAUNCHER_HANDLER_CB_ADD(laundler->hooks_co,
2089                            e_comp_object_intercept_hook_add,
2090                            E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER,
2091                            _launcher_handler_cb_hook_intercept_show_helper, NULL);
2092
2093    LAUNCHER_HANDLER_CB_ADD(laundler->hooks_appinfo,
2094                            e_appinfo_hook_add,
2095                            E_APPINFO_HOOK_PID_SET,
2096                            _launcher_handler_cb_hook_appinfo_pid_set, NULL);
2097
2098    LAUNCHER_HANDLER_CB_ADD(laundler->hdlrs_ev,
2099                            ecore_event_handler_add,
2100                            E_EVENT_CLIENT_SHOW,
2101                            _launcher_handler_cb_event_client_show, NULL);
2102
2103    LAUNCHER_HANDLER_CB_ADD(laundler->hdlrs_ev,
2104                            ecore_event_handler_add,
2105                            E_EVENT_CLIENT_VISIBILITY_CHANGE,
2106                            _launcher_handler_cb_event_client_visibility_change, NULL);
2107
2108    ELOGF("LAUNCHER_SRV", "new launcher handler(%p) created", NULL, laundler);
2109
2110    return laundler;
2111 }
2112
2113 static void
2114 _launcher_handler_destroy(E_Service_Launcher_Handler *laundler)
2115 {
2116    EINA_SAFETY_ON_NULL_RETURN(laundler);
2117
2118    E_FREE_LIST(laundler->hdlrs_ev, ecore_event_handler_del);
2119    E_FREE_LIST(laundler->hooks_appinfo, e_appinfo_hook_del);
2120    E_FREE_LIST(laundler->hooks_co, e_comp_object_intercept_hook_del);
2121    E_FREE_LIST(laundler->hooks_ec, e_client_hook_del);
2122    E_FREE_LIST(laundler->hooks_vis, e_policy_visibility_hook_del);
2123
2124    E_FREE_FUNC(laundler->launcher_hash, eina_hash_free);
2125    E_FREE(laundler);
2126 }
2127
2128 EINTERN void
2129 e_service_launcher_resource_set(E_Client *ec, struct wl_resource *res_tws_lc)
2130 {
2131    E_Service_Launcher *lc;
2132
2133    EINA_SAFETY_ON_NULL_RETURN(ec);
2134    EINA_SAFETY_ON_NULL_RETURN(res_tws_lc);
2135
2136    lc = _launcher_handler_launcher_find(ec);
2137    EINA_SAFETY_ON_NULL_RETURN(lc);
2138    EINA_SAFETY_ON_TRUE_RETURN(lc->ec != ec);
2139
2140    if (lc->res)
2141      _launcher_data_reset(lc);
2142
2143    lc->res = res_tws_lc;
2144    wl_resource_set_implementation(res_tws_lc,
2145                                   &_launcher_iface, lc,
2146                                   _launcher_cb_resource_destroy);
2147 }
2148
2149 EINTERN void
2150 e_service_launcher_client_set(E_Client *ec)
2151 {
2152    E_Service_Launcher *lc = NULL;
2153
2154    EINA_SAFETY_ON_NULL_RETURN(ec);
2155    EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(ec)));
2156
2157    if ((lc = _launcher_handler_launcher_find(ec)))
2158      {
2159         ELOGF("LAUNCHER_SRV", "ec(%p) is already set as launcher(%p)",
2160               ec, ec, lc);
2161         return;
2162      }
2163
2164    if (!_laundler)
2165      {
2166         _laundler = _launcher_handler_create();
2167         EINA_SAFETY_ON_NULL_RETURN(_laundler);
2168      }
2169
2170    lc = E_NEW(E_Service_Launcher, 1);
2171    EINA_SAFETY_ON_NULL_RETURN(lc);
2172
2173    lc->ec = ec;
2174    if (!_launcher_handler_launcher_add(lc))
2175      {
2176         E_FREE(lc);
2177         ELOGF("LAUNCHER_SRV", "Fail to add launcher", ec);
2178         return;
2179      }
2180
2181    ELOGF("LAUNCHER_SRV", "client set|Created New Launcher(%p)", ec, lc);
2182    _launcher_state_set(lc, LAUNCHER_STATE_IDLE);
2183
2184    return;
2185 }
2186
2187 EINTERN void
2188 e_service_launcher_client_unset(E_Client *ec)
2189 {
2190    E_Service_Launcher *lc;
2191
2192    EINA_SAFETY_ON_NULL_RETURN(ec);
2193
2194    lc = _launcher_handler_launcher_find(ec);
2195    EINA_SAFETY_ON_NULL_RETURN(lc);
2196
2197    _launcher_handler_launcher_del(lc);
2198    _launcher_data_reset(lc);
2199    E_FREE(lc);
2200
2201    ELOGF("LAUNCHER_SRV", "client unset", ec);
2202
2203    if ((_laundler) && (_laundler->launcher_count == 0))
2204      {
2205         ELOGF("LAUNCHER_SRV", "No launcher available, Destroy Launcher Handler(%p)",
2206               NULL, _laundler);
2207
2208         _launcher_handler_destroy(_laundler);
2209         _laundler = NULL;
2210      }
2211 }
2212
2213 EINTERN void
2214 e_service_launcher_prepare_send_with_shared_widget_info(E_Client *target_ec,
2215                                                         const char *shared_widget_info,
2216                                                         uint32_t state,
2217                                                         uint32_t serial)
2218 {
2219    E_Service_Launcher *lc = NULL;
2220    Eina_Bool sent;
2221    int x, y;
2222    Eina_Iterator *hash_iter;
2223    Eina_Bool found = EINA_FALSE;
2224
2225    EINA_SAFETY_ON_NULL_RETURN(_laundler);
2226
2227    /* look for launcher service object which has given target_ec */
2228    hash_iter = eina_hash_iterator_data_new(_laundler->launcher_hash);
2229    EINA_ITERATOR_FOREACH(hash_iter, lc)
2230      {
2231         if (lc->target.ec != target_ec) continue;
2232         if (lc->serial != serial) continue;
2233         found = EINA_TRUE;
2234         break;
2235      }
2236    eina_iterator_free(hash_iter);
2237
2238    EINA_SAFETY_ON_FALSE_RETURN(found);
2239    EINA_SAFETY_ON_NULL_RETURN(lc);
2240
2241    ELOGF("LAUNCHER_SRV", "SWL | callee(%p) cb(PREPARE_DONE(%d))",
2242          lc->ec, target_ec, state);
2243
2244    if (state == TWS_SHARED_WIDGET_LAUNCH_PREPARE_STATE_WIDGET_HIDE)
2245      {
2246         e_client_pos_get(target_ec, &x, &y);
2247
2248         sent = _launcher_prepare_send(lc, target_ec, x, y, shared_widget_info);
2249         EINA_SAFETY_ON_FALSE_GOTO(sent, error);
2250
2251         _launcher_state_set(lc, LAUNCHER_STATE_PREPARING);
2252      }
2253    else if (state == TWS_SHARED_WIDGET_LAUNCH_PREPARE_STATE_WIDGET_SHOW)
2254      {
2255         if (!lc->buff_attach)
2256           {
2257              if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
2258                _launcher_post_forward(lc, EINA_TRUE);
2259              else if (lc->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
2260                _launcher_post_backward(lc, EINA_TRUE);
2261
2262              _launcher_handler_launcher_runner_unset(lc);
2263              _launcher_handler_launcher_pre_runner_set(lc);
2264              _launcher_state_set(lc, LAUNCHER_STATE_DONE);
2265           }
2266
2267         lc->swl_done = EINA_TRUE;
2268
2269         ELOGF("LAUNCHER_SRV", "SWL | send CLEANUP", lc->ec);
2270         tws_service_launcher_send_cleanup(lc->res,
2271                                           lc->serial);
2272      }
2273
2274    return;
2275
2276 error:
2277    ELOGF("LAUNCHER_SRV", "Failed to send event(PREPARE:FORWARD)", lc->ec);
2278    _launcher_post_forward(lc, EINA_FALSE);
2279 }
2280
2281 EINTERN void
2282 e_service_launcher_release_shared_widget_launch(E_Client *ec)
2283 {
2284    E_Service_Launcher *runner;
2285
2286    EINA_SAFETY_ON_NULL_RETURN(ec);
2287
2288    runner = _launcher_handler_launcher_runner_get();
2289    EINA_SAFETY_ON_NULL_RETURN(runner);
2290
2291    ELOGF("LAUNCHER_SRV", "Released tzsh_swl", ec);
2292
2293    if ((runner) && (runner->target.ec == ec))
2294      {
2295         if (runner->with_swl)
2296           {
2297              //callee is gone before replying prepare_done
2298              if (runner->state == LAUNCHER_STATE_WAIT_RESPONSE_FROM_CALLEE)
2299                {
2300                   if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_FORWARD)
2301                     _launcher_post_forward(runner, EINA_FALSE);
2302                   else if (runner->direction == TWS_SERVICE_LAUNCHER_DIRECTION_BACKWARD)
2303                     _launcher_post_backward(runner, EINA_FALSE);
2304
2305                   _launcher_state_set(runner, LAUNCHER_STATE_IDLE);
2306                   _launcher_launched_ec_set(runner, NULL);
2307
2308                   _launcher_handler_launcher_runner_unset(runner);
2309                   _launcher_handler_launcher_pre_runner_unset(runner);
2310
2311                   runner->direction = 0;
2312                   runner->with_swl = 0;
2313                }
2314           }
2315      }
2316 }
2317
2318 EINTERN void
2319 e_service_launcher_callee_register(E_Client *callee, const char *appid, const char *splash_path, const char *splash_group)
2320 {
2321    E_Service_Launcher *runner;
2322
2323    EINA_SAFETY_ON_NULL_RETURN(callee);
2324
2325    runner = _launcher_handler_launcher_runner_get();
2326    EINA_SAFETY_ON_NULL_RETURN(runner);
2327    EINA_SAFETY_ON_TRUE_RETURN(runner->state != LAUNCHER_STATE_MONITORING);
2328
2329    if (runner->target.appid)
2330      {
2331         if (!e_util_strcmp(appid, runner->target.appid))
2332           {
2333              runner->target.ec = callee;
2334              runner->target.splash_path = eina_stringshare_add(splash_path);
2335              runner->target.splash_group = eina_stringshare_add(splash_group);
2336
2337              ELOGF("LAUNCHER_SRV", "Register callee(%p)  by appid(%s)",
2338                    runner->ec, runner->target.ec, runner->target.appid);
2339           }
2340      }
2341 }