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