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