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