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