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