bb189b1b22ec12ffb5c9494f3af1a45c58dd058c
[platform/upstream/enlightenment.git] / src / bin / e_comp_wl_rsm.c
1 #include "e.h"
2 #include "e_policy_wl.h"
3 #ifdef HAVE_REMOTE_SURFACE
4  #include <tizen-remote-surface-server-protocol.h>
5 #endif /* HAVE_REMOTE_SURFACE */
6 #include <tbm_surface.h>
7 #include <tbm_surface_internal.h>
8 #include <wayland-tbm-server.h>
9 #include <tizen-extension-server-protocol.h>
10
11 #include <pixman.h>
12
13 #define RSMINF(f, cp, ec, obj, ptr, x...)                             \
14    do                                                                 \
15      {                                                                \
16         if ((!cp) && (!ec))                                           \
17           INF("EWL|%20.20s|              |             |%10.10s|%p|"f,\
18               "RSM", (obj), (ptr), ##x);                              \
19         else                                                          \
20           INF("EWL|%20.20s|win:0x%08zx|ec:%8p|%10.10s|%p|"f,          \
21               "RSM",                                                  \
22               (e_client_util_win_get(ec)),                            \
23               (ec),                                                   \
24               (obj), (ptr),                                           \
25               ##x);                                                   \
26      }                                                                \
27    while (0)
28
29 #define RSMDBG(f, cp, ec, obj, ptr, x...)                             \
30    do                                                                 \
31      {                                                                \
32         if ((!cp) && (!ec))                                           \
33           DBG("EWL|%20.20s|              |             |%10.10s|%p|"f,\
34               "RSM", (obj), (ptr), ##x);                              \
35         else                                                          \
36           DBG("EWL|%20.20s|win:0x%08zx|ec:%8p|%10.10s|%p|"f,          \
37               "RSM",                                                  \
38               (e_client_util_win_get(ec)),                            \
39               (ec),                                                   \
40               (obj), (ptr),                                           \
41               ##x);                                                   \
42      }                                                                \
43    while (0)
44
45 #define container_of(ptr, type, member) \
46    ({ \
47     const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
48     (type *)( (char *)__mptr - offsetof(type,member) ); \
49     })
50
51 E_API int E_EVENT_REMOTE_SURFACE_PROVIDER_VISIBILITY_CHANGE = -1;
52
53 #ifdef HAVE_REMOTE_SURFACE
54 typedef struct _E_Comp_Wl_Remote_Manager E_Comp_Wl_Remote_Manager;
55 typedef struct _E_Comp_Wl_Remote_Common E_Comp_Wl_Remote_Common;
56 typedef struct _E_Comp_Wl_Remote_Provider E_Comp_Wl_Remote_Provider;
57 typedef struct _E_Comp_Wl_Remote_Source E_Comp_Wl_Remote_Source;
58 typedef struct _E_Comp_Wl_Remote_Surface E_Comp_Wl_Remote_Surface;
59 typedef struct _E_Comp_Wl_Remote_Region E_Comp_Wl_Remote_Region;
60 typedef struct _E_Comp_Wl_Remote_Buffer E_Comp_Wl_Remote_Buffer;
61
62 struct _E_Comp_Wl_Remote_Manager
63 {
64    struct wl_global *global;
65
66    Eina_Hash *provider_hash;
67    Eina_Hash *surface_hash;
68    Eina_Hash *source_hash;
69    Eina_Hash *bind_surface_hash;
70    Eina_List *event_hdlrs;
71    Eina_List *client_hooks;
72    Eina_List *process_hooks;
73
74    int dummy_fd; /* tizen_remote_surface@chagned_buffer need valid fd when it send tbm surface */
75 };
76
77 /* common structure of provider and source */
78 struct _E_Comp_Wl_Remote_Common
79 {
80    E_Client *ec;
81    Eina_List *surfaces;
82
83    Eina_Bool is_offscreen;
84    Eina_Bool ignore_output_transform;
85 };
86
87 /* widget client */
88 struct _E_Comp_Wl_Remote_Provider
89 {
90    E_Comp_Wl_Remote_Common common;
91
92    struct wl_resource *resource;
93
94    E_Comp_Wl_Remote_Surface *onscreen_parent;
95
96    Eina_Bool visible;
97    int vis_ref;
98    uint32_t input_event_filter;
99    int buffer_mode;
100 };
101
102 /* normal UI client */
103 struct _E_Comp_Wl_Remote_Source
104 {
105    E_Comp_Wl_Remote_Common common;
106
107    E_Comp_Wl_Buffer_Ref buffer_ref;
108    const char *image_path;
109    Ecore_Thread *th;
110    Eina_Bool deleted;
111
112    int offscreen_ref;
113    int ref_as_child;
114
115    Eina_Bool defer_img_save;
116 };
117
118 /* widget viewer or task-manager client */
119 struct _E_Comp_Wl_Remote_Surface
120 {
121    struct wl_resource *resource;
122    struct wl_resource *wl_tbm;
123    struct wl_listener tbm_destroy_listener;
124
125    E_Comp_Wl_Remote_Provider *provider;
126    E_Comp_Wl_Remote_Source *source;
127    E_Client *bind_ec;
128
129    E_Client *owner;
130    Eina_List *regions;
131
132    Eina_Bool redirect;
133    Eina_Bool visible;
134
135    Eina_Bool remote_render;
136
137    Eina_Bool valid;
138
139    Eina_List *send_remote_bufs;
140
141    struct
142    {
143       Eina_Bool use;
144       enum tizen_remote_surface_changed_buffer_event_filter filter;
145    } changed_buff_ev_filter;
146
147    struct
148    {
149       Eina_Bool set;
150       enum tizen_remote_surface_buffer_type type;
151       uint32_t serial;
152    } req_curr_buff;
153
154    int version;
155 };
156
157 struct _E_Comp_Wl_Remote_Region
158 {
159    struct wl_resource *resource;
160
161    E_Comp_Wl_Remote_Surface *remote_surface;
162    Eina_Rectangle geometry;
163    Evas_Object *mirror;
164 };
165
166 struct _E_Comp_Wl_Remote_Buffer
167 {
168    E_Comp_Wl_Buffer_Ref ref;
169    struct wl_resource *resource;
170    struct wl_listener destroy_listener;
171
172    E_Comp_Wl_Remote_Surface *remote_surface;
173 };
174
175 static E_Comp_Wl_Remote_Manager *_rsm = NULL;
176
177 static void _e_comp_wl_remote_surface_state_buffer_set(E_Comp_Wl_Surface_State *state, E_Comp_Wl_Buffer *buffer);
178 static void _e_comp_wl_remote_buffer_cb_destroy(struct wl_listener *listener, void *data);
179 static E_Comp_Wl_Remote_Buffer *_e_comp_wl_remote_buffer_get(E_Comp_Wl_Remote_Surface *remote_surface,
180                                                              struct wl_resource *remote_buffer_resource);
181 static void _remote_surface_region_clear(E_Comp_Wl_Remote_Surface *remote_surface);
182 static void _remote_surface_ignore_output_transform_send(E_Comp_Wl_Remote_Common *common);
183 static void _remote_source_save_start(E_Comp_Wl_Remote_Source *source);
184
185 static Evas_Device *
186 _device_get_by_identifier(const char *identifier)
187 {
188    Evas_Device *dev = NULL;
189    const Eina_List *devices, *l;
190
191    devices = evas_device_list(e_comp->evas, NULL);
192    EINA_LIST_FOREACH(devices, l, dev)
193      {
194         if (!e_util_strcmp(identifier, evas_device_description_get(dev)))
195           return dev;
196      }
197
198    return NULL;
199 }
200
201 static void
202 _remote_region_mirror_clear(E_Comp_Wl_Remote_Region *region)
203 {
204    if (!region) return;
205    if (!region->mirror) return;
206
207    evas_object_del(region->mirror);
208 }
209
210 static void
211 _remote_provider_rect_add(E_Comp_Wl_Remote_Provider *provider, Eina_Rectangle *rect)
212 {
213    E_Client *ec;
214
215    ec = provider->common.ec;
216    if (!ec) return;
217    if (!ec->comp_data) return;
218
219    ec->comp_data->remote_surface.regions =
220       eina_list_remove(ec->comp_data->remote_surface.regions,
221                        rect);
222    ec->comp_data->remote_surface.regions =
223       eina_list_append(ec->comp_data->remote_surface.regions,
224                        rect);
225 }
226
227 static void
228 _remote_provider_rect_del(E_Comp_Wl_Remote_Provider *provider, Eina_Rectangle *rect)
229 {
230    E_Client *ec;
231
232    ec = provider->common.ec;
233    if (!ec) return;
234    if (!ec->comp_data) return;
235
236    ec->comp_data->remote_surface.regions =
237       eina_list_remove(ec->comp_data->remote_surface.regions,
238                        rect);
239 }
240
241 static void
242 _remote_provider_rect_clear(E_Comp_Wl_Remote_Provider *provider)
243 {
244    E_Client *ec;
245
246    ec = provider->common.ec;
247    if (!ec) return;
248    if (!ec->comp_data) return;
249
250    /* TODO : remove it from here after supporting multiple onscreen surface */
251    _remote_surface_region_clear(provider->onscreen_parent);
252
253    ec->comp_data->remote_surface.regions =
254       eina_list_remove_list(ec->comp_data->remote_surface.regions,
255                             ec->comp_data->remote_surface.regions);
256 }
257
258 static void
259 _remote_provider_onscreen_parent_set(E_Comp_Wl_Remote_Provider *provider, E_Comp_Wl_Remote_Surface *parent)
260 {
261    E_Comp_Wl_Remote_Region *region;
262    Eina_List *l;
263
264    if (!provider) return;
265    if ((parent) && !(parent->owner)) return;
266    if (provider->onscreen_parent == parent) return;
267
268    _remote_provider_rect_clear(provider);
269
270    provider->onscreen_parent = parent;
271    provider->common.ec->comp_data->remote_surface.onscreen_parent = NULL;
272
273    RSMDBG("set onscreen_parent %p(ec:%p)",
274           provider->common.ec->pixmap, provider->common.ec,
275           "PROVIDER", provider,
276           parent, parent? parent->owner:NULL);
277
278    if (parent)
279      {
280         EINA_LIST_FOREACH(provider->onscreen_parent->regions, l, region)
281           {
282              _remote_provider_rect_add(provider, &region->geometry);
283           }
284
285         provider->common.ec->comp_data->remote_surface.onscreen_parent = parent->owner;
286      }
287 }
288
289 static void
290 _remote_provider_onscreen_parent_calculate(E_Comp_Wl_Remote_Provider *provider)
291 {
292    Evas_Object *o;
293    E_Client *ec, *_ec, *parent = NULL;
294    E_Comp_Wl_Remote_Surface *surface;
295    E_Comp_Wl_Client_Data *cdata;
296
297    if (!provider) return;
298
299    ec = provider->common.ec;
300    if (!ec) return;
301    if (!ec->comp_data) return;
302    if (!provider->common.surfaces) return;
303
304    o = evas_object_top_get(e_comp->evas);
305    for (; o; o = evas_object_below_get(o))
306      {
307         _ec = evas_object_data_get(o, "E_Client");
308         if (!_ec) continue;
309         if (_ec == ec) continue;
310
311         if ((surface = eina_hash_find(_rsm->surface_hash, &_ec)))
312           {
313              if (surface->provider != provider) continue;
314              if (!surface->visible) continue;
315
316              if (e_object_is_del(E_OBJECT(_ec))) continue;
317              if (e_client_util_ignored_get(_ec)) continue;
318              if (_ec->zone != ec->zone) continue;
319              if (!_ec->frame) continue;
320              if (!_ec->visible) continue;
321              if (_ec->visibility.skip) continue;
322              if ((_ec->visibility.obscured != E_VISIBILITY_UNOBSCURED) &&
323                  (_ec->visibility.obscured != E_VISIBILITY_PARTIALLY_OBSCURED))
324                continue;
325
326              /* if _ec is subsurface, skip this */
327              cdata = (E_Comp_Wl_Client_Data *)_ec->comp_data;
328              if (cdata && cdata->sub.data) continue;
329
330              if (!E_INTERSECTS(_ec->x, _ec->y, _ec->w, _ec->h, ec->zone->x, ec->zone->y, ec->zone->w, ec->zone->h))
331                continue;
332
333              parent = _ec;
334              break;
335           }
336      }
337
338    surface = NULL;
339    if (parent)
340      surface = eina_hash_find(_rsm->surface_hash, &parent);
341
342    _remote_provider_onscreen_parent_set(provider, surface);
343 }
344
345 static void
346 _remote_provider_offscreen_set(E_Comp_Wl_Remote_Provider* provider, Eina_Bool set)
347 {
348    E_Client *ec;
349
350    EINA_SAFETY_ON_NULL_RETURN(provider);
351    EINA_SAFETY_ON_NULL_RETURN(provider->common.ec);
352
353    ec = provider->common.ec;
354
355    if (e_object_is_del(E_OBJECT(ec))) return;
356
357    if (set)
358      {
359         provider->common.is_offscreen = set;
360         ec->ignored = EINA_TRUE;
361
362         //TODO: consider what happens if it's not normal client such as subsurface client
363         //TODO: save original values
364         if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.unmap))
365           {
366              ELOGF("COMP", "Call shell.unmap by rsm", ec);
367              ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
368           }
369         else
370           {
371              ec->visible = EINA_FALSE;
372              evas_object_hide(ec->frame);
373              ec->comp_data->mapped = 0;
374           }
375
376         ec->icccm.accepts_focus = ec->icccm.take_focus = ec->want_focus = EINA_FALSE;
377         ec->placed = EINA_TRUE;
378         e_client_visibility_skip_set(ec, EINA_TRUE);
379
380         _remote_provider_onscreen_parent_calculate(provider);
381      }
382    else
383      {
384         e_client_visibility_skip_set(ec, EINA_FALSE);
385         provider->common.is_offscreen = set;
386         ec->icccm.accepts_focus = ec->icccm.take_focus = ec->want_focus = EINA_TRUE;
387         ec->placed = EINA_FALSE;
388
389         _remote_provider_onscreen_parent_set(provider, NULL);
390
391         e_comp_wl_surface_commit(ec);
392      }
393
394    _remote_surface_ignore_output_transform_send(&provider->common);
395
396    RSMINF("%s offscreen",
397           ec->pixmap, ec,
398           "PROVIDER", provider, set? "Set":"Unset");
399 }
400
401 static void
402 _remote_provider_visible_event_free(void *data EINA_UNUSED, E_Event_Remote_Surface_Provider *ev)
403 {
404    e_object_unref(E_OBJECT(ev->ec));
405    free(ev);
406 }
407
408 static void
409 _remote_provider_visible_event_send(E_Comp_Wl_Remote_Provider *provider)
410 {
411    E_Event_Remote_Surface_Provider *ev;
412
413    if (e_object_is_del(E_OBJECT(provider->common.ec))) return;
414
415    ev = E_NEW(E_Event_Remote_Surface_Provider, 1);
416    if (!ev) return;
417
418    ev->ec = provider->common.ec;
419    e_object_ref(E_OBJECT(provider->common.ec));
420    ecore_event_add(E_EVENT_REMOTE_SURFACE_PROVIDER_VISIBILITY_CHANGE, ev, (Ecore_End_Cb)_remote_provider_visible_event_free, NULL);
421 }
422
423 static void
424 _remote_provider_visible_set(E_Comp_Wl_Remote_Provider *provider, Eina_Bool set)
425 {
426    EINA_SAFETY_ON_NULL_RETURN(provider);
427
428    if (set)
429      {
430         provider->vis_ref ++;
431         RSMDBG("Count up vis_ref:%d",
432                provider->common.ec->pixmap, provider->common.ec,
433                "PROVIDER", provider, provider->vis_ref);
434
435         if (provider->vis_ref == 1)
436           {
437              provider->common.ec->visibility.obscured = E_VISIBILITY_UNOBSCURED;
438
439              _remote_provider_visible_event_send(provider);
440              e_policy_client_visibility_send(provider->common.ec);
441
442              tizen_remote_surface_provider_send_visibility
443                 (provider->resource,
444                  TIZEN_REMOTE_SURFACE_PROVIDER_VISIBILITY_TYPE_VISIBLE);
445           }
446      }
447    else
448      {
449         provider->vis_ref --;
450         RSMDBG("Count down vis_ref:%d",
451                provider->common.ec->pixmap, provider->common.ec,
452                "PROVIDER", provider, provider->vis_ref);
453
454         if (provider->vis_ref == 0)
455           {
456              provider->common.ec->visibility.obscured = E_VISIBILITY_FULLY_OBSCURED;
457
458              _remote_provider_visible_event_send(provider);
459              e_policy_client_visibility_send(provider->common.ec);
460
461              tizen_remote_surface_provider_send_visibility
462                 (provider->resource,
463                  TIZEN_REMOTE_SURFACE_PROVIDER_VISIBILITY_TYPE_INVISIBLE);
464
465              if (provider->buffer_mode)
466                e_pixmap_buffer_clear(provider->common.ec->pixmap, EINA_TRUE);
467           }
468      }
469
470    _remote_provider_onscreen_parent_calculate(provider);
471 }
472
473 static void
474 _remote_provider_client_set(E_Client *ec, Eina_Bool set)
475 {
476    if (!ec) return;
477    if ((e_object_is_del(E_OBJECT(ec)))) return;
478
479    ec->remote_surface.provider = set;
480 }
481
482 static E_Comp_Wl_Remote_Provider *
483 _remote_provider_find(E_Client *ec)
484 {
485    E_Comp_Wl_Remote_Provider *provider;
486
487    EINA_SAFETY_ON_NULL_RETURN_VAL(_rsm, NULL);
488    EINA_SAFETY_ON_NULL_RETURN_VAL(_rsm->provider_hash, NULL);
489
490    provider = eina_hash_find(_rsm->provider_hash, &ec);
491    return provider;
492 }
493
494 /* true : given buffer type can be delivered to the client
495  * false: the client wants to filter given buffer type, thus changed_buffer
496  *        event for this type of buffer will not be sent to the client.
497  */
498 static Eina_Bool
499 _remote_surface_changed_buff_ev_filter_check(E_Comp_Wl_Remote_Surface *rs,
500                                              enum tizen_remote_surface_buffer_type buff_type)
501 {
502    Eina_Bool res = EINA_TRUE;
503
504    if (rs->changed_buff_ev_filter.use)
505      {
506         switch (buff_type)
507           {
508            case TIZEN_REMOTE_SURFACE_BUFFER_TYPE_TBM:
509               if (rs->changed_buff_ev_filter.filter & TIZEN_REMOTE_SURFACE_CHANGED_BUFFER_EVENT_FILTER_TBM)
510                 res = EINA_FALSE;
511               break;
512            case TIZEN_REMOTE_SURFACE_BUFFER_TYPE_IMAGE_FILE:
513               if (rs->changed_buff_ev_filter.filter & TIZEN_REMOTE_SURFACE_CHANGED_BUFFER_EVENT_FILTER_IMAGE_FILE)
514                 res = EINA_FALSE;
515               break;
516            default:
517               break;
518           }
519      }
520
521    return res;
522 }
523
524 static Eina_Bool
525 _remote_surface_changed_buff_protocol_send(E_Comp_Wl_Remote_Surface *rs,
526                                            enum tizen_remote_surface_buffer_type buff_type,
527                                            int img_file_fd,
528                                            unsigned int img_file_size,
529                                            Eina_Bool ref_set,
530                                            E_Comp_Wl_Buffer *buff)
531 {
532    E_Comp_Wl_Remote_Common *common = NULL;
533    E_Client *src_ec = NULL;
534    struct wl_resource *tbm = NULL;
535    Eina_Bool send = EINA_FALSE;
536    struct wl_array opts;
537    Eina_Bool add_opts = EINA_FALSE;
538    char *p, tmp[16];
539    int len;
540    struct wl_resource *rbuff_res = NULL;
541    E_Comp_Wl_Remote_Buffer *rbuff = NULL;
542
543    if (rs->provider)
544      {
545         common = &rs->provider->common;
546         src_ec = rs->provider->common.ec;
547      }
548    else if (rs->source)
549      {
550         common = &rs->source->common;
551         src_ec = rs->source->common.ec;
552      }
553
554    if (!common || !src_ec)
555      {
556         ERR("CHANGED_BUFF: no common(%p) or src_ec(%p)", common, src_ec);
557         return EINA_FALSE;
558      }
559
560    DBG("CHANGED_BUFF: src_ec(%p) bind_ec(%p) buffer_transform(%d)",
561        src_ec, rs->bind_ec, e_comp_wl_output_buffer_transform_get(src_ec));
562
563    /* if unbinded, buffer_transform should be 0 for consumer to composite buffers.
564     * Otherwise, we skip sending a change_buffer event because buffer is not ready.
565     */
566    if (!rs->bind_ec && e_comp_wl_output_buffer_transform_get(src_ec))
567      {
568         RSMINF("CHANGED_BUFF skiped: buffer not ready", NULL, NULL, "SURFACE", rs);
569         return EINA_TRUE;
570      }
571
572    send = _remote_surface_changed_buff_ev_filter_check(rs, buff_type);
573    if (send)
574      {
575         if (buff)
576           {
577              rbuff_res = e_comp_wl_tbm_remote_buffer_get(rs->wl_tbm, buff->resource);
578              EINA_SAFETY_ON_NULL_RETURN_VAL(rbuff_res, EINA_FALSE);
579
580              rbuff = _e_comp_wl_remote_buffer_get(rs, rbuff_res);
581              EINA_SAFETY_ON_NULL_RETURN_VAL(rbuff, EINA_FALSE);
582
583              tbm = rbuff->resource;
584              EINA_SAFETY_ON_NULL_RETURN_VAL(tbm, EINA_FALSE);
585
586              if ((ref_set) &&
587                  (rs->version >= 2)) /* WORKAROUND for 3.0: old version wayland-scanner can't generation since macro. TIZEN_REMOTE_SURFACE_RELEASE_SINCE_VERSION */
588                e_comp_wl_buffer_reference(&rbuff->ref, buff);
589           }
590
591         if (rs->version >= TIZEN_REMOTE_SURFACE_CHANGED_BUFFER_SINCE_VERSION)
592           {
593              if (rs->req_curr_buff.set)
594                {
595                   /* example of option list:
596                    *  [0] "curr_buff_req_serial"
597                    *  [1] "257"
598                    *  [2] "opt_none"
599                    */
600                   wl_array_init(&opts);
601                   p = wl_array_add(&opts, 21);
602                   if (p) strncpy(p, "curr_buff_req_serial", 21);
603
604                   snprintf(tmp, sizeof(tmp), "%u", rs->req_curr_buff.serial);
605                   len = strlen(tmp) + 1;
606                   p = wl_array_add(&opts, len);
607                   if (p) strncpy(p, tmp, len);
608
609                   p = wl_array_add(&opts, 9);
610                   if (p) strncpy(p, "opt_none", 9);
611
612                   rs->req_curr_buff.set = EINA_FALSE;
613                   add_opts = EINA_TRUE;
614                }
615
616              RSMDBG("CHANGED_BUFF send:%d type:%u tbm:%p fd:%d(%d) add_opts:%d EV_FILTER(%d):%u",
617                     NULL, NULL, "SURFACE", rs,
618                     send, buff_type, tbm, img_file_fd, img_file_size, add_opts,
619                     rs->changed_buff_ev_filter.use,
620                     rs->changed_buff_ev_filter.filter);
621
622              tizen_remote_surface_send_changed_buffer(rs->resource,
623                                                       buff_type,
624                                                       tbm,
625                                                       img_file_fd,
626                                                       img_file_size,
627                                                       ecore_time_get() * 1000,
628                                                       add_opts ? &opts : NULL);
629           }
630         else
631           tizen_remote_surface_send_update_buffer(rs->resource,
632                                                   tbm,
633                                                   ecore_time_get() * 1000);
634      }
635
636    if (add_opts)
637      wl_array_release(&opts);
638
639    return send;
640 }
641
642 static Eina_Bool
643 _remote_surface_buff_send(E_Comp_Wl_Remote_Surface *rs)
644 {
645    enum tizen_remote_surface_buffer_type buff_type;
646    E_Comp_Wl_Remote_Provider *provider;
647    E_Comp_Wl_Remote_Source *source;
648    E_Comp_Wl_Buffer *buff = NULL;
649    char *img_path;
650    int fd = _rsm->dummy_fd;
651    off_t img_size = 0;
652    Eina_Bool res = EINA_FALSE;
653
654    E_Client *src_ec = NULL;
655
656    source = rs->source;
657    provider = rs->provider;
658
659    if (provider)
660      {
661         src_ec = provider->common.ec;
662         img_path = NULL;
663      }
664    else if (source)
665      {
666         src_ec = source->common.ec;
667         img_path = (char *)source->image_path;
668      }
669
670    EINA_SAFETY_ON_NULL_RETURN_VAL(src_ec, EINA_FALSE);
671
672    buff = e_pixmap_resource_get(src_ec->pixmap);
673    if (buff)
674      {
675         buff_type = TIZEN_REMOTE_SURFACE_BUFFER_TYPE_TBM;
676         res = EINA_TRUE;
677
678         /* TODO: if client wants to receive image file for the remote_surfac_provider,
679          * then makes image file from tbm buffer and sends information for that file.
680          * otherwise, just sends tbm buffer to the client.
681          */
682         res = _remote_surface_changed_buff_protocol_send(rs,
683                                                          buff_type,
684                                                          _rsm->dummy_fd,
685                                                          (unsigned int)img_size,
686                                                          EINA_FALSE,
687                                                          buff);
688      }
689    else
690      {
691         EINA_SAFETY_ON_NULL_RETURN_VAL(img_path, EINA_FALSE);
692
693         fd = open(img_path, O_RDONLY);
694         EINA_SAFETY_ON_FALSE_RETURN_VAL(fd != -1, EINA_FALSE);
695
696         img_size = lseek(fd, 0, SEEK_END);
697         EINA_SAFETY_ON_FALSE_GOTO(img_size > 0, close_fd);
698
699         buff_type = TIZEN_REMOTE_SURFACE_BUFFER_TYPE_IMAGE_FILE;
700         res = EINA_TRUE;
701
702         /* TODO: if client wants to receive image file for the remote_surfac_provider,
703          * then makes image file from tbm buffer and sends information for that file.
704          * otherwise, just sends tbm buffer to the client.
705          */
706         res = _remote_surface_changed_buff_protocol_send(rs,
707                                                          buff_type,
708                                                          fd,
709                                                          (unsigned int)img_size,
710                                                          EINA_FALSE,
711                                                          NULL);
712         close(fd);
713      }
714
715
716    return res;
717
718 close_fd:
719    close(fd);
720    return EINA_FALSE;
721 }
722
723 static void
724 _remote_surface_visible_set(E_Comp_Wl_Remote_Surface *remote_surface, Eina_Bool set)
725 {
726    E_Comp_Wl_Remote_Provider *provider;
727
728    if (remote_surface->visible == set) return;
729
730    remote_surface->visible = set;
731
732    RSMDBG("Switch visible:%d",
733           NULL, NULL,
734           "SURFACE", remote_surface, remote_surface->visible);
735
736    provider = remote_surface->provider;
737    if (!provider) return;
738
739    _remote_provider_visible_set(provider, set);
740 }
741
742 static void
743 _remote_surface_bind_client_set(E_Comp_Wl_Remote_Surface *remote_surface, E_Client *ec)
744 {
745    if (!remote_surface) return;
746
747    RSMINF("Set bind_ec:%p, bind_ref:%d",
748           NULL, NULL,
749           "SURFACE", remote_surface, ec, ec->remote_surface.bind_ref + 1);
750
751    remote_surface->bind_ec = ec;
752    remote_surface->bind_ec->remote_surface.bind_ref++;
753 }
754
755 static void
756 _remote_surface_bind_client_unset(E_Comp_Wl_Remote_Surface *remote_surface)
757 {
758    if (!remote_surface) return;
759
760    RSMINF("Unset bind_ec:%p, bind_ref:%d",
761           NULL, NULL,
762           "SURFACE", remote_surface, remote_surface->bind_ec,
763           remote_surface->bind_ec->remote_surface.bind_ref - 1);
764
765    remote_surface->bind_ec->remote_surface.bind_ref--;
766    remote_surface->bind_ec = NULL;
767 }
768
769 static void
770 _remote_surface_bind_client(E_Comp_Wl_Remote_Surface *remote_surface, E_Client *ec)
771 {
772    if (!remote_surface) return;
773    if ((ec) && (remote_surface->bind_ec == ec)) return;
774
775    /* clear previous binding */
776    if (remote_surface->bind_ec)
777      {
778         RSMINF("Clear previous bind_ec:%p",
779                NULL, NULL,
780                "SURFACE", remote_surface, remote_surface->bind_ec);
781
782         remote_surface->bind_ec->comp_data->pending.sx = 0;
783         remote_surface->bind_ec->comp_data->pending.sy = 0;
784         remote_surface->bind_ec->comp_data->pending.new_attach = EINA_TRUE;
785
786 #if 0   /* FIXME: no proper position to add below codes */
787         /* when unbinded, ignore_output_transform event is sended. And map should be disable. */
788         remote_surface->bind_ec->comp_data->pending.buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
789         remote_surface->bind_ec->comp_data->pending.buffer_viewport.changed = 0;
790         remote_surface->bind_ec->comp_data->scaler.buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
791         remote_surface->bind_ec->comp_data->scaler.buffer_viewport.changed = 0;
792         e_comp_wl_map_apply(remote_surface->bind_ec);
793 #endif
794
795         e_comp_wl_surface_attach(remote_surface->bind_ec, NULL);
796         e_comp_object_render_update_del(remote_surface->bind_ec->frame);
797
798         eina_hash_del(_rsm->bind_surface_hash, &remote_surface->bind_ec, remote_surface);
799         _remote_surface_bind_client_unset(remote_surface);
800
801         /* try to send latest buffer of the provider to the consumer when unbinding
802          * the remote surface to avoid showing old buffer on consumer's window for a while.
803          */
804         if (remote_surface->provider)
805           {
806              E_Comp_Wl_Buffer *buffer;
807
808              RSMINF("Try to send latest buffer of provider:%p(ec:%p)",
809                     NULL, NULL,
810                     "SURFACE", remote_surface,
811                     remote_surface->provider,
812                     remote_surface->provider->common.ec);
813
814              EINA_SAFETY_ON_NULL_GOTO(remote_surface->provider->common.ec, bind_ec_set);
815
816              buffer = e_pixmap_resource_get(remote_surface->provider->common.ec->pixmap);
817              EINA_SAFETY_ON_NULL_GOTO(buffer, bind_ec_set);
818
819              _remote_surface_changed_buff_protocol_send(remote_surface,
820                                                         TIZEN_REMOTE_SURFACE_BUFFER_TYPE_TBM,
821                                                         _rsm->dummy_fd,
822                                                         0,
823                                                         EINA_TRUE,
824                                                         buffer);
825           }
826      }
827
828 bind_ec_set:
829    if (ec)
830      {
831         if (e_object_is_del(E_OBJECT(ec)))
832           {
833              ERR("Trying to bind with deleted EC(%p)", ec);
834              return;
835           }
836
837         /* TODO: enable user geometry? */
838         e_policy_allow_user_geometry_set(ec, EINA_TRUE);
839         _remote_surface_bind_client_set(remote_surface, ec);
840         eina_hash_add(_rsm->bind_surface_hash, &remote_surface->bind_ec, remote_surface);
841
842         /* try to set latest buffer of the provider to bind_ec */
843         if (remote_surface->provider && remote_surface->provider->common.ec)
844           {
845              E_Comp_Wl_Buffer *buffer;
846
847              buffer = e_pixmap_resource_get(remote_surface->provider->common.ec->pixmap);
848              EINA_SAFETY_ON_NULL_RETURN(buffer);
849
850              _e_comp_wl_remote_surface_state_buffer_set(&remote_surface->bind_ec->comp_data->pending, buffer);
851
852              remote_surface->bind_ec->comp_data->pending.sx = 0;
853              remote_surface->bind_ec->comp_data->pending.sy = 0;
854              remote_surface->bind_ec->comp_data->pending.new_attach = EINA_TRUE;
855
856              remote_surface->bind_ec->comp_data->pending.buffer_viewport =
857                remote_surface->provider->common.ec->comp_data->scaler.buffer_viewport;
858
859              e_comp_wl_surface_commit(remote_surface->bind_ec);
860           }
861      }
862 }
863
864 static void
865 _remote_surface_ignore_output_transform_send(E_Comp_Wl_Remote_Common *common)
866 {
867    E_Comp_Wl_Remote_Surface *remote_surface;
868    const char *msg;
869
870    EINA_SAFETY_ON_NULL_RETURN(common);
871
872    if (eina_list_count(common->surfaces) != 1)
873      {
874         msg = "remote surface count = 0 or over 1";
875         goto ignore;
876      }
877
878    remote_surface = eina_list_nth(common->surfaces, 0);
879    if (remote_surface && remote_surface->bind_ec)
880      {
881         msg = "1 binding remote surface";
882         goto no_ignore;
883      }
884
885    if (common->is_offscreen)
886      {
887         msg = "offscreen";
888         goto ignore;
889      }
890    else
891      {
892         msg = "not offscreen";
893         goto no_ignore;
894      }
895
896 ignore:
897    if (common->ignore_output_transform != EINA_TRUE)
898      {
899         ELOGF("TRANSFORM", "ignore output transform: %s", common->ec, msg);
900         e_comp_screen_rotation_ignore_output_transform_send(common->ec, EINA_TRUE);
901         common->ignore_output_transform = EINA_TRUE;
902      }
903    return;
904
905 no_ignore:
906    if (common->ignore_output_transform != EINA_FALSE)
907      {
908         ELOGF("TRANSFORM", "not ignore output transform: %s", common->ec, msg);
909         e_comp_screen_rotation_ignore_output_transform_send(common->ec, EINA_FALSE);
910         common->ignore_output_transform = EINA_FALSE;
911      }
912    return;
913 }
914
915 static void
916 _remote_source_send_image_update(E_Comp_Wl_Remote_Source *source)
917 {
918    int fd = -1;
919    off_t image_size;
920    Eina_List *l;
921    E_Comp_Wl_Remote_Surface *remote_surface;
922
923    if (!source->image_path) return;
924
925    fd = open(source->image_path, O_RDONLY);
926    if (fd == -1)
927      {
928         ERR("%m");
929         return;
930      }
931
932    image_size = lseek(fd, 0, SEEK_END);
933    if (image_size <= 0)
934      {
935         close(fd);
936         return;
937      }
938
939    RSMDBG("send image fd(%d) path(%s) size(%jd)",
940           NULL, source->common.ec, "SOURCE", source, fd, source->image_path, (intmax_t)image_size);
941
942    EINA_LIST_FOREACH(source->common.surfaces, l, remote_surface)
943      {
944         if (remote_surface->version < TIZEN_REMOTE_SURFACE_CHANGED_BUFFER_SINCE_VERSION)
945           continue;
946
947         _remote_surface_changed_buff_protocol_send(remote_surface,
948                                                    TIZEN_REMOTE_SURFACE_BUFFER_TYPE_IMAGE_FILE,
949                                                    fd,
950                                                    (unsigned int)image_size,
951                                                    EINA_FALSE,
952                                                    NULL);
953      }
954
955    close(fd);
956 }
957
958 typedef struct
959 {
960    void *shm_buffer_ptr;
961    int shm_buffer_stride;
962    int shm_buffer_h;
963    unsigned int shm_buffer_format;
964    struct wl_shm_pool *shm_pool;
965
966    tbm_surface_h tbm_surface;
967
968    uint32_t transform;
969
970    int x, y, w, h;
971    E_Client *ec;
972    E_Client *parent;
973 } Capture_Data;
974
975 typedef struct {
976      void *shm_buffer_ptr;
977      int shm_buffer_stride;
978      int shm_buffer_h;
979      unsigned int shm_buffer_format;
980      struct wl_shm_pool *shm_pool;
981
982      tbm_surface_h tbm_surface;
983
984      uint32_t transform;
985
986      const char *image_path;
987      E_Client *ec;
988
989      Capture_Data *child_data;
990 } Thread_Data;
991
992 static E_Comp_Wl_Remote_Source *
993 _remote_source_find(E_Client *ec)
994 {
995    E_Comp_Wl_Remote_Source *source;
996
997    EINA_SAFETY_ON_NULL_RETURN_VAL(_rsm, NULL);
998    EINA_SAFETY_ON_NULL_RETURN_VAL(_rsm->source_hash, NULL);
999
1000    source = eina_hash_find(_rsm->source_hash, &ec);
1001    return source;
1002 }
1003
1004 static E_Comp_Wl_Remote_Source *
1005 _remote_source_get(E_Client *ec)
1006 {
1007    E_Comp_Wl_Remote_Source *source = NULL;
1008
1009    source = _remote_source_find(ec);
1010    if (!source)
1011      {
1012         if (e_object_is_del(E_OBJECT(ec)))
1013           return NULL;
1014
1015         source = E_NEW(E_Comp_Wl_Remote_Source, 1);
1016         if (!source) return NULL;
1017
1018         source->common.ec = ec;
1019         eina_hash_add(_rsm->source_hash, &ec, source);
1020      }
1021
1022    return source;
1023 }
1024
1025 static void
1026 _remote_source_destroy(E_Comp_Wl_Remote_Source *source)
1027 {
1028    E_Comp_Wl_Remote_Surface *remote_surface;
1029    if (!source) return;
1030
1031    RSMDBG("remote source destroy", NULL, source->common.ec,"SOURCE", source);
1032
1033    if (source->th)
1034      {
1035         RSMDBG("IMG save is cancelled. th:%p pending destroy",
1036                source->common.ec->pixmap, source->common.ec, "SOURCE",
1037                source, source->th);
1038         ecore_thread_cancel(source->th);
1039         source->deleted = EINA_TRUE;
1040         return;
1041      }
1042
1043    if (source->ref_as_child > 0)
1044      {
1045         RSMDBG("Parent IMG save is running. ref_as_child:%d pending destroy",
1046                source->common.ec->pixmap, source->common.ec, "SOURCE",
1047                source, source->ref_as_child);
1048         source->deleted = EINA_TRUE;
1049         return;
1050      }
1051
1052    if (_rsm)
1053      eina_hash_del_by_data(_rsm->source_hash, source);
1054
1055    EINA_LIST_FREE(source->common.surfaces, remote_surface)
1056      {
1057         if (remote_surface->source == source)
1058           {
1059              remote_surface->source = NULL;
1060              tizen_remote_surface_send_missing(remote_surface->resource);
1061           }
1062      }
1063
1064    /* is it ok without client's ack ?*/
1065    if (source->image_path)
1066      {
1067         if (!e_config->hold_prev_win_img)
1068           {
1069              RSMDBG("IMG del %s", NULL, source->common.ec, "SOURCE", source, source->image_path);
1070              ecore_file_remove(source->image_path);
1071           }
1072         eina_stringshare_del(source->image_path);
1073      }
1074
1075    E_FREE(source);
1076 }
1077
1078 static pixman_format_code_t
1079 _remote_source_image_data_pixman_format_get_from_tbm_surface(tbm_format format)
1080 {
1081    switch(format)
1082      {
1083       case TBM_FORMAT_ARGB8888: return PIXMAN_a8r8g8b8;
1084       case TBM_FORMAT_XRGB8888: return PIXMAN_x8r8g8b8;
1085       default:                  return PIXMAN_x8r8g8b8;
1086      }
1087 }
1088
1089 static pixman_format_code_t
1090 _remote_source_image_data_pixman_format_get_from_shm_buffer(uint32_t format)
1091 {
1092    switch(format)
1093      {
1094       case WL_SHM_FORMAT_ARGB8888: return PIXMAN_a8r8g8b8;
1095       case WL_SHM_FORMAT_XRGB8888: return PIXMAN_x8r8g8b8;
1096       default:                     return PIXMAN_x8r8g8b8;
1097      }
1098 }
1099
1100 static tbm_surface_h
1101 _remote_source_image_data_transform(Thread_Data *td, int w, int h)
1102 {
1103    // for base
1104    tbm_surface_h transform_surface = NULL;
1105    tbm_surface_info_s info;
1106    int tw = 0, th = 0;
1107    pixman_image_t *src_img = NULL, *dst_img = NULL;
1108    pixman_format_code_t src_format, dst_format;
1109    pixman_transform_t t;
1110    struct pixman_f_transform ft;
1111    unsigned char *src_ptr = NULL, *dst_ptr = NULL;
1112    int c = 0, s = 0, tx = 0, ty = 0;
1113
1114    // for child
1115    tbm_surface_h c_transform_surface = NULL;
1116    tbm_surface_info_s c_info;
1117    pixman_image_t *c_src_img = NULL, *c_dst_img = NULL;
1118    pixman_format_code_t c_src_format, c_dst_format;
1119    pixman_transform_t c_t;
1120    struct pixman_f_transform c_ft;
1121    unsigned char *c_src_ptr = NULL, *c_dst_ptr = NULL;
1122    int c_x, c_y, c_w, c_h;
1123    int c_tx, c_ty, c_tw, c_th;
1124
1125    EINA_SAFETY_ON_NULL_RETURN_VAL(td, NULL);
1126
1127    if (td->transform > WL_OUTPUT_TRANSFORM_270) return NULL;
1128
1129    if (td->tbm_surface)
1130      {
1131         src_format = _remote_source_image_data_pixman_format_get_from_tbm_surface(tbm_surface_get_format(td->tbm_surface));
1132         dst_format = src_format;
1133
1134         tbm_surface_map(td->tbm_surface, TBM_SURF_OPTION_READ, &info);
1135         src_ptr = info.planes[0].ptr;
1136
1137         src_img = pixman_image_create_bits(src_format, w, h, (uint32_t*)src_ptr, info.planes[0].stride);
1138         EINA_SAFETY_ON_NULL_GOTO(src_img, clean_up);
1139      }
1140    else if (td->shm_buffer_ptr)
1141      {
1142         src_format = _remote_source_image_data_pixman_format_get_from_shm_buffer(td->shm_buffer_format);
1143         dst_format = src_format;
1144
1145         src_ptr = td->shm_buffer_ptr;
1146         src_img = pixman_image_create_bits(src_format, w, h, (uint32_t*)src_ptr, w * 4);
1147         EINA_SAFETY_ON_NULL_GOTO(src_img, clean_up);
1148      }
1149    else
1150      {
1151         ERR("invalid source buffer");
1152         return NULL;
1153      }
1154
1155    if (td->transform == WL_OUTPUT_TRANSFORM_90)
1156      {
1157         c = 0, s = -1, tx = -h;
1158         tw = h, th = w;
1159      }
1160    else if (td->transform == WL_OUTPUT_TRANSFORM_180)
1161      {
1162         c = -1, s = 0, tx = -w, ty = -h;
1163         tw = w, th = h;
1164      }
1165    else if (td->transform == WL_OUTPUT_TRANSFORM_270)
1166      {
1167         c = 0, s = 1, ty = -w;
1168         tw = h, th = w;
1169      }
1170    else
1171      {
1172         c = 1, s = 0;
1173         tw = w, th = h;
1174      }
1175
1176    transform_surface = tbm_surface_create(tw, th, tbm_surface_get_format(td->tbm_surface));
1177    EINA_SAFETY_ON_NULL_GOTO(transform_surface, clean_up);
1178
1179    tbm_surface_map(transform_surface, TBM_SURF_OPTION_WRITE, &info);
1180    dst_ptr = info.planes[0].ptr;
1181
1182    dst_img = pixman_image_create_bits(dst_format, tw, th, (uint32_t*)dst_ptr, info.planes[0].stride);
1183    EINA_SAFETY_ON_NULL_GOTO(dst_img, clean_up);
1184
1185    pixman_f_transform_init_identity(&ft);
1186    pixman_f_transform_translate(&ft, NULL, tx, ty);
1187    pixman_f_transform_rotate(&ft, NULL, c, s);
1188
1189    pixman_transform_from_pixman_f_transform(&t, &ft);
1190    pixman_image_set_transform(src_img, &t);
1191
1192    pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0, 0, 0, tw, th);
1193
1194    // for child data
1195    if (td->child_data)
1196      {
1197         c_x = td->child_data->x;
1198         c_y = td->child_data->y;
1199         c_w = td->child_data->w;
1200         c_h = td->child_data->h;
1201
1202         c_tx = 0;
1203         c_ty = 0;
1204         c_tw = c_w;
1205         c_th = c_h;
1206
1207         if (td->child_data->tbm_surface)
1208           {
1209              c_src_format = _remote_source_image_data_pixman_format_get_from_tbm_surface(tbm_surface_get_format(td->child_data->tbm_surface));
1210              c_dst_format = c_src_format;
1211
1212              tbm_surface_map(td->child_data->tbm_surface, TBM_SURF_OPTION_READ, &c_info);
1213              c_src_ptr = c_info.planes[0].ptr;
1214
1215              c_src_img = pixman_image_create_bits(c_src_format, c_w, c_h, (uint32_t*)c_src_ptr, c_info.planes[0].stride);
1216              EINA_SAFETY_ON_NULL_GOTO(c_src_img, clean_up);
1217           }
1218         else if (td->child_data->shm_buffer_ptr)
1219           {
1220              c_src_format = _remote_source_image_data_pixman_format_get_from_shm_buffer(td->child_data->shm_buffer_format);
1221              c_dst_format = c_src_format;
1222
1223              c_src_ptr = td->child_data->shm_buffer_ptr;
1224              c_src_img = pixman_image_create_bits(c_src_format, c_w, c_h, (uint32_t*)c_src_ptr, c_w * 4);
1225              EINA_SAFETY_ON_NULL_GOTO(c_src_img, clean_up);
1226           }
1227         else
1228           {
1229              ERR("invalid source buffer");
1230              goto clean_up;
1231           }
1232
1233         if (td->child_data->transform == WL_OUTPUT_TRANSFORM_90)
1234           {
1235              c = 0, s = -1, c_tx = -c_h;
1236              c_tw = c_h, c_th = c_w;
1237           }
1238         else if (td->child_data->transform == WL_OUTPUT_TRANSFORM_180)
1239           {
1240              c = -1, s = 0, c_tx = -c_w, c_ty = -c_h;
1241              c_tw = c_w, c_th = c_h;
1242           }
1243         else if (td->child_data->transform == WL_OUTPUT_TRANSFORM_270)
1244           {
1245              c = 0, s = 1, c_ty = -c_w;
1246              c_tw = c_h, c_th = c_w;
1247           }
1248         else
1249           {
1250              c = 1, s = 0;
1251              c_tw = c_w, c_th = c_h;
1252           }
1253
1254         c_transform_surface = tbm_surface_create(c_tw, c_th, tbm_surface_get_format(td->child_data->tbm_surface));
1255         EINA_SAFETY_ON_NULL_GOTO(c_transform_surface, clean_up);
1256
1257         tbm_surface_map(c_transform_surface, TBM_SURF_OPTION_WRITE, &c_info);
1258         c_dst_ptr = c_info.planes[0].ptr;
1259
1260         c_dst_img = pixman_image_create_bits(c_dst_format, c_tw, c_th, (uint32_t*)c_dst_ptr, c_info.planes[0].stride);
1261         EINA_SAFETY_ON_NULL_GOTO(c_dst_img, clean_up);
1262
1263         pixman_f_transform_init_identity(&c_ft);
1264         pixman_f_transform_translate(&c_ft, NULL, c_tx, c_ty);
1265         pixman_f_transform_rotate(&c_ft, NULL, c, s);
1266
1267         pixman_transform_from_pixman_f_transform(&c_t, &c_ft);
1268         pixman_image_set_transform(c_src_img, &c_t);
1269
1270         pixman_image_composite(PIXMAN_OP_SRC, c_src_img, NULL, c_dst_img, 0, 0, 0, 0, 0, 0, c_tw, c_th);
1271
1272         RSMDBG("image composite with child. child(win:%zx, ec:%p)",
1273                td->ec->pixmap, td->ec, "SOURCE", NULL,
1274                e_client_util_win_get(td->child_data->ec), td->child_data->ec);
1275
1276         pixman_image_composite(PIXMAN_OP_OVER, c_dst_img, NULL, dst_img, 0, 0, 0, 0, c_x, c_y, tw, th);
1277      }
1278
1279 clean_up:
1280    if (td->child_data)
1281      {
1282         if (c_src_ptr && td->child_data->tbm_surface) tbm_surface_unmap(td->child_data->tbm_surface);
1283         if (c_dst_ptr) tbm_surface_unmap(c_transform_surface);
1284
1285         if (c_transform_surface)
1286           {
1287              tbm_surface_destroy(c_transform_surface);
1288              c_transform_surface = NULL;
1289           }
1290
1291         if (c_src_img) pixman_image_unref(c_src_img);
1292         if (c_dst_img) pixman_image_unref(c_dst_img);
1293      }
1294
1295    if (src_ptr && td->tbm_surface) tbm_surface_unmap(td->tbm_surface);
1296    if (dst_ptr) tbm_surface_unmap(transform_surface);
1297
1298    // if dst_img is null, then trasform is failed. So we should destroy transform_surface.
1299    if (!dst_img)
1300      {
1301         tbm_surface_destroy(transform_surface);
1302         transform_surface = NULL;
1303      }
1304
1305    if (src_img) pixman_image_unref(src_img);
1306    if (dst_img) pixman_image_unref(dst_img);
1307
1308    return transform_surface;
1309 }
1310
1311 static const char *
1312 _remote_source_image_data_save(Thread_Data *td, const char *path, const char *name)
1313 {
1314    void *shm_buffer_ptr = NULL;
1315    tbm_surface_h tbm_surface = NULL, transform_surface = NULL;
1316    int w, h, stride;
1317    void *ptr;
1318    char dest[2048], fname[2048];
1319    const char *dupname;
1320    int id = 0, ret = 0;
1321
1322    EINA_SAFETY_ON_NULL_RETURN_VAL(td, NULL);
1323    EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
1324    EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
1325
1326    snprintf(fname, sizeof(fname), "%s-%d", name, id);
1327    snprintf(dest, sizeof(dest), "%s/%s.png", path, fname);
1328    while (ecore_file_exists(dest))
1329      {
1330         snprintf(fname, sizeof(fname), "%s-%d", name, ++id);
1331         snprintf(dest, sizeof(dest), "%s/%s.png", path, fname);
1332      }
1333
1334    shm_buffer_ptr = td->shm_buffer_ptr;
1335    tbm_surface = td->tbm_surface;
1336
1337    if (shm_buffer_ptr)
1338      {
1339          stride = td->shm_buffer_stride;
1340          w = stride / 4;
1341          h = td->shm_buffer_h;
1342
1343          transform_surface = _remote_source_image_data_transform(td, w, h);
1344          if (transform_surface)
1345            {
1346               tbm_surface_info_s info;
1347               tbm_surface_map(transform_surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1348               ptr = info.planes[0].ptr;
1349            }
1350          else
1351            {
1352               ptr = shm_buffer_ptr;
1353               EINA_SAFETY_ON_NULL_RETURN_VAL(ptr, NULL);
1354            }
1355
1356          dupname = strdup(fname);
1357          ret = tbm_surface_internal_capture_shm_buffer(ptr, w, h, stride, path, dupname, "png");
1358
1359          if (transform_surface)
1360            {
1361               tbm_surface_unmap(transform_surface);
1362               tbm_surface_destroy(transform_surface);
1363            }
1364
1365          free((void*)dupname);
1366          if (!ret)
1367            return NULL;
1368      }
1369    else if (tbm_surface)
1370      {
1371          w = tbm_surface_get_width(tbm_surface);
1372          EINA_SAFETY_ON_FALSE_RETURN_VAL(w > 0, NULL);
1373          h = tbm_surface_get_height(tbm_surface);
1374          EINA_SAFETY_ON_FALSE_RETURN_VAL(h > 0, NULL);
1375
1376          transform_surface = _remote_source_image_data_transform(td, w, h);
1377          if (transform_surface)
1378            tbm_surface = transform_surface;
1379
1380          RSMDBG("image save. transform_surface=%p transform=%d", td->ec->pixmap, td->ec, "SOURCE", NULL, transform_surface, td->transform);
1381
1382          dupname = strdup(fname);
1383          ret = tbm_surface_internal_capture_buffer(tbm_surface, path, dupname, "png");
1384
1385          if (transform_surface)
1386            tbm_surface_destroy(transform_surface);
1387
1388          free((void*)dupname);
1389          if (!ret)
1390            return NULL;
1391      }
1392    else
1393      {
1394          return NULL;
1395      }
1396
1397    return strdup(dest);
1398 }
1399
1400 static void
1401 _remote_source_child_data_release(Thread_Data *td)
1402 {
1403    E_Comp_Wl_Remote_Source *source;
1404    E_Client *ec;
1405
1406    if (!td) return;
1407    if (!td->child_data) return;
1408
1409    if (td->child_data->tbm_surface)
1410      tbm_surface_internal_unref(td->child_data->tbm_surface);
1411
1412    if (td->child_data->shm_pool)
1413      wl_shm_pool_unref(td->child_data->shm_pool);
1414
1415    ec = td->child_data->ec;
1416    if (!ec) return;
1417
1418    source = _remote_source_find(ec);
1419    if (!source) return;
1420
1421    e_comp_wl_buffer_reference(&source->buffer_ref, NULL);
1422    source->ref_as_child--;
1423    RSMDBG("Child data release. ref_as_child:%d", NULL, ec, "SOURCE", source, source->ref_as_child);
1424
1425    if ((source->deleted) || (e_object_is_del(E_OBJECT(ec))))
1426      {
1427         _remote_source_destroy(source);
1428      }
1429
1430    e_object_unref(E_OBJECT(ec));
1431
1432    E_FREE(td->child_data);
1433 }
1434
1435 static Eina_Bool
1436 _remote_source_child_data_create(Thread_Data *td, E_Client *ec)
1437 {
1438    Capture_Data *capture_data;
1439    E_Comp_Wl_Remote_Source *source;
1440    E_Comp_Wl_Buffer *buffer = NULL;
1441    struct wl_shm_buffer *shm_buffer;
1442    struct wl_shm_pool *shm_pool;
1443    void *shm_buffer_ptr = NULL;
1444    int shm_buffer_stride, shm_buffer_h;
1445    tbm_surface_h tbm_surface;
1446
1447    if (!td) return EINA_FALSE;
1448    if (!ec) return EINA_FALSE;
1449
1450    source = _remote_source_get(ec);
1451    if (!source) return EINA_FALSE;
1452
1453    if (!(buffer = e_pixmap_resource_get(ec->pixmap))) return EINA_FALSE;
1454
1455    if (td->child_data)
1456      {
1457         // how do we handle this case?
1458         _remote_source_child_data_release(td);
1459      }
1460
1461    capture_data = E_NEW(Capture_Data, 1);
1462    if (!capture_data) return EINA_FALSE;
1463
1464    e_object_ref(E_OBJECT(ec));
1465    capture_data->ec = ec;
1466
1467    capture_data->x = ec->x;
1468    capture_data->y = ec->y;
1469    capture_data->w = ec->w;
1470    capture_data->h = ec->h;
1471
1472    capture_data->transform = e_comp_wl_output_buffer_transform_get(ec);
1473
1474    e_comp_wl_buffer_reference(&source->buffer_ref, buffer);
1475    switch (buffer->type)
1476      {
1477       case E_COMP_WL_BUFFER_TYPE_SHM:
1478          shm_buffer = wl_shm_buffer_get(buffer->resource);
1479          if (!shm_buffer) goto end;
1480
1481          shm_buffer_ptr = wl_shm_buffer_get_data(shm_buffer);
1482          if (!shm_buffer_ptr) goto end;
1483
1484          shm_buffer_stride = wl_shm_buffer_get_stride(shm_buffer);
1485          if (shm_buffer_stride <= 0) goto end;
1486
1487          shm_buffer_h = wl_shm_buffer_get_height(shm_buffer);
1488          if (shm_buffer_h <= 0) goto end;
1489
1490          shm_pool = wl_shm_buffer_ref_pool(shm_buffer);
1491          if (!shm_pool) goto end;
1492
1493          capture_data->shm_buffer_format = wl_shm_buffer_get_format(shm_buffer);
1494          capture_data->shm_buffer_ptr = shm_buffer_ptr;
1495          capture_data->shm_buffer_stride = shm_buffer_stride;
1496          capture_data->shm_buffer_h = shm_buffer_h;
1497          capture_data->shm_pool = shm_pool;
1498          break;
1499
1500       case E_COMP_WL_BUFFER_TYPE_NATIVE:
1501       case E_COMP_WL_BUFFER_TYPE_VIDEO:
1502          tbm_surface = wayland_tbm_server_get_surface(e_comp_wl->tbm.server, buffer->resource);
1503          if (!tbm_surface) goto end;
1504
1505          tbm_surface_internal_ref(tbm_surface);
1506          capture_data->tbm_surface = tbm_surface;
1507          break;
1508
1509       case E_COMP_WL_BUFFER_TYPE_TBM:
1510          tbm_surface = buffer->tbm_surface;
1511          if (!tbm_surface) goto end;
1512
1513          tbm_surface_internal_ref(tbm_surface);
1514          capture_data->tbm_surface = tbm_surface;
1515          break;
1516
1517       default:
1518          goto end;
1519      }
1520
1521    td->child_data = capture_data;
1522    source->ref_as_child++;
1523    RSMDBG("Child data create. ref_as_child:%d", NULL, ec, "SOURCE", source, source->ref_as_child);
1524    return EINA_TRUE;
1525
1526 end:
1527    e_comp_wl_buffer_reference(&source->buffer_ref, NULL);
1528    e_object_unref(E_OBJECT(ec));
1529    E_FREE(capture_data);
1530
1531    return EINA_FALSE;
1532 }
1533
1534 static Eina_Bool
1535 _remote_source_child_is_placed_above(E_Client *child, E_Client *ec)
1536 {
1537    E_Client *above = NULL;
1538
1539    for (above = e_client_above_get(ec); above; above = e_client_above_get(above))
1540      {
1541         if (above == child)
1542           return EINA_TRUE;
1543      }
1544
1545    return EINA_FALSE;
1546 }
1547
1548 static Eina_Bool
1549 _remote_source_child_data_check(Thread_Data *td)
1550 {
1551    Eina_List *list, *l;
1552    E_Client *ec = NULL;
1553    E_Client *child_ec = NULL;
1554
1555    ec = td->ec;
1556    if (!ec) return EINA_FALSE;
1557
1558    list = eina_list_clone(ec->transients);
1559
1560    EINA_LIST_FOREACH(list, l, child_ec)
1561      {
1562         if (!child_ec->comp_data) continue;
1563         if (!child_ec->comp_data->mapped) continue;
1564
1565         if (child_ec->iconic && child_ec->exp_iconify.by_client)
1566           continue;
1567
1568         if (child_ec->bg_state)
1569           continue;
1570
1571         if (!e_policy_client_is_keyboard(child_ec))
1572           continue;
1573
1574         if (!_remote_source_child_is_placed_above(child_ec, ec))
1575           continue;
1576
1577         _remote_source_child_data_create(td, child_ec);
1578         break;
1579      }
1580
1581    eina_list_free(list);
1582
1583    return EINA_TRUE;
1584 }
1585
1586 static void
1587 _remote_source_save(void *data, Ecore_Thread *th)
1588 {
1589    Thread_Data *td;
1590    E_Client *ec;
1591    char name[1024];
1592    char dest_dir[1024];
1593    const char *dest_path, *dupname, *dupdir;
1594    char *run_dir;
1595
1596    if (!(td = data)) return;
1597
1598    ec = td->ec;
1599    if (!ec) return;
1600    if (ecore_thread_check(th)) return;
1601
1602    run_dir = e_util_env_get("XDG_RUNTIME_DIR");
1603    if (!run_dir) return;
1604
1605    snprintf(dest_dir, sizeof(dest_dir), "%s/.e-img", run_dir);
1606    E_FREE(run_dir);
1607
1608    if (!ecore_file_exists(dest_dir))
1609      ecore_file_mkdir(dest_dir);
1610    dupdir = strdup(dest_dir);
1611
1612    snprintf(name, sizeof(name),
1613             "win_%d_%u",
1614             ec->netwm.pid,
1615             e_pixmap_res_id_get(ec->pixmap));
1616
1617    dupname = strdup(name);
1618
1619    dest_path = _remote_source_image_data_save(td, dupdir, dupname);
1620    if (dest_path)
1621      {
1622         RSMDBG("IMG save success. th:%p file:%s", NULL, ec, "SOURCE", NULL, th, dest_path);
1623         td->image_path = eina_stringshare_add(dest_path);
1624         free((void*)dest_path);
1625      }
1626    else
1627      {
1628         RSMDBG("IMG save failure. th:%p file:%s", NULL, ec, "SOURCE", NULL, th, dest_path);
1629      }
1630    free((void*)dupname);
1631    free((void*)dupdir);
1632 }
1633
1634 static void
1635 _remote_source_save_done(void *data, Ecore_Thread *th)
1636 {
1637    Thread_Data *td = data;
1638    E_Client *ec;
1639    E_Comp_Wl_Remote_Source *source = NULL;
1640
1641    if (!td) return;
1642
1643    ec = td->ec;
1644    if (!ec) goto end;
1645
1646    source = _remote_source_find(ec);
1647    if (!source) goto end;
1648
1649    RSMDBG("IMG save DONE. th:%p", NULL, ec, "SOURCE", source, th);
1650
1651    if (th == source->th)
1652      {
1653         source->th = NULL;
1654         e_comp_wl_buffer_reference(&source->buffer_ref, NULL);
1655
1656         if ((source->deleted) || (e_object_is_del(E_OBJECT(ec))))
1657           {
1658              _remote_source_destroy(source);
1659              goto end;
1660           }
1661
1662         if (!td->image_path) goto end;
1663
1664         RSMDBG("Source save DONE path(%s)", source->common.ec->pixmap, source->common.ec,
1665                "SOURCE", source, td->image_path);
1666
1667         /* remove previous file */
1668         if ((source->image_path) && (e_util_strcmp(source->image_path, td->image_path)))
1669           {
1670              if (!e_config->hold_prev_win_img)
1671                {
1672                   RSMDBG("IMG del %s", ec->pixmap, ec, "SOURCE", source, source->image_path);
1673                   ecore_file_remove(source->image_path);
1674                }
1675              eina_stringshare_del(source->image_path);
1676           }
1677         source->image_path = eina_stringshare_add(td->image_path);
1678         _remote_source_send_image_update(source);
1679
1680         ec->saved_img = EINA_TRUE;
1681      }
1682    else
1683      {
1684         RSMDBG("IMG not matched. del. src:%s td:%s", ec->pixmap, ec, "SOURCE",
1685                source, source->image_path, td->image_path);
1686         ecore_file_remove(td->image_path);
1687      }
1688 end:
1689    if (td->child_data)
1690      {
1691         _remote_source_child_data_release(td);
1692      }
1693
1694    if (ec)
1695      e_object_unref(E_OBJECT(ec));
1696    if (td->tbm_surface)
1697      tbm_surface_internal_unref(td->tbm_surface);
1698    if (td->shm_pool)
1699      wl_shm_pool_unref(td->shm_pool);
1700
1701    eina_stringshare_del(td->image_path);
1702    E_FREE(td);
1703 }
1704
1705 static void
1706 _remote_source_save_cancel(void *data, Ecore_Thread *th)
1707 {
1708    Thread_Data *td = data;
1709    E_Client *ec;
1710    E_Comp_Wl_Remote_Source *source = NULL;
1711    Eina_Bool del = EINA_FALSE;
1712
1713    if (!td) return;
1714
1715    ec = td->ec;
1716    if (!ec) goto end;
1717
1718    source = _remote_source_find(ec);
1719    if (!source) goto end;
1720
1721    RSMDBG("IMG save CANCELED. th:%p %s", source->common.ec->pixmap, source->common.ec,
1722           "SOURCE", source, th, td->image_path);
1723
1724    if (th == source->th)
1725      {
1726         source->th = NULL;
1727         e_comp_wl_buffer_reference(&source->buffer_ref, NULL);
1728
1729         if (td->child_data)
1730           {
1731              _remote_source_child_data_release(td);
1732           }
1733      }
1734
1735    if (!e_config->hold_prev_win_img)
1736      {
1737         if (td->image_path)
1738           {
1739              RSMDBG("IMG del %s", NULL, source->common.ec, "SOURCE", source, td->image_path);
1740              ecore_file_remove(td->image_path);
1741           }
1742      }
1743
1744    if (source->deleted)
1745      {
1746         _remote_source_destroy(source);
1747         del = EINA_TRUE;
1748      }
1749 end:
1750    if (ec)
1751      e_object_unref(E_OBJECT(ec));
1752    if (td->tbm_surface)
1753      tbm_surface_internal_unref(td->tbm_surface);
1754    if (td->shm_pool)
1755      wl_shm_pool_unref(td->shm_pool);
1756
1757    eina_stringshare_del(td->image_path);
1758    E_FREE(td);
1759
1760    if ((!del) && (source))
1761      {
1762         if (source->defer_img_save)
1763           {
1764              RSMDBG("IMG save retry", NULL, source->common.ec, "SOURCE", source);
1765              _remote_source_save_start(source);
1766              source->defer_img_save = EINA_FALSE;
1767           }
1768      }
1769 }
1770
1771 /* Stop capture job when the window is uniconified while capturing
1772  * on another thread.
1773  *
1774  * If a commit event occurs for iconified window, then does cancellation
1775  * for capture thread and set the defer_img_save to true to restart the
1776  * capture thread again for new window buffer.
1777  *
1778  * It can be using ecore_thread_check API to check whether the capture
1779  * job is done.
1780  */
1781 static void
1782 _remote_source_save_start(E_Comp_Wl_Remote_Source *source)
1783 {
1784    E_Client *ec;
1785    E_Comp_Wl_Buffer *buffer = NULL;
1786    Thread_Data *td;
1787    struct wl_shm_buffer *shm_buffer;
1788    struct wl_shm_pool *shm_pool;
1789    void *shm_buffer_ptr = NULL;
1790    int shm_buffer_stride, shm_buffer_h;
1791    tbm_surface_h tbm_surface;
1792
1793    if (!(ec = source->common.ec)) return;
1794    if (!(buffer = e_pixmap_resource_get(ec->pixmap))) return;
1795    if (!e_config->save_win_buffer) return;
1796
1797    if (source->th)
1798      {
1799         RSMDBG("ALREADY doing capture", NULL, source->common.ec, "SOURCE", source);
1800         return;
1801      }
1802
1803    td = E_NEW(Thread_Data, 1);
1804    if (!td) return;
1805
1806    e_object_ref(E_OBJECT(ec));
1807    td->ec = ec;
1808
1809    td->transform = e_comp_wl_output_buffer_transform_get(ec);
1810
1811    e_comp_wl_buffer_reference(&source->buffer_ref, buffer);
1812    switch (buffer->type)
1813      {
1814       case E_COMP_WL_BUFFER_TYPE_SHM:
1815          shm_buffer = wl_shm_buffer_get(buffer->resource);
1816          if (!shm_buffer) goto end;
1817
1818          shm_buffer_ptr = wl_shm_buffer_get_data(shm_buffer);
1819          if (!shm_buffer_ptr) goto end;
1820
1821          shm_buffer_stride = wl_shm_buffer_get_stride(shm_buffer);
1822          if (shm_buffer_stride <= 0) goto end;
1823
1824          shm_buffer_h = wl_shm_buffer_get_height(shm_buffer);
1825          if (shm_buffer_h <= 0) goto end;
1826
1827          shm_pool = wl_shm_buffer_ref_pool(shm_buffer);
1828          if (!shm_pool) goto end;
1829
1830          td->shm_buffer_format = wl_shm_buffer_get_format(shm_buffer);
1831          td->shm_buffer_ptr = shm_buffer_ptr;
1832          td->shm_buffer_stride = shm_buffer_stride;
1833          td->shm_buffer_h = shm_buffer_h;
1834          td->shm_pool = shm_pool;
1835          break;
1836       case E_COMP_WL_BUFFER_TYPE_NATIVE:
1837       case E_COMP_WL_BUFFER_TYPE_VIDEO:
1838          tbm_surface = wayland_tbm_server_get_surface(e_comp_wl->tbm.server, buffer->resource);
1839          if (!tbm_surface) goto end;
1840
1841          tbm_surface_internal_ref(tbm_surface);
1842          td->tbm_surface = tbm_surface;
1843          break;
1844       case E_COMP_WL_BUFFER_TYPE_TBM:
1845          tbm_surface = buffer->tbm_surface;
1846          if (!tbm_surface) goto end;
1847
1848          tbm_surface_internal_ref(tbm_surface);
1849          td->tbm_surface = tbm_surface;
1850          break;
1851       default:
1852          goto end;
1853      }
1854
1855    _remote_source_child_data_check(td);
1856
1857    source->th = ecore_thread_run(_remote_source_save,
1858                                  _remote_source_save_done,
1859                                  _remote_source_save_cancel,
1860                                  td);
1861    RSMDBG("IMG save START. th:%p", ec->pixmap, ec, "SOURCE", source, source->th);
1862    return;
1863 end:
1864    e_comp_wl_buffer_reference(&source->buffer_ref, NULL);
1865    e_object_unref(E_OBJECT(ec));
1866
1867    _remote_source_child_data_release(td);
1868
1869    E_FREE(td);
1870 }
1871
1872 static void
1873 _remote_source_save_start_cancel(E_Client *ec)
1874 {
1875    E_Comp_Wl_Remote_Source *source;
1876
1877    source = _remote_source_find(ec);
1878    if (!source) return;
1879    EINA_SAFETY_ON_FALSE_RETURN(ec == source->common.ec);
1880
1881    if (source->th)
1882      {
1883         RSMDBG("IMG save could be cancelled. UNICONIFY th:%p(cancel:%d) defer_img_save:%d iconic:%d del:%d ec_del:%d",
1884                ec->pixmap, ec, "SOURCE", source,
1885                source->th, ecore_thread_check(source->th),
1886                source->defer_img_save, ec->iconic,
1887                source->deleted, e_object_is_del(E_OBJECT(ec)));
1888         if (!ecore_thread_check(source->th) &&
1889             !source->deleted &&
1890             !e_object_is_del(E_OBJECT(ec)))
1891           {
1892              RSMDBG("IMG save CANCELLED.", ec->pixmap, ec, "SOURCE", source);
1893              ecore_thread_cancel(source->th);
1894           }
1895      }
1896 }
1897
1898 static void
1899 _remote_source_offscreen_set(E_Comp_Wl_Remote_Source *source, Eina_Bool set)
1900 {
1901    EINA_SAFETY_ON_NULL_RETURN(source);
1902    if (set)
1903      {
1904         source->offscreen_ref++;
1905         RSMDBG("Set offscreen offscreen_ref:%d",
1906                source->common.ec->pixmap, source->common.ec,
1907                "SOURCE", source, source->offscreen_ref);
1908
1909         if (source->offscreen_ref == 1)
1910           {
1911              _remote_surface_ignore_output_transform_send(&source->common);
1912              source->common.is_offscreen = EINA_TRUE;
1913
1914              source->common.ec->exp_iconify.not_raise = 1;
1915              if (!source->common.ec->exp_iconify.by_client)
1916                e_policy_wl_iconify_state_change_send(source->common.ec, 0);
1917
1918              RSMINF("Un-Set ICONIFY BY Remote_Surface", source->common.ec->pixmap, source->common.ec,
1919                     "SOURCE", source);
1920              e_client_uniconify(source->common.ec);
1921
1922              source->common.ec->exp_iconify.by_client = 0;
1923              source->common.ec->exp_iconify.skip_by_remote = 1;
1924
1925              EC_CHANGED(source->common.ec);
1926           }
1927      }
1928    else
1929      {
1930         if (!source->common.is_offscreen)
1931           return;
1932
1933         source->offscreen_ref--;
1934         RSMDBG("Unset offscreen offscreen_ref:%d",
1935                source->common.ec->pixmap, source->common.ec,
1936                "SOURCE", source, source->offscreen_ref);
1937
1938         if (source->offscreen_ref == 0)
1939           {
1940              _remote_surface_ignore_output_transform_send(&source->common);
1941              source->common.is_offscreen = EINA_FALSE;
1942              source->common.ec->exp_iconify.skip_by_remote = 0;
1943              EC_CHANGED(source->common.ec);
1944           }
1945      }
1946 }
1947
1948 static void
1949 _remote_surface_region_clear(E_Comp_Wl_Remote_Surface *remote_surface)
1950 {
1951    Eina_List *l;
1952    E_Comp_Wl_Remote_Region *region;
1953    if (!remote_surface) return;
1954
1955    EINA_LIST_FOREACH(remote_surface->regions, l, region)
1956      {
1957         _remote_region_mirror_clear(region);
1958      }
1959 }
1960
1961 static void
1962 _remote_surface_client_set(E_Client *ec, Eina_Bool set)
1963 {
1964    if (!ec) return;
1965    if ((e_object_is_del(E_OBJECT(ec)))) return;
1966
1967    ec->remote_surface.consumer = set;
1968 }
1969
1970 static void
1971 _remote_region_cb_mirror_del(void *data, Evas *e, Evas_Object *obj, void *event_info)
1972 {
1973    E_Comp_Wl_Remote_Region *region = data;
1974    if (!region->mirror) return;
1975
1976    region->mirror = NULL;
1977 }
1978
1979 static void
1980 _remote_region_cb_resource_destroy(struct wl_resource *resource)
1981 {
1982    E_Comp_Wl_Remote_Region *region;
1983
1984    region = wl_resource_get_user_data(resource);
1985    if (!region) return;
1986
1987    if (region->remote_surface)
1988      {
1989         if (region->remote_surface->provider)
1990           {
1991              _remote_provider_rect_del(region->remote_surface->provider,
1992                                        &region->geometry);
1993           }
1994         region->remote_surface->regions = eina_list_remove(region->remote_surface->regions,
1995                                                            region);
1996      }
1997
1998    if (region->mirror)
1999      {
2000         evas_object_event_callback_del_full(region->mirror, EVAS_CALLBACK_DEL, _remote_region_cb_mirror_del, region);
2001         evas_object_del(region->mirror);
2002      }
2003
2004    E_FREE(region);
2005 }
2006
2007 static void
2008 _remote_region_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
2009 {
2010    wl_resource_destroy(resource);
2011 }
2012
2013 static void
2014 _remote_region_cb_geometry_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
2015 {
2016    E_Comp_Wl_Remote_Region *region;
2017
2018    region = wl_resource_get_user_data(resource);
2019    if (!region) return;
2020
2021    region->geometry.x = x;
2022    region->geometry.y = y;
2023    region->geometry.w = w;
2024    region->geometry.h = h;
2025
2026    RSMDBG("Region %p geometry set (%d, %d) %dx%d",
2027           NULL, NULL,
2028           "SURFACE", region->remote_surface, region, x, y, w, h);
2029 }
2030
2031 static const struct tizen_remote_surface_region_interface _remote_region_interface =
2032 {
2033    _remote_region_cb_destroy,
2034    _remote_region_cb_geometry_set,
2035 };
2036
2037 static void
2038 _remote_provider_cb_resource_destroy(struct wl_resource *resource)
2039 {
2040    E_Comp_Wl_Remote_Provider *provider;
2041    E_Comp_Wl_Remote_Surface *remote_surface;
2042
2043    provider = wl_resource_get_user_data(resource);
2044    if (!provider) return;
2045
2046    if (_rsm)
2047      eina_hash_del(_rsm->provider_hash, &provider->common.ec, provider);
2048
2049    EINA_LIST_FREE(provider->common.surfaces, remote_surface)
2050      {
2051         if (remote_surface->provider == provider)
2052           {
2053              /* unset remote buffer from provider */
2054              if (remote_surface->bind_ec)
2055                _remote_surface_bind_client(remote_surface, NULL);
2056
2057              remote_surface->provider = NULL;
2058              //notify of this ejection to remote surface_resource
2059              tizen_remote_surface_send_missing(remote_surface->resource);
2060           }
2061      }
2062
2063    _remote_provider_client_set(provider->common.ec, EINA_FALSE);
2064    E_FREE(provider);
2065 }
2066
2067 static void
2068 _remote_provider_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
2069 {
2070    wl_resource_destroy(resource);
2071 }
2072
2073 static void
2074 _remote_provider_cb_offscreen_set(struct wl_client *client EINA_UNUSED, struct wl_resource *provider_resource, uint32_t offscreen)
2075 {
2076    E_Comp_Wl_Remote_Provider *provider;
2077
2078    provider = wl_resource_get_user_data(provider_resource);
2079    if (!provider) return;
2080
2081    if (provider->common.is_offscreen == offscreen) return;
2082    _remote_provider_offscreen_set(provider, offscreen);
2083 }
2084
2085 static void
2086 _remote_provider_cb_input_event_filter_set(struct wl_client *client EINA_UNUSED, struct wl_resource *provider_resource, uint32_t event_filter)
2087 {
2088    E_Comp_Wl_Remote_Provider *provider;
2089    E_Comp_Wl_Remote_Surface *remote_surface;
2090    Eina_List *l;
2091
2092    provider = wl_resource_get_user_data(provider_resource);
2093    if (!provider) return;
2094
2095    provider->input_event_filter = event_filter;
2096    RSMDBG("set input event filter 0x%08x",
2097           provider->common.ec->pixmap, provider->common.ec,
2098           "PROVIDER", provider, event_filter);
2099
2100    if (!event_filter) return;
2101
2102    EINA_LIST_FOREACH(provider->common.surfaces, l, remote_surface)
2103      {
2104         if (remote_surface->version >= TIZEN_REMOTE_SURFACE_INPUT_EVENT_FILTER_SINCE_VERSION)
2105           tizen_remote_surface_send_input_event_filter(remote_surface->resource, event_filter);
2106      }
2107 }
2108
2109 static const struct tizen_remote_surface_provider_interface _remote_provider_interface =
2110 {
2111    _remote_provider_cb_destroy,
2112    _remote_provider_cb_offscreen_set,
2113    _remote_provider_cb_input_event_filter_set,
2114 };
2115
2116 static void
2117 _remote_surface_cb_tbm_destroy(struct wl_listener *listener, void *data)
2118 {
2119    E_Comp_Wl_Remote_Surface *remote_surface;
2120
2121    remote_surface = container_of(listener, E_Comp_Wl_Remote_Surface, tbm_destroy_listener);
2122    if (!remote_surface) return;
2123
2124    if (remote_surface->tbm_destroy_listener.notify)
2125      {
2126         wl_list_remove(&remote_surface->tbm_destroy_listener.link);
2127         remote_surface->tbm_destroy_listener.notify = NULL;
2128      }
2129
2130    remote_surface->wl_tbm = NULL;
2131 }
2132
2133 static void
2134 _remote_surface_cb_resource_destroy(struct wl_resource *resource)
2135 {
2136    E_Comp_Wl_Remote_Surface *remote_surface;
2137    E_Comp_Wl_Remote_Provider *provider;
2138    E_Comp_Wl_Remote_Source *source;
2139    E_Comp_Wl_Remote_Region *region;
2140    E_Comp_Wl_Remote_Buffer *remote_buf;
2141
2142    remote_surface = wl_resource_get_user_data(resource);
2143    if (!remote_surface) return;
2144
2145    provider = remote_surface->provider;
2146    if (provider)
2147      {
2148         _remote_surface_visible_set(remote_surface, EINA_FALSE);
2149         if (provider->onscreen_parent == remote_surface)
2150           _remote_provider_onscreen_parent_set(provider, NULL);
2151
2152         provider->common.surfaces = eina_list_remove(provider->common.surfaces,
2153                                               remote_surface);
2154         remote_surface->provider = NULL;
2155      }
2156
2157    source = remote_surface->source;
2158    if (source)
2159      {
2160         source->common.surfaces = eina_list_remove(source->common.surfaces, remote_surface);
2161         remote_surface->source = NULL;
2162      }
2163
2164    EINA_LIST_FREE(remote_surface->regions, region)
2165      {
2166         region->remote_surface = NULL;
2167         wl_resource_destroy(region->resource);
2168      }
2169
2170    EINA_LIST_FREE(remote_surface->send_remote_bufs, remote_buf)
2171      {
2172         remote_buf->remote_surface = NULL;
2173         wayland_tbm_server_send_destroy_buffer(remote_surface->wl_tbm, remote_buf->resource);
2174      }
2175
2176    if (remote_surface->bind_ec)
2177      _remote_surface_bind_client(remote_surface, NULL);
2178    if (remote_surface->owner)
2179      {
2180         eina_hash_del_by_key(_rsm->surface_hash, &remote_surface->owner);
2181         _remote_surface_client_set(remote_surface->owner, EINA_FALSE);
2182      }
2183
2184    if (remote_surface->wl_tbm)
2185      wl_list_remove(&remote_surface->tbm_destroy_listener.link);
2186
2187    if (provider)
2188      _remote_surface_ignore_output_transform_send(&provider->common);
2189    if (source)
2190      _remote_surface_ignore_output_transform_send(&source->common);
2191
2192    E_FREE(remote_surface);
2193 }
2194
2195 static void
2196 _remote_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
2197 {
2198    wl_resource_destroy(resource);
2199 }
2200
2201 static void
2202 _remote_surface_cb_redirect(struct wl_client *client, struct wl_resource *resource)
2203 {
2204    E_Comp_Wl_Buffer *buffer;
2205    E_Comp_Wl_Remote_Surface *remote_surface;
2206
2207    EINA_SAFETY_ON_NULL_RETURN(_rsm);
2208
2209    remote_surface = wl_resource_get_user_data(resource);
2210    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2211    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2212
2213    if (remote_surface->provider)
2214      {
2215         EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider->common.ec);
2216
2217         if (remote_surface->redirect)
2218           {
2219              RSMINF("Already Redirect surface provider:%p(ec:%p)",
2220                     NULL, NULL,
2221                     "SURFACE", remote_surface,
2222                     remote_surface->provider, remote_surface->provider->common.ec);
2223
2224              return;
2225           }
2226
2227         RSMINF("Redirect surface provider:%p(ec:%p)",
2228                NULL, NULL,
2229                "SURFACE", remote_surface,
2230                remote_surface->provider, remote_surface->provider->common.ec);
2231
2232         remote_surface->redirect = EINA_TRUE;
2233
2234         /* Send input event filter of provider */
2235         if ((remote_surface->provider->input_event_filter) &&
2236             (remote_surface->version >= TIZEN_REMOTE_SURFACE_INPUT_EVENT_FILTER_SINCE_VERSION))
2237           tizen_remote_surface_send_input_event_filter(resource,
2238                                                        remote_surface->provider->input_event_filter);
2239
2240         buffer = e_pixmap_resource_get(remote_surface->provider->common.ec->pixmap);
2241         EINA_SAFETY_ON_NULL_RETURN(buffer);
2242
2243         _remote_surface_changed_buff_protocol_send(remote_surface,
2244                                                    TIZEN_REMOTE_SURFACE_BUFFER_TYPE_TBM,
2245                                                    _rsm->dummy_fd,
2246                                                    0,
2247                                                    EINA_TRUE,
2248                                                    buffer);
2249      }
2250    else if (remote_surface->source)
2251      {
2252         EINA_SAFETY_ON_NULL_RETURN(remote_surface->source->common.ec);
2253
2254         if (remote_surface->redirect)
2255           {
2256              RSMINF("Already Redirect surface source:%p(ec:%p)",
2257                     NULL, NULL,
2258                     "SURFACE", remote_surface,
2259                     remote_surface->source, remote_surface->source->common.ec);
2260
2261              return;
2262           }
2263
2264         RSMINF("Redirect surface source:%p(ec:%p)",
2265                NULL, NULL,
2266                "SURFACE", remote_surface,
2267                remote_surface->source, remote_surface->source->common.ec);
2268
2269         if (remote_surface->version < TIZEN_REMOTE_SURFACE_CHANGED_BUFFER_SINCE_VERSION)
2270           return;
2271
2272         remote_surface->redirect = EINA_TRUE;
2273
2274         if ((buffer = e_pixmap_resource_get(remote_surface->source->common.ec->pixmap)))
2275           {
2276              _remote_surface_changed_buff_protocol_send(remote_surface,
2277                                                         TIZEN_REMOTE_SURFACE_BUFFER_TYPE_TBM,
2278                                                         _rsm->dummy_fd,
2279                                                         0,
2280                                                         EINA_TRUE,
2281                                                         buffer);
2282           }
2283         else
2284           {
2285              _remote_source_send_image_update(remote_surface->source);
2286           }
2287      }
2288 }
2289
2290 static void
2291 _remote_surface_cb_unredirect(struct wl_client *client, struct wl_resource *resource)
2292 {
2293    E_Comp_Wl_Remote_Surface *remote_surface;
2294
2295    remote_surface = wl_resource_get_user_data(resource);
2296    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2297    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2298
2299    remote_surface->redirect = EINA_FALSE;
2300 //   _remote_surface_visible_set(remote_surface, EINA_FALSE);
2301
2302    RSMINF("Unredirect surface provider:%p(ec:%p)",
2303           NULL, NULL,
2304           "SURFACE", remote_surface,
2305           remote_surface->provider, remote_surface->provider? remote_surface->provider->common.ec: NULL);
2306 }
2307
2308 static void
2309 _remote_surface_cb_mouse_event_transfer(struct wl_client *client, struct wl_resource *resource, uint32_t event_type, int32_t device, int32_t button, int32_t x, int32_t y, wl_fixed_t radius_x, wl_fixed_t radius_y, wl_fixed_t pressure, wl_fixed_t angle, uint32_t clas, uint32_t subclas EINA_UNUSED, const char *identifier, uint32_t time)
2310 {
2311    E_Comp_Wl_Remote_Provider *provider;
2312    E_Comp_Wl_Remote_Surface *remote_surface;
2313    E_Client *ec;
2314
2315    Evas_Device *edev = NULL;
2316    Evas_Device_Class eclas = EVAS_DEVICE_CLASS_NONE;
2317    double eradx, erady, epressure, eangle;
2318
2319    remote_surface = wl_resource_get_user_data(resource);
2320    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2321    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2322    EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider);
2323    EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider->common.ec);
2324
2325    provider = remote_surface->provider;
2326    ec = provider->common.ec;
2327
2328    if (e_object_is_del(E_OBJECT(ec))) return;
2329
2330    /* identify class */
2331    if (clas == TIZEN_INPUT_DEVICE_CLAS_MOUSE)
2332      eclas = EVAS_DEVICE_CLASS_MOUSE;
2333    else if (clas == TIZEN_INPUT_DEVICE_CLAS_TOUCHSCREEN)
2334      eclas = EVAS_DEVICE_CLASS_TOUCH;
2335    else
2336      {
2337         ERR("Not supported device clas(%d) subclas(%d) identifier(%s)",
2338             clas, subclas, identifier);
2339      }
2340
2341    /* find ecore device*/
2342    edev = _device_get_by_identifier(identifier);
2343    if (edev)
2344      {
2345         eclas = evas_device_class_get(edev);
2346      }
2347
2348    /* fixed to */
2349    eradx = wl_fixed_to_double(radius_x);
2350    erady = wl_fixed_to_double(radius_y);
2351    epressure = wl_fixed_to_double(pressure);
2352    eangle = wl_fixed_to_double(angle);
2353
2354    if (eclas == EVAS_DEVICE_CLASS_MOUSE)
2355      {
2356         switch (event_type)
2357           {
2358            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_DOWN:
2359               e_client_mouse_button_send(ec,
2360                                          button,
2361                                          EINA_TRUE,
2362                                          edev,
2363                                          time);
2364               break;
2365            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_UP:
2366               e_client_mouse_button_send(ec,
2367                                          button,
2368                                          EINA_FALSE,
2369                                          edev,
2370                                          time);
2371               break;
2372            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_MOVE:
2373               e_client_mouse_move_send(ec,
2374                                        x, y,
2375                                        edev,
2376                                        time);
2377               break;
2378            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_IN:
2379               e_client_mouse_in_send(ec,
2380                                      x, y,
2381                                      edev,
2382                                      time);
2383               break;
2384            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_OUT:
2385               e_client_mouse_out_send(ec,
2386                                       edev,
2387                                       time);
2388               break;
2389            default:
2390               ERR("Not supported event_type(%d)", event_type);
2391               break;
2392           }
2393      }
2394    else if (eclas == EVAS_DEVICE_CLASS_TOUCH)
2395      {
2396         switch (event_type)
2397           {
2398            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_DOWN:
2399               /* FIXME: temporary fix for first touch down w/o move event */
2400               e_client_touch_update_send(ec,
2401                                          device,
2402                                          x, y,
2403                                          edev,
2404                                          eradx, erady, epressure, eangle,
2405                                          time);
2406               e_client_touch_send(ec,
2407                                   device,
2408                                   x, y,
2409                                   EINA_TRUE,
2410                                   edev,
2411                                   eradx, erady, epressure, eangle,
2412                                   time);
2413               break;
2414            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_UP:
2415               e_client_touch_send(ec,
2416                                   device,
2417                                   x, y,
2418                                   EINA_FALSE,
2419                                   edev,
2420                                   eradx, erady, epressure, eangle,
2421                                   time);
2422               break;
2423            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_MOUSE_MOVE:
2424               e_client_touch_update_send(ec,
2425                                          device,
2426                                          x, y,
2427                                          edev,
2428                                          eradx, erady, epressure, eangle,
2429                                          time);
2430               break;
2431            default:
2432               ERR("Not supported event_type(%d)", event_type);
2433               break;
2434           }
2435      }
2436 }
2437
2438 static void
2439 _remote_surface_cb_mouse_wheel_transfer(struct wl_client *client, struct wl_resource *resource, uint32_t direction, int32_t z, uint32_t clas, uint32_t subclas, const char *identifier, uint32_t time)
2440 {
2441    E_Comp_Wl_Remote_Provider *provider;
2442    E_Comp_Wl_Remote_Surface *remote_surface;
2443    E_Client *ec;
2444
2445    Evas_Device *edev = NULL;
2446
2447    remote_surface = wl_resource_get_user_data(resource);
2448    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2449    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2450    EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider);
2451    EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider->common.ec);
2452
2453    provider = remote_surface->provider;
2454    ec = provider->common.ec;
2455
2456    if (e_object_is_del(E_OBJECT(ec))) return;
2457
2458    /* identify class */
2459    edev = _device_get_by_identifier(identifier);
2460
2461    e_client_mouse_wheel_send(ec, direction, z, edev, time);
2462 }
2463
2464 static void
2465 _remote_surface_cb_touch_event_transfer(struct wl_client *client, struct wl_resource *resource, uint32_t event_type, int32_t device, int32_t button, int32_t x, int32_t y, wl_fixed_t radius_x, wl_fixed_t radius_y, wl_fixed_t pressure, wl_fixed_t angle, uint32_t clas, uint32_t subclas, const char *identifier, uint32_t time)
2466 {
2467    E_Comp_Wl_Remote_Provider *provider;
2468    E_Comp_Wl_Remote_Surface *remote_surface;
2469    E_Client *ec;
2470
2471    Evas_Device *edev = NULL;
2472    Evas_Device_Class eclas;
2473    double eradx, erady, epressure, eangle;
2474
2475    remote_surface = wl_resource_get_user_data(resource);
2476    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2477    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2478    EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider);
2479    EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider->common.ec);
2480
2481    provider = remote_surface->provider;
2482    ec = provider->common.ec;
2483
2484    if (e_object_is_del(E_OBJECT(ec))) return;
2485
2486    /* identify class */
2487    if (clas == TIZEN_INPUT_DEVICE_CLAS_TOUCHSCREEN)
2488      eclas = EVAS_DEVICE_CLASS_TOUCH;
2489    else
2490      {
2491         ERR("Not supported device clas(%d) subclas(%d identifier(%s)",
2492             clas, subclas, identifier);
2493         return;
2494      }
2495
2496    /* find ecore device*/
2497    edev = _device_get_by_identifier(identifier);
2498    if (edev)
2499      {
2500         eclas = evas_device_class_get(edev);
2501      }
2502
2503    /* fixed to */
2504    eradx = wl_fixed_to_double(radius_x);
2505    erady = wl_fixed_to_double(radius_y);
2506    epressure = wl_fixed_to_double(pressure);
2507    eangle = wl_fixed_to_double(angle);
2508
2509    if (eclas == EVAS_DEVICE_CLASS_TOUCH)
2510      {
2511         switch (event_type)
2512           {
2513            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_TOUCH_DOWN:
2514               e_client_touch_update_send(ec,
2515                                          device,
2516                                          x, y,
2517                                          edev,
2518                                          eradx, erady, epressure, eangle,
2519                                          time);
2520               e_client_touch_send(ec,
2521                                   device,
2522                                   x, y,
2523                                   EINA_TRUE,
2524                                   edev,
2525                                   eradx, erady, epressure, eangle,
2526                                   time);
2527               break;
2528            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_TOUCH_UP:
2529               e_client_touch_send(ec,
2530                                   device,
2531                                   x, y,
2532                                   EINA_FALSE,
2533                                   edev,
2534                                   eradx, erady, epressure, eangle,
2535                                   time);
2536               break;
2537            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_TOUCH_MOVE:
2538               e_client_touch_update_send(ec,
2539                                          device,
2540                                          x, y,
2541                                          edev,
2542                                          eradx, erady, epressure, eangle,
2543                                          time);
2544               break;
2545            default:
2546               ERR("Not supported event_type(%d)", event_type);
2547               break;
2548           }
2549      }
2550 }
2551
2552 static void
2553 _remote_surface_cb_touch_cancel_transfer(struct wl_client *client, struct wl_resource *resource)
2554 {
2555    E_Comp_Wl_Remote_Provider *provider;
2556    E_Comp_Wl_Remote_Surface *remote_surface;
2557    E_Client *ec;
2558
2559    remote_surface = wl_resource_get_user_data(resource);
2560    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2561    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2562    EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider);
2563    EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider->common.ec);
2564
2565    provider = remote_surface->provider;
2566    ec = provider->common.ec;
2567
2568    if (e_object_is_del(E_OBJECT(ec))) return;
2569    e_client_touch_cancel_send(ec);
2570 }
2571
2572 static void
2573 _remote_surface_cb_key_event_transfer(struct wl_client *client, struct wl_resource *resource, uint32_t event_type, int32_t keycode, uint32_t clas, uint32_t subclas, const char *identifier, uint32_t time)
2574 {
2575    E_Comp_Wl_Remote_Provider *provider;
2576    E_Comp_Wl_Remote_Surface *remote_surface;
2577    E_Client *ec;
2578
2579    Evas_Device *edev = NULL;
2580    Evas_Device_Class eclas;
2581
2582    remote_surface = wl_resource_get_user_data(resource);
2583    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2584    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2585    EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider);
2586    EINA_SAFETY_ON_NULL_RETURN(remote_surface->provider->common.ec);
2587
2588    provider = remote_surface->provider;
2589    ec = provider->common.ec;
2590
2591    if (e_object_is_del(E_OBJECT(ec))) return;
2592
2593    /* identify class */
2594    if (clas == TIZEN_INPUT_DEVICE_CLAS_KEYBOARD)
2595      eclas = EVAS_DEVICE_CLASS_KEYBOARD;
2596    else
2597      {
2598         ERR("Not supported device class(%d) subclass(%d identifier(%s)",
2599             clas, subclas, identifier);
2600         return;
2601      }
2602
2603    /* find ecore device*/
2604    edev = _device_get_by_identifier(identifier);
2605    if (edev)
2606      {
2607         eclas = evas_device_class_get(edev);
2608      }
2609
2610    if (eclas == EVAS_DEVICE_CLASS_KEYBOARD)
2611      {
2612         switch (event_type)
2613           {
2614            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_KEY_DOWN:
2615               e_client_key_send(ec,
2616                                 keycode,
2617                                 EINA_TRUE,
2618                                 edev,
2619                                 time);
2620               break;
2621            case TIZEN_REMOTE_SURFACE_EVENT_TYPE_KEY_UP:
2622               e_client_key_send(ec,
2623                                 keycode,
2624                                 EINA_FALSE,
2625                                 edev,
2626                                 time);
2627               break;
2628            default:
2629               ERR("Not supported event_type(%d)", event_type);
2630               break;
2631           }
2632      }
2633 }
2634
2635 static void
2636 _remote_surface_cb_visibility_transfer(struct wl_client *client, struct wl_resource *resource, uint32_t visibility_type)
2637 {
2638    E_Comp_Wl_Remote_Surface *remote_surface;
2639
2640    remote_surface = wl_resource_get_user_data(resource);
2641    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2642    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2643
2644    if (visibility_type == TIZEN_REMOTE_SURFACE_VISIBILITY_TYPE_INVISIBLE)
2645      {
2646         _remote_surface_visible_set(remote_surface, EINA_FALSE);
2647      }
2648    else if (visibility_type == TIZEN_REMOTE_SURFACE_VISIBILITY_TYPE_VISIBLE)
2649      {
2650         _remote_surface_visible_set(remote_surface, EINA_TRUE);
2651      }
2652 }
2653
2654 static void
2655 _remote_surface_cb_owner_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface_resource)
2656 {
2657    E_Comp_Wl_Remote_Surface *remote_surface;
2658    E_Client *owner = NULL;
2659
2660    remote_surface = wl_resource_get_user_data(resource);
2661    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2662    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2663
2664    if (surface_resource)
2665      owner = wl_resource_get_user_data(surface_resource);
2666
2667    if (remote_surface->owner)
2668      _remote_surface_client_set(remote_surface->owner, EINA_FALSE);
2669
2670    remote_surface->owner = owner;
2671    eina_hash_del_by_data(_rsm->surface_hash, remote_surface);
2672
2673    if ((owner) && (remote_surface->provider))
2674      {
2675         eina_hash_add(_rsm->surface_hash, &owner, remote_surface);
2676         _remote_surface_client_set(remote_surface->owner, EINA_TRUE);
2677      }
2678
2679    if (remote_surface->provider)
2680      _remote_provider_onscreen_parent_calculate(remote_surface->provider);
2681 }
2682
2683 static void
2684 _remote_surface_cb_region_create(struct wl_client *client, struct wl_resource *remote_surface_resource, uint32_t id)
2685 {
2686    struct wl_resource *resource;
2687    E_Comp_Wl_Remote_Surface *remote_surface;
2688    E_Comp_Wl_Remote_Region *region;
2689    E_Comp_Wl_Remote_Provider *provider;
2690
2691    remote_surface = wl_resource_get_user_data(remote_surface_resource);
2692    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2693    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2694
2695    resource = wl_resource_create(client,
2696                                  &tizen_remote_surface_region_interface,
2697                                  1, id);
2698
2699    if (!resource)
2700      {
2701         ERR("Could not create tizen remote region resource: %m");
2702         wl_client_post_no_memory(client);
2703         return;
2704      }
2705
2706    region = E_NEW(E_Comp_Wl_Remote_Region, 1);
2707    if (!region)
2708      {
2709         wl_client_post_no_memory(client);
2710         wl_resource_destroy(resource);
2711         return;
2712      }
2713    region->remote_surface = remote_surface;
2714    region->resource = resource;
2715    region->geometry.x = -1;
2716    region->geometry.y = -1;
2717    region->geometry.w = -1;
2718    region->geometry.h = -1;
2719    remote_surface->regions = eina_list_append(remote_surface->regions, region);
2720
2721    wl_resource_set_implementation(resource,
2722                                   &_remote_region_interface,
2723                                   region,
2724                                   _remote_region_cb_resource_destroy);
2725
2726    //update provider's region rect list
2727    provider = remote_surface->provider;
2728    if ((provider) && (provider->onscreen_parent == remote_surface))
2729      {
2730         _remote_provider_rect_add(provider, &region->geometry);
2731      }
2732 }
2733
2734 static void
2735 _remote_surface_cb_release(struct wl_client *client, struct wl_resource *resource, struct wl_resource *remote_buffer_resource)
2736 {
2737    E_Comp_Wl_Remote_Surface *remote_surface;
2738    E_Comp_Wl_Remote_Buffer *remote_buffer;
2739
2740    remote_surface = wl_resource_get_user_data(resource);
2741    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2742    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2743
2744    remote_buffer = _e_comp_wl_remote_buffer_get(remote_surface, remote_buffer_resource);
2745    EINA_SAFETY_ON_NULL_RETURN(remote_buffer);
2746
2747    if (remote_surface->version >= 2)
2748      {
2749         E_Comp_Wl_Buffer *buf = NULL;
2750
2751         if (remote_buffer->ref.buffer &&
2752             remote_buffer->ref.buffer->resource)
2753            buf = remote_buffer->ref.buffer;
2754
2755         e_comp_wl_buffer_reference(&remote_buffer->ref, NULL);
2756
2757         /*Send release event to provider*/
2758         if (remote_surface->provider &&
2759             remote_surface->provider->buffer_mode &&
2760             buf && buf->busy == 0)
2761           {
2762              if (remote_surface->provider->buffer_mode == 1 ||
2763                  (remote_surface->provider->buffer_mode == 2 &&
2764                   remote_surface->provider->vis_ref == 0))
2765                {
2766                   E_Client *ec = remote_surface->provider->common.ec;
2767                   e_pixmap_buffer_clear(ec->pixmap, EINA_TRUE);
2768                }
2769           }
2770      }
2771 }
2772
2773 static void
2774 _remote_surface_cb_remote_render_set(struct wl_client *client, struct wl_resource *resource, uint32_t set)
2775 {
2776    E_Comp_Wl_Remote_Surface *remote_surface;
2777    E_Comp_Wl_Remote_Source *source = NULL;
2778
2779    remote_surface = wl_resource_get_user_data(resource);
2780    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
2781    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
2782
2783    source = remote_surface->source;
2784    if (!source) return;
2785
2786    if (remote_surface->remote_render == set)
2787      return;
2788
2789    remote_surface->remote_render = set;
2790    _remote_source_offscreen_set(source, set);
2791 }
2792
2793 static void
2794 _remote_surface_cb_changed_buffer_event_filter_set(struct wl_client *client,
2795                                                    struct wl_resource *rsurf_res,
2796                                                    enum tizen_remote_surface_changed_buffer_event_filter filter)
2797 {
2798    E_Comp_Wl_Remote_Surface *rs;
2799
2800    rs = wl_resource_get_user_data(rsurf_res);
2801    EINA_SAFETY_ON_NULL_RETURN(rs);
2802    EINA_SAFETY_ON_FALSE_RETURN(rs->valid);
2803
2804    if (filter == TIZEN_REMOTE_SURFACE_CHANGED_BUFFER_EVENT_FILTER_NONE)
2805      rs->changed_buff_ev_filter.use = EINA_FALSE;
2806    else
2807      rs->changed_buff_ev_filter.use = EINA_TRUE;
2808
2809    rs->changed_buff_ev_filter.filter = filter;
2810
2811    RSMINF("use:%d filter:%u", NULL, NULL, "SURFACE", rs,
2812           rs->changed_buff_ev_filter.use,
2813           rs->changed_buff_ev_filter.filter);
2814 }
2815
2816 static void
2817 _remote_surface_cb_curr_buff_get(struct wl_client *client,
2818                                  struct wl_resource *rsurf_res,
2819                                  enum tizen_remote_surface_buffer_type buff_type,
2820                                  uint32_t req_serial)
2821 {
2822    E_Comp_Wl_Remote_Surface *rs;
2823    Eina_Bool res;
2824
2825    rs = wl_resource_get_user_data(rsurf_res);
2826    EINA_SAFETY_ON_NULL_RETURN(rs);
2827    EINA_SAFETY_ON_FALSE_RETURN(rs->valid);
2828
2829    RSMINF("buff_type:%u req_serial:%u", NULL, NULL, "SURFACE", rs,
2830           buff_type, req_serial);
2831
2832    /* compare buffer type with filter value of changed_buffer event */
2833    res = _remote_surface_changed_buff_ev_filter_check(rs, buff_type);
2834    EINA_SAFETY_ON_FALSE_RETURN(res);
2835
2836    /* setup request info before sending current buffer */
2837    rs->req_curr_buff.set = EINA_TRUE;
2838    rs->req_curr_buff.type = buff_type;
2839    rs->req_curr_buff.serial = req_serial;
2840
2841    RSMINF("buff_type:%u req_serial:%u", NULL, NULL, "SURFACE", rs,
2842           buff_type, req_serial);
2843
2844    /* send current buffer to the requesting client */
2845    res = _remote_surface_buff_send(rs);
2846    EINA_SAFETY_ON_FALSE_GOTO(res, err_cleanup);
2847
2848    return;
2849
2850 err_cleanup:
2851    rs->req_curr_buff.set = EINA_FALSE;
2852    rs->req_curr_buff.type = 0;
2853    rs->req_curr_buff.serial = 0;
2854 }
2855
2856 static const struct tizen_remote_surface_interface _remote_surface_interface =
2857 {
2858    _remote_surface_cb_destroy,
2859    _remote_surface_cb_redirect,
2860    _remote_surface_cb_unredirect,
2861    _remote_surface_cb_mouse_event_transfer,
2862    _remote_surface_cb_mouse_wheel_transfer,
2863    _remote_surface_cb_touch_event_transfer,
2864    _remote_surface_cb_touch_cancel_transfer,
2865    _remote_surface_cb_key_event_transfer,
2866    _remote_surface_cb_visibility_transfer,
2867    _remote_surface_cb_owner_set,
2868    _remote_surface_cb_region_create,
2869    _remote_surface_cb_release,
2870    _remote_surface_cb_remote_render_set,
2871    _remote_surface_cb_changed_buffer_event_filter_set,
2872    _remote_surface_cb_curr_buff_get,
2873 };
2874
2875 static void
2876 _remote_manager_cb_provider_create(struct wl_client *client, struct wl_resource *res_remote_manager, uint32_t id, struct wl_resource *surface_resource)
2877 {
2878    struct wl_resource *resource;
2879    E_Comp_Wl_Remote_Provider *provider;
2880    E_Client *ec;
2881    uint32_t res_id;
2882    int version;
2883
2884    EINA_SAFETY_ON_NULL_RETURN(_rsm);
2885
2886    ec = wl_resource_get_user_data(surface_resource);
2887    EINA_SAFETY_ON_NULL_RETURN(ec);
2888
2889    if (e_object_is_del(E_OBJECT(ec))) return;
2890
2891    version = wl_resource_get_version(res_remote_manager);
2892    resource = wl_resource_create(client,
2893                                  &tizen_remote_surface_provider_interface,
2894                                  version, id);
2895    if (!resource)
2896      {
2897         ERR("Could not create tizen remote surface provider resource: %m");
2898         wl_client_post_no_memory(client);
2899         return;
2900      }
2901
2902    provider = E_NEW(E_Comp_Wl_Remote_Provider, 1);
2903    if (!provider)
2904      {
2905         wl_client_post_no_memory(client);
2906         wl_resource_destroy(resource);
2907         return;
2908      }
2909    provider->common.ec = ec;
2910    provider->resource = resource;
2911
2912    wl_resource_set_implementation(resource,
2913                                   &_remote_provider_interface,
2914                                   provider,
2915                                   _remote_provider_cb_resource_destroy);
2916
2917    eina_hash_add(_rsm->provider_hash, &ec, provider);
2918
2919    RSMINF("Created resource(%p)",
2920           ec->pixmap, ec,
2921           "PROVIDER", provider, resource);
2922
2923    _remote_provider_client_set(ec, EINA_TRUE);
2924    _remote_provider_offscreen_set(provider, EINA_TRUE);
2925
2926    /* send resource id */
2927    res_id = e_pixmap_res_id_get(ec->pixmap);
2928    tizen_remote_surface_provider_send_resource_id(resource, res_id);
2929
2930    /* set buffer mode */
2931    provider->buffer_mode = e_config->rsm_buffer_release_mode;
2932 }
2933
2934 static void
2935 _remote_manager_cb_surface_create(struct wl_client *client,
2936                                   struct wl_resource *res_remote_manager,
2937                                   uint32_t id,
2938                                   uint32_t res_id,
2939                                   struct wl_resource *wl_tbm)
2940 {
2941    struct wl_resource *resource;
2942    E_Comp_Wl_Remote_Surface *remote_surface;
2943    E_Comp_Wl_Remote_Provider *provider = NULL;
2944    E_Comp_Wl_Remote_Source *source = NULL;
2945    E_Client *ec;
2946    int version;
2947    pid_t pid = 0;
2948    uid_t uid = 0;
2949    Eina_Bool res;
2950
2951    EINA_SAFETY_ON_NULL_RETURN(_rsm);
2952
2953    version = wl_resource_get_version(res_remote_manager);
2954    resource = wl_resource_create(client,
2955                                  &tizen_remote_surface_interface,
2956                                  version, id);
2957    if (!resource)
2958      {
2959         ERR("Could not create tizen remote surface resource: %m");
2960         wl_client_post_no_memory(client);
2961         return;
2962      }
2963
2964    remote_surface = E_NEW(E_Comp_Wl_Remote_Surface, 1);
2965    if (!remote_surface)
2966      {
2967         wl_client_post_no_memory(client);
2968         wl_resource_destroy(resource);
2969         return;
2970      }
2971    remote_surface->resource = resource;
2972    remote_surface->version = wl_resource_get_version(resource);
2973    remote_surface->redirect = EINA_FALSE;
2974    remote_surface->valid = EINA_FALSE;
2975
2976    wl_resource_set_implementation(resource,
2977                                   &_remote_surface_interface,
2978                                   remote_surface,
2979                                   _remote_surface_cb_resource_destroy);
2980
2981    ec = e_pixmap_find_client_by_res_id(res_id);
2982    if (!ec)
2983      {
2984         ERR("Could not find client by res_id(%u)", res_id);
2985         goto fail;
2986      }
2987
2988    if (!wl_tbm)
2989      {
2990         ERR("wayland_tbm resource is NULL");
2991         goto fail;
2992      }
2993
2994    provider = _remote_provider_find(ec);
2995    if (!provider)
2996      {
2997         /* check the privilege for the client which wants to be the remote surface of normal UI client */
2998         wl_client_get_credentials(client, &pid, &uid, NULL);
2999         res = e_security_privilege_check(pid, uid, E_PRIVILEGE_INTERNAL_DEFAULT_PLATFORM);
3000         if (!res)
3001           {
3002              ELOGF("TRS",
3003                    "Privilege Check Failed! DENY creating tizen_remote_surface pid:%d",
3004                    NULL, pid);
3005              goto fail;
3006           }
3007
3008         if (version >= TIZEN_REMOTE_SURFACE_CHANGED_BUFFER_SINCE_VERSION)
3009           {
3010              if (ec->comp_data->sub.data)
3011                {
3012                   ERR("Subsurface could not be source client");
3013                   goto fail;
3014                }
3015
3016              /* if passed */
3017              source = _remote_source_get(ec);
3018              if (!source) goto fail;
3019           }
3020         else
3021           {
3022              ERR("Could not support tizen_remote_surface to client :%d", pid);
3023              goto fail;
3024           }
3025      }
3026
3027    remote_surface->provider = provider;
3028    remote_surface->source = source;
3029    remote_surface->wl_tbm = wl_tbm;
3030
3031    /* Add destroy listener for wl_tbm resource */
3032    remote_surface->tbm_destroy_listener.notify = _remote_surface_cb_tbm_destroy;
3033    wl_resource_add_destroy_listener((struct wl_resource *)wl_tbm, &remote_surface->tbm_destroy_listener);
3034
3035    if (provider)
3036      provider->common.surfaces = eina_list_append(provider->common.surfaces, remote_surface);
3037    else if (source)
3038      source->common.surfaces = eina_list_append(source->common.surfaces, remote_surface);
3039
3040    RSMINF("Created resource(%p) ec(%p) provider(%p) source(%p) version(%d)",
3041           NULL, NULL,
3042           "SURFACE", remote_surface, resource, ec, provider, source, remote_surface->version);
3043
3044    remote_surface->valid = EINA_TRUE;
3045
3046    if (provider)
3047      _remote_surface_ignore_output_transform_send(&provider->common);
3048    else if (source)
3049      _remote_surface_ignore_output_transform_send(&source->common);
3050
3051    return;
3052
3053 fail:
3054    tizen_remote_surface_send_missing(resource);
3055 }
3056
3057
3058 static void
3059 _remote_manager_cb_surface_bind(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface_resource, struct wl_resource *remote_surface_resource)
3060 {
3061    E_Comp_Wl_Remote_Surface *remote_surface;
3062    E_Comp_Wl_Remote_Provider *provider;
3063    E_Client *ec = NULL;
3064
3065    remote_surface = wl_resource_get_user_data(remote_surface_resource);
3066    EINA_SAFETY_ON_NULL_RETURN(remote_surface);
3067    EINA_SAFETY_ON_FALSE_RETURN(remote_surface->valid);
3068
3069    provider = remote_surface->provider;
3070    if (!provider) return;
3071
3072    if (surface_resource)
3073      ec = wl_resource_get_user_data(surface_resource);
3074
3075    _remote_surface_bind_client(remote_surface, ec);
3076
3077    _remote_surface_ignore_output_transform_send(&provider->common);
3078 }
3079
3080 static void
3081 _remote_manager_cb_destroy(struct wl_client *client, struct wl_resource *resource)
3082 {
3083    wl_resource_destroy(resource);
3084 }
3085
3086 static const struct tizen_remote_surface_manager_interface _remote_manager_interface =
3087 {
3088    _remote_manager_cb_provider_create,
3089    _remote_manager_cb_surface_create,
3090    _remote_manager_cb_surface_bind,
3091    _remote_manager_cb_destroy,
3092 };
3093
3094 static void
3095 _remote_manager_cb_unbind(struct wl_resource *res_remote_manager)
3096 {
3097    //nothing to do yet.
3098 }
3099
3100 static void
3101 _remote_manager_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t ver, uint32_t id)
3102 {
3103    struct wl_resource *res_remote_manager;
3104
3105    res_remote_manager = wl_resource_create(client,
3106                                         &tizen_remote_surface_manager_interface,
3107                                         ver,
3108                                         id);
3109    EINA_SAFETY_ON_NULL_GOTO(res_remote_manager, err);
3110
3111    wl_resource_set_implementation(res_remote_manager,
3112                                   &_remote_manager_interface,
3113                                   NULL,
3114                                   _remote_manager_cb_unbind);
3115    return;
3116
3117 err:
3118    ERR("Could not create tizen_remote_surface_manager_interface res: %m");
3119    wl_client_post_no_memory(client);
3120 }
3121
3122 static Eina_Bool
3123 _image_save_type_check(E_Client *ec)
3124 {
3125    if (ec->skip_save_img) return EINA_FALSE;
3126
3127    if (e_policy_client_is_lockscreen(ec) ||
3128        e_policy_client_is_home_screen(ec) ||
3129        e_policy_client_is_quickpanel(ec) ||
3130        e_policy_client_is_volume(ec) ||
3131        e_policy_client_is_volume_tv(ec) ||
3132        e_policy_client_is_floating(ec) ||
3133        e_policy_client_is_cursor(ec) ||
3134        e_policy_client_is_subsurface(ec) ||
3135        e_policy_client_is_cbhm(ec) ||
3136        e_policy_client_is_toast_popup(ec) ||
3137        e_policy_client_is_keyboard(ec) ||
3138        e_policy_client_is_keyboard_sub(ec) ||
3139        e_policy_client_is_keyboard_magnifier(ec))
3140      return EINA_FALSE;
3141
3142    return EINA_TRUE;
3143 }
3144
3145 static void
3146 _e_comp_wl_remote_cb_client_iconify(void *data, E_Client *ec)
3147 {
3148    E_Comp_Wl_Remote_Source *source;
3149
3150    if (!(source = _remote_source_find(ec)))
3151      {
3152         if (ec->ignored) return;
3153         if (!_image_save_type_check(ec)) return;
3154         if (e_object_is_del(E_OBJECT(ec))) return;
3155
3156         source = E_NEW(E_Comp_Wl_Remote_Source, 1);
3157         EINA_SAFETY_ON_NULL_RETURN(source);
3158
3159         source->common.ec = ec;
3160         eina_hash_add(_rsm->source_hash, &ec, source);
3161      }
3162
3163    _remote_source_save_start(source);
3164 }
3165
3166 static void
3167 _e_comp_wl_remote_cb_client_uniconify(void *data, E_Client *ec)
3168 {
3169    _remote_source_save_start_cancel(ec);
3170 }
3171
3172 static void
3173 _e_comp_wl_remote_cb_client_del(void *data, E_Client *ec)
3174 {
3175    E_Comp_Wl_Remote_Provider *provider;
3176    E_Comp_Wl_Remote_Source *source;
3177    E_Comp_Wl_Remote_Surface *remote_surface;
3178
3179    if ((provider = eina_hash_find(_rsm->provider_hash, &ec)))
3180      {
3181         eina_hash_del(_rsm->provider_hash, &ec, provider);
3182         EINA_LIST_FREE(provider->common.surfaces, remote_surface)
3183           {
3184              if (remote_surface->provider == provider)
3185                {
3186                   /* unset remote buffer from provider */
3187                   if (remote_surface->bind_ec)
3188                     _remote_surface_bind_client(remote_surface, NULL);
3189
3190                   remote_surface->provider = NULL;
3191                   //notify of this ejection to remote surface_resource
3192                   tizen_remote_surface_send_missing(remote_surface->resource);
3193                }
3194           }
3195         _remote_provider_offscreen_set(provider, EINA_FALSE);
3196         wl_resource_set_user_data(provider->resource, NULL);
3197         E_FREE(provider);
3198      }
3199
3200    if ((source = _remote_source_find(ec)))
3201      {
3202         _remote_source_destroy(source);
3203      }
3204
3205    if ((remote_surface = eina_hash_find(_rsm->surface_hash, &ec)))
3206      {
3207         eina_hash_del(_rsm->surface_hash, &ec, remote_surface);
3208         if (remote_surface->owner == ec)
3209           remote_surface->owner = NULL;
3210         if (remote_surface->provider)
3211           _remote_provider_onscreen_parent_calculate(remote_surface->provider);
3212      }
3213
3214    if ((remote_surface = eina_hash_find(_rsm->bind_surface_hash, &ec)))
3215      {
3216         eina_hash_del(_rsm->bind_surface_hash, &ec, remote_surface);
3217         if (remote_surface->bind_ec == ec)
3218            _remote_surface_bind_client(remote_surface, NULL);
3219      }
3220 }
3221
3222 static void
3223 _e_comp_wl_remote_cb_hook_action_change(void *d EINA_UNUSED, E_Process *epro, void *user)
3224 {
3225    E_Process_Action act;
3226    E_Client *ec = NULL;
3227    E_Client *base_ec = NULL;
3228    Eina_List *l;
3229
3230    act = *(E_Process_Action*)user;
3231
3232    if (act == E_PROCESS_ACT_ACTIVATE)
3233      {
3234         EINA_LIST_FOREACH(epro->ec_list, l, ec)
3235           {
3236              _remote_source_save_start_cancel(ec);
3237              ec->saved_img = EINA_FALSE;
3238           }
3239      }
3240    else if (act == E_PROCESS_ACT_DEACTIVATE)
3241      {
3242         EINA_LIST_FOREACH(epro->ec_list, l, ec)
3243           {
3244              if (base_ec)
3245                continue;
3246              if (ec->iconic)
3247                continue;
3248              if (!_image_save_type_check(ec))
3249                continue;
3250
3251              base_ec = ec;
3252           }
3253      }
3254
3255    if (base_ec)
3256      {
3257         E_Comp_Wl_Remote_Source *source;
3258
3259         if (!(source = _remote_source_find(base_ec)))
3260           {
3261              if (base_ec->ignored) return;
3262              if (!_image_save_type_check(base_ec)) return;
3263              if (e_object_is_del(E_OBJECT(base_ec))) return;
3264
3265              source = E_NEW(E_Comp_Wl_Remote_Source, 1);
3266              EINA_SAFETY_ON_NULL_RETURN(source);
3267
3268              source->common.ec = base_ec;
3269              eina_hash_add(_rsm->source_hash, &base_ec, source);
3270           }
3271
3272         _remote_source_save_start(source);
3273      }
3274 }
3275
3276 static Eina_Bool
3277 _e_comp_wl_remote_cb_visibility_change(void *data, int type, void *event)
3278 {
3279    E_Event_Client *ev = event;
3280    E_Client *ec;
3281    E_Comp_Wl_Remote_Surface *remote_surface;
3282
3283    EINA_SAFETY_ON_NULL_RETURN_VAL(_rsm, ECORE_CALLBACK_PASS_ON);
3284
3285    E_Process_Hook *process_hook;
3286
3287    if (!_rsm->process_hooks)
3288      {
3289         process_hook = e_process_hook_add(E_PROCESS_HOOK_ACTION_CHANGE, _e_comp_wl_remote_cb_hook_action_change, NULL);
3290         if (process_hook) _rsm->process_hooks = eina_list_append(_rsm->process_hooks, process_hook);
3291      }
3292
3293    ec = ev->ec;
3294    if (!ec) return ECORE_CALLBACK_PASS_ON;
3295
3296    if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
3297
3298    if ((remote_surface = eina_hash_find(_rsm->surface_hash, &ec)))
3299      {
3300         _remote_provider_onscreen_parent_calculate(remote_surface->provider);
3301      }
3302
3303    return ECORE_CALLBACK_PASS_ON;
3304 }
3305
3306 static void
3307 _e_comp_wl_remote_buffer_cb_destroy(struct wl_listener *listener, void *data)
3308 {
3309    E_Comp_Wl_Remote_Buffer *remote_buffer;
3310    E_Comp_Wl_Remote_Surface *remote_surface;
3311
3312    remote_buffer = container_of(listener, E_Comp_Wl_Remote_Buffer, destroy_listener);
3313    if (!remote_buffer) return;
3314
3315
3316    if (remote_buffer->destroy_listener.notify)
3317      {
3318         wl_list_remove(&remote_buffer->destroy_listener.link);
3319         remote_buffer->destroy_listener.notify = NULL;
3320      }
3321
3322    remote_surface = remote_buffer->remote_surface;
3323    if (remote_surface)
3324      remote_surface->send_remote_bufs = eina_list_remove(remote_surface->send_remote_bufs, remote_buffer);
3325
3326    e_comp_wl_buffer_reference(&remote_buffer->ref, NULL);
3327    free(remote_buffer);
3328 }
3329
3330 static E_Comp_Wl_Remote_Buffer *
3331 _e_comp_wl_remote_buffer_get(E_Comp_Wl_Remote_Surface *remote_surface, struct wl_resource *remote_buffer_resource)
3332 {
3333    E_Comp_Wl_Remote_Buffer *remote_buffer = NULL;
3334    struct wl_listener *listener;
3335
3336    listener = wl_resource_get_destroy_listener(remote_buffer_resource, _e_comp_wl_remote_buffer_cb_destroy);
3337    if (listener)
3338      return container_of(listener, E_Comp_Wl_Remote_Buffer, destroy_listener);
3339
3340    if (!(remote_buffer = E_NEW(E_Comp_Wl_Remote_Buffer, 1))) return NULL;
3341
3342    remote_buffer->remote_surface = remote_surface;
3343    remote_buffer->resource = remote_buffer_resource;
3344    remote_buffer->destroy_listener.notify = _e_comp_wl_remote_buffer_cb_destroy;
3345    wl_resource_add_destroy_listener(remote_buffer->resource, &remote_buffer->destroy_listener);
3346
3347   remote_surface->send_remote_bufs = eina_list_append(remote_surface->send_remote_bufs, remote_buffer);
3348
3349    return remote_buffer;
3350 }
3351
3352 static void
3353 _e_comp_wl_remote_surface_source_update(E_Comp_Wl_Remote_Source *source, E_Comp_Wl_Buffer *buffer)
3354 {
3355    E_Comp_Wl_Remote_Surface *remote_surface;
3356    Eina_List *l;
3357
3358    if ((!source) || (!buffer)) return;
3359
3360    EINA_LIST_FOREACH(source->common.surfaces, l, remote_surface)
3361      {
3362         if (remote_surface->version < TIZEN_REMOTE_SURFACE_CHANGED_BUFFER_SINCE_VERSION)
3363           continue;
3364
3365         if (!remote_surface->redirect) continue;
3366
3367         _remote_surface_changed_buff_protocol_send(remote_surface,
3368                                                    TIZEN_REMOTE_SURFACE_BUFFER_TYPE_TBM,
3369                                                    _rsm->dummy_fd,
3370                                                    0,
3371                                                    EINA_TRUE,
3372                                                    buffer);
3373      }
3374 }
3375
3376 static int
3377 _e_comp_wl_remote_surface_dummy_fd_get(void)
3378 {
3379    int fd = 0, blen = 0, len = 0;
3380    char *path;
3381    char tmp[PATH_MAX];
3382
3383    blen = sizeof(tmp) - 1;
3384
3385    path = e_util_env_get("XDG_RUNTIME_DIR");
3386    if (!path) return -1;
3387
3388    len = strlen(path);
3389    if (len < blen)
3390      {
3391         strncpy(tmp, path, len + 1);
3392         strncat(tmp, "/enlightenment_rsm_dummy_fdXXXXXX", 34);
3393         E_FREE(path);
3394      }
3395    else
3396      {
3397         E_FREE(path);
3398         return -1;
3399      }
3400
3401    if ((fd = mkstemp(tmp)) < 0)
3402      return -1;
3403
3404    unlink(tmp);
3405
3406    return fd;
3407 }
3408
3409 static void
3410 _e_comp_wl_remote_surface_state_buffer_set(E_Comp_Wl_Surface_State *state, E_Comp_Wl_Buffer *buffer)
3411 {
3412    if (state->buffer == buffer) return;
3413    if (state->buffer)
3414      wl_list_remove(&state->buffer_destroy_listener.link);
3415    state->buffer = buffer;
3416    if (state->buffer)
3417      wl_signal_add(&state->buffer->destroy_signal,
3418                    &state->buffer_destroy_listener);
3419 }
3420
3421 static void
3422 _e_comp_wl_remote_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
3423 {
3424    E_Comp_Wl_Remote_Provider *provider;
3425    E_Comp_Wl_Remote_Source *source;
3426    E_Comp_Wl_Remote_Surface *surface;
3427    struct wl_resource *cb;
3428    Eina_Rectangle *dmg;
3429    int x = 0, y = 0, sx = 0, sy = 0;
3430    E_Comp_Wl_Buffer *buffer;
3431    Eina_List *l, *ll;
3432    E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
3433
3434    if (e_object_is_del(E_OBJECT(ec))) return;
3435
3436    if (vp->buffer.transform != state->buffer_viewport.buffer.transform)
3437      {
3438         int transform_change = (4 + state->buffer_viewport.buffer.transform - vp->buffer.transform) & 0x3;
3439
3440         ELOGF("TRANSFORM", "buffer_transform changed: old(%d) new(%d)",
3441               ec,
3442               vp->buffer.transform, state->buffer_viewport.buffer.transform);
3443
3444         if (transform_change == vp->wait_for_transform_change)
3445           vp->wait_for_transform_change = 0;
3446      }
3447
3448    ec->comp_data->scaler.buffer_viewport = state->buffer_viewport;
3449
3450    if (state->new_attach)
3451      e_comp_wl_surface_attach(ec, state->buffer);
3452
3453    _e_comp_wl_remote_surface_state_buffer_set(state, NULL);
3454
3455    if (state->new_attach)
3456      {
3457         x = ec->client.x, y = ec->client.y;
3458
3459         ec->w = ec->client.w = state->bw;
3460         ec->h = ec->client.h = state->bh;
3461
3462         if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.configure))
3463           ec->comp_data->shell.configure(ec->comp_data->shell.surface,
3464                                          x, y, ec->w, ec->h);
3465      }
3466
3467    sx = state->sx;
3468    sy = state->sy;
3469    state->sx = 0;
3470    state->sy = 0;
3471    state->new_attach = EINA_FALSE;
3472
3473    /* send previous frame done */
3474    EINA_LIST_FOREACH_SAFE(ec->comp_data->frames, l, ll, cb)
3475      {
3476          wl_callback_send_done(cb, ecore_time_unix_get() * 1000);
3477          wl_resource_destroy(cb);
3478      }
3479
3480    ec->comp_data->frames = eina_list_merge(ec->comp_data->frames,
3481                                            state->frames);
3482    state->frames = NULL;
3483
3484    /* clear stored damages... */
3485    EINA_LIST_FREE(state->buffer_damages, dmg)
3486       eina_rectangle_free(dmg);
3487
3488    EINA_LIST_FREE(state->damages, dmg)
3489       eina_rectangle_free(dmg);
3490
3491    state->buffer_viewport.changed = 0;
3492
3493    /* send remote buffer to remote surfaces */
3494    buffer = e_pixmap_resource_get(ec->pixmap);
3495    if (buffer)
3496      {
3497         if ((provider = _remote_provider_find(ec)))
3498           {
3499              EINA_LIST_FOREACH(provider->common.surfaces, l, surface)
3500                {
3501                   if (!surface->redirect) continue;
3502                   if (surface->bind_ec)
3503                     {
3504                        surface->bind_ec->comp_data->pending.buffer_viewport = ec->comp_data->scaler.buffer_viewport;
3505
3506                        _e_comp_wl_remote_surface_state_buffer_set(&surface->bind_ec->comp_data->pending, buffer);
3507                        surface->bind_ec->comp_data->pending.sx = sx;
3508                        surface->bind_ec->comp_data->pending.sy = sy;
3509                        surface->bind_ec->comp_data->pending.new_attach = EINA_TRUE;
3510
3511                        e_comp_wl_surface_commit(surface->bind_ec);
3512
3513                        /* need to prepare hwc whenever buffer changed */
3514                        e_comp_render_queue();
3515                     }
3516                   else
3517                     {
3518                        _remote_surface_changed_buff_protocol_send(surface,
3519                                                                   TIZEN_REMOTE_SURFACE_BUFFER_TYPE_TBM,
3520                                                                   _rsm->dummy_fd,
3521                                                                   0,
3522                                                                   EINA_TRUE,
3523                                                                   buffer);
3524                     }
3525                }
3526           }
3527         else if ((source = _remote_source_find(ec)))
3528           {
3529              _e_comp_wl_remote_surface_source_update(source, buffer);
3530           }
3531
3532         /* send frame done */
3533         e_pixmap_image_clear(ec->pixmap, 1);
3534      }
3535 }
3536
3537 static Eina_Bool
3538 _e_comp_wl_remote_surface_subsurface_commit(E_Comp_Wl_Remote_Provider *parent_provider,
3539                                             E_Client *ec)
3540 {
3541    E_Comp_Wl_Subsurf_Data *sdata;
3542    E_Comp_Wl_Remote_Surface *onscreen_parent;
3543    Eina_List *l;
3544    Eina_Rectangle *rect;
3545    int fx, fy, fw, fh;
3546    int x, y, w, h;
3547    Eina_Bool first_skip = EINA_TRUE;
3548    E_Comp_Wl_Buffer *buffer;
3549
3550    if (!e_comp_wl_subsurface_commit(ec)) return EINA_FALSE;
3551
3552    buffer = e_pixmap_resource_get(ec->pixmap);
3553    if (!buffer) return EINA_TRUE;
3554
3555    if (buffer->type != E_COMP_WL_BUFFER_TYPE_SHM) return EINA_TRUE;
3556
3557    /* TODO : store and use multiple onscreen_parent for geometry calculation */
3558    onscreen_parent = parent_provider->onscreen_parent;
3559    if (!onscreen_parent) return EINA_TRUE;
3560
3561    if (!evas_object_visible_get(ec->frame)) return EINA_TRUE;
3562
3563    sdata = ec->comp_data->sub.data;
3564    evas_object_geometry_get(ec->frame, &fx, &fy, &fw, &fh);
3565
3566    EINA_LIST_FOREACH(parent_provider->common.ec->comp_data->remote_surface.regions, l, rect)
3567      {
3568         E_Comp_Wl_Remote_Region *region;
3569
3570         region = container_of(rect, E_Comp_Wl_Remote_Region, geometry);
3571
3572         x = sdata->position.x + rect->x;
3573         y = sdata->position.y + rect->y;
3574         if (onscreen_parent->owner)
3575           {
3576              x += onscreen_parent->owner->x;
3577              y += onscreen_parent->owner->y;
3578           }
3579
3580         if ((fx == x) && (fy == y) && (first_skip))
3581           {
3582              first_skip = EINA_FALSE;
3583              continue;
3584           }
3585
3586         w = ec->comp_data->width_from_viewport;
3587         h = ec->comp_data->height_from_viewport;
3588
3589         /* consider scale?
3590          * w = (int) (w * ((double)rect->w / parent_provider->ec->w));
3591          * h = (int) (h * ((double)rect->h / parent_provider->ec->h));
3592          */
3593
3594         if (!region->mirror)
3595           {
3596              region->mirror = e_comp_object_util_mirror_add(ec->frame);
3597              evas_object_layer_set(region->mirror, ec->layer);
3598              evas_object_stack_below(region->mirror, ec->frame);
3599              evas_object_show(region->mirror);
3600              evas_object_event_callback_add(region->mirror, EVAS_CALLBACK_DEL, _remote_region_cb_mirror_del, region);
3601           }
3602         if (!region->mirror) continue;
3603
3604         evas_object_move(region->mirror, x, y);
3605         evas_object_resize(region->mirror, w, h);
3606      }
3607
3608    return EINA_TRUE;
3609 }
3610 #endif /* HAVE_REMOTE_SURFACE */
3611
3612 EAPI E_Client*
3613 e_comp_wl_remote_surface_bound_provider_ec_get(E_Client *ec)
3614 {
3615 #ifdef HAVE_REMOTE_SURFACE
3616    E_Comp_Wl_Remote_Surface *remote_surface;
3617
3618    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
3619    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), NULL);
3620    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, NULL);
3621
3622    remote_surface = eina_hash_find(_rsm->bind_surface_hash, &ec);
3623    if (!remote_surface || !remote_surface->provider) return NULL;
3624
3625    return remote_surface->provider->common.ec;
3626 #endif /* HAVE_REMOTE_SURFACE */
3627 }
3628
3629 EINTERN Eina_Bool
3630 e_comp_wl_remote_surface_commit(E_Client *ec)
3631 {
3632 #ifdef HAVE_REMOTE_SURFACE
3633    E_Comp_Wl_Remote_Provider *provider;
3634    E_Comp_Wl_Remote_Source *source = NULL;
3635    E_Comp_Wl_Subsurf_Data *sdata, *ssdata;
3636    E_Client *offscreen_parent;
3637
3638    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
3639    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
3640    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
3641
3642    source = _remote_source_find(ec);
3643    if (source)
3644      {
3645         if (source->common.is_offscreen)
3646           {
3647              _e_comp_wl_remote_surface_state_commit(ec, &ec->comp_data->pending);
3648              return EINA_TRUE;
3649           }
3650
3651         //send update to remote_surface of source client
3652         _e_comp_wl_remote_surface_source_update(source, ec->comp_data->pending.buffer);
3653
3654         //do normal commit callback process
3655         return EINA_FALSE;
3656      }
3657
3658    /* subsurface case */
3659    if ((sdata = ec->comp_data->sub.data))
3660      {
3661         /* check for valid subcompositor data */
3662         if (!sdata->parent)
3663           return EINA_FALSE;
3664
3665         if (!(ssdata = sdata->parent->comp_data->sub.data))
3666           return EINA_FALSE;
3667
3668         if (!ssdata->remote_surface.offscreen_parent)
3669           return EINA_FALSE;
3670
3671         offscreen_parent = ssdata->remote_surface.offscreen_parent;
3672
3673         provider = _remote_provider_find(offscreen_parent);
3674         if (!provider) return EINA_FALSE;
3675
3676         if (!_e_comp_wl_remote_surface_subsurface_commit(provider, ec))
3677           return EINA_FALSE;
3678         return EINA_TRUE;
3679      }
3680
3681    if (!(provider = _remote_provider_find(ec)))
3682      return EINA_FALSE;
3683
3684    _e_comp_wl_remote_surface_state_commit(ec, &ec->comp_data->pending);
3685
3686    return EINA_TRUE;
3687 #else
3688    return EINA_FALSE;
3689 #endif /* HAVE_REMOTE_SURFACE */
3690 }
3691
3692 EAPI void
3693 e_comp_wl_remote_surface_image_save(E_Client *ec)
3694 {
3695 #ifdef HAVE_REMOTE_SURFACE
3696    E_Comp_Wl_Remote_Source *src;
3697
3698    if (!e_config->save_win_buffer) return;
3699    if (!e_config->hold_prev_win_img) return;
3700    if (ec->saved_img) return;
3701    if (ec->ignored) return;
3702    if (!_image_save_type_check(ec)) return;
3703
3704    src = _remote_source_get(ec);
3705    EINA_SAFETY_ON_NULL_GOTO(src, end);
3706
3707    _remote_source_save_start(src);
3708
3709 end:
3710    return;
3711 #endif /* HAVE_REMOTE_SURFACE */
3712 }
3713
3714 EAPI void
3715 e_comp_wl_remote_surface_image_save_skip_set(E_Client *ec, Eina_Bool set)
3716 {
3717    if (!e_config->save_win_buffer) return;
3718    if (e_object_is_del(E_OBJECT(ec))) return;
3719
3720    ec->skip_save_img = set;
3721 }
3722
3723 EAPI Eina_Bool
3724 e_comp_wl_remote_surface_image_save_skip_get(E_Client *ec)
3725 {
3726    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
3727    return ec->skip_save_img;
3728 }
3729
3730 EINTERN void
3731 e_comp_wl_remote_surface_debug_info_get(Eldbus_Message_Iter *iter)
3732 {
3733 #ifdef HAVE_REMOTE_SURFACE
3734    Eldbus_Message_Iter *line_array;
3735    Eina_Iterator *hash_iter;
3736    E_Comp_Wl_Remote_Provider *provider;
3737    E_Comp_Wl_Remote_Source *source;
3738    int idx = 0;
3739    char info_str[1024];
3740
3741    eldbus_message_iter_arguments_append(iter, "as", &line_array);
3742    if (!_rsm)
3743      {
3744         eldbus_message_iter_basic_append(line_array,
3745                                          's',
3746                                          "Remote Surface not initialized..");
3747         eldbus_message_iter_container_close(iter, line_array);
3748         return;
3749      }
3750
3751    /* PROVIDER */
3752    hash_iter = eina_hash_iterator_data_new(_rsm->provider_hash);
3753    EINA_ITERATOR_FOREACH(hash_iter, provider)
3754      {
3755         E_Client *ec = provider->common.ec;
3756         E_Comp_Wl_Remote_Surface *remote_surface;
3757         Eina_List *l;
3758
3759         if (!ec) continue;
3760
3761         snprintf(info_str, sizeof(info_str),
3762                  "%10s [%d] %8p win(0x%08zx) res(%d) pid(%d) vis(%d) name(%s)",
3763                  "PROVIDER", idx++, provider,
3764                  e_client_util_win_get(ec),
3765                  e_pixmap_res_id_get(ec->pixmap),
3766                  ec->netwm.pid,
3767                  provider->vis_ref,
3768                  e_client_util_name_get(ec)?:ec->icccm.class?:"NO NAME");
3769         eldbus_message_iter_basic_append(line_array, 's', info_str);
3770
3771         if (provider->common.surfaces)
3772           {
3773              snprintf(info_str, sizeof(info_str), "%7s", "│");
3774              eldbus_message_iter_basic_append(line_array, 's', info_str);
3775           }
3776
3777         EINA_LIST_FOREACH(provider->common.surfaces, l, remote_surface)
3778           {
3779              struct wl_client *wc = NULL;
3780              E_Client *owner = NULL;
3781              pid_t pid = -1;
3782              int s_idx = 0;
3783              Eina_Bool is_last = 0;
3784
3785              if (!remote_surface->resource) continue;
3786
3787              owner = remote_surface->owner;
3788              if (!owner)
3789                owner = remote_surface->bind_ec;
3790
3791              wc = wl_resource_get_client(remote_surface->resource);
3792              if (wc)
3793                wl_client_get_credentials(wc, &pid, NULL, NULL);
3794
3795              if ((eina_list_last(provider->common.surfaces) == l))
3796                  is_last = EINA_TRUE;
3797
3798              snprintf(info_str, sizeof(info_str),
3799                       "%10s CONSUMER [%d] %8p ec(%8p) win(0x%08zx) pid(%d) vis(%d) redirected(%d) name(%s)",
3800                       is_last? "└─" : "├─", s_idx++, remote_surface,
3801                       owner ? owner : NULL,
3802                       owner ? e_client_util_win_get(owner) : 0,
3803                       pid,
3804                       remote_surface->visible,
3805                       remote_surface->redirect,
3806                       owner? e_client_util_name_get(owner)?:owner->icccm.class?:"NO NAME":"NO OWNER"
3807                       );
3808              eldbus_message_iter_basic_append(line_array, 's', info_str);
3809           }
3810         eldbus_message_iter_basic_append(line_array, 's', "");
3811      }
3812    eina_iterator_free(hash_iter);
3813
3814    /* SOURCE */
3815    idx = 0;
3816    hash_iter = eina_hash_iterator_data_new(_rsm->source_hash);
3817    EINA_ITERATOR_FOREACH(hash_iter, source)
3818      {
3819         E_Client *ec = source->common.ec;
3820         E_Comp_Wl_Remote_Surface *remote_surface;
3821         Eina_List *l;
3822
3823         if (!ec) continue;
3824         snprintf(info_str, sizeof(info_str),
3825                  "%10s [%d] %8p win(0x%08zx) res(%d) pid(%d) offscreen(%d) name(%s)",
3826                  "SOURCE", idx++, source,
3827                  e_client_util_win_get(ec),
3828                  e_pixmap_res_id_get(ec->pixmap),
3829                  ec->netwm.pid,
3830                  source->offscreen_ref,
3831                  e_client_util_name_get(ec)?:ec->icccm.class?:"NO NAME");
3832         eldbus_message_iter_basic_append(line_array, 's', info_str);
3833
3834         if (source->common.surfaces)
3835           {
3836              snprintf(info_str, sizeof(info_str), "%7s", "│");
3837              eldbus_message_iter_basic_append(line_array, 's', info_str);
3838           }
3839
3840         EINA_LIST_FOREACH(source->common.surfaces, l, remote_surface)
3841           {
3842              struct wl_client *wc = NULL;
3843              E_Client *owner = NULL;
3844              pid_t pid = -1;
3845              int s_idx = 0;
3846              Eina_Bool is_last = 0;
3847
3848              if (!remote_surface->resource) continue;
3849
3850              owner = remote_surface->owner;
3851              if (!owner)
3852                owner = remote_surface->bind_ec;
3853
3854              wc = wl_resource_get_client(remote_surface->resource);
3855              if (wc)
3856                wl_client_get_credentials(wc, &pid, NULL, NULL);
3857
3858              if ((eina_list_last(source->common.surfaces) == l))
3859                is_last = EINA_TRUE;
3860
3861              snprintf(info_str, sizeof(info_str),
3862                       "%10s CONSUMER [%d] %8p ec(%8p) win(0x%08zx) pid(%d) vis(%d) redirected(%d) name(%s)",
3863                       is_last? "└─" : "├─", s_idx++, remote_surface,
3864                       owner ? owner : NULL,
3865                       owner ? e_client_util_win_get(owner) : 0,
3866                       pid,
3867                       remote_surface->visible,
3868                       remote_surface->redirect,
3869                       owner? e_client_util_name_get(owner)?:owner->icccm.class?:"NO NAME":"NO OWNER"
3870                      );
3871              eldbus_message_iter_basic_append(line_array, 's', info_str);
3872           }
3873         eldbus_message_iter_basic_append(line_array, 's', "");
3874      }
3875    eina_iterator_free(hash_iter);
3876
3877    eldbus_message_iter_container_close(iter, line_array);
3878 #else
3879    Eldbus_Message_Iter *line_array;
3880
3881    eldbus_message_iter_arguments_append(iter, "as", &line_array);
3882    eldbus_message_iter_basic_append(line_array,
3883                                     's',
3884                                     "Enlightenment doesn't support remote surface");
3885    eldbus_message_iter_container_close(iter, line_array);
3886 #endif
3887 }
3888
3889 #undef E_CLIENT_HOOK_APPEND
3890 #define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
3891   do                                      \
3892     {                                     \
3893        E_Client_Hook *_h;                 \
3894        _h = e_client_hook_add(t, cb, d);  \
3895        assert(_h);                        \
3896        l = eina_list_append(l, _h);       \
3897     }                                     \
3898   while (0)
3899
3900 EINTERN void
3901 e_comp_wl_remote_surface_init(void)
3902 {
3903 #ifdef HAVE_REMOTE_SURFACE
3904    E_Comp_Wl_Remote_Manager *rs_manager = NULL;
3905
3906    EINA_SAFETY_ON_NULL_RETURN(e_comp_wl);
3907    EINA_SAFETY_ON_NULL_RETURN(e_comp_wl->wl.disp);
3908    EINA_SAFETY_ON_NULL_RETURN(e_comp->wl_comp_data->tbm.server);
3909
3910    rs_manager = E_NEW(E_Comp_Wl_Remote_Manager, 1);
3911    EINA_SAFETY_ON_NULL_RETURN(rs_manager);
3912
3913    rs_manager->global = wl_global_create(e_comp_wl->wl.disp,
3914                                          &tizen_remote_surface_manager_interface,
3915                                          5,
3916                                          NULL,
3917                                          _remote_manager_cb_bind);
3918
3919    /* client hook */
3920    E_CLIENT_HOOK_APPEND(rs_manager->client_hooks, E_CLIENT_HOOK_DEL, _e_comp_wl_remote_cb_client_del, NULL);
3921    if (e_config->save_win_buffer)
3922      {
3923         E_CLIENT_HOOK_APPEND(rs_manager->client_hooks, E_CLIENT_HOOK_ICONIFY,   _e_comp_wl_remote_cb_client_iconify,   NULL);
3924         E_CLIENT_HOOK_APPEND(rs_manager->client_hooks, E_CLIENT_HOOK_UNICONIFY, _e_comp_wl_remote_cb_client_uniconify, NULL);
3925      }
3926
3927    /* client event */
3928    E_LIST_HANDLER_APPEND(rs_manager->event_hdlrs,
3929                          E_EVENT_CLIENT_VISIBILITY_CHANGE,
3930                          _e_comp_wl_remote_cb_visibility_change, rs_manager);
3931
3932    rs_manager->provider_hash = eina_hash_pointer_new(NULL);
3933    rs_manager->surface_hash = eina_hash_pointer_new(NULL);
3934    rs_manager->source_hash = eina_hash_pointer_new(NULL);
3935    rs_manager->bind_surface_hash = eina_hash_pointer_new(NULL);
3936    rs_manager->dummy_fd = _e_comp_wl_remote_surface_dummy_fd_get();
3937
3938    if (rs_manager->dummy_fd == -1)
3939      {
3940         ERR("it's FATAL error, remote surface can't send remote buffer without dummy_fd...");
3941         _rsm = rs_manager;
3942         e_comp_wl_remote_surface_shutdown();
3943         return;
3944      }
3945
3946    RSMINF("dummy_fd created %d", NULL, NULL, "MANAGER", rs_manager, rs_manager->dummy_fd);
3947
3948    _rsm = rs_manager;
3949
3950    E_EVENT_REMOTE_SURFACE_PROVIDER_VISIBILITY_CHANGE = ecore_event_type_new();
3951 #endif /* HAVE_REMOTE_SURFACE */
3952 }
3953
3954 EINTERN void
3955 e_comp_wl_remote_surface_shutdown(void)
3956 {
3957 #ifdef HAVE_REMOTE_SURFACE
3958    E_Comp_Wl_Remote_Manager *rsm;
3959    E_Comp_Wl_Remote_Provider *provider;
3960    E_Comp_Wl_Remote_Source *source;
3961    E_Comp_Wl_Remote_Surface *remote_surface;
3962    Eina_Iterator *it;
3963
3964    if (!_rsm) return;
3965
3966    rsm = _rsm;
3967    _rsm = NULL;
3968
3969    it = eina_hash_iterator_data_new(rsm->provider_hash);
3970    EINA_ITERATOR_FOREACH(it, provider)
3971      {
3972         EINA_LIST_FREE(provider->common.surfaces, remote_surface)
3973           {
3974              remote_surface->provider = NULL;
3975              wl_resource_destroy(remote_surface->resource);
3976           }
3977         wl_resource_destroy(provider->resource);
3978      }
3979    eina_iterator_free(it);
3980
3981    it = eina_hash_iterator_data_new(rsm->source_hash);
3982    EINA_ITERATOR_FOREACH(it, source)
3983      {
3984         EINA_LIST_FREE(source->common.surfaces, remote_surface)
3985           {
3986              remote_surface->source = NULL;
3987              wl_resource_destroy(remote_surface->resource);
3988           }
3989         _remote_source_destroy(source);
3990      }
3991    eina_iterator_free(it);
3992
3993    if (rsm->dummy_fd != -1)
3994      close(rsm->dummy_fd);
3995
3996    E_FREE_LIST(rsm->process_hooks, e_process_hook_del);
3997
3998    E_FREE_FUNC(rsm->provider_hash, eina_hash_free);
3999    E_FREE_FUNC(rsm->surface_hash, eina_hash_free);
4000    E_FREE_FUNC(rsm->source_hash, eina_hash_free);
4001    E_FREE_FUNC(rsm->bind_surface_hash, eina_hash_free);
4002
4003    E_FREE_LIST(rsm->client_hooks, e_client_hook_del);
4004    E_FREE_LIST(rsm->event_hdlrs, ecore_event_handler_del);
4005    wl_global_destroy(rsm->global);
4006    E_FREE(rsm);
4007 #endif /* HAVE_REMOTE_SURFACE */
4008 }