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