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