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