compositor: Add destroy signal of E_Surface
[platform/upstream/enlightenment.git] / src / bin / server / e_compositor.c
1 #include "e_compositor_intern.h"
2 #include "e_comp_wl_intern.h"
3 #include "e_comp_wl_buffer_intern.h"
4 #include "e_comp_wl_data_intern.h"
5 #include "e_comp_wl_rsm_intern.h"
6 #include "e_comp_wl_subsurface_intern.h"
7 #include "e_comp_intern.h"
8 #include "e_pixmap_intern.h"
9 #include "e_presentation_time_intern.h"
10 #include "e_client_video_intern.h"
11 #include "e_client_intern.h"
12
13 #include <libds/compositor.h>
14 #include <libds/subcompositor.h>
15 #include <libds/types/ds_surface.h>
16 #include <libds/types/ds_subsurface.h>
17
18 typedef struct _E_Compositor E_Compositor;
19 typedef struct _E_Subsurface E_Subsurface;
20 typedef struct _E_Frame_Callback E_Frame_Callback;
21
22 struct _E_Compositor
23 {
24    struct ds_compositor *ds_compositor;
25    struct ds_subcompositor *ds_subcompositor;
26
27    E_Client_Hook *new_client_hook;
28
29    struct wl_listener new_surface;
30    struct wl_listener display_destroy;
31 };
32
33 struct _E_Surface
34 {
35    E_Comp_Wl_Client_Data base;
36
37    E_Client *ec;
38    struct ds_surface *ds_surface;
39    struct ds_surface_viewport *surface_viewport;
40
41    E_Client_Hook *client_del_hook;
42
43    struct wl_listener destroy;
44    struct wl_listener commit;
45    struct wl_listener new_subsurface;
46
47    struct
48      {
49         struct wl_signal destroy;
50         struct wl_signal parent_destroy;
51      } events;
52 };
53
54 struct _E_Subsurface
55 {
56    E_Comp_Wl_Subsurf_Data base;
57
58    E_Surface *surface;
59    struct ds_subsurface *ds_subsurface;
60
61    struct wl_listener destroy;
62    struct wl_listener surface_destroy;
63    struct wl_listener parent_surface_destroy;
64    struct wl_listener cached;
65    struct wl_listener request_move;
66 };
67
68 struct _E_Frame_Callback
69 {
70    E_Client *ec;
71    struct wl_listener destroy;
72 };
73
74 static void _e_compositor_cb_display_destroy(struct wl_listener *listener, void *data);
75 static void _e_compositor_cb_new_surface(struct wl_listener *listener, void *data);
76 static void _e_compositor_cb_new_client(void *data EINA_UNUSED, E_Client *ec);
77
78 static E_Surface *_e_surface_create(E_Client *ec);
79 static E_Surface *_e_surface_from_ds_surface(struct ds_surface *ds_surface);
80 static E_Surface *_e_surface_from_comp_data(E_Comp_Wl_Client_Data *comp_data);
81 static void _e_surface_destroy(E_Surface *surface);
82 static void _e_surface_ds_surface_set(E_Surface *surface, struct ds_surface *ds_surface);
83 static void _e_surface_cb_client_del(void *data, E_Client *ec);
84 static void _e_surface_cb_destroy(struct wl_listener *listener, void *data);
85 static void _e_surface_cb_commit(struct wl_listener *listener, void *data);
86 static void _e_surface_cb_new_subsurface(struct wl_listener *listener, void *data);
87
88 static E_Subsurface *_e_subsurface_create(struct ds_subsurface *ds_subsurface, E_Surface *parent_surface);
89 static E_Subsurface *_e_subsurface_from_surface(E_Surface *surface);
90 static E_Subsurface *_e_subsurface_from_resource(struct wl_resource *resource);
91 static E_Subsurface *_e_subsurface_from_ds_subsurface(struct ds_subsurface *ds_subsurface);
92 static void _e_subsurface_destroy(E_Subsurface *sub);
93 static void _e_subsurface_commit(E_Subsurface *sub);
94 static void _e_subsurface_place_below_parent(E_Subsurface *sub);
95 static void _e_subsurface_position_update(E_Subsurface *sub);
96 static void _e_subsurface_cb_destroy(struct wl_listener *listener, void *data);
97 static void _e_subsurface_cb_cached(struct wl_listener *listener, void *data);
98 static void _e_subsurface_cb_request_move(struct wl_listener *listener, void *data);
99 static void _e_subsurface_cb_surface_destroy(struct wl_listener *listener, void *data);
100 static void _e_subsurface_cb_parent_surface_destroy(struct wl_listener *listener, void *data);
101
102 static void _ds_surface_buffer_transform_set(struct ds_surface *ds_surface, enum wl_output_transform transform);
103 static void _ds_surface_viewport_source_box_set(struct ds_surface *ds_surface, Eina_Rectangle *box);
104 static void _ds_surface_viewport_destination_set(struct ds_surface *ds_surface, int32_t width, int32_t height);
105 static void _ds_surface_viewport_unset(struct ds_surface *ds_surface);
106 static void _ds_subsurface_position_set(struct ds_subsurface *ds_subsurface, int x, int y);
107
108 static const char *e_comp_wl_subsurface_role_name = "ds_subsurface";
109 static E_Compositor *_compositor;
110
111 EINTERN Eina_Bool
112 e_compositor_init(struct wl_display *display)
113 {
114    E_Compositor *comp;
115
116    if (_compositor)
117      return EINA_TRUE;
118
119    comp = E_NEW(E_Compositor, 1);
120    if (!comp)
121      return EINA_FALSE;
122
123    comp->ds_compositor = ds_compositor_create(display);
124    if (!comp->ds_compositor)
125      {
126         ELOGF("COMPOSITOR", "Could not create ds_compositor", NULL);
127         free(comp);
128         return EINA_FALSE;
129      }
130
131    comp->ds_subcompositor = ds_subcompositor_create(display);
132    if (!comp->ds_subcompositor)
133      {
134         ELOGF("COMPOSITOR", "Could not create ds_subcompositor", NULL);
135         free(comp);
136         return EINA_FALSE;
137      }
138
139    comp->new_surface.notify = _e_compositor_cb_new_surface;
140    ds_compositor_add_new_surface_listener(comp->ds_compositor,
141                                           &comp->new_surface);
142
143    comp->new_client_hook = e_client_hook_add(E_CLIENT_HOOK_NEW_CLIENT,
144                                              _e_compositor_cb_new_client,
145                                              NULL);
146
147    comp->display_destroy.notify = _e_compositor_cb_display_destroy;
148    wl_display_add_destroy_listener(display, &comp->display_destroy);
149
150    _compositor = comp;
151
152    return EINA_TRUE;
153 }
154
155 EINTERN E_Client *
156 e_compositor_util_client_from_surface_resource(struct wl_resource *surface_resource)
157 {
158    E_Surface *surface;
159    struct ds_surface *ds_surface;
160
161    ds_surface = ds_surface_from_resource(surface_resource);
162    if (!ds_surface)
163      return NULL;
164
165    surface = _e_surface_from_ds_surface(ds_surface);
166    if (!surface)
167      return NULL;
168
169    return surface->ec;
170 }
171
172 EINTERN Eina_Bool
173 e_comp_wl_subsurface_add(struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource)
174 {
175    return !!ds_subsurface_create(resource,
176                                  ds_surface_from_resource(surface_resource),
177                                  ds_surface_from_resource(parent_resource),
178                                  id);
179 }
180
181 EINTERN void
182 e_comp_wl_subsurface_resource_stand_alone_mode_set(struct wl_resource *subsurface_resource)
183 {
184    E_Subsurface *sub;
185
186    sub = _e_subsurface_from_resource(subsurface_resource);
187    if (!sub)
188      {
189         INF("The given subsurface resource(%p) seems inert.", subsurface_resource);
190         return;
191      }
192
193    ELOGF("SUBSURFACE", "SUBSURF|STAND_ALONE", sub->surface->ec);
194
195    sub->base.stand_alone = EINA_TRUE;
196 }
197
198 EINTERN void
199 e_comp_wl_subsurface_resource_place_below_parent(struct wl_resource *subsurface_resource)
200 {
201    E_Subsurface *sub;
202    E_Comp_Wl_Client_Data *epc_cdata;
203
204    sub = _e_subsurface_from_resource(subsurface_resource);
205    if (!sub)
206      {
207         INF("The given subsurface resource(%p) seems inert.", subsurface_resource);
208         return;
209      }
210
211    EINA_SAFETY_ON_NULL_RETURN(sub->base.parent);
212    epc_cdata = e_client_cdata_get(sub->base.parent);
213    EINA_SAFETY_ON_NULL_RETURN(epc_cdata);
214
215    ELOGF("SUBSURFACE", "SUBSURF|BELOW_PARENT", sub->surface->ec);
216
217    _e_subsurface_place_below_parent(sub);
218
219    epc_cdata->sub.list = eina_list_remove(epc_cdata->sub.list, sub->surface->ec);
220    epc_cdata->sub.list_pending = eina_list_remove(epc_cdata->sub.list_pending, sub->surface->ec);
221    epc_cdata->sub.below_list = eina_list_remove(epc_cdata->sub.below_list, sub->surface->ec);
222    epc_cdata->sub.below_list_pending = eina_list_remove(epc_cdata->sub.below_list_pending, sub->surface->ec);
223
224    epc_cdata->sub.below_list_pending = eina_list_append(epc_cdata->sub.below_list_pending, sub->surface->ec);
225    epc_cdata->sub.below_list = eina_list_append(epc_cdata->sub.below_list, sub->surface->ec);
226    epc_cdata->sub.list_changed = EINA_TRUE;
227 }
228
229 EINTERN Eina_Bool
230 e_comp_wl_subsurface_commit(E_Client *ec)
231 {
232    E_Surface *surface;
233    E_Subsurface *sub;
234
235    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
236
237    if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return EINA_FALSE;
238
239    surface = _e_surface_from_comp_data(ec->comp_data);
240    sub = _e_subsurface_from_surface(surface);
241    if (!sub)
242      return EINA_FALSE;
243
244    _e_subsurface_commit(sub);
245
246    return EINA_TRUE;
247 }
248
249 EINTERN E_Surface *
250 e_surface_from_resource(struct wl_resource *surface_resource)
251 {
252    E_Surface *surface;
253    struct ds_surface *ds_surface;
254
255    ds_surface = ds_surface_from_resource(surface_resource);
256    if (!ds_surface)
257      return NULL;
258
259    surface = _e_surface_from_ds_surface(ds_surface);
260    if (!surface)
261      return NULL;
262
263    return surface;
264 }
265
266 EINTERN void
267 e_surface_destroy_listener_add(E_Surface *surface, struct wl_listener *listener)
268 {
269    wl_signal_add(&surface->events.destroy, listener);
270 }
271
272 EINTERN struct wl_listener *
273 e_surface_destroy_listener_get(E_Surface *surface, wl_notify_func_t notify)
274 {
275    return wl_signal_get(&surface->events.destroy, notify);
276 }
277
278 EINTERN void
279 e_surface_parent_destroy_listener_add(E_Surface *surface, struct wl_listener *listener)
280 {
281    wl_signal_add(&surface->events.parent_destroy, listener);
282 }
283
284 EINTERN Eina_Bool
285 e_surface_viewporter_resource_set(E_Surface *surface, struct wl_resource *viewporter)
286 {
287    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
288
289    if (surface->base.scaler.viewport)
290      return EINA_FALSE;
291
292    if (surface->surface_viewport)
293      return EINA_FALSE;
294
295    surface->surface_viewport = ds_surface_take_viewport(surface->ds_surface);
296    if (!surface->surface_viewport)
297      return EINA_FALSE;
298
299    surface->base.scaler.viewport = viewporter;
300
301    return EINA_TRUE;
302 }
303
304 EINTERN void
305 e_surface_viewporter_resource_unset(E_Surface *surface)
306 {
307    EINA_SAFETY_ON_NULL_RETURN(surface);
308
309    surface->base.scaler.viewport = NULL;
310    surface->base.scaler.buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
311    surface->base.scaler.buffer_viewport.surface.width = -1;
312    surface->base.scaler.buffer_viewport.changed = 1;
313    surface->base.pending.buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
314    surface->base.pending.buffer_viewport.surface.width = -1;
315    surface->base.pending.buffer_viewport.changed = 1;
316
317    if (surface->surface_viewport)
318      {
319         ds_surface_viewport_release(surface->surface_viewport);
320         surface->surface_viewport = NULL;
321      }
322
323    if (surface->ds_surface)
324      _ds_surface_viewport_unset(surface->ds_surface);
325 }
326
327 EINTERN enum wl_output_transform
328 e_surface_buffer_transform_get(E_Surface *surface)
329 {
330    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, WL_OUTPUT_TRANSFORM_NORMAL);
331    return surface->base.scaler.buffer_viewport.buffer.transform;
332 }
333
334 EINTERN Eina_Bool
335 e_surface_buffer_transform_set(E_Surface *surface, enum wl_output_transform transform)
336 {
337    E_Subsurface *sub;
338    E_Comp_Wl_Buffer_Viewport *vp;
339
340    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
341
342    vp = &surface->base.scaler.buffer_viewport;
343    if (vp->buffer.transform == transform)
344      return EINA_FALSE;
345
346    vp->buffer.transform = transform;
347    vp->changed = EINA_TRUE;
348
349    surface->base.pending.buffer_viewport = *vp;
350
351    sub = _e_subsurface_from_surface(surface);
352    if (sub)
353      sub->base.cached.buffer_viewport = *vp;
354
355    if (surface->ds_surface)
356      _ds_surface_buffer_transform_set(surface->ds_surface, transform);
357
358    return EINA_TRUE;
359 }
360
361 EINTERN Eina_Bool
362 e_surface_viewport_source_box_set(E_Surface *surface, Eina_Rectangle *box)
363 {
364    E_Subsurface *sub;
365    E_Comp_Wl_Buffer_Viewport *vp;
366    wl_fixed_t fx, fy, fw, fh;
367
368    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
369
370    fx = wl_fixed_from_int(box->x);
371    fy = wl_fixed_from_int(box->y);
372    fw = wl_fixed_from_int(box->w);
373    fh = wl_fixed_from_int(box->h);
374
375    vp = &surface->base.scaler.buffer_viewport;
376    if ((vp->buffer.src_x == fx) && (vp->buffer.src_y == fy) &&
377        (vp->buffer.src_width == fw) && (vp->buffer.src_height == fh))
378      return EINA_FALSE;
379
380    vp->buffer.src_x = fx;
381    vp->buffer.src_y = fy;
382    vp->buffer.src_width = fw;
383    vp->buffer.src_height = fh;
384    vp->changed = EINA_TRUE;
385
386    surface->base.pending.buffer_viewport = *vp;
387
388    sub = _e_subsurface_from_surface(surface);
389    if (sub)
390      sub->base.cached.buffer_viewport = *vp;
391
392    if (surface->ds_surface)
393      _ds_surface_viewport_source_box_set(surface->ds_surface, box);
394
395    return EINA_TRUE;
396 }
397
398 EINTERN Eina_Bool
399 e_surface_viewport_destination_set(E_Surface *surface, int32_t width, int32_t height)
400 {
401    E_Subsurface *sub;
402    E_Comp_Wl_Buffer_Viewport *vp;
403
404    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
405
406    vp = &surface->base.scaler.buffer_viewport;
407    if ((vp->surface.width == width) && (vp->surface.height == height))
408      return EINA_FALSE;
409
410    vp->surface.width = width;
411    vp->surface.height = height;
412    vp->changed = EINA_TRUE;
413
414    surface->base.pending.buffer_viewport = *vp;
415
416    sub = _e_subsurface_from_surface(surface);
417    if (sub)
418      sub->base.cached.buffer_viewport = *vp;
419
420    if (surface->ds_surface)
421      _ds_surface_viewport_destination_set(surface->ds_surface, width, height);
422
423    return EINA_TRUE;
424 }
425
426 EINTERN Eina_Bool
427 e_surface_viewport_changed_get(E_Surface *surface)
428 {
429    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
430    return surface->base.scaler.buffer_viewport.changed;
431 }
432
433 EINTERN E_Subsurface *
434 e_subsurface_from_surface(E_Surface *surface)
435 {
436    EINA_SAFETY_ON_NULL_RETURN_VAL(surface, NULL);
437    return _e_subsurface_from_surface(surface);
438 }
439
440 EINTERN Eina_Bool
441 e_subsurface_position_set(E_Subsurface *subsurface, int x, int y)
442 {
443    EINA_SAFETY_ON_NULL_RETURN_VAL(subsurface, EINA_FALSE);
444
445    if ((subsurface->base.position.x == x) && (subsurface->base.position.y == y))
446     return EINA_FALSE;
447
448    subsurface->base.position.x = x;
449    subsurface->base.position.y = y;
450    subsurface->base.position.set = EINA_TRUE;
451
452    _ds_subsurface_position_set(subsurface->ds_subsurface, x, y);
453
454    return EINA_TRUE;
455 }
456
457 static void
458 _e_compositor_cb_display_destroy(struct wl_listener *listener EINA_UNUSED, void *data EINA_UNUSED)
459 {
460    wl_list_remove(&_compositor->display_destroy.link);
461    wl_list_remove(&_compositor->new_surface.link);
462    e_client_hook_del(_compositor->new_client_hook);
463    E_FREE(_compositor);
464 }
465
466 static E_Client *
467 _e_comp_wl_client_usable_get(pid_t pid, E_Pixmap *ep)
468 {
469    /* NOTE: this will return usable E_Client for a surface of specified process
470     * by pid. it doesn't care whatever this surfaces is for but care only what
471     * is owner process of the surface.
472     */
473
474    E_Client *ec = NULL, *_ec = NULL;
475    Eina_List *l;
476
477    /* find launchscreen client list */
478    if (e_comp->launchscrns)
479      {
480         EINA_LIST_FOREACH(e_comp->launchscrns, l, _ec)
481           {
482              if (_ec->netwm.pid == pid)
483                {
484                   ec = _ec;
485                   break;
486                }
487           }
488         if (ec)
489           {
490              E_Pixmap *oldep = NULL;
491
492              if (ec->comp_data)
493                {
494                   /* do NOT replace with the client having comp data */
495                   return NULL;
496                }
497
498              e_comp->launchscrns = eina_list_remove(e_comp->launchscrns, ec);
499
500              oldep = e_client_pixmap_change(ec, ep);
501              if (oldep)
502                {
503                   e_pixmap_win_id_del(oldep);
504                   e_pixmap_free(oldep);
505                }
506
507              if (ec->internal)
508                ec->internal = 0;
509
510              /* to set-up comp data */
511              _e_compositor_cb_new_client(NULL, ec);
512              ec->ignored = 0;
513              if (!ec->comp_data) return NULL;
514              e_comp_wl_client_evas_init(ec);
515
516              ELOGF("COMP", "Reusable ec. new_pixmap:%p", ec, ec->pixmap);
517              e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_REUSE, ec);
518           }
519      }
520
521    return ec;
522 }
523
524 static void
525 _e_compositor_cb_new_surface(struct wl_listener *listener, void *data)
526 {
527    struct ds_surface *ds_surface = data;
528    E_Client *ec = NULL;
529    E_Pixmap *ep;
530    struct wl_resource *surface_resource;
531    pid_t pid;
532    int internal = 0;
533
534    DBG("New ds_surface %p", ds_surface);
535
536    TRACE_DS_BEGIN(COMP_WL:NEW SURFACE CB);
537
538    surface_resource = ds_surface_get_wl_resource(ds_surface);
539    wl_client_get_credentials(wl_resource_get_client(surface_resource), &pid, NULL, NULL);
540    if (pid == getpid())
541      {
542         internal = 1;
543         ec = e_pixmap_find_client(E_PIXMAP_TYPE_WL, (uintptr_t)wl_resource_get_id(surface_resource));
544      }
545    else if ((ep = e_pixmap_find(E_PIXMAP_TYPE_WL, (uintptr_t)surface_resource)))
546      {
547         ERR("There is e_pixmap already, Delete old e_pixmap %p", ep);
548         e_pixmap_win_id_del(ep);
549      }
550
551    if (!ec)
552      {
553         /* try to create new pixmap */
554         if (!(ep = e_pixmap_new(E_PIXMAP_TYPE_WL, surface_resource)))
555           {
556              ERR("Could not create new pixmap");
557              TRACE_DS_END();
558              return;
559           }
560
561         E_Comp_Wl_Client_Data *cdata = e_pixmap_cdata_get(ep);
562         if (cdata)
563           cdata->wl_surface = surface_resource;
564
565         DBG("\tUsing Pixmap: %p", ep);
566
567         if (!(ec = _e_comp_wl_client_usable_get(pid, ep)))
568           {
569              ec = e_client_new(ep, 0, internal);
570           }
571      }
572    if (ec)
573      {
574         if (!ec->netwm.pid)
575           ec->netwm.pid = pid;
576         if (ec->new_client)
577           e_comp->new_clients--;
578         ec->new_client = 0;
579         if ((!ec->client.w) && (ec->client.h))
580           ec->client.w = ec->client.h = 1;
581
582         e_comp_wl_client_surface_set(ec, surface_resource);
583         ec->icccm.accepts_focus = 1;
584         wl_list_init(&ec->comp_data->pointer_constraints);
585
586         _e_surface_ds_surface_set(_e_surface_from_comp_data(ec->comp_data),
587                                   ds_surface);
588      }
589
590    DBG("\tUsing Client: %p", ec);
591
592    TRACE_DS_END();
593 }
594
595 static void
596 _e_compositor_cb_new_client(void *data EINA_UNUSED, E_Client *ec)
597 {
598    E_Surface *surface;
599    Ecore_Window win;
600
601    /* make sure this is a wayland client */
602    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
603
604    TRACE_DS_BEGIN(COMP_WL:CLIENT NEW HOOK);
605
606    /* get window id from pixmap */
607    win = e_pixmap_window_get(ec->pixmap);
608
609    /* ignore fake root windows */
610    if ((ec->override) && ((ec->x == -77) && (ec->y == -77)))
611      {
612         e_comp_ignore_win_add(E_PIXMAP_TYPE_WL, win);
613         e_object_del(E_OBJECT(ec));
614         TRACE_DS_END();
615         return;
616      }
617
618    surface = _e_surface_create(ec);
619    if (!surface)
620      {
621         ERR("Could not create E_Surface");
622         TRACE_DS_END();
623         return;
624      }
625
626    ec->comp_data = &surface->base;
627
628    /* set initial client properties */
629    ec->argb = EINA_FALSE;
630    ELOGF("COMP", "Set argb:%d", ec, ec->argb);
631    ec->redirected = ec->ignored = 1;
632    ec->border_size = 0;
633
634    /* NB: could not find a better place to do this, BUT for internal windows,
635     * we need to set delete_request else the close buttons on the frames do
636     * basically nothing */
637    if (ec->internal)
638      ec->icccm.delete_request = EINA_TRUE;
639
640    E_Comp_Wl_Client_Data *p_cdata = e_pixmap_cdata_get(ec->pixmap);
641    EINA_SAFETY_ON_NULL_GOTO(p_cdata, end);
642
643    e_pixmap_cdata_set(ec->pixmap, &surface->base);
644
645    g_mutex_init(&ec->comp_data->surface_mutex);
646
647 end:
648    TRACE_DS_END();
649 }
650
651 static E_Surface *
652 _e_surface_create(E_Client *ec)
653 {
654    E_Surface *surface;
655
656    surface = E_NEW(E_Surface, 1);
657    if (!surface)
658      return NULL;
659
660    e_object_ref(E_OBJECT(ec));
661    surface->ec = ec;
662
663    wl_signal_init(&surface->events.destroy);
664    wl_signal_init(&surface->events.parent_destroy);
665    wl_signal_init(&surface->base.destroy_signal);
666    wl_signal_init(&surface->base.apply_viewport_signal);
667    wl_signal_init(&surface->base.state_commit_signal);
668
669    e_comp_wl_surface_state_init(&surface->base.pending, ec->w, ec->h);
670
671    /* set initial client data properties */
672    surface->base.mapped = EINA_FALSE;
673    surface->base.first_damage = ec->internal;
674    surface->base.need_reparent = !ec->internal;
675
676    /* set initial value of scaler */
677    surface->base.scaler.buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
678    surface->base.scaler.buffer_viewport.buffer.scale = 1;
679    surface->base.scaler.buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
680    surface->base.scaler.buffer_viewport.surface.width = -1;
681
682    e_presentation_time_container_init(&surface->base.presentation_container);
683
684    surface->client_del_hook = e_client_hook_add(E_CLIENT_HOOK_DEL,
685                                                 _e_surface_cb_client_del,
686                                                 surface);
687
688    return surface;
689 }
690
691 static void
692 _e_surface_destroy(E_Surface *surface)
693 {
694    struct wl_resource *cb;
695
696    g_mutex_lock(&surface->base.surface_mutex);
697
698    wl_signal_emit(&surface->base.destroy_signal, &surface->base.surface);
699
700    e_comp_wl_surface_state_finish(&surface->base.pending);
701
702    e_comp_wl_buffer_reference(&surface->base.buffer_ref, NULL);
703
704    EINA_LIST_FREE(surface->base.frames, cb)
705      wl_resource_destroy(cb);
706
707    EINA_LIST_FREE(surface->base.pending.frames, cb)
708      wl_resource_destroy(cb);
709
710    if (surface->base.aux_hint.hints)
711      {
712         E_Comp_Wl_Aux_Hint *hint;
713         EINA_LIST_FREE(surface->base.aux_hint.hints, hint)
714           {
715              eina_stringshare_del(hint->hint);
716              eina_stringshare_del(hint->val);
717              E_FREE(hint);
718           }
719      }
720
721    if (e_comp_wl->ptr.ec == surface->ec)
722      {
723         e_comp_wl->ptr.ec = NULL;
724         E_FREE_FUNC(e_comp_wl->ptr.hide_tmr, ecore_timer_del);
725      }
726
727    if (e_comp_wl->touch.faked_ec == surface->ec)
728      e_comp_wl->touch.faked_ec = NULL;
729
730    if (e_comp_wl->selection.cbhm == surface->base.surface)
731      e_comp_wl->selection.cbhm = NULL;
732
733    e_comp_wl_data_secondary_remove(surface->ec);
734
735    if (surface->base.viewport_transform)
736      {
737         e_client_transform_core_remove(surface->ec, surface->base.viewport_transform);
738         e_util_transform_del(surface->base.viewport_transform);
739         surface->base.viewport_transform = NULL;
740      }
741
742    e_presentation_time_container_finish(&surface->base.presentation_container);
743
744    E_FREE_FUNC(surface->base.on_focus_timer, ecore_timer_del);
745
746    e_client_hook_del(surface->client_del_hook);
747
748    g_mutex_unlock(&surface->base.surface_mutex);
749
750    g_mutex_clear(&surface->base.surface_mutex);
751
752    surface->ec->comp_data = NULL;
753    e_object_unref(E_OBJECT(surface->ec));
754    free(surface);
755 }
756
757 static void
758 _e_surface_ds_surface_set(E_Surface *surface, struct ds_surface *ds_surface)
759 {
760    surface->ds_surface = ds_surface;
761
762    surface->destroy.notify = _e_surface_cb_destroy;
763    ds_surface_add_destroy_listener(ds_surface, &surface->destroy);
764
765    surface->commit.notify = _e_surface_cb_commit;
766    ds_surface_add_commit_listener(ds_surface, &surface->commit);
767
768    surface->new_subsurface.notify = _e_surface_cb_new_subsurface;
769    ds_surface_add_new_subsurface_listener(ds_surface, &surface->new_subsurface);
770 }
771
772 static E_Surface *
773 _e_surface_from_ds_surface(struct ds_surface *ds_surface)
774 {
775    E_Surface *surface = NULL;
776    struct wl_listener *listener;
777
778    listener = wl_signal_get(&ds_surface->events.destroy,
779                             _e_surface_cb_destroy);
780    if (listener)
781      surface = wl_container_of(listener, surface, destroy);
782
783    return surface;
784 }
785
786 static E_Surface *
787 _e_surface_from_comp_data(E_Comp_Wl_Client_Data *comp_data)
788 {
789    E_Surface *surface;
790    return wl_container_of(comp_data, surface, base);
791 }
792
793 static E_Surface *
794 _e_surface_root_surface_get(E_Surface *surface)
795 {
796    E_Surface *iter = surface;
797    E_Subsurface *sub;
798
799    while ((sub = _e_subsurface_from_surface(iter)))
800      iter = _e_surface_from_ds_surface(sub->ds_subsurface->parent);
801
802    return iter;
803 }
804
805 static void
806 _e_surface_buffer_video_content_type_check_and_set(E_Surface *surface, E_Comp_Wl_Buffer *buffer)
807 {
808    E_Client *ec = surface->ec;
809
810    if (ec->comp_data->video_client)
811      {
812         buffer->type = E_COMP_WL_BUFFER_TYPE_VIDEO;
813         buffer->w = buffer->h = 1;
814         buffer->format = 0;
815      }
816    else if (e_client_video_hw_composition_check(ec))
817      {
818         buffer->type = E_COMP_WL_BUFFER_TYPE_VIDEO;
819      }
820 }
821
822 static void
823 _e_surface_pending_buffer_update(E_Surface *surface)
824 {
825    struct ds_surface *ds_surface = surface->ds_surface;
826    E_Client *ec = surface->ec;
827    E_Comp_Wl_Buffer *buffer = NULL;
828
829    if (ds_surface->buffer)
830      {
831         buffer = e_comp_wl_buffer_get(ds_surface->buffer);
832         if (buffer)
833           _e_surface_buffer_video_content_type_check_and_set(surface, buffer);
834      }
835
836    e_comp_wl_client_surface_pending_buffer_set(ec, buffer,
837                                                ds_surface->current.dx,
838                                                ds_surface->current.dy);
839 }
840
841 static void
842 _e_surface_pending_surface_damage_update(E_Surface *surface)
843 {
844    struct ds_surface *ds_surface = surface->ds_surface;
845    pixman_box32_t *rects;
846    int32_t x, y, w, h;
847    int nrects, i;
848    Eina_Rectangle *dmg;
849
850    rects = pixman_region32_rectangles(&ds_surface->current.surface_damage, &nrects);
851    for (i = 0; i < nrects; i++)
852      {
853         x = rects[i].x1;
854         y = rects[i].y1;
855         w = rects[i].x2 - x;
856         h = rects[i].y2 - y;
857
858         dmg = eina_rectangle_new(x, y, w, h);
859         if (dmg)
860           {
861              surface->base.pending.damages =
862                 eina_list_append(surface->base.pending.damages, dmg);
863           }
864      }
865 }
866
867 static void
868 _e_surface_pending_buffer_damage_update(E_Surface *surface)
869 {
870    struct ds_surface *ds_surface = surface->ds_surface;
871    pixman_box32_t *rects;
872    int32_t x, y, w, h;
873    int nrects, i;
874    Eina_Rectangle *dmg;
875
876    rects = pixman_region32_rectangles(&ds_surface->current.buffer_damage, &nrects);
877    for (i = 0; i < nrects; i++)
878      {
879         x = rects[i].x1;
880         y = rects[i].y1;
881         w = rects[i].x2 - x;
882         h = rects[i].y2 - y;
883
884         dmg = eina_rectangle_new(x, y, w, h);
885         if (dmg)
886           {
887              surface->base.pending.buffer_damages =
888                 eina_list_append(surface->base.pending.buffer_damages, dmg);
889           }
890      }
891 }
892
893 static void
894 _region_area_check(Eina_Tiler *tiler, int32_t x, int32_t y, int32_t w, int32_t h)
895 {
896    Eina_Bool need_set = EINA_FALSE;
897    int area_w = 0;
898    int area_h = 0;
899
900    eina_tiler_area_size_get(tiler, &area_w, &area_h);
901    if (x + w > area_w)
902      {
903         area_w = x + w;
904         need_set = EINA_TRUE;
905      }
906
907    if (y + h > area_h)
908      {
909         area_h = y + h;
910         need_set = EINA_TRUE;
911      }
912
913    if (need_set)
914      {
915         INF("change region area. (%dx%d)", area_w, area_h);
916         eina_tiler_area_size_set(tiler, area_w, area_h);
917      }
918 }
919
920 static Eina_Tiler *
921 _tiler_new_from_pixman_region(pixman_region32_t *pixman_region)
922 {
923    Eina_Tiler *tiler;
924    pixman_box32_t *rects;
925    int32_t x, y, w, h;
926    int nrects, i;
927
928    tiler = eina_tiler_new(e_comp->w, e_comp->h);
929    if (!tiler)
930      return NULL;
931
932    eina_tiler_tile_size_set(tiler, 1, 1);
933
934    rects = pixman_region32_rectangles(pixman_region, &nrects);
935    for (i = 0; i < nrects; i++)
936      {
937         x = rects[i].x1;
938         y = rects[i].y1;
939         w = rects[i].x2 - x;
940         h = rects[i].y2 - y;
941         _region_area_check(tiler, x, y, w, h);
942         eina_tiler_rect_add(tiler, &(Eina_Rectangle){x, y, w, h});
943      }
944
945    return tiler;
946 }
947
948 static void
949 _e_surface_pending_opaque_region_update(E_Surface *surface)
950 {
951    struct ds_surface *ds_surface = surface->ds_surface;
952    E_Client *ec = surface->ec;
953    Eina_Tiler *region;
954
955    if (pixman_region32_not_empty(&ds_surface->current.opaque))
956      {
957         region = _tiler_new_from_pixman_region(&ds_surface->current.opaque);
958         if (!region)
959           return;
960
961         e_comp_wl_client_surface_pending_opaque_region_set(ec, region);
962
963         eina_tiler_free(region);
964      }
965    else
966      {
967         e_comp_wl_client_surface_pending_opaque_region_set(ec, NULL);
968      }
969 }
970
971 static void
972 _e_surface_pending_input_region_update(E_Surface *surface)
973 {
974    struct ds_surface *ds_surface = surface->ds_surface;
975    E_Client *ec = surface->ec;
976    Eina_Tiler *region;
977    pixman_region32_t infinite_region;
978
979    pixman_region32_init_rect(&infinite_region, INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX);
980    if (pixman_region32_equal(&ds_surface->current.input, &infinite_region))
981      {
982         e_comp_wl_client_surface_pending_input_region_set(ec, NULL);
983      }
984    else
985      {
986         region = _tiler_new_from_pixman_region(&ds_surface->current.input);
987         if (region)
988           {
989              e_comp_wl_client_surface_pending_input_region_set(ec, region);
990              eina_tiler_free(region);
991           }
992      }
993 }
994
995 static void
996 _e_surface_pending_buffer_transform_update(E_Surface *surface)
997 {
998    int32_t transform = surface->ds_surface->current.transform;
999
1000    surface->base.pending.buffer_viewport.buffer.transform = transform;
1001    surface->base.pending.buffer_viewport.changed = 1;
1002 }
1003
1004 static void
1005 _e_surface_pending_buffer_scale_update(E_Surface *surface)
1006 {
1007    int32_t scale = surface->ds_surface->current.scale;
1008
1009    surface->base.pending.buffer_viewport.buffer.scale = scale;
1010    surface->base.pending.buffer_viewport.changed = 1;
1011 }
1012
1013 static void
1014 _frame_callback_cb_destroy(struct wl_listener *listener, void *data)
1015 {
1016    struct wl_resource *resource = data;
1017    E_Frame_Callback *frame_callback;
1018
1019    frame_callback = wl_container_of(listener, frame_callback, destroy);
1020    e_comp_wl_client_surface_frame_callback_remove(frame_callback->ec, resource);
1021    e_object_unref(E_OBJECT(frame_callback->ec));
1022    free(frame_callback);
1023 }
1024
1025 static void
1026 _e_surface_pending_frame_callback_update(E_Surface *surface)
1027 {
1028    struct ds_surface *ds_surface = surface->ds_surface;
1029    E_Client *ec = surface->ec;
1030    E_Frame_Callback *frame_callback;
1031    struct wl_resource *resource;
1032
1033    wl_resource_for_each(resource, &ds_surface->current.frame_callback_list)
1034      {
1035         frame_callback = E_NEW(E_Frame_Callback, 1);
1036         if (!frame_callback)
1037           continue;
1038
1039         e_object_ref(E_OBJECT(ec));
1040         frame_callback->ec = ec;
1041
1042         frame_callback->destroy.notify = _frame_callback_cb_destroy;
1043         wl_resource_add_destroy_listener(resource, &frame_callback->destroy);
1044
1045         e_comp_wl_client_surface_pending_frame_callback_add(ec, resource);
1046      }
1047
1048    wl_list_init(&ds_surface->current.frame_callback_list);
1049 }
1050
1051 static void
1052 _e_surface_pending_viewport_update(E_Surface *surface)
1053 {
1054    struct ds_surface *ds_surface = surface->ds_surface;
1055    struct ds_surface_state *state = &ds_surface->current;
1056    E_Comp_Wl_Buffer_Viewport *vp = &surface->base.pending.buffer_viewport;
1057
1058    if (state->viewport.has_src)
1059      {
1060         vp->buffer.src_x = wl_fixed_from_double(state->viewport.src.x);
1061         vp->buffer.src_y = wl_fixed_from_double(state->viewport.src.y);
1062         vp->buffer.src_width = wl_fixed_from_double(state->viewport.src.width);
1063         vp->buffer.src_height = wl_fixed_from_double(state->viewport.src.height);
1064         vp->changed = EINA_TRUE;
1065      }
1066    else
1067      {
1068         vp->buffer.src_width = wl_fixed_from_int(-1);
1069         vp->changed = EINA_TRUE;
1070      }
1071
1072    if (state->viewport.has_dst)
1073      {
1074         vp->surface.width = state->viewport.dst_width;
1075         vp->surface.height = state->viewport.dst_height;
1076         vp->changed = EINA_TRUE;
1077      }
1078    else
1079      {
1080         vp->surface.width = -1;
1081         vp->changed = EINA_TRUE;
1082      }
1083 }
1084
1085 static void
1086 _e_surface_pending_subsurface_order_update(E_Surface *surface)
1087 {
1088    struct ds_surface *ds_surface = surface->ds_surface;
1089    struct ds_subsurface *ds_subsurface;
1090    E_Subsurface *sub;
1091    Eina_Bool reordered = EINA_FALSE;
1092
1093    E_FREE_FUNC(surface->base.sub.list_pending, eina_list_free);
1094    E_FREE_FUNC(surface->base.sub.below_list_pending, eina_list_free);
1095
1096    wl_list_for_each(ds_subsurface,
1097                     &ds_surface->pending.subsurfaces_above,
1098                     pending.link)
1099      {
1100         sub = _e_subsurface_from_ds_subsurface(ds_subsurface);
1101         surface->base.sub.list_pending =
1102            eina_list_append(surface->base.sub.list_pending, sub->surface->ec);
1103
1104         reordered |= ds_subsurface->reordered;
1105         ds_subsurface->reordered = false;
1106
1107         _e_surface_pending_subsurface_order_update(sub->surface);
1108      }
1109
1110    wl_list_for_each(ds_subsurface,
1111                     &ds_surface->pending.subsurfaces_below,
1112                     pending.link)
1113      {
1114         sub = _e_subsurface_from_ds_subsurface(ds_subsurface);
1115         surface->base.sub.below_list_pending =
1116            eina_list_append(surface->base.sub.below_list_pending, sub->surface->ec);
1117
1118         reordered |= ds_subsurface->reordered;
1119         ds_subsurface->reordered = false;
1120
1121         _e_surface_pending_subsurface_order_update(sub->surface);
1122      }
1123
1124    surface->base.sub.list_changed |= reordered;
1125 }
1126
1127 static void
1128 _e_surface_pending_update(E_Surface *surface)
1129 {
1130    E_Surface *root_surface;
1131    struct ds_surface *ds_surface = surface->ds_surface;
1132
1133    if (ds_surface->current.committed & DS_SURFACE_STATE_BUFFER)
1134      _e_surface_pending_buffer_update(surface);
1135
1136    if (ds_surface->current.committed & DS_SURFACE_STATE_SURFACE_DAMAGE)
1137      _e_surface_pending_surface_damage_update(surface);
1138
1139    if (ds_surface->current.committed & DS_SURFACE_STATE_BUFFER_DAMAGE)
1140      _e_surface_pending_buffer_damage_update(surface);
1141
1142    if (ds_surface->current.committed & DS_SURFACE_STATE_OPAQUE_REGION)
1143      _e_surface_pending_opaque_region_update(surface);
1144
1145    if (ds_surface->current.committed & DS_SURFACE_STATE_INPUT_REGION)
1146      _e_surface_pending_input_region_update(surface);
1147
1148    if (ds_surface->current.committed & DS_SURFACE_STATE_TRANSFORM)
1149      _e_surface_pending_buffer_transform_update(surface);
1150
1151    if (ds_surface->current.committed & DS_SURFACE_STATE_SCALE)
1152      _e_surface_pending_buffer_scale_update(surface);
1153
1154    if (ds_surface->current.committed & DS_SURFACE_STATE_FRAME_CALLBACK_LIST)
1155      _e_surface_pending_frame_callback_update(surface);
1156
1157    if (ds_surface->current.committed & DS_SURFACE_STATE_VIEWPORT)
1158      _e_surface_pending_viewport_update(surface);
1159
1160    // FIXME
1161    // It's not supposed to update subsurface order for entire surface tree.
1162    // This is for backward compatibility
1163    root_surface = _e_surface_root_surface_get(surface);
1164    _e_surface_pending_subsurface_order_update(root_surface);
1165 }
1166
1167 static void
1168 _e_surface_commit_pre(E_Surface *surface)
1169 {
1170    E_Client *ec = surface->ec;
1171    E_Comp_Config *comp_conf = NULL;
1172
1173    if (e_object_is_del(E_OBJECT(ec))) return;
1174
1175    if (!surface->base.first_commit)
1176      surface->base.first_commit = EINA_TRUE;
1177
1178    if (!surface->base.mapped)
1179      {
1180         if (surface->base.shell.surface && surface->base.pending.new_attach &&
1181             !ec->internal && !e_comp_wl_subsurface_check(ec) && !ec->remote_surface.provider)
1182           {
1183              ELOGF("COMP", "Current unmapped. COMMIT. pixmap_usable:%d", ec, e_pixmap_usable_get(ec->pixmap));
1184
1185              // no canvas update before client's commit request, begin rendering after 1st commit
1186              comp_conf = e_comp_config_get();
1187              if (comp_conf && comp_conf->canvas_render_delay_after_boot && e_comp->canvas_render_delayed)
1188                {
1189                   ELOGF("COMP", "Begin canvas update for the first time after boot", ec);
1190                   e_comp->canvas_render_delayed = EINA_FALSE;
1191                }
1192           }
1193      }
1194
1195    e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_BEFORE_SURFACE_COMMIT, ec);
1196 }
1197
1198 static void
1199 _e_surface_commit(E_Surface *surface)
1200 {
1201    e_comp_wl_client_surface_pending_commit(surface->ec);
1202 }
1203
1204 static void
1205 _e_surface_cb_client_del(void *data, E_Client *ec)
1206 {
1207    E_Surface *surface = data;
1208
1209    if (surface->ec != ec)
1210      return;
1211
1212    /* make sure this is a wayland client */
1213    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
1214
1215    TRACE_DS_BEGIN(COMP_WL:CLIENT DEL CB);
1216
1217    e_comp_wl_hook_call(E_COMP_WL_HOOK_DEL, ec);
1218
1219    e_comp_wl_client_evas_deinit(ec);
1220
1221    e_pixmap_cdata_set(ec->pixmap, NULL);
1222
1223    _e_surface_destroy(surface);
1224
1225    TRACE_DS_END();
1226 }
1227
1228 static void
1229 _e_surface_cb_destroy(struct wl_listener *listener, void *data)
1230 {
1231    E_Surface *surface;
1232
1233    surface = wl_container_of(listener, surface, destroy);
1234
1235    wl_signal_emit(&surface->events.destroy, surface);
1236
1237    wl_list_remove(&surface->destroy.link);
1238    wl_list_remove(&surface->commit.link);
1239    wl_list_remove(&surface->new_subsurface.link);
1240    surface->ds_surface = NULL;
1241
1242    e_comp_wl_client_surface_finish(surface->ec);
1243 }
1244
1245 static void
1246 _e_surface_cb_commit(struct wl_listener *listener, void *data)
1247 {
1248    E_Surface *surface;
1249    E_Subsurface *sub;
1250
1251    surface = wl_container_of(listener, surface, commit);
1252
1253    _e_surface_pending_update(surface);
1254    _e_surface_commit_pre(surface);
1255
1256    if (e_comp_wl_remote_surface_commit(surface->ec)) return;
1257
1258    sub = _e_subsurface_from_surface(surface);
1259    if (sub)
1260      _e_subsurface_commit(sub);
1261    else
1262      _e_surface_commit(surface);
1263 }
1264
1265 static void
1266 _e_surface_cb_new_subsurface(struct wl_listener *listener, void *data)
1267 {
1268    struct ds_subsurface *ds_subsurface = data;
1269    E_Surface *surface;
1270
1271    surface = wl_container_of(listener, surface, new_subsurface);
1272
1273    if (!_e_subsurface_create(ds_subsurface, surface))
1274      {
1275         ELOGF("COMPOSITOR", "Could not create E_Subsurface", surface->ec);
1276         return;
1277      }
1278 }
1279
1280 static E_Subsurface *
1281 _e_subsurface_create(struct ds_subsurface *ds_subsurface, E_Surface *parent_surface)
1282 {
1283    E_Subsurface *sub;
1284    E_Surface *surface;
1285    E_Client *offscreen_parent = NULL, *epc = parent_surface->ec;
1286
1287    sub = E_NEW(E_Subsurface, 1);
1288    if (!sub)
1289      return NULL;
1290
1291    surface = _e_surface_from_ds_surface(ds_subsurface->surface);
1292
1293    if (parent_surface->base.remote_surface.onscreen_parent)
1294      {
1295         offscreen_parent = epc;
1296         epc = parent_surface->base.remote_surface.onscreen_parent;
1297      }
1298
1299    if (e_comp_wl_client_subsurface_cyclic_reference_check(surface->ec, epc))
1300      {
1301         ERR("Subsurface parent relationship is a cycle : "
1302             "[child win : %zx, %s], [parent win : %zx, %s]",
1303             e_client_util_win_get(surface->ec),
1304             e_client_util_name_get(surface->ec),
1305             e_client_util_win_get(epc),
1306             e_client_util_name_get(epc));
1307         free(sub);
1308         return NULL;
1309      }
1310
1311    if (!e_comp_wl_surface_role_set(surface->ec, e_comp_wl_subsurface_role_name,
1312                                    NULL, 0))
1313      {
1314         free(sub);
1315         return NULL;
1316      }
1317
1318    sub->ds_subsurface = ds_subsurface;
1319    sub->destroy.notify = _e_subsurface_cb_destroy;
1320    wl_signal_add(&ds_subsurface->events.destroy, &sub->destroy);
1321
1322    sub->cached.notify = _e_subsurface_cb_cached;
1323    wl_signal_add(&ds_subsurface->events.cached, &sub->cached);
1324
1325    sub->request_move.notify = _e_subsurface_cb_request_move;
1326    wl_signal_add(&ds_subsurface->events.request_move, &sub->request_move);
1327
1328    sub->surface = surface;
1329    sub->surface_destroy.notify = _e_subsurface_cb_surface_destroy;
1330    wl_signal_add(&surface->base.destroy_signal, &sub->surface_destroy);
1331
1332    sub->parent_surface_destroy.notify = _e_subsurface_cb_parent_surface_destroy;
1333    wl_signal_add(&parent_surface->base.destroy_signal, &sub->parent_surface_destroy);
1334
1335    e_comp_wl_client_subsurface_init(surface->ec,
1336                                     ds_subsurface->resource,
1337                                     &sub->base,
1338                                     epc,
1339                                     offscreen_parent);
1340
1341    _e_subsurface_position_update(sub);
1342
1343    ELOGF("SUBSURFACE", "Create: parent(%p)", surface->ec, epc);
1344
1345    return sub;
1346 }
1347
1348 static void
1349 _e_subsurface_destroy(E_Subsurface *sub)
1350 {
1351    ELOGF("SUBSURFACE", "Destroy", sub->surface->ec);
1352    e_comp_wl_client_subsurface_finish(sub->surface->ec);
1353    wl_list_remove(&sub->request_move.link);
1354    wl_list_remove(&sub->parent_surface_destroy.link);
1355    wl_list_remove(&sub->cached.link);
1356    wl_list_remove(&sub->surface_destroy.link);
1357    wl_list_remove(&sub->destroy.link);
1358    free(sub);
1359 }
1360
1361 static E_Subsurface *
1362 _e_subsurface_from_ds_subsurface(struct ds_subsurface *ds_subsurface)
1363 {
1364    struct wl_listener *listener;
1365    E_Subsurface *sub = NULL;
1366
1367    listener = wl_signal_get(&ds_subsurface->events.destroy,
1368                             _e_subsurface_cb_destroy);
1369    if (listener)
1370      sub = wl_container_of(listener, sub, destroy);
1371
1372    return sub;
1373 }
1374
1375 static E_Subsurface *
1376 _e_subsurface_from_surface(E_Surface *surface)
1377 {
1378    struct ds_subsurface *ds_subsurface;
1379
1380    if (!surface->ds_surface)
1381      return NULL;
1382
1383    ds_subsurface = ds_subsurface_from_surface(surface->ds_surface);
1384    if (!ds_subsurface)
1385      return NULL;
1386
1387    return _e_subsurface_from_ds_subsurface(ds_subsurface);
1388 }
1389
1390 static E_Subsurface *
1391 _e_subsurface_from_resource(struct wl_resource *resource)
1392 {
1393    struct ds_subsurface *ds_subsurface;
1394
1395    ds_subsurface = ds_subsurface_from_resource(resource);
1396    if (!ds_subsurface)
1397      return NULL;
1398
1399    return _e_subsurface_from_ds_subsurface(ds_subsurface);
1400 }
1401
1402 static Eina_Bool
1403 _e_subsurface_synchronized_check(E_Subsurface *sub)
1404 {
1405    struct ds_subsurface *ds_subsurface = sub->ds_subsurface;
1406
1407    do
1408      {
1409         if (ds_subsurface->synchronized)
1410           return EINA_TRUE;
1411      }
1412    while ((ds_subsurface = ds_subsurface_from_surface(ds_subsurface->parent)));
1413
1414    return EINA_FALSE;
1415 }
1416
1417 static void
1418 _e_subsurface_commit(E_Subsurface *sub)
1419 {
1420    if (sub->base.cached.has_data)
1421      {
1422         e_comp_wl_client_subsurface_commit_to_cache(sub->surface->ec);
1423         e_comp_wl_client_subsurface_commit_from_cache(sub->surface->ec);
1424      }
1425    else
1426      {
1427         e_comp_wl_surface_commit(sub->surface->ec);
1428      }
1429
1430    if (_e_subsurface_synchronized_check(sub))
1431      {
1432         e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_SYNCHRONIZED_COMMIT,
1433                             sub->surface->ec);
1434      }
1435 }
1436
1437 static void
1438 _e_subsurface_position_update(E_Subsurface *sub)
1439 {
1440    E_Client *ec = sub->surface->ec;
1441    int x, y;
1442
1443    if (e_comp_wl_subsurface_global_coord_get(ec, &x, &y))
1444      evas_object_move(ec->frame, x, y);
1445 }
1446
1447 static void
1448 _e_subsurface_place_below_parent(E_Subsurface *sub)
1449 {
1450    struct ds_subsurface *ds_subsurface = sub->ds_subsurface;
1451
1452    wl_list_remove(&ds_subsurface->pending.link);
1453    wl_list_insert(ds_subsurface->parent->pending.subsurfaces_below.prev,
1454                   &ds_subsurface->pending.link);
1455
1456    // FIXME
1457    wl_list_remove(&ds_subsurface->current.link);
1458    wl_list_insert(ds_subsurface->parent->current.subsurfaces_below.prev,
1459                   &ds_subsurface->current.link);
1460
1461    ds_subsurface->reordered = true;
1462 }
1463
1464 static void
1465 _e_subsurface_cb_destroy(struct wl_listener *listener, void *data)
1466 {
1467    E_Subsurface *sub;
1468
1469    sub = wl_container_of(listener, sub, destroy);
1470    _e_subsurface_destroy(sub);
1471 }
1472
1473 static void
1474 _e_subsurface_cb_cached(struct wl_listener *listener, void *data)
1475 {
1476    E_Subsurface *sub;
1477
1478    sub = wl_container_of(listener, sub, cached);
1479
1480    e_presentation_time_container_feedback_discard(&sub->base.cached.presentation_container);
1481    e_presentation_time_container_feedback_merge(&sub->base.cached.presentation_container,
1482                                                 &sub->surface->base.pending.presentation_container);
1483
1484    sub->base.cached.has_data = EINA_TRUE;
1485
1486    e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_COMMIT_TO_CACHE, sub->surface->ec);
1487 }
1488
1489 static void
1490 _e_subsurface_cb_request_move(struct wl_listener *listener, void *data)
1491 {
1492    E_Subsurface *sub;
1493    struct ds_subsurface *ds_subsurface;
1494
1495    sub = wl_container_of(listener, sub, request_move);
1496    ds_subsurface = sub->ds_subsurface;
1497
1498    if ((sub->base.position.x == ds_subsurface->current.x) &&
1499        (sub->base.position.y == ds_subsurface->current.y))
1500      return;
1501
1502    sub->base.position.x = ds_subsurface->current.x;
1503    sub->base.position.y = ds_subsurface->current.y;
1504
1505    _e_subsurface_position_update(sub);
1506 }
1507
1508 static void
1509 _e_subsurface_cb_surface_destroy(struct wl_listener *listener, void *data)
1510 {
1511    E_Subsurface *sub;
1512
1513    sub = wl_container_of(listener, sub, surface_destroy);
1514    _e_subsurface_destroy(sub);
1515 }
1516
1517 static void
1518 _e_subsurface_cb_parent_surface_destroy(struct wl_listener *listener, void *data)
1519 {
1520    E_Subsurface *sub;
1521
1522    sub = wl_container_of(listener, sub, parent_surface_destroy);
1523
1524    wl_signal_emit(&sub->surface->events.parent_destroy, sub->surface);
1525
1526    wl_list_remove(&sub->parent_surface_destroy.link);
1527    wl_list_init(&sub->parent_surface_destroy.link);
1528
1529    e_comp_wl_client_subsurface_parent_unset(sub->surface->ec);
1530 }
1531
1532 static void
1533 _ds_surface_buffer_transform_set(struct ds_surface *ds_surface, enum wl_output_transform transform)
1534 {
1535    ds_surface->pending.transform = transform;
1536    ds_surface->current.transform = transform;
1537 }
1538
1539 static void
1540 _ds_surface_viewport_source_box_set(struct ds_surface *ds_surface, Eina_Rectangle *box)
1541 {
1542    ds_surface->pending.viewport.has_src = true;
1543    ds_surface->pending.viewport.src.x = (double)box->x;
1544    ds_surface->pending.viewport.src.y = (double)box->y;
1545    ds_surface->pending.viewport.src.width = (double)box->w;
1546    ds_surface->pending.viewport.src.height = (double)box->h;
1547    ds_surface->current.viewport.has_src = true;
1548    ds_surface->current.viewport.src = ds_surface->pending.viewport.src;
1549 }
1550
1551 static void
1552 _ds_surface_viewport_destination_set(struct ds_surface *ds_surface, int32_t width, int32_t height)
1553 {
1554    ds_surface->pending.viewport.has_dst = true;
1555    ds_surface->pending.viewport.dst_width = width;
1556    ds_surface->pending.viewport.dst_height = height;
1557    ds_surface->pending.width = width;
1558    ds_surface->pending.height = height;
1559    ds_surface->current.viewport.has_dst = true;
1560    ds_surface->current.viewport.dst_width = width;
1561    ds_surface->current.viewport.dst_height = height;
1562    ds_surface->current.width = width;
1563    ds_surface->current.height = height;
1564 }
1565
1566 static void
1567 _ds_surface_viewport_unset(struct ds_surface *ds_surface)
1568 {
1569    ds_surface->pending.viewport.has_src = false;
1570    ds_surface->pending.viewport.has_dst = false;
1571    ds_surface->current.viewport.has_src = false;
1572    ds_surface->current.viewport.has_dst = false;
1573 }
1574
1575 static void
1576 _ds_subsurface_position_set(struct ds_subsurface *ds_subsurface, int x, int y)
1577 {
1578    ds_subsurface->pending.x = x;
1579    ds_subsurface->pending.y = y;
1580
1581    ds_subsurface->current.x = x;
1582    ds_subsurface->current.y = y;
1583 }