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