e_keyrouter: take keyrouter functions to enlightenment's core
[platform/upstream/enlightenment.git] / src / bin / e_comp_wl.c
1 #include "e.h"
2 #include <tizen-extension-server-protocol.h>
3
4 #include <wayland-tbm-server.h>
5
6 /* handle include for printing uint64_t */
7 #define __STDC_FORMAT_MACROS
8 #include <inttypes.h>
9
10 #define COMPOSITOR_VERSION 4
11
12 E_API int E_EVENT_WAYLAND_GLOBAL_ADD = -1;
13 #include "session-recovery-server-protocol.h"
14
15 #ifndef EGL_HEIGHT
16 # define EGL_HEIGHT                     0x3056
17 #endif
18 #ifndef EGL_WIDTH
19 # define EGL_WIDTH                      0x3057
20 #endif
21
22 /* Resource Data Mapping: (wl_resource_get_user_data)
23  *
24  * wl_surface == e_pixmap
25  * wl_region == eina_tiler
26  * wl_subsurface == e_client
27  *
28  */
29
30 static void _e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized);
31 static void _e_comp_wl_subsurface_restack(E_Client *ec);
32 static void _e_comp_wl_subsurface_restack_bg_rectangle(E_Client *ec);
33 static void _e_comp_wl_subsurface_check_below_bg_rectangle(E_Client *ec);
34 static void _e_comp_wl_subsurface_show(E_Client *ec);
35 static void _e_comp_wl_subsurface_hide(E_Client *ec);
36
37 static E_Client * _e_comp_wl_client_usable_get(pid_t pid, E_Pixmap *ep);
38
39 /* local variables */
40 typedef struct _E_Comp_Wl_Transform_Context
41 {
42    E_Client *ec;
43    int direction;
44    int degree;
45 } E_Comp_Wl_Transform_Context;
46
47 typedef struct _E_Comp_Wl_Key_Data
48 {
49    uint32_t key;
50    Ecore_Device *dev;
51 } E_Comp_Wl_Key_Data;
52
53 static Eina_List *handlers = NULL;
54 static E_Client *cursor_timer_ec = NULL;
55 static Eina_Bool need_send_leave = EINA_TRUE;
56 static Eina_Bool need_send_released = EINA_FALSE;
57 static Eina_Bool need_send_motion = EINA_TRUE;
58
59 static int _e_comp_wl_hooks_delete = 0;
60 static int _e_comp_wl_hooks_walking = 0;
61
62 static Eina_Inlist *_e_comp_wl_hooks[] =
63 {
64    [E_COMP_WL_HOOK_SHELL_SURFACE_READY] = NULL,
65    [E_COMP_WL_HOOK_SUBSURFACE_CREATE] = NULL,
66    [E_COMP_WL_HOOK_BUFFER_CHANGE] = NULL,
67    [E_COMP_WL_HOOK_CLIENT_REUSE] = NULL,
68 };
69
70 static Eina_List *hooks = NULL;
71
72 /* local functions */
73 static void
74 _e_comp_wl_hooks_clean(void)
75 {
76    Eina_Inlist *l;
77    E_Comp_Wl_Hook *ch;
78    unsigned int x;
79    for (x = 0; x < E_COMP_WL_HOOK_LAST; x++)
80      EINA_INLIST_FOREACH_SAFE(_e_comp_wl_hooks[x], l, ch)
81        {
82           if (!ch->delete_me) continue;
83           _e_comp_wl_hooks[x] = eina_inlist_remove(_e_comp_wl_hooks[x], EINA_INLIST_GET(ch));
84          free(ch); 
85        }
86 }
87
88 static void
89 _e_comp_wl_hook_call(E_Comp_Wl_Hook_Point hookpoint, E_Client *ec)
90 {
91    E_Comp_Wl_Hook *ch;
92
93    e_object_ref(E_OBJECT(ec));
94    _e_comp_wl_hooks_walking++;
95    EINA_INLIST_FOREACH(_e_comp_wl_hooks[hookpoint], ch)
96      {
97         if (ch->delete_me) continue;
98         ch->func(ch->data, ec);
99         if (e_object_is_del(E_OBJECT(ec)))
100           break;
101      }
102    _e_comp_wl_hooks_walking--;
103    if ((_e_comp_wl_hooks_walking == 0) && (_e_comp_wl_hooks_delete > 0))
104      _e_comp_wl_hooks_clean();
105    e_object_unref(E_OBJECT(ec));
106 }
107
108 static void
109 _e_comp_wl_configure_send(E_Client *ec, Eina_Bool edges, Eina_Bool send_size)
110 {
111    int w, h;
112
113    if (send_size)
114      {
115         if (e_comp_object_frame_exists(ec->frame))
116           w = ec->client.w, h = ec->client.h;
117         else
118           w = ec->w, h = ec->h;
119      }
120    else
121      w = h = 0;
122
123    ec->comp_data->shell.configure_send(ec->comp_data->shell.surface,
124                                        edges * e_comp_wl->resize.edges,
125                                        w, h);
126 }
127
128 static void
129 _e_comp_wl_focus_down_set(E_Client *ec EINA_UNUSED)
130 {
131    // do nothing
132 }
133
134 static void
135 _e_comp_wl_focus_check(void)
136 {
137    E_Client *ec;
138
139    if (stopping) return;
140    ec = e_client_focused_get();
141    if ((!ec) || e_pixmap_is_x(ec->pixmap))
142      e_grabinput_focus(e_comp->ee_win, E_FOCUS_METHOD_PASSIVE);
143 }
144
145 static Eina_Bool
146 _e_comp_wl_cb_read(void *data EINA_UNUSED, Ecore_Fd_Handler *hdlr EINA_UNUSED)
147 {
148    /* dispatch pending wayland events */
149    wl_event_loop_dispatch(e_comp_wl->wl.loop, 0);
150
151    return ECORE_CALLBACK_RENEW;
152 }
153
154 static void
155 _e_comp_wl_cb_prepare(void *data EINA_UNUSED, Ecore_Fd_Handler *hdlr EINA_UNUSED)
156 {
157    /* flush pending client events */
158    wl_display_flush_clients(e_comp_wl->wl.disp);
159 }
160
161 E_API enum wl_output_transform
162 e_comp_wl_output_buffer_transform_get(E_Client *ec)
163 {
164    E_Comp_Wl_Buffer_Viewport *vp;
165    E_Comp_Wl_Buffer *buffer;
166    enum wl_output_transform transform, rotation;
167
168    if (!ec) return WL_OUTPUT_TRANSFORM_NORMAL;
169    if (e_object_is_del(E_OBJECT(ec))) return WL_OUTPUT_TRANSFORM_NORMAL;
170    if (!ec->comp_data) return WL_OUTPUT_TRANSFORM_NORMAL;
171
172    vp = &ec->comp_data->scaler.buffer_viewport;
173    if (ec->comp_data->sub.data)
174      return vp->buffer.transform;
175
176    buffer = ec->comp_data->buffer_ref.buffer;
177
178    if (!buffer ||
179        (buffer->type != E_COMP_WL_BUFFER_TYPE_NATIVE && buffer->type != E_COMP_WL_BUFFER_TYPE_TBM))
180      return vp->buffer.transform;
181
182    rotation = wayland_tbm_server_buffer_get_buffer_transform(NULL, buffer->resource);
183    if (rotation == 0)
184      return vp->buffer.transform;
185
186    /* ignore the flip value when calculating transform because the screen rotation
187     * functionality doesn't consider the flip output transform currently
188     */
189    transform = (4 + (vp->buffer.transform & 0x3) - rotation) & 0x3;
190
191    DBG("ec(%p) window rotation(%d) buffer_transform(%d) : transform(%d)",
192        ec, rotation, vp->buffer.transform, transform);
193
194    return transform;
195 }
196
197 E_API void
198 e_comp_wl_map_size_cal_from_buffer(E_Client *ec)
199 {
200    E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
201    E_Comp_Wl_Buffer *buffer;
202    int32_t width, height;
203
204    buffer = e_pixmap_resource_get(ec->pixmap);
205    if (!buffer)
206      {
207         ec->comp_data->width_from_buffer = 0;
208         ec->comp_data->height_from_buffer = 0;
209         return;
210      }
211
212    switch (e_comp_wl_output_buffer_transform_get(ec))
213      {
214       case WL_OUTPUT_TRANSFORM_90:
215       case WL_OUTPUT_TRANSFORM_270:
216       case WL_OUTPUT_TRANSFORM_FLIPPED_90:
217       case WL_OUTPUT_TRANSFORM_FLIPPED_270:
218         width = buffer->h / vp->buffer.scale;
219         height = buffer->w / vp->buffer.scale;
220         break;
221       default:
222         width = buffer->w / vp->buffer.scale;
223         height = buffer->h / vp->buffer.scale;
224         break;
225      }
226
227    ec->comp_data->width_from_buffer = width;
228    ec->comp_data->height_from_buffer = height;
229 }
230
231 E_API void
232 e_comp_wl_map_size_cal_from_viewport(E_Client *ec)
233 {
234    E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
235    int32_t width, height;
236
237    width = ec->comp_data->width_from_buffer;
238    height = ec->comp_data->height_from_buffer;
239
240    if (width == 0 && height == 0) return;
241
242    if (width != 0 && vp->surface.width != -1)
243      {
244         ec->comp_data->width_from_viewport = vp->surface.width;
245         ec->comp_data->height_from_viewport = vp->surface.height;
246         return;
247      }
248
249    if (width != 0 && vp->buffer.src_width != wl_fixed_from_int(-1))
250      {
251         int32_t w = wl_fixed_to_int(wl_fixed_from_int(1) - 1 + vp->buffer.src_width);
252         int32_t h = wl_fixed_to_int(wl_fixed_from_int(1) - 1 + vp->buffer.src_height);
253         ec->comp_data->width_from_viewport = w ?: 1;
254         ec->comp_data->height_from_viewport = h ?: 1;
255         return;
256      }
257
258    ec->comp_data->width_from_viewport = width;
259    ec->comp_data->height_from_viewport = height;
260 }
261
262 EINTERN E_Client*
263 e_comp_wl_topmost_parent_get(E_Client *ec)
264 {
265    E_Client *parent = NULL;
266
267    if (!ec->comp_data || !ec->comp_data->sub.data)
268       return ec;
269
270    parent = ec->comp_data->sub.data->parent;
271    while (parent)
272      {
273         if (!parent->comp_data || !parent->comp_data->sub.data)
274           return parent;
275
276         parent = parent->comp_data->sub.data->parent;
277      }
278
279    return ec;
280 }
281
282 EINTERN Eina_Bool
283 e_comp_wl_video_subsurface_has(E_Client *ec)
284 {
285    E_Client *subc;
286    Eina_List *l;
287
288    if (!ec) return EINA_FALSE;
289    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
290    if (!ec->comp_data) return EINA_FALSE;
291
292    if (ec->comp_data->video_client)
293      return EINA_TRUE;
294
295    if (ec->comp_data->has_video_client)
296      return EINA_TRUE;
297
298    EINA_LIST_FOREACH(ec->comp_data->sub.below_list_pending, l, subc)
299      if (e_comp_wl_video_subsurface_has(subc))
300         return EINA_TRUE;
301
302    EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
303      if (e_comp_wl_video_subsurface_has(subc))
304         return EINA_TRUE;
305
306    return EINA_FALSE;
307 }
308
309 EINTERN Eina_Bool
310 e_comp_wl_normal_subsurface_has(E_Client *ec)
311 {
312    E_Client *subc;
313    Eina_List *l;
314
315    if (!ec) return EINA_FALSE;
316    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
317    if (!ec->comp_data) return EINA_FALSE;
318
319    /* if a leaf client is not video cliet */
320    if (ec->comp_data->sub.data && !ec->comp_data->sub.below_list &&
321        !ec->comp_data->sub.below_list_pending && !ec->comp_data->video_client)
322      return EINA_TRUE;
323
324    EINA_LIST_FOREACH(ec->comp_data->sub.below_list_pending, l, subc)
325      if (e_comp_wl_normal_subsurface_has(subc))
326         return EINA_TRUE;
327
328    EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
329      if (e_comp_wl_normal_subsurface_has(subc))
330         return EINA_TRUE;
331
332    return EINA_FALSE;
333 }
334
335 static void
336 _e_comp_wl_extern_parent_commit(E_Client *ec)
337 {
338    E_Client *subc;
339    Eina_List *l;
340
341    if (!ec->comp_data || e_object_is_del(E_OBJECT(ec))) return;
342
343    EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
344      _e_comp_wl_extern_parent_commit(subc);
345
346    EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
347      _e_comp_wl_extern_parent_commit(subc);
348
349    _e_comp_wl_subsurface_parent_commit(ec, EINA_TRUE);
350 }
351
352 E_API void
353 e_comp_wl_map_apply(E_Client *ec)
354 {
355    E_Comp_Wl_Buffer_Viewport *vp;
356    E_Comp_Wl_Subsurf_Data *sdata;
357    E_Comp_Wl_Client_Data *cdata;
358    int x1, y1, x2, y2, x, y;
359    int dx, dy;
360
361    if (!ec || !ec->comp_data || e_object_is_del(E_OBJECT(ec))) return;
362
363    e_comp_object_map_update(ec->frame);
364
365    vp = &ec->comp_data->scaler.buffer_viewport;
366    if (vp->buffer.src_width == wl_fixed_from_int(-1)) return;
367
368    cdata = ec->comp_data;
369    sdata = ec->comp_data->sub.data;
370    if (sdata)
371      {
372         dx = sdata->position.x;
373         dy = sdata->position.y;
374
375         if (sdata->parent)
376           {
377              dx += sdata->parent->x;
378              dy += sdata->parent->y;
379           }
380
381         if (sdata->remote_surface.offscreen_parent)
382           {
383              E_Client *offscreen_parent = sdata->remote_surface.offscreen_parent;
384              Eina_Rectangle *rect;
385              Eina_List *l;
386
387              EINA_LIST_FOREACH(offscreen_parent->comp_data->remote_surface.regions, l, rect)
388                {
389                   /* TODO: If there are one more regions, it means that provider's offscreen
390                    * is displayed by one more remote_surfaces. Have to consider it later. At
391                    * this time, just consider only one remote_surface.
392                    */
393                   dx += rect->x;
394                   dy += rect->y;
395                   break;
396                }
397           }
398      }
399    else
400      {
401         dx = ec->x;
402         dy = ec->y;
403      }
404
405    evas_object_geometry_get(ec->frame, &x, &y, NULL, NULL);
406    if (x != dx || y != dy)
407      evas_object_move(ec->frame, dx, dy);
408
409    if (!cdata->viewport_transform)
410      {
411         cdata->viewport_transform = e_util_transform_new();
412         e_client_transform_core_add(ec, cdata->viewport_transform);
413      }
414
415    e_util_transform_viewport_set(cdata->viewport_transform, dx, dy,
416                                  ec->comp_data->width_from_viewport,
417                                  ec->comp_data->height_from_viewport);
418
419    x1 = wl_fixed_to_int(vp->buffer.src_x);
420    y1 = wl_fixed_to_int(vp->buffer.src_y);
421    x2 = wl_fixed_to_int(vp->buffer.src_x + vp->buffer.src_width);
422    y2 = wl_fixed_to_int(vp->buffer.src_y + vp->buffer.src_height);
423
424    e_util_transform_texcoord_set(cdata->viewport_transform, 0, x1, y1);
425    e_util_transform_texcoord_set(cdata->viewport_transform, 1, x2, y1);
426    e_util_transform_texcoord_set(cdata->viewport_transform, 2, x2, y2);
427    e_util_transform_texcoord_set(cdata->viewport_transform, 3, x1, y2);
428
429    ELOGF("TRANSFORM", "viewport map: point(%d,%d %dx%d) uv(%d,%d %d,%d %d,%d %d,%d)",
430          ec->pixmap, ec, ec->x, ec->y, ec->comp_data->width_from_viewport,
431          ec->comp_data->height_from_viewport, x1, y1, x2, y1, x2, y2, x1, y2);
432
433    e_client_transform_core_update(ec);
434 }
435
436 static void
437 _e_comp_wl_evas_cb_show(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
438 {
439    E_Client *ec, *tmp;
440    Eina_List *l;
441    E_Client *topmost;
442
443    if (!(ec = data)) return;
444    if (e_object_is_del(data)) return;
445
446    if (!ec->override) e_hints_window_visible_set(ec);
447
448    if ((!ec->override) && (!ec->re_manage) && (!ec->comp_data->reparented) &&
449        (!ec->comp_data->need_reparent))
450      {
451         ec->comp_data->need_reparent = EINA_TRUE;
452         ec->visible = EINA_TRUE;
453      }
454    if (!e_client_util_ignored_get(ec))
455      {
456         ec->take_focus = !starting;
457         EC_CHANGED(ec);
458      }
459
460    if (!ec->comp_data->need_reparent)
461      {
462         if ((ec->hidden) || (ec->iconic))
463           {
464              evas_object_hide(ec->frame);
465 //             e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
466           }
467         else if (!ec->internal_elm_win)
468           evas_object_show(ec->frame);
469      }
470
471    EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
472      evas_object_show(tmp->frame);
473
474    topmost = e_comp_wl_topmost_parent_get(ec);
475    if (topmost == ec && (ec->comp_data->sub.list || ec->comp_data->sub.below_list))
476      _e_comp_wl_subsurface_show(ec);
477
478    if (ec->comp_data->sub.below_obj)
479      evas_object_show(ec->comp_data->sub.below_obj);
480 }
481
482 static void
483 _e_comp_wl_evas_cb_hide(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
484 {
485    E_Client *ec, *tmp;
486    Eina_List *l;
487    E_Client *topmost;
488
489    if (!(ec = data)) return;
490    if (e_object_is_del(E_OBJECT(ec))) return;
491
492    /* Uncommonly some clients's final buffer can be skipped if the client
493     * requests unmap of its surface right after wl_surface@commit.
494     * So if this client evas object is hidden state and client is already
495     * unmmapped, we can consider to clear pixmap image here mandatorily.
496     */
497    if (!ec->comp_data->mapped)
498      e_pixmap_image_clear(ec->pixmap, 1);
499
500    EINA_LIST_FOREACH(ec->e.state.video_child, l, tmp)
501      evas_object_hide(tmp->frame);
502
503    topmost = e_comp_wl_topmost_parent_get(ec);
504    if (topmost == ec && (ec->comp_data->sub.list || ec->comp_data->sub.below_list))
505      _e_comp_wl_subsurface_hide(ec);
506
507    if (ec->comp_data->sub.below_obj)
508      evas_object_hide(ec->comp_data->sub.below_obj);
509 }
510
511 static void
512 _e_comp_wl_evas_cb_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
513 {
514    E_Client *ec;
515    E_Client *subc;
516    Eina_List *l;
517    int x, y;
518
519    if (!(ec = data)) return;
520    if (e_object_is_del(E_OBJECT(ec))) return;
521
522    EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
523      {
524         if (!subc->comp_data || !subc->comp_data->sub.data) continue;
525         x = ec->x + subc->comp_data->sub.data->position.x;
526         y = ec->y + subc->comp_data->sub.data->position.y;
527         evas_object_move(subc->frame, x, y);
528
529         if (subc->comp_data->scaler.viewport)
530           {
531              E_Comp_Wl_Client_Data *cdata = subc->comp_data;
532              if (cdata->viewport_transform)
533                e_comp_wl_map_apply(subc);
534           }
535      }
536
537    EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
538      {
539         if (!subc->comp_data || !subc->comp_data->sub.data) continue;
540         x = ec->x + subc->comp_data->sub.data->position.x;
541         y = ec->y + subc->comp_data->sub.data->position.y;
542         evas_object_move(subc->frame, x, y);
543
544         if (subc->comp_data->scaler.viewport)
545           {
546              E_Comp_Wl_Client_Data *cdata = subc->comp_data;
547              if (cdata->viewport_transform)
548                e_comp_wl_map_apply(subc);
549           }
550      }
551
552    if (ec->comp_data->sub.below_obj)
553      evas_object_move(ec->comp_data->sub.below_obj, ec->x, ec->y);
554 }
555
556 static void
557 _e_comp_wl_send_touch_cancel(E_Client *ec)
558 {
559    Eina_List *l;
560    struct wl_resource *res;
561    struct wl_client *wc;
562    E_Comp_Config *comp_conf = NULL;
563
564    if (!ec) return;
565    if (e_object_is_del(E_OBJECT(ec))) return;
566    if (!ec->comp_data || !ec->comp_data->surface) return;
567    if ((ec->ignored) && (!ec->remote_surface.provider)) return;
568
569    wc = wl_resource_get_client(ec->comp_data->surface);
570
571    comp_conf = e_comp_config_get();
572
573    EINA_LIST_FOREACH(e_comp->wl_comp_data->touch.resources, l, res)
574      {
575         if (wl_resource_get_client(res) != wc) continue;
576         if (!e_comp_wl_input_touch_check(res)) continue;
577
578         if (comp_conf && comp_conf->input_log_enable)
579            INF("[Server] Touch Cancel (win:0x%08x, name:%20s)\n", e_client_util_win_get(ec), e_client_util_name_get(ec));
580
581         wl_touch_send_cancel(res);
582      }
583 }
584
585 static void
586 _e_comp_wl_touch_cancel(void)
587 {
588    if (!e_comp_wl->ptr.ec)
589      return;
590
591    if (!need_send_released)
592      return;
593
594    _e_comp_wl_send_touch_cancel(e_comp_wl->ptr.ec);
595
596    need_send_released = EINA_FALSE;
597    need_send_motion = EINA_FALSE;
598 }
599
600 static void
601 _e_comp_wl_evas_cb_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
602 {
603    E_Client *ec = (E_Client *)data;
604
605    if ((!ec) || (!ec->comp_data)) return;
606    if (e_object_is_del(E_OBJECT(ec))) return;
607    if (ec->comp_data->sub.restacking) return;
608
609    if (ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)
610      _e_comp_wl_touch_cancel();
611
612    e_comp_wl_subsurface_stack_update(ec);
613 }
614
615 static E_Comp_Wl_Input_Device *
616 _e_comp_wl_device_last_device_get(Ecore_Device_Class dev_class)
617 {
618    switch (dev_class)
619      {
620       case ECORE_DEVICE_CLASS_MOUSE:
621          return e_comp_wl->input_device_manager.last_device_ptr;
622       case ECORE_DEVICE_CLASS_KEYBOARD:
623          return e_comp_wl->input_device_manager.last_device_kbd;
624       case ECORE_DEVICE_CLASS_TOUCH:
625          return e_comp_wl->input_device_manager.last_device_touch;
626       default:
627          return NULL;;
628      }
629    return NULL;
630 }
631
632 static void
633 _e_comp_wl_device_last_device_set(Ecore_Device_Class dev_class, E_Comp_Wl_Input_Device *device)
634 {
635    switch (dev_class)
636      {
637       case ECORE_DEVICE_CLASS_MOUSE:
638          e_comp_wl->input_device_manager.last_device_ptr = device;
639          break;
640       case ECORE_DEVICE_CLASS_KEYBOARD:
641          e_comp_wl->input_device_manager.last_device_kbd = device;
642          break;
643       case ECORE_DEVICE_CLASS_TOUCH:
644          e_comp_wl->input_device_manager.last_device_touch = device;
645          break;
646       default:
647          break;
648      }
649 }
650
651 static E_Comp_Wl_Input_Device *
652 _e_comp_wl_device_client_last_device_get(E_Client *ec, Ecore_Device_Class dev_class)
653 {
654    switch (dev_class)
655      {
656       case ECORE_DEVICE_CLASS_MOUSE:
657          return ec->comp_data->last_device_ptr;
658       case ECORE_DEVICE_CLASS_KEYBOARD:
659          return ec->comp_data->last_device_kbd;
660       case ECORE_DEVICE_CLASS_TOUCH:
661          return ec->comp_data->last_device_touch;
662       default:
663          return NULL;;
664      }
665    return NULL;
666 }
667
668 static void
669 _e_comp_wl_device_client_last_device_set(E_Client *ec, Ecore_Device_Class dev_class, E_Comp_Wl_Input_Device *device)
670 {
671    switch (dev_class)
672      {
673       case ECORE_DEVICE_CLASS_MOUSE:
674          ec->comp_data->last_device_ptr = device;
675          break;
676       case ECORE_DEVICE_CLASS_KEYBOARD:
677          ec->comp_data->last_device_kbd = device;
678          break;
679       case ECORE_DEVICE_CLASS_TOUCH:
680          ec->comp_data->last_device_touch = device;
681          break;
682       default:
683          break;
684      }
685 }
686
687 static void
688 _e_comp_wl_device_send_event_device(E_Client *ec, Evas_Device *dev, uint32_t timestamp)
689 {
690    E_Comp_Wl_Input_Device *last_device, *ec_last_device, *input_dev;
691    struct wl_resource *dev_res;
692    const char *dev_name;
693    Ecore_Device_Class dev_class;
694    struct wl_client *wc;
695    uint32_t serial;
696    Eina_List *l, *ll;
697
698    EINA_SAFETY_ON_NULL_RETURN(dev);
699
700    if (!ec) return;
701    if (ec->cur_mouse_action || e_comp_wl->drag)
702      return;
703    if (e_object_is_del(E_OBJECT(ec))) return;
704    if ((ec->ignored) && (!ec->remote_surface.provider)) return;
705    if (!ec->comp_data || !ec->comp_data->surface) return;
706
707    dev_class = (Ecore_Device_Class)evas_device_class_get(dev);
708    dev_name = evas_device_description_get(dev);
709    last_device = _e_comp_wl_device_last_device_get(dev_class);
710    ec_last_device = _e_comp_wl_device_client_last_device_get(ec, dev_class);
711
712    serial = wl_display_next_serial(e_comp_wl->wl.disp);
713    wc = wl_resource_get_client(ec->comp_data->surface);
714    EINA_LIST_FOREACH(e_comp_wl->input_device_manager.device_list, l, input_dev)
715      {
716         if (!eina_streq(input_dev->identifier, dev_name) || (input_dev->clas != dev_class)) continue;
717         if ((!last_device) || (last_device != input_dev) || (!ec_last_device) || (ec_last_device != input_dev))
718           {
719              _e_comp_wl_device_last_device_set(dev_class, input_dev);
720              _e_comp_wl_device_client_last_device_set(ec, dev_class, input_dev);
721
722              EINA_LIST_FOREACH(input_dev->resources, ll, dev_res)
723                {
724                   if (wl_resource_get_client(dev_res) != wc) continue;
725                   tizen_input_device_send_event_device(dev_res, serial, input_dev->identifier, timestamp);
726                }
727           }
728      }
729 }
730
731 static void
732 _e_comp_wl_device_send_last_event_device(E_Client *ec, Ecore_Device_Class dev_class, uint32_t timestamp)
733 {
734    E_Comp_Wl_Input_Device *last_device;
735    struct wl_resource *dev_res;
736    struct wl_client *wc;
737    uint32_t serial;
738    Eina_List *l;
739
740    if (!ec->comp_data || !ec->comp_data->surface) return;
741
742    last_device = _e_comp_wl_device_last_device_get(dev_class);
743    if (!last_device) return;
744
745    _e_comp_wl_device_client_last_device_set(ec, dev_class, last_device);
746
747    serial = wl_display_next_serial(e_comp_wl->wl.disp);
748    wc = wl_resource_get_client(ec->comp_data->surface);
749    EINA_LIST_FOREACH(last_device->resources, l, dev_res)
750      {
751         if (wl_resource_get_client(dev_res) != wc) continue;
752         tizen_input_device_send_event_device(dev_res, serial, last_device->identifier, timestamp);
753      }
754  }
755
756  static void
757 _e_comp_wl_send_event_device(struct wl_client *wc, uint32_t timestamp, Ecore_Device *dev, uint32_t serial)
758 {
759    E_Comp_Wl_Input_Device *input_dev;
760    struct wl_resource *dev_res;
761    const char *dev_name;
762    Eina_List *l, *ll;
763
764    EINA_SAFETY_ON_NULL_RETURN(dev);
765
766    dev_name = ecore_device_identifier_get(dev);
767
768    EINA_LIST_FOREACH(e_comp_wl->input_device_manager.device_list, l, input_dev)
769      {
770         if (!eina_streq(input_dev->identifier, dev_name)) continue;
771         _e_comp_wl_device_last_device_set(ecore_device_class_get(dev), input_dev);
772
773         EINA_LIST_FOREACH(input_dev->resources, ll, dev_res)
774           {
775              if (wl_resource_get_client(dev_res) != wc) continue;
776              tizen_input_device_send_event_device(dev_res, serial, input_dev->identifier, timestamp);
777           }
778      }
779 }
780
781 static void
782 _e_comp_wl_cursor_reload(E_Client *ec)
783 {
784    struct wl_resource *res;
785    struct wl_client *wc;
786    Eina_List *l;
787    uint32_t serial;
788    int cx, cy;
789
790    if (e_comp->pointer->o_ptr && (!evas_object_visible_get(e_comp->pointer->o_ptr)))
791      e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
792
793    if (!ec) return;
794    if (e_object_is_del(E_OBJECT(ec))) return;
795    if (!ec->comp_data || !ec->comp_data->surface) return;
796
797    cx = wl_fixed_to_int(e_comp_wl->ptr.x) - ec->client.x;
798    cy = wl_fixed_to_int(e_comp_wl->ptr.y) - ec->client.y;
799
800    wc = wl_resource_get_client(ec->comp_data->surface);
801    serial = wl_display_next_serial(e_comp_wl->wl.disp);
802    EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
803      {
804         if (!e_comp_wl_input_pointer_check(res)) continue;
805         if (wl_resource_get_client(res) != wc) continue;
806         wl_pointer_send_enter(res, serial, ec->comp_data->surface,
807                               wl_fixed_from_int(cx), wl_fixed_from_int(cy));
808         ec->pointer_enter_sent = EINA_TRUE;
809      }
810 }
811
812 static Eina_Bool
813 _e_comp_wl_cursor_timer(void *data)
814 {
815    E_Client *ec = data;
816
817    e_comp_wl_cursor_hide(ec);
818
819    return ECORE_CALLBACK_CANCEL;
820 }
821
822 static void
823 _e_comp_wl_device_send_axis(const char *dev_name, Evas_Device_Class dev_class, E_Client *ec, enum tizen_input_device_axis_type axis_type, double value)
824 {
825    E_Comp_Wl_Input_Device *input_dev;
826    struct wl_resource *dev_res;
827    struct wl_client *wc;
828    Eina_List *l, *ll;
829    wl_fixed_t f_value;
830
831    if (!ec) return;
832    if (e_object_is_del(E_OBJECT(ec))) return;
833    if (!ec->comp_data || !ec->comp_data->surface) return;
834
835    f_value = wl_fixed_from_double(value);
836    wc = wl_resource_get_client(ec->comp_data->surface);
837
838    EINA_LIST_FOREACH(e_comp_wl->input_device_manager.device_list, l, input_dev)
839      {
840         if ((strcmp(input_dev->identifier, dev_name)) || (input_dev->clas != (Ecore_Device_Class)dev_class)) continue;
841         EINA_LIST_FOREACH(input_dev->resources, ll, dev_res)
842           {
843              if (wl_resource_get_client(dev_res) != wc) continue;
844              tizen_input_device_send_axis(dev_res, axis_type, f_value);
845           }
846      }
847 }
848
849 static void
850 _e_comp_wl_device_renew_axis(const char *dev_name, Evas_Device_Class dev_class, E_Client *ec, unsigned int idx, double radius_x, double radius_y, double pressure, double angle)
851 {
852    _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_X, radius_x);
853    e_comp_wl->input_device_manager.multi[idx].radius_x = radius_x;
854    _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_Y, radius_y);
855    e_comp_wl->input_device_manager.multi[idx].radius_y = radius_y;
856    _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_PRESSURE, pressure);
857    e_comp_wl->input_device_manager.multi[idx].pressure = pressure;
858    _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_ANGLE, angle);
859    e_comp_wl->input_device_manager.multi[idx].angle = angle;
860 }
861
862 static void
863 _e_comp_wl_device_handle_axes(const char *dev_name, Evas_Device_Class dev_class, E_Client *ec, unsigned int idx, double radius_x, double radius_y, double pressure, double angle)
864 {
865    if (idx >= E_COMP_WL_TOUCH_MAX) return;
866
867    if (e_comp_wl->input_device_manager.multi[idx].radius_x != radius_x)
868      {
869         _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_X, radius_x);
870         e_comp_wl->input_device_manager.multi[idx].radius_x = radius_x;
871      }
872    if (e_comp_wl->input_device_manager.multi[idx].radius_y != radius_y)
873      {
874         _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_RADIUS_Y, radius_y);
875         e_comp_wl->input_device_manager.multi[idx].radius_y = radius_y;
876      }
877    if (e_comp_wl->input_device_manager.multi[idx].pressure != pressure)
878      {
879         _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_PRESSURE, pressure);
880         e_comp_wl->input_device_manager.multi[idx].pressure = pressure;
881      }
882    if (e_comp_wl->input_device_manager.multi[idx].angle != angle)
883      {
884         _e_comp_wl_device_send_axis(dev_name, dev_class, ec, TIZEN_INPUT_DEVICE_AXIS_TYPE_ANGLE, angle);
885         e_comp_wl->input_device_manager.multi[idx].angle = angle;
886      }
887 }
888
889 static void
890 _e_comp_wl_evas_cb_mouse_in(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
891 {
892    E_Client *ec;
893    Evas_Event_Mouse_In *ev;
894    struct wl_resource *res;
895    struct wl_client *wc;
896    Eina_List *l;
897    uint32_t serial;
898
899    ev = event;
900    if (!(ec = data)) return;
901    if (e_object_is_del(E_OBJECT(ec))) return;
902
903    if (!ec->comp_data || !ec->comp_data->surface) return;
904
905    e_comp_wl->ptr.ec = ec;
906    if (e_comp_wl->drag)
907      {
908         e_comp_wl_data_device_send_enter(ec);
909         return;
910      }
911
912    if (e_config->use_cursor_timer)
913      {
914         if (e_comp_wl->ptr.hide_tmr)
915           {
916              ecore_timer_del(e_comp_wl->ptr.hide_tmr);
917              cursor_timer_ec = ec;
918              e_comp_wl->ptr.hide_tmr = ecore_timer_add(e_config->cursor_timer_interval, _e_comp_wl_cursor_timer, ec);
919           }
920         else
921           {
922              if (e_pointer_is_hidden(e_comp->pointer))
923                return;
924           }
925      }
926
927    if (!eina_list_count(e_comp_wl->ptr.resources)) return;
928    wc = wl_resource_get_client(ec->comp_data->surface);
929    serial = wl_display_next_serial(e_comp_wl->wl.disp);
930    EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
931      {
932         if (!e_comp_wl_input_pointer_check(res)) continue;
933         if (wl_resource_get_client(res) != wc) continue;
934
935         _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, ev->timestamp);
936
937         wl_pointer_send_enter(res, serial, ec->comp_data->surface,
938                               wl_fixed_from_int(ev->canvas.x - ec->client.x),
939                               wl_fixed_from_int(ev->canvas.y - ec->client.y));
940         ec->pointer_enter_sent = EINA_TRUE;
941      }
942 }
943
944 static void
945 _e_comp_wl_evas_cb_mouse_out(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
946 {
947    E_Client *ec;
948    Evas_Event_Mouse_Out *ev;
949    struct wl_resource *res;
950    struct wl_client *wc;
951    Eina_List *l;
952    uint32_t serial;
953    Eina_Bool inside_check;
954
955    ev = event;
956
957    if (!(ec = data)) return;
958    inside_check = E_INSIDE(ev->canvas.x, ev->canvas.y,
959                           ec->client.x, ec->client.y, ec->client.w, ec->client.h);
960    if (ec->cur_mouse_action && inside_check) return;
961    if (e_object_is_del(E_OBJECT(e_comp))) return;
962
963    /* FIXME? this is a hack to just reset the cursor whenever we mouse out. not sure if accurate */
964    {
965       Evas_Object *o;
966
967       ecore_evas_cursor_get(e_comp->ee, &o, NULL, NULL, NULL);
968       if ((e_comp->pointer->o_ptr != o) && (e_comp->wl_comp_data->ptr.enabled))
969         {
970            if ((!e_config->use_cursor_timer) || (!e_pointer_is_hidden(e_comp->pointer)))
971              e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
972         }
973    }
974
975    if (e_comp_wl->ptr.ec == ec)
976      e_comp_wl->ptr.ec = NULL;
977    if (e_object_is_del(E_OBJECT(ec))) return;
978
979    if (!ec->comp_data || !ec->comp_data->surface) return;
980
981    if (e_comp_wl->drag)
982      {
983         e_comp_wl_data_device_send_leave(ec);
984         return;
985      }
986
987    if (e_config->use_cursor_timer && !e_comp_wl->ptr.hide_tmr)
988      {
989         if (e_pointer_is_hidden(e_comp->pointer))
990           return;
991      }
992
993    if (!eina_list_count(e_comp_wl->ptr.resources)) return;
994
995    wc = wl_resource_get_client(ec->comp_data->surface);
996    serial = wl_display_next_serial(e_comp_wl->wl.disp);
997    EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
998      {
999         if (!e_comp_wl_input_pointer_check(res)) continue;
1000         if (wl_resource_get_client(res) != wc) continue;
1001         if (ec->pointer_enter_sent == EINA_FALSE) continue;
1002
1003         _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, ev->timestamp);
1004
1005         wl_pointer_send_leave(res, serial, ec->comp_data->surface);
1006      }
1007    ec->pointer_enter_sent = EINA_FALSE;
1008 }
1009
1010 static void
1011 _e_comp_wl_send_touch(E_Client *ec, int idx, int canvas_x, int canvas_y, uint32_t timestamp, Eina_Bool pressed)
1012 {
1013    Eina_List *l;
1014    struct wl_client *wc;
1015    struct wl_resource *res;
1016    wl_fixed_t x, y;
1017    uint32_t serial;
1018    E_Comp_Config *comp_conf = NULL;
1019
1020    if (!ec) return;
1021    if (e_object_is_del(E_OBJECT(ec))) return;
1022    if (!ec->comp_data || !ec->comp_data->surface) return;
1023
1024    wc = wl_resource_get_client(ec->comp_data->surface);
1025    serial = wl_display_next_serial(e_comp_wl->wl.disp);
1026
1027    if (pressed)
1028      {
1029         x = wl_fixed_from_int(canvas_x - ec->client.x);
1030         y = wl_fixed_from_int(canvas_y - ec->client.y);
1031      }
1032
1033    comp_conf = e_comp_config_get();
1034
1035    EINA_LIST_FOREACH(e_comp_wl->touch.resources, l, res)
1036      {
1037         if (wl_resource_get_client(res) != wc) continue;
1038         if (!e_comp_wl_input_touch_check(res)) continue;
1039         TRACE_INPUT_BEGIN(_e_comp_wl_send_touch);
1040         if (pressed)
1041           {
1042              if (comp_conf && comp_conf->input_log_enable)
1043                INF("[Server] Touch Down (id: %d, time: %d, x:%d, y:%d, win:0x%08x, name:%20s)\n", idx, timestamp, canvas_x - ec->client.x, canvas_y - ec->client.y, e_client_util_win_get(ec), e_client_util_name_get(ec));
1044
1045              wl_touch_send_down(res, serial, timestamp, ec->comp_data->surface, idx, x, y); //id 0 for the 1st finger
1046           }
1047         else
1048           {
1049              if (comp_conf && comp_conf->input_log_enable)
1050                INF("[Server] Touch Up (id: %d, time: %d, x:%d, y:%d, win:0x%08x, name:%20s)\n", idx, timestamp, canvas_x - ec->client.x, canvas_y - ec->client.y, e_client_util_win_get(ec), e_client_util_name_get(ec));
1051
1052              wl_touch_send_up(res, serial, timestamp, idx);
1053           }
1054         TRACE_INPUT_END();
1055      }
1056 }
1057
1058 static void
1059 _e_comp_wl_send_touch_move(E_Client *ec, int idx, int canvas_x, int canvas_y, uint32_t timestamp)
1060 {
1061    Eina_List *l;
1062    struct wl_client *wc;
1063    struct wl_resource *res;
1064    wl_fixed_t x, y;
1065
1066    if (!ec) return;
1067    if (e_object_is_del(E_OBJECT(ec))) return;
1068    if (!ec->comp_data || !ec->comp_data->surface) return;
1069
1070    wc = wl_resource_get_client(ec->comp_data->surface);
1071
1072    x = wl_fixed_from_int(canvas_x - ec->client.x);
1073    y = wl_fixed_from_int(canvas_y - ec->client.y);
1074
1075    EINA_LIST_FOREACH(e_comp_wl->touch.resources, l, res)
1076      {
1077         if (wl_resource_get_client(res) != wc) continue;
1078         if (!e_comp_wl_input_touch_check(res)) continue;
1079         wl_touch_send_motion(res, timestamp, idx, x, y);
1080      }
1081 }
1082
1083 static void
1084 _e_comp_wl_send_mouse_move(E_Client *ec, int x, int y, unsigned int timestamp)
1085 {
1086    struct wl_resource *res;
1087    struct wl_client *wc;
1088    Eina_List *l;
1089
1090    if (!ec) return;
1091    if (e_object_is_del(E_OBJECT(ec))) return;
1092    if (!ec->comp_data || !ec->comp_data->surface) return;
1093
1094    wc = wl_resource_get_client(ec->comp_data->surface);
1095    EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
1096      {
1097         if (!e_comp_wl_input_pointer_check(res)) continue;
1098         if (wl_resource_get_client(res) != wc) continue;
1099         wl_pointer_send_motion(res, timestamp,
1100                                wl_fixed_from_int(x - ec->client.x),
1101                                wl_fixed_from_int(y - ec->client.y));
1102      }
1103 }
1104
1105 static void
1106 _e_comp_wl_cursor_move_timer_control(E_Client *ec)
1107 {
1108    if (!e_config->use_cursor_timer) return;
1109
1110    if (e_comp_wl->ptr.hide_tmr)
1111      {
1112         if (cursor_timer_ec == ec)
1113           {
1114              ecore_timer_interval_set(e_comp_wl->ptr.hide_tmr, e_config->cursor_timer_interval);
1115              ecore_timer_reset(e_comp_wl->ptr.hide_tmr);
1116           }
1117         else
1118           {
1119              ecore_timer_del(e_comp_wl->ptr.hide_tmr);
1120              cursor_timer_ec = ec;
1121              e_comp_wl->ptr.hide_tmr = ecore_timer_add(e_config->cursor_timer_interval, _e_comp_wl_cursor_timer, ec);
1122           }
1123      }
1124    else
1125      {
1126         cursor_timer_ec = ec;
1127         e_comp_wl->ptr.hide_tmr = ecore_timer_add(e_config->cursor_timer_interval, _e_comp_wl_cursor_timer, ec);
1128      }
1129 }
1130
1131 static void
1132 _e_comp_wl_evas_cb_mouse_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
1133 {
1134    E_Client *ec;
1135    Evas_Event_Mouse_Move *ev;
1136    Evas_Device *dev = NULL;
1137    const char *dev_name;
1138
1139    ev = event;
1140
1141    e_comp->wl_comp_data->ptr.x = wl_fixed_from_int(ev->cur.canvas.x);
1142    e_comp->wl_comp_data->ptr.y = wl_fixed_from_int(ev->cur.canvas.y);
1143
1144    if (!(ec = data)) return;
1145    if (ec->cur_mouse_action) return;
1146    if (e_object_is_del(E_OBJECT(ec))) return;
1147    if ((ec->ignored) && (!ec->remote_surface.provider)) return;
1148    if (!ec->comp_data || !ec->comp_data->surface) return;
1149
1150    if ((!need_send_motion) && (!need_send_released) && (ec->visibility.obscured == E_VISIBILITY_FULLY_OBSCURED)) return;
1151
1152    if ((!e_comp_wl->drag_client) ||
1153        (!e_client_has_xwindow(e_comp_wl->drag_client)))
1154      {
1155         dev = ev->dev;
1156         dev_name = evas_device_description_get(dev);
1157
1158         if (dev && (evas_device_class_get(dev) == EVAS_DEVICE_CLASS_TOUCH))
1159           {
1160              if (e_comp_wl->touch.pressed & (1 << 0))
1161                {
1162                   _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1163                   if (dev_name)
1164                     _e_comp_wl_device_handle_axes(dev_name, evas_device_class_get(dev),
1165                                                   ec, 0, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1166                   _e_comp_wl_send_touch_move(ec, 0, ev->cur.canvas.x, ev->cur.canvas.y, ev->timestamp);
1167                }
1168              e_pointer_touch_move(e_comp->pointer, ev->cur.output.x, ev->cur.output.y);
1169           }
1170         else
1171           {
1172              if (e_config->use_cursor_timer)
1173                {
1174                  if (e_pointer_is_hidden(e_comp->pointer))
1175                    _e_comp_wl_cursor_reload(ec);
1176                }
1177
1178              _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1179              _e_comp_wl_send_mouse_move(ec, ev->cur.canvas.x, ev->cur.canvas.y, ev->timestamp);
1180              e_pointer_mouse_move(e_comp->pointer, ev->cur.output.x, ev->cur.output.y);
1181
1182              _e_comp_wl_cursor_move_timer_control(ec);
1183           }
1184      }
1185 }
1186
1187 static void
1188 _e_comp_wl_evas_handle_mouse_button_to_touch(E_Client *ec, uint32_t timestamp, int canvas_x, int canvas_y, Eina_Bool flag)
1189 {
1190    if (ec->cur_mouse_action || e_comp_wl->drag) return;
1191    if (e_object_is_del(E_OBJECT(ec))) return;
1192    if (!ec->comp_data || !ec->comp_data->surface) return;
1193    if ((ec->ignored) && (!ec->remote_surface.provider)) return;
1194
1195    e_comp_wl->ptr.button = BTN_LEFT;
1196
1197    _e_comp_wl_send_touch(ec, 0, canvas_x, canvas_y, timestamp, flag);
1198 }
1199
1200 static void
1201 _e_comp_wl_send_mouse_out(E_Client *ec)
1202 {
1203    struct wl_resource *res;
1204    struct wl_client *wc;
1205    uint32_t serial;
1206    Eina_List *l;
1207
1208    if (!ec) return;
1209    if (e_object_is_del(E_OBJECT(ec))) return;
1210    if (!ec->comp_data || !ec->comp_data->surface) return;
1211
1212    wc = wl_resource_get_client(ec->comp_data->surface);
1213    serial = wl_display_next_serial(e_comp_wl->wl.disp);
1214    EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
1215      {
1216         if (!e_comp_wl_input_pointer_check(res)) continue;
1217         if (wl_resource_get_client(res) != wc) continue;
1218         wl_pointer_send_leave(res, serial, ec->comp_data->surface);
1219      }
1220 }
1221
1222 static void
1223 _e_comp_wl_evas_cb_mouse_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
1224 {
1225    E_Client *ec = data;
1226    Evas_Event_Mouse_Down *ev = event;
1227    Evas_Device *dev = NULL;
1228    const char *dev_name;
1229    E_Client *focused;
1230
1231    if (!ec) return;
1232    if (e_object_is_del(E_OBJECT(ec))) return;
1233
1234    dev = ev->dev;
1235    dev_name = evas_device_description_get(dev);
1236
1237    _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1238
1239    if (dev &&  (evas_device_class_get(dev) == EVAS_DEVICE_CLASS_TOUCH))
1240      {
1241         if (dev_name)
1242           _e_comp_wl_device_renew_axis(dev_name, evas_device_class_get(dev),
1243                                         ec, 0, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1244         _e_comp_wl_evas_handle_mouse_button_to_touch(ec, ev->timestamp, ev->canvas.x, ev->canvas.y, EINA_TRUE);
1245         e_pointer_touch_move(e_comp->pointer, ev->output.x, ev->output.y);
1246         e_comp_wl->touch.pressed |= (1 << 0);
1247      }
1248    else
1249      {
1250         e_comp_wl_evas_handle_mouse_button(ec, ev->timestamp, ev->button,
1251                                            WL_POINTER_BUTTON_STATE_PRESSED);
1252         e_pointer_mouse_move(e_comp->pointer, ev->output.x, ev->output.y);
1253      }
1254
1255    need_send_released = EINA_TRUE;
1256
1257    focused = e_client_focused_get();
1258    if ((focused) && (ec != focused))
1259      {
1260         if (need_send_leave)
1261           {
1262              need_send_leave = EINA_FALSE;
1263              _e_comp_wl_device_send_event_device(focused, dev, ev->timestamp);
1264              _e_comp_wl_send_mouse_out(focused);
1265           }
1266         e_focus_event_mouse_down(ec);
1267      }
1268    else
1269      need_send_leave = EINA_TRUE;
1270 }
1271
1272 static void
1273 _e_comp_wl_evas_cb_mouse_up(void *data, Evas *evas, Evas_Object *obj EINA_UNUSED, void *event)
1274 {
1275    E_Client *ec = data;
1276    Evas_Event_Mouse_Up *ev = event;
1277    Evas_Device *dev = NULL;
1278    const char *dev_name;
1279    Evas_Event_Flags flags;
1280
1281    if (!ec) return;
1282    if (ec->cur_mouse_action) return;
1283    if (e_object_is_del(E_OBJECT(ec))) return;
1284
1285    if (!need_send_released)
1286      {
1287         need_send_motion = EINA_TRUE;
1288      }
1289
1290    flags = evas_event_default_flags_get(evas);
1291    if (flags & EVAS_EVENT_FLAG_ON_HOLD) goto finish;
1292
1293    dev = ev->dev;
1294    dev_name = evas_device_description_get(dev);
1295
1296    _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1297
1298    if (dev && (evas_device_class_get(dev) == EVAS_DEVICE_CLASS_TOUCH))
1299      {
1300         if (dev_name)
1301           _e_comp_wl_device_handle_axes(dev_name, evas_device_class_get(dev),
1302                                         ec, 0, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1303         _e_comp_wl_evas_handle_mouse_button_to_touch(ec, ev->timestamp, ev->canvas.x, ev->canvas.y, EINA_FALSE);
1304         e_comp_wl->touch.pressed &= ~(1 << 0);
1305      }
1306    else
1307      e_comp_wl_evas_handle_mouse_button(ec, ev->timestamp, ev->button,
1308                                         WL_POINTER_BUTTON_STATE_RELEASED);
1309
1310 finish:
1311    need_send_released = EINA_FALSE;
1312 }
1313
1314 static void
1315 _e_comp_wl_mouse_wheel_send(E_Client *ec, int direction, int z, int timestamp)
1316 {
1317    struct wl_resource *res;
1318    struct wl_client *wc;
1319    Eina_List *l;
1320    uint32_t axis, dir;
1321
1322    if (direction == 0)
1323      axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
1324    else
1325      axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
1326
1327    if (z < 0)
1328      dir = -wl_fixed_from_int(abs(z));
1329    else
1330      dir = wl_fixed_from_int(z);
1331
1332    if (!ec) return;
1333    if (e_object_is_del(E_OBJECT(ec))) return;
1334    if (!ec->comp_data || !ec->comp_data->surface) return;
1335
1336    wc = wl_resource_get_client(ec->comp_data->surface);
1337    EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
1338      {
1339         if (!e_comp_wl_input_pointer_check(res)) continue;
1340         if (wl_resource_get_client(res) != wc) continue;
1341         wl_pointer_send_axis(res, timestamp, axis, dir);
1342      }
1343 }
1344
1345 static void
1346 _e_comp_wl_evas_cb_mouse_wheel(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
1347 {
1348    E_Client *ec;
1349    Evas_Event_Mouse_Wheel *ev;
1350
1351    ev = event;
1352    if (!(ec = data)) return;
1353    if (ec->cur_mouse_action) return;
1354    if (e_object_is_del(E_OBJECT(ec))) return;
1355    if ((ec->ignored) && (!ec->remote_surface.provider)) return;
1356
1357    if (!ec->comp_data || !ec->comp_data->surface) return;
1358
1359    if (!eina_list_count(e_comp_wl->ptr.resources))
1360      return;
1361
1362    _e_comp_wl_device_send_event_device(ec, ev->dev, ev->timestamp);
1363
1364   _e_comp_wl_mouse_wheel_send(ec, ev->direction, ev->z, ev->timestamp);
1365 }
1366
1367 static void
1368 _e_comp_wl_evas_cb_multi_down(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
1369 {
1370    E_Client *ec = data;
1371    Evas_Event_Multi_Down *ev = event;
1372    Evas_Device *dev = NULL;
1373    const char *dev_name;
1374    Evas_Device_Class dev_class;
1375
1376    if (!ec) return;
1377    if (e_object_is_del(E_OBJECT(ec))) return;
1378    if (!ec->comp_data || !ec->comp_data->surface) return;
1379
1380    /* Do not deliver emulated single touch events to client */
1381    if (ev->device == 0) return;
1382
1383    dev = ev->dev;
1384    if (dev && (dev_name = evas_device_description_get(dev)))
1385      {
1386         dev_class = evas_device_class_get(dev);
1387         _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1388         _e_comp_wl_device_renew_axis(dev_name, dev_class, ec, ev->device, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1389      }
1390
1391    _e_comp_wl_send_touch(ec, ev->device, ev->canvas.x, ev->canvas.y, ev->timestamp, EINA_TRUE);
1392    e_comp_wl->touch.pressed |= (1 << ev->device);
1393 }
1394
1395 static void
1396 _e_comp_wl_evas_cb_multi_up(void *data, Evas *evas, Evas_Object *obj EINA_UNUSED, void *event)
1397 {
1398    E_Client *ec = data;
1399    Evas_Event_Multi_Up *ev = event;
1400    Evas_Device *dev = NULL;
1401    const char *dev_name;
1402    Evas_Device_Class dev_class;
1403    Evas_Event_Flags flags;
1404
1405    if (!ec) return;
1406    if (e_object_is_del(E_OBJECT(ec))) return;
1407    if (!ec->comp_data || !ec->comp_data->surface) return;
1408
1409    /* Do not deliver emulated single touch events to client */
1410    if (ev->device == 0) return;
1411
1412    flags = evas_event_default_flags_get(evas);
1413    if (flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1414
1415    dev = ev->dev;
1416    if (dev && (dev_name = evas_device_description_get(dev)))
1417      {
1418         dev_class = evas_device_class_get(dev);
1419         _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1420         _e_comp_wl_device_handle_axes(dev_name, dev_class, ec, ev->device, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1421      }
1422
1423    _e_comp_wl_send_touch(ec, ev->device, 0, 0, ev->timestamp, EINA_FALSE);
1424    e_comp_wl->touch.pressed &= ~(1 << ev->device);
1425 }
1426
1427 static void
1428 _e_comp_wl_evas_cb_multi_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event)
1429 {
1430    E_Client *ec = data;
1431    Evas_Event_Multi_Move *ev = event;
1432    Evas_Device *dev = NULL;
1433    const char *dev_name;
1434    Evas_Device_Class dev_class;
1435
1436    if (!ec) return;
1437    if (e_object_is_del(E_OBJECT(ec))) return;
1438    if (!ec->comp_data || !ec->comp_data->surface) return;
1439
1440    /* Do not deliver emulated single touch events to client */
1441    if (ev->device == 0) return;
1442
1443    if (e_comp_wl->touch.pressed & (1 << ev->device))
1444      {
1445         dev = ev->dev;
1446         if (dev && (dev_name = evas_device_description_get(dev)))
1447           {
1448              dev_class = evas_device_class_get(dev);
1449              _e_comp_wl_device_send_event_device(ec, dev, ev->timestamp);
1450              _e_comp_wl_device_handle_axes(dev_name, dev_class, ec, ev->device, ev->radius_x, ev->radius_y, ev->pressure, ev->angle);
1451           }
1452
1453         _e_comp_wl_send_touch_move(ec, ev->device, ev->cur.canvas.x, ev->cur.canvas.y, ev->timestamp);
1454      }
1455 }
1456
1457 static void
1458 _e_comp_wl_client_priority_adjust(int pid, int set, int adj, Eina_Bool use_adj, Eina_Bool adj_child, Eina_Bool do_child)
1459 {
1460    Eina_List *files;
1461    char *file, buff[PATH_MAX];
1462    FILE *f;
1463    int pid2, ppid;
1464    int num_read;
1465    int n;
1466
1467    if (use_adj)
1468      n = (getpriority(PRIO_PROCESS, pid) + adj);
1469    else
1470      n = set;
1471
1472    setpriority(PRIO_PROCESS, pid, n);
1473
1474    if (adj_child)
1475      use_adj = EINA_TRUE;
1476
1477    if (!do_child) return;
1478
1479    files = ecore_file_ls("/proc");
1480    EINA_LIST_FREE(files, file)
1481       {
1482          if (!isdigit(file[0]))
1483            continue;
1484
1485          snprintf(buff, sizeof(buff), "/proc/%s/stat", file);
1486          if ((f = fopen(buff, "r")))
1487            {
1488               pid2 = -1;
1489               ppid = -1;
1490               num_read = fscanf(f, "%i %*s %*s %i %*s", &pid2, &ppid);
1491               fclose(f);
1492               if (num_read == 2 && ppid == pid)
1493                 _e_comp_wl_client_priority_adjust(pid2, set,
1494                                                   adj, use_adj,
1495                                                   adj_child, do_child);
1496            }
1497
1498          free(file);
1499       }
1500 }
1501
1502 static void
1503 _e_comp_wl_client_priority_raise(E_Client *ec)
1504 {
1505    if (!e_config->priority_control) return;
1506    if (ec->netwm.pid <= 0) return;
1507    if (ec->netwm.pid == getpid()) return;
1508    _e_comp_wl_client_priority_adjust(ec->netwm.pid,
1509                                      e_config->priority - 1, -1,
1510                                      EINA_FALSE, EINA_TRUE, EINA_FALSE);
1511 }
1512
1513 static void
1514 _e_comp_wl_client_priority_normal(E_Client *ec)
1515 {
1516    if (!e_config->priority_control) return;
1517    if (ec->netwm.pid <= 0) return;
1518    if (ec->netwm.pid == getpid()) return;
1519    _e_comp_wl_client_priority_adjust(ec->netwm.pid, e_config->priority, 1,
1520                                      EINA_FALSE, EINA_TRUE, EINA_FALSE);
1521 }
1522
1523 static Eina_Bool
1524 _e_comp_wl_evas_cb_focus_in_timer(E_Client *ec)
1525 {
1526    uint32_t serial;
1527    E_Comp_Wl_Key_Data *k;
1528    struct wl_resource *res;
1529    Eina_List *l;
1530    double t;
1531
1532    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1533
1534    ec->comp_data->on_focus_timer = NULL;
1535
1536    if (!e_comp_wl->kbd.focused) return EINA_FALSE;
1537    serial = wl_display_next_serial(e_comp_wl->wl.disp);
1538    t = ecore_time_unix_get();
1539
1540    EINA_LIST_FOREACH(e_comp_wl->kbd.focused, l, res)
1541      {
1542         wl_array_for_each(k, &e_comp_wl->kbd.keys)
1543           {
1544              _e_comp_wl_send_event_device(wl_resource_get_client(res), t, k->dev, serial);
1545              wl_keyboard_send_key(res, serial, t,
1546                                   k->key, WL_KEYBOARD_KEY_STATE_PRESSED);
1547           }
1548      }
1549    return EINA_FALSE;
1550 }
1551
1552 /* It is called in the following cases:
1553  *  When a normal ec->frame has focus.
1554  *  Or launching image ec is replaced to the real ec.
1555  */
1556 EINTERN void
1557 e_comp_wl_feed_focus_in(E_Client *ec)
1558 {
1559    E_Client *focused;
1560    struct wl_resource *res;
1561    struct wl_client *wc;
1562    Eina_List *l;
1563
1564    if (!ec) return;
1565    if (e_object_is_del(E_OBJECT(ec))) return;
1566    if (ec->iconic) return;
1567
1568    /* block spurious focus events */
1569    focused = e_client_focused_get();
1570    if ((focused) && (ec != focused)) return;
1571
1572    /* raise client priority */
1573    _e_comp_wl_client_priority_raise(ec);
1574
1575    wc = wl_resource_get_client(ec->comp_data->surface);
1576
1577    EINA_LIST_FOREACH(e_comp_wl->kbd.resources, l, res)
1578      {
1579         if (wl_resource_get_client(res) == wc)
1580           {
1581              if (!eina_list_data_find(e_comp_wl->kbd.focused, res))
1582                e_comp_wl->kbd.focused = eina_list_append(e_comp_wl->kbd.focused, res);
1583           }
1584      }
1585
1586    if (!e_comp_wl->kbd.focused) return;
1587    e_comp_wl->kbd.focus = ec->comp_data->surface;
1588    e_comp_wl_input_keyboard_enter_send(ec);
1589    e_comp_wl_data_device_keyboard_focus_set();
1590    ec->comp_data->on_focus_timer =
1591       ecore_timer_add(((e_config->xkb.delay_held_key_input_to_focus)/1000.0),
1592                       (Ecore_Task_Cb)_e_comp_wl_evas_cb_focus_in_timer, ec);
1593    int rotation = ec->e.state.rot.ang.curr;
1594    if (e_comp->pointer->rotation != rotation)
1595      e_pointer_rotation_set(e_comp->pointer, rotation);
1596 }
1597
1598 E_API void
1599 e_comp_wl_subsurface_stack_update(E_Client *ec)
1600 {
1601    E_Client *topmost;
1602
1603    if (!(ec) || !ec->comp_data) return;
1604    if (e_object_is_del(E_OBJECT(ec))) return;
1605    if (ec->comp_data->sub.restacking) return;
1606
1607    /* return if ec isn't both a parent of a subsurface and a subsurface itself */
1608    if (!ec->comp_data->sub.list && !ec->comp_data->sub.below_list && !ec->comp_data->sub.data)
1609      {
1610         if (ec->comp_data->sub.below_obj)
1611           _e_comp_wl_subsurface_restack_bg_rectangle(ec);
1612         return;
1613      }
1614
1615    topmost = e_comp_wl_topmost_parent_get(ec);
1616
1617    _e_comp_wl_subsurface_restack(topmost);
1618    _e_comp_wl_subsurface_restack_bg_rectangle(topmost);
1619
1620    //To update client stack list
1621    if ((ec->comp_data->sub.data) &&
1622        (ec->comp_data->sub.data->parent))
1623      {
1624         E_Client *parent;
1625         Evas_Object *o;
1626
1627         parent = ec->comp_data->sub.data->parent;
1628
1629         if ((parent->comp_data->sub.list) &&
1630             (eina_list_data_find(parent->comp_data->sub.list, ec)))
1631           {
1632              //stack above done
1633              o = evas_object_below_get(ec->frame);
1634              e_comp_object_layer_update(ec->frame, o, NULL);
1635           }
1636         else if ((parent->comp_data->sub.below_list) &&
1637                  (eina_list_data_find(parent->comp_data->sub.below_list, ec)))
1638           {
1639              //stack below done
1640              o = evas_object_above_get(ec->frame);
1641              e_comp_object_layer_update(ec->frame, NULL, o);
1642           }
1643      }
1644 }
1645
1646 static void
1647 _e_comp_wl_evas_cb_focus_in(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1648 {
1649    E_Client *ec;
1650    if (!(ec = data)) return;
1651    e_comp_wl_feed_focus_in(ec);
1652 }
1653
1654 static void
1655 _e_comp_wl_evas_cb_focus_out(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1656 {
1657    E_Client *ec;
1658    struct wl_resource *res;
1659    uint32_t serial;
1660    E_Comp_Wl_Key_Data *k;
1661    Eina_List *l, *ll;
1662    double t;
1663
1664    if (!(ec = data)) return;
1665
1666    if (!ec->comp_data) return;
1667
1668    E_FREE_FUNC(ec->comp_data->on_focus_timer, ecore_timer_del);
1669
1670    /* lower client priority */
1671    if (!e_object_is_del(data))
1672      _e_comp_wl_client_priority_normal(ec);
1673
1674
1675    /* update keyboard modifier state */
1676    wl_array_for_each(k, &e_comp_wl->kbd.keys)
1677       e_comp_wl_input_keyboard_state_update(k->key, EINA_FALSE);
1678
1679    if (!ec->comp_data->surface) return;
1680
1681    if (!eina_list_count(e_comp_wl->kbd.resources)) return;
1682
1683    /* send keyboard_leave to all keyboard resources */
1684    serial = wl_display_next_serial(e_comp_wl->wl.disp);
1685    t = ecore_time_unix_get();
1686
1687    EINA_LIST_FOREACH_SAFE(e_comp_wl->kbd.focused, l, ll, res)
1688      {
1689         wl_array_for_each(k, &e_comp_wl->kbd.keys)
1690           {
1691              _e_comp_wl_send_event_device(wl_resource_get_client(res), t, k->dev, serial);
1692               wl_keyboard_send_key(res, serial, t,
1693                                    k->key, WL_KEYBOARD_KEY_STATE_RELEASED);
1694           }
1695         wl_keyboard_send_leave(res, serial, ec->comp_data->surface);
1696         e_comp_wl->kbd.focused =
1697            eina_list_remove_list(e_comp_wl->kbd.focused, l);
1698      }
1699 }
1700
1701 static void
1702 _e_comp_wl_evas_cb_resize(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1703 {
1704    E_Client *ec;
1705
1706    if (!(ec = data)) return;
1707
1708    if ((ec->shading) || (ec->shaded)) return;
1709    if (!ec->comp_data->shell.configure_send) return;
1710
1711    /* TODO: calculate x, y with transfrom object */
1712    if ((e_client_util_resizing_get(ec)) && (!ec->transformed) && (e_comp_wl->resize.edges))
1713      {
1714         int x, y;
1715
1716         x = ec->mouse.last_down[ec->moveinfo.down.button - 1].w;
1717         y = ec->mouse.last_down[ec->moveinfo.down.button - 1].h;
1718         if (e_comp_object_frame_exists(ec->frame))
1719           e_comp_object_frame_wh_unadjust(ec->frame, x, y, &x, &y);
1720
1721         switch (ec->resize_mode)
1722           {
1723            case E_POINTER_RESIZE_TL:
1724            case E_POINTER_RESIZE_L:
1725            case E_POINTER_RESIZE_BL:
1726              x += ec->mouse.last_down[ec->moveinfo.down.button - 1].mx -
1727                ec->mouse.current.mx;
1728              break;
1729            case E_POINTER_RESIZE_TR:
1730            case E_POINTER_RESIZE_R:
1731            case E_POINTER_RESIZE_BR:
1732              x += ec->mouse.current.mx - ec->mouse.last_down[ec->moveinfo.down.button - 1].mx;
1733              break;
1734            default:
1735              break;;
1736           }
1737         switch (ec->resize_mode)
1738           {
1739            case E_POINTER_RESIZE_TL:
1740            case E_POINTER_RESIZE_T:
1741            case E_POINTER_RESIZE_TR:
1742              y += ec->mouse.last_down[ec->moveinfo.down.button - 1].my -
1743                ec->mouse.current.my;
1744              break;
1745            case E_POINTER_RESIZE_BL:
1746            case E_POINTER_RESIZE_B:
1747            case E_POINTER_RESIZE_BR:
1748              y += ec->mouse.current.my - ec->mouse.last_down[ec->moveinfo.down.button - 1].my;
1749              break;
1750            default:
1751              break;
1752           }
1753         x = E_CLAMP(x, 1, x);
1754         y = E_CLAMP(y, 1, y);
1755         ec->comp_data->shell.configure_send(ec->comp_data->shell.surface,
1756                                             e_comp_wl->resize.edges,
1757                                             x, y);
1758      }
1759    else if ((!ec->fullscreen) && (!ec->maximized) &&
1760             (!ec->comp_data->maximize_pre))
1761      _e_comp_wl_configure_send(ec, 1, 1);
1762
1763    if (ec->comp_data->sub.below_obj)
1764      evas_object_resize(ec->comp_data->sub.below_obj, ec->w, ec->h);
1765 }
1766
1767 static void
1768 _e_comp_wl_evas_cb_state_update(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1769 {
1770    E_Client *ec = data;
1771
1772    if (e_object_is_del(E_OBJECT(ec))) return;
1773
1774    /* check for wayland pixmap */
1775
1776    if (ec->comp_data->shell.configure_send)
1777      _e_comp_wl_configure_send(ec, 0, 0);
1778    ec->comp_data->maximize_pre = 0;
1779 }
1780
1781 static void
1782 _e_comp_wl_evas_cb_maximize_pre(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1783 {
1784    E_Client *ec = data;
1785
1786    ec->comp_data->maximize_pre = 1;
1787 }
1788
1789 static void
1790 _e_comp_wl_evas_cb_delete_request(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1791 {
1792    E_Client *ec;
1793
1794    if (!(ec = data)) return;
1795
1796    e_comp_ignore_win_del(E_PIXMAP_TYPE_WL, e_pixmap_window_get(ec->pixmap));
1797
1798    e_object_del(E_OBJECT(ec));
1799
1800    _e_comp_wl_focus_check();
1801
1802    /* TODO: Delete request send ??
1803     * NB: No such animal wrt wayland */
1804 }
1805
1806 static void
1807 _e_comp_wl_evas_cb_kill_request(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1808 {
1809    E_Client *ec;
1810
1811    if (!(ec = data)) return;
1812
1813    e_comp_ignore_win_del(E_PIXMAP_TYPE_WL, e_pixmap_window_get(ec->pixmap));
1814    if (ec->comp_data)
1815      {
1816         if (ec->comp_data->reparented)
1817           e_client_comp_hidden_set(ec, EINA_TRUE);
1818      }
1819
1820    evas_object_pass_events_set(ec->frame, EINA_TRUE);
1821    if (ec->visible) evas_object_hide(ec->frame);
1822    if (!ec->internal) e_object_del(E_OBJECT(ec));
1823
1824    _e_comp_wl_focus_check();
1825 }
1826
1827 static void
1828 _e_comp_wl_evas_cb_ping(void *data, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
1829 {
1830    E_Client *ec;
1831
1832    if (!(ec = data)) return;
1833    if (!(ec->comp_data)) return;
1834    if (!(ec->comp_data->shell.ping)) return;
1835    if (!(ec->comp_data->shell.surface)) return;
1836
1837    ec->comp_data->shell.ping(ec->comp_data->shell.surface);
1838 }
1839
1840 static void
1841 _e_comp_wl_evas_cb_color_set(void *data, Evas_Object *obj, void *event EINA_UNUSED)
1842 {
1843    E_Client *ec;
1844    int a = 0;
1845
1846    if (!(ec = data)) return;
1847    evas_object_color_get(obj, NULL, NULL, NULL, &a);
1848    if (ec->netwm.opacity == a) return;
1849    ec->netwm.opacity = a;
1850    ec->netwm.opacity_changed = EINA_TRUE;
1851 }
1852
1853 static void
1854 _e_comp_wl_buffer_reference_cb_destroy(struct wl_listener *listener, void *data)
1855 {
1856    E_Comp_Wl_Buffer_Ref *ref;
1857
1858    ref = container_of(listener, E_Comp_Wl_Buffer_Ref, destroy_listener);
1859    if ((E_Comp_Wl_Buffer *)data != ref->buffer) return;
1860    ref->buffer = NULL;
1861    ref->destroy_listener_usable = EINA_FALSE;
1862 }
1863
1864 static void
1865 _e_comp_wl_buffer_cb_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
1866 {
1867    E_Comp_Wl_Buffer *buffer;
1868
1869    buffer = container_of(listener, E_Comp_Wl_Buffer, destroy_listener);
1870
1871    DBG("Wl Buffer Destroy: b %p owner '%s'(%p)",
1872        buffer, buffer->debug_info.owner_name, buffer->debug_info.owner_ptr);
1873
1874    /* remove debug info */
1875    eina_stringshare_del(buffer->debug_info.owner_name);
1876
1877    wl_signal_emit(&buffer->destroy_signal, buffer);
1878
1879    if (buffer->destroy_listener.notify)
1880      {
1881         wl_list_remove(&buffer->destroy_listener.link);
1882         buffer->destroy_listener.notify = NULL;
1883      }
1884
1885    free(buffer);
1886 }
1887
1888 static void
1889 _e_comp_wl_client_evas_init(E_Client *ec)
1890 {
1891    if (!ec || !ec->comp_data) return;
1892    if (ec->comp_data->evas_init) return;
1893
1894    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW,        _e_comp_wl_evas_cb_show,        ec);
1895    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE,        _e_comp_wl_evas_cb_hide,        ec);
1896    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE,        _e_comp_wl_evas_cb_move,        ec);
1897    evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESTACK,     _e_comp_wl_evas_cb_restack,     ec);
1898
1899
1900    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_IN,    EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_in,    ec);
1901    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_OUT,   EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_out,   ec);
1902    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_MOVE,  EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_move,  ec);
1903    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_DOWN,  EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_down,  ec);
1904    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_UP,    EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_up,    ec);
1905    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MOUSE_WHEEL, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_mouse_wheel, ec);
1906
1907    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MULTI_DOWN, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_multi_down, ec);
1908    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MULTI_UP,   EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_multi_up,   ec);
1909    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_MULTI_MOVE, EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_multi_move, ec);
1910
1911    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_FOCUS_IN,    EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_focus_in,    ec);
1912    evas_object_event_callback_priority_add(ec->frame, EVAS_CALLBACK_FOCUS_OUT,   EVAS_CALLBACK_PRIORITY_AFTER, _e_comp_wl_evas_cb_focus_out,   ec);
1913
1914    if (!ec->override)
1915      {
1916         evas_object_smart_callback_add(ec->frame, "client_resize",   _e_comp_wl_evas_cb_resize,       ec);
1917         evas_object_smart_callback_add(ec->frame, "maximize_done",   _e_comp_wl_evas_cb_state_update, ec);
1918         evas_object_smart_callback_add(ec->frame, "unmaximize_done", _e_comp_wl_evas_cb_state_update, ec);
1919         evas_object_smart_callback_add(ec->frame, "maximize_pre",    _e_comp_wl_evas_cb_maximize_pre, ec);
1920         evas_object_smart_callback_add(ec->frame, "unmaximize_pre",  _e_comp_wl_evas_cb_maximize_pre, ec);
1921         evas_object_smart_callback_add(ec->frame, "fullscreen",      _e_comp_wl_evas_cb_state_update, ec);
1922         evas_object_smart_callback_add(ec->frame, "unfullscreen",    _e_comp_wl_evas_cb_state_update, ec);
1923      }
1924
1925    /* setup delete/kill callbacks */
1926    evas_object_smart_callback_add(ec->frame, "delete_request", _e_comp_wl_evas_cb_delete_request, ec);
1927    evas_object_smart_callback_add(ec->frame, "kill_request",   _e_comp_wl_evas_cb_kill_request,   ec);
1928
1929    /* setup ping callback */
1930    evas_object_smart_callback_add(ec->frame, "ping",           _e_comp_wl_evas_cb_ping,           ec);
1931    evas_object_smart_callback_add(ec->frame, "color_set",      _e_comp_wl_evas_cb_color_set,      ec);
1932
1933    ec->comp_data->evas_init = EINA_TRUE;
1934 }
1935
1936 static Eina_Bool
1937 _e_comp_wl_cb_randr_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
1938 {
1939    Eina_List *l;
1940    E_Output *eout;
1941    E_Comp_Screen *e_comp_screen;
1942    unsigned int transform = WL_OUTPUT_TRANSFORM_NORMAL;
1943
1944    if (!e_comp) return ECORE_CALLBACK_RENEW;
1945    if (!e_comp->e_comp_screen) return ECORE_CALLBACK_RENEW;
1946    e_comp_screen = e_comp->e_comp_screen;
1947
1948    EINA_LIST_FOREACH(e_comp_screen->outputs, l, eout)
1949      {
1950         if (!eout->config.enabled)
1951           {
1952              e_comp_wl_output_remove(eout->id);
1953              continue;
1954           }
1955
1956         switch (eout->config.rotation)
1957           {
1958            case 90:
1959              transform = WL_OUTPUT_TRANSFORM_90;
1960              break;
1961            case 180:
1962              transform = WL_OUTPUT_TRANSFORM_180;
1963              break;
1964            case 270:
1965              transform = WL_OUTPUT_TRANSFORM_270;
1966              break;
1967            case 0:
1968            default:
1969              transform = WL_OUTPUT_TRANSFORM_NORMAL;
1970              break;
1971           }
1972
1973         if (!e_comp_wl_output_init(eout->id, eout->info.name,
1974                                    eout->info.screen,
1975                                    eout->config.geom.x, eout->config.geom.y,
1976                                    eout->config.geom.w, eout->config.geom.h,
1977                                    eout->info.size.w, eout->info.size.h,
1978                                    eout->config.mode.refresh, 0, transform))
1979           ERR("Could not initialize screen %s", eout->info.name);
1980      }
1981
1982    return ECORE_CALLBACK_RENEW;
1983 }
1984
1985 static Eina_Bool
1986 _e_comp_wl_cb_comp_object_add(void *data EINA_UNUSED, int type EINA_UNUSED, E_Event_Comp_Object *ev)
1987 {
1988    E_Client *ec;
1989
1990    /* try to get the client from the object */
1991    if (!(ec = e_comp_object_client_get(ev->comp_object)))
1992      return ECORE_CALLBACK_RENEW;
1993
1994    /* check for client being deleted */
1995    if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_RENEW;
1996
1997    /* check for wayland pixmap */
1998    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL)
1999      return ECORE_CALLBACK_RENEW;
2000
2001    /* if we have not setup evas callbacks for this client, do it */
2002    if (!ec->comp_data->evas_init) _e_comp_wl_client_evas_init(ec);
2003
2004    return ECORE_CALLBACK_RENEW;
2005 }
2006
2007 static Eina_Bool
2008 _e_comp_wl_cb_mouse_move(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Move *ev)
2009 {
2010    e_comp_wl->ptr.x = wl_fixed_from_int(ev->x);
2011    e_comp_wl->ptr.y = wl_fixed_from_int(ev->y);
2012    if (e_comp_wl->selection.target &&
2013        e_comp_wl->drag)
2014      {
2015         struct wl_resource *res;
2016         int x, y;
2017
2018         res = e_comp_wl_data_find_for_client(wl_resource_get_client(e_comp_wl->selection.target->comp_data->surface));
2019         EINA_SAFETY_ON_NULL_RETURN_VAL(res, ECORE_CALLBACK_RENEW);
2020
2021         x = ev->x - e_comp_wl->selection.target->client.x;
2022         y = ev->y - e_comp_wl->selection.target->client.y;
2023
2024         if (e_comp_wl->drag_client)
2025           evas_object_move(e_comp_wl->drag_client->frame, ev->x, ev->y);
2026
2027         wl_data_device_send_motion(res, ev->timestamp, wl_fixed_from_int(x), wl_fixed_from_int(y));
2028      }
2029
2030    return ECORE_CALLBACK_RENEW;
2031 }
2032
2033 static Eina_Bool
2034 _e_comp_wl_cb_mouse_button_cancel(void *d EINA_UNUSED, int t EINA_UNUSED, Ecore_Event_Mouse_Button *ev)
2035 {
2036    if (e_comp_wl->ptr.ec)
2037      _e_comp_wl_send_touch_cancel(e_comp_wl->ptr.ec);
2038
2039    return ECORE_CALLBACK_PASS_ON;
2040 }
2041
2042 static Eina_Bool
2043 _e_comp_wl_cb_zone_display_state_change(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Zone_Display_State_Change *ev EINA_UNUSED)
2044 {
2045    if (e_comp_wl->ptr.ec && need_send_released)
2046      {
2047         _e_comp_wl_send_touch_cancel(e_comp_wl->ptr.ec);
2048
2049         need_send_released = EINA_FALSE;
2050       }
2051
2052     return ECORE_CALLBACK_PASS_ON;
2053  }
2054
2055 static Eina_Bool
2056 _e_comp_wl_cb_client_rot_change_begin(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Client_Rotation_Change_Begin *ev)
2057 {
2058    E_Client *ec = ev->ec;
2059    E_Comp_Wl_Buffer_Viewport *vp;
2060
2061    if (!ec) return ECORE_CALLBACK_PASS_ON;
2062    if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
2063    if (!ec->comp_data) return ECORE_CALLBACK_PASS_ON;
2064    if (ec->comp_data->sub.data) return ECORE_CALLBACK_PASS_ON;
2065    if (ec->e.state.rot.ang.next < 0) return ECORE_CALLBACK_PASS_ON;
2066
2067    vp = &ec->comp_data->scaler.buffer_viewport;
2068    vp->wait_for_transform_change = ((360 + ec->e.state.rot.ang.next - ec->e.state.rot.ang.curr) % 360) / 90;
2069
2070    DBG("ec(%p) wait_for_transform_change(%d)", ec, vp->wait_for_transform_change);
2071
2072    return ECORE_CALLBACK_PASS_ON;
2073 }
2074
2075 static Eina_Bool
2076 _e_comp_wl_cb_client_rot_change_cancel(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Client_Rotation_Change_Cancel *ev)
2077 {
2078    E_Client *ec = ev->ec;
2079    E_Comp_Wl_Buffer_Viewport *vp;
2080
2081    if (!ec) return ECORE_CALLBACK_PASS_ON;
2082    if (e_object_is_del(E_OBJECT(ec))) return ECORE_CALLBACK_PASS_ON;
2083    if (!ec->comp_data) return ECORE_CALLBACK_PASS_ON;
2084    if (ec->comp_data->sub.data) return ECORE_CALLBACK_PASS_ON;
2085
2086    vp = &ec->comp_data->scaler.buffer_viewport;
2087    vp->wait_for_transform_change = 0;
2088
2089    DBG("ec(%p) wait_for_transform_change(%d) reset", ec, vp->wait_for_transform_change);
2090
2091    return ECORE_CALLBACK_PASS_ON;
2092 }
2093
2094 static Eina_Bool
2095 _e_comp_wl_cb_client_rot_change_end(void *d EINA_UNUSED, int t EINA_UNUSED, E_Event_Client_Rotation_Change_End *ev EINA_UNUSED)
2096 {
2097    E_Client *focused_ec;
2098    int rotation;
2099
2100    focused_ec = e_client_focused_get();
2101    if (!focused_ec) return ECORE_CALLBACK_PASS_ON;
2102
2103    rotation = focused_ec->e.state.rot.ang.curr;
2104    if (e_comp->pointer->rotation != rotation)
2105      e_pointer_rotation_set(e_comp->pointer, rotation);
2106
2107    return ECORE_CALLBACK_PASS_ON;
2108 }
2109
2110 static void
2111 _e_comp_wl_subsurface_restack(E_Client *ec)
2112 {
2113    E_Client *subc, *temp;
2114    Eina_List *l;
2115
2116    if (!ec || !ec->comp_data || e_object_is_del(E_OBJECT(ec))) return;
2117
2118    temp = ec;
2119    EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
2120      {
2121         if (!subc || !subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
2122         subc->comp_data->sub.restacking = EINA_TRUE;
2123         evas_object_stack_above(subc->frame, temp->frame);
2124         subc->comp_data->sub.restacking = EINA_FALSE;
2125         temp = subc;
2126      }
2127
2128    temp = ec;
2129    EINA_LIST_REVERSE_FOREACH(ec->comp_data->sub.below_list, l, subc)
2130      {
2131         if (!subc || !subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
2132         subc->comp_data->sub.restacking = EINA_TRUE;
2133         evas_object_stack_below(subc->frame, temp->frame);
2134         subc->comp_data->sub.restacking = EINA_FALSE;
2135         temp = subc;
2136      }
2137
2138    EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
2139      _e_comp_wl_subsurface_restack(subc);
2140
2141    EINA_LIST_REVERSE_FOREACH(ec->comp_data->sub.below_list, l, subc)
2142      _e_comp_wl_subsurface_restack(subc);
2143 }
2144
2145 static void
2146 _e_comp_wl_subsurface_restack_bg_rectangle(E_Client *ec)
2147 {
2148    E_Client *bottom = ec;
2149
2150    if (!ec->comp_data->sub.below_obj)
2151      return;
2152
2153    while (bottom)
2154      {
2155         short layer = evas_object_layer_get(bottom->frame);
2156
2157         if (evas_object_layer_get(ec->comp_data->sub.below_obj) != layer)
2158           evas_object_layer_set(ec->comp_data->sub.below_obj, layer);
2159
2160         evas_object_stack_below(ec->comp_data->sub.below_obj, bottom->frame);
2161         bottom = eina_list_nth(bottom->comp_data->sub.below_list, 0);
2162      }
2163 }
2164
2165 static void
2166 _e_comp_wl_subsurface_show(E_Client *ec)
2167 {
2168    E_Client *subc;
2169    Eina_List *l;
2170
2171    if (!ec->comp_data || e_object_is_del(E_OBJECT(ec))) return;
2172
2173    EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
2174      {
2175         if (!subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
2176
2177         if (e_pixmap_resource_get(subc->pixmap) && !subc->comp_data->mapped)
2178           {
2179              subc->visible = EINA_TRUE;
2180              evas_object_show(subc->frame);
2181              subc->comp_data->mapped = 1;
2182           }
2183         _e_comp_wl_subsurface_show(subc);
2184      }
2185
2186    EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
2187      {
2188         if (!subc->comp_data || e_object_is_del(E_OBJECT(subc))) continue;
2189
2190         if (e_pixmap_resource_get(subc->pixmap) && !subc->comp_data->mapped)
2191           {
2192              subc->visible = EINA_TRUE;
2193              evas_object_show(subc->frame);
2194              subc->comp_data->mapped = 1;
2195           }
2196         _e_comp_wl_subsurface_show(subc);
2197      }
2198 }
2199
2200 static void
2201 _e_comp_wl_subsurface_hide(E_Client *ec)
2202 {
2203    E_Client *subc;
2204    Eina_List *l;
2205
2206    EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
2207      {
2208         if (!subc->comp_data || !subc->comp_data->sub.data) continue;
2209
2210         if (!subc->comp_data->sub.data->stand_alone)
2211           {
2212              if (subc->comp_data->mapped)
2213                {
2214                   subc->visible = EINA_FALSE;
2215                   evas_object_hide(subc->frame);
2216                   subc->comp_data->mapped = 0;
2217                }
2218              _e_comp_wl_subsurface_hide(subc);
2219           }
2220      }
2221
2222    EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
2223      {
2224         if (!subc->comp_data || !subc->comp_data->sub.data) continue;
2225
2226         if (!subc->comp_data->sub.data->stand_alone)
2227           {
2228              if (subc->comp_data->mapped)
2229                {
2230                   subc->visible = EINA_FALSE;
2231                   evas_object_hide(subc->frame);
2232                   subc->comp_data->mapped = 0;
2233                }
2234              _e_comp_wl_subsurface_hide(subc);
2235           }
2236      }
2237 }
2238
2239 static E_Client*
2240 _e_comp_wl_subsurface_invisible_parent_get(E_Client *ec)
2241 {
2242    E_Client *parent = NULL;
2243
2244    if (!ec->comp_data || e_object_is_del(E_OBJECT(ec)) || !ec->comp_data->sub.data)
2245       return NULL;
2246
2247    parent = ec->comp_data->sub.data->parent;
2248    while (parent)
2249      {
2250         /* in case of topmost */
2251         if (e_object_is_del(E_OBJECT(parent)) || !parent->comp_data) return NULL;
2252
2253         if (!parent->comp_data->sub.data)
2254           return (!evas_object_visible_get(parent->frame)) ? parent : NULL;
2255
2256         if (!evas_object_visible_get(parent->frame)){
2257           if (e_pixmap_resource_get(parent->pixmap))
2258             return parent;
2259
2260           if (!parent->comp_data->sub.data->parent)
2261             return parent;
2262         }
2263
2264         parent = parent->comp_data->sub.data->parent;
2265      }
2266
2267    return NULL;
2268 }
2269
2270 static Eina_Bool
2271 _e_comp_wl_subsurface_can_show(E_Client *ec)
2272 {
2273    E_Comp_Wl_Subsurf_Data *sdata = ec->comp_data->sub.data;
2274    E_Client *invisible_parent;
2275    E_Client *topmost;
2276
2277    /* if it's not subsurface */
2278    if (!sdata)
2279      return EINA_FALSE;
2280
2281    invisible_parent = _e_comp_wl_subsurface_invisible_parent_get(ec);
2282    topmost = e_comp_wl_topmost_parent_get(ec);
2283
2284    /* if topmost is composited by compositor && if there is a invisible parent */
2285    if (topmost->redirected && invisible_parent)
2286      return EINA_FALSE;
2287
2288    return EINA_TRUE;
2289 }
2290
2291 static Eina_Bool
2292 _e_comp_wl_surface_subsurface_order_commit(E_Client *ec)
2293 {
2294    E_Client *subc, *epc;
2295    Eina_List *l;
2296    Eina_Bool need_restack = EINA_FALSE;
2297
2298    if (!ec->comp_data) return EINA_FALSE;
2299
2300    if (ec->comp_data->sub.data && (epc = ec->comp_data->sub.data->parent))
2301      if (epc->comp_data->sub.list_changed)
2302        need_restack = _e_comp_wl_surface_subsurface_order_commit(epc);
2303
2304    if (!ec->comp_data->sub.list_changed) return (EINA_FALSE | need_restack);
2305    ec->comp_data->sub.list_changed = EINA_FALSE;
2306
2307    /* TODO: need to check more complicated subsurface tree */
2308    EINA_LIST_FOREACH(ec->comp_data->sub.list_pending, l, subc)
2309      {
2310         ec->comp_data->sub.list = eina_list_remove(ec->comp_data->sub.list, subc);
2311         ec->comp_data->sub.list = eina_list_append(ec->comp_data->sub.list, subc);
2312
2313         _e_comp_wl_surface_subsurface_order_commit(subc);
2314      }
2315
2316    EINA_LIST_FOREACH(ec->comp_data->sub.below_list_pending, l, subc)
2317      {
2318         ec->comp_data->sub.below_list = eina_list_remove(ec->comp_data->sub.below_list, subc);
2319         ec->comp_data->sub.below_list = eina_list_append(ec->comp_data->sub.below_list, subc);
2320
2321         _e_comp_wl_surface_subsurface_order_commit(subc);
2322      }
2323
2324    return EINA_TRUE;
2325 }
2326
2327 static void
2328 _e_comp_wl_surface_state_size_update(E_Client *ec, E_Comp_Wl_Surface_State *state)
2329 {
2330    Eina_Rectangle *window;
2331
2332    if (!e_pixmap_size_get(ec->pixmap, &state->bw, &state->bh)) return;
2333    if (e_comp_object_frame_exists(ec->frame)) return;
2334    window = &ec->comp_data->shell.window;
2335    if ((!ec->borderless) && /* FIXME temporarily added this check code
2336                              * to prevent updating E_Client's size by frame */
2337        (window->x || window->y || window->w || window->h))
2338      {
2339         e_comp_object_frame_geometry_set(ec->frame,
2340                                          -window->x,
2341                                          (window->x + window->w) - state->bw,
2342                                          -window->y,
2343                                          (window->y + window->h) - state->bh);
2344      }
2345    else
2346      e_comp_object_frame_geometry_set(ec->frame, 0, 0, 0, 0);
2347 }
2348
2349 static void
2350 _e_comp_wl_surface_state_cb_buffer_destroy(struct wl_listener *listener, void *data EINA_UNUSED)
2351 {
2352    E_Comp_Wl_Surface_State *state;
2353
2354    state =
2355      container_of(listener, E_Comp_Wl_Surface_State, buffer_destroy_listener);
2356    state->buffer = NULL;
2357 }
2358
2359 static void
2360 _e_comp_wl_surface_state_init(E_Comp_Wl_Surface_State *state, int w, int h)
2361 {
2362    state->new_attach = EINA_FALSE;
2363    state->buffer = NULL;
2364    state->buffer_destroy_listener.notify =
2365      _e_comp_wl_surface_state_cb_buffer_destroy;
2366    state->sx = state->sy = 0;
2367
2368    state->input = eina_tiler_new(w, h);
2369    eina_tiler_tile_size_set(state->input, 1, 1);
2370
2371    state->opaque = eina_tiler_new(w, h);
2372    eina_tiler_tile_size_set(state->opaque, 1, 1);
2373
2374    state->buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
2375    state->buffer_viewport.buffer.scale = 1;
2376    state->buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
2377    state->buffer_viewport.surface.width = -1;
2378    state->buffer_viewport.changed = 0;
2379 }
2380
2381 static void
2382 _e_comp_wl_surface_state_finish(E_Comp_Wl_Surface_State *state)
2383 {
2384    struct wl_resource *cb;
2385    Eina_Rectangle *dmg;
2386
2387    EINA_LIST_FREE(state->frames, cb)
2388      wl_resource_destroy(cb);
2389
2390    EINA_LIST_FREE(state->damages, dmg)
2391      eina_rectangle_free(dmg);
2392
2393    EINA_LIST_FREE(state->buffer_damages, dmg)
2394      eina_rectangle_free(dmg);
2395
2396    if (state->opaque) eina_tiler_free(state->opaque);
2397    state->opaque = NULL;
2398
2399    if (state->input) eina_tiler_free(state->input);
2400    state->input = NULL;
2401
2402    if (state->buffer) wl_list_remove(&state->buffer_destroy_listener.link);
2403    state->buffer = NULL;
2404 }
2405
2406 static void
2407 _e_comp_wl_surface_state_buffer_set(E_Comp_Wl_Surface_State *state, E_Comp_Wl_Buffer *buffer)
2408 {
2409    if (state->buffer == buffer) return;
2410    if (state->buffer)
2411      wl_list_remove(&state->buffer_destroy_listener.link);
2412    state->buffer = buffer;
2413    if (state->buffer)
2414      wl_signal_add(&state->buffer->destroy_signal,
2415                    &state->buffer_destroy_listener);
2416 }
2417
2418 static void
2419 _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
2420 {
2421    Eina_Rectangle *dmg;
2422    Eina_Bool placed = EINA_TRUE;
2423    int x = 0, y = 0;
2424    int w, h;
2425    E_Comp_Wl_Buffer *buffer;
2426    struct wl_resource *cb;
2427    Eina_List *l, *ll;
2428    E_Comp_Wl_Buffer_Viewport *vp = &ec->comp_data->scaler.buffer_viewport;
2429
2430    if (ec->ignored)
2431      {
2432         if ((ec->internal) ||
2433             (ec->comp_data->shell.surface && state->new_attach))
2434           {
2435              EC_CHANGED(ec);
2436              ec->new_client = 1;
2437              e_comp->new_clients++;
2438              e_client_unignore(ec);
2439           }
2440      }
2441
2442    if (vp->buffer.transform != state->buffer_viewport.buffer.transform)
2443      {
2444         int transform_change = (4 + state->buffer_viewport.buffer.transform - vp->buffer.transform) & 0x3;
2445
2446         /* when buffer is transformed, we have to apply the new evas-map */
2447         state->buffer_viewport.changed = EINA_TRUE;
2448
2449         ELOGF("TRANSFORM", "buffer_transform changed: old(%d) new(%d)",
2450               ec->pixmap, ec,
2451               vp->buffer.transform, state->buffer_viewport.buffer.transform);
2452
2453         if (transform_change == vp->wait_for_transform_change)
2454           vp->wait_for_transform_change = 0;
2455
2456         if (e_comp_is_on_overlay(ec)) e_comp_hwc_end(__FUNCTION__);
2457      }
2458
2459    ec->comp_data->scaler.buffer_viewport = state->buffer_viewport;
2460
2461    if (state->new_attach)
2462      e_comp_wl_surface_attach(ec, state->buffer);
2463
2464    /* emit a apply_viewport signal when the information of viewport and buffer is ready */
2465    wl_signal_emit(&ec->comp_data->apply_viewport_signal,
2466                   &ec->comp_data->surface);
2467
2468    _e_comp_wl_surface_state_buffer_set(state, NULL);
2469
2470    if ((state->new_attach) ||
2471        (state->buffer_viewport.changed))
2472      {
2473         _e_comp_wl_surface_state_size_update(ec, state);
2474         e_comp_wl_map_size_cal_from_viewport(ec);
2475
2476         if (ec->changes.pos)
2477           {
2478              e_comp_object_frame_xy_unadjust(ec->frame,
2479                                              ec->x, ec->y,
2480                                              &x, &y);
2481           }
2482         else
2483           {
2484              x = ec->client.x;
2485              y = ec->client.y;
2486           }
2487
2488         if (ec->new_client) placed = ec->placed;
2489
2490         if (!ec->lock_client_size)
2491           {
2492              w = ec->w;
2493              h = ec->h;
2494
2495              ec->client.w = state->bw;
2496              ec->client.h = state->bh;
2497
2498              e_comp_object_frame_wh_adjust(ec->frame,
2499                                            ec->client.w, ec->client.h,
2500                                            &ec->w, &ec->h);
2501
2502              if ((w != ec->w) || (h != ec->h))
2503                {
2504                   ec->changes.size = 1;
2505                   EC_CHANGED(ec);
2506                }
2507           }
2508      }
2509
2510    /* map or unmap ec */
2511    if (!e_pixmap_usable_get(ec->pixmap))
2512      {
2513         /* unmap ec */
2514         if (ec->comp_data->mapped)
2515           {
2516              if ((ec->comp_data->shell.surface) &&
2517                  (ec->comp_data->shell.unmap))
2518                {
2519                   ELOGF("COMP", "Try to unmap. Call shell.unmap.", ec->pixmap, ec);
2520                   ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
2521                }
2522              else if ((ec->internal) ||
2523                       (ec->comp_data->sub.data) ||
2524                       (ec == e_comp_wl->drag_client))
2525                {
2526                   ELOGF("COMP", "Try to unmap. Hide window. internal:%d, sub:%p, drag:%d",
2527                         ec->pixmap, ec, ec->internal, ec->comp_data->sub.data, (ec == e_comp_wl->drag_client));
2528                   ec->visible = EINA_FALSE;
2529                   evas_object_hide(ec->frame);
2530                   ec->comp_data->mapped = 0;
2531                }
2532           }
2533
2534         if ((ec->comp_data->sub.below_obj) &&
2535             (evas_object_visible_get(ec->comp_data->sub.below_obj)))
2536           {
2537              evas_object_hide(ec->comp_data->sub.below_obj);
2538           }
2539      }
2540    else
2541      {
2542         /* map ec */
2543         if (!ec->comp_data->mapped)
2544           {
2545              if ((ec->comp_data->shell.surface) &&
2546                  (ec->comp_data->shell.map))
2547                {
2548                   ELOGF("COMP", "Try to map. Call shell.map.", ec->pixmap, ec);
2549                   ec->comp_data->shell.map(ec->comp_data->shell.surface);
2550                }
2551              else if ((ec->internal) ||
2552                       (_e_comp_wl_subsurface_can_show(ec)) ||
2553                       (ec == e_comp_wl->drag_client))
2554                {
2555                   ELOGF("COMP", "Try to map. Show window. internal:%d, drag:%d",
2556                         ec->pixmap, ec, ec->internal, (ec == e_comp_wl->drag_client));
2557                   ec->visible = EINA_TRUE;
2558                   ec->ignored = 0;
2559                   evas_object_show(ec->frame);
2560                   ec->comp_data->mapped = 1;
2561                }
2562           }
2563
2564         if ((ec->comp_data->sub.below_obj) &&
2565             (!evas_object_visible_get(ec->comp_data->sub.below_obj)) &&
2566             (evas_object_visible_get(ec->frame)))
2567           {
2568              evas_object_show(ec->comp_data->sub.below_obj);
2569           }
2570      }
2571
2572    if ((state->new_attach) ||
2573        (state->buffer_viewport.changed))
2574      {
2575         if ((ec->comp_data->shell.surface) &&
2576             (ec->comp_data->shell.configure))
2577           {
2578              ec->comp_data->shell.configure(ec->comp_data->shell.surface,
2579                                             x, y,
2580                                             ec->w, ec->h);
2581           }
2582         else
2583           {
2584              if ((e_comp_wl->drag) &&
2585                  (e_comp_wl->drag_client) &&
2586                  (e_comp_wl->drag_client == ec))
2587                {
2588                   e_comp_wl->drag->dx -= state->sx;
2589                   e_comp_wl->drag->dy -= state->sy;
2590
2591                   e_drag_move(e_comp_wl->drag,
2592                               e_comp_wl->drag->x + state->sx,
2593                               e_comp_wl->drag->y + state->sy);
2594
2595                   e_drag_resize(e_comp_wl->drag,
2596                                 state->bw, state->bh);
2597                }
2598              else
2599                {
2600                   e_client_util_move_resize_without_frame(ec, x, y, ec->w, ec->h);
2601                }
2602           }
2603
2604         if (ec->new_client)
2605           {
2606              ec->placed = placed;
2607              ec->want_focus |= ec->icccm.accepts_focus && (!ec->override);
2608           }
2609      }
2610
2611    if (ec->comp_data->scaler.buffer_viewport.changed)
2612      e_comp_wl_map_apply(ec);
2613
2614    /* resize transform object */
2615    if (ec->transformed)
2616      e_client_transform_update(ec);
2617
2618    state->sx = 0;
2619    state->sy = 0;
2620    state->new_attach = EINA_FALSE;
2621
2622    EINA_LIST_FOREACH_SAFE(ec->comp_data->frames, l, ll, cb)
2623      {
2624         wl_callback_send_done(cb, ecore_time_unix_get() * 1000);
2625         wl_resource_destroy(cb);
2626      }
2627
2628    /* insert state frame callbacks into comp_data->frames
2629     * NB: This clears state->frames list */
2630    ec->comp_data->frames = eina_list_merge(ec->comp_data->frames,
2631                                            state->frames);
2632    state->frames = NULL;
2633
2634    buffer = e_pixmap_resource_get(ec->pixmap);
2635
2636    /* put state damages into surface */
2637    if (ec->frame)
2638      {
2639         /* FIXME: workaround for bad wayland egl driver which doesn't send damage request */
2640         if (!eina_list_count(state->damages) && !eina_list_count(state->buffer_damages))
2641           {
2642              if ((ec->comp_data->buffer_ref.buffer) &&
2643                  ((ec->comp_data->buffer_ref.buffer->type == E_COMP_WL_BUFFER_TYPE_NATIVE) ||
2644                   (ec->comp_data->buffer_ref.buffer->type == E_COMP_WL_BUFFER_TYPE_TBM)))
2645                {
2646                   e_comp_object_damage(ec->frame,
2647                                        0, 0,
2648                                        ec->comp_data->buffer_ref.buffer->w,
2649                                        ec->comp_data->buffer_ref.buffer->h);
2650                }
2651           }
2652         else
2653           {
2654              Eina_List *damages = NULL;
2655
2656              if (eina_list_count(state->buffer_damages))
2657                {
2658                   EINA_LIST_FREE(state->buffer_damages, dmg)
2659                     {
2660                        if (buffer)
2661                          e_comp_wl_rect_convert_inverse(buffer->w, buffer->h,
2662                                                         e_comp_wl_output_buffer_transform_get(ec),
2663                                                         vp->buffer.scale,
2664                                                         dmg->x, dmg->y, dmg->w, dmg->h,
2665                                                         &dmg->x, &dmg->y, &dmg->w, &dmg->h);
2666                        damages = eina_list_append(damages, dmg);
2667                     }
2668                }
2669
2670              EINA_LIST_FREE(state->damages, dmg)
2671                damages = eina_list_append(damages, dmg);
2672
2673              EINA_LIST_FREE(damages, dmg)
2674                {
2675                   /* not creating damage for ec that shows a underlay video */
2676                   if (state->buffer_viewport.changed ||
2677                       !e_comp->wl_comp_data->available_hw_accel.underlay ||
2678                       !buffer || buffer->type != E_COMP_WL_BUFFER_TYPE_VIDEO)
2679                     e_comp_object_damage(ec->frame, dmg->x, dmg->y, dmg->w, dmg->h);
2680
2681                   eina_rectangle_free(dmg);
2682                }
2683           }
2684      }
2685
2686    /* put state opaque into surface */
2687    e_pixmap_image_opaque_set(ec->pixmap, 0, 0, 0, 0);
2688    if (state->opaque)
2689      {
2690         Eina_Rectangle *rect;
2691         Eina_Iterator *itr;
2692
2693         itr = eina_tiler_iterator_new(state->opaque);
2694         EINA_ITERATOR_FOREACH(itr, rect)
2695           {
2696              Eina_Rectangle r;
2697
2698              EINA_RECTANGLE_SET(&r, rect->x, rect->y, rect->w, rect->h);
2699              E_RECTS_CLIP_TO_RECT(r.x, r.y, r.w, r.h, 0, 0, state->bw, state->bh);
2700              e_pixmap_image_opaque_set(ec->pixmap, r.x, r.y, r.w, r.h);
2701              break;
2702           }
2703
2704         eina_iterator_free(itr);
2705      }
2706
2707    /* put state input into surface */
2708    if ((state->input) &&
2709        (!eina_tiler_empty(state->input)))
2710      {
2711         Eina_Tiler *src, *tmp;
2712
2713         tmp = eina_tiler_new(state->bw, state->bh);
2714         eina_tiler_tile_size_set(tmp, 1, 1);
2715         eina_tiler_rect_add(tmp,
2716                             &(Eina_Rectangle){0, 0, state->bw, state->bh});
2717         if ((src = eina_tiler_intersection(state->input, tmp)))
2718           {
2719              Eina_Rectangle *rect;
2720              Eina_Iterator *itr;
2721
2722              e_comp_object_input_objs_del(ec->frame);
2723              itr = eina_tiler_iterator_new(src);
2724              EINA_ITERATOR_FOREACH(itr, rect)
2725                {
2726                   e_comp_object_input_area_set(ec->frame,
2727                                                rect->x, rect->y,
2728                                                rect->w, rect->h);
2729                }
2730
2731              eina_iterator_free(itr);
2732              eina_tiler_free(src);
2733           }
2734         else
2735           e_comp_object_input_area_set(ec->frame, 0, 0, ec->w, ec->h);
2736
2737         eina_tiler_free(tmp);
2738
2739         /* clear input tiler */
2740         eina_tiler_clear(state->input);
2741      }
2742
2743    _e_comp_wl_subsurface_check_below_bg_rectangle(ec);
2744
2745    if (((buffer) &&
2746         (buffer->type == E_COMP_WL_BUFFER_TYPE_VIDEO)) &&
2747        (e_comp->wl_comp_data->available_hw_accel.underlay))
2748      {
2749         e_pixmap_image_clear(ec->pixmap, 1);
2750      }
2751
2752    state->buffer_viewport.changed = 0;
2753
2754    if (buffer &&
2755        ec->exp_iconify.buffer_flush &&
2756        e_policy_visibility_client_is_iconic(ec))
2757      {
2758         e_pixmap_buffer_clear(ec->pixmap, EINA_FALSE);
2759      }
2760 }
2761
2762 static void
2763 _e_comp_wl_surface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
2764 {
2765    DBG("Surface Cb Destroy: %d", wl_resource_get_id(resource));
2766    wl_resource_destroy(resource);
2767 }
2768
2769 static void
2770 _e_comp_wl_surface_cb_attach(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *buffer_resource, int32_t sx, int32_t sy)
2771 {
2772    E_Client *ec;
2773    E_Comp_Wl_Buffer *buffer = NULL;
2774
2775    if (!(ec = wl_resource_get_user_data(resource))) return;
2776    if (e_object_is_del(E_OBJECT(ec))) return;
2777
2778    if (buffer_resource)
2779      {
2780         if (!(buffer = e_comp_wl_buffer_get(buffer_resource, ec)))
2781           {
2782              ERR("Could not get buffer from resource");
2783              wl_client_post_no_memory(client);
2784              return;
2785           }
2786      }
2787
2788    if (!ec->comp_data->mapped)
2789      {
2790         if (ec->comp_data->shell.surface &&
2791             !ec->internal && !ec->comp_data->sub.data && !ec->remote_surface.provider)
2792           {
2793              ELOGF("COMP", "Current unmapped. ATTACH buffer:%p", ec->pixmap, ec, buffer);
2794           }
2795      }
2796
2797    _e_comp_wl_surface_state_buffer_set(&ec->comp_data->pending, buffer);
2798
2799    ec->comp_data->pending.sx = sx;
2800    ec->comp_data->pending.sy = sy;
2801    ec->comp_data->pending.new_attach = EINA_TRUE;
2802 }
2803
2804 static void
2805 _e_comp_wl_surface_cb_damage(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
2806 {
2807    E_Client *ec;
2808    Eina_Rectangle *dmg = NULL;
2809
2810    if (!(ec = wl_resource_get_user_data(resource))) return;
2811    if (e_object_is_del(E_OBJECT(ec))) return;
2812
2813    if (!(dmg = eina_rectangle_new(x, y, w, h))) return;
2814
2815    ec->comp_data->pending.damages =
2816      eina_list_append(ec->comp_data->pending.damages, dmg);
2817 }
2818
2819 static void
2820 _e_comp_wl_frame_cb_destroy(struct wl_resource *resource)
2821 {
2822    E_Client *ec;
2823
2824    if (!(ec = wl_resource_get_user_data(resource))) return;
2825    if (e_object_is_del(E_OBJECT(ec)))
2826      {
2827         if (!e_object_delay_del_ref_get(E_OBJECT(ec)))
2828           return;
2829      }
2830    if (!ec->comp_data) return;
2831
2832    if (ec->comp_data->frames)
2833      {
2834         ec->comp_data->frames =
2835           eina_list_remove(ec->comp_data->frames, resource);
2836      }
2837
2838    if (ec->comp_data->pending.frames)
2839      {
2840         ec->comp_data->pending.frames =
2841           eina_list_remove(ec->comp_data->pending.frames, resource);
2842      }
2843 }
2844
2845 static void
2846 _e_comp_wl_surface_cb_frame(struct wl_client *client, struct wl_resource *resource, uint32_t callback)
2847 {
2848    E_Client *ec;
2849    struct wl_resource *res;
2850
2851    if (!(ec = wl_resource_get_user_data(resource))) return;
2852    if (e_object_is_del(E_OBJECT(ec))) return;
2853
2854    /* create frame callback */
2855    if (!(res =
2856          wl_resource_create(client, &wl_callback_interface, 1, callback)))
2857      {
2858         wl_resource_post_no_memory(resource);
2859         return;
2860      }
2861
2862    wl_resource_set_implementation(res, NULL, ec, _e_comp_wl_frame_cb_destroy);
2863
2864    ec->comp_data->pending.frames =
2865      eina_list_prepend(ec->comp_data->pending.frames, res);
2866 }
2867
2868 static void
2869 _e_comp_wl_surface_cb_opaque_region_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource)
2870 {
2871    E_Client *ec;
2872
2873    if (!(ec = wl_resource_get_user_data(resource))) return;
2874    if (e_object_is_del(E_OBJECT(ec))) return;
2875
2876    if (ec->comp_data->pending.opaque)
2877      eina_tiler_clear(ec->comp_data->pending.opaque);
2878    if (region_resource)
2879      {
2880         Eina_Tiler *tmp;
2881
2882         if (!(tmp = wl_resource_get_user_data(region_resource)))
2883           return;
2884
2885         eina_tiler_union(ec->comp_data->pending.opaque, tmp);
2886
2887         if (!eina_tiler_empty(ec->comp_data->pending.opaque))
2888           {
2889              if (ec->argb)
2890                {
2891                   ec->argb = EINA_FALSE;
2892                   EC_CHANGED(ec);
2893                   e_comp_object_alpha_set(ec->frame, EINA_FALSE);
2894                }
2895           }
2896      }
2897    else
2898      {
2899         if (!ec->argb)
2900           {
2901              ec->argb = EINA_TRUE;
2902              EC_CHANGED(ec);
2903              e_comp_object_alpha_set(ec->frame, EINA_TRUE);
2904           }
2905      }
2906 }
2907
2908 static void
2909 _e_comp_wl_surface_cb_input_region_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *region_resource)
2910 {
2911    E_Client *ec;
2912
2913    if (!(ec = wl_resource_get_user_data(resource))) return;
2914    if (e_object_is_del(E_OBJECT(ec))) return;
2915
2916    if (ec->comp_data->pending.input)
2917      eina_tiler_clear(ec->comp_data->pending.input);
2918    if (region_resource)
2919      {
2920         Eina_Tiler *tmp;
2921
2922         if (!(tmp = wl_resource_get_user_data(region_resource)))
2923           return;
2924
2925         if (eina_tiler_empty(tmp))
2926           {
2927              ELOGF("COMP", "         |unset input rect", NULL, NULL);
2928              e_comp_object_input_objs_del(ec->frame);
2929              e_comp_object_input_area_set(ec->frame, -1, -1, 1, 1);
2930           }
2931         else
2932           eina_tiler_union(ec->comp_data->pending.input, tmp);
2933      }
2934    else
2935      {
2936         eina_tiler_rect_add(ec->comp_data->pending.input,
2937                             &(Eina_Rectangle){0, 0, ec->client.w, ec->client.h});
2938      }
2939 }
2940
2941 static void
2942 _e_comp_wl_surface_cb_commit(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
2943 {
2944    E_Client *ec, *subc;
2945    Eina_List *l;
2946
2947    if (!(ec = wl_resource_get_user_data(resource))) return;
2948    if (e_object_is_del(E_OBJECT(ec))) return;
2949
2950    if (!ec->comp_data->mapped)
2951      {
2952         if (ec->comp_data->shell.surface &&
2953             !ec->internal && !ec->comp_data->sub.data && !ec->remote_surface.provider)
2954           {
2955              ELOGF("COMP", "Current unmapped. COMMIT. pixmap_usable:%d", ec->pixmap, ec, e_pixmap_usable_get(ec->pixmap));
2956           }
2957      }
2958
2959    if (ec->comp_data->need_commit_extern_parent)
2960      {
2961         ec->comp_data->need_commit_extern_parent = 0;
2962         _e_comp_wl_extern_parent_commit(ec);
2963      }
2964
2965    if (e_comp_wl_remote_surface_commit(ec)) return;
2966    if (e_comp_wl_subsurface_commit(ec)) return;
2967
2968    e_comp_wl_surface_commit(ec);
2969
2970    EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
2971      {
2972         if (ec != subc)
2973           _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
2974      }
2975
2976    EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
2977      {
2978         if (ec != subc)
2979           _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
2980      }
2981 }
2982
2983 static void
2984 _e_comp_wl_surface_cb_buffer_transform_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t transform)
2985 {
2986    E_Client *ec;
2987
2988    if (!(ec = wl_resource_get_user_data(resource))) return;
2989    if (e_object_is_del(E_OBJECT(ec))) return;
2990
2991    if (transform < 0 || transform > WL_OUTPUT_TRANSFORM_FLIPPED_270)
2992      {
2993         wl_resource_post_error(resource,
2994                                WL_SURFACE_ERROR_INVALID_TRANSFORM,
2995                                "buffer transform must be a valid transform "
2996                                "('%d' specified)", transform);
2997         return;
2998      }
2999
3000    ec->comp_data->pending.buffer_viewport.buffer.transform = transform;
3001    ec->comp_data->pending.buffer_viewport.changed = 1;
3002 }
3003
3004 static void
3005 _e_comp_wl_surface_cb_buffer_scale_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t scale)
3006 {
3007    E_Client *ec;
3008
3009    if (!(ec = wl_resource_get_user_data(resource))) return;
3010    if (e_object_is_del(E_OBJECT(ec))) return;
3011
3012    if (scale < 1)
3013      {
3014         wl_resource_post_error(resource,
3015                                WL_SURFACE_ERROR_INVALID_SCALE,
3016                                "buffer scale must be at least one "
3017                                "('%d' specified)", scale);
3018         return;
3019      }
3020
3021    ec->comp_data->pending.buffer_viewport.buffer.scale = scale;
3022    ec->comp_data->pending.buffer_viewport.changed = 1;
3023 }
3024
3025 static void
3026 _e_comp_wl_surface_cb_damage_buffer(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
3027 {
3028    E_Client *ec;
3029    Eina_Rectangle *dmg = NULL;
3030
3031    if (!(ec = wl_resource_get_user_data(resource))) return;
3032    if (e_object_is_del(E_OBJECT(ec))) return;
3033
3034    if (!(dmg = eina_rectangle_new(x, y, w, h))) return;
3035
3036    ec->comp_data->pending.buffer_damages =
3037      eina_list_append(ec->comp_data->pending.buffer_damages, dmg);
3038 }
3039
3040 static const struct wl_surface_interface _e_surface_interface =
3041 {
3042    _e_comp_wl_surface_cb_destroy,
3043    _e_comp_wl_surface_cb_attach,
3044    _e_comp_wl_surface_cb_damage,
3045    _e_comp_wl_surface_cb_frame,
3046    _e_comp_wl_surface_cb_opaque_region_set,
3047    _e_comp_wl_surface_cb_input_region_set,
3048    _e_comp_wl_surface_cb_commit,
3049    _e_comp_wl_surface_cb_buffer_transform_set,
3050    _e_comp_wl_surface_cb_buffer_scale_set,
3051    _e_comp_wl_surface_cb_damage_buffer,
3052 };
3053
3054 static void
3055 _e_comp_wl_surface_render_stop(E_Client *ec)
3056 {
3057    /* FIXME: this may be fine after e_pixmap can create textures for wl clients? */
3058    //if ((!ec->internal) && (!e_comp_gl_get()))
3059      ec->dead = 1;
3060
3061    /* check if internal animation is running */
3062    if (e_comp_object_is_animating(ec->frame)) return;
3063    /* check if external animation is running */
3064    if (evas_object_data_get(ec->frame, "effect_running")) return;
3065
3066    evas_object_hide(ec->frame);
3067 }
3068
3069 static void
3070 _e_comp_wl_surface_destroy(struct wl_resource *resource)
3071 {
3072    E_Client *ec;
3073    struct wl_resource *res;
3074    Eina_List *l, *ll;
3075
3076    if (!(ec = wl_resource_get_user_data(resource))) return;
3077
3078    if (ec == e_client_focused_get())
3079      {
3080         EINA_LIST_FOREACH_SAFE(e_comp_wl->kbd.focused, l, ll, res)
3081           {
3082              if (wl_resource_get_client(res) ==
3083                  wl_resource_get_client(ec->comp_data->surface))
3084                e_comp_wl->kbd.focused =
3085                   eina_list_remove_list(e_comp_wl->kbd.focused, l);
3086           }
3087      }
3088
3089    ec->comp_data->surface = NULL;
3090    ec->comp_data->wl_surface = NULL;
3091    e_pixmap_win_id_del(ec->pixmap);
3092
3093    _e_comp_wl_surface_render_stop(ec);
3094    e_object_del(E_OBJECT(ec));
3095 }
3096
3097 static void
3098 _e_comp_wl_compositor_cb_surface_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
3099 {
3100    struct wl_resource *res;
3101    E_Pixmap *ep = NULL;
3102    E_Client *ec = NULL;
3103    pid_t pid;
3104    int internal = 0;
3105
3106    DBG("Compositor Cb Surface Create: %d", id);
3107
3108    TRACE_DS_BEGIN(COMP_WL:SURFACE CREATE CB);
3109
3110    /* try to create an internal surface */
3111    if (!(res = wl_resource_create(client, &wl_surface_interface,
3112                                   wl_resource_get_version(resource), id)))
3113      {
3114         ERR("Could not create compositor surface");
3115         wl_client_post_no_memory(client);
3116         TRACE_DS_END();
3117         return;
3118      }
3119
3120    DBG("\tCreated Resource: %d", wl_resource_get_id(res));
3121
3122    /* set implementation on resource */
3123    wl_resource_set_implementation(res, &_e_surface_interface, NULL,
3124                                   _e_comp_wl_surface_destroy);
3125
3126    wl_client_get_credentials(client, &pid, NULL, NULL);
3127    if (pid == getpid())
3128      {
3129         /* pixmap of internal win was supposed to be created at trap show */
3130         internal = 1;
3131         ec = e_pixmap_find_client(E_PIXMAP_TYPE_WL, (uintptr_t)id);
3132      }
3133    else
3134      {
3135         if ((ep = e_pixmap_find(E_PIXMAP_TYPE_WL, (uintptr_t)res)))
3136           {
3137              ERR("There is e_pixmap already, Delete old e_pixmap %p", ep);
3138              e_pixmap_win_id_del(ep);
3139              ep = NULL;
3140           }
3141      }
3142
3143    if (!ec)
3144      {
3145         /* try to create new pixmap */
3146         if (!(ep = e_pixmap_new(E_PIXMAP_TYPE_WL, res)))
3147           {
3148              ERR("Could not create new pixmap");
3149              wl_resource_destroy(res);
3150              wl_client_post_no_memory(client);
3151              TRACE_DS_END();
3152              return;
3153           }
3154
3155         E_Comp_Wl_Client_Data *cdata = e_pixmap_cdata_get(ep);
3156         if (cdata)
3157           cdata->wl_surface = res;
3158
3159         DBG("\tUsing Pixmap: %p", ep);
3160
3161         if (!(ec = _e_comp_wl_client_usable_get(pid, ep)))
3162           {
3163              ec = e_client_new(ep, 0, internal);
3164           }
3165      }
3166    if (ec)
3167      {
3168         if (!ec->netwm.pid)
3169           ec->netwm.pid = pid;
3170         if (ec->new_client)
3171           e_comp->new_clients--;
3172         ec->new_client = 0;
3173         if ((!ec->client.w) && (ec->client.h))
3174           ec->client.w = ec->client.h = 1;
3175         ec->comp_data->surface = res;
3176      }
3177
3178    /* set reference to pixmap so we can fetch it later */
3179    DBG("\tUsing Client: %p", ec);
3180    wl_resource_set_user_data(res, ec);
3181
3182    /* emit surface create signal */
3183    wl_signal_emit(&e_comp_wl->signals.surface.create, res);
3184
3185    TRACE_DS_END();
3186 }
3187
3188 static void
3189 _e_comp_wl_region_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
3190 {
3191    DBG("Region Destroy: %d", wl_resource_get_id(resource));
3192    wl_resource_destroy(resource);
3193 }
3194
3195 static void
3196 _e_comp_wl_region_cb_add(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
3197 {
3198    Eina_Tiler *tiler;
3199
3200    DBG("Region Add: %d", wl_resource_get_id(resource));
3201    DBG("\tGeom: %d %d %d %d", x, y, w, h);
3202
3203    /* get the tiler from the resource */
3204    if ((tiler = wl_resource_get_user_data(resource)))
3205      eina_tiler_rect_add(tiler, &(Eina_Rectangle){x, y, w, h});
3206 }
3207
3208 static void
3209 _e_comp_wl_region_cb_subtract(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y, int32_t w, int32_t h)
3210 {
3211    Eina_Tiler *tiler;
3212
3213    DBG("Region Subtract: %d", wl_resource_get_id(resource));
3214    DBG("\tGeom: %d %d %d %d", x, y, w, h);
3215
3216    /* get the tiler from the resource */
3217    if ((tiler = wl_resource_get_user_data(resource)))
3218      eina_tiler_rect_del(tiler, &(Eina_Rectangle){x, y, w, h});
3219 }
3220
3221 static const struct wl_region_interface _e_region_interface =
3222 {
3223    _e_comp_wl_region_cb_destroy,
3224    _e_comp_wl_region_cb_add,
3225    _e_comp_wl_region_cb_subtract
3226 };
3227
3228 static void
3229 _e_comp_wl_compositor_cb_region_destroy(struct wl_resource *resource)
3230 {
3231    Eina_Tiler *tiler;
3232
3233    DBG("Compositor Region Destroy: %d", wl_resource_get_id(resource));
3234
3235    /* try to get the tiler from the region resource */
3236    if ((tiler = wl_resource_get_user_data(resource)))
3237      eina_tiler_free(tiler);
3238 }
3239
3240 static void
3241 _e_comp_wl_compositor_cb_region_create(struct wl_client *client, struct wl_resource *resource, uint32_t id)
3242 {
3243    Eina_Tiler *tiler;
3244    struct wl_resource *res;
3245
3246    DBG("Region Create: %d", wl_resource_get_id(resource));
3247
3248    /* try to create new tiler */
3249    if (!(tiler = eina_tiler_new(e_comp->w, e_comp->h)))
3250      {
3251         ERR("Could not create Eina_Tiler");
3252         wl_resource_post_no_memory(resource);
3253         return;
3254      }
3255
3256    /* set tiler size */
3257    eina_tiler_tile_size_set(tiler, 1, 1);
3258
3259    if (!(res = wl_resource_create(client, &wl_region_interface, 1, id)))
3260      {
3261         ERR("\tFailed to create region resource");
3262                 eina_tiler_free(tiler);
3263         wl_resource_post_no_memory(resource);
3264         return;
3265      }
3266
3267    wl_resource_set_implementation(res, &_e_region_interface, tiler,
3268                                   _e_comp_wl_compositor_cb_region_destroy);
3269 }
3270
3271 static const struct wl_compositor_interface _e_comp_interface =
3272 {
3273    _e_comp_wl_compositor_cb_surface_create,
3274    _e_comp_wl_compositor_cb_region_create
3275 };
3276
3277 static void
3278 _e_comp_wl_pname_get(pid_t pid, char *name, int size)
3279 {
3280    if (!name) return;
3281
3282    FILE *h;
3283    char proc[512], pname[512];
3284    size_t len;
3285
3286    snprintf(proc, 512,"/proc/%d/cmdline", pid);
3287
3288    h = fopen(proc, "r");
3289    if (!h) return;
3290
3291    len = fread(pname, sizeof(char), 512, h);
3292    if (len > 0)
3293      pname[len - 1] = '\0';
3294    else
3295      strncpy(pname, "NO NAME", sizeof(pname));
3296
3297    fclose(h);
3298
3299    strncpy(name, pname, size);
3300 }
3301
3302 static void
3303 _e_comp_wl_pname_print(pid_t pid)
3304 {
3305    FILE *h;
3306    char proc[512], pname[512];
3307    size_t len;
3308
3309    snprintf(proc, 512,"/proc/%d/cmdline", pid);
3310
3311    h = fopen(proc, "r");
3312    if (!h) return;
3313
3314    len = fread(pname, sizeof(char), 512, h);
3315    if (len > 0)
3316      pname[len - 1] = '\0';
3317    else
3318      strncpy(pname, "NO NAME", sizeof(pname));
3319
3320    fclose(h);
3321
3322    ELOGF("COMP", "         |%s", NULL, NULL, pname);
3323 }
3324
3325
3326 static void
3327 _e_comp_wl_compositor_cb_unbind(struct wl_resource *res_comp)
3328 {
3329    struct wl_client *client;
3330    pid_t pid = 0;
3331    uid_t uid = 0;
3332    gid_t gid = 0;
3333
3334    client = wl_resource_get_client(res_comp);
3335    if (client)
3336      wl_client_get_credentials(client,
3337                                &pid,
3338                                &uid,
3339                                &gid);
3340
3341    ELOGF("COMP",
3342          "UNBIND   |res_comp:0x%08x|client:0x%08x|%d|%d|%d",
3343          NULL, NULL,
3344          (unsigned int)res_comp,
3345          (unsigned int)client,
3346          pid, uid, gid);
3347
3348    E_Comp *comp;
3349    if ((comp = wl_resource_get_user_data(res_comp)))
3350      {
3351         Eina_List *l;
3352         E_Comp_Connected_Client_Info *cinfo;
3353         EINA_LIST_FOREACH(comp->connected_clients, l, cinfo)
3354           {
3355              if (cinfo->pid == pid)
3356                break;
3357              cinfo = NULL;
3358           }
3359         if (cinfo)
3360           {
3361              if (cinfo->name)
3362                eina_stringshare_del(cinfo->name);
3363              comp->connected_clients = eina_list_remove(comp->connected_clients, cinfo);
3364              E_FREE(cinfo);
3365           }
3366      }
3367 }
3368
3369 static void
3370 _e_comp_wl_compositor_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
3371 {
3372    struct wl_resource *res;
3373    pid_t pid = 0;
3374    uid_t uid = 0;
3375    gid_t gid = 0;
3376
3377    if (!(res =
3378          wl_resource_create(client, &wl_compositor_interface,
3379                             version, id)))
3380      {
3381         ERR("Could not create compositor resource: %m");
3382         wl_client_post_no_memory(client);
3383         return;
3384      }
3385
3386    wl_resource_set_implementation(res, &_e_comp_interface, e_comp, _e_comp_wl_compositor_cb_unbind);
3387
3388    wl_client_get_credentials(client, &pid, &uid, &gid);
3389
3390    ELOGF("COMP",
3391          "BIND     |res_comp:0x%08x|client:0x%08x|%d|%d|%d",
3392          NULL, NULL,
3393          (unsigned int)res,
3394          (unsigned int)client,
3395          pid, uid, gid);
3396
3397    _e_comp_wl_pname_print(pid);
3398
3399    char name[512];
3400    _e_comp_wl_pname_get(pid, name, sizeof(name));
3401
3402    E_Comp_Connected_Client_Info *cinfo;
3403    cinfo = E_NEW(E_Comp_Connected_Client_Info, 1);
3404    if (cinfo)
3405      {
3406         cinfo->name = eina_stringshare_add(name);
3407         cinfo->pid = pid;
3408         cinfo->uid = uid;
3409         cinfo->gid = gid;
3410         e_comp->connected_clients= eina_list_append(e_comp->connected_clients, cinfo);
3411      }
3412 }
3413
3414 static void
3415 _e_comp_wl_subsurface_destroy_sdata(E_Client *ec)
3416 {
3417    E_Comp_Wl_Subsurf_Data *sdata;
3418
3419    if (!ec || !ec->comp_data || !ec->comp_data->sub.data) return;
3420
3421    sdata = ec->comp_data->sub.data;
3422    if (sdata->parent)
3423      {
3424         /* remove this client from parents sub list */
3425         sdata->parent->comp_data->sub.list =
3426           eina_list_remove(sdata->parent->comp_data->sub.list, ec);
3427         sdata->parent->comp_data->sub.list_pending =
3428           eina_list_remove(sdata->parent->comp_data->sub.list_pending, ec);
3429         sdata->parent->comp_data->sub.below_list =
3430           eina_list_remove(sdata->parent->comp_data->sub.below_list, ec);
3431         sdata->parent->comp_data->sub.below_list_pending =
3432           eina_list_remove(sdata->parent->comp_data->sub.below_list_pending, ec);
3433      }
3434
3435    _e_comp_wl_surface_state_finish(&sdata->cached);
3436    e_comp_wl_buffer_reference(&sdata->cached_buffer_ref, NULL);
3437
3438    /* the client is getting deleted, which means the pixmap will be getting
3439     * freed. We need to unset the surface user data */
3440    /* wl_resource_set_user_data(ec->comp_data->surface, NULL); */
3441
3442    E_FREE(sdata);
3443
3444    ec->comp_data->sub.data = NULL;
3445 }
3446
3447 static void
3448 _e_comp_wl_subsurface_destroy(struct wl_resource *resource)
3449 {
3450    E_Client *ec = wl_resource_get_user_data(resource);
3451
3452    if (!e_object_unref(E_OBJECT(ec))) return;
3453    if (e_object_is_del(E_OBJECT(ec))) return;
3454
3455    _e_comp_wl_subsurface_destroy_sdata(ec);
3456 }
3457
3458 static Eina_Bool
3459 _e_comp_wl_subsurface_synchronized_get(E_Comp_Wl_Subsurf_Data *sdata)
3460 {
3461    while (sdata)
3462      {
3463         if (sdata->synchronized) return EINA_TRUE;
3464         if (!sdata->parent) return EINA_FALSE;
3465         sdata = sdata->parent->comp_data->sub.data;
3466      }
3467
3468    return EINA_FALSE;
3469 }
3470
3471 static void
3472 _e_comp_wl_subsurface_bg_evas_cb_resize(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
3473 {
3474    E_Client *ec;
3475
3476    if (!(ec = data)) return;
3477    if (e_object_is_del(E_OBJECT(ec))) return;
3478    if (!ec->comp_data) return;
3479
3480    if (ec->comp_data->sub.below_obj)
3481       evas_object_resize(ec->comp_data->sub.below_obj, ec->w, ec->h);
3482 }
3483
3484 static void
3485 _e_comp_wl_subsurface_check_below_bg_rectangle(E_Client *ec)
3486 {
3487    short layer;
3488
3489    if (!ec || e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3490    if (ec->comp_data->sub.below_obj) return;
3491    if (ec->comp_data->sub.data)
3492      {
3493          E_Client *topmost = e_comp_wl_topmost_parent_get(ec);
3494          if (!topmost || e_object_is_del(E_OBJECT(topmost)) || !topmost->comp_data) return;
3495          if (topmost->comp_data->sub.data) return;
3496          if (topmost->comp_data->sub.below_obj) return;
3497          _e_comp_wl_subsurface_check_below_bg_rectangle(topmost);
3498          return;
3499      }
3500
3501    if (ec->argb) return;
3502
3503    if (ec->comp_data->sub.below_list ||
3504        ec->comp_data->sub.below_list_pending ||
3505        e_comp_wl_video_subsurface_has(ec))
3506      {
3507         ELOGF("COMP", "         |bg_rectangle(%p) created", NULL, ec, ec->comp_data->sub.below_obj);
3508
3509         /* create a bg rectangle if topmost window is 24 depth window */
3510         ec->comp_data->sub.below_obj = evas_object_rectangle_add(e_comp->evas);
3511         EINA_SAFETY_ON_NULL_RETURN(ec->comp_data->sub.below_obj);
3512
3513         layer = evas_object_layer_get(ec->frame);
3514         evas_object_layer_set(ec->comp_data->sub.below_obj, layer);
3515         evas_object_render_op_set(ec->comp_data->sub.below_obj, EVAS_RENDER_COPY);
3516
3517         /* It's more reasonable to use the transparent color instead of black because
3518          * we can show the alpha value of the 24 depth topmost window.
3519          */
3520         evas_object_color_set(ec->comp_data->sub.below_obj, 0x00, 0x00, 0x00, 0x00);
3521         evas_object_move(ec->comp_data->sub.below_obj, ec->x, ec->y);
3522         evas_object_resize(ec->comp_data->sub.below_obj, ec->w, ec->h);
3523         evas_object_name_set(ec->comp_data->sub.below_obj, "below_bg_rectangle");
3524
3525         evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESIZE,
3526                                        _e_comp_wl_subsurface_bg_evas_cb_resize, ec);
3527
3528         /* set alpha only if SW path */
3529         e_comp_object_alpha_set(ec->frame, EINA_TRUE);
3530
3531         /* force update for changing alpha value. If the native surface has been already
3532          * set before, changing alpha value can't be applied to egl image.
3533          */
3534         e_comp_object_native_surface_set(ec->frame, EINA_FALSE);
3535         e_pixmap_image_refresh(ec->pixmap);
3536         e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
3537         e_comp_object_dirty(ec->frame);
3538         e_comp_object_render(ec->frame);
3539
3540         _e_comp_wl_subsurface_restack(ec);
3541         _e_comp_wl_subsurface_restack_bg_rectangle(ec);
3542
3543         if (evas_object_visible_get(ec->frame))
3544           evas_object_show(ec->comp_data->sub.below_obj);
3545      }
3546 }
3547
3548 static void
3549 _e_comp_wl_subsurface_commit_to_cache(E_Client *ec)
3550 {
3551    E_Comp_Client_Data *cdata;
3552    E_Comp_Wl_Subsurf_Data *sdata;
3553    struct wl_resource *cb;
3554    Eina_List *l, *ll;
3555    Eina_Iterator *itr;
3556    Eina_Rectangle *rect;
3557
3558    if (!(cdata = ec->comp_data)) return;
3559    if (!(sdata = cdata->sub.data)) return;
3560
3561    DBG("Subsurface Commit to Cache");
3562
3563    /* move pending damage to cached */
3564    EINA_LIST_FOREACH_SAFE(cdata->pending.damages, l, ll, rect)
3565      eina_list_move_list(&sdata->cached.damages, &cdata->pending.damages, l);
3566
3567    EINA_LIST_FOREACH_SAFE(cdata->pending.buffer_damages, l, ll, rect)
3568      eina_list_move_list(&sdata->cached.buffer_damages, &cdata->pending.buffer_damages, l);
3569
3570    if (cdata->pending.new_attach)
3571      {
3572         sdata->cached.new_attach = EINA_TRUE;
3573         _e_comp_wl_surface_state_buffer_set(&sdata->cached,
3574                                             cdata->pending.buffer);
3575         e_comp_wl_buffer_reference(&sdata->cached_buffer_ref,
3576                                    cdata->pending.buffer);
3577      }
3578
3579    sdata->cached.sx = cdata->pending.sx;
3580    sdata->cached.sy = cdata->pending.sy;
3581    /* sdata->cached.buffer = cdata->pending.buffer; */
3582
3583    /* When subsurface is sync mode, the commit of subsurface can happen before
3584     * a parent surface is committed. In this case, we can't show a attached
3585     * buffer on screen.
3586     */
3587    //sdata->cached.new_attach = cdata->pending.new_attach;
3588
3589    sdata->cached.buffer_viewport.changed |= cdata->pending.buffer_viewport.changed;
3590    sdata->cached.buffer_viewport.buffer =cdata->pending.buffer_viewport.buffer;
3591    sdata->cached.buffer_viewport.surface = cdata->pending.buffer_viewport.surface;
3592
3593    _e_comp_wl_surface_state_buffer_set(&cdata->pending, NULL);
3594    cdata->pending.sx = 0;
3595    cdata->pending.sy = 0;
3596    cdata->pending.new_attach = EINA_FALSE;
3597    cdata->pending.buffer_viewport.changed = 0;
3598
3599    /* copy cdata->pending.opaque into sdata->cached.opaque */
3600    itr = eina_tiler_iterator_new(cdata->pending.opaque);
3601    EINA_ITERATOR_FOREACH(itr, rect)
3602      eina_tiler_rect_add(sdata->cached.opaque, rect);
3603    eina_iterator_free(itr);
3604
3605    /* repeat for input */
3606    itr = eina_tiler_iterator_new(cdata->pending.input);
3607    EINA_ITERATOR_FOREACH(itr, rect)
3608      eina_tiler_rect_add(sdata->cached.input, rect);
3609    eina_iterator_free(itr);
3610
3611    EINA_LIST_FOREACH_SAFE(cdata->pending.frames, l, ll, cb)
3612      {
3613         if (cb)
3614           eina_list_move_list(&sdata->cached.frames,
3615                               &cdata->pending.frames,
3616                               l);
3617      }
3618
3619    sdata->cached.has_data = EINA_TRUE;
3620 }
3621
3622 static void
3623 _e_comp_wl_subsurface_commit_from_cache(E_Client *ec)
3624 {
3625    E_Comp_Client_Data *cdata;
3626    E_Comp_Wl_Subsurf_Data *sdata;
3627
3628    if (!(cdata = ec->comp_data)) return;
3629    if (!(sdata = cdata->sub.data)) return;
3630
3631    DBG("Subsurface Commit from Cache");
3632
3633    _e_comp_wl_surface_state_commit(ec, &sdata->cached);
3634
3635    if (!e_comp_object_damage_exists(ec->frame))
3636      e_pixmap_image_clear(ec->pixmap, 1);
3637
3638    e_comp_wl_buffer_reference(&sdata->cached_buffer_ref, NULL);
3639
3640    if (_e_comp_wl_surface_subsurface_order_commit(ec))
3641      {
3642         E_Client *topmost = e_comp_wl_topmost_parent_get(ec);
3643         _e_comp_wl_subsurface_restack(topmost);
3644         _e_comp_wl_subsurface_restack_bg_rectangle(topmost);
3645      }
3646 }
3647
3648 static void
3649 _e_comp_wl_subsurface_parent_commit(E_Client *ec, Eina_Bool parent_synchronized)
3650 {
3651    E_Client *parent;
3652    E_Comp_Wl_Subsurf_Data *sdata;
3653
3654    if (!ec || e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3655    if (!(sdata = ec->comp_data->sub.data)) return;
3656    if (!(parent = sdata->parent)) return;
3657
3658    if (sdata->position.set)
3659      {
3660         evas_object_move(ec->frame, parent->x + sdata->position.x,
3661                          parent->y + sdata->position.y);
3662         sdata->position.set = EINA_FALSE;
3663      }
3664
3665    if ((parent_synchronized) || (sdata->synchronized))
3666      {
3667         E_Client *subc;
3668         Eina_List *l;
3669
3670         if (sdata->cached.has_data)
3671           _e_comp_wl_subsurface_commit_from_cache(ec);
3672
3673         EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
3674           {
3675              if (ec != subc)
3676                _e_comp_wl_subsurface_parent_commit(subc, EINA_TRUE);
3677           }
3678         EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
3679           {
3680              if (ec != subc)
3681                _e_comp_wl_subsurface_parent_commit(subc, EINA_TRUE);
3682           }
3683      }
3684 }
3685
3686 static void
3687 _e_comp_wl_subsurface_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
3688 {
3689    wl_resource_destroy(resource);
3690 }
3691
3692 static void
3693 _e_comp_wl_subsurface_cb_position_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, int32_t x, int32_t y)
3694 {
3695    E_Client *ec;
3696    E_Comp_Wl_Subsurf_Data *sdata;
3697
3698    DBG("Subsurface Cb Position Set: %d", wl_resource_get_id(resource));
3699
3700    /* try to get the client from resource data */
3701    if (!(ec = wl_resource_get_user_data(resource))) return;
3702    if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3703    if (!(sdata = ec->comp_data->sub.data)) return;
3704
3705    sdata->position.x = x;
3706    sdata->position.y = y;
3707    sdata->position.set = EINA_TRUE;
3708 }
3709
3710 static void
3711 _e_comp_wl_subsurface_cb_place_above(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *sibling_resource)
3712 {
3713    E_Client *ec, *ecs;
3714    E_Client *parent;
3715
3716    DBG("Subsurface Cb Place Above: %d", wl_resource_get_id(resource));
3717
3718    /* try to get the client from resource data */
3719    if (!(ec = wl_resource_get_user_data(resource))) return;
3720    if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3721    if (!ec->comp_data->sub.data) return;
3722
3723    /* try to get the client from the sibling resource */
3724    if (!(ecs = wl_resource_get_user_data(sibling_resource))) return;
3725
3726    if (!ecs->comp_data->sub.data) return;
3727
3728    if (!(parent = ec->comp_data->sub.data->parent)) return;
3729    if (e_object_is_del(E_OBJECT(parent)) || !parent->comp_data) return;
3730
3731    parent->comp_data->sub.list_pending =
3732      eina_list_remove(parent->comp_data->sub.list_pending, ec);
3733
3734    parent->comp_data->sub.list_pending =
3735      eina_list_append_relative(parent->comp_data->sub.list_pending, ec, ecs);
3736
3737    parent->comp_data->sub.list_changed = EINA_TRUE;
3738 }
3739
3740 static void
3741 _e_comp_wl_subsurface_cb_place_below(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *sibling_resource)
3742 {
3743    E_Client *ec, *ecs;
3744    E_Client *parent;
3745
3746    DBG("Subsurface Cb Place Below: %d", wl_resource_get_id(resource));
3747
3748    /* try to get the client from resource data */
3749    if (!(ec = wl_resource_get_user_data(resource))) return;
3750    if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3751    if (!ec->comp_data->sub.data) return;
3752
3753    /* try to get the client from the sibling resource */
3754    if (!(ecs = wl_resource_get_user_data(sibling_resource))) return;
3755
3756    if (!ecs->comp_data->sub.data) return;
3757
3758    if (!(parent = ec->comp_data->sub.data->parent)) return;
3759    if (e_object_is_del(E_OBJECT(parent)) || !parent->comp_data) return;
3760
3761    parent->comp_data->sub.list_pending =
3762      eina_list_remove(parent->comp_data->sub.list_pending, ec);
3763
3764    parent->comp_data->sub.list_pending =
3765      eina_list_prepend_relative(parent->comp_data->sub.list_pending, ec, ecs);
3766
3767    parent->comp_data->sub.list_changed = EINA_TRUE;
3768 }
3769
3770 static void
3771 _e_comp_wl_subsurface_cb_sync_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
3772 {
3773    E_Client *ec;
3774    E_Comp_Wl_Subsurf_Data *sdata;
3775
3776    DBG("Subsurface Cb Sync Set: %d", wl_resource_get_id(resource));
3777
3778    /* try to get the client from resource data */
3779    if (!(ec = wl_resource_get_user_data(resource))) return;
3780    if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3781    if (!(sdata = ec->comp_data->sub.data)) return;
3782
3783    sdata->synchronized = EINA_TRUE;
3784 }
3785
3786 static void
3787 _e_comp_wl_subsurface_cb_desync_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
3788 {
3789    E_Client *ec;
3790    E_Comp_Wl_Subsurf_Data *sdata;
3791
3792    DBG("Subsurface Cb Desync Set: %d", wl_resource_get_id(resource));
3793
3794    /* try to get the client from resource data */
3795    if (!(ec = wl_resource_get_user_data(resource))) return;
3796    if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return;
3797    if (!(sdata = ec->comp_data->sub.data)) return;
3798
3799    sdata->synchronized = EINA_FALSE;
3800 }
3801
3802 static const struct wl_subsurface_interface _e_subsurface_interface =
3803 {
3804    _e_comp_wl_subsurface_cb_destroy,
3805    _e_comp_wl_subsurface_cb_position_set,
3806    _e_comp_wl_subsurface_cb_place_above,
3807    _e_comp_wl_subsurface_cb_place_below,
3808    _e_comp_wl_subsurface_cb_sync_set,
3809    _e_comp_wl_subsurface_cb_desync_set
3810 };
3811
3812 E_API Eina_Bool
3813 e_comp_wl_subsurface_create(E_Client *ec, E_Client *epc, uint32_t id, struct wl_resource *surface_resource)
3814 {
3815    struct wl_client *client;
3816    struct wl_resource *res;
3817    E_Comp_Wl_Subsurf_Data *sdata;
3818    E_Client *offscreen_parent = NULL;
3819
3820    /* try to get the wayland client from the surface resource */
3821    if (!(client = wl_resource_get_client(surface_resource)))
3822      {
3823         ERR("Could not get client from resource %d",
3824             wl_resource_get_id(surface_resource));
3825         return EINA_FALSE;
3826      }
3827
3828    if (!ec || e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return EINA_FALSE;
3829
3830    if (!epc || e_object_is_del(E_OBJECT(epc)))
3831      {
3832         if (ec->comp_data->sub.watcher)
3833           tizen_subsurface_watcher_send_message(ec->comp_data->sub.watcher, TIZEN_SUBSURFACE_WATCHER_MSG_PARENT_ID_INVALID);
3834
3835         /* We have to create a subsurface resource here even though it's error case
3836          * because server will send the fatal error when a client destroy a subsurface object.
3837          * Otherwise, server will kill a client by the fatal error.
3838          */
3839         if (!(res = wl_resource_create(client, &wl_subsurface_interface, 1, id)))
3840           {
3841              ERR("Failed to create subsurface resource");
3842              wl_resource_post_no_memory(surface_resource);
3843              return EINA_FALSE;
3844           }
3845
3846         wl_resource_set_implementation(res, &_e_subsurface_interface, NULL, NULL);
3847
3848         ERR("tizen_policy failed: invalid parent");
3849         return EINA_FALSE;
3850      }
3851
3852    // reparent remote surface provider's subsurfaces
3853    if (epc->comp_data->remote_surface.onscreen_parent)
3854      {
3855         offscreen_parent = epc;
3856         epc = epc->comp_data->remote_surface.onscreen_parent;
3857      }
3858
3859    // check parent relationship is a cycle
3860      {
3861         E_Client *parent = epc;
3862
3863         while(parent)
3864           {
3865              if (ec == parent)
3866                {
3867                   ERR("Subsurface parent relationship is a cycle : [child win : %x, %s], [parent win : %x, %s]",
3868                       e_client_util_win_get(ec), e_client_util_name_get(ec),
3869                       e_client_util_win_get(epc), e_client_util_name_get(epc));
3870
3871                   return EINA_FALSE;
3872                }
3873
3874              if (parent->comp_data->sub.data)
3875                 parent = parent->comp_data->sub.data->parent;
3876              else
3877                 break;
3878           }
3879      }
3880
3881    /* try to allocate subsurface data */
3882    if (!(sdata = E_NEW(E_Comp_Wl_Subsurf_Data, 1)))
3883      {
3884         ERR("Could not allocate space for subsurface data");
3885         goto dat_err;
3886      }
3887
3888    /* try to create the subsurface resource */
3889    if (!(res = wl_resource_create(client, &wl_subsurface_interface, 1, id)))
3890      {
3891         ERR("Failed to create subsurface resource");
3892         wl_resource_post_no_memory(surface_resource);
3893         goto res_err;
3894      }
3895
3896    /* set resource implementation */
3897    wl_resource_set_implementation(res, &_e_subsurface_interface, ec,
3898                                   _e_comp_wl_subsurface_destroy);
3899    e_object_ref(E_OBJECT(ec));
3900
3901    _e_comp_wl_surface_state_init(&sdata->cached, ec->w, ec->h);
3902
3903    /* set subsurface data properties */
3904    sdata->cached_buffer_ref.buffer = NULL;
3905    sdata->resource = res;
3906    sdata->synchronized = EINA_TRUE;
3907    sdata->parent = epc;
3908    sdata->remote_surface.offscreen_parent = offscreen_parent;
3909
3910    /* set subsurface client properties */
3911    ec->borderless = EINA_TRUE;
3912    ec->argb = EINA_TRUE;
3913    ec->lock_border = EINA_TRUE;
3914    ec->lock_focus_in = ec->lock_focus_out = EINA_TRUE;
3915    ec->netwm.state.skip_taskbar = EINA_TRUE;
3916    ec->netwm.state.skip_pager = EINA_TRUE;
3917    ec->no_shape_cut = EINA_TRUE;
3918    ec->border_size = 0;
3919
3920    ELOGF("COMP", "         |subsurface_parent:%p", NULL, ec, epc);
3921    if (offscreen_parent)
3922      ELOGF("COMP", "         |offscreen_parent:%p", NULL, ec, offscreen_parent);
3923
3924    if (epc)
3925      {
3926         if (epc->frame)
3927           {
3928             short layer = evas_object_layer_get(epc->frame);
3929             evas_object_layer_set(ec->frame, layer);
3930           }
3931
3932         if (epc->comp_data)
3933           {
3934              /* append this client to the parents subsurface list */
3935              epc->comp_data->sub.list =
3936                eina_list_append(epc->comp_data->sub.list, ec);
3937              epc->comp_data->sub.list_changed = EINA_TRUE;
3938           }
3939
3940         /* TODO: add callbacks ?? */
3941      }
3942
3943    ec->comp_data->surface = surface_resource;
3944    ec->comp_data->sub.data = sdata;
3945
3946    ec->lock_user_location = 0;
3947    ec->lock_client_location = 0;
3948    ec->lock_user_size = 0;
3949    ec->lock_client_size = 0;
3950    ec->lock_client_stacking = 0;
3951    ec->lock_user_shade = 0;
3952    ec->lock_client_shade = 0;
3953    ec->lock_user_maximize = 0;
3954    ec->lock_client_maximize = 0;
3955    ec->changes.need_maximize = 0;
3956    ec->maximized = E_MAXIMIZE_NONE;
3957    EC_CHANGED(ec);
3958
3959    ec->new_client = ec->netwm.ping = EINA_TRUE;
3960    e_comp->new_clients++;
3961    e_client_unignore(ec);
3962
3963    _e_comp_wl_hook_call(E_COMP_WL_HOOK_SUBSURFACE_CREATE, ec);
3964    return EINA_TRUE;
3965
3966 res_err:
3967    free(sdata);
3968 dat_err:
3969    return EINA_FALSE;
3970 }
3971
3972 static void
3973 _e_comp_wl_surface_sub_list_free(Eina_List *sub_list)
3974 {
3975    E_Client *subc;
3976
3977    EINA_LIST_FREE(sub_list, subc)
3978      {
3979         if (!subc->comp_data || !subc->comp_data->sub.data) continue;
3980
3981         subc->comp_data->sub.data->parent = NULL;
3982
3983         if (subc->comp_data->sub.watcher)
3984           tizen_subsurface_watcher_send_message(subc->comp_data->sub.watcher, TIZEN_SUBSURFACE_WATCHER_MSG_PARENT_ID_DESTROYED);
3985      }
3986 }
3987
3988 static void
3989 _e_comp_wl_subcompositor_cb_destroy(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
3990 {
3991    wl_resource_destroy(resource);
3992 }
3993
3994 static void
3995 _e_comp_wl_subcompositor_cb_subsurface_get(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, uint32_t id, struct wl_resource *surface_resource, struct wl_resource *parent_resource)
3996 {
3997    E_Client *ec, *epc = NULL;
3998    static const char where[] = "get_subsurface: wl_subsurface@";
3999
4000    if (!(ec = wl_resource_get_user_data(surface_resource))) return;
4001    if (!(epc = wl_resource_get_user_data(parent_resource))) return;
4002
4003    if (ec == epc)
4004      {
4005         wl_resource_post_error(resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4006                                "%s%d: wl_surface@%d cannot be its own parent",
4007                                where, id, wl_resource_get_id(surface_resource));
4008         return;
4009      }
4010
4011    if (e_object_is_del(E_OBJECT(ec))) return;
4012    if (e_object_is_del(E_OBJECT(epc))) return;
4013
4014    /* check if this surface is already a sub-surface */
4015    if ((ec->comp_data) && (ec->comp_data->sub.data))
4016      {
4017         wl_resource_post_error(resource,
4018                                WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE,
4019                                "%s%d: wl_surface@%d is already a sub-surface",
4020                                where, id, wl_resource_get_id(surface_resource));
4021         return;
4022      }
4023
4024    /* try to create a new subsurface */
4025    if (!e_comp_wl_subsurface_create(ec, epc, id, surface_resource))
4026      ERR("Failed to create subsurface for surface %d",
4027          wl_resource_get_id(surface_resource));
4028 }
4029
4030 static const struct wl_subcompositor_interface _e_subcomp_interface =
4031 {
4032    _e_comp_wl_subcompositor_cb_destroy,
4033    _e_comp_wl_subcompositor_cb_subsurface_get
4034 };
4035
4036 static void
4037 _e_comp_wl_subcompositor_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version, uint32_t id)
4038 {
4039    struct wl_resource *res;
4040
4041    if (!(res =
4042          wl_resource_create(client, &wl_subcompositor_interface,
4043                             version, id)))
4044      {
4045         ERR("Could not create subcompositor resource: %m");
4046         wl_client_post_no_memory(client);
4047         return;
4048      }
4049
4050    wl_resource_set_implementation(res, &_e_subcomp_interface, e_comp, NULL);
4051
4052    /* TODO: add handlers for client iconify/uniconify */
4053 }
4054
4055 static void
4056 _e_comp_wl_sr_cb_provide_uuid(struct wl_client *client EINA_UNUSED, struct wl_resource *resource EINA_UNUSED, const char *uuid)
4057 {
4058    DBG("Provide UUID callback called for UUID: %s", uuid);
4059 }
4060
4061 static const struct session_recovery_interface _e_session_recovery_interface =
4062 {
4063    _e_comp_wl_sr_cb_provide_uuid,
4064 };
4065
4066 static void
4067 _e_comp_wl_session_recovery_cb_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id)
4068 {
4069    struct wl_resource *res;
4070
4071    if (!(res = wl_resource_create(client, &session_recovery_interface, 1, id)))
4072      {
4073         ERR("Could not create session_recovery interface");
4074         wl_client_post_no_memory(client);
4075         return;
4076      }
4077
4078    /* set implementation on resource */
4079    wl_resource_set_implementation(res, &_e_session_recovery_interface, e_comp, NULL);
4080 }
4081
4082 static void
4083 _e_comp_wl_client_cb_new(void *data EINA_UNUSED, E_Client *ec)
4084 {
4085    Ecore_Window win;
4086
4087    /* make sure this is a wayland client */
4088    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4089
4090    TRACE_DS_BEGIN(COMP_WL:CLIENT NEW HOOK);
4091
4092    /* get window id from pixmap */
4093    win = e_pixmap_window_get(ec->pixmap);
4094
4095    /* ignore fake root windows */
4096    if ((ec->override) && ((ec->x == -77) && (ec->y == -77)))
4097      {
4098         e_comp_ignore_win_add(E_PIXMAP_TYPE_WL, win);
4099         e_object_del(E_OBJECT(ec));
4100         TRACE_DS_END();
4101         return;
4102      }
4103
4104    if (!(ec->comp_data = E_NEW(E_Comp_Client_Data, 1)))
4105      {
4106         ERR("Could not allocate new client data structure");
4107         TRACE_DS_END();
4108         return;
4109      }
4110
4111    wl_signal_init(&ec->comp_data->destroy_signal);
4112    wl_signal_init(&ec->comp_data->apply_viewport_signal);
4113
4114    _e_comp_wl_surface_state_init(&ec->comp_data->pending, ec->w, ec->h);
4115
4116    /* set initial client properties */
4117    ec->argb = EINA_FALSE;
4118    ec->no_shape_cut = EINA_TRUE;
4119    ec->redirected = ec->ignored = 1;
4120    ec->border_size = 0;
4121
4122    /* NB: could not find a better place to do this, BUT for internal windows,
4123     * we need to set delete_request else the close buttons on the frames do
4124     * basically nothing */
4125    if ((ec->internal) || (ec->internal_elm_win))
4126      ec->icccm.delete_request = EINA_TRUE;
4127
4128    /* set initial client data properties */
4129    ec->comp_data->mapped = EINA_FALSE;
4130    ec->comp_data->first_damage = ec->internal;
4131
4132    ec->comp_data->need_reparent = !ec->internal;
4133
4134    ec->comp_data->scaler.buffer_viewport.buffer.transform = WL_OUTPUT_TRANSFORM_NORMAL;
4135    ec->comp_data->scaler.buffer_viewport.buffer.scale = 1;
4136    ec->comp_data->scaler.buffer_viewport.buffer.src_width = wl_fixed_from_int(-1);
4137    ec->comp_data->scaler.buffer_viewport.surface.width = -1;
4138
4139    E_Comp_Client_Data *p_cdata = e_pixmap_cdata_get(ec->pixmap);
4140    EINA_SAFETY_ON_NULL_RETURN(p_cdata);
4141    ec->comp_data->accepts_focus = p_cdata->accepts_focus;
4142    ec->comp_data->conformant = p_cdata->conformant;
4143    ec->comp_data->aux_hint = p_cdata->aux_hint;
4144    ec->comp_data->win_type = p_cdata->win_type;
4145    ec->comp_data->layer = p_cdata->layer;
4146    ec->comp_data->fetch.win_type = p_cdata->fetch.win_type;
4147    ec->comp_data->fetch.layer = p_cdata->fetch.layer;
4148    ec->comp_data->video_client = p_cdata->video_client;
4149
4150    e_pixmap_cdata_set(ec->pixmap, ec->comp_data);
4151
4152    TRACE_DS_END();
4153 }
4154
4155 static void
4156 _e_comp_wl_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
4157 {
4158    /* Eina_Rectangle *dmg; */
4159    struct wl_resource *cb;
4160
4161    /* make sure this is a wayland client */
4162    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4163
4164    TRACE_DS_BEGIN(COMP_WL:CLIENT DEL CB);
4165
4166    if ((!ec->already_unparented) && (ec->comp_data->reparented))
4167      _e_comp_wl_focus_down_set(ec);
4168
4169    ec->already_unparented = EINA_TRUE;
4170    if (ec->comp_data->reparented)
4171      {
4172         /* reset pixmap parent window */
4173         e_pixmap_parent_window_set(ec->pixmap, 0);
4174      }
4175
4176    if (ec->comp_data->sub.data)
4177      _e_comp_wl_subsurface_destroy_sdata(ec);
4178
4179    if (ec->comp_data->sub.below_obj)
4180      evas_object_del(ec->comp_data->sub.below_obj);
4181
4182    /* remove sub list */
4183    /* TODO: if parent is set by onscreen_parent of remote surface? */
4184    _e_comp_wl_surface_sub_list_free(ec->comp_data->sub.list);
4185    ec->comp_data->sub.list = NULL;
4186    _e_comp_wl_surface_sub_list_free(ec->comp_data->sub.list_pending);
4187    ec->comp_data->sub.list_pending = NULL;
4188    _e_comp_wl_surface_sub_list_free(ec->comp_data->sub.below_list);
4189    ec->comp_data->sub.below_list = NULL;
4190    _e_comp_wl_surface_sub_list_free(ec->comp_data->sub.below_list_pending);
4191    ec->comp_data->sub.below_list_pending = NULL;
4192
4193    if (ec->comp_data->sub.watcher)
4194      wl_resource_destroy(ec->comp_data->sub.watcher);
4195
4196    if ((ec->parent) && (ec->parent->modal == ec))
4197      {
4198         ec->parent->lock_close = EINA_FALSE;
4199         ec->parent->modal = NULL;
4200      }
4201
4202    wl_signal_emit(&ec->comp_data->destroy_signal, &ec->comp_data->surface);
4203
4204    _e_comp_wl_surface_state_finish(&ec->comp_data->pending);
4205
4206    e_comp_wl_buffer_reference(&ec->comp_data->buffer_ref, NULL);
4207
4208    EINA_LIST_FREE(ec->comp_data->frames, cb)
4209      wl_resource_destroy(cb);
4210
4211    EINA_LIST_FREE(ec->comp_data->pending.frames, cb)
4212      wl_resource_destroy(cb);
4213
4214    if (ec->comp_data->surface)
4215      wl_resource_set_user_data(ec->comp_data->surface, NULL);
4216
4217    if (ec->internal_elm_win)
4218      _e_comp_wl_surface_render_stop(ec);
4219    _e_comp_wl_focus_check();
4220
4221    if (ec->comp_data->aux_hint.hints)
4222      {
4223         E_Comp_Wl_Aux_Hint *hint;
4224         EINA_LIST_FREE(ec->comp_data->aux_hint.hints, hint)
4225           {
4226              eina_stringshare_del(hint->hint);
4227              eina_stringshare_del(hint->val);
4228              E_FREE(hint);
4229           }
4230      }
4231
4232    if (cursor_timer_ec == ec)
4233      {
4234         E_FREE_FUNC(e_comp_wl->ptr.hide_tmr, ecore_timer_del);
4235         cursor_timer_ec = NULL;
4236      }
4237
4238    if (e_comp_wl->selection.cbhm == ec->comp_data->surface)
4239      e_comp_wl->selection.cbhm = NULL;
4240
4241    if (ec->comp_data->viewport_transform)
4242      {
4243         e_client_transform_core_remove(ec, ec->comp_data->viewport_transform);
4244         e_util_transform_del(ec->comp_data->viewport_transform);
4245         ec->comp_data->viewport_transform = NULL;
4246      }
4247
4248    e_pixmap_cdata_set(ec->pixmap, NULL);
4249
4250    E_FREE(ec->comp_data);
4251
4252    _e_comp_wl_focus_check();
4253
4254    TRACE_DS_END();
4255 }
4256
4257 static void
4258 _e_comp_wl_client_cb_focus_set(void *data EINA_UNUSED, E_Client *ec)
4259 {
4260    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4261
4262    /* send configure */
4263    if (ec->comp_data->shell.configure_send)
4264      {
4265         if (ec->comp_data->shell.surface)
4266           _e_comp_wl_configure_send(ec, 0, 0);
4267      }
4268
4269    e_comp_wl->kbd.focus = ec->comp_data->surface;
4270 }
4271
4272 static void
4273 _e_comp_wl_client_cb_focus_unset(void *data EINA_UNUSED, E_Client *ec)
4274 {
4275    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4276
4277    /* send configure */
4278    if (ec->comp_data->shell.configure_send)
4279      {
4280         if (ec->comp_data->shell.surface)
4281           _e_comp_wl_configure_send(ec, 0, 0);
4282      }
4283
4284    _e_comp_wl_focus_check();
4285
4286    if (e_comp_wl->kbd.focus == ec->comp_data->surface)
4287      e_comp_wl->kbd.focus = NULL;
4288 }
4289
4290 static void
4291 _e_comp_wl_client_cb_resize_begin(void *data EINA_UNUSED, E_Client *ec)
4292 {
4293    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4294    if (ec->keyboard_resizing) return;
4295
4296    /* do nothing currently */
4297    ;
4298 }
4299
4300 static void
4301 _e_comp_wl_client_cb_resize_end(void *data EINA_UNUSED, E_Client *ec)
4302 {
4303    if (e_object_is_del(E_OBJECT(ec))) return;
4304    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4305
4306    e_comp_wl->resize.edges = 0;
4307    e_comp_wl->resize.resource = NULL;
4308
4309    if (ec->pending_resize)
4310      {
4311         ec->changes.pos = EINA_TRUE;
4312         ec->changes.size = EINA_TRUE;
4313         EC_CHANGED(ec);
4314      }
4315
4316    E_FREE_LIST(ec->pending_resize, free);
4317 }
4318
4319 static void
4320 _e_comp_wl_client_cb_move_end(void *data EINA_UNUSED, E_Client *ec)
4321 {
4322    if (e_object_is_del(E_OBJECT(ec))) return;
4323    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4324 }
4325
4326 static void
4327 _e_comp_wl_client_cb_iconify(void *data EINA_UNUSED, E_Client *ec)
4328 {
4329    if (e_object_is_del(E_OBJECT(ec))) return;
4330    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4331
4332    /* DON'T iconify subsurface. When iconfied, buffer will be released. */
4333    _e_comp_wl_subsurface_hide(ec);
4334 }
4335
4336 static void
4337 _e_comp_wl_client_cb_uniconify(void *data EINA_UNUSED, E_Client *ec)
4338 {
4339    if (e_object_is_del(E_OBJECT(ec))) return;
4340    if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_WL) return;
4341
4342    _e_comp_wl_subsurface_show(ec);
4343 }
4344
4345 static E_Client *
4346 _e_comp_wl_client_usable_get(pid_t pid, E_Pixmap *ep)
4347 {
4348    /* NOTE: this will return usable E_Client for a surface of specified process
4349     * by pid. it doesn't care whatever this surfaces is for but care only what
4350     * is owner process of the surface.
4351     */
4352
4353    E_Client *ec = NULL, *_ec = NULL;
4354    Eina_List *l;
4355
4356    /* find launchscreen client list */
4357    if (e_comp->launchscrns)
4358      {
4359         EINA_LIST_FOREACH(e_comp->launchscrns, l, _ec)
4360           {
4361              if (_ec->netwm.pid == pid)
4362                {
4363                   ec = _ec;
4364                   break;
4365                }
4366           }
4367         if (ec)
4368           {
4369              E_Pixmap *oldep = NULL;
4370
4371              if (ec->comp_data)
4372                {
4373                   /* do NOT replace with the client having comp data */
4374                   return NULL;
4375                }
4376
4377              e_comp->launchscrns = eina_list_remove(e_comp->launchscrns, ec);
4378
4379              oldep = e_client_pixmap_change(ec, ep);
4380              if (oldep)
4381                {
4382                   e_pixmap_win_id_del(oldep);
4383                   e_pixmap_free(oldep);
4384                }
4385
4386              if (ec->internal)
4387                ec->internal = 0;
4388
4389              /* to set-up comp data */
4390              _e_comp_wl_client_cb_new(NULL, ec);
4391              ec->ignored = 0;
4392              if (!ec->comp_data) return NULL;
4393              _e_comp_wl_client_evas_init(ec);
4394
4395              ELOGF("COMP", "Reusable ec. new_pixmap:%p", ec->pixmap, ec, ec->pixmap);
4396              _e_comp_wl_hook_call(E_COMP_WL_HOOK_CLIENT_REUSE, ec);
4397           }
4398      }
4399
4400    return ec;
4401 }
4402
4403 static void
4404 _e_comp_wl_cb_output_unbind(struct wl_resource *resource)
4405 {
4406    E_Comp_Wl_Output *output;
4407
4408    if (!(output = wl_resource_get_user_data(resource))) return;
4409
4410    output->resources = eina_list_remove(output->resources, resource);
4411 }
4412
4413 static void
4414 _e_comp_wl_cb_output_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
4415 {
4416    E_Comp_Wl_Output *output;
4417    struct wl_resource *resource;
4418
4419    if (!(output = data)) return;
4420
4421    resource =
4422      wl_resource_create(client, &wl_output_interface, version, id);
4423    if (!resource)
4424      {
4425         wl_client_post_no_memory(client);
4426         return;
4427      }
4428
4429    DBG("Bound Output: %s", output->id);
4430    DBG("\tGeom: %d %d %d %d", output->x, output->y, output->w, output->h);
4431
4432    output->resources = eina_list_append(output->resources, resource);
4433
4434    wl_resource_set_implementation(resource, NULL, output,
4435                                   _e_comp_wl_cb_output_unbind);
4436    wl_resource_set_user_data(resource, output);
4437
4438    wl_output_send_geometry(resource, output->x, output->y,
4439                            output->phys_width, output->phys_height,
4440                            output->subpixel, output->make ?: "",
4441                            output->model ?: "", output->transform);
4442
4443    if (version >= WL_OUTPUT_SCALE_SINCE_VERSION)
4444      wl_output_send_scale(resource, output->scale);
4445
4446    /* 3 == preferred + current */
4447    wl_output_send_mode(resource, 3, output->w, output->h, output->refresh);
4448
4449    if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
4450      wl_output_send_done(resource);
4451 }
4452
4453 static void
4454 _e_comp_wl_gl_init(void *data EINA_UNUSED)
4455 {
4456    Evas *evas = NULL;
4457    Evas_GL *evasgl = NULL;
4458    Evas_GL_API *glapi = NULL;
4459    Evas_GL_Context *ctx = NULL;
4460    Evas_GL_Surface *sfc = NULL;
4461    Evas_GL_Config *cfg = NULL;
4462    Eina_Bool res;
4463
4464    if (!e_comp_gl_get()) return;
4465
4466    /* create dummy evas gl to bind wayland display of enlightenment to egl display */
4467    e_main_ts_begin("\tE_Comp_Wl_GL Init");
4468
4469    /* if wl_drm module doesn't call e_comp_canvas_init yet,
4470     * then we should get evas from ecore_evas.
4471     */
4472    if (e_comp->evas)
4473      evas = e_comp->evas;
4474    else
4475      evas = ecore_evas_get(e_comp->ee);
4476
4477    evasgl = evas_gl_new(evas);
4478    EINA_SAFETY_ON_NULL_GOTO(evasgl, err);
4479
4480    glapi = evas_gl_api_get(evasgl);
4481    EINA_SAFETY_ON_NULL_GOTO(glapi, err);
4482    EINA_SAFETY_ON_NULL_GOTO(glapi->evasglBindWaylandDisplay, err);
4483
4484    cfg = evas_gl_config_new();
4485    EINA_SAFETY_ON_NULL_GOTO(cfg, err);
4486
4487    sfc = evas_gl_surface_create(evasgl, cfg, 1, 1);
4488    EINA_SAFETY_ON_NULL_GOTO(sfc, err);
4489
4490    ctx = evas_gl_context_create(evasgl, NULL);
4491    EINA_SAFETY_ON_NULL_GOTO(ctx, err);
4492
4493    res = evas_gl_make_current(evasgl, sfc, ctx);
4494    EINA_SAFETY_ON_FALSE_GOTO(res, err);
4495
4496    res = glapi->evasglBindWaylandDisplay(evasgl, e_comp_wl->wl.disp);
4497    EINA_SAFETY_ON_FALSE_GOTO(res, err);
4498
4499    evas_gl_config_free(cfg);
4500
4501    e_comp_wl->wl.gl = evasgl;
4502    e_comp_wl->wl.glapi = glapi;
4503    e_comp_wl->wl.glsfc = sfc;
4504    e_comp_wl->wl.glctx = ctx;
4505
4506    /* for native surface */
4507    e_comp->gl = 1;
4508
4509    e_main_ts_end("\tE_Comp_Wl_GL Init Done");
4510
4511    return;
4512
4513 err:
4514    evas_gl_config_free(cfg);
4515    evas_gl_make_current(evasgl, NULL, NULL);
4516    evas_gl_context_destroy(evasgl, ctx);
4517    evas_gl_surface_destroy(evasgl, sfc);
4518    evas_gl_free(evasgl);
4519 }
4520
4521 // FIXME
4522 #if 0
4523 static void
4524 _e_comp_wl_gl_popup_cb_close(void *data,
4525                              Evas_Object *obj EINA_UNUSED,
4526                              void *event_info EINA_UNUSED)
4527 {
4528    evas_object_del(data);
4529 }
4530
4531 static void
4532 _e_comp_wl_gl_popup_cb_focus(void *data,
4533                              Evas_Object *obj EINA_UNUSED,
4534                              void *event_info EINA_UNUSED)
4535 {
4536    elm_object_focus_set(data, EINA_TRUE);
4537 }
4538 #endif
4539
4540 static Eina_Bool
4541 _e_comp_wl_gl_idle(void *data)
4542 {
4543    if (!e_comp->gl)
4544      {
4545         /* show warning window to notify failure of gl init */
4546         // TODO: yigl
4547 #if 0
4548         Evas_Object *win, *bg, *popup, *btn;
4549
4550         win = elm_win_add(NULL, "compositor warning", ELM_WIN_BASIC);
4551         elm_win_title_set(win, "Compositor Warning");
4552         elm_win_autodel_set(win, EINA_TRUE);
4553         elm_win_borderless_set(win, EINA_TRUE);
4554         elm_win_role_set(win, "notification-low");
4555         elm_win_alpha_set(win, EINA_TRUE);
4556
4557         bg = evas_object_rectangle_add(evas_object_evas_get(win));
4558         evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
4559         elm_win_resize_object_add(win, bg);
4560         evas_object_color_set(bg, 125, 125, 125, 125);
4561         evas_object_show(bg);
4562
4563         popup = elm_popup_add(win);
4564         elm_object_text_set(popup,
4565                             _( "Your screen does not support OpenGL.<br>"
4566                                "Falling back to software engine."));
4567         elm_object_part_text_set(popup, "title,text", "Compositor Warning");
4568
4569         btn = elm_button_add(popup);
4570         elm_object_text_set(btn, "Close");
4571         elm_object_part_content_set(popup, "button1", btn);
4572         evas_object_show(btn);
4573
4574         evas_object_smart_callback_add(win, "focus,in", _e_comp_wl_gl_popup_cb_focus, popup);
4575         evas_object_smart_callback_add(btn, "unpressed", _e_comp_wl_gl_popup_cb_close, win);
4576
4577         evas_object_show(popup);
4578         evas_object_show(win);
4579 #endif
4580      }
4581
4582    return ECORE_CALLBACK_CANCEL;
4583 }
4584
4585 static Eina_Bool
4586 _e_comp_wl_compositor_create(void)
4587 {
4588    E_Comp_Wl_Data *cdata;
4589    const char *name;
4590    int fd = 0;
4591    Eina_Bool res;
4592
4593    /* create new compositor data */
4594    if (!(cdata = E_NEW(E_Comp_Wl_Data, 1)))
4595      {
4596        ERR("Could not create compositor data: %m");
4597        return EINA_FALSE;
4598      }
4599
4600    /* set compositor wayland data */
4601    e_comp_wl = e_comp->wl_comp_data = cdata;
4602
4603    /* try to create a wayland display */
4604    if (!(cdata->wl.disp = wl_display_create()))
4605      {
4606         ERR("Could not create a Wayland display: %m");
4607         goto disp_err;
4608      }
4609
4610    /* try to setup wayland socket */
4611    if (!(name = wl_display_add_socket_auto(cdata->wl.disp)))
4612      {
4613         ERR("Could not create Wayland display socket: %m");
4614         PRCTL("[Winsys] Could not create Wayland display socket: /run/wayland-0");
4615         goto sock_err;
4616      }
4617
4618    res = e_comp_socket_init(name);
4619    EINA_SAFETY_ON_FALSE_GOTO(res, sock_err);
4620    PRCTL("[Winsys] change permission and create sym link for %s", name);
4621
4622    /* set wayland display environment variable */
4623    e_env_set("WAYLAND_DISPLAY", name);
4624
4625    /* initialize compositor signals */
4626    wl_signal_init(&cdata->signals.surface.create);
4627    wl_signal_init(&cdata->signals.surface.activate);
4628    wl_signal_init(&cdata->signals.surface.kill);
4629
4630    /* cdata->output.transform = WL_OUTPUT_TRANSFORM_NORMAL; */
4631    /* cdata->output.scale = e_scale; */
4632
4633    /* try to add compositor to wayland globals */
4634    if (!wl_global_create(cdata->wl.disp, &wl_compositor_interface,
4635                          COMPOSITOR_VERSION, e_comp,
4636                          _e_comp_wl_compositor_cb_bind))
4637      {
4638         ERR("Could not add compositor to wayland globals: %m");
4639         goto comp_global_err;
4640      }
4641
4642    /* try to add subcompositor to wayland globals */
4643    if (!wl_global_create(cdata->wl.disp, &wl_subcompositor_interface, 1,
4644                          e_comp, _e_comp_wl_subcompositor_cb_bind))
4645      {
4646         ERR("Could not add subcompositor to wayland globals: %m");
4647         goto comp_global_err;
4648      }
4649
4650    /* try to add session_recovery to wayland globals */
4651    if (!wl_global_create(cdata->wl.disp, &session_recovery_interface, 1,
4652                          e_comp, _e_comp_wl_session_recovery_cb_bind))
4653      {
4654         ERR("Could not add session_recovery to wayland globals: %m");
4655         goto comp_global_err;
4656      }
4657
4658    /* initialize shm mechanism */
4659    wl_display_init_shm(cdata->wl.disp);
4660
4661    /* _e_comp_wl_cb_randr_change(NULL, 0, NULL); */
4662
4663    /* try to init data manager */
4664    if (!e_comp_wl_data_manager_init())
4665      {
4666         ERR("Could not initialize data manager");
4667         goto data_err;
4668      }
4669
4670    /* try to init input */
4671    if (!e_comp_wl_input_init())
4672      {
4673         ERR("Could not initialize input");
4674         goto input_err;
4675      }
4676
4677    if (e_comp_gl_get())
4678      _e_comp_wl_gl_init(NULL);
4679
4680    /* get the wayland display loop */
4681    cdata->wl.loop = wl_display_get_event_loop(cdata->wl.disp);
4682
4683    /* get the file descriptor of the wayland event loop */
4684    fd = wl_event_loop_get_fd(cdata->wl.loop);
4685
4686    /* create a listener for wayland main loop events */
4687    cdata->fd_hdlr =
4688      ecore_main_fd_handler_add(fd, (ECORE_FD_READ | ECORE_FD_ERROR),
4689                                _e_comp_wl_cb_read, cdata, NULL, NULL);
4690    ecore_main_fd_handler_prepare_callback_set(cdata->fd_hdlr,
4691                                               _e_comp_wl_cb_prepare, cdata);
4692
4693    return EINA_TRUE;
4694
4695 input_err:
4696    e_comp_wl_data_manager_shutdown();
4697 data_err:
4698 comp_global_err:
4699    e_env_unset("WAYLAND_DISPLAY");
4700 sock_err:
4701    wl_display_destroy(cdata->wl.disp);
4702 disp_err:
4703    free(cdata);
4704    return EINA_FALSE;
4705 }
4706
4707 static void
4708 _e_comp_wl_gl_shutdown(void)
4709 {
4710    if (!e_comp_wl->wl.gl) return;
4711
4712    e_comp_wl->wl.glapi->evasglUnbindWaylandDisplay(e_comp_wl->wl.gl, e_comp_wl->wl.disp);
4713
4714    evas_gl_make_current(e_comp_wl->wl.gl, NULL, NULL);
4715    evas_gl_context_destroy(e_comp_wl->wl.gl, e_comp_wl->wl.glctx);
4716    evas_gl_surface_destroy(e_comp_wl->wl.gl, e_comp_wl->wl.glsfc);
4717    evas_gl_free(e_comp_wl->wl.gl);
4718
4719    e_comp_wl->wl.glsfc = NULL;
4720    e_comp_wl->wl.glctx = NULL;
4721    e_comp_wl->wl.glapi = NULL;
4722    e_comp_wl->wl.gl = NULL;
4723 }
4724
4725 /* public functions */
4726
4727 /**
4728  * Creates and initializes a Wayland compositor with ecore.
4729  * Registers callback handlers for keyboard and mouse activity
4730  * and other client events.
4731  *
4732  * @returns true on success, false if initialization failed.
4733  */
4734 E_API Eina_Bool
4735 e_comp_wl_init(void)
4736 {
4737    TRACE_DS_BEGIN(COMP_WL:INIT);
4738
4739    /* try to create a wayland compositor */
4740    if (!_e_comp_wl_compositor_create())
4741      {
4742         e_error_message_show(_("Enlightenment cannot create a Wayland Compositor!\n"));
4743         TRACE_DS_END();
4744         return EINA_FALSE;
4745      }
4746
4747    e_comp_wl_shell_init();
4748
4749 #ifdef HAVE_WAYLAND_TBM
4750    e_comp_wl_tbm_init();
4751 #endif
4752    e_comp_wl_remote_surface_init();
4753
4754    e_pixmap_init();
4755
4756    e_comp_wl_screenshooter_init();
4757    e_comp_wl_video_init();
4758    e_comp_wl_viewport_init();
4759
4760    /* add event handlers to catch E events */
4761    E_LIST_HANDLER_APPEND(handlers, E_EVENT_SCREEN_CHANGE,            _e_comp_wl_cb_randr_change,        NULL);
4762    E_LIST_HANDLER_APPEND(handlers, E_EVENT_COMP_OBJECT_ADD,         _e_comp_wl_cb_comp_object_add,     NULL);
4763    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_MOVE,          _e_comp_wl_cb_mouse_move,          NULL);
4764    E_LIST_HANDLER_APPEND(handlers, ECORE_EVENT_MOUSE_BUTTON_CANCEL, _e_comp_wl_cb_mouse_button_cancel, NULL);
4765    E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DISPLAY_STATE_CHANGE, _e_comp_wl_cb_zone_display_state_change, NULL);
4766    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN, _e_comp_wl_cb_client_rot_change_begin, NULL);
4767    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL, _e_comp_wl_cb_client_rot_change_cancel, NULL);
4768    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ROTATION_CHANGE_END, _e_comp_wl_cb_client_rot_change_end, NULL);
4769
4770    /* add hooks to catch e_client events */
4771    E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_NEW_CLIENT,   _e_comp_wl_client_cb_new,          NULL);
4772    E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_DEL,          _e_comp_wl_client_cb_del,          NULL);
4773    E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_FOCUS_SET,    _e_comp_wl_client_cb_focus_set,    NULL);
4774    E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_FOCUS_UNSET,  _e_comp_wl_client_cb_focus_unset,  NULL);
4775    E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_RESIZE_BEGIN, _e_comp_wl_client_cb_resize_begin, NULL);
4776    E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_RESIZE_END,   _e_comp_wl_client_cb_resize_end,   NULL);
4777    E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_MOVE_END,     _e_comp_wl_client_cb_move_end,     NULL);
4778    E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_ICONIFY,      _e_comp_wl_client_cb_iconify,      NULL);
4779    E_LIST_HOOK_APPEND(hooks, E_CLIENT_HOOK_UNICONIFY,    _e_comp_wl_client_cb_uniconify,    NULL);
4780
4781    E_EVENT_WAYLAND_GLOBAL_ADD = ecore_event_type_new();
4782
4783    TRACE_DS_END();
4784    return EINA_TRUE;
4785 }
4786
4787 E_API void
4788 e_comp_wl_deferred_job(void)
4789 {
4790    ecore_idle_enterer_add(_e_comp_wl_gl_idle, NULL);
4791 }
4792
4793 /**
4794  * Get the signal that is fired for the creation of a Wayland surface.
4795  *
4796  * @returns the corresponding Wayland signal
4797  */
4798 E_API struct wl_signal
4799 e_comp_wl_surface_create_signal_get(void)
4800 {
4801    return e_comp_wl->signals.surface.create;
4802 }
4803
4804 /* internal functions */
4805 EINTERN void
4806 e_comp_wl_shutdown(void)
4807 {
4808    /* free handlers */
4809    E_FREE_LIST(handlers, ecore_event_handler_del);
4810    E_FREE_LIST(hooks, e_client_hook_del);
4811    _e_comp_wl_gl_shutdown();
4812
4813    e_comp_wl_viewport_shutdown();
4814    e_comp_wl_video_shutdown();
4815    e_comp_wl_screenshooter_shutdown();
4816
4817 #ifdef HAVE_WAYLAND_TBM
4818    e_comp_wl_tbm_shutdown();
4819 #endif
4820    e_comp_wl_remote_surface_shutdown();
4821
4822    e_pixmap_shutdown();
4823
4824    e_comp_wl_shell_shutdown();
4825    e_comp_wl_input_shutdown();
4826
4827    // TODO: yigl
4828 #if 0
4829    E_Comp_Wl_Output *output;
4830
4831    if (e_comp_wl->screenshooter.global)
4832      wl_global_destroy(e_comp_wl->screenshooter.global);
4833
4834    EINA_LIST_FREE(e_comp_wl->outputs, output)
4835      {
4836         if (output->id) eina_stringshare_del(output->id);
4837         if (output->make) eina_stringshare_del(output->make);
4838         if (output->model) eina_stringshare_del(output->model);
4839         free(output);
4840      }
4841
4842    /* delete fd handler */
4843    if (e_comp_wl->fd_hdlr) ecore_main_fd_handler_del(e_comp_wl->fd_hdlr);
4844
4845    E_FREE_FUNC(e_comp_wl->ptr.hide_tmr, ecore_timer_del);
4846    cursor_timer_ec = NULL;
4847
4848    /* free allocated data structure */
4849    free(e_comp_wl);
4850 #endif
4851 }
4852
4853 static void
4854 e_comp_wl_surface_event_simple_free(void *d EINA_UNUSED, E_Event_Client *ev)
4855 {
4856    e_object_unref(E_OBJECT(ev->ec));
4857    free(ev);
4858 }
4859
4860 EINTERN void
4861 e_comp_wl_surface_attach(E_Client *ec, E_Comp_Wl_Buffer *buffer)
4862 {
4863    E_Event_Client *ev;
4864    ev = E_NEW(E_Event_Client, 1);
4865    if (!ev) return;
4866
4867    e_comp_wl_buffer_reference(&ec->comp_data->buffer_ref, buffer);
4868
4869    /* set usable early because shell module checks this */
4870    e_pixmap_usable_set(ec->pixmap, (buffer != NULL));
4871    e_pixmap_resource_set(ec->pixmap, buffer);
4872    e_pixmap_dirty(ec->pixmap);
4873    e_pixmap_refresh(ec->pixmap);
4874
4875    e_comp_wl_map_size_cal_from_buffer(ec);
4876    _e_comp_wl_surface_state_size_update(ec, &ec->comp_data->pending);
4877
4878    /* wm-policy module uses it */
4879    _e_comp_wl_hook_call(E_COMP_WL_HOOK_BUFFER_CHANGE, ec);
4880
4881    ev->ec = ec;
4882    e_object_ref(E_OBJECT(ec));
4883    ecore_event_add(E_EVENT_CLIENT_BUFFER_CHANGE, ev,
4884                    (Ecore_End_Cb)e_comp_wl_surface_event_simple_free, NULL);
4885 }
4886
4887 E_API Eina_Bool
4888 e_comp_wl_surface_commit(E_Client *ec)
4889 {
4890    Eina_Bool ignored;
4891
4892    _e_comp_wl_surface_state_commit(ec, &ec->comp_data->pending);
4893    if (!e_comp_object_damage_exists(ec->frame))
4894      e_pixmap_image_clear(ec->pixmap, 1);
4895
4896    ignored = ec->ignored;
4897
4898    if (_e_comp_wl_surface_subsurface_order_commit(ec))
4899      {
4900         E_Client *topmost = e_comp_wl_topmost_parent_get(ec);
4901         _e_comp_wl_subsurface_restack(topmost);
4902         _e_comp_wl_subsurface_restack_bg_rectangle(topmost);
4903      }
4904
4905    if (!e_pixmap_usable_get(ec->pixmap))
4906      {
4907         if (ec->comp_data->mapped)
4908           {
4909              if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.unmap))
4910                {
4911                   ELOGF("COMP", "Try to unmap2. Call shell.unmap.", ec->pixmap, ec);
4912                   ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
4913                }
4914              else if (e_client_has_xwindow(ec) || ec->internal || ec->comp_data->sub.data ||
4915                       (ec == e_comp_wl->drag_client))
4916                {
4917                   ELOGF("COMP", "Try to unmap2. Hide window. internal:%d, sub:%p, drag:%d",
4918                         ec->pixmap, ec, ec->internal, ec->comp_data->sub.data, (ec == e_comp_wl->drag_client));
4919                   ec->visible = EINA_FALSE;
4920                   evas_object_hide(ec->frame);
4921                   ec->comp_data->mapped = 0;
4922                }
4923           }
4924
4925         if (ec->comp_data->sub.below_obj && evas_object_visible_get(ec->comp_data->sub.below_obj))
4926           evas_object_hide(ec->comp_data->sub.below_obj);
4927      }
4928    else
4929      {
4930         if (!ec->comp_data->mapped)
4931           {
4932              if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.map))
4933                {
4934                   ELOGF("COMP", "Try to map2. Call shell.map.", ec->pixmap, ec);
4935                   ec->comp_data->shell.map(ec->comp_data->shell.surface);
4936                }
4937              else if (e_client_has_xwindow(ec) || ec->internal || _e_comp_wl_subsurface_can_show(ec) ||
4938                       (ec == e_comp_wl->drag_client))
4939                {
4940                   ELOGF("COMP", "Try to map2. Show window. internal:%d, drag:%d",
4941                         ec->pixmap, ec, ec->internal, (ec == e_comp_wl->drag_client));
4942                   ec->visible = EINA_TRUE;
4943                   ec->ignored = 0;
4944                   evas_object_show(ec->frame);
4945                   ec->comp_data->mapped = 1;
4946                }
4947           }
4948
4949         if (ec->comp_data->sub.below_obj && !evas_object_visible_get(ec->comp_data->sub.below_obj)
4950             && evas_object_visible_get(ec->frame))
4951           evas_object_show(ec->comp_data->sub.below_obj);
4952      }
4953    ec->ignored = ignored;
4954    return EINA_TRUE;
4955 }
4956
4957 EINTERN Eina_Bool
4958 e_comp_wl_subsurface_commit(E_Client *ec)
4959 {
4960    E_Comp_Wl_Subsurf_Data *sdata;
4961
4962    /* check for valid subcompositor data */
4963    if (e_object_is_del(E_OBJECT(ec)) || !ec->comp_data) return EINA_FALSE;
4964    if (!(sdata = ec->comp_data->sub.data)) return EINA_FALSE;
4965
4966    if (_e_comp_wl_subsurface_synchronized_get(sdata))
4967      _e_comp_wl_subsurface_commit_to_cache(ec);
4968    else
4969      {
4970         E_Client *subc;
4971         Eina_List *l;
4972
4973         if (sdata->position.set)
4974           {
4975              E_Client *parent = sdata->parent;
4976              if (parent)
4977                {
4978                   evas_object_move(ec->frame, parent->x + sdata->position.x,
4979                                    parent->y + sdata->position.y);
4980                   sdata->position.set = EINA_FALSE;
4981                }
4982           }
4983
4984         if (sdata->cached.has_data)
4985           {
4986              _e_comp_wl_subsurface_commit_to_cache(ec);
4987              _e_comp_wl_subsurface_commit_from_cache(ec);
4988           }
4989         else
4990           e_comp_wl_surface_commit(ec);
4991
4992         EINA_LIST_FOREACH(ec->comp_data->sub.list, l, subc)
4993           {
4994              if (ec != subc)
4995                _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
4996           }
4997         EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
4998           {
4999              if (ec != subc)
5000                _e_comp_wl_subsurface_parent_commit(subc, EINA_FALSE);
5001           }
5002      }
5003
5004    return EINA_TRUE;
5005 }
5006
5007 E_API void
5008 e_comp_wl_buffer_reference(E_Comp_Wl_Buffer_Ref *ref, E_Comp_Wl_Buffer *buffer)
5009 {
5010    if ((ref->buffer) && (buffer != ref->buffer))
5011      {
5012         ref->buffer->busy--;
5013         if (ref->buffer->busy == 0)
5014           {
5015              if (ref->buffer->resource)
5016                {
5017                   if (!wl_resource_get_client(ref->buffer->resource)) return;
5018
5019                   wl_buffer_send_release(ref->buffer->resource);
5020 #ifdef HAVE_WAYLAND_TBM
5021                   wayland_tbm_server_increase_buffer_sync_timeline(e_comp_wl->tbm.server,
5022                                                                    ref->buffer->resource, 1);
5023 #endif
5024                }
5025              else
5026                {
5027                   if (ref->buffer->type == E_COMP_WL_BUFFER_TYPE_TBM)
5028                      e_comp_wl_tbm_buffer_destroy(ref->buffer);
5029                }
5030           }
5031
5032         if (ref->destroy_listener_usable)
5033           {
5034              wl_list_remove(&ref->destroy_listener.link);
5035              ref->destroy_listener_usable = EINA_FALSE;
5036           }
5037      }
5038
5039    if ((buffer) && (buffer != ref->buffer))
5040      {
5041         buffer->busy++;
5042         wl_signal_add(&buffer->destroy_signal, &ref->destroy_listener);
5043         ref->destroy_listener_usable = EINA_TRUE;
5044      }
5045
5046    ref->buffer = buffer;
5047    ref->destroy_listener.notify = _e_comp_wl_buffer_reference_cb_destroy;
5048 }
5049
5050 /**
5051  * Get the buffer for a given resource.
5052  *
5053  * Retrieves the Wayland SHM buffer for the resource and
5054  * uses it to create a new E_Comp_Wl_Buffer object. This
5055  * buffer will be freed when the resource is destroyed.
5056  *
5057  * @param resource that owns the desired buffer
5058  * @returns a new E_Comp_Wl_Buffer object
5059  */
5060 E_API E_Comp_Wl_Buffer *
5061 e_comp_wl_buffer_get(struct wl_resource *resource, E_Client *ec)
5062 {
5063    E_Comp_Wl_Buffer *buffer = NULL;
5064    struct wl_listener *listener;
5065    struct wl_shm_buffer *shmbuff;
5066    Eina_Bool res;
5067    tbm_surface_h tbm_surf;
5068
5069    listener =
5070      wl_resource_get_destroy_listener(resource, _e_comp_wl_buffer_cb_destroy);
5071    if (listener)
5072      return container_of(listener, E_Comp_Wl_Buffer, destroy_listener);
5073
5074    if (!(buffer = E_NEW(E_Comp_Wl_Buffer, 1))) return NULL;
5075
5076    shmbuff = wl_shm_buffer_get(resource);
5077
5078    /* TODO: This option is temporarily. It will be removed later. */
5079    /* prefer to use native buffer(wl_buffer) */
5080    if (e_comp->use_native_type_buffer)
5081      {
5082         if (shmbuff)
5083           {
5084              buffer->type = E_COMP_WL_BUFFER_TYPE_SHM;
5085
5086              buffer->w = wl_shm_buffer_get_width(shmbuff);
5087              buffer->h = wl_shm_buffer_get_height(shmbuff);
5088           }
5089         else
5090           {
5091              if ((ec) && (ec->comp_data->video_client))
5092                {
5093                   buffer->type = E_COMP_WL_BUFFER_TYPE_VIDEO;
5094                   buffer->w = buffer->h = 1;
5095                }
5096              else if (e_comp->gl)
5097                {
5098                   buffer->type = E_COMP_WL_BUFFER_TYPE_NATIVE;
5099
5100                   res = e_comp_wl->wl.glapi->evasglQueryWaylandBuffer(e_comp_wl->wl.gl,
5101                                                                       resource,
5102                                                                       EVAS_GL_WIDTH,
5103                                                                       &buffer->w);
5104                   EINA_SAFETY_ON_FALSE_GOTO(res, err);
5105
5106                   res = e_comp_wl->wl.glapi->evasglQueryWaylandBuffer(e_comp_wl->wl.gl,
5107                                                                       resource,
5108                                                                       EVAS_GL_HEIGHT,
5109                                                                       &buffer->h);
5110                   EINA_SAFETY_ON_FALSE_GOTO(res, err);
5111                }
5112              else
5113                {
5114                   tbm_surf = wayland_tbm_server_get_surface(e_comp_wl->tbm.server, resource);
5115                   if (!tbm_surf)
5116                     goto err;
5117
5118                   buffer->type = E_COMP_WL_BUFFER_TYPE_NATIVE;
5119                   buffer->w = tbm_surface_get_width(tbm_surf);
5120                   buffer->h = tbm_surface_get_height(tbm_surf);
5121                   buffer->tbm_surface = tbm_surf;
5122                }
5123           }
5124           buffer->shm_buffer = shmbuff;
5125        }
5126      else
5127        {
5128           tbm_surf = wayland_tbm_server_get_surface(e_comp_wl->tbm.server, resource);
5129
5130           if (shmbuff)
5131             {
5132                buffer->type = E_COMP_WL_BUFFER_TYPE_SHM;
5133
5134                buffer->w = wl_shm_buffer_get_width(shmbuff);
5135                buffer->h = wl_shm_buffer_get_height(shmbuff);
5136             }
5137           else if (tbm_surf)
5138             {
5139                tbm_surf = wayland_tbm_server_get_surface(e_comp_wl->tbm.server, resource);
5140                if (!tbm_surf)
5141                  goto err;
5142
5143                if ((ec) && (ec->comp_data->video_client))
5144                  {
5145                     buffer->type = E_COMP_WL_BUFFER_TYPE_VIDEO;
5146                     buffer->w = buffer->h = 1;
5147                  }
5148                else
5149                  {
5150                     buffer->type = E_COMP_WL_BUFFER_TYPE_TBM;
5151                     buffer->w = tbm_surface_get_width(tbm_surf);
5152                     buffer->h = tbm_surface_get_height(tbm_surf);
5153                  }
5154             }
5155           else if (e_comp->gl)
5156             {
5157                 buffer->type = E_COMP_WL_BUFFER_TYPE_NATIVE;
5158
5159                 res = e_comp_wl->wl.glapi->evasglQueryWaylandBuffer(e_comp_wl->wl.gl,
5160                                                                     resource,
5161                                                                     EVAS_GL_WIDTH,
5162                                                                     &buffer->w);
5163                 EINA_SAFETY_ON_FALSE_GOTO(res, err);
5164
5165                 res = e_comp_wl->wl.glapi->evasglQueryWaylandBuffer(e_comp_wl->wl.gl,
5166                                                                     resource,
5167                                                                     EVAS_GL_HEIGHT,
5168                                                                     &buffer->h);
5169                 EINA_SAFETY_ON_FALSE_GOTO(res, err);
5170             }
5171           else
5172             {
5173                 goto err;
5174             }
5175
5176           buffer->shm_buffer = shmbuff;
5177           buffer->tbm_surface = tbm_surf;
5178        }
5179
5180    buffer->resource = resource;
5181    wl_signal_init(&buffer->destroy_signal);
5182    buffer->destroy_listener.notify = _e_comp_wl_buffer_cb_destroy;
5183    wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
5184
5185    if (ec)
5186      {
5187         buffer->debug_info.owner_ptr = (void *)ec;
5188         buffer->debug_info.owner_name = eina_stringshare_add(ec->icccm.name?:"");
5189      }
5190
5191    DBG("Wl Buffer Create: b %p owner '%s'(%p)",
5192        buffer, buffer->debug_info.owner_name, buffer->debug_info.owner_ptr);
5193
5194    return buffer;
5195
5196 err:
5197    ERR("Invalid resource:%u", wl_resource_get_id(resource));
5198    E_FREE(buffer);
5199    return NULL;
5200 }
5201
5202 static E_Comp_Wl_Output *
5203 _e_comp_wl_output_get(Eina_List *outputs, const char *id)
5204 {
5205    Eina_List *l;
5206    E_Comp_Wl_Output *output;
5207
5208    EINA_LIST_FOREACH(outputs, l, output)
5209      {
5210        if (!strcmp(output->id, id))
5211          return output;
5212      }
5213
5214    return NULL;
5215 }
5216
5217 /**
5218  * Initializes information about one display output.
5219  *
5220  * Adds or updates the given data about a single display output,
5221  * with an id matching the provided id.
5222  *
5223  * @param id         identification of output to be added or changed
5224  * @param make       manufacturer name of the display output
5225  * @param model      model name of the display output
5226  * @param x          output's top left corner x coordinate
5227  * @param y          output's top left corner y coordinate
5228  * @param w          output's width in pixels
5229  * @param h          output's height in pixels
5230  * @param pw         output's physical width in millimeters
5231  * @param ph         output's physical height in millimeters
5232  * @param refresh    output's refresh rate in mHz
5233  * @param subpixel   output's subpixel layout
5234  * @param transform  output's rotation and/or mirror transformation
5235  *
5236  * @returns True if a display output object could be added or updated
5237  */
5238 E_API Eina_Bool
5239 e_comp_wl_output_init(const char *id, const char *make, const char *model,
5240                       int x, int y, int w, int h, int pw, int ph,
5241                       unsigned int refresh, unsigned int subpixel,
5242                       unsigned int transform)
5243 {
5244    E_Comp_Wl_Output *output;
5245    Eina_List *l2;
5246    struct wl_resource *resource;
5247
5248    /* retrieve named output; or create it if it doesn't exist */
5249    output = _e_comp_wl_output_get(e_comp_wl->outputs, id);
5250    if (!output)
5251      {
5252         if (!(output = E_NEW(E_Comp_Wl_Output, 1))) return EINA_FALSE;
5253
5254         if (id) output->id = eina_stringshare_add(id);
5255         if (make)
5256           output->make = eina_stringshare_add(make);
5257         else
5258           output->make = eina_stringshare_add("unknown");
5259         if (model)
5260           output->model = eina_stringshare_add(model);
5261         else
5262           output->model = eina_stringshare_add("unknown");
5263
5264         e_comp_wl->outputs = eina_list_append(e_comp_wl->outputs, output);
5265
5266         output->global = 
5267           wl_global_create(e_comp_wl->wl.disp, &wl_output_interface,
5268                            2, output, _e_comp_wl_cb_output_bind);
5269
5270         output->resources = NULL;
5271         output->scale = e_scale;
5272      }
5273
5274    /* update the output details */
5275    output->x = x;
5276    output->y = y;
5277    output->w = w;
5278    output->h = h;
5279    output->phys_width = pw;
5280    output->phys_height = ph;
5281    output->refresh = refresh;
5282    output->subpixel = subpixel;
5283    output->transform = transform;
5284
5285    if (output->scale <= 0)
5286      output->scale = e_scale;
5287
5288    /* if we have bound resources, send updates */
5289    EINA_LIST_FOREACH(output->resources, l2, resource)
5290      {
5291         wl_output_send_geometry(resource,
5292                                 output->x, output->y,
5293                                 output->phys_width,
5294                                 output->phys_height,
5295                                 output->subpixel,
5296                                 output->make ?: "", output->model ?: "",
5297                                 output->transform);
5298
5299         if (wl_resource_get_version(resource) >= WL_OUTPUT_SCALE_SINCE_VERSION)
5300           wl_output_send_scale(resource, output->scale);
5301
5302         /* 3 == preferred + current */
5303         wl_output_send_mode(resource, 3, output->w, output->h, output->refresh);
5304
5305         if (wl_resource_get_version(resource) >= WL_OUTPUT_DONE_SINCE_VERSION)
5306           wl_output_send_done(resource);
5307      }
5308
5309    return EINA_TRUE;
5310 }
5311
5312 E_API void
5313 e_comp_wl_output_remove(const char *id)
5314 {
5315    E_Comp_Wl_Output *output;
5316
5317    output = _e_comp_wl_output_get(e_comp_wl->outputs, id);
5318    if (output)
5319      {
5320         e_comp_wl->outputs = eina_list_remove(e_comp_wl->outputs, output);
5321
5322         /* wl_global_destroy(output->global); */
5323
5324         /* eina_stringshare_del(output->id); */
5325         /* eina_stringshare_del(output->make); */
5326         /* eina_stringshare_del(output->model); */
5327
5328         /* free(output); */
5329      }
5330 }
5331
5332 static void
5333 _e_comp_wl_key_send(Ecore_Event_Key *ev, enum wl_keyboard_key_state state, Eina_List *key_list, E_Client *ec)
5334 {
5335    struct wl_resource *res;
5336    Eina_List *l;
5337    uint32_t serial, keycode;
5338    struct wl_client *wc = NULL;
5339    E_Comp_Config *comp_conf = NULL;
5340
5341    keycode = (ev->keycode - 8);
5342
5343    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5344
5345    comp_conf = e_comp_config_get();
5346
5347    if (ec && ec->comp_data && ec->comp_data->surface)
5348      wc = wl_resource_get_client(ec->comp_data->surface);
5349
5350    EINA_LIST_FOREACH(key_list, l, res)
5351      {
5352         if (wl_resource_get_client(res) != wc) continue;
5353
5354         TRACE_INPUT_BEGIN(_e_comp_wl_key_send);
5355         _e_comp_wl_send_event_device(ev->data, ev->timestamp, ev->dev, serial);
5356
5357         if (comp_conf && comp_conf->input_log_enable)
5358           INF("[Server] Key %s (time: %d)\n", (state ? "Down" : "Up"), ev->timestamp);
5359
5360         wl_keyboard_send_key(res, serial, ev->timestamp,
5361                              keycode, state);
5362         TRACE_INPUT_END();
5363      }
5364 }
5365
5366 EINTERN Eina_Bool
5367 e_comp_wl_key_down(Ecore_Event_Key *ev)
5368 {
5369    E_Client *ec = NULL;
5370    uint32_t keycode;
5371    E_Comp_Wl_Key_Data *end, *k;
5372
5373    if ((e_comp->comp_type != E_PIXMAP_TYPE_WL) || (ev->window != e_comp->ee_win))
5374      {
5375         return EINA_FALSE;
5376      }
5377
5378    keycode = (ev->keycode - 8);
5379    if (!(e_comp_wl = e_comp->wl_comp_data))
5380      {
5381         return EINA_FALSE;
5382      }
5383
5384 #ifndef E_RELEASE_BUILD
5385    if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
5386        ((ev->modifiers & ECORE_EVENT_MODIFIER_ALT) ||
5387        (ev->modifiers & ECORE_EVENT_MODIFIER_ALTGR)) &&
5388        eina_streq(ev->key, "BackSpace"))
5389      {
5390         exit(0);
5391      }
5392 #endif
5393
5394    end = (E_Comp_Wl_Key_Data *)e_comp_wl->kbd.keys.data + (e_comp_wl->kbd.keys.size / sizeof(*k));
5395
5396    for (k = e_comp_wl->kbd.keys.data; k < end; k++)
5397      {
5398         /* ignore server-generated key repeats */
5399         if (k->key == keycode)
5400           {
5401              return EINA_FALSE;
5402           }
5403      }
5404
5405    if ((!e_client_action_get()) && (!e_comp->input_key_grabs))
5406      {
5407         ec = e_client_focused_get();
5408         if (ec && ec->comp_data && ec->comp_data->surface && e_comp_wl->kbd.focused)
5409           {
5410              _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_PRESSED, e_comp_wl->kbd.focused, ec);
5411
5412              /* A key only sent to clients is added to the list */
5413              e_comp_wl->kbd.keys.size = (const char *)end - (const char *)e_comp_wl->kbd.keys.data;
5414              if (!(k = wl_array_add(&e_comp_wl->kbd.keys, sizeof(*k))))
5415                {
5416                   DBG("wl_array_add: Out of memory\n");
5417                   return EINA_FALSE;
5418                }
5419              k->key = keycode;
5420              k->dev = ev->dev;
5421           }
5422      }
5423
5424    /* update modifier state */
5425    e_comp_wl_input_keyboard_state_update(keycode, EINA_TRUE);
5426
5427    return !!ec;
5428 }
5429
5430 EINTERN Eina_Bool
5431 e_comp_wl_key_up(Ecore_Event_Key *ev)
5432 {
5433    E_Client *ec = NULL;
5434    uint32_t keycode, delivered_key;
5435    E_Comp_Wl_Key_Data *end, *k;
5436
5437    if ((e_comp->comp_type != E_PIXMAP_TYPE_WL) ||
5438        (ev->window != e_comp->ee_win))
5439      {
5440         return EINA_FALSE;
5441      }
5442
5443    keycode = (ev->keycode - 8);
5444    delivered_key = 0;
5445    if (!(e_comp_wl = e_comp->wl_comp_data))
5446      {
5447         return EINA_FALSE;
5448      }
5449
5450    end = (E_Comp_Wl_Key_Data *)e_comp_wl->kbd.keys.data + (e_comp_wl->kbd.keys.size / sizeof(*k));
5451    for (k = e_comp_wl->kbd.keys.data; k < end; k++)
5452      {
5453         if (k->key == keycode)
5454           {
5455              *k = *--end;
5456              delivered_key = 1;
5457           }
5458      }
5459
5460    e_comp_wl->kbd.keys.size =
5461      (const char *)end - (const char *)e_comp_wl->kbd.keys.data;
5462
5463    /* If a key down event have been sent to clients, send a key up event to client for garantee key event sequence pair. (down/up) */
5464    if ((delivered_key) ||
5465        ((!e_client_action_get()) && (!e_comp->input_key_grabs)))
5466      {
5467         ec = e_client_focused_get();
5468
5469         if (e_comp_wl->kbd.focused)
5470           {
5471              _e_comp_wl_key_send(ev, WL_KEYBOARD_KEY_STATE_RELEASED, e_comp_wl->kbd.focused, ec);
5472           }
5473      }
5474
5475    /* update modifier state */
5476    e_comp_wl_input_keyboard_state_update(keycode, EINA_FALSE);
5477
5478    return !!ec;
5479 }
5480
5481 E_API Eina_Bool
5482 e_comp_wl_key_process(Ecore_Event_Key *ev, int type)
5483 {
5484    Eina_Bool res = EINA_FALSE;
5485
5486    if (type == ECORE_EVENT_KEY_DOWN)
5487      {
5488         res = e_comp_wl_key_down(ev);
5489      }
5490    else if (type == ECORE_EVENT_KEY_UP)
5491      {
5492         res = e_comp_wl_key_up(ev);
5493      }
5494
5495    return res;
5496 }
5497
5498 E_API Eina_Bool
5499 e_comp_wl_evas_handle_mouse_button(E_Client *ec, uint32_t timestamp, uint32_t button_id, uint32_t state)
5500 {
5501    Eina_List *l;
5502    struct wl_client *wc;
5503    uint32_t serial, btn;
5504    struct wl_resource *res;
5505    E_Comp_Config *comp_conf = NULL;
5506
5507    if (ec->cur_mouse_action || e_comp_wl->drag)
5508      return EINA_FALSE;
5509    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
5510    if ((ec->ignored) && (!ec->remote_surface.provider)) return EINA_FALSE;
5511
5512    switch (button_id)
5513      {
5514       case 1:  btn = BTN_LEFT;   break;
5515       case 2:  btn = BTN_MIDDLE; break;
5516       case 3:  btn = BTN_RIGHT;  break;
5517       default: btn = button_id;  break;
5518      }
5519
5520    e_comp_wl->ptr.button = btn;
5521
5522    if (!ec->comp_data || !ec->comp_data->surface) return EINA_FALSE;
5523
5524    if (!eina_list_count(e_comp_wl->ptr.resources))
5525      return EINA_TRUE;
5526
5527    wc = wl_resource_get_client(ec->comp_data->surface);
5528    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5529
5530    comp_conf = e_comp_config_get();
5531
5532    EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
5533      {
5534         if (wl_resource_get_client(res) != wc) continue;
5535         if (!e_comp_wl_input_pointer_check(res)) continue;
5536         TRACE_INPUT_BEGIN(e_comp_wl_evas_handle_mouse_button);
5537
5538         if (comp_conf && comp_conf->input_log_enable)
5539           INF("[Server] Mouse Button %s (btn: %d, time: %d)\n", (state ? "Down" : "Up"), btn, timestamp);
5540
5541         wl_pointer_send_button(res, serial, timestamp, btn, state);
5542         TRACE_INPUT_END();
5543      }
5544    return EINA_TRUE;
5545 }
5546
5547 E_API void
5548 e_comp_wl_touch_cancel(void)
5549 {
5550    _e_comp_wl_touch_cancel();
5551 }
5552
5553 E_API E_Comp_Wl_Hook *
5554 e_comp_wl_hook_add(E_Comp_Wl_Hook_Point hookpoint, E_Comp_Wl_Hook_Cb func, const void *data)
5555 {
5556    E_Comp_Wl_Hook *ch;
5557
5558    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_COMP_WL_HOOK_LAST, NULL);
5559    ch = E_NEW(E_Comp_Wl_Hook, 1);
5560    if (!ch) return NULL;
5561    ch->hookpoint = hookpoint;
5562    ch->func = func;
5563    ch->data = (void*)data;
5564    _e_comp_wl_hooks[hookpoint] = eina_inlist_append(_e_comp_wl_hooks[hookpoint], EINA_INLIST_GET(ch));
5565    return ch;
5566 }
5567
5568 E_API void
5569 e_comp_wl_hook_del(E_Comp_Wl_Hook *ch)
5570 {
5571    ch->delete_me = 1;
5572    if (_e_comp_wl_hooks_walking == 0)
5573      {
5574         _e_comp_wl_hooks[ch->hookpoint] = eina_inlist_remove(_e_comp_wl_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
5575         free(ch);
5576      }
5577    else
5578      _e_comp_wl_hooks_delete++;
5579 }
5580
5581 E_API void
5582 e_comp_wl_shell_surface_ready(E_Client *ec)
5583 {
5584    if (!ec) return;
5585
5586    _e_comp_wl_hook_call(E_COMP_WL_HOOK_SHELL_SURFACE_READY, ec);
5587 }
5588
5589 E_API void
5590 e_comp_wl_input_cursor_timer_enable_set(Eina_Bool enabled)
5591 {
5592    e_config->use_cursor_timer = !!enabled;
5593
5594    if (e_config->use_cursor_timer == EINA_FALSE)
5595      {
5596         if (e_comp_wl->ptr.hide_tmr)
5597           {
5598              ecore_timer_del(e_comp_wl->ptr.hide_tmr);
5599              e_comp_wl->ptr.hide_tmr = NULL;
5600           }
5601         cursor_timer_ec = NULL;
5602
5603         if (e_pointer_is_hidden(e_comp->pointer))
5604           {
5605              _e_comp_wl_cursor_reload(e_comp_wl->ptr.ec);
5606           }
5607      }
5608 }
5609
5610 EINTERN Eina_Bool
5611 e_comp_wl_key_send(E_Client *ec, int keycode, Eina_Bool pressed, Ecore_Device *dev, uint32_t time)
5612 {
5613    struct wl_resource *res;
5614    struct wl_client *wc;
5615    Eina_List *l;
5616    uint32_t serial, wl_keycode;
5617    enum wl_keyboard_key_state state;
5618    E_Comp_Config *comp_conf = NULL;
5619
5620    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5621    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5622    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5623    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5624
5625    wl_keycode = keycode - 8;
5626    EINA_SAFETY_ON_TRUE_RETURN_VAL(wl_keycode <= 0, EINA_FALSE);
5627
5628    wc = wl_resource_get_client(ec->comp_data->surface);
5629    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5630    if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5631    if (pressed) state = WL_KEYBOARD_KEY_STATE_PRESSED;
5632    else state = WL_KEYBOARD_KEY_STATE_RELEASED;
5633
5634    comp_conf = e_comp_config_get();
5635
5636    EINA_LIST_FOREACH(e_comp_wl->kbd.resources, l, res)
5637      {
5638         if (wl_resource_get_client(res) != wc) continue;
5639         if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5640         else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_KEYBOARD, time);
5641
5642         if (comp_conf && comp_conf->input_log_enable)
5643           INF("[Server] Key %s (time: %d)\n", (state ? "Down" : "Up"), time);
5644
5645         wl_keyboard_send_key(res, serial, time,
5646                              wl_keycode, state);
5647      }
5648
5649    return EINA_TRUE;
5650 }
5651
5652 EINTERN Eina_Bool
5653 e_comp_wl_touch_send(E_Client *ec, int idx, int x, int y, Eina_Bool pressed, Ecore_Device *dev, double radius_x, double radius_y, double pressure, double angle, uint32_t time)
5654 {
5655    struct wl_client *wc;
5656    uint32_t serial;
5657    E_Comp_Wl_Input_Device *device = NULL;
5658
5659    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5660    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5661    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5662    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5663
5664    if (!dev) device = _e_comp_wl_device_last_device_get(ECORE_DEVICE_CLASS_TOUCH);
5665
5666    wc = wl_resource_get_client(ec->comp_data->surface);
5667    if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5668    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5669
5670    if (dev)
5671      {
5672         _e_comp_wl_send_event_device(wc, time, dev, serial);
5673         _e_comp_wl_device_handle_axes(ecore_device_identifier_get(dev), ECORE_DEVICE_CLASS_TOUCH, ec, idx, radius_x, radius_y, pressure, angle);
5674      }
5675    else if (device)
5676      {
5677         _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_TOUCH, time);
5678         _e_comp_wl_device_handle_axes(device->identifier, device->clas, ec, idx, radius_x, radius_y, pressure, angle);
5679      }
5680
5681    x = x + ec->client.x;
5682    y = y + ec->client.y;
5683
5684    _e_comp_wl_send_touch(ec, idx, x, y, time, pressed);
5685
5686    return EINA_TRUE;
5687 }
5688
5689 EINTERN Eina_Bool
5690 e_comp_wl_touch_update_send(E_Client *ec, int idx, int x, int y, Ecore_Device *dev, double radius_x, double radius_y, double pressure, double angle, uint32_t time)
5691 {
5692    E_Comp_Wl_Input_Device *device;
5693    uint32_t serial;
5694    struct wl_client *wc;
5695
5696    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5697    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5698    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5699    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5700
5701    if (!dev) device = _e_comp_wl_device_last_device_get(ECORE_DEVICE_CLASS_TOUCH);
5702
5703    wc = wl_resource_get_client(ec->comp_data->surface);
5704    if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5705    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5706
5707    if (dev)
5708      {
5709         _e_comp_wl_send_event_device(wc, time, dev, serial);
5710         _e_comp_wl_device_handle_axes(ecore_device_identifier_get(dev), ECORE_DEVICE_CLASS_TOUCH, ec, idx, radius_x, radius_y, pressure, angle);
5711      }
5712    else if (device)
5713      {
5714         _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_TOUCH, time);
5715         _e_comp_wl_device_handle_axes(device->identifier, device->clas, ec, idx, radius_x, radius_y, pressure, angle);
5716      }
5717
5718    x = x + ec->client.x;
5719    y = y + ec->client.y;
5720
5721    _e_comp_wl_send_touch_move(ec, idx, x, y, time);
5722
5723    return EINA_TRUE;
5724 }
5725
5726 EINTERN Eina_Bool
5727 e_comp_wl_touch_cancel_send(E_Client *ec)
5728 {
5729    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5730    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5731    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5732
5733    _e_comp_wl_send_touch_cancel(ec);
5734
5735    return EINA_TRUE;
5736 }
5737
5738 EINTERN Eina_Bool
5739 e_comp_wl_mouse_button_send(E_Client *ec, int buttons, Eina_Bool pressed, Ecore_Device *dev, uint32_t time)
5740 {
5741    uint32_t serial;
5742    struct wl_client *wc;
5743
5744    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5745    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5746    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5747    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5748
5749    wc = wl_resource_get_client(ec->comp_data->surface);
5750    if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5751    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5752
5753    if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5754    else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, time);
5755
5756    if (pressed)
5757      e_comp_wl_evas_handle_mouse_button(ec, time, buttons,
5758                                           WL_POINTER_BUTTON_STATE_PRESSED);
5759    else
5760      e_comp_wl_evas_handle_mouse_button(ec, time, buttons,
5761                                           WL_POINTER_BUTTON_STATE_RELEASED);
5762
5763    return EINA_TRUE;
5764 }
5765
5766 EINTERN Eina_Bool
5767 e_comp_wl_mouse_move_send(E_Client *ec, int x, int y, Ecore_Device *dev, uint32_t time)
5768 {
5769    uint32_t serial;
5770    struct wl_client *wc;
5771
5772    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5773    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5774    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5775    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5776
5777    wc = wl_resource_get_client(ec->comp_data->surface);
5778    if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5779    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5780
5781    if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5782    else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, time);
5783
5784    x = x + ec->client.x;
5785    y = y + ec->client.y;
5786
5787    _e_comp_wl_send_mouse_move(ec, x, y, time);
5788
5789    return EINA_TRUE;
5790 }
5791
5792 EINTERN Eina_Bool
5793 e_comp_wl_mouse_wheel_send(E_Client *ec, int direction, int z, Ecore_Device *dev, uint32_t time)
5794 {
5795    uint32_t serial;
5796    struct wl_client *wc;
5797
5798    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5799    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5800    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5801    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5802
5803    wc = wl_resource_get_client(ec->comp_data->surface);
5804    if (!time) time = (uint32_t)(ecore_time_get() * 1000);
5805    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5806
5807    if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5808    else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, time);
5809
5810    _e_comp_wl_mouse_wheel_send(ec, direction, z, time);
5811
5812    return EINA_TRUE;
5813 }
5814
5815 EINTERN Eina_Bool
5816 e_comp_wl_mouse_in_send(E_Client *ec, int x, int y, Ecore_Device *dev, uint32_t time)
5817 {
5818    uint32_t serial;
5819    struct wl_client *wc;
5820    struct wl_resource *res;
5821    Eina_List *l;
5822
5823    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5824    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5825    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5826    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5827    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
5828
5829    if (!eina_list_count(e_comp_wl->ptr.resources)) return EINA_FALSE;
5830    wc = wl_resource_get_client(ec->comp_data->surface);
5831    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5832    EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
5833      {
5834         if (!e_comp_wl_input_pointer_check(res)) continue;
5835         if (wl_resource_get_client(res) != wc) continue;
5836
5837         if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5838         else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, time);
5839
5840         wl_pointer_send_enter(res, serial, ec->comp_data->surface,
5841                               wl_fixed_from_int(x),
5842                               wl_fixed_from_int(y));
5843      }
5844
5845    return EINA_TRUE;
5846 }
5847
5848 EINTERN Eina_Bool
5849 e_comp_wl_mouse_out_send(E_Client *ec, Ecore_Device *dev, uint32_t time)
5850 {
5851    uint32_t serial;
5852    struct wl_client *wc;
5853    struct wl_resource *res;
5854    Eina_List *l;
5855
5856    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
5857    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5858    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
5859    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data->surface, EINA_FALSE);
5860    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
5861
5862    if (!eina_list_count(e_comp_wl->ptr.resources)) return EINA_FALSE;
5863    wc = wl_resource_get_client(ec->comp_data->surface);
5864    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5865    EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
5866      {
5867         if (!e_comp_wl_input_pointer_check(res)) continue;
5868         if (wl_resource_get_client(res) != wc) continue;
5869
5870         if (dev) _e_comp_wl_send_event_device(wc, time, dev, serial);
5871         else _e_comp_wl_device_send_last_event_device(ec, ECORE_DEVICE_CLASS_MOUSE, time);
5872
5873         wl_pointer_send_leave(res, serial, ec->comp_data->surface);
5874      }
5875
5876    return EINA_TRUE;
5877 }
5878
5879 EINTERN void
5880 e_comp_wl_mouse_in_renew(E_Client *ec, int buttons, int x, int y, void *data, Evas_Modifier *modifiers, Evas_Lock *locks, unsigned int timestamp, Evas_Event_Flags event_flags, Evas_Device *dev, Evas_Object *event_src)
5881 {
5882    Evas_Event_Mouse_In ev_in;
5883
5884    if (!ec) return;
5885    if (ec->pointer_enter_sent) return;
5886
5887    ev_in.buttons = buttons;
5888
5889    ev_in.output.x = x;
5890    ev_in.output.y = y;
5891    ev_in.canvas.x = x;
5892    ev_in.canvas.y = y;
5893
5894    ev_in.data = data;
5895    ev_in.modifiers = modifiers;
5896    ev_in.locks = locks;
5897    ev_in.timestamp = timestamp;
5898    ev_in.event_flags = event_flags;
5899
5900    ev_in.dev = dev;
5901    ev_in.event_src = event_src;
5902
5903    _e_comp_wl_evas_cb_mouse_in((void *)ec, NULL, NULL, &ev_in);
5904 }
5905
5906 EINTERN void
5907 e_comp_wl_mouse_out_renew(E_Client *ec, int buttons, int x, int y, void *data, Evas_Modifier *modifiers, Evas_Lock *locks, unsigned int timestamp, Evas_Event_Flags event_flags, Evas_Device *dev, Evas_Object *event_src)
5908 {
5909    Evas_Event_Mouse_Out ev_out;
5910
5911    if (!ec) return;
5912    if (!ec->pointer_enter_sent) return;
5913
5914    ev_out.buttons = buttons;
5915
5916    ev_out.output.x = x;
5917    ev_out.output.y = y;
5918    ev_out.canvas.x = x;
5919    ev_out.canvas.y = y;
5920
5921    ev_out.data = data;
5922    ev_out.modifiers = modifiers;
5923    ev_out.locks = locks;
5924    ev_out.timestamp = timestamp;
5925    ev_out.event_flags = event_flags;
5926
5927    ev_out.dev = dev;
5928    ev_out.event_src = event_src;
5929
5930    _e_comp_wl_evas_cb_mouse_out((void *)ec, NULL, NULL, &ev_out);
5931 }
5932
5933 EINTERN Eina_Bool
5934 e_comp_wl_cursor_hide(E_Client *ec)
5935 {
5936    struct wl_resource *res;
5937    struct wl_client *wc;
5938    Eina_List *l;
5939    uint32_t serial;
5940
5941    e_pointer_object_set(e_comp->pointer, NULL, 0, 0);
5942
5943    if (e_comp_wl->ptr.hide_tmr)
5944      {
5945         ecore_timer_del(e_comp_wl->ptr.hide_tmr);
5946         e_comp_wl->ptr.hide_tmr = NULL;
5947      }
5948    cursor_timer_ec = NULL;
5949
5950    if (!ec) return EINA_FALSE;
5951    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
5952
5953    if (!ec->comp_data || !ec->comp_data->surface) return EINA_FALSE;
5954    wc = wl_resource_get_client(ec->comp_data->surface);
5955    serial = wl_display_next_serial(e_comp_wl->wl.disp);
5956    EINA_LIST_FOREACH(e_comp_wl->ptr.resources, l, res)
5957      {
5958         if (!e_comp_wl_input_pointer_check(res)) continue;
5959         if (wl_resource_get_client(res) != wc) continue;
5960         if (ec->pointer_enter_sent == EINA_FALSE) continue;
5961         wl_pointer_send_leave(res, serial, ec->comp_data->surface);
5962         ec->pointer_enter_sent = EINA_FALSE;
5963      }
5964
5965    return EINA_TRUE;
5966 }
5967
5968 /* surface to buffer
5969  *   - width    : surface width
5970  *   - height   : surface height
5971  *   - transform: buffer transform
5972  *   - scale    : buffer scale
5973  * screen to output
5974  *   - width    : screen width
5975  *   - height   : screen height
5976  *   - transform: output transform
5977  *   - scale    : output scale
5978  */
5979 static E_Util_Transform_Matrix
5980 _e_comp_wl_buffer_coord_get(int width, int height, int transform, int scale)
5981 {
5982    E_Util_Transform_Matrix m;
5983
5984    e_util_transform_matrix_load_identity(&m);
5985
5986    if (transform & 0x4)
5987      {
5988         e_util_transform_matrix_translate(&m, -((double)width / 2), 0, 0);
5989         e_util_transform_matrix_flip_x(&m);
5990         e_util_transform_matrix_translate(&m, (double)width / 2, 0, 0);
5991      }
5992
5993    switch (transform & 0x3)
5994      {
5995       case WL_OUTPUT_TRANSFORM_90:
5996         e_util_transform_matrix_translate(&m, -width, 0, 0);
5997         e_util_transform_matrix_rotation_z(&m, 270);
5998         break;
5999       case WL_OUTPUT_TRANSFORM_180:
6000         e_util_transform_matrix_translate(&m, -width, -height, 0);
6001         e_util_transform_matrix_rotation_z(&m, 180);
6002         break;
6003       case WL_OUTPUT_TRANSFORM_270:
6004         e_util_transform_matrix_translate(&m, 0, -height, 0);
6005         e_util_transform_matrix_rotation_z(&m, 90);
6006         break;
6007       default:
6008         break;
6009      }
6010
6011    e_util_transform_matrix_scale(&m, scale, scale, 1);
6012
6013    return m;
6014 }
6015
6016 /* surface to buffer
6017  *   - surface width, surface height, buffer transform, buffer scale
6018  * screen to output
6019  *   - screen width, screen height, output transform, output scale
6020  */
6021 E_API void
6022 e_comp_wl_pos_convert(int width, int height, int transform, int scale, int sx, int sy, int *bx, int *by)
6023 {
6024    E_Util_Transform_Matrix m;
6025    E_Util_Transform_Vertex v;
6026
6027    m = _e_comp_wl_buffer_coord_get(width, height, transform, scale);
6028
6029    e_util_transform_vertex_init(&v, sx, sy, 0.0, 1.0);
6030    v = e_util_transform_matrix_multiply_vertex(&m, &v);
6031    e_util_transform_vertex_pos_round_get(&v, bx, by, NULL, NULL);
6032 }
6033
6034 /* buffer to screen
6035  *   - buffer width, buffer height, buffer transform, buffer scale
6036  */
6037 E_API void
6038 e_comp_wl_pos_convert_inverse(int width, int height, int transform, int scale, int bx, int by, int *sx, int *sy)
6039 {
6040    E_Util_Transform_Matrix m;
6041    E_Util_Transform_Vertex v;
6042    int tw, th;
6043
6044    if (transform != 0 || scale > 1)
6045      {
6046         tw = ((transform % 2) ? height : width) / scale;
6047         th = ((transform % 2) ? width : height) / scale;
6048      }
6049    else
6050      {
6051         tw = width;
6052         th = height;
6053      }
6054
6055    m = _e_comp_wl_buffer_coord_get(tw, th, transform, scale);
6056    m = e_util_transform_matrix_inverse_get(&m);
6057
6058    e_util_transform_vertex_init(&v, bx, by, 0.0, 1.0);
6059    v = e_util_transform_matrix_multiply_vertex(&m, &v);
6060    e_util_transform_vertex_pos_round_get(&v, sx, sy, NULL, NULL);
6061 }
6062
6063 /* surface to buffer
6064  *   - surface width, surface height, buffer transform, buffer scale
6065  * screen to output
6066  *   - screen width, screen height, output transform, output scale
6067  */
6068 E_API void
6069 e_comp_wl_rect_convert(int width, int height, int transform, int scale,
6070                        int sx, int sy, int sw, int sh, int *bx, int *by, int *bw, int *bh)
6071 {
6072    E_Util_Transform_Matrix m;
6073    E_Util_Transform_Rect sr = {sx, sy, sw, sh};
6074    E_Util_Transform_Rect_Vertex sv;
6075
6076    m = _e_comp_wl_buffer_coord_get(width, height, transform, scale);
6077
6078    sv = e_util_transform_rect_to_vertices(&sr);
6079    sv = e_util_transform_matrix_multiply_rect_vertex(&m, &sv);
6080    sr = e_util_transform_vertices_to_rect(&sv);
6081
6082    if (bx) *bx = sr.x;
6083    if (by) *by = sr.y;
6084    if (bw) *bw = sr.w;
6085    if (bh) *bh = sr.h;
6086 }
6087
6088 /* buffer to screen
6089  *   - buffer width, buffer height, buffer transform, buffer scale
6090  */
6091 E_API void
6092 e_comp_wl_rect_convert_inverse(int width, int height, int transform, int scale,
6093                                int bx, int by, int bw, int bh, int *sx, int *sy, int *sw, int *sh)
6094 {
6095    E_Util_Transform_Matrix m;
6096    E_Util_Transform_Rect br = {bx, by, bw, bh};
6097    E_Util_Transform_Rect_Vertex bv;
6098    int tw, th;
6099
6100    if (transform != 0 || scale > 1)
6101      {
6102         tw = ((transform % 2) ? height : width) / scale;
6103         th = ((transform % 2) ? width : height) / scale;
6104      }
6105    else
6106      {
6107         tw = width;
6108         th = height;
6109      }
6110
6111    m = _e_comp_wl_buffer_coord_get(tw, th, transform, scale);
6112    m = e_util_transform_matrix_inverse_get(&m);
6113
6114    bv = e_util_transform_rect_to_vertices(&br);
6115    bv = e_util_transform_matrix_multiply_rect_vertex(&m, &bv);
6116    br = e_util_transform_vertices_to_rect(&bv);
6117
6118    if (sx) *sx = br.x;
6119    if (sy) *sy = br.y;
6120    if (sw) *sw = br.w;
6121    if (sh) *sh = br.h;
6122 }
6123
6124 E_API E_Comp_Wl_Output*
6125 e_comp_wl_output_find(E_Client *ec)
6126 {
6127    Eina_List *l;
6128    E_Comp_Wl_Output *output;
6129
6130    if (!ec || !ec->comp_data || e_object_is_del(E_OBJECT(ec))) return NULL;
6131
6132    EINA_LIST_FOREACH(e_comp_wl->outputs, l, output)
6133      {
6134         if (ec->x < output->x || ec->x >= (output->x + output->w) ||
6135             ec->y < output->y || ec->y >= (output->y + output->h))
6136           continue;
6137
6138         return output;
6139      }
6140
6141    return NULL;
6142 }