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