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