e739f2962a2fe224654c5b648f280c8a039c36cc
[platform/upstream/enlightenment.git] / src / bin / e_client.c
1 #include "e_client_intern.h"
2 #include "e_actions_intern.h"
3 #include "e_appinfo_intern.h"
4 #include "e_bindings_intern.h"
5 #include "e_uuid_store_intern.h"
6 #include "e_utils_intern.h"
7 #include "e_comp_canvas_intern.h"
8 #include "e_comp_wl_intern.h"
9 #include "e_comp_wl_subsurface_intern.h"
10 #include "e_comp_intern.h"
11 #include "e_input_intern.h"
12 #include "e_policy_intern.h"
13 #include "e_map_intern.h"
14 #include "e_policy_visibility_intern.h"
15 #include "e_comp_object_intern.h"
16 #include "e_desk_area_intern.h"
17 #include "e_desk_intern.h"
18 #include "e_zone_intern.h"
19 #include "e_config_intern.h"
20 #include "e_input_thread_client_intern.h"
21
22 #define PRI(ec) ((E_Client_Private *)e_object_data_get(E_OBJECT(ec)))
23
24 #define API_ENTRY \
25    EINA_SAFETY_ON_NULL_RETURN(ec); \
26    E_Client_Private *priv = PRI(ec); \
27    EINA_SAFETY_ON_NULL_RETURN(priv);
28
29 #define API_ENTRY_VAL(ret) \
30    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, ret); \
31    E_Client_Private *priv = PRI(ec); \
32    EINA_SAFETY_ON_NULL_RETURN_VAL(priv, ret);
33
34 typedef struct _E_Client_Private E_Client_Private;
35
36 struct _E_Client_Private
37 {
38    struct
39      {
40         struct wl_signal eval_pre_fetch;
41         struct wl_signal eval_fetch;
42         struct wl_signal eval_pre_post_fetch;
43         struct wl_signal eval_post_fetch;
44         struct wl_signal eval_pre_frame_assign;
45         struct wl_signal eval_post_frame_assign;
46         struct wl_signal eval_pre_new_client;
47         struct wl_signal eval_post_new_client;
48         struct wl_signal eval_visibility;
49         struct wl_signal eval_visibility_end;
50         struct wl_signal eval_end;
51
52         struct wl_signal move_begin;
53         struct wl_signal move_update;
54         struct wl_signal move_end;
55         struct wl_signal move_resize_begin;
56         struct wl_signal move_resize_update;
57         struct wl_signal move_resize_end;
58
59         struct wl_signal destroy;
60         struct wl_signal new_client;
61         struct wl_signal new_client_post;
62
63         struct wl_signal unredirect;
64         struct wl_signal redirect;
65
66         struct wl_signal aux_hint_change;
67         struct wl_signal window_role_change;
68         struct wl_signal transform_change;
69         struct wl_signal activate_done;
70
71         struct wl_signal mouse_in;
72         struct wl_signal mouse_out;
73         struct wl_signal mouse_down;
74
75         struct wl_signal focus_set;
76         struct wl_signal focus_unset;
77         struct wl_signal focus_defer_set;
78         struct wl_signal focus_latest_set;
79
80         struct wl_signal iconify;
81         struct wl_signal uniconify;
82         struct wl_signal maximize;
83         struct wl_signal unmaximize;
84         struct wl_signal fullscreen_pre;
85         struct wl_signal fullscreen;
86         struct wl_signal unfullscreen;
87
88         struct wl_signal move;
89
90         struct wl_signal set_layer;
91         struct wl_signal raise;
92         struct wl_signal lower;
93         struct wl_signal stack_below;
94         struct wl_signal stack_above;
95         struct wl_signal stack_transient_for_done;
96
97         struct wl_signal stick;
98         struct wl_signal unstick;
99
100 #ifdef REFACTOR_DESK_AREA
101         struct wl_signal get_above;
102         struct wl_signal get_below;
103         struct wl_signal get_visible_above;
104         struct wl_signal get_visible_below;
105         struct wl_signal subsurface_stack_update;
106 #endif
107
108         struct wl_signal delete_request;
109         struct wl_signal kill_request;
110         struct wl_signal ping;
111      } events;
112
113    Eina_Bool hide_by_request;
114    Eina_Bool focus_check;
115
116    E_Client *modal;
117 };
118
119 static int _e_client_hooks_delete = 0;
120 static int _e_client_hooks_walking = 0;
121
122 static int _e_client_intercept_hooks_delete = 0;
123 static int _e_client_intercept_hooks_walking = 0;
124
125 E_API int E_EVENT_CLIENT_ADD = -1;
126 E_API int E_EVENT_CLIENT_REMOVE = -1;
127 E_API int E_EVENT_CLIENT_ZONE_SET = -1;
128 E_API int E_EVENT_CLIENT_DESK_SET = -1;
129 E_API int E_EVENT_CLIENT_RESIZE = -1;
130 E_API int E_EVENT_CLIENT_MOVE = -1;
131 E_API int E_EVENT_CLIENT_SHOW = -1;
132 E_API int E_EVENT_CLIENT_HIDE = -1;
133 E_API int E_EVENT_CLIENT_ICONIFY = -1;
134 E_API int E_EVENT_CLIENT_UNICONIFY = -1;
135 E_API int E_EVENT_CLIENT_STACK = -1;
136 E_API int E_EVENT_CLIENT_FOCUS_IN = -1;
137 E_API int E_EVENT_CLIENT_FOCUS_OUT = -1;
138 E_API int E_EVENT_CLIENT_PROPERTY = -1;
139 E_API int E_EVENT_CLIENT_FULLSCREEN = -1;
140 E_API int E_EVENT_CLIENT_UNFULLSCREEN = -1;
141 #ifdef _F_ZONE_WINDOW_ROTATION_
142 E_API int E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN = -1;
143 E_API int E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL = -1;
144 E_API int E_EVENT_CLIENT_ROTATION_CHANGE_END = -1;
145 E_API int E_EVENT_CLIENT_ROTATION_GEOMETRY_SET = -1;
146 #endif
147 E_API int E_EVENT_CLIENT_VISIBILITY_CHANGE = -1;
148 E_API int E_EVENT_CLIENT_BUFFER_CHANGE = -1;
149 E_API int E_EVENT_CLIENT_FOCUS_SKIP_SET = -1;
150 E_API int E_EVENT_CLIENT_FOCUS_SKIP_UNSET = -1;
151
152 static Eina_Hash *clients_hash[E_PIXMAP_TYPE_MAX] = {NULL}; // pixmap->client
153
154 static E_Client *ecmove = NULL;
155 static E_Client *ecresize = NULL;
156 static E_Client *action_client = NULL;
157
158 static Eina_Bool comp_grabbed = EINA_FALSE;
159
160 static Eina_List *handlers = NULL;
161 static Eina_List *hooks = NULL;
162 static Eina_List *comp_hooks = NULL;
163
164 static Ecore_Event_Handler *action_handler_mouse = NULL;
165 static Ecore_Timer *action_timer = NULL;
166 static Eina_Rectangle action_orig = {0, 0, 0, 0};
167
168 static E_Client_Resize_Object_Create_Cb _e_client_resize_object_create_cb = NULL;
169
170 EINTERN void e_client_focused_set(E_Client *ec);
171 static void _e_client_transient_for_group_make(E_Client *ec, Eina_List **list);
172 static Evas_Object *_e_client_resize_object_create(E_Client *ec);
173 static void _e_client_resize_object_del(E_Client *ec);
174 static void _e_client_stay_within_canvas(E_Client *ec, int x, int y, int *new_x, int *new_y);
175 static void _e_client_stay_within_canvas_margin(E_Client *ec, int x, int y, int *new_x, int *new_y);
176
177 static Eina_Inlist *_e_client_hooks[] =
178 {
179    [E_CLIENT_HOOK_EVAL_PRE_FETCH] = NULL,
180    [E_CLIENT_HOOK_EVAL_FETCH] = NULL,
181    [E_CLIENT_HOOK_EVAL_PRE_POST_FETCH] = NULL,
182    [E_CLIENT_HOOK_EVAL_POST_FETCH] = NULL,
183    [E_CLIENT_HOOK_EVAL_PRE_FRAME_ASSIGN] = NULL,
184    [E_CLIENT_HOOK_EVAL_POST_FRAME_ASSIGN] = NULL,
185    [E_CLIENT_HOOK_EVAL_PRE_NEW_CLIENT] = NULL,
186    [E_CLIENT_HOOK_EVAL_POST_NEW_CLIENT] = NULL,
187    [E_CLIENT_HOOK_EVAL_END] = NULL,
188    [E_CLIENT_HOOK_FOCUS_SET] = NULL,
189    [E_CLIENT_HOOK_FOCUS_UNSET] = NULL,
190    [E_CLIENT_HOOK_NEW_CLIENT] = NULL,
191    [E_CLIENT_HOOK_MOVE_BEGIN] = NULL,
192    [E_CLIENT_HOOK_MOVE_UPDATE] = NULL,
193    [E_CLIENT_HOOK_MOVE_END] = NULL,
194    [E_CLIENT_HOOK_RESIZE_BEGIN] = NULL,
195    [E_CLIENT_HOOK_RESIZE_UPDATE] = NULL,
196    [E_CLIENT_HOOK_RESIZE_END] = NULL,
197    [E_CLIENT_HOOK_FULLSCREEN_PRE] = NULL,
198    [E_CLIENT_HOOK_DEL] = NULL,
199    [E_CLIENT_HOOK_UNREDIRECT] = NULL,
200    [E_CLIENT_HOOK_REDIRECT] = NULL,
201 #ifdef _F_E_CLIENT_NEW_CLIENT_POST_HOOK_
202    [E_CLIENT_HOOK_NEW_CLIENT_POST] = NULL,
203 #endif
204    [E_CLIENT_HOOK_EVAL_VISIBILITY] = NULL,
205    [E_CLIENT_HOOK_ICONIFY] = NULL,
206    [E_CLIENT_HOOK_UNICONIFY] = NULL,
207    [E_CLIENT_HOOK_AUX_HINT_CHANGE] = NULL,
208    [E_CLIENT_HOOK_WINDOW_ROLE_CHANGE] = NULL,
209    [E_CLIENT_HOOK_TRANSFORM_CHANGE] = NULL,
210    [E_CLIENT_HOOK_ACTIVATE_DONE] = NULL,
211    [E_CLIENT_HOOK_EVAL_VISIBILITY_END] = NULL,
212 };
213
214 static Eina_Inlist *_e_client_intercept_hooks[] =
215 {
216    [E_CLIENT_INTERCEPT_HOOK_FOCUS_REVERT] = NULL,
217    [E_CLIENT_INTERCEPT_HOOK_AUTO_PLACEMENT] = NULL,
218 };
219
220 ///////////////////////////////////////////
221
222 static void
223 _e_client_hooks_clean(void)
224 {
225    Eina_Inlist *l;
226    E_Client_Hook *ch;
227    unsigned int x;
228
229    for (x = 0; x < E_CLIENT_HOOK_LAST; x++)
230      EINA_INLIST_FOREACH_SAFE(_e_client_hooks[x], l, ch)
231        {
232           if (!ch->delete_me) continue;
233           _e_client_hooks[x] = eina_inlist_remove(_e_client_hooks[x], EINA_INLIST_GET(ch));
234           free(ch);
235        }
236 }
237
238 static Eina_Bool
239 _e_client_hook_call(E_Client_Hook_Point hookpoint, E_Client *ec)
240 {
241    E_Client_Hook *ch;
242
243    e_object_ref(E_OBJECT(ec));
244    _e_client_hooks_walking++;
245    EINA_INLIST_FOREACH(_e_client_hooks[hookpoint], ch)
246      {
247         if (ch->delete_me) continue;
248         ch->func(ch->data, ec);
249         if ((hookpoint != E_CLIENT_HOOK_DEL) &&
250           (hookpoint != E_CLIENT_HOOK_MOVE_END) &&
251           (hookpoint != E_CLIENT_HOOK_RESIZE_END) &&
252           (hookpoint != E_CLIENT_HOOK_FOCUS_UNSET) &&
253           e_object_is_del(E_OBJECT(ec)))
254           break;
255      }
256    _e_client_hooks_walking--;
257    if ((_e_client_hooks_walking == 0) && (_e_client_hooks_delete > 0))
258      _e_client_hooks_clean();
259    return !!e_object_unref(E_OBJECT(ec));
260 }
261
262 ///////////////////////////////////////////
263
264 static void
265 _e_client_intercept_hooks_clean(void)
266 {
267    Eina_Inlist *l;
268    E_Client_Intercept_Hook *ch;
269    unsigned int x;
270
271    for (x = 0; x < E_CLIENT_INTERCEPT_HOOK_LAST; x++)
272      EINA_INLIST_FOREACH_SAFE(_e_client_intercept_hooks[x], l, ch)
273        {
274           if (!ch->delete_me) continue;
275           _e_client_intercept_hooks[x] =
276              eina_inlist_remove(_e_client_intercept_hooks[x], EINA_INLIST_GET(ch));
277           free(ch);
278        }
279 }
280
281 static Eina_Bool
282 _e_client_intercept_hook_call(E_Client_Intercept_Hook_Point hookpoint, E_Client *ec)
283 {
284    E_Client_Intercept_Hook *ch;
285    Eina_Bool ret = EINA_TRUE;
286
287    if (e_object_is_del(E_OBJECT(ec)))
288      {
289         if (hookpoint != E_CLIENT_INTERCEPT_HOOK_FOCUS_REVERT)
290           {
291              return ret;
292           }
293      }
294
295    e_object_ref(E_OBJECT(ec));
296    _e_client_intercept_hooks_walking++;
297    EINA_INLIST_FOREACH(_e_client_intercept_hooks[hookpoint], ch)
298      {
299         if (ch->delete_me) continue;
300         if (!(ch->func(ch->data, ec)))
301           {
302              ret = EINA_FALSE;
303              break;
304           }
305      }
306    _e_client_intercept_hooks_walking--;
307    if ((_e_client_intercept_hooks_walking == 0) &&
308        (_e_client_intercept_hooks_delete > 0))
309      _e_client_intercept_hooks_clean();
310
311    e_object_unref(E_OBJECT(ec));
312    return ret;
313 }
314
315 static void
316 _e_client_event_simple_free(void *d EINA_UNUSED, E_Event_Client *ev)
317 {
318    UNREFD(ev->ec, 3);
319    e_object_unref(E_OBJECT(ev->ec));
320    free(ev);
321 }
322
323 static void
324 _e_client_event_simple(E_Client *ec, int type)
325 {
326    E_Event_Client *ev;
327
328    ev = E_NEW(E_Event_Client, 1);
329    if (!ev) return;
330    ev->ec = ec;
331    REFD(ec, 3);
332    e_object_ref(E_OBJECT(ec));
333    ecore_event_add(type, ev, (Ecore_End_Cb)_e_client_event_simple_free, NULL);
334 }
335
336 static void
337 _e_client_event_add(E_Client *ec)
338 {
339    if (ec->reg_ev.add)
340      return;
341
342    ec->reg_ev.add = EINA_TRUE;
343    ELOGF("COMP", "SEND E_EVENT_CLIENT_ADD event", ec);
344    _e_client_event_simple(ec, E_EVENT_CLIENT_ADD);
345 }
346
347 static void
348 _e_client_event_remove(E_Client *ec)
349 {
350    if (!ec->reg_ev.add)
351      return;
352
353    ec->reg_ev.add = EINA_FALSE;
354    ELOGF("COMP", "SEND E_EVENT_CLIENT_REMOVE event", ec);
355    _e_client_event_simple(ec, E_EVENT_CLIENT_REMOVE);
356 }
357
358 static void
359 _e_client_event_show(E_Client *ec)
360 {
361    if (ec->reg_ev.show)
362      return;
363
364    ec->reg_ev.show = EINA_TRUE;
365    _e_client_event_simple(ec, E_EVENT_CLIENT_SHOW);
366 }
367
368 static void
369 _e_client_event_hide(E_Client *ec)
370 {
371    if (!ec->reg_ev.show)
372      return;
373
374    ec->reg_ev.show = EINA_FALSE;
375    _e_client_event_simple(ec, E_EVENT_CLIENT_HIDE);
376 }
377
378 static void
379 _e_client_event_property(E_Client *ec, int prop)
380 {
381    E_Event_Client_Property *ev;
382
383    ev = E_NEW(E_Event_Client_Property, 1);
384    if (!ev) return;
385    ev->ec = ec;
386    ev->property = prop;
387    REFD(ec, 33);
388    e_object_ref(E_OBJECT(ec));
389    ecore_event_add(E_EVENT_CLIENT_PROPERTY, ev, (Ecore_End_Cb)_e_client_event_simple_free, NULL);
390 }
391
392 ////////////////////////////////////////////////
393
394 static int
395 _e_client_action_input_win_del(void)
396 {
397    if (!comp_grabbed) return 0;
398
399    e_comp_ungrab_input(1, 1);
400    comp_grabbed = 0;
401    return 1;
402 }
403
404 static void
405 _e_client_action_finish(void)
406 {
407    if (comp_grabbed)
408      _e_client_action_input_win_del();
409
410    E_FREE_FUNC(action_timer, ecore_timer_del);
411    E_FREE_FUNC(action_handler_mouse, ecore_event_handler_del);
412    if (action_client)
413      {
414         action_client->keyboard_resizing = 0;
415      }
416    action_client = NULL;
417 }
418
419 static void
420 _e_client_transform_point_transform(int cx, int cy, double angle, int x, int y, int *tx, int *ty)
421 {
422    double s = sin(angle * M_PI / 180);
423    double c = cos(angle * M_PI / 180);
424    int rx, ry;
425
426    x -= cx;
427    y -= cy;
428
429    rx = x * c + y * s;
430    ry = - x * s + y * c;
431
432    rx += cx;
433    ry += cy;
434
435    *tx = rx;
436    *ty = ry;
437 }
438
439 static void
440 _e_client_transform_geometry_save(E_Client *ec, E_Map *map)
441 {
442    int i;
443
444    if (!map) return;
445
446    for (i = 0; i < 4; i ++)
447      {
448         e_map_point_precise_coord_get(map, i,
449                                       &ec->transform.saved[i].x,
450                                       &ec->transform.saved[i].y,
451                                       &ec->transform.saved[i].z);
452      }
453 }
454
455 static void
456 _e_client_transform_resize(E_Client *ec)
457 {
458    E_Map *map;
459    int cx, cy;
460    double dx = 0, dy = 0;
461    double px[4], py[4];
462    int pw, ph;
463    int i;
464
465    if (!ec->transformed) return;
466
467    if (!e_pixmap_size_get(ec->pixmap, &pw, &ph))
468      {
469         pw = ec->client.w;
470         ph = ec->client.h;
471      }
472
473    cx = ec->client.x + pw / 2;
474    cy = ec->client.y + ph / 2;
475
476    /* step 1: Rotate resized object and get map points */
477    map = e_map_new_with_direct_render(ec->transform_core.direct_render);
478    e_map_util_points_populate_from_geometry(map,
479                                             ec->client.x, ec->client.y,
480                                             pw, ph,
481                                             0);
482    e_map_util_rotate(map, ec->transform.angle, cx, cy);
483    e_map_util_zoom(map, ec->transform.zoom, ec->transform.zoom, cx, cy);
484
485    for (i = 0; i < 4; i++)
486      e_map_point_precise_coord_get(map, i, &px[i], &py[i], NULL);
487
488    e_map_free(map);
489
490    /* step 2: get adjusted values to keep up fixed position according
491     * to resize mode */
492    switch (ec->resize_mode)
493      {
494       case E_POINTER_RESIZE_R:
495       case E_POINTER_RESIZE_BR:
496          dx = ec->transform.saved[0].x - px[0];
497          dy = ec->transform.saved[0].y - py[0];
498          break;
499       case E_POINTER_RESIZE_BL:
500       case E_POINTER_RESIZE_B:
501          dx = ec->transform.saved[1].x - px[1];
502          dy = ec->transform.saved[1].y - py[1];
503          break;
504       case E_POINTER_RESIZE_TL:
505       case E_POINTER_RESIZE_L:
506          dx = ec->transform.saved[2].x - px[2];
507          dy = ec->transform.saved[2].y - py[2];
508          break;
509       case E_POINTER_RESIZE_T:
510       case E_POINTER_RESIZE_TR:
511          dx = ec->transform.saved[3].x - px[3];
512          dy = ec->transform.saved[3].y - py[3];
513          break;
514       default:
515          break;
516      }
517
518    ec->transform.adjusted.x = dx;
519    ec->transform.adjusted.y = dy;
520
521    /* step 3: set each points of the quadrangle */
522    map = e_map_new_with_direct_render(ec->transform_core.direct_render);
523    e_map_util_points_populate_from_object_full(map, ec->frame, 0);
524
525    for (i = 0; i < 4; i++)
526       e_map_point_precise_coord_set(map, i, px[i] + dx, py[i] + dy, 0);
527
528    e_client_map_set(ec, map);
529    e_client_map_enable_set(ec, EINA_TRUE);
530    e_map_free(map);
531 }
532
533 static void
534 _e_client_transform_resize_handle(E_Client *ec)
535 {
536
537    int new_x, new_y, new_w, new_h;
538    int org_w, org_h;
539    int button_id;
540    int cx, cy;
541    Evas_Point current, moveinfo;
542    E_Zone *zone;
543
544    if (e_object_is_del(E_OBJECT(ec))) return;
545    if (e_client_util_ignored_get(ec)) return;
546    if (!ec->transformed) return;
547
548    zone = e_comp_zone_find_by_ec(ec);
549    if (!zone) return;
550
551    button_id = ec->moveinfo.down.button;
552
553    org_w = ec->mouse.last_down[button_id - 1].w;
554    org_h = ec->mouse.last_down[button_id - 1].h;
555
556    new_w = ec->client.w;
557    new_h = ec->client.h;
558    new_x = ec->client.x;
559    new_y = ec->client.y;
560
561    /* step 1: get center coordinate its' based on original object geometry*/
562    cx = ec->client.x + org_w / 2;
563    cy = ec->client.y + org_h / 2;
564
565    /* step 2: transform coordinates of mouse position
566     * subtract adjusted value from mouse position is needed */
567    current.x = ec->mouse.current.mx - ec->transform.adjusted.x;
568    current.y = ec->mouse.current.my - ec->transform.adjusted.y;
569    moveinfo.x = ec->moveinfo.down.mx - ec->transform.adjusted.x;
570    moveinfo.y = ec->moveinfo.down.my - ec->transform.adjusted.y;
571
572    _e_client_transform_point_transform(cx, cy, ec->transform.angle,
573                                        current.x, current.y,
574                                        &current.x, &current.y);
575    _e_client_transform_point_transform(cx, cy, ec->transform.angle,
576                                        moveinfo.x, moveinfo.y,
577                                        &moveinfo.x, &moveinfo.y);
578
579    /* step 3: calculate new size */
580    if ((ec->resize_mode == E_POINTER_RESIZE_TR) ||
581        (ec->resize_mode == E_POINTER_RESIZE_R) ||
582        (ec->resize_mode == E_POINTER_RESIZE_BR))
583      {
584         if ((button_id >= 1) && (button_id <= 3))
585           new_w = org_w + (current.x - moveinfo.x);
586         else
587           new_w = ec->moveinfo.down.w + (current.x - moveinfo.x);
588      }
589    else if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
590             (ec->resize_mode == E_POINTER_RESIZE_L) ||
591             (ec->resize_mode == E_POINTER_RESIZE_BL))
592      {
593         if ((button_id >= 1) && (button_id <= 3))
594           new_w = org_w - (current.x - moveinfo.x);
595         else
596           new_w = ec->moveinfo.down.w - (current.x - moveinfo.x);
597      }
598
599    if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
600        (ec->resize_mode == E_POINTER_RESIZE_T) ||
601        (ec->resize_mode == E_POINTER_RESIZE_TR))
602      {
603         if ((button_id >= 1) && (button_id <= 3))
604           new_h = org_h - (current.y - moveinfo.y);
605         else
606           new_h = ec->moveinfo.down.h - (current.y - moveinfo.y);
607      }
608    else if ((ec->resize_mode == E_POINTER_RESIZE_BL) ||
609             (ec->resize_mode == E_POINTER_RESIZE_B) ||
610             (ec->resize_mode == E_POINTER_RESIZE_BR))
611      {
612         if ((button_id >= 1) && (button_id <= 3))
613           new_h = org_h + (current.y - moveinfo.y);
614         else
615           new_h = ec->moveinfo.down.h + (current.y - moveinfo.y);
616      }
617
618    new_w = MIN(new_w, zone->w);
619    new_h = MIN(new_h, zone->h);
620
621    /* step 4: move to new position */
622    if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
623        (ec->resize_mode == E_POINTER_RESIZE_L) ||
624        (ec->resize_mode == E_POINTER_RESIZE_BL))
625      new_x += (new_w - org_w);
626    if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
627        (ec->resize_mode == E_POINTER_RESIZE_T) ||
628        (ec->resize_mode == E_POINTER_RESIZE_TR))
629      new_y += (new_h - org_h);
630
631    /* step 5: set geometry to new value */
632    evas_object_geometry_set(ec->frame, new_x, new_y, new_w, new_h);
633 }
634
635 void
636 _e_client_transform_resize_begin(E_Client *ec)
637 {
638    E_Map *map;
639    if (!ec->transformed) return;
640
641    map = e_client_map_get(ec);
642    _e_client_transform_geometry_save(ec, map);
643    e_map_free(map);
644 }
645
646 void
647 _e_client_transform_resize_end(E_Client *ec)
648 {
649    E_Map *map;
650    int new_x = 0, new_y = 0;
651    int cx, cy, pw, ph;
652
653    if (!ec->transformed) return;
654
655    map = e_client_map_get(ec);
656    if (!map) return;
657
658    if (!e_pixmap_size_get(ec->pixmap, &pw, &ph))
659      {
660         pw = ec->client.w;
661         ph = ec->client.h;
662      }
663
664    cx = ec->client.x + pw / 2 + ec->transform.adjusted.x;
665    cy = ec->client.y + ph / 2 + ec->transform.adjusted.y;
666
667    if (ec->transform.zoom != 1.0)
668      {
669         E_Map *tmp_map;
670
671         tmp_map = e_map_dup(map);
672         e_map_util_zoom(tmp_map,
673                            1 / ec->transform.zoom,
674                            1 / ec->transform.zoom,
675                            cx, cy);
676
677         _e_client_transform_geometry_save(ec, tmp_map);
678         e_map_free(tmp_map);
679      }
680    else
681      {
682         _e_client_transform_geometry_save(ec, map);
683      }
684
685    /* move original object to adjusted position after resizing */
686    _e_client_transform_point_transform(cx, cy,
687                                        ec->transform.angle,
688                                        ec->transform.saved[0].x,
689                                        ec->transform.saved[0].y,
690                                        &new_x, &new_y);
691    e_client_util_move_without_frame(ec, new_x, new_y);
692    e_map_util_object_move_sync_set(map, EINA_TRUE);
693    e_map_free(map);
694 }
695
696 static void
697 _e_client_transform_move_end(E_Client *ec)
698 {
699
700    int i;
701    double dx, dy, px, py;
702    E_Map *map;
703
704    if (!ec->transformed) return;
705
706    map = e_client_map_get(ec);
707    if (!map) return;
708
709    if (ec->transform.zoom != 1.0)
710      {
711         e_map_point_precise_coord_get(map, 0, &px, &py, NULL);
712
713         dx = px - ec->transform.saved[0].x;
714         dy = py - ec->transform.saved[0].y;
715
716         for (i = 0; i < 4; i++)
717           {
718              ec->transform.saved[i].x += dx;
719              ec->transform.saved[i].y += dy;
720           }
721      }
722    else
723      _e_client_transform_geometry_save(ec, map);
724    e_map_free(map);
725 }
726
727 EINTERN Eina_Bool
728 e_client_intercept_hook_focus_revert_call(E_Client *ec)
729 {
730   // no need to call the intercept hook if ec is NULL.
731   if (!ec) return EINA_FALSE;
732
733   if (!_e_client_intercept_hook_call(E_CLIENT_INTERCEPT_HOOK_FOCUS_REVERT, ec))
734     {
735        ELOGF("FOCUS", "E_CLIENT_INTERCEPT_HOOK_FOCUS_REVERT Intercepted.", ec);
736        return EINA_TRUE;
737     }
738
739   return EINA_FALSE;
740 }
741
742 EINTERN E_Client *
743 e_client_check_fully_contain_by_above(E_Client *ec, Eina_Bool check_layer)
744 {
745    E_Client *above = NULL;
746    E_Zone *zone = NULL;
747    int x = 0, y = 0, w = 0, h = 0;
748    int ax = 0, ay = 0, aw = 0, ah = 0;
749
750    if (!ec) return NULL;
751
752    e_client_geometry_get(ec, &x, &y, &w, &h);
753
754    zone = e_comp_zone_find_by_ec(ec);
755    if (zone)
756      E_RECTS_CLIP_TO_RECT(x, y, w, h, zone->x, zone->y, zone->w, zone->h);
757
758    above = e_client_above_get(ec);
759    while (above)
760      {
761         if ((check_layer) &&
762             (above->layer <= ec->layer))
763           {
764              above = e_client_above_get(above);
765              continue;
766           }
767
768         if ((!e_object_is_del(E_OBJECT(above))) &&
769             (!e_client_util_ignored_get(above)) &&
770             (above->visible) &&
771             (!above->iconic || e_policy_visibility_client_is_uniconic(above)) &&
772             (!above->bg_state) &&
773             (!above->argb) &&
774             (!above->visibility.force_obscured) &&
775             (above->frame))
776           {
777              e_client_geometry_get(above, &ax, &ay, &aw, &ah);
778              if (E_CONTAINS(ax, ay, aw, ah, x, y, w, h))
779                break;
780           }
781         above = e_client_above_get(above);
782      }
783
784    return above;
785 }
786
787 EINTERN E_Client *
788 e_client_check_obscured_by_children_group(E_Client *ec)
789 {
790    E_Client *cec = NULL;
791    Eina_List *transients = NULL, *l = NULL;
792
793    _e_client_transient_for_group_make(ec, &transients);
794    if (!transients) return NULL;
795
796    EINA_LIST_FOREACH(transients, l, cec)
797      {
798         if (E_CONTAINS(cec->x, cec->y, cec->w, cec->h, ec->x, ec->y, ec->w, ec->h))
799           {
800             if (!cec->argb) break;
801             if (cec->visibility.opaque > 0) break;
802           }
803      }
804
805    eina_list_free(transients);
806
807    return cec;
808 }
809
810 EINTERN Eina_Bool
811 e_client_check_really_iconified(E_Client *ec)
812 {
813    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
814
815    if (!ec->iconic) return EINA_FALSE;
816
817    return ((!e_policy_visibility_client_is_uniconic(ec) &&
818             !e_policy_visibility_client_is_uniconify_render_running(ec)) ||
819            (e_client_is_iconified_by_client(ec)));
820 }
821
822 static void
823 _e_client_event_focus_skip_set(E_Client *ec, Eina_Bool by_client)
824 {
825    E_Event_Client_Focus_Skip_Set *ev;
826
827    ev = E_NEW(E_Event_Client_Focus_Skip_Set, 1);
828    if (!ev) return;
829
830    ev->ec = ec;
831    ev->by_client = by_client;
832    e_object_ref(E_OBJECT(ec));
833
834    ecore_event_add(E_EVENT_CLIENT_FOCUS_SKIP_SET, ev, (Ecore_End_Cb)_e_client_event_simple_free, NULL);
835 }
836
837 static void
838 _e_client_event_focus_skip_unset(E_Client *ec, Eina_Bool by_client)
839 {
840    E_Event_Client_Focus_Skip_Unset *ev;
841
842    ev = E_NEW(E_Event_Client_Focus_Skip_Unset, 1);
843    if (!ev) return;
844
845    ev->ec = ec;
846    ev->by_client = by_client;
847    e_object_ref(E_OBJECT(ec));
848
849    ecore_event_add(E_EVENT_CLIENT_FOCUS_SKIP_UNSET, ev, (Ecore_End_Cb)_e_client_event_simple_free, NULL);
850 }
851
852 E_API void
853 e_client_focus_skip_set(E_Client *ec, Eina_Bool skip, Eina_Bool by_client)
854 {
855    if (!ec) return;
856
857    if (skip)
858      {
859         if (ec->icccm.accepts_focus)
860           {
861              ELOGF("TZPOL", "FOCUS|SKIP SET (by_client:%d)", ec, by_client);
862              ec->icccm.accepts_focus = ec->icccm.take_focus = 0;
863              ec->changes.accepts_focus = 1;
864              EC_CHANGED(ec);
865
866              _e_client_event_focus_skip_set(ec, by_client);
867           }
868      }
869    else
870      {
871         if (!ec->icccm.accepts_focus)
872           {
873              ELOGF("TZPOL", "FOCUS|SKIP UNSET (by_client:%d)", ec, by_client);
874              ec->icccm.accepts_focus = ec->icccm.take_focus = 1;
875              ec->changes.accepts_focus = 1;
876              EC_CHANGED(ec);
877
878              _e_client_event_focus_skip_unset(ec, by_client);
879           }
880      }
881 }
882
883 EINTERN Eina_Bool
884 e_client_check_above_focused(E_Client *ec)
885 {
886    E_Client *focus = NULL;
887    E_Client *above = NULL;
888
889    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
890
891    focus = e_client_focused_get();
892    if (!focus) return EINA_FALSE;
893
894    above = e_client_above_get(ec);
895    while (above)
896      {
897         if (above == focus)
898           return EINA_TRUE;
899
900         above = e_client_above_get(above);
901      }
902
903    return EINA_FALSE;
904 }
905
906 static Eina_Bool
907 _e_client_private_init(E_Client *ec)
908 {
909    E_Client_Private *priv;
910
911    priv = E_NEW(E_Client_Private, 1);
912    if (!priv)
913      return EINA_FALSE;
914
915    wl_signal_init(&priv->events.eval_pre_fetch);
916    wl_signal_init(&priv->events.eval_fetch);
917    wl_signal_init(&priv->events.eval_pre_post_fetch);
918    wl_signal_init(&priv->events.eval_post_fetch);
919    wl_signal_init(&priv->events.eval_pre_frame_assign);
920    wl_signal_init(&priv->events.eval_post_frame_assign);
921    wl_signal_init(&priv->events.eval_pre_new_client);
922    wl_signal_init(&priv->events.eval_post_new_client);
923    wl_signal_init(&priv->events.eval_visibility);
924    wl_signal_init(&priv->events.eval_visibility_end);
925    wl_signal_init(&priv->events.eval_end);
926    wl_signal_init(&priv->events.move_begin);
927    wl_signal_init(&priv->events.move_update);
928    wl_signal_init(&priv->events.move_end);
929    wl_signal_init(&priv->events.move_resize_begin);
930    wl_signal_init(&priv->events.move_resize_update);
931    wl_signal_init(&priv->events.move_resize_end);
932    wl_signal_init(&priv->events.destroy);
933    wl_signal_init(&priv->events.new_client);
934    wl_signal_init(&priv->events.new_client_post);
935    wl_signal_init(&priv->events.unredirect);
936    wl_signal_init(&priv->events.redirect);
937    wl_signal_init(&priv->events.aux_hint_change);
938    wl_signal_init(&priv->events.window_role_change);
939    wl_signal_init(&priv->events.transform_change);
940    wl_signal_init(&priv->events.activate_done);
941    wl_signal_init(&priv->events.mouse_in);
942    wl_signal_init(&priv->events.mouse_out);
943    wl_signal_init(&priv->events.mouse_down);
944    wl_signal_init(&priv->events.focus_set);
945    wl_signal_init(&priv->events.focus_unset);
946    wl_signal_init(&priv->events.focus_defer_set);
947    wl_signal_init(&priv->events.focus_latest_set);
948    wl_signal_init(&priv->events.iconify);
949    wl_signal_init(&priv->events.uniconify);
950    wl_signal_init(&priv->events.maximize);
951    wl_signal_init(&priv->events.unmaximize);
952    wl_signal_init(&priv->events.fullscreen_pre);
953    wl_signal_init(&priv->events.fullscreen);
954    wl_signal_init(&priv->events.unfullscreen);
955    wl_signal_init(&priv->events.move);
956    wl_signal_init(&priv->events.set_layer);
957    wl_signal_init(&priv->events.raise);
958    wl_signal_init(&priv->events.lower);
959    wl_signal_init(&priv->events.stack_below);
960    wl_signal_init(&priv->events.stack_above);
961    wl_signal_init(&priv->events.stack_transient_for_done);
962    wl_signal_init(&priv->events.stick);
963    wl_signal_init(&priv->events.unstick);
964 #ifdef REFACTOR_DESK_AREA
965    wl_signal_init(&priv->events.get_above);
966    wl_signal_init(&priv->events.get_below);
967    wl_signal_init(&priv->events.get_visible_above);
968    wl_signal_init(&priv->events.get_visible_below);
969    wl_signal_init(&priv->events.subsurface_stack_update);
970 #endif
971
972    wl_signal_init(&priv->events.delete_request);
973    wl_signal_init(&priv->events.kill_request);
974    wl_signal_init(&priv->events.ping);
975
976    e_object_data_set(E_OBJECT(ec), priv);
977
978    return EINA_TRUE;
979 }
980
981 static void
982 _e_client_private_finish(E_Client *ec)
983 {
984    E_Client_Private *priv;
985
986    priv = PRI(ec);
987    e_object_data_set(E_OBJECT(ec), NULL);
988
989    free(priv);
990 }
991
992 static void
993 _e_input_thread_client_free(void *data)
994 {
995    E_Input_Thread_Request_EClient_Data *ec_data = data;
996    EINA_SAFETY_ON_NULL_RETURN(ec_data);
997
998    INF("[input thread|%s] ec: %p\n", __func__, ec_data->ec);
999    e_input_thread_client_free(e_input_thread_client_get(ec_data->ec));
1000 }
1001
1002 static void
1003 _e_client_free(E_Client *ec)
1004 {
1005    g_rec_mutex_lock(&e_comp->ec_list_mutex);
1006
1007    E_Input_Thread_Request_EClient_Data ec_data;
1008    memset(&ec_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
1009
1010    e_comp_object_redirected_set(ec->frame, 0);
1011    e_comp_object_render_update_del(ec->frame);
1012
1013    E_OBJECT(ec)->references++;
1014
1015    if (ec->new_client)
1016      e_comp->new_clients--;
1017
1018    if (ec->e.state.video_parent && ec->e.state.video_parent_client)
1019      {
1020         ec->e.state.video_parent_client->e.state.video_child =
1021           eina_list_remove(ec->e.state.video_parent_client->e.state.video_child, ec);
1022      }
1023    if (ec->e.state.video_child)
1024      {
1025         E_Client *tmp;
1026
1027         EINA_LIST_FREE(ec->e.state.video_child, tmp)
1028           tmp->e.state.video_parent_client = NULL;
1029      }
1030    E_FREE_FUNC(ec->kill_timer, ecore_timer_del);
1031
1032    E_FREE_FUNC(ec->map_timer, ecore_timer_del);
1033
1034    ec->transients = eina_list_free(ec->transients);
1035    eina_stringshare_replace(&ec->border.name, NULL);
1036    eina_stringshare_replace(&ec->bordername, NULL);
1037    eina_stringshare_replace(&ec->icccm.name, NULL);
1038 #if defined(__cplusplus) || defined(c_plusplus)
1039    eina_stringshare_replace(&ec->icccm.cpp_class, NULL);
1040 #else
1041    eina_stringshare_replace(&ec->icccm.class, NULL);
1042 #endif
1043    e_client_icccm_title_set(ec, NULL);
1044    eina_stringshare_replace(&ec->icccm.window_role, NULL);
1045    e_client_netwm_name_set(ec, NULL);
1046
1047    E_FREE_FUNC(ec->frame, evas_object_del);
1048
1049    E_OBJECT(ec)->references--;
1050    ELOGF("COMP", "CLIENT FREE", ec);
1051
1052    e_uuid_store_entry_del(ec->uuid);
1053
1054    ec_data.ec = ec;
1055    INF("[%s] ec: %p\n", __func__, ec);
1056    e_input_thread_safe_call(_e_input_thread_client_free, &ec_data, sizeof(E_Input_Thread_Request_EClient_Data));
1057
1058    _e_client_private_finish(ec);
1059    free(ec);
1060
1061    g_rec_mutex_unlock(&e_comp->ec_list_mutex);
1062 }
1063
1064 static void
1065 _e_input_thread_client_del(void *data)
1066 {
1067    E_Input_Thread_Request_EClient_Data *ec_data = data;
1068    EINA_SAFETY_ON_NULL_RETURN(ec_data);
1069
1070    INF("[input thread|%s] ec: %p\n", __func__, ec_data->ec);
1071    e_input_thread_client_del(e_input_thread_client_get(ec_data->ec));
1072 }
1073
1074 static void
1075 _e_client_del(E_Client *ec)
1076 {
1077    E_Client *child;
1078    E_Pixmap_Type type;
1079    E_Input_Thread_Request_EClient_Data ec_data;
1080    memset(&ec_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
1081
1082    g_rec_mutex_lock(&e_comp->ec_list_mutex);
1083
1084    ec->changed = 0;
1085
1086    if (ec == e_comp_object_dim_client_get())
1087      {
1088         INF("[DIM] client deleted\n");
1089         e_comp_object_dim_client_set(NULL);
1090      }
1091
1092    if (ec->cur_mouse_action)
1093      {
1094         if (ec->cur_mouse_action->func.end)
1095           ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
1096      }
1097    if (action_client == ec) _e_client_action_finish();
1098
1099    if (!stopping)
1100      {
1101         e_client_comp_hidden_set(ec, 1);
1102         evas_object_pass_events_set(ec->frame, 1);
1103      }
1104
1105    E_FREE_FUNC(ec->ping_poller, ecore_poller_del);
1106
1107    wl_signal_emit_mutable(&PRI(ec)->events.destroy, NULL);
1108
1109    /* must be called before parent/child clear */
1110    _e_client_hook_call(E_CLIENT_HOOK_DEL, ec);
1111
1112    _e_client_event_remove(ec);
1113
1114    ELOGF("COMP", "CLIENT DEL", ec);
1115
1116    if (ec->parent)
1117      {
1118         if (e_client_modal_child_get(ec->parent) == ec)
1119           e_client_modal_child_set(ec->parent, NULL);
1120         ec->parent->transients = eina_list_remove(ec->parent->transients, ec);
1121         ec->parent = NULL;
1122      }
1123    EINA_LIST_FREE(ec->transients, child)
1124      child->parent = NULL;
1125
1126    type = e_pixmap_type_get(ec->pixmap);
1127    if (type < E_PIXMAP_TYPE_MAX)
1128      eina_hash_del_by_key(clients_hash[type], &ec->pixmap);
1129    e_comp->clients = eina_list_remove(e_comp->clients, ec);
1130    e_comp_object_render_update_del(ec->frame);
1131    e_comp_post_update_purge(ec);
1132    if (e_pixmap_free(ec->pixmap))
1133      e_pixmap_client_set(ec->pixmap, NULL);
1134    ec->pixmap = NULL;
1135
1136    // base_output_resolution
1137    e_util_transform_del(ec->base_output_resolution.transform);
1138    ec->base_output_resolution.transform = NULL;
1139    E_FREE_FUNC(ec->base_output_resolution.hook_subsurf_create, e_comp_wl_hook_del);
1140
1141    if (ec->transform_core.transform_list)
1142      {
1143         E_Util_Transform *transform;
1144
1145         EINA_LIST_FREE(ec->transform_core.transform_list, transform)
1146           {
1147              e_util_transform_unref(transform);
1148           }
1149      }
1150
1151    ec->transform_core.result.enable = EINA_FALSE;
1152
1153    _e_client_resize_object_del(ec);
1154
1155    e_comp_visibility_calculation_set(EINA_TRUE);
1156
1157    ec_data.ec = ec;
1158    INF("[%s] ec: %p\n", __func__, ec);
1159    e_input_thread_safe_call(_e_input_thread_client_del, &ec_data, sizeof(E_Input_Thread_Request_EClient_Data));
1160
1161    g_rec_mutex_unlock(&e_comp->ec_list_mutex);
1162 }
1163
1164 ///////////////////////////////////////////
1165
1166 static Eina_Bool
1167 _e_client_cb_kill_timer(void *data)
1168 {
1169    E_Client *ec = data;
1170
1171 // dont wait until it's hung -
1172 //   if (ec->hung)
1173 //     {
1174    if (ec->netwm.pid > 1)
1175      kill(ec->netwm.pid, SIGKILL);
1176 //     }
1177    ec->kill_timer = NULL;
1178    return ECORE_CALLBACK_CANCEL;
1179 }
1180
1181 static Eina_Bool
1182 _e_client_cb_ping_poller(void *data)
1183 {
1184    E_Client *ec;
1185
1186    ec = data;
1187    if (e_object_is_del(E_OBJECT(ec)))
1188      {
1189         ec->ping_poller = NULL;
1190         return ECORE_CALLBACK_CANCEL;
1191      }
1192
1193    if (ec->ping_ok)
1194      {
1195         if (ec->hung)
1196           {
1197              ec->hung = 0;
1198              E_FREE_FUNC(ec->kill_timer, ecore_timer_del);
1199           }
1200      }
1201    else
1202      {
1203         /* if time between last ping and now is greater
1204          * than half the ping interval... */
1205         if ((ecore_loop_time_get() - ec->ping) >
1206             ((e_config->ping_clients_interval *
1207               ecore_poller_poll_interval_get(ECORE_POLLER_CORE)) / 2.0))
1208           {
1209              if (!ec->hung)
1210                {
1211                   ec->hung = 1;
1212                   /* FIXME: if below dialog is up - hide it now */
1213                }
1214              if (ec->delete_requested)
1215                {
1216                   /* FIXME: pop up dialog saying app is hung - kill client, or pid */
1217                   e_client_act_kill_begin(ec);
1218                }
1219           }
1220      }
1221    ec->ping_poller = NULL;
1222    e_client_ping(ec);
1223    return ECORE_CALLBACK_CANCEL;
1224 }
1225
1226 ///////////////////////////////////////////
1227
1228 static int
1229 _e_client_action_input_win_new(void)
1230 {
1231    if (comp_grabbed)
1232      {
1233         CRI("DOUBLE COMP GRAB! ACK!!!!");
1234         return 1;
1235      }
1236    comp_grabbed = e_comp_grab_input(1, 1);
1237    if (!comp_grabbed) _e_client_action_input_win_del();
1238    return comp_grabbed;
1239 }
1240
1241 static void
1242 _e_client_action_init(E_Client *ec)
1243 {
1244    action_orig.x = ec->x;
1245    action_orig.y = ec->y;
1246    action_orig.w = ec->w;
1247    action_orig.h = ec->h;
1248
1249    if (action_client)
1250      {
1251         action_client->keyboard_resizing = 0;
1252      }
1253    action_client = ec;
1254 }
1255
1256 static int
1257 _e_client_move_begin(E_Client *ec)
1258 {
1259    if ((ec->fullscreen) || (ec->lock_user_location))
1260      return 0;
1261
1262    if (!_e_client_action_input_win_new()) return 0;
1263    ec->moving = 1;
1264    ecmove = ec;
1265
1266    wl_signal_emit(&PRI(ec)->events.move_begin, NULL);
1267    _e_client_hook_call(E_CLIENT_HOOK_MOVE_BEGIN, ec);
1268    if (!ec->moving)
1269      {
1270         if (ecmove == ec) ecmove = NULL;
1271         _e_client_action_input_win_del();
1272         return 0;
1273      }
1274    if (!ec->lock_user_stacking)
1275      {
1276         if (e_config->border_raise_on_mouse_action)
1277           e_client_raise(ec);
1278      }
1279
1280    if (e_comp->hwc)
1281      e_comp_client_override_add(ec);
1282
1283    return 1;
1284 }
1285
1286 static int
1287 _e_client_move_end(E_Client *ec)
1288 {
1289    ec->moving = 0;
1290    _e_client_action_input_win_del();
1291
1292    wl_signal_emit(&PRI(ec)->events.move_end, NULL);
1293    _e_client_hook_call(E_CLIENT_HOOK_MOVE_END, ec);
1294
1295    if (ec->transformed)
1296      _e_client_transform_move_end(ec);
1297
1298    if (e_comp->hwc)
1299      e_comp_client_override_del(ec);
1300
1301    ecmove = NULL;
1302    return 1;
1303 }
1304
1305 static Eina_Bool
1306 _e_client_action_move_timeout(void *data EINA_UNUSED)
1307 {
1308    _e_client_move_end(action_client);
1309    _e_client_action_finish();
1310    return ECORE_CALLBACK_CANCEL;
1311 }
1312
1313 static void
1314 _e_client_action_move_timeout_add(void)
1315 {
1316    E_FREE_FUNC(action_timer, ecore_timer_del);
1317    if (e_config->border_keyboard.timeout)
1318      action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_client_action_move_timeout, NULL);
1319 }
1320
1321 static Eina_Bool
1322 _e_client_move_mouse_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
1323 {
1324    if (!comp_grabbed) return ECORE_CALLBACK_RENEW;
1325
1326    if (!action_client)
1327      ERR("no action_client!");
1328
1329    if (action_client) _e_client_move_end(action_client);
1330    _e_client_action_finish();
1331    return ECORE_CALLBACK_DONE;
1332 }
1333
1334 static void
1335 _e_client_moveinfo_gather(E_Client *ec, const char *source)
1336 {
1337    if (e_util_glob_match(source, "mouse,*,1"))
1338      ec->moveinfo.down.button = 1;
1339    else if (e_util_glob_match(source, "mouse,*,2"))
1340      ec->moveinfo.down.button = 2;
1341    else if (e_util_glob_match(source, "mouse,*,3"))
1342      ec->moveinfo.down.button = 3;
1343    else
1344      ec->moveinfo.down.button = 0;
1345    if ((ec->moveinfo.down.button >= 1) && (ec->moveinfo.down.button <= 3))
1346      {
1347         ec->moveinfo.down.mx = ec->mouse.last_down[ec->moveinfo.down.button - 1].mx;
1348         ec->moveinfo.down.my = ec->mouse.last_down[ec->moveinfo.down.button - 1].my;
1349      }
1350    else
1351      {
1352         ec->moveinfo.down.mx = ec->mouse.current.mx;
1353         ec->moveinfo.down.my = ec->mouse.current.my;
1354      }
1355 }
1356
1357 static void
1358 _e_client_move_handle(E_Client *ec)
1359 {
1360    int x, y;
1361
1362    if ((ec->moveinfo.down.button >= 1) && (ec->moveinfo.down.button <= 3))
1363      {
1364         x = ec->mouse.last_down[ec->moveinfo.down.button - 1].x +
1365            (ec->mouse.current.mx - ec->moveinfo.down.mx);
1366         y = ec->mouse.last_down[ec->moveinfo.down.button - 1].y +
1367            (ec->mouse.current.my - ec->moveinfo.down.my);
1368      }
1369    else
1370      {
1371         x = ec->moveinfo.down.x +
1372            (ec->mouse.current.mx - ec->moveinfo.down.mx);
1373         y = ec->moveinfo.down.y +
1374            (ec->mouse.current.my - ec->moveinfo.down.my);
1375      }
1376
1377    if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
1378      _e_client_stay_within_canvas(ec, x, y, &x, &y);
1379
1380    if (ec->floating)
1381      _e_client_stay_within_canvas_margin(ec, x, y, &x, &y);
1382
1383    evas_object_move(ec->frame, x, y);
1384
1385    if (e_client_transform_core_enable_get(ec))
1386      {
1387         e_client_transform_core_update(ec);
1388      }
1389 }
1390
1391 static Evas_Object *
1392 _e_client_resize_object_rectangle_get(E_Client *ec)
1393 {
1394    Evas_Object *resize_obj = NULL;
1395
1396    resize_obj = evas_object_rectangle_add(evas_object_evas_get(ec->frame));
1397    EINA_SAFETY_ON_NULL_RETURN_VAL(resize_obj, NULL);
1398
1399    if (e_config->resize_object.customize)
1400      {
1401         evas_object_color_set(resize_obj,
1402                               e_config->resize_object.r,
1403                               e_config->resize_object.g,
1404                               e_config->resize_object.b,
1405                               e_config->resize_object.a);
1406      }
1407    else
1408      evas_object_color_set(resize_obj, 128, 128, 128, 100);
1409
1410    return resize_obj;
1411 }
1412
1413 static Evas_Object *
1414 _e_client_resize_object_image_get(E_Client *ec)
1415 {
1416    int err;
1417    Evas_Object *resize_obj = NULL;
1418
1419    if (!e_config->resize_object.image_path)
1420      {
1421         ELOGF("COMP", "NO resize_object image! Make default resize_object", ec);
1422         goto get_rectangle;
1423      }
1424
1425    resize_obj = evas_object_image_add(evas_object_evas_get(ec->frame));
1426    EINA_SAFETY_ON_NULL_RETURN_VAL(resize_obj, NULL);
1427
1428    evas_object_image_file_set(resize_obj, e_config->resize_object.image_path, NULL);
1429    err = evas_object_image_load_error_get(resize_obj);
1430    if (err != EVAS_LOAD_ERROR_NONE)
1431      {
1432         ELOGF("COMP", "Image load error. path:%s, errno:%d. Make default resize_object",
1433               ec, e_config->resize_object.image_path, err);
1434         evas_object_del(resize_obj);
1435         resize_obj = NULL;
1436         goto get_rectangle;
1437      }
1438
1439    evas_object_image_fill_set(resize_obj, 0, 0, ec->w, ec->h);
1440    evas_object_image_filled_set(resize_obj, EINA_TRUE);
1441
1442    evas_object_image_border_set(resize_obj,
1443                                 e_config->resize_object.border_width.l,
1444                                 e_config->resize_object.border_width.r,
1445                                 e_config->resize_object.border_width.t,
1446                                 e_config->resize_object.border_width.b);
1447
1448    return resize_obj;
1449
1450 get_rectangle:
1451    return _e_client_resize_object_rectangle_get(ec);
1452 }
1453
1454 static Evas_Object *
1455 _e_client_resize_object_create(E_Client *ec)
1456 {
1457    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, NULL);
1458
1459    Evas_Object *resize_obj = NULL;
1460
1461    if (_e_client_resize_object_create_cb)
1462      resize_obj = _e_client_resize_object_create_cb(ec);
1463    else
1464      {
1465         if (e_config->resize_object.type == 1) // image object
1466           {
1467              resize_obj = _e_client_resize_object_image_get(ec);
1468           }
1469         else // rectangle
1470           {
1471              resize_obj = _e_client_resize_object_rectangle_get(ec);
1472           }
1473      }
1474    EINA_SAFETY_ON_NULL_RETURN_VAL(resize_obj, NULL);
1475
1476    evas_object_pass_events_set(resize_obj, EINA_TRUE);
1477    evas_object_layer_set(resize_obj, evas_object_layer_get(ec->frame));
1478    evas_object_stack_above(resize_obj, ec->frame);
1479    evas_object_name_set(resize_obj, "resize_object");
1480
1481    return resize_obj;
1482 }
1483
1484 static void
1485 _e_client_resize_object_del(E_Client *ec)
1486 {
1487    if (ec == NULL) return;
1488    if (ec->manage_resize.resize_obj == NULL) return;
1489
1490    evas_object_hide(ec->manage_resize.resize_obj);
1491    evas_object_del(ec->manage_resize.resize_obj);
1492    ec->manage_resize.resize_obj = NULL;
1493 }
1494
1495 static void
1496 _e_client_resize_handle(E_Client *ec)
1497 {
1498    int x, y, w, h;
1499    int new_x, new_y, new_w, new_h;
1500    int tw, th;
1501    int trans_x = 0, trans_y = 0;
1502    int trans_w = 0, trans_h = 0;
1503
1504    if (ec->transformed)
1505      {
1506         _e_client_transform_resize_handle(ec);
1507         return;
1508      }
1509
1510    x = ec->x;
1511    y = ec->y;
1512    w = ec->w;
1513    h = ec->h;
1514
1515    if ((ec->resize_mode == E_POINTER_RESIZE_TR) ||
1516        (ec->resize_mode == E_POINTER_RESIZE_R) ||
1517        (ec->resize_mode == E_POINTER_RESIZE_BR))
1518      {
1519         if ((ec->moveinfo.down.button >= 1) &&
1520             (ec->moveinfo.down.button <= 3))
1521           w = ec->mouse.last_down[ec->moveinfo.down.button - 1].w +
1522             (ec->mouse.current.mx - ec->moveinfo.down.mx);
1523         else
1524           w = ec->moveinfo.down.w + (ec->mouse.current.mx - ec->moveinfo.down.mx);
1525      }
1526    else if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
1527             (ec->resize_mode == E_POINTER_RESIZE_L) ||
1528             (ec->resize_mode == E_POINTER_RESIZE_BL))
1529      {
1530         if ((ec->moveinfo.down.button >= 1) &&
1531             (ec->moveinfo.down.button <= 3))
1532           w = ec->mouse.last_down[ec->moveinfo.down.button - 1].w -
1533             (ec->mouse.current.mx - ec->moveinfo.down.mx);
1534         else
1535           w = ec->moveinfo.down.w - (ec->mouse.current.mx - ec->moveinfo.down.mx);
1536      }
1537
1538    if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
1539        (ec->resize_mode == E_POINTER_RESIZE_T) ||
1540        (ec->resize_mode == E_POINTER_RESIZE_TR))
1541      {
1542         if ((ec->moveinfo.down.button >= 1) &&
1543             (ec->moveinfo.down.button <= 3))
1544           h = ec->mouse.last_down[ec->moveinfo.down.button - 1].h -
1545             (ec->mouse.current.my - ec->moveinfo.down.my);
1546         else
1547           h = ec->moveinfo.down.h - (ec->mouse.current.my - ec->moveinfo.down.my);
1548      }
1549    else if ((ec->resize_mode == E_POINTER_RESIZE_BL) ||
1550             (ec->resize_mode == E_POINTER_RESIZE_B) ||
1551             (ec->resize_mode == E_POINTER_RESIZE_BR))
1552      {
1553         if ((ec->moveinfo.down.button >= 1) &&
1554             (ec->moveinfo.down.button <= 3))
1555           h = ec->mouse.last_down[ec->moveinfo.down.button - 1].h +
1556             (ec->mouse.current.my - ec->moveinfo.down.my);
1557         else
1558           h = ec->moveinfo.down.h + (ec->mouse.current.my - ec->moveinfo.down.my);
1559      }
1560    tw = ec->w;
1561    th = ec->h;
1562
1563    if ((ec->resize_mode == E_POINTER_RESIZE_T) ||
1564        (ec->resize_mode == E_POINTER_RESIZE_TL) ||
1565        (ec->resize_mode == E_POINTER_RESIZE_L) ||
1566        (ec->resize_mode == E_POINTER_RESIZE_BL))
1567      x += (tw - w);
1568    if ((ec->resize_mode == E_POINTER_RESIZE_L) ||
1569        (ec->resize_mode == E_POINTER_RESIZE_TL) ||
1570        (ec->resize_mode == E_POINTER_RESIZE_T) ||
1571        (ec->resize_mode == E_POINTER_RESIZE_TR))
1572      y += (th - h);
1573
1574    new_x = x;
1575    new_y = y;
1576    new_w = w;
1577    new_h = h;
1578    if (e_config->screen_limits == E_CLIENT_OFFSCREEN_LIMIT_ALLOW_NONE)
1579      {
1580         E_Zone *zone;
1581         zone = e_comp_zone_find_by_ec(ec);
1582         if (zone)
1583           {
1584              w = MIN(w, zone->w);
1585              h = MIN(h, zone->h);
1586           }
1587      }
1588    e_client_resize_limit(ec, &new_w, &new_h);
1589
1590    if (ec->manage_resize.enable_aspect_ratio)
1591      {
1592         if ((ec->resize_mode == E_POINTER_RESIZE_TL) ||
1593             (ec->resize_mode == E_POINTER_RESIZE_L) ||
1594             (ec->resize_mode == E_POINTER_RESIZE_BL) ||
1595             (ec->resize_mode == E_POINTER_RESIZE_TR) ||
1596             (ec->resize_mode == E_POINTER_RESIZE_R) ||
1597             (ec->resize_mode == E_POINTER_RESIZE_BR))
1598           {
1599              new_h = (int) ec->manage_resize.ah / ec->manage_resize.aw * new_w;
1600           }
1601         else if ((ec->resize_mode == E_POINTER_RESIZE_T) ||
1602                  (ec->resize_mode == E_POINTER_RESIZE_B))
1603           {
1604              new_w = (int) ec->manage_resize.aw / ec->manage_resize.ah * new_h;
1605           }
1606           new_h += ec->manage_resize.header_h;
1607           new_h += ec->manage_resize.footer_h;
1608      }
1609
1610    if ((ec->resize_mode == E_POINTER_RESIZE_T) ||
1611        (ec->resize_mode == E_POINTER_RESIZE_TL) ||
1612        (ec->resize_mode == E_POINTER_RESIZE_L) ||
1613        (ec->resize_mode == E_POINTER_RESIZE_BL))
1614      new_x += (w - new_w);
1615    if ((ec->resize_mode == E_POINTER_RESIZE_L) ||
1616        (ec->resize_mode == E_POINTER_RESIZE_TL) ||
1617        (ec->resize_mode == E_POINTER_RESIZE_T) ||
1618        (ec->resize_mode == E_POINTER_RESIZE_TR))
1619      new_y += (h - new_h);
1620
1621    if (e_config->interactive_resize)
1622      {
1623         evas_object_geometry_set(ec->frame, new_x, new_y, new_w, new_h);
1624      }
1625    else
1626      {
1627         if (ec->manage_resize.resize_obj == NULL)
1628           {
1629              ec->manage_resize.resize_obj = _e_client_resize_object_create(ec);
1630              EINA_SAFETY_ON_NULL_RETURN(ec->manage_resize.resize_obj);
1631           }
1632
1633         if (e_client_transform_core_enable_get(ec))
1634           {
1635              e_client_transform_core_input_inv_transform(ec, new_x, new_y, &trans_x, &trans_y);
1636              e_client_transform_core_input_inv_transform(ec, new_w, new_h, &trans_w, &trans_h);
1637              evas_object_geometry_set(ec->manage_resize.resize_obj, trans_x, trans_y, trans_w, trans_h);
1638           }
1639         else
1640           evas_object_geometry_set(ec->manage_resize.resize_obj, new_x, new_y, new_w, new_h);
1641         evas_object_show(ec->manage_resize.resize_obj);
1642
1643         ec->manage_resize.x = new_x;
1644         ec->manage_resize.y = new_y;
1645         ec->manage_resize.w = new_w;
1646         ec->manage_resize.h = new_h;
1647      }
1648 }
1649
1650 static int
1651 _e_client_adjust_size_by_ppu(int size, int start_size, unsigned int ppu)
1652 {
1653    if (ppu <= 1) return size;
1654
1655    unsigned int remainder = size % ppu;
1656    if (remainder == 0) return size;
1657
1658    int gap = size - start_size;
1659    int new_size = size;
1660    if (gap > 0)
1661      new_size = size + (ppu - remainder);
1662    else
1663      new_size = size - remainder;
1664
1665    return new_size;
1666 }
1667
1668 static int
1669 _e_client_adjust_position_by_ppu(int pos, int size, int prev_pos, int prev_size)
1670 {
1671    int new_pos = 0;
1672
1673    if (prev_pos == pos)
1674      new_pos = pos;
1675    else
1676      new_pos = (prev_pos + prev_size) - size;
1677
1678    return new_pos;
1679 }
1680
1681 static void
1682 _e_client_adjust_geometry_by_resize_ppu(E_Client *ec)
1683 {
1684    if (ec->manage_resize.unit_size <= 1) return;
1685
1686    ec->manage_resize.w = _e_client_adjust_size_by_ppu(ec->manage_resize.w, ec->w, ec->manage_resize.unit_size);
1687    ec->manage_resize.h = _e_client_adjust_size_by_ppu(ec->manage_resize.h, ec->h, ec->manage_resize.unit_size);
1688
1689    ec->manage_resize.x = _e_client_adjust_position_by_ppu(ec->manage_resize.x, ec->manage_resize.w, ec->x, ec->w);
1690    ec->manage_resize.y = _e_client_adjust_position_by_ppu(ec->manage_resize.y, ec->manage_resize.h, ec->y, ec->h);
1691 }
1692
1693 static int
1694 _e_client_resize_end(E_Client *ec)
1695 {
1696    ec->resize_mode = E_POINTER_RESIZE_NONE;
1697    _e_client_action_input_win_del();
1698
1699    wl_signal_emit(&PRI(ec)->events.move_resize_end, NULL);
1700    _e_client_hook_call(E_CLIENT_HOOK_RESIZE_END, ec);
1701
1702    if (ec->transformed)
1703      _e_client_transform_resize_end(ec);
1704
1705    if (e_comp->hwc)
1706      e_comp_client_override_del(ec);
1707
1708    ecresize = NULL;
1709
1710    if (!e_config->interactive_resize)
1711      {
1712         if (ec->manage_resize.resize_obj)
1713           {
1714              if (ec->manage_resize.unit_size > 1)
1715                _e_client_adjust_geometry_by_resize_ppu(ec);
1716
1717              e_client_frame_geometry_set(ec,
1718                                          ec->manage_resize.x,
1719                                          ec->manage_resize.y,
1720                                          ec->manage_resize.w,
1721                                          ec->manage_resize.h);
1722              _e_client_resize_object_del(ec);
1723           }
1724      }
1725
1726    return 1;
1727 }
1728
1729 static Eina_Bool
1730 _e_client_action_resize_timeout(void *data EINA_UNUSED)
1731 {
1732    _e_client_resize_end(action_client);
1733    _e_client_action_finish();
1734    return ECORE_CALLBACK_CANCEL;
1735 }
1736
1737 static void
1738 _e_client_action_resize_timeout_add(void)
1739 {
1740    E_FREE_FUNC(action_timer, ecore_timer_del);
1741    if (e_config->border_keyboard.timeout)
1742      action_timer = ecore_timer_add(e_config->border_keyboard.timeout, _e_client_action_resize_timeout, NULL);
1743 }
1744
1745 static Eina_Bool
1746 _e_client_resize_mouse_down(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
1747 {
1748    if (!comp_grabbed) return ECORE_CALLBACK_RENEW;
1749
1750    if (!action_client)
1751      ERR("no action_client!");
1752
1753    if (action_client) _e_client_resize_end(action_client);
1754    _e_client_action_finish();
1755    return ECORE_CALLBACK_DONE;
1756 }
1757
1758 ////////////////////////////////////////////////
1759
1760 static Eina_Bool
1761 _e_client_position_inside_input_rect(E_Client *ec, int tx, int ty)
1762 {
1763    int x, y, w, h;
1764    Eina_Bool res = EINA_FALSE;
1765    Eina_List *list = NULL, *l;
1766    Eina_Rectangle *data;
1767
1768    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1769
1770    e_client_geometry_get(ec, &x, &y, &w, &h);
1771    e_comp_object_input_rect_get(ec->frame, &list);
1772    if (list)
1773      {
1774         EINA_LIST_FOREACH(list, l, data)
1775           {
1776              if ((tx >= x + data->x) && (tx <= x + data->x + data->w) &&
1777                  (ty >= y + data->y) && (ty <= y + data->y + data->h))
1778                {
1779                   res = EINA_TRUE;
1780                   break;
1781                }
1782           }
1783         list = eina_list_free(list);
1784      }
1785    else
1786      {
1787         if ((tx >= x) && (tx <= x + w) &&
1788             (ty >= y) && (ty <= y + h))
1789           {
1790              res = EINA_TRUE;
1791           }
1792      }
1793
1794    return res;
1795 }
1796
1797 static Eina_Bool
1798 _e_client_under_pointer_helper_ignore_client(E_Desk *desk, E_Client *client)
1799 {
1800    /* If a border was specified which should be excluded from the list
1801     * (because it will be closed shortly for example), skip */
1802    if (e_client_util_ignored_get(client) || (!e_desk_has_ec(desk, client))) return EINA_TRUE;
1803    if (!evas_object_visible_get(client->frame)) return EINA_TRUE;
1804    if (e_policy_client_is_cursor(client)) return EINA_TRUE;
1805    if (e_comp_wl->drag_client == client) return EINA_TRUE;
1806
1807    return EINA_FALSE;
1808 }
1809
1810 static E_Client *
1811 _e_client_under_pointer_helper(E_Desk *desk, E_Client *exclude, int x, int y)
1812 {
1813    E_Client *ec = NULL, *cec;
1814
1815    E_CLIENT_REVERSE_FOREACH(cec)
1816      {
1817         if (_e_client_under_pointer_helper_ignore_client(desk, cec)) continue;
1818         if ((exclude) && (cec == exclude)) continue;
1819         if (!E_INSIDE(x, y, cec->x, cec->y, cec->w, cec->h))
1820           continue;
1821         /* If the layer is higher, the position of the window is higher
1822          * (always on top vs always below) */
1823         if (!ec || (cec->layer > ec->layer))
1824           ec = cec;
1825      }
1826    return ec;
1827 }
1828
1829 static E_Client *
1830 _e_client_under_pointer_input_helper(E_Desk *desk, int x, int y)
1831 {
1832    E_Client *ec = NULL, *cec;
1833
1834    E_CLIENT_REVERSE_FOREACH(cec)
1835      {
1836         if (_e_client_under_pointer_helper_ignore_client(desk, cec)) continue;
1837
1838         Eina_List *list = NULL;
1839         Eina_Rectangle *rect;
1840         Eina_Bool inside = EINA_FALSE;
1841         e_comp_object_input_rect_get(cec->frame, &list);
1842         if (list)
1843           {
1844              EINA_LIST_FREE(list, rect)
1845                {
1846                   if (E_INSIDE(x, y, rect->x, rect->y, rect->w, rect->h))
1847                     inside = EINA_TRUE;
1848                }
1849           }
1850         else if (E_INSIDE(x, y, cec->x, cec->y, cec->w, cec->h))
1851           {
1852              inside = EINA_TRUE;
1853           }
1854
1855         if (!inside) continue;
1856         /* If the layer is higher, the position of the window is higher
1857          * (always on top vs always below) */
1858         if (!ec || (cec->layer > ec->layer))
1859           ec = cec;
1860      }
1861
1862    return ec;
1863 }
1864
1865 ////////////////////////////////////////////////
1866
1867 static void
1868 _e_client_zones_layout_calc(E_Client *ec, int *zx, int *zy, int *zw, int *zh)
1869 {
1870    int x, y, w, h;
1871    E_Zone *zone_above, *zone_below, *zone_left, *zone_right;
1872    E_Zone *zone;
1873
1874    zone = e_comp_zone_find_by_ec(ec);
1875    if (!zone) return;
1876    x = zone->x;
1877    y = zone->y;
1878    w = zone->w;
1879    h = zone->h;
1880
1881    if (eina_list_count(e_comp->zones) == 1)
1882      {
1883         if (zx) *zx = x;
1884         if (zy) *zy = y;
1885         if (zw) *zw = w;
1886         if (zh) *zh = h;
1887         return;
1888      }
1889
1890    zone_left = e_comp_zone_xy_get((x - w + 5), y);
1891    zone_right = e_comp_zone_xy_get((x + w + 5), y);
1892    zone_above = e_comp_zone_xy_get(x, (y - h + 5));
1893    zone_below = e_comp_zone_xy_get(x, (y + h + 5));
1894
1895    if (!(zone_above) && (y))
1896      zone_above = e_comp_zone_xy_get(x, (h - 5));
1897
1898    if (!(zone_left) && (x))
1899      zone_left = e_comp_zone_xy_get((x - 5), y);
1900
1901    if (zone_right)
1902      w = zone_right->x + zone_right->w;
1903
1904    if (zone_left)
1905      w = zone->x + zone->w;
1906
1907    if (zone_below)
1908      h = zone_below->y + zone_below->h;
1909
1910    if (zone_above)
1911      h = zone->y + zone->h;
1912
1913    if ((zone_left) && (zone_right))
1914      w = zone->w + zone_right->x;
1915
1916    if ((zone_above) && (zone_below))
1917      h = zone->h + zone_below->y;
1918
1919    if (x) x -= zone->w;
1920    if (y) y -= zone->h;
1921
1922    if (zx) *zx = x > 0 ? x : 0;
1923    if (zy) *zy = y > 0 ? y : 0;
1924    if (zw) *zw = w;
1925    if (zh) *zh = h;
1926 }
1927
1928 static void
1929 _e_client_stay_within_canvas(E_Client *ec, int x, int y, int *new_x, int *new_y)
1930 {
1931    int new_x_max, new_y_max;
1932    int zw, zh;
1933    Eina_Bool lw, lh;
1934    E_Zone *zone;
1935
1936    zone = e_comp_zone_find_by_ec(ec);
1937    if (!zone)
1938      {
1939         if (new_x) *new_x = x;
1940         if (new_y) *new_y = y;
1941         return;
1942      }
1943
1944    _e_client_zones_layout_calc(ec, NULL, NULL, &zw, &zh);
1945
1946    new_x_max = zw - ec->w;
1947    new_y_max = zh - ec->h;
1948    lw = ec->w > zw ? EINA_TRUE : EINA_FALSE;
1949    lh = ec->h > zh ? EINA_TRUE : EINA_FALSE;
1950
1951    if (lw)
1952      {
1953         if (x <= new_x_max)
1954           *new_x = new_x_max;
1955         else if (x >= 0)
1956           *new_x = 0;
1957      }
1958    else
1959      {
1960         if (x >= new_x_max)
1961           *new_x = new_x_max;
1962         else if (x <= 0)
1963           *new_x = 0;
1964      }
1965
1966    if (lh)
1967      {
1968         if (y <= new_y_max)
1969           *new_y = new_y_max;
1970         else if (y >= 0)
1971           *new_y = 0;
1972      }
1973    else
1974      {
1975         if (y >= new_y_max)
1976           *new_y = new_y_max;
1977         else if (y <= 0)
1978           *new_y = 0;
1979      }
1980 }
1981
1982 static void
1983 _e_client_stay_within_canvas_margin(E_Client *ec, int x, int y, int *new_x, int *new_y)
1984 {
1985    int new_x_max, new_y_max, new_x_min, new_y_min;
1986    int margin_w, margin_h;
1987    int zw, zh;
1988    int cw, ch;
1989    E_Zone *zone;
1990
1991    zone = e_comp_zone_find_by_ec(ec);
1992    if (!zone)
1993      {
1994         if (new_x) *new_x = x;
1995         if (new_y) *new_y = y;
1996         return;
1997      }
1998
1999    cw = ec->w;
2000    ch = ec->h;
2001
2002    _e_client_zones_layout_calc(ec, NULL, NULL, &zw, &zh);
2003
2004    margin_w = zw/3;
2005    margin_h = zh/10;
2006
2007    new_x_min = (margin_w > cw) ? 0 : -(cw - margin_w);
2008    new_x_max = (margin_w > cw) ? (zw - cw) : (zw - margin_w);
2009    new_y_min = (margin_h > ch) ? 0 : -(ch - margin_h);
2010    new_y_max = (margin_h > ch) ? (zh - ch) : (zh - margin_h);
2011
2012    if (x >= new_x_max)
2013      *new_x = new_x_max;
2014    else if (x <= new_x_min)
2015      *new_x = new_x_min;
2016
2017    if (y >= new_y_max)
2018      *new_y = new_y_max;
2019    else if (y <= new_y_min)
2020      *new_y = new_y_min;
2021
2022 }
2023
2024 ////////////////////////////////////////////////
2025
2026 static void
2027 _e_client_transform_core_activate_set(E_Client *ec, Eina_Bool set)
2028 {
2029    if (ec->transform_core.activate == set) return;
2030
2031    ec->transform_core.activate = set;
2032
2033    if (set)
2034      {
2035         if (ec->transform_core.result.enable)
2036           e_client_map_enable_set(ec, EINA_TRUE);
2037      }
2038    else
2039      {
2040         e_client_map_enable_set(ec, EINA_FALSE);
2041      }
2042 }
2043
2044 static void
2045 _e_client_cb_evas_hide(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2046 {
2047    E_Client *ec = data;
2048
2049    if (stopping) return; //ignore all of this if we're shutting down!
2050    if (e_object_is_del(data)) return; //client is about to die
2051    if (ec->cur_mouse_action)
2052      {
2053         if (ec->cur_mouse_action->func.end_mouse)
2054           ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", NULL);
2055         else if (ec->cur_mouse_action->func.end)
2056           ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
2057         E_FREE_FUNC(ec->cur_mouse_action, e_object_unref);
2058      }
2059    if (action_client == ec) _e_client_action_finish();
2060
2061    ec->want_focus = ec->take_focus = 0;
2062
2063    _e_client_transform_core_activate_set(ec, EINA_FALSE);
2064
2065    if (ec->new_client) return;
2066    _e_client_event_hide(ec);
2067
2068    e_client_focus_check_set(ec, EINA_TRUE);
2069    EC_CHANGED(ec);
2070 }
2071
2072 static void
2073 _e_client_cb_evas_move(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2074 {
2075    E_Client *ec = data;
2076    E_Map *map;
2077    Evas_Coord x, y;
2078
2079    if (e_object_is_del(data)) return;
2080
2081    ec->pre_res_change.valid = 0;
2082
2083    _e_client_event_simple(ec, E_EVENT_CLIENT_MOVE);
2084
2085    evas_object_geometry_get(ec->frame, &x, &y, NULL, NULL);
2086    if ((e_config->transient.move) && (ec->transients))
2087      {
2088         Eina_List *list = eina_list_clone(ec->transients);
2089         E_Client *child;
2090
2091         EINA_LIST_FREE(list, child)
2092           {
2093              if (child->vkbd.vkbd) continue;
2094
2095              evas_object_move(child->frame,
2096                               child->x + x - ec->pre_cb.x,
2097                               child->y + y - ec->pre_cb.y);
2098           }
2099      }
2100    if (ec->moving || (ecmove == ec))
2101      {
2102         wl_signal_emit(&PRI(ec)->events.move_resize_update, NULL);
2103         _e_client_hook_call(E_CLIENT_HOOK_MOVE_UPDATE, ec);
2104      }
2105
2106    if ((!ec->moving) && (ec->transformed))
2107      {
2108         map = e_client_map_get(ec);
2109         _e_client_transform_geometry_save(ec, map);
2110         e_map_free(map);
2111      }
2112
2113    ec->pre_cb.x = x; ec->pre_cb.y = y;
2114
2115    wl_signal_emit(&PRI(ec)->events.move, NULL);
2116
2117    e_comp_visibility_calculation_set(EINA_TRUE);
2118 }
2119
2120 static void
2121 _e_client_cb_evas_resize(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2122 {
2123    E_Client *ec = data;
2124    Evas_Coord x, y, w, h;
2125
2126    if (e_object_is_del(data)) return;
2127
2128    ec->pre_res_change.valid = 0;
2129
2130    _e_client_event_simple(ec, E_EVENT_CLIENT_RESIZE);
2131
2132    evas_object_geometry_get(ec->frame, &x, &y, &w, &h);
2133    if ((e_config->transient.resize) && (ec->transients))
2134      {
2135         Eina_List *list = eina_list_clone(ec->transients);
2136         E_Client *child;
2137
2138         EINA_LIST_FREE(list, child)
2139           {
2140              Evas_Coord nx, ny, nw, nh;
2141
2142              if ((ec->pre_cb.w > 0) && (ec->pre_cb.h > 0))
2143                {
2144                   nx = x + (((child->x - x) * w) / ec->pre_cb.w);
2145                   ny = y + (((child->y - y) * h) / ec->pre_cb.h);
2146                   nw = (child->w * w) / ec->pre_cb.w;
2147                   nh = (child->h * h) / ec->pre_cb.h;
2148                   nx += ((nw - child->w) / 2);
2149                   ny += ((nh - child->h) / 2);
2150                   evas_object_move(child->frame, nx, ny);
2151                }
2152           }
2153      }
2154
2155    if (e_client_util_resizing_get(ec) || (ecresize == ec))
2156      {
2157          wl_signal_emit(&PRI(ec)->events.move_resize_update, NULL);
2158         _e_client_hook_call(E_CLIENT_HOOK_RESIZE_UPDATE, ec);
2159      }
2160    ec->pre_cb.w = w; ec->pre_cb.h = h;
2161
2162    e_client_transform_core_update(ec);
2163    e_comp_visibility_calculation_set(EINA_TRUE);
2164 }
2165
2166 static void
2167 _e_client_cb_evas_show(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2168 {
2169    E_Client *ec = data;
2170
2171    if (e_object_is_del(data)) return;
2172
2173    _e_client_transform_core_activate_set(ec, EINA_TRUE);
2174
2175    _e_client_event_show(ec);
2176
2177    e_client_focus_check_set(ec, EINA_TRUE);
2178    EC_CHANGED(ec);
2179 }
2180
2181 static void
2182 _e_client_cb_evas_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
2183 {
2184    E_Client *ec = data;
2185    E_Comp_Wl_Client_Data *child_cdata = NULL;
2186
2187    if (e_object_is_del(data)) return;
2188    if (ec->layer_block) return;
2189    if (ec->layer_pending) return;
2190    if (e_config->transient.raise && ec->transients)
2191      {
2192         Eina_List *list = eina_list_clone(ec->transients);
2193         E_Client *child, *below = NULL, *above = NULL;
2194         E_Transient transient_policy;
2195
2196         E_LIST_REVERSE_FREE(list, child)
2197           {
2198              child_cdata = e_client_cdata_get(child);
2199              if (child_cdata && !child_cdata->mapped)
2200                {
2201                   ELOGF("COMP", "STACK CHANGE CHILD. BUT not mapped. skip. child(ec:%p, win:0x%08zx)", ec, child, e_client_util_win_get(child));
2202                   continue;
2203                }
2204
2205              /* Don't stack iconic transients. If the user wants these shown,
2206               * that's another option.
2207               */
2208              if (child->iconic && e_client_is_iconified_by_client(child)) continue;
2209
2210              transient_policy = e_client_transient_policy_get(child);
2211              if (transient_policy == E_TRANSIENT_ABOVE)
2212                {
2213                   if (below)
2214                     e_client_stack_below(child, below);
2215                   else
2216                     e_client_stack_above(child, ec);
2217                   below = child;
2218                }
2219              else if (transient_policy == E_TRANSIENT_BELOW)
2220                {
2221                   if (above)
2222                     e_client_stack_below(child, above);
2223                   else
2224                     e_client_stack_below(child, ec);
2225                   above = child;
2226                }
2227
2228           }
2229      }
2230
2231    _e_client_event_simple(ec, E_EVENT_CLIENT_STACK);
2232
2233    e_client_focus_check_set(ec, EINA_TRUE);
2234    EC_CHANGED(ec);
2235
2236    e_comp_visibility_calculation_set(EINA_TRUE);
2237 }
2238
2239 ////////////////////////////////////////////////
2240 static void
2241 _e_client_aux_hint_eval(E_Client *ec)
2242 {
2243    if (!ec) return;
2244
2245    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
2246    Eina_List *l, *ll;
2247    E_Comp_Wl_Aux_Hint *hint;
2248
2249    if (cdata && cdata->aux_hint.changed)
2250      {
2251         wl_signal_emit(&PRI(ec)->events.aux_hint_change, NULL);
2252         _e_client_hook_call(E_CLIENT_HOOK_AUX_HINT_CHANGE, ec);
2253
2254         EINA_LIST_FOREACH_SAFE(cdata->aux_hint.hints, l, ll, hint)
2255           {
2256              hint->changed = EINA_FALSE;
2257              if (hint->deleted)
2258                {
2259                   ELOGF("COMP", "AUX_HINT |Del [%d:%s:%s]", ec, hint->id, hint->hint, hint->val);
2260                   if (hint->hint) eina_stringshare_del(hint->hint);
2261                   if (hint->val) eina_stringshare_del(hint->val);
2262                   cdata->aux_hint.hints = eina_list_remove_list(cdata->aux_hint.hints, l);
2263                   E_FREE(hint);
2264                }
2265           }
2266         cdata->aux_hint.changed = 0;
2267      }
2268 }
2269
2270 static void
2271 _e_client_eval(E_Client *ec)
2272 {
2273    int send_event = 1;
2274    unsigned int prop = 0;
2275    int tx, ty;
2276
2277    if (e_object_is_del(E_OBJECT(ec)))
2278      {
2279         CRI("_e_client_eval(%p) with deleted border! - %d\n", ec, ec->new_client);
2280         ec->changed = 0;
2281         return;
2282      }
2283
2284    TRACE_DS_BEGIN(CLIENT:EVAL);
2285
2286    wl_signal_emit(&PRI(ec)->events.eval_pre_new_client, NULL);
2287    if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_PRE_NEW_CLIENT, ec))
2288      {
2289         TRACE_DS_END();
2290         return;
2291      }
2292
2293    if ((ec->new_client) && (!e_client_util_ignored_get(ec)))
2294      {
2295         wl_signal_emit(&PRI(ec)->events.eval_post_new_client, NULL);
2296         if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_POST_NEW_CLIENT, ec))
2297           {
2298              TRACE_DS_END();
2299              return;
2300           }
2301      }
2302
2303    if (ec->changes.size)
2304      {
2305         ec->changes.size = 0;
2306         evas_object_resize(ec->frame, ec->w, ec->h);
2307
2308         prop |= E_CLIENT_PROPERTY_SIZE;
2309      }
2310    if (ec->changes.pos)
2311      {
2312         ec->changes.tz_position = 0;
2313         ec->changes.pos = 0;
2314         evas_object_move(ec->frame, ec->x, ec->y);
2315         prop |= E_CLIENT_PROPERTY_POS;
2316      }
2317
2318    if (ec->changes.reset_gravity)
2319      {
2320         ec->changes.reset_gravity = 0;
2321         prop |= E_CLIENT_PROPERTY_GRAVITY;
2322      }
2323
2324    if (ec->changes.title)
2325      {
2326         ec->changes.title = 0;
2327         prop |= E_CLIENT_PROPERTY_TITLE;
2328      }
2329
2330    if ((ec->changes.visible) && (ec->visible) && (ec->new_client) && (!ec->iconic))
2331      {
2332         int x, y;
2333
2334         e_input_device_pointer_xy_get(NULL, &x, &y);
2335         if ((!ec->placed) && (!ec->re_manage) &&
2336             (e_config->window_placement_policy == E_WINDOW_PLACEMENT_MANUAL) &&
2337             (!((ec->icccm.transient_for != 0) ||
2338                (ec->dialog))) &&
2339             (!ecmove) && (!ecresize))
2340           {
2341              /* Set this window into moving state */
2342
2343              ec->cur_mouse_action = e_action_find("window_move");
2344              if (ec->cur_mouse_action)
2345                {
2346                   if ((!ec->cur_mouse_action->func.end_mouse) &&
2347                       (!ec->cur_mouse_action->func.end))
2348                     ec->cur_mouse_action = NULL;
2349                   if (ec->cur_mouse_action)
2350                     {
2351                        int t;
2352                        tx = x - (ec->w >> 1);
2353                        e_comp_object_frame_geometry_get(ec->frame, NULL, NULL, &t, NULL);
2354                        ty = y - (t >> 1);
2355                        e_client_pos_set(ec, tx, ty);
2356                        EC_CHANGED(ec);
2357                        ec->changes.pos = 1;
2358                     }
2359                }
2360           }
2361
2362         evas_object_show(ec->frame);
2363         if (evas_object_visible_get(ec->frame))
2364           {
2365              ec->changes.visible = 0;
2366              _e_client_event_show(ec);
2367           }
2368      }
2369    else if ((ec->changes.visible) && (ec->new_client))
2370      {
2371         ec->changes.visible = 0;
2372         if (!ec->iconic)
2373           _e_client_event_hide(ec);
2374      }
2375
2376    if (ec->changes.icon)
2377      {
2378         ec->changes.icon = 0;
2379      }
2380
2381    if (ec->new_client)
2382      e_comp->new_clients--;
2383    ec->new_client = 0;
2384    ec->changed = ec->changes.pos || ec->changes.size ||
2385                  ec->changes.stack || ec->changes.prop || ec->changes.border ||
2386                  ec->changes.reset_gravity ||
2387                  ec->changes.shape || ec->changes.shape_input || ec->changes.icon ||
2388                  ec->changes.internal_state ||
2389                  ec->changes.need_maximize || ec->changes.need_unmaximize ||
2390                  e_client_focus_check_get(ec);
2391    ec->changes.stack = 0;
2392
2393    if (ec->changes.need_maximize)
2394      {
2395         E_Maximize max = ec->maximized;
2396         ec->maximized = E_MAXIMIZE_NONE;
2397         e_client_maximize(ec, max);
2398         ec->changes.need_maximize = 0;
2399      }
2400    else if (ec->changes.need_unmaximize)
2401      {
2402         e_client_unmaximize(ec, ec->maximized);
2403         ec->changes.need_unmaximize = 0;
2404      }
2405
2406    if (ec->need_fullscreen)
2407      {
2408         e_client_fullscreen(ec, e_config->fullscreen_policy);
2409         ec->need_fullscreen = 0;
2410      }
2411
2412    if (ec->changes.accepts_focus)
2413      {
2414         if ((!ec->icccm.accepts_focus) && (!ec->icccm.take_focus))
2415           {
2416              if (!ec->focused)
2417                ec->changes.accepts_focus = 0;
2418           }
2419      }
2420
2421    if (send_event && prop)
2422      {
2423         _e_client_event_property(ec, prop);
2424      }
2425
2426    _e_client_aux_hint_eval(ec);
2427
2428    e_client_transform_core_update(ec);
2429
2430    wl_signal_emit(&PRI(ec)->events.eval_end, NULL);
2431    _e_client_hook_call(E_CLIENT_HOOK_EVAL_END, ec);
2432
2433    TRACE_DS_END();
2434 }
2435
2436 EINTERN void
2437 e_client_frame_update(E_Client *ec)
2438 {
2439    const char *bordername;
2440
2441    EINA_SAFETY_ON_NULL_RETURN(ec);
2442    if (e_object_is_del(E_OBJECT(ec))) return;
2443
2444    ec->border.changed = 0;
2445    if (!e_comp_object_frame_allowed(ec->frame)) return;
2446    if (ec->fullscreen || ec->borderless)
2447      bordername = "borderless";
2448    else if (ec->bordername)
2449      bordername = ec->bordername;
2450    else if (((ec->icccm.transient_for != 0) || (ec->dialog)) &&
2451             (ec->icccm.min_w == ec->icccm.max_w) &&
2452             (ec->icccm.min_h == ec->icccm.max_h))
2453      bordername = "noresize_dialog";
2454    else if ((ec->icccm.min_w == ec->icccm.max_w) &&
2455             (ec->icccm.min_h == ec->icccm.max_h))
2456      bordername = "noresize";
2457    else if (ec->shaped)
2458      bordername = "shaped";
2459    else if ((ec->netwm.state.skip_taskbar) ||
2460             (ec->netwm.state.skip_pager))
2461      bordername = "skipped";
2462   /*
2463    else if ((ec->internal) && (ec->icccm.class) &&
2464             (!strncmp(ec->icccm.class, "e_fwin", 6)))
2465      bordername = "internal_fileman";
2466   */
2467    else
2468      bordername = e_config->theme_default_border_style;
2469    if (!bordername) bordername = "default";
2470 }
2471
2472 static Eina_Bool
2473 _e_client_type_match(E_Client *ec, E_Config_Client_Type *m)
2474 {
2475    if (!ec || !m) return EINA_FALSE;
2476    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
2477
2478    if ((int)ec->netwm.type != m->window_type)
2479      return EINA_FALSE;
2480
2481 #if defined(__cplusplus) || defined(c_plusplus)
2482    if (m->clas)
2483      {
2484         if (!ec->icccm.cpp_class)
2485           return EINA_FALSE;
2486
2487         if (!e_util_glob_match(ec->icccm.cpp_class, m->clas))
2488           return EINA_FALSE;
2489      }
2490 #else
2491    if (m->clas)
2492      {
2493         if (!ec->icccm.class)
2494           return EINA_FALSE;
2495
2496         if (!e_util_glob_match(ec->icccm.class, m->clas))
2497           return EINA_FALSE;
2498      }
2499 #endif
2500
2501    if (m->name)
2502      {
2503         if (ec->icccm.name && e_util_glob_match(ec->icccm.name, m->name))
2504           return EINA_TRUE;
2505
2506         if (ec->icccm.title && e_util_glob_match(ec->icccm.title, m->name))
2507           return EINA_TRUE;
2508
2509         if (ec->netwm.name && e_util_glob_match(ec->netwm.name, m->name))
2510           return EINA_TRUE;
2511      }
2512
2513    return EINA_FALSE;
2514 }
2515
2516 EINTERN int
2517 e_client_type_update(E_Client *ec)
2518 {
2519    E_Config_Client_Type *m;
2520    Eina_List *l;
2521    int type = 0;
2522
2523    if (!e_config->client_types) return 0;
2524
2525    EINA_LIST_FOREACH(e_config->client_types, l, m)
2526      {
2527         if (!_e_client_type_match(ec, m)) continue;
2528         else
2529           {
2530              type = m->client_type;
2531              break;
2532           }
2533      }
2534
2535    if (ec->client_type != type)
2536      {
2537         ec->client_type = type;
2538         _e_client_event_property(ec, E_CLIENT_PROPERTY_CLIENT_TYPE);
2539      }
2540
2541    return ec->client_type;
2542 }
2543
2544 static void
2545 _e_client_transform_sub_apply(E_Client *ec, E_Client *epc, double zoom)
2546 {
2547    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
2548    E_Client *subc;
2549    Eina_List *l;
2550    int px = 0, py = 0;
2551    int ox = 0, oy = 0, ow, oh;
2552    int mx, my, mw, mh;
2553    E_Map *map;
2554
2555    EINA_SAFETY_ON_FALSE_RETURN(e_comp_wl_subsurface_check(ec));
2556
2557    e_comp_wl_subsurface_position_get(ec, &ox, &oy);
2558    ow = cdata->width_from_viewport;
2559    oh = cdata->height_from_viewport;
2560
2561    map = e_client_map_get(epc);
2562    e_map_point_coord_get(map, 0, &px, &py, 0);
2563    e_map_free(map);
2564
2565    mx = ox * zoom + px;
2566    my = oy * zoom + py;
2567    mw = ow * zoom;
2568    mh = oh * zoom;
2569
2570    map = e_map_new_with_direct_render(ec->transform_core.direct_render);
2571    e_map_util_points_populate_from_geometry(map, mx, my, mw, mh, 0);
2572    e_map_util_object_move_sync_set(map, EINA_TRUE);
2573    e_client_map_set(ec, map);
2574    e_client_map_enable_set(ec, EINA_TRUE);
2575
2576    EINA_LIST_FOREACH(cdata->sub.list, l, subc)
2577      _e_client_transform_sub_apply(subc, ec, zoom);
2578    EINA_LIST_REVERSE_FOREACH(cdata->sub.below_list, l, subc)
2579      _e_client_transform_sub_apply(subc, ec, zoom);
2580
2581    e_map_free(map);
2582 }
2583
2584 static void
2585 _e_client_transient_for_group_make(E_Client *ec, Eina_List **list)
2586 {
2587    E_Client *child;
2588    Eina_List *l;
2589
2590    if (!ec) return;
2591    if (!e_config->transient.raise) return;
2592
2593    EINA_LIST_FOREACH(ec->transients, l, child)
2594      {
2595         if (!child) continue;
2596         if (child->iconic) continue;
2597         if (e_client_transient_policy_get(child) == E_TRANSIENT_ABOVE)
2598           {
2599              *list = eina_list_prepend(*list, child);
2600              _e_client_transient_for_group_make(child, list);
2601           }
2602      }
2603 }
2604
2605 EINTERN E_Client *
2606 e_client_transient_child_top_get(E_Client *ec, Eina_Bool consider_focus)
2607 {
2608    E_Client *top_ec = NULL;
2609    Eina_List *transient_list = NULL;
2610
2611    _e_client_transient_for_group_make(ec, &transient_list);
2612
2613    if (transient_list)
2614      {
2615         Eina_List *l = NULL;
2616         E_Client *temp_ec = NULL;
2617         E_Client *temp_ec2 = NULL;
2618
2619         E_CLIENT_REVERSE_FOREACH(temp_ec)
2620           {
2621              if (top_ec) break;
2622              if (temp_ec == ec)
2623                {
2624                   top_ec = ec;
2625                   break;
2626                }
2627
2628              EINA_LIST_FOREACH(transient_list, l, temp_ec2)
2629                {
2630                   if (temp_ec == temp_ec2)
2631                     {
2632                        if (consider_focus)
2633                          {
2634                             if ((temp_ec2->icccm.accepts_focus) ||
2635                                 (temp_ec2->icccm.take_focus))
2636                               {
2637                                  top_ec = temp_ec2;
2638                               }
2639                          }
2640                        else
2641                          {
2642                             top_ec = temp_ec2;
2643                          }
2644                        break;
2645                     }
2646                }
2647           }
2648         eina_list_free(transient_list);
2649      }
2650    return top_ec;
2651 }
2652
2653 #ifdef EC_IS_NOT_VISIBLE
2654 # undef EC_IS_NOT_VISIBLE
2655 #endif
2656 #define EC_IS_NOT_VISIBLE if (e_client_visibility_get(ec) != E_VISIBILITY_UNOBSCURED)
2657
2658 EINTERN Eina_Bool
2659 e_client_visibility_touched_check(E_Client *ec)
2660 {
2661    int tx, ty;
2662
2663    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
2664
2665    tx = wl_fixed_to_int(e_comp->wl_comp_data->ptr.x);
2666    ty = wl_fixed_to_int(e_comp->wl_comp_data->ptr.y);
2667
2668    return _e_client_position_inside_input_rect(ec, tx, ty);
2669 }
2670
2671 EINTERN void
2672 e_client_visibility_change_notify(E_Client *ec)
2673 {
2674    EINA_SAFETY_ON_NULL_RETURN(ec);
2675
2676    if (ec->visibility.changed)
2677      _e_client_event_simple(ec, E_EVENT_CLIENT_VISIBILITY_CHANGE);
2678
2679    wl_signal_emit(&PRI(ec)->events.eval_visibility, NULL);
2680    _e_client_hook_call(E_CLIENT_HOOK_EVAL_VISIBILITY, ec);
2681 }
2682
2683 EINTERN void
2684 e_client_visibility_end_notify(void)
2685 {
2686    // FIXME: This hook means that the visiblitiy calculation of a zone is done
2687    //        at this idle handler.This is a hook for a zone, not for a client.
2688    //        Therefore, this hook may be defined as a zone hook,
2689    //        ex) E_ZONE_HOOK_EVAL_VISIBILITY_END or E_ZONE_HOOK_EVAL_VISIBILITY_DONE.
2690    _e_client_hook_call(E_CLIENT_HOOK_EVAL_VISIBILITY_END, NULL);
2691 }
2692
2693 EINTERN E_Visibility
2694 e_client_visibility_get(E_Client *ec)
2695 {
2696    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, E_VISIBILITY_UNKNOWN);
2697
2698    return ec->visibility.obscured;
2699 }
2700
2701 static void
2702 _e_input_thread_client_visibility_set(void *data)
2703 {
2704    E_Input_Thread_Request_EClient_Data *ec_data = data;
2705    EINA_SAFETY_ON_NULL_RETURN(ec_data);
2706
2707    INF("[input thread|%s] ec(%p), visibility(%d)\n", __func__, ec_data->ec, ec_data->visibility);
2708    e_input_thread_client_visibility_set(e_input_thread_client_get(ec_data->ec), ec_data->visibility);
2709 }
2710
2711 EINTERN void
2712 e_client_visibility_set(E_Client *ec, E_Visibility visibility)
2713 {
2714    E_Input_Thread_Request_EClient_Data ec_data;
2715    memset(&ec_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
2716
2717    EINA_SAFETY_ON_NULL_RETURN(ec);
2718
2719    if (e_client_visibility_get(ec) == visibility) return;
2720
2721    ec->visibility.obscured = visibility;
2722
2723    ec_data.ec = ec;
2724    ec_data.visibility = ec->visibility.obscured;
2725
2726    INF("[%s] ec(%p), visibility(%d)\n", __func__, ec, ec->visibility.obscured);
2727    e_input_thread_safe_call(_e_input_thread_client_visibility_set, &ec_data, sizeof(E_Input_Thread_Request_EClient_Data));
2728 }
2729
2730 static Eina_Bool
2731 _e_client_transform_core_check_change(E_Client *ec)
2732 {
2733    int w = 0;
2734    int h = 0;
2735    Eina_Bool check = EINA_FALSE;
2736    if (!ec) return EINA_FALSE;
2737
2738    if (ec->frame)
2739      evas_object_geometry_get(ec->frame, 0, 0, &w, &h);
2740
2741    // check client position or size change
2742    if (ec->x != ec->transform_core.backup.client_x ||
2743        ec->y != ec->transform_core.backup.client_y ||
2744        ec->w != ec->transform_core.backup.client_w ||
2745        ec->h != ec->transform_core.backup.client_h ||
2746        w     != ec->transform_core.backup.frame_w ||
2747        h     != ec->transform_core.backup.frame_h ||
2748        ec->argb != ec->transform_core.backup.argb)
2749      {
2750         check = EINA_TRUE;
2751         ec->transform_core.backup.client_x = ec->x;
2752         ec->transform_core.backup.client_y = ec->y;
2753         ec->transform_core.backup.client_w = ec->w;
2754         ec->transform_core.backup.client_h = ec->h;
2755         ec->transform_core.backup.frame_w = w;
2756         ec->transform_core.backup.frame_h = h;
2757         ec->transform_core.backup.argb = ec->argb;
2758      }
2759
2760    // check new transform or del transform
2761    if (ec->transform_core.changed)
2762      {
2763         check = EINA_TRUE;
2764         ec->transform_core.changed = EINA_FALSE;
2765      }
2766
2767    // check each transform change
2768    if (ec->transform_core.transform_list)
2769      {
2770         Eina_List *l;
2771         Eina_List *l_next;
2772         E_Util_Transform *transform;
2773
2774         EINA_LIST_FOREACH_SAFE(ec->transform_core.transform_list, l, l_next, transform)
2775           {
2776              // del transform check
2777              if (e_util_transform_ref_count_get(transform) <= 1)
2778                {
2779                   ec->transform_core.transform_list = eina_list_remove(ec->transform_core.transform_list, transform);
2780                   e_util_transform_unref(transform);
2781                   check = EINA_TRUE;
2782                   continue;
2783                }
2784
2785              // transform change test
2786              if (e_util_transform_change_get(transform))
2787                {
2788                   check = EINA_TRUE;
2789                   e_util_transform_change_unset(transform);
2790                }
2791           }
2792      }
2793
2794    if (e_comp_wl_subsurface_check(ec))
2795      {
2796         // check parent matrix change
2797         E_Client *parent = e_comp_wl_subsurface_parent_get(ec);
2798         if (parent && parent->transform_core.result.enable)
2799           {
2800              ec->transform_core.parent.enable = EINA_TRUE;
2801
2802              if (!e_util_transform_matrix_equal_check(&ec->transform_core.parent.matrix,
2803                                                       &parent->transform_core.result.matrix))
2804                {
2805                   check = EINA_TRUE;
2806                   ec->transform_core.parent.matrix = parent->transform_core.result.matrix;
2807                }
2808              if (memcmp(&ec->transform_core.parent.zoom, &parent->transform_core.result.transform.zoom, sizeof(E_Util_Transform_Zoom)) != 0)
2809                {
2810                   check = EINA_TRUE;
2811                   ec->transform_core.parent.zoom = parent->transform_core.result.transform.zoom;
2812                }
2813           }
2814         else if (ec->transform_core.parent.enable)
2815           {
2816              ec->transform_core.parent.enable = EINA_FALSE;
2817              e_util_transform_matrix_load_identity(&ec->transform_core.parent.matrix);
2818              ec->transform_core.parent.zoom.zoom_x = 1.0;
2819              ec->transform_core.parent.zoom.zoom_y = 1.0;
2820              ec->transform_core.parent.zoom.cx = 0;
2821              ec->transform_core.parent.zoom.cy = 0;
2822              check = EINA_TRUE;
2823           }
2824      }
2825
2826    return check;
2827 }
2828
2829 static void
2830 _e_client_transform_core_boundary_update(E_Client *ec, E_Util_Transform_Rect_Vertex *vertices)
2831 {
2832    int minx = 99999, miny = 99999;
2833    int maxx = -99999, maxy = -99999;
2834    int x, y;
2835    int i;
2836
2837    if (!ec) return;
2838    if (!ec->frame) return;
2839    if (!ec->transform_core.result.enable) return;
2840    if (!vertices) return;
2841
2842    for (i = 0; i < 4; ++i)
2843      {
2844         x = 0;
2845         y = 0;
2846
2847         e_util_transform_vertices_pos_round_get(vertices, i, &x, &y, 0, 0);
2848
2849         if (x < minx) minx = x;
2850         if (y < miny) miny = y;
2851         if (x > maxx) maxx = x;
2852         if (y > maxy) maxy = y;
2853      }
2854
2855    ec->transform_core.result.boundary.x = minx;
2856    ec->transform_core.result.boundary.y = miny;
2857    ec->transform_core.result.boundary.w = maxx - minx;
2858    ec->transform_core.result.boundary.h = maxy - miny;
2859
2860    ELOGF("COMP", "[Transform][boundary][%d %d %d %d]",
2861          ec,
2862          ec->transform_core.result.boundary.x,
2863          ec->transform_core.result.boundary.y,
2864          ec->transform_core.result.boundary.w,
2865          ec->transform_core.result.boundary.h);
2866 }
2867
2868 static E_Map *
2869 _e_client_transform_core_map_new(Evas_Object *obj,
2870                                  E_Util_Transform_Rect_Vertex *vertices,
2871                                  E_Util_Transform *transform,
2872                                  Eina_Bool direct_render)
2873 {
2874    E_Map *map;
2875    int i;
2876    int x, y;
2877    double u, v;
2878
2879    map = e_map_new_with_direct_render(direct_render);
2880    EINA_SAFETY_ON_NULL_RETURN_VAL(map, NULL);
2881
2882    e_map_util_points_populate_from_object_full(map, obj, 0);
2883    e_map_util_points_color_set(map, 255, 255, 255, 255);
2884
2885    for (i = 0 ; i < 4 ; ++i)
2886      {
2887         x = 0;
2888         y = 0;
2889
2890         e_util_transform_vertices_pos_round_get(vertices, i, &x, &y, 0, 0);
2891         e_map_point_coord_set(map, i, x, y, 1.0);
2892
2893         if (transform && e_util_transform_texcoord_flag_get(transform))
2894           {
2895              u = 0.0;
2896              v = 0.0;
2897
2898              e_util_transform_texcoord_get(transform, i, &u, &v);
2899              e_map_point_image_uv_set(map, i, u, v);
2900           }
2901      }
2902
2903    return map;
2904 }
2905
2906 static void
2907 _e_client_transform_core_vertices_apply_with_zoom(E_Client *ec,
2908                                         Evas_Object *obj,
2909                                         E_Util_Transform_Rect_Vertex *vertices,
2910                                         E_Util_Transform *transform,
2911                                         E_Util_Transform_Zoom zoom)
2912 {
2913    E_Map *map = NULL, *current_map = NULL;
2914
2915    if (!obj) return;
2916
2917    if (vertices)
2918      {
2919         if (!ec->transform_core.update_lock)
2920           {
2921              map = _e_client_transform_core_map_new(obj, vertices, transform,
2922                                                     ec->transform_core.direct_render);
2923              EINA_SAFETY_ON_NULL_RETURN(map);
2924
2925              e_map_util_zoom(map, zoom.zoom_x, zoom.zoom_y, zoom.cx, zoom.cy);
2926
2927              e_comp_object_map_set(obj, map);
2928           }
2929
2930         current_map = e_comp_object_map_get(obj);
2931
2932         if ((ec->transform_core.activate) && (current_map))
2933           e_comp_object_map_enable_set(obj, EINA_TRUE);
2934         else
2935           e_comp_object_map_enable_set(obj, EINA_FALSE);
2936
2937         if (map) e_map_free(map);
2938         if (current_map) e_map_free(current_map);
2939      }
2940    else
2941      evas_object_map_enable_set(obj, EINA_FALSE);
2942 }
2943
2944 static void
2945 _e_client_transform_core_vertices_apply(E_Client *ec,
2946                                         Evas_Object *obj,
2947                                         E_Util_Transform_Rect_Vertex *vertices,
2948                                         E_Util_Transform *transform)
2949 {
2950    E_Map *map = NULL, *current_map = NULL;
2951
2952    if (!obj) return;
2953
2954    if (vertices)
2955      {
2956         if (!ec->transform_core.update_lock)
2957           {
2958               map = _e_client_transform_core_map_new(obj, vertices, transform,
2959                                                      ec->transform_core.direct_render);
2960               EINA_SAFETY_ON_NULL_RETURN(map);
2961
2962               e_comp_object_map_set(obj, map);
2963           }
2964
2965         current_map = e_comp_object_map_get(obj);
2966
2967         if ((ec->transform_core.activate) && (current_map))
2968           e_comp_object_map_enable_set(obj, EINA_TRUE);
2969         else
2970           e_comp_object_map_enable_set(obj, EINA_FALSE);
2971
2972         if (map) e_map_free(map);
2973         if (current_map) e_map_free(current_map);
2974      }
2975    else
2976      evas_object_map_enable_set(obj, EINA_FALSE);
2977 }
2978
2979 static void
2980 _e_client_transform_core_sub_update(E_Client *ec, E_Util_Transform_Rect_Vertex *vertices)
2981 {
2982    Eina_List *l;
2983    E_Client *subc;
2984    E_Comp_Wl_Client_Data *cdata;
2985
2986    if (!ec) return;
2987
2988    cdata = e_client_cdata_get(ec);
2989    if (!cdata) return;
2990
2991    EINA_LIST_FOREACH(cdata->sub.list, l, subc)
2992       e_client_transform_core_update(subc);
2993
2994    EINA_LIST_FOREACH(cdata->sub.below_list, l, subc)
2995       e_client_transform_core_update(subc);
2996 }
2997
2998 static void
2999 _e_client_cb_hook_shell_surface_ready(void *data EINA_UNUSED, E_Client *ec)
3000 {
3001    if (EINA_UNLIKELY(!ec))
3002      return;
3003
3004    _e_client_aux_hint_eval(ec);
3005 }
3006
3007 // FIXME: This function has to be deleted and it remains for the backward compatibility.
3008 //        Please find and fix to use e_comp_visibility_calculation_set(EINA_TRUE)
3009 //        instead of e_client_visibility_calculate() call at e20 modules.
3010 E_API void
3011 e_client_visibility_calculate(void)
3012 {
3013    e_comp_visibility_calculation_set(EINA_TRUE);
3014 }
3015
3016 E_API void
3017 e_client_visibility_skip_set(E_Client *ec, Eina_Bool skip)
3018 {
3019    if (!ec) return;
3020
3021    ELOGF("POL_VIS", "visibility skip set to %d", ec, skip);
3022    ec->visibility.skip = skip;
3023 }
3024
3025 E_API void
3026 e_client_post_raise_lower_set(E_Client *ec, Eina_Bool raise_set, Eina_Bool lower_set)
3027 {
3028    if (!ec) return;
3029
3030    ec->post_raise = raise_set;
3031    ec->post_lower = lower_set;
3032 }
3033
3034 E_API Eina_Bool
3035 e_client_first_mapped_get(E_Client *ec)
3036 {
3037    if (!ec) return EINA_FALSE;
3038
3039    return ec->first_mapped;
3040 }
3041
3042 EINTERN Eina_Bool e_client_mapped_get(E_Client *ec)
3043 {
3044    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
3045    EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, EINA_FALSE);
3046
3047   return cdata->mapped;
3048 }
3049
3050 EINTERN void
3051 e_client_mapped_set(E_Client *ec, Eina_Bool set)
3052 {
3053    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
3054    EINA_SAFETY_ON_NULL_RETURN(cdata);
3055
3056    cdata->mapped = set;
3057 }
3058
3059 EINTERN void
3060 e_client_modal_child_set(E_Client *ec, E_Client *modal)
3061 {
3062    API_ENTRY;
3063
3064    E_Client *old_modal = priv->modal;
3065    if (old_modal == modal) return;
3066
3067    ELOGF("E_CLIENT", "SET modal. new(ec:%p, win:0x%08zx), old(ec:%p, win:0x%08zx)", ec,
3068          modal, e_client_util_win_get(modal), old_modal, e_client_util_win_get(old_modal));
3069
3070    // TODO: if ec has a modal window already, then how does we do?
3071    priv->modal = modal;
3072 }
3073
3074 EINTERN E_Client *
3075 e_client_modal_child_get(E_Client *ec)
3076 {
3077    API_ENTRY_VAL(NULL);
3078    return priv->modal;
3079 }
3080
3081 EINTERN void
3082 e_client_modal_state_set(E_Client *ec, Eina_Bool modal)
3083 {
3084    if (!ec) return;
3085    ec->netwm.state.modal = modal;
3086
3087    if (ec->parent)
3088      {
3089         if (ec->netwm.state.modal)
3090           e_client_modal_child_set(ec->parent, ec);
3091         else
3092           e_client_modal_child_set(ec->parent, NULL);
3093      }
3094 }
3095
3096 EINTERN Eina_Bool
3097 e_client_is_modal_state(E_Client *ec)
3098 {
3099    if (!ec) return EINA_FALSE;
3100    return ec->netwm.state.modal;
3101 }
3102
3103 ////////////////////////////////////////////////
3104 EINTERN Eina_Bool
3105 e_client_clients_hash_exist()
3106 {
3107   int pix_id;
3108
3109   for (pix_id = 0; pix_id < E_PIXMAP_TYPE_MAX; pix_id++)
3110     {
3111       if (eina_hash_population(clients_hash[pix_id]))
3112         return EINA_TRUE;
3113     }
3114
3115   return EINA_FALSE;
3116 }
3117
3118 EINTERN void
3119 e_client_idler_before(Eina_Bool *check_focus)
3120 {
3121    const Eina_List *l;
3122    E_Client *ec;
3123
3124    *check_focus = EINA_FALSE;
3125
3126    if (!e_client_clients_hash_exist()) return;
3127
3128    TRACE_DS_BEGIN(CLIENT:IDLE BEFORE);
3129
3130    EINA_LIST_FOREACH(e_comp->clients, l, ec)
3131      {
3132         // pass 1 - eval0. fetch properties on new or on change and
3133         // call hooks to decide what to do - maybe move/resize
3134         if (ec->ignored || (!ec->changed)) continue;
3135
3136         wl_signal_emit(&PRI(ec)->events.eval_pre_fetch, NULL);
3137         if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_PRE_FETCH, ec)) continue;
3138
3139
3140         /* FETCH is hooked by the compositor to get client hints */
3141         wl_signal_emit(&PRI(ec)->events.eval_fetch, NULL);
3142         if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_FETCH, ec)) continue;
3143
3144         if (ec->new_client)
3145           {
3146              e_client_type_update(ec);
3147           }
3148
3149         /* PRE_POST_FETCH calls e_remember apply for new client */
3150         wl_signal_emit(&PRI(ec)->events.eval_pre_post_fetch, NULL);
3151         if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_PRE_POST_FETCH, ec)) continue;
3152         wl_signal_emit(&PRI(ec)->events.eval_post_fetch, NULL);
3153         if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_POST_FETCH, ec)) continue;
3154         wl_signal_emit(&PRI(ec)->events.eval_pre_frame_assign, NULL);
3155         if (!_e_client_hook_call(E_CLIENT_HOOK_EVAL_PRE_FRAME_ASSIGN, ec)) continue;
3156
3157         wl_signal_emit(&PRI(ec)->events.eval_post_frame_assign, NULL);
3158         _e_client_hook_call(E_CLIENT_HOOK_EVAL_POST_FRAME_ASSIGN, ec);
3159      }
3160    // pass 2 - show and hide windows needing hide and eval (main eval)
3161    E_CLIENT_FOREACH(ec)
3162      {
3163         if (e_object_is_del(E_OBJECT(ec))) continue;
3164         if (ec->ignored)
3165           {
3166              // ignored client but needing eval (aux hint) such as remote surfaces
3167              if (ec->changed)
3168                {
3169                   E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
3170                   if (cdata && cdata->first_commit)
3171                     _e_client_aux_hint_eval(ec);
3172                }
3173              continue;
3174           }
3175
3176         if (ec->changes.visible)
3177           {
3178              if (ec->visible)
3179                {
3180                   if ((!ec->new_client) &&
3181                       (!ec->changes.pos) &&
3182                       (!ec->changes.size))
3183                     {
3184                        evas_object_show(ec->frame);
3185                        ec->changes.visible = !evas_object_visible_get(ec->frame);
3186                     }
3187                }
3188              else
3189                {
3190                   evas_object_hide(ec->frame);
3191                   ec->changes.visible = 0;
3192                }
3193           }
3194
3195         if (ec->changed)
3196           {
3197              _e_client_eval(ec);
3198              e_comp_visibility_calculation_set(EINA_TRUE);
3199              if (ec->changes.accepts_focus)
3200                *check_focus = EINA_TRUE;
3201              ec->changes.accepts_focus = 0;
3202
3203              if (e_client_focus_check_get(ec))
3204                {
3205                   *check_focus = EINA_TRUE;
3206                   e_client_focus_check_set(ec, EINA_FALSE);
3207                }
3208           }
3209
3210         if ((ec->changes.visible) && (ec->visible) && (!ec->changed))
3211           {
3212              evas_object_show(ec->frame);
3213              ec->changes.visible = !evas_object_visible_get(ec->frame);
3214              ec->changed = ec->changes.visible;
3215              e_comp_visibility_calculation_set(EINA_TRUE);
3216           }
3217      }
3218
3219    TRACE_DS_END();
3220 }
3221
3222 static Eina_Bool
3223 _e_client_cb_hook_comp_render_update_lock_set(void *data, E_Client *ec)
3224 {
3225    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_TRUE);
3226
3227    ec->transform_core.update_lock = EINA_TRUE;
3228
3229    return EINA_TRUE;
3230 }
3231
3232 static Eina_Bool
3233 _e_client_cb_hook_comp_render_update_lock_unset(void *data, E_Client *ec)
3234 {
3235    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_TRUE);
3236
3237    ec->transform_core.update_lock = EINA_FALSE;
3238    ec->transform_core.changed = EINA_TRUE;
3239
3240    e_client_transform_core_update(ec);
3241
3242    return EINA_TRUE;
3243 }
3244
3245 EINTERN Eina_Bool
3246 e_client_init(void)
3247 {
3248    int pix_id;
3249    for (pix_id = 0; pix_id < E_PIXMAP_TYPE_MAX; pix_id++)
3250      clients_hash[pix_id] = eina_hash_pointer_new(NULL);
3251
3252    E_COMP_WL_HOOK_APPEND(hooks, E_COMP_WL_HOOK_SHELL_SURFACE_READY, _e_client_cb_hook_shell_surface_ready, NULL);
3253    E_COMP_COMP_HOOK_APPEND(comp_hooks, E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET, _e_client_cb_hook_comp_render_update_lock_set, NULL);
3254    E_COMP_COMP_HOOK_APPEND(comp_hooks, E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_UNSET, _e_client_cb_hook_comp_render_update_lock_unset, NULL);
3255
3256    E_EVENT_CLIENT_ADD = ecore_event_type_new();
3257    E_EVENT_CLIENT_REMOVE = ecore_event_type_new();
3258    E_EVENT_CLIENT_DESK_SET = ecore_event_type_new();
3259    E_EVENT_CLIENT_ZONE_SET = ecore_event_type_new();
3260    E_EVENT_CLIENT_RESIZE = ecore_event_type_new();
3261    E_EVENT_CLIENT_MOVE = ecore_event_type_new();
3262    E_EVENT_CLIENT_SHOW = ecore_event_type_new();
3263    E_EVENT_CLIENT_HIDE = ecore_event_type_new();
3264    E_EVENT_CLIENT_ICONIFY = ecore_event_type_new();
3265    E_EVENT_CLIENT_UNICONIFY = ecore_event_type_new();
3266    E_EVENT_CLIENT_STACK = ecore_event_type_new();
3267    E_EVENT_CLIENT_FOCUS_IN = ecore_event_type_new();
3268    E_EVENT_CLIENT_FOCUS_OUT = ecore_event_type_new();
3269    E_EVENT_CLIENT_PROPERTY = ecore_event_type_new();
3270    E_EVENT_CLIENT_FULLSCREEN = ecore_event_type_new();
3271    E_EVENT_CLIENT_UNFULLSCREEN = ecore_event_type_new();
3272 #ifdef _F_ZONE_WINDOW_ROTATION_
3273    E_EVENT_CLIENT_ROTATION_CHANGE_BEGIN = ecore_event_type_new();
3274    E_EVENT_CLIENT_ROTATION_CHANGE_CANCEL = ecore_event_type_new();
3275    E_EVENT_CLIENT_ROTATION_CHANGE_END = ecore_event_type_new();
3276    E_EVENT_CLIENT_ROTATION_GEOMETRY_SET = ecore_event_type_new();
3277 #endif
3278    E_EVENT_CLIENT_VISIBILITY_CHANGE = ecore_event_type_new();
3279    E_EVENT_CLIENT_BUFFER_CHANGE = ecore_event_type_new();
3280    E_EVENT_CLIENT_FOCUS_SKIP_SET = ecore_event_type_new();;
3281    E_EVENT_CLIENT_FOCUS_SKIP_UNSET = ecore_event_type_new();;
3282
3283    return (!!clients_hash[1]);
3284 }
3285
3286 EINTERN void
3287 e_client_shutdown(void)
3288 {
3289    int pix_id;
3290    for (pix_id = 0; pix_id < E_PIXMAP_TYPE_MAX; pix_id++)
3291      E_FREE_FUNC(clients_hash[pix_id], eina_hash_free);
3292
3293    E_FREE_LIST(comp_hooks, e_comp_object_hook_del);
3294    E_FREE_LIST(hooks, e_comp_wl_hook_del);
3295    E_FREE_LIST(handlers, ecore_event_handler_del);
3296
3297 }
3298
3299 E_API void
3300 e_client_unignore(E_Client *ec)
3301 {
3302    E_OBJECT_CHECK(ec);
3303    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
3304    if (!ec->ignored) return;
3305
3306    ec->ignored = 0;
3307    _e_client_event_add(ec);
3308 }
3309
3310 static E_Layer
3311 _e_client_convert_fullscreen_layer(int layer)
3312 {
3313    if (layer <= E_LAYER_CLIENT_NORMAL)
3314      return E_LAYER_CLIENT_NORMAL;
3315    else if (layer <= E_LAYER_CLIENT_ABOVE)
3316      return E_LAYER_CLIENT_ABOVE;
3317    else if (layer <= E_LAYER_CLIENT_EDGE)
3318      return E_LAYER_CLIENT_EDGE;
3319    else
3320      return E_LAYER_CLIENT_FULLSCREEN;
3321 }
3322
3323 static void
3324 _e_input_thread_client_new(void *data)
3325 {
3326    E_Input_Thread_Request_EClient_Data *ec_data = data;
3327    EINA_SAFETY_ON_NULL_RETURN(ec_data);
3328
3329    INF("[input thread|%s] ec(%p), surface(%p)\n", __func__, ec_data->ec, ec_data->wl_surface);
3330    e_input_thread_client_new(ec_data->ec, ec_data->wl_surface);
3331 }
3332
3333 E_API E_Client *
3334 e_client_new(E_Pixmap *cp, int first_map, int internal)
3335 {
3336    E_Client *ec;
3337    E_Pixmap_Type type;
3338
3339    type = e_pixmap_type_get(cp);
3340    if (type >= E_PIXMAP_TYPE_MAX) return NULL;
3341    if (eina_hash_find(clients_hash[type], &cp)) return NULL;
3342
3343    ec = E_OBJECT_ALLOC(E_Client, E_CLIENT_TYPE, _e_client_free);
3344    if (!ec) return NULL;
3345    e_object_del_func_set(E_OBJECT(ec), E_OBJECT_CLEANUP_FUNC(_e_client_del));
3346
3347    if (!_e_client_private_init(ec))
3348      {
3349         e_object_del(E_OBJECT(ec));
3350         return NULL;
3351      }
3352
3353    E_Input_Thread_Request_EClient_Data ec_new_data;
3354    memset(&ec_new_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
3355
3356    ec_new_data.ec = ec;
3357    ec_new_data.wl_surface = ec->comp_data ? ec->comp_data->wl_surface : NULL;
3358    INF("[%s] ec(%p), surface(%p)\n", __func__, ec, ec_new_data.wl_surface);
3359    e_input_thread_safe_call(_e_input_thread_client_new, &ec_new_data, sizeof(E_Input_Thread_Request_EClient_Data));
3360
3361    uuid_generate(ec->uuid);
3362
3363    ec->focus_policy_override = E_FOCUS_LAST;
3364    e_client_size_set(ec, 1, 1);
3365    ec->internal = internal;
3366
3367    ec->pixmap = cp;
3368    e_pixmap_client_set(cp, ec);
3369    ec->resize_mode = E_POINTER_RESIZE_NONE;
3370    ec->layer = E_LAYER_CLIENT_NORMAL;
3371    ec->first_mapped = EINA_FALSE;
3372    ec->post_raise = EINA_TRUE;
3373    ec->post_lower = EINA_FALSE;
3374    ec->animatable = EINA_TRUE;
3375    ec->maximize_type = e_config->maximize_policy & E_MAXIMIZE_TYPE;
3376    ec->fullscreen_layer = _e_client_convert_fullscreen_layer(e_config->fullscreen_layer);
3377
3378    /* FIXME: if first_map is 1 then we should ignore the first hide event
3379     * or ensure the window is already hidden and events flushed before we
3380     * create a border for it */
3381    if (first_map)
3382      {
3383         ec->changes.pos = 1;
3384         ec->re_manage = 1;
3385      }
3386    ec->new_client = 1;
3387    e_comp->new_clients++;
3388
3389    ec->exp_iconify.by_client = 0;
3390    ec->exp_iconify.not_raise = 0;
3391    ec->exp_iconify.skip_iconify = 0;
3392    ec->exp_iconify.skip_by_remote = 0;
3393    if (e_config->deiconify_approve)
3394      ec->exp_iconify.deiconify_update= 1;
3395    else
3396      ec->exp_iconify.deiconify_update= 0;
3397    if (e_config->use_buffer_flush)
3398      ec->exp_iconify.buffer_flush = 1;
3399    else
3400      ec->exp_iconify.buffer_flush = 0;
3401
3402    e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_NONE);
3403
3404    wl_signal_emit(&PRI(ec)->events.new_client, NULL);
3405    if (!_e_client_hook_call(E_CLIENT_HOOK_NEW_CLIENT, ec))
3406      {
3407         /* delete the above allocated object */
3408         //e_object_del(E_OBJECT(ec));
3409         return NULL;
3410      }
3411
3412    _e_client_aux_hint_eval(ec);
3413
3414    ec->icccm.title = NULL;
3415    ec->icccm.name = NULL;
3416 #if defined(__cplusplus) || defined(c_plusplus)
3417    ec->icccm.cpp_class = NULL;
3418 #else
3419    ec->icccm.class = NULL;
3420 #endif
3421    ec->icccm.min_w = 1;
3422    ec->icccm.min_h = 1;
3423    ec->icccm.max_w = 32767;
3424    ec->icccm.max_h = 32767;
3425
3426    ec->netwm.pid = 0;
3427    ec->netwm.name = NULL;
3428    ec->netwm.state.skip_taskbar = 0;
3429    ec->netwm.state.skip_pager = 0;
3430    ec->netwm.opacity = 255;
3431
3432    ec->visibility.obscured = E_VISIBILITY_UNKNOWN;
3433    ec->visibility.opaque = -1;
3434    ec->visibility.changed = 0;
3435    ec->visibility.skip = 0;
3436    ec->visibility.last_sent_type = E_VISIBILITY_UNKNOWN;
3437
3438    ec->transform.zoom = 1.0;
3439    ec->transform.angle = 0.0;
3440    ec->transform_core.direct_render = EINA_TRUE;
3441    ec->transform_core.activate = EINA_TRUE;
3442
3443    ec->pointer_enter_sent = EINA_FALSE;
3444
3445    ec->acquire_fence_fd = -1;
3446
3447    EC_CHANGED(ec);
3448
3449    e_comp->clients = eina_list_append(e_comp->clients, ec);
3450    eina_hash_add(clients_hash[type], &ec->pixmap, ec);
3451
3452    ELOGF("COMP", "CLIENT ADD. cp:%p, argb:%d, internal:%d, ignored:%d", ec, cp, ec->argb, internal, ec->ignored);
3453    if (!ec->ignored)
3454      _e_client_event_add(ec);
3455    e_comp_object_client_add(ec);
3456    if (ec->frame)
3457      {
3458         evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, _e_client_cb_evas_show, ec);
3459         evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE, _e_client_cb_evas_hide, ec);
3460         evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE, _e_client_cb_evas_move, ec);
3461         evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESIZE, _e_client_cb_evas_resize, ec);
3462         evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESTACK, _e_client_cb_evas_restack, ec);
3463      }
3464
3465    wl_signal_emit(&PRI(ec)->events.new_client_post, NULL);
3466
3467 #ifdef _F_E_CLIENT_NEW_CLIENT_POST_HOOK_
3468    _e_client_hook_call(E_CLIENT_HOOK_NEW_CLIENT_POST, ec);
3469 #endif
3470
3471    ec->manage_resize.resize_obj = NULL;
3472    ec->manage_resize.x = ec->manage_resize.y = ec->manage_resize.w = ec->manage_resize.h = 0;
3473    ec->manage_resize.enable_aspect_ratio = EINA_FALSE;
3474    ec->manage_resize.aw = ec->manage_resize.ah = 0;
3475    ec->manage_resize.header_h = 0;
3476    ec->manage_resize.footer_h = 0;
3477
3478    ec->visibility.ignore_geometry = e_config->calc_vis_ignore_geometry;
3479
3480    return ec;
3481 }
3482
3483 E_API Eina_Bool e_client_is_internal(E_Client *ec)
3484 {
3485    E_OBJECT_CHECK_RETURN(ec, EINA_TRUE);
3486    return ec->internal;
3487 }
3488
3489 EINTERN void
3490 e_client_desk_iconify_skip_set(E_Client *ec, Eina_Bool skip)
3491 {
3492    if (!ec) return;
3493    ec->user_skip_winlist = skip;
3494 }
3495
3496 EINTERN Eina_Bool
3497 e_client_desk_iconify_skip_get(E_Client *ec)
3498 {
3499    if (!ec) return EINA_FALSE;
3500    return ec->user_skip_winlist;
3501 }
3502
3503 EINTERN Eina_Bool
3504 e_client_comp_grabbed_get(void)
3505 {
3506    return comp_grabbed;
3507 }
3508
3509 EINTERN E_Client *
3510 e_client_action_get(void)
3511 {
3512    return action_client;
3513 }
3514
3515
3516 //////////////////////////////////////////////////////////
3517
3518 EINTERN void
3519 e_client_mouse_in(E_Client *ec, int x, int y)
3520 {
3521    E_Desk *desk;
3522
3523    if (comp_grabbed) return;
3524    if (e_object_is_del(E_OBJECT(ec))) return;
3525    desk = e_comp_desk_find_by_ec(ec);
3526    if (desk && desk->animate_count) return;
3527    ec->mouse.current.mx = x;
3528    ec->mouse.current.my = y;
3529    ec->mouse.in = 1;
3530
3531    wl_signal_emit(&PRI(ec)->events.mouse_in, NULL);
3532 }
3533
3534 EINTERN void
3535 e_client_mouse_out(E_Client *ec, int x, int y)
3536 {
3537    E_Desk *desk;
3538
3539    if (comp_grabbed) return;
3540    if (ec->fullscreen) return;
3541    if (e_object_is_del(E_OBJECT(ec))) return;
3542    desk = e_comp_desk_find_by_ec(ec);
3543    if (desk && desk->animate_count) return;
3544
3545    ec->mouse.current.mx = x;
3546    ec->mouse.current.my = y;
3547    ec->mouse.in = 0;
3548
3549    wl_signal_emit(&PRI(ec)->events.mouse_out, NULL);
3550 }
3551
3552 EINTERN void
3553 e_client_mouse_wheel(E_Client *ec, Evas_Point *output, E_Binding_Event_Wheel *ev)
3554 {
3555    EINA_SAFETY_ON_NULL_RETURN(ec);
3556    if (action_client) return;
3557    ec->mouse.current.mx = output->x;
3558    ec->mouse.current.my = output->y;
3559 }
3560
3561 EINTERN void
3562 e_client_mouse_down(E_Client *ec, int button, Evas_Point *output, E_Binding_Event_Mouse_Button *ev)
3563 {
3564    EINA_SAFETY_ON_NULL_RETURN(ec);
3565
3566    if (action_client || ec->iconic || e_client_util_ignored_get(ec)) return;
3567    if ((button >= 1) && (button <= 3))
3568      {
3569         ec->mouse.last_down[button - 1].mx = output->x;
3570         ec->mouse.last_down[button - 1].my = output->y;
3571         ec->mouse.last_down[button - 1].x = ec->x;
3572         ec->mouse.last_down[button - 1].y = ec->y;
3573         ec->mouse.last_down[button - 1].w = ec->w;
3574         ec->mouse.last_down[button - 1].h = ec->h;
3575      }
3576    else
3577      {
3578         ec->moveinfo.down.x = ec->x;
3579         ec->moveinfo.down.y = ec->y;
3580         ec->moveinfo.down.w = ec->w;
3581         ec->moveinfo.down.h = ec->h;
3582      }
3583    ec->mouse.current.mx = output->x;
3584    ec->mouse.current.my = output->y;
3585    if ((button >= 1) && (button <= 3))
3586      {
3587         ec->mouse.last_down[button - 1].mx = output->x;
3588         ec->mouse.last_down[button - 1].my = output->y;
3589         ec->mouse.last_down[button - 1].x = ec->x;
3590         ec->mouse.last_down[button - 1].y = ec->y;
3591         ec->mouse.last_down[button - 1].w = ec->w;
3592         ec->mouse.last_down[button - 1].h = ec->h;
3593      }
3594    else
3595      {
3596         ec->moveinfo.down.x = ec->x;
3597         ec->moveinfo.down.y = ec->y;
3598         ec->moveinfo.down.w = ec->w;
3599         ec->moveinfo.down.h = ec->h;
3600      }
3601    ec->mouse.current.mx = output->x;
3602    ec->mouse.current.my = output->y;
3603
3604    wl_signal_emit(&PRI(ec)->events.mouse_down, NULL);
3605 }
3606
3607 EINTERN void
3608 e_client_mouse_up(E_Client *ec, int button, Evas_Point *output, E_Binding_Event_Mouse_Button* ev)
3609 {
3610    EINA_SAFETY_ON_NULL_RETURN(ec);
3611    if (ec->iconic || e_client_util_ignored_get(ec)) return;
3612    if ((button >= 1) && (button <= 3))
3613      {
3614         ec->mouse.last_up[button - 1].mx = output->x;
3615         ec->mouse.last_up[button - 1].my = output->y;
3616         ec->mouse.last_up[button - 1].x = ec->x;
3617         ec->mouse.last_up[button - 1].y = ec->y;
3618      }
3619    ec->mouse.current.mx = output->x;
3620    ec->mouse.current.my = output->y;
3621    /* also we don't pass the same params that went in - then again that */
3622    /* should be ok as we are just ending the action if it has an end */
3623    if (ec->cur_mouse_action)
3624      {
3625         if (ec->cur_mouse_action->func.end_mouse)
3626           ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", ev);
3627         else if (ec->cur_mouse_action->func.end)
3628           ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
3629         e_object_unref(E_OBJECT(ec->cur_mouse_action));
3630         ec->cur_mouse_action = NULL;
3631      }
3632
3633    if ((button >= 1) && (button <= 3))
3634      {
3635         ec->mouse.last_up[button - 1].mx = output->x;
3636         ec->mouse.last_up[button - 1].my = output->y;
3637         ec->mouse.last_up[button - 1].x = ec->x;
3638         ec->mouse.last_up[button - 1].y = ec->y;
3639      }
3640 }
3641
3642 E_API void
3643 e_client_stay_within_canvas_margin(E_Client *ec)
3644 {
3645    int new_x = ec->x;
3646    int new_y = ec->y;
3647
3648    if (ec->floating)
3649      {
3650         _e_client_stay_within_canvas_margin(ec, ec->x, ec->y, &new_x, &new_y);
3651
3652         if ((ec->x != new_x) || (ec->y != new_y))
3653           evas_object_move(ec->frame, new_x, new_y);
3654      }
3655 }
3656
3657 EINTERN void
3658 e_client_mouse_move(E_Client *ec, Evas_Point *output)
3659 {
3660    EINA_SAFETY_ON_NULL_RETURN(ec);
3661    if (ec->iconic || e_client_util_ignored_get(ec)) return;
3662    ec->mouse.current.mx = output->x;
3663    ec->mouse.current.my = output->y;
3664    if (e_client_util_moving_get(ec))
3665      {
3666         _e_client_move_handle(ec);
3667      }
3668    else if (e_client_util_resizing_get(ec))
3669      {
3670         _e_client_resize_handle(ec);
3671      }
3672 }
3673 ///////////////////////////////////////////////////////
3674
3675 EINTERN void
3676 e_client_res_change_geometry_save(E_Client *ec)
3677 {
3678    E_OBJECT_CHECK(ec);
3679    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
3680
3681    if (ec->pre_res_change.valid) return;
3682    ec->pre_res_change.valid = 1;
3683    ec->pre_res_change.x = ec->x;
3684    ec->pre_res_change.y = ec->y;
3685    ec->pre_res_change.w = ec->w;
3686    ec->pre_res_change.h = ec->h;
3687    ec->pre_res_change.saved.x = ec->saved.x;
3688    ec->pre_res_change.saved.y = ec->saved.y;
3689    ec->pre_res_change.saved.w = ec->saved.w;
3690    ec->pre_res_change.saved.h = ec->saved.h;
3691 }
3692
3693 EINTERN void
3694 e_client_res_change_geometry_restore(E_Client *ec)
3695 {
3696    E_Zone *zone;
3697
3698    struct
3699    {
3700       unsigned char valid : 1;
3701       int           x, y, w, h;
3702       struct
3703       {
3704          int x, y, w, h;
3705       } saved;
3706    } pre_res_change;
3707
3708    E_OBJECT_CHECK(ec);
3709    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
3710    if (!ec->pre_res_change.valid) return;
3711    if (ec->new_client) return;
3712
3713    zone = e_comp_zone_find_by_ec(ec);
3714    if (!zone) return;
3715
3716    memcpy(&pre_res_change, &ec->pre_res_change, sizeof(pre_res_change));
3717
3718    if (ec->fullscreen)
3719      {
3720         e_client_unfullscreen(ec);
3721         e_client_fullscreen(ec, e_config->fullscreen_policy);
3722      }
3723    else if (ec->maximized != E_MAXIMIZE_NONE)
3724      {
3725         E_Maximize max;
3726
3727         max = ec->maximized;
3728         e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
3729         e_client_maximize(ec, max);
3730      }
3731    else
3732      {
3733         int x, y, w, h, zx, zy, zw, zh;
3734
3735         ec->saved.x = ec->pre_res_change.saved.x;
3736         ec->saved.y = ec->pre_res_change.saved.y;
3737         ec->saved.w = ec->pre_res_change.saved.w;
3738         ec->saved.h = ec->pre_res_change.saved.h;
3739
3740         e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
3741
3742         if (ec->saved.w > zw)
3743           ec->saved.w = zw;
3744         if ((ec->saved.x + ec->saved.w) > (zx + zw))
3745           ec->saved.x = zx + zw - ec->saved.w;
3746
3747         if (ec->saved.h > zh)
3748           ec->saved.h = zh;
3749         if ((ec->saved.y + ec->saved.h) > (zy + zh))
3750           ec->saved.y = zy + zh - ec->saved.h;
3751
3752         x = ec->pre_res_change.x;
3753         y = ec->pre_res_change.y;
3754         w = ec->pre_res_change.w;
3755         h = ec->pre_res_change.h;
3756         if (w > zw)
3757           w = zw;
3758         if (h > zh)
3759           h = zh;
3760         if ((x + w) > (zx + zw))
3761           x = zx + zw - w;
3762         if ((y + h) > (zy + zh))
3763           y = zy + zh - h;
3764         evas_object_geometry_set(ec->frame, x, y, w, h);
3765      }
3766    memcpy(&ec->pre_res_change, &pre_res_change, sizeof(pre_res_change));
3767 }
3768
3769 EINTERN void
3770 e_client_pos_set(E_Client *ec, int x, int y)
3771 {
3772    if (!ec) return;
3773    ec->x = x;
3774    ec->y = y;
3775 }
3776
3777 EINTERN void
3778 e_client_pos_get(E_Client *ec, int *x, int *y)
3779 {
3780    int ex = 0;
3781    int ey = 0;
3782
3783    if (ec)
3784      {
3785         ex = ec->x;
3786         ey = ec->y;
3787      }
3788
3789    if (x) *x = ex;
3790    if (y) *y = ey;
3791 }
3792
3793 E_API void
3794 e_client_size_set(E_Client *ec, int w, int h)
3795 {
3796    if (!ec) return;
3797    ec->w = w;
3798    ec->h = h;
3799 }
3800
3801 E_API void
3802 e_client_size_get(E_Client *ec, int *w, int *h)
3803 {
3804    int ew = 0;
3805    int eh = 0;
3806
3807    if (ec)
3808      {
3809         ew = ec->w;
3810         eh = ec->h;
3811      }
3812
3813    if (w) *w = ew;
3814    if (h) *h = eh;
3815 }
3816
3817 E_API void
3818 e_client_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
3819 {
3820    int gx = 0;
3821    int gy = 0;
3822    int gw = 0;
3823    int gh = 0;
3824
3825    E_OBJECT_CHECK(ec);
3826    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
3827
3828    if (e_client_transform_core_enable_get(ec))
3829      {
3830         gx = ec->transform_core.result.boundary.x;
3831         gy = ec->transform_core.result.boundary.y;
3832         gw = ec->transform_core.result.boundary.w;
3833         gh = ec->transform_core.result.boundary.h;
3834      }
3835    else
3836      {
3837         if (ec->frame)
3838           {
3839              evas_object_geometry_get(ec->frame, &gx, &gy, &gw, &gh);
3840              if (gw == 0 && gh == 0)
3841                {
3842                   /* In this case, there is no image buffer in e_comp_object, thus it
3843                    * should return geometry value of ec itself. It usually happens if
3844                    * new ec is not mapped yet.
3845                    */
3846                   gw = ec->w;
3847                   gh = ec->h;
3848                   gx = ec->x;
3849                   gy = ec->y;
3850                }
3851           }
3852         else
3853           {
3854              gx = ec->x;
3855              gy = ec->y;
3856              gw = ec->w;
3857              gh = ec->h;
3858           }
3859      }
3860
3861    if (x) *x = gx;
3862    if (y) *y = gy;
3863    if (w) *w = gw;
3864    if (h) *h = gh;
3865 }
3866
3867 E_API E_Client *
3868 e_client_above_get(const E_Client *ec)
3869 {
3870 #ifdef REFACTOR_DESK_AREA
3871    API_ENTRY_VAL(NULL);
3872
3873    E_Client_Data_Get_Above data;
3874
3875    data.above_ec = NULL;
3876
3877    wl_signal_emit(&priv->events.get_above, &data);
3878
3879    return data.above_ec;
3880 #else
3881    unsigned int x;
3882    E_Client *ec2;
3883
3884    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
3885    if (EINA_INLIST_GET(ec)->next) //check current layer
3886      {
3887         EINA_INLIST_FOREACH(EINA_INLIST_GET(ec)->next, ec2)
3888           {
3889              if (ec == ec2)
3890                {
3891                   ELOGF("FATAL", "CHECK the ec inlist next", ec);
3892                   continue;
3893                }
3894              if (!e_object_is_del(E_OBJECT(ec2)))
3895                return ec2;
3896           }
3897      }
3898    if (ec->layer == E_LAYER_CLIENT_CURSOR) return NULL;
3899    if (e_comp_canvas_client_layer_map(ec->layer) == 9999) return NULL;
3900
3901    g_rec_mutex_lock(&e_comp->ec_list_mutex);
3902    /* go up the layers until we find one */
3903    for (x = e_comp_canvas_layer_map(ec->layer) + 1; x <= e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR); x++)
3904      {
3905         if (!e_comp->layers[x].clients) continue;
3906         EINA_INLIST_FOREACH(e_comp->layers[x].clients, ec2)
3907           {
3908              if (ec == ec2)
3909                {
3910                   ELOGF("FATAL", "EC exist above layer. ec layer_map:%d, cur layer_map:%d",
3911                         ec, e_comp_canvas_layer_map(ec->layer), x);
3912                   continue;
3913                }
3914              if (!e_object_is_del(E_OBJECT(ec2)))
3915                {
3916                   g_rec_mutex_unlock(&e_comp->ec_list_mutex);
3917                   return ec2;
3918                }
3919           }
3920      }
3921    g_rec_mutex_unlock(&e_comp->ec_list_mutex);
3922
3923    return NULL;
3924 #endif
3925 }
3926
3927 E_API E_Client *
3928 e_client_below_get(const E_Client *ec)
3929 {
3930 #ifdef REFACTOR_DESK_AREA
3931    API_ENTRY_VAL(NULL);
3932
3933    E_Client_Data_Get_Below data;
3934
3935    data.below_ec = NULL;
3936
3937    wl_signal_emit(&priv->events.get_below, &data);
3938
3939    return data.below_ec;
3940 #else
3941    unsigned int x;
3942    E_Client *ec2;
3943    Eina_Inlist *l;
3944    E_Layer ec_layer, ec_layer_cw;
3945    int cw_layer;
3946
3947    E_OBJECT_CHECK_RETURN(ec, NULL);
3948    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, NULL);
3949
3950    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
3951    if (EINA_INLIST_GET(ec)->prev) //check current layer
3952      {
3953         for (l = EINA_INLIST_GET(ec)->prev; l; l = l->prev)
3954           {
3955              ec2 = EINA_INLIST_CONTAINER_GET(l, E_Client);
3956              if (ec == ec2)
3957                {
3958                   ELOGF("FATAL", "CHECK the ec inlist prev", ec);
3959                   continue;
3960                }
3961              if (!e_object_is_del(E_OBJECT(ec2)))
3962                return ec2;
3963           }
3964      }
3965
3966    // check layer validation
3967    ec_layer = ec->layer;
3968    if (ec->layer_block || ec->layer_pending)
3969      {
3970         cw_layer = e_comp_object_layer_get(ec->frame);
3971         if (cw_layer >= 0)
3972           {
3973              ec_layer_cw = e_comp_canvas_layer_map_to(cw_layer);
3974              if (ec_layer != ec_layer_cw)
3975                {
3976                   ELOGF("COMP", "LAYER is not same. USE obj layer! (ec->layer:%d, obj:%d). block:%d, pending:%d)", ec, ec_layer, ec_layer_cw, ec->layer_block, ec->layer_pending);
3977                   ec_layer = ec_layer_cw;
3978                }
3979           }
3980      }
3981
3982    if (ec_layer == E_LAYER_CLIENT_DESKTOP) return NULL;
3983    if (e_comp_canvas_client_layer_map(ec_layer) == 9999) return NULL;
3984
3985    /* go down the layers until we find one */
3986    x = e_comp_canvas_layer_map(ec_layer);
3987    if (x > 0) x--;
3988
3989    g_rec_mutex_lock(&e_comp->ec_list_mutex);
3990    for (; x >= e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); x--)
3991      {
3992         if (!e_comp->layers[x].clients) continue;
3993         EINA_INLIST_REVERSE_FOREACH(e_comp->layers[x].clients, ec2)
3994           {
3995              if (ec == ec2)
3996                {
3997                   ELOGF("FATAL", "EC exist below layer. ec layer_map:%d, cur layer_map:%d",
3998                         ec, e_comp_canvas_layer_map(ec_layer), x);
3999                   continue;
4000                }
4001              if (!e_object_is_del(E_OBJECT(ec2)))
4002                {
4003                   g_rec_mutex_unlock(&e_comp->ec_list_mutex);
4004                   return ec2;
4005                }
4006           }
4007      }
4008    g_rec_mutex_unlock(&e_comp->ec_list_mutex);
4009
4010    return NULL;
4011 #endif
4012 }
4013
4014 EINTERN E_Client *
4015 e_client_visible_above_get(E_Client *ec)
4016 {
4017 #ifdef REFACTOR_DESK_AREA
4018    API_ENTRY_VAL(NULL);
4019
4020    E_Client_Data_Get_Visible_Above data;
4021
4022    data.above_ec = NULL;
4023
4024    wl_signal_emit(&priv->events.get_visible_above, &data);
4025
4026    return data.above_ec;
4027 #else
4028    unsigned int x;
4029    E_Client *ec2;
4030
4031    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
4032    if (EINA_INLIST_GET(ec)->next) //check current layer
4033      {
4034         EINA_INLIST_FOREACH(EINA_INLIST_GET(ec)->next, ec2)
4035           {
4036              if (ec == ec2) continue;
4037              if ((!e_object_is_del(E_OBJECT(ec2))) &&
4038                  (!e_client_util_ignored_get(ec2)) &&
4039                  (ec2->visible) &&
4040                  (ec2->frame))
4041                return ec2;
4042           }
4043      }
4044
4045    if (ec->layer == E_LAYER_CLIENT_CURSOR) return NULL;
4046    if (e_comp_canvas_client_layer_map(ec->layer) == 9999) return NULL;
4047
4048    /* go up the layers until we find one */
4049    for (x = e_comp_canvas_layer_map(ec->layer) + 1; x <= e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR); x++)
4050      {
4051         if (!e_comp->layers[x].clients) continue;
4052         EINA_INLIST_FOREACH(e_comp->layers[x].clients, ec2)
4053           {
4054              if (ec == ec2) continue;
4055              if ((!e_object_is_del(E_OBJECT(ec2))) &&
4056                  (!e_client_util_ignored_get(ec2)) &&
4057                  (ec2->visible) &&
4058                  (ec2->frame))
4059                return ec2;
4060           }
4061      }
4062
4063    return NULL;
4064 #endif
4065 }
4066
4067 EINTERN E_Client *
4068 e_client_visible_below_get(E_Client *ec)
4069 {
4070 #ifdef REFACTOR_DESK_AREA
4071    API_ENTRY_VAL(NULL);
4072
4073    E_Client_Data_Get_Visible_Below data;
4074
4075    data.below_ec = NULL;
4076
4077    wl_signal_emit(&priv->events.get_visible_below, &data);
4078
4079    return data.below_ec;
4080 #else
4081    unsigned int x;
4082    E_Client *ec2;
4083    Eina_Inlist *l;
4084    E_Layer ec_layer, ec_layer_cw;
4085    int cw_layer;
4086
4087    E_OBJECT_CHECK_RETURN(ec, NULL);
4088    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, NULL);
4089
4090    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
4091    if (EINA_INLIST_GET(ec)->prev) //check current layer
4092      {
4093         for (l = EINA_INLIST_GET(ec)->prev; l; l = l->prev)
4094           {
4095              ec2 = EINA_INLIST_CONTAINER_GET(l, E_Client);
4096              if (ec == ec2) continue;
4097              if ((!e_object_is_del(E_OBJECT(ec2))) &&
4098                  (!e_client_util_ignored_get(ec2)) &&
4099                  (ec2->visible) &&
4100                  (ec2->frame))
4101                return ec2;
4102           }
4103      }
4104
4105    // check layer validation
4106    ec_layer = ec->layer;
4107    if (ec->layer_block || ec->layer_pending)
4108      {
4109         cw_layer = e_comp_object_layer_get(ec->frame);
4110         if (cw_layer >= 0)
4111           {
4112              ec_layer_cw = e_comp_canvas_layer_map_to(cw_layer);
4113              if (ec_layer != ec_layer_cw)
4114                {
4115                   ELOGF("COMP", "LAYER is not same. USE obj layer! (ec->layer:%d, obj:%d). block:%d, pending:%d)", ec, ec_layer, ec_layer_cw, ec->layer_block, ec->layer_pending);
4116                   ec_layer = ec_layer_cw;
4117                }
4118           }
4119      }
4120
4121    /* go down the layers until we find one */
4122    if (e_comp_canvas_layer_map(ec->layer) > e_comp_canvas_layer_map(E_LAYER_MAX)) return NULL;
4123    x = e_comp_canvas_layer_map(ec->layer);
4124    if (x > 0) x--;
4125
4126    for (; x >= e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); x--)
4127      {
4128         if (!e_comp->layers[x].clients) continue;
4129         EINA_INLIST_REVERSE_FOREACH(e_comp->layers[x].clients, ec2)
4130           {
4131              if (ec == ec2) continue;
4132              if ((!e_object_is_del(E_OBJECT(ec2))) &&
4133                  (!e_client_util_ignored_get(ec2)) &&
4134                  (ec2->visible) &&
4135                  (ec2->frame))
4136                return ec2;
4137           }
4138      }
4139
4140    return NULL;
4141 #endif
4142 }
4143
4144 E_API E_Client *
4145 e_client_bottom_get(void)
4146 {
4147 #ifdef REFACTOR_DESK_AREA
4148    E_Zone *zone;
4149    E_Desk *desk;
4150
4151    // get the bottom ec from current desk at current zone
4152    zone = e_zone_current_get();
4153    desk = e_desk_current_get(zone);
4154
4155    return e_desk_bottom_ec_get(desk);
4156 #else
4157    unsigned int x;
4158    g_rec_mutex_lock(&e_comp->ec_list_mutex);
4159    for (x = e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); x <= e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR); x++)
4160      {
4161         E_Client *ec2;
4162
4163         if (!e_comp->layers[x].clients) continue;
4164         EINA_INLIST_FOREACH(e_comp->layers[x].clients, ec2)
4165           if (!e_object_is_del(E_OBJECT(ec2)))
4166             {
4167                g_rec_mutex_unlock(&e_comp->ec_list_mutex);
4168                return ec2;
4169             }
4170      }
4171    g_rec_mutex_unlock(&e_comp->ec_list_mutex);
4172
4173    return NULL;
4174 #endif
4175 }
4176
4177 E_API E_Client *
4178 e_client_top_get(void)
4179 {
4180 #ifdef REFACTOR_DESK_AREA
4181    E_Zone *zone;
4182    E_Desk *desk;
4183
4184    // get the top ec from current desk at current zone
4185    zone = e_zone_current_get();
4186    desk = e_desk_current_get(zone);
4187
4188    return e_desk_top_ec_get(desk);
4189 #else
4190    unsigned int x;
4191    g_rec_mutex_lock(&e_comp->ec_list_mutex);
4192    for (x = e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR); x >= e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); x--)
4193      {
4194         E_Client *ec2;
4195
4196         if (!e_comp->layers[x].clients) continue;
4197         EINA_INLIST_REVERSE_FOREACH(e_comp->layers[x].clients, ec2)
4198           if (!e_object_is_del(E_OBJECT(ec2)))
4199             {
4200                g_rec_mutex_unlock(&e_comp->ec_list_mutex);
4201                return ec2;
4202             }
4203      }
4204    g_rec_mutex_unlock(&e_comp->ec_list_mutex);
4205
4206    return NULL;
4207 #endif
4208 }
4209
4210 EINTERN unsigned int
4211 e_clients_count(void)
4212 {
4213    return eina_list_count(e_comp->clients);
4214 }
4215
4216
4217 /**
4218  * Set a callback which will be called just prior to updating the
4219  * move coordinates for a border
4220  */
4221 EINTERN void
4222 e_client_move_intercept_cb_set(E_Client *ec, E_Client_Move_Intercept_Cb cb)
4223 {
4224    ec->move_intercept_cb = cb;
4225 }
4226
4227 ///////////////////////////////////////
4228
4229 E_API E_Client_Hook *
4230 e_client_hook_add(E_Client_Hook_Point hookpoint, E_Client_Hook_Cb func, const void *data)
4231 {
4232    E_Client_Hook *ch;
4233
4234    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_CLIENT_HOOK_LAST, NULL);
4235    ch = E_NEW(E_Client_Hook, 1);
4236    if (!ch) return NULL;
4237    ch->hookpoint = hookpoint;
4238    ch->func = func;
4239    ch->data = (void*)data;
4240    _e_client_hooks[hookpoint] = eina_inlist_append(_e_client_hooks[hookpoint], EINA_INLIST_GET(ch));
4241    return ch;
4242 }
4243
4244 E_API void
4245 e_client_hook_del(E_Client_Hook *ch)
4246 {
4247    ch->delete_me = 1;
4248    if (_e_client_hooks_walking == 0)
4249      {
4250         _e_client_hooks[ch->hookpoint] = eina_inlist_remove(_e_client_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
4251         free(ch);
4252      }
4253    else
4254      _e_client_hooks_delete++;
4255 }
4256
4257 ///////////////////////////////////////
4258
4259 E_API E_Client_Intercept_Hook *
4260 e_client_intercept_hook_add(E_Client_Intercept_Hook_Point hookpoint, E_Client_Intercept_Hook_Cb func, const void *data)
4261 {
4262    E_Client_Intercept_Hook *ch;
4263
4264    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_CLIENT_INTERCEPT_HOOK_LAST, NULL);
4265    ch = E_NEW(E_Client_Intercept_Hook, 1);
4266    if (!ch) return NULL;
4267    ch->hookpoint = hookpoint;
4268    ch->func = func;
4269    ch->data = (void*)data;
4270    _e_client_intercept_hooks[hookpoint] = eina_inlist_append(_e_client_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
4271    return ch;
4272 }
4273
4274 E_API void
4275 e_client_intercept_hook_del(E_Client_Intercept_Hook *ch)
4276 {
4277    if (!ch) return;
4278
4279    ch->delete_me = 1;
4280    if (_e_client_intercept_hooks_walking == 0)
4281      {
4282         _e_client_intercept_hooks[ch->hookpoint] =
4283            eina_inlist_remove(_e_client_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
4284         free(ch);
4285      }
4286    else
4287      _e_client_intercept_hooks_delete++;
4288 }
4289
4290 E_API void
4291 e_client_focus_latest_set(E_Client *ec)
4292 {
4293    EINA_SAFETY_ON_NULL_RETURN(ec);
4294
4295    wl_signal_emit(&PRI(ec)->events.focus_latest_set, NULL);
4296 }
4297
4298 E_API void
4299 e_client_focus_defer_set(E_Client *ec)
4300 {
4301    EINA_SAFETY_ON_NULL_RETURN(ec);
4302
4303    wl_signal_emit(&PRI(ec)->events.focus_defer_set, NULL);
4304 }
4305
4306 EINTERN void
4307 e_client_focused_set(E_Client *ec)
4308 {
4309    E_Client *focused_ec;
4310    E_Zone *zone;
4311
4312    if (ec)
4313      ELOGF("FOCUS", "CLIENT FOCUSED_SET : SET", ec);
4314    else
4315      ELOGF("FOCUS", "CLIENT FOCUSED_SET : UNSET", NULL);
4316
4317   focused_ec = e_comp_focused_ec_get();
4318   if (ec == focused_ec) return;
4319
4320    TRACE_DS_BEGIN(CLIENT:FOCUSED SET);
4321
4322    // unset the current focused_ec if focused_ec is not being deleted
4323    if (focused_ec)
4324      {
4325        if (!e_object_is_del(E_OBJECT(focused_ec)))
4326          {
4327             // FIXME: Remove focus_unset event of client.
4328             //        Instead, make zone focus_unset event and use it.
4329             wl_signal_emit(&PRI(focused_ec)->events.focus_unset, NULL);
4330             _e_client_hook_call(E_CLIENT_HOOK_FOCUS_UNSET, focused_ec);
4331
4332             if (e_object_ref_get(E_OBJECT(focused_ec)) > 0)
4333               {
4334                  _e_client_event_simple(focused_ec, E_EVENT_CLIENT_FOCUS_OUT);
4335               }
4336          }
4337      }
4338
4339    // clear the current focused_ec when ec is NULL
4340    if (!ec)
4341      {
4342         zone = e_comp_zone_find_by_ec(focused_ec);
4343         e_zone_focus_clear(zone);
4344         TRACE_DS_END();
4345         return;
4346      }
4347
4348    // FIXME: Remove focus_set event of client.
4349    //        Instead, make zone focus_set event and use it.
4350    // set the new current focused_ec
4351    wl_signal_emit(&PRI(ec)->events.focus_set, NULL);
4352    _e_client_hook_call(E_CLIENT_HOOK_FOCUS_SET, ec);
4353
4354    // send the client_focuse_in event
4355    _e_client_event_simple(ec, E_EVENT_CLIENT_FOCUS_IN);
4356
4357    TRACE_DS_END();
4358 }
4359
4360 EINTERN void
4361 e_client_activate(E_Client *ec)
4362 {
4363    E_OBJECT_CHECK(ec);
4364    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4365
4366    TRACE_DS_BEGIN(CLIENT:ACTIVATE);
4367
4368    ELOGF("COMP", "Set launching flag..", ec);
4369    ec->launching = EINA_TRUE;
4370
4371    ec->exp_iconify.not_raise = 0;
4372
4373    if (ec->iconic)
4374      {
4375          if (!ec->lock_user_iconify)
4376            e_client_uniconify(ec);
4377      }
4378    ELOGF("COMP", "Un-Set ICONIFY BY CLIENT", ec);
4379    ec->exp_iconify.by_client = 0;
4380    e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_NONE);
4381
4382    wl_signal_emit(&PRI(ec)->events.activate_done, NULL);
4383    _e_client_hook_call(E_CLIENT_HOOK_ACTIVATE_DONE, ec);
4384
4385    TRACE_DS_END();
4386 }
4387
4388 E_API E_Client *
4389 e_client_focused_get(void)
4390 {
4391    return e_comp_focused_ec_get();
4392 }
4393
4394 EINTERN Eina_List *
4395 e_client_lost_windows_get(E_Zone *zone)
4396 {
4397    Eina_List *list = NULL;
4398    const Eina_List *l;
4399    E_Client *ec;
4400    int loss_overlap = 5;
4401
4402    E_OBJECT_CHECK_RETURN(zone, NULL);
4403    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
4404    EINA_LIST_FOREACH(e_comp->clients, l, ec)
4405      {
4406         if (!e_zone_has_ec(zone, ec)) continue;
4407         if (e_client_util_ignored_get(ec)) continue;
4408
4409         if (!E_INTERSECTS(zone->x + loss_overlap,
4410                           zone->y + loss_overlap,
4411                           zone->w - (2 * loss_overlap),
4412                           zone->h - (2 * loss_overlap),
4413                           ec->x, ec->y, ec->w, ec->h))
4414           {
4415              list = eina_list_append(list, ec);
4416           }
4417      }
4418    return list;
4419 }
4420
4421 ///////////////////////////////////////
4422
4423 EINTERN void
4424 e_client_maximized_geometry_set(E_Client *ec, int x, int y, int w, int h)
4425 {
4426    if (!ec) return;
4427
4428    ec->maximized_info.x = x;
4429    ec->maximized_info.y = y;
4430    ec->maximized_info.w = w;
4431    ec->maximized_info.h = h;
4432
4433    e_client_frame_geometry_set(ec, x, y, w, h);
4434 }
4435
4436 EINTERN void
4437 e_client_maximized_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
4438 {
4439    if (!ec) return;
4440
4441    if (x) *x = ec->maximized_info.x;
4442    if (y) *y = ec->maximized_info.y;
4443    if (w) *w = ec->maximized_info.w;
4444    if (h) *h = ec->maximized_info.h;
4445 }
4446
4447 EINTERN void
4448 e_client_maximize_update(E_Client *ec)
4449 {
4450    E_Maximize max;
4451
4452    E_OBJECT_CHECK(ec);
4453    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4454
4455    if (ec->maximized)
4456      {
4457         max = ec->maximized;
4458         ec->maximized = 0;
4459         e_client_maximize(ec, max);
4460      }
4461 }
4462
4463 E_API void
4464 e_client_maximize(E_Client *ec, E_Maximize max)
4465 {
4466    E_OBJECT_CHECK(ec);
4467    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4468
4469    if (!(max & E_MAXIMIZE_DIRECTION)) max |= E_MAXIMIZE_BOTH;
4470
4471    if ((ec->maximized & E_MAXIMIZE_DIRECTION) == (max & E_MAXIMIZE_DIRECTION))
4472      {
4473         if ((ec->maximized & E_MAXIMIZE_TYPE) == (max & E_MAXIMIZE_TYPE))
4474           return;
4475      }
4476
4477    if (ec->new_client)
4478      {
4479         ec->changes.need_maximize = 1;
4480         ec->maximized &= ~E_MAXIMIZE_TYPE;
4481         ec->maximized |= max;
4482         EC_CHANGED(ec);
4483         return;
4484      }
4485
4486    if (!ec->fullscreen)
4487      {
4488         // call the maximize hook of a client
4489         wl_signal_emit(&PRI(ec)->events.maximize, &max);
4490
4491         // store the E_Maximize value
4492         ec->maximized = max;
4493         ec->changes.need_unmaximize = 0;
4494      }
4495    else
4496      {
4497         // store the E_Maximize value
4498         ec->maximized = max;
4499         ec->changes.need_unmaximize = 0;
4500      }
4501 }
4502
4503 E_API void
4504 e_client_unmaximize(E_Client *ec, E_Maximize max)
4505 {
4506    E_OBJECT_CHECK(ec);
4507    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4508
4509    if (!(max & E_MAXIMIZE_DIRECTION))
4510      {
4511         CRI("BUG: Unmaximize call without direction!");
4512         return;
4513      }
4514    if (ec->new_client)
4515      {
4516         ec->changes.need_unmaximize = 1;
4517         EC_CHANGED(ec);
4518         return;
4519      }
4520
4521    /* Remove directions not used */
4522    max &= (ec->maximized & E_MAXIMIZE_DIRECTION);
4523    /* Can only remove existing maximization directions */
4524    if (!max) return;
4525
4526    if (!ec->fullscreen)
4527      {
4528         // call the unmaximize hook of a client
4529         wl_signal_emit(&PRI(ec)->events.unmaximize, &max);
4530      }
4531
4532    ec->maximized = E_MAXIMIZE_NONE;
4533    ec->changes.need_unmaximize = 0;
4534 }
4535
4536 EINTERN void
4537 e_client_fullscreen(E_Client *ec, E_Fullscreen policy)
4538 {
4539    E_OBJECT_CHECK(ec);
4540    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4541
4542    if (ec->fullscreen) return;
4543
4544    // call the fullscreen_pre hook of a client
4545    wl_signal_emit(&PRI(ec)->events.fullscreen_pre, NULL);
4546    _e_client_hook_call(E_CLIENT_HOOK_FULLSCREEN_PRE, ec);
4547
4548    if (ec->skip_fullscreen) return;
4549    if (ec->new_client)
4550      {
4551         ec->need_fullscreen = 1;
4552         return;
4553      }
4554
4555    ec->saved.layer = ec->layer;
4556    e_client_layer_set(ec, ec->fullscreen_layer);
4557
4558    ec->fullscreen = 1;
4559
4560    // call the fullscreen hook of a client
4561    wl_signal_emit(&PRI(ec)->events.fullscreen, &policy);
4562
4563    ec->fullscreen_policy = policy;
4564
4565    _e_client_event_simple(ec, E_EVENT_CLIENT_FULLSCREEN);
4566 }
4567
4568 EINTERN void
4569 e_client_unfullscreen(E_Client *ec)
4570 {
4571    E_OBJECT_CHECK(ec);
4572    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4573
4574    ec->need_fullscreen = 0;
4575
4576    if (!ec->fullscreen) return;
4577
4578    ec->fullscreen = 0;
4579
4580    E_Fullscreen policy = ec->fullscreen_policy;
4581
4582    // call the unfullscreen hook of a client
4583    wl_signal_emit(&PRI(ec)->events.unfullscreen, &policy);
4584
4585    e_client_layer_set(ec, ec->saved.layer);
4586
4587    ec->fullscreen_policy = E_FULLSCREEN_RESIZE;
4588
4589    _e_client_event_simple(ec, E_EVENT_CLIENT_UNFULLSCREEN);
4590 }
4591
4592 ///////////////////////////////////////
4593 EINTERN Eina_Bool
4594 e_client_is_parent_iconify_by_client(E_Client *ec)
4595 {
4596    E_Client *parent = ec->parent;
4597    if (!parent) return EINA_FALSE;
4598
4599    if ((parent->exp_iconify.type == E_ICONIFIED_TYPE_ICONIFY_BY_CLIENT) ||
4600        (parent->exp_iconify.type == E_ICONIFIED_TYPE_PARENT_ICONIFY_BY_CLIENT))
4601      return EINA_TRUE;
4602
4603    return EINA_FALSE;
4604 }
4605
4606 E_API void
4607 e_client_iconify(E_Client *ec)
4608 {
4609    E_OBJECT_CHECK(ec);
4610    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4611
4612    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
4613    Eina_Bool iconified_by_client = e_client_is_iconified_by_client(ec);
4614
4615    ELOGF("TZVIS", "ICONIFY  |iconic:%d  |argb:%d       |not_raise:%d   |by_client:%d, type:%d",
4616          ec, ec->iconic, ec->argb, (unsigned int)ec->exp_iconify.not_raise,
4617          ec->exp_iconify.by_client, ec->exp_iconify.type);
4618
4619    if (ec->iconic) return;
4620    if (ec->exp_iconify.skip_iconify && !iconified_by_client) return;
4621    if (ec->exp_iconify.skip_by_remote) return;
4622    if (!cdata || !cdata->mapped)
4623      {
4624         if (!iconified_by_client)
4625           {
4626              ELOGF("TZVIS", "Not mapped.. So, don't iconify", ec);
4627              return;
4628           }
4629         else
4630           {
4631              ELOGF("TZVIS", "Not mapped.. But, iconify by user request", ec);
4632           }
4633      }
4634
4635    TRACE_DS_BEGIN(CLIENT:ICONIFY);
4636
4637    wl_signal_emit(&PRI(ec)->events.iconify, NULL);
4638    _e_client_hook_call(E_CLIENT_HOOK_ICONIFY, ec);
4639
4640    TRACE_DS_END();
4641 }
4642
4643 E_API void
4644 e_client_uniconify(E_Client *ec)
4645 {
4646    E_Comp_Wl_Client_Data *cdata;
4647
4648    E_OBJECT_CHECK(ec);
4649    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4650
4651    cdata = e_client_cdata_get(ec);
4652
4653    ELOGF("TZVIS", "UNICONIFY|iconic:%d  |argb:%d       |not_raise:%d  |by_client:%d, type:%d |mapped:%d",
4654          ec, ec->iconic, ec->argb, (unsigned int)ec->exp_iconify.not_raise,
4655          ec->exp_iconify.by_client, ec->exp_iconify.type,
4656          cdata ? cdata->mapped : 0);
4657
4658    if (!ec->iconic) return;
4659
4660    TRACE_DS_BEGIN(CLIENT:UNICONIFY);
4661
4662     // call the uniconify hook of a client
4663    wl_signal_emit(&PRI(ec)->events.uniconify, NULL);
4664    _e_client_hook_call(E_CLIENT_HOOK_UNICONIFY, ec);
4665
4666    TRACE_DS_END();
4667 }
4668
4669 E_API void
4670 e_client_iconified_type_set(E_Client *ec, E_Iconified_Type type)
4671 {
4672    if (!ec) return;
4673    ec->exp_iconify.type = type;
4674 }
4675
4676 EINTERN E_Iconified_Type
4677 e_client_iconified_type_get(E_Client *ec)
4678 {
4679    if (!ec) return E_ICONIFIED_TYPE_NONE;
4680    return ec->exp_iconify.type;
4681 }
4682
4683 E_API Eina_Bool e_client_is_iconified_by_client(E_Client *ec)
4684 {
4685    if (!ec) return EINA_FALSE;
4686
4687    if (ec->exp_iconify.type == E_ICONIFIED_TYPE_ICONIFY_BY_CLIENT)
4688      return EINA_TRUE;
4689
4690    if (ec->exp_iconify.type == E_ICONIFIED_TYPE_DESK_ICONIFY_BY_CLIENT)
4691      return EINA_TRUE;
4692
4693    if (ec->exp_iconify.type == E_ICONIFIED_TYPE_PARENT_ICONIFY_BY_CLIENT)
4694      return EINA_TRUE;
4695
4696    if (ec->exp_iconify.by_client)
4697      {
4698         ELOGF("POL", "CHECK. mismatch value. by_client:%d, type:%d", ec, ec->exp_iconify.by_client, ec->exp_iconify.type);
4699         return EINA_TRUE;
4700      }
4701
4702    return EINA_FALSE;
4703 }
4704
4705 ///////////////////////////////////////
4706
4707 EINTERN void e_client_hide_by_request_set(E_Client *ec, Eina_Bool set)
4708 {
4709    API_ENTRY;
4710    priv->hide_by_request = set;
4711 }
4712
4713 EINTERN Eina_Bool e_client_hide_by_request_get(E_Client *ec)
4714 {
4715    API_ENTRY_VAL(EINA_FALSE);
4716    return priv->hide_by_request;
4717 }
4718
4719 EINTERN void e_client_focus_check_set(E_Client *ec, Eina_Bool set)
4720 {
4721    API_ENTRY;
4722    priv->focus_check = set;
4723 }
4724
4725 EINTERN Eina_Bool e_client_focus_check_get(E_Client *ec)
4726 {
4727    API_ENTRY_VAL(EINA_FALSE);
4728    return priv->focus_check;
4729 }
4730
4731 ///////////////////////////////////////
4732
4733 EINTERN void
4734 e_client_stick(E_Client *ec)
4735 {
4736    E_OBJECT_CHECK(ec);
4737    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4738    if (ec->sticky) return;
4739
4740    // call the stick hook of a client
4741    wl_signal_emit(&PRI(ec)->events.stick, NULL);
4742
4743    // send the sticky property event of a client
4744    _e_client_event_property(ec, E_CLIENT_PROPERTY_STICKY);
4745 }
4746
4747 EINTERN void
4748 e_client_unstick(E_Client *ec)
4749 {
4750    E_OBJECT_CHECK(ec);
4751    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4752
4753    if (!ec->sticky) return;
4754
4755    // call the unstick hook of a client
4756    wl_signal_emit(&PRI(ec)->events.unstick, NULL);
4757
4758   // send the sticky property event of a client
4759    _e_client_event_property(ec, E_CLIENT_PROPERTY_STICKY);
4760 }
4761
4762 EINTERN void
4763 e_client_pinned_set(E_Client *ec, Eina_Bool set)
4764 {
4765    E_Layer layer;
4766
4767    EINA_SAFETY_ON_NULL_RETURN(ec);
4768    if (set)
4769      layer = E_LAYER_CLIENT_ABOVE;
4770    else
4771      layer = E_LAYER_CLIENT_NORMAL;
4772
4773    e_client_layer_set(ec, layer);
4774
4775    EC_CHANGED(ec);
4776 }
4777
4778 ///////////////////////////////////////
4779
4780 ///////////////////////////////////////
4781
4782 EINTERN void
4783 e_client_comp_hidden_set(E_Client *ec, Eina_Bool hidden)
4784 {
4785    E_OBJECT_CHECK(ec);
4786    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4787
4788    hidden = !!hidden;
4789    if (ec->comp_hidden == hidden) return;
4790    ec->comp_hidden = hidden;
4791 }
4792
4793 ///////////////////////////////////////
4794
4795 EINTERN void
4796 e_client_act_move_keyboard(E_Client *ec)
4797 {
4798    EINA_SAFETY_ON_NULL_RETURN(ec);
4799
4800    if (!_e_client_move_begin(ec))
4801      return;
4802
4803    _e_client_action_init(ec);
4804    _e_client_action_move_timeout_add();
4805
4806    wl_signal_emit(&PRI(ec)->events.move_update, NULL);
4807    if (!_e_client_hook_call(E_CLIENT_HOOK_MOVE_UPDATE, ec)) return;
4808    evas_object_freeze_events_set(ec->frame, 1);
4809
4810    if (!action_handler_mouse)
4811      action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_client_move_mouse_down, NULL);
4812 }
4813
4814 EINTERN void
4815 e_client_act_resize_keyboard(E_Client *ec)
4816 {
4817    EINA_SAFETY_ON_NULL_RETURN(ec);
4818
4819    ec->resize_mode = E_POINTER_RESIZE_TL;
4820    ec->keyboard_resizing = 1;
4821    if (!e_client_resize_begin(ec))
4822      {
4823         ec->keyboard_resizing = 0;
4824         return;
4825      }
4826
4827    _e_client_action_init(ec);
4828    _e_client_action_resize_timeout_add();
4829    evas_object_freeze_events_set(ec->frame, 1);
4830
4831    if (!action_handler_mouse)
4832      action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_client_resize_mouse_down, NULL);
4833 }
4834
4835 EINTERN void
4836 e_client_act_move_begin(E_Client *ec, E_Binding_Event_Mouse_Button *ev)
4837 {
4838    E_OBJECT_CHECK(ec);
4839    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4840    if (e_client_util_resizing_get(ec) || (ec->moving)) return;
4841    if (ev)
4842      {
4843         char source[256];
4844
4845         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->button);
4846         _e_client_moveinfo_gather(ec, source);
4847      }
4848    if (!_e_client_move_begin(ec))
4849      return;
4850
4851    _e_client_action_init(ec);
4852 }
4853
4854 E_API void
4855 e_client_act_move_end(E_Client *ec, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
4856 {
4857    E_OBJECT_CHECK(ec);
4858    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4859    if (!ec->moving) return;
4860    _e_client_move_end(ec);
4861    _e_client_action_finish();
4862 }
4863
4864 EINTERN void
4865 e_client_act_resize_begin(E_Client *ec, E_Binding_Event_Mouse_Button *ev, E_Pointer_Mode resize_mode)
4866 {
4867    E_OBJECT_CHECK(ec);
4868    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4869    if (ec->lock_user_size) return;
4870    if (e_client_util_resizing_get(ec) || (ec->moving)) return;
4871    if (ev)
4872      {
4873         char source[256];
4874         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->button);
4875         _e_client_moveinfo_gather(ec, source);
4876
4877         if (resize_mode != E_POINTER_RESIZE_NONE)
4878           {
4879              ec->resize_mode = resize_mode;
4880           }
4881         else
4882           {
4883              /* Use canvas.x, canvas.y of event.
4884               * Transformed coordinates has to be considered for accurate resize_mode
4885               * rather than absolute coordinates. */
4886              if ((ev->canvas.x > (ec->x + ec->w / 5)) &&
4887                  (ev->canvas.x < (ec->x + ec->w * 4 / 5)))
4888                {
4889                   if (ev->canvas.y < (ec->y + ec->h / 2)) ec->resize_mode = E_POINTER_RESIZE_T;
4890                   else ec->resize_mode = E_POINTER_RESIZE_B;
4891                }
4892              else if (ev->canvas.x < (ec->x + ec->w / 2))
4893                {
4894                   if ((ev->canvas.y > (ec->y + ec->h / 5)) && (ev->canvas.y < (ec->y + ec->h * 4 / 5))) ec->resize_mode = E_POINTER_RESIZE_L;
4895                   else if (ev->canvas.y < (ec->y + ec->h / 2)) ec->resize_mode = E_POINTER_RESIZE_TL;
4896                   else ec->resize_mode = E_POINTER_RESIZE_BL;
4897                }
4898              else
4899                {
4900                   if ((ev->canvas.y > (ec->y + ec->h / 5)) && (ev->canvas.y < (ec->y + ec->h * 4 / 5))) ec->resize_mode = E_POINTER_RESIZE_R;
4901                   else if (ev->canvas.y < (ec->y + ec->h / 2)) ec->resize_mode = E_POINTER_RESIZE_TR;
4902                   else ec->resize_mode = E_POINTER_RESIZE_BR;
4903                }
4904           }
4905      }
4906    if (!e_client_resize_begin(ec))
4907      return;
4908    _e_client_action_init(ec);
4909 }
4910
4911 EINTERN void
4912 e_client_act_resize_end(E_Client *ec, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
4913 {
4914    E_OBJECT_CHECK(ec);
4915    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4916    if (e_client_util_resizing_get(ec))
4917      {
4918         _e_client_resize_end(ec);
4919         ec->changes.reset_gravity = 1;
4920         if (!e_object_is_del(E_OBJECT(ec)))
4921           EC_CHANGED(ec);
4922      }
4923    _e_client_action_finish();
4924 }
4925
4926 EINTERN void
4927 e_client_act_menu_begin(E_Client *ec, E_Binding_Event_Mouse_Button *ev, int key)
4928 {
4929    E_OBJECT_CHECK(ec);
4930    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4931 }
4932
4933 EINTERN void
4934 e_client_act_close_begin(E_Client *ec)
4935 {
4936    E_OBJECT_CHECK(ec);
4937    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4938    if (ec->lock_close) return;
4939    if (ec->icccm.delete_request)
4940      {
4941         ec->delete_requested = 1;
4942         wl_signal_emit(&PRI(ec)->events.delete_request, ec);
4943      }
4944    else if (e_config->kill_if_close_not_possible)
4945      {
4946         e_client_act_kill_begin(ec);
4947      }
4948 }
4949
4950 EINTERN void
4951 e_client_act_kill_begin(E_Client *ec)
4952 {
4953    E_OBJECT_CHECK(ec);
4954    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4955    if (ec->internal) return;
4956    if (ec->lock_close) return;
4957    if ((ec->netwm.pid > 1) && (e_config->kill_process))
4958      {
4959         kill(ec->netwm.pid, SIGINT);
4960         ec->kill_timer = ecore_timer_add(e_config->kill_timer_wait,
4961                                          _e_client_cb_kill_timer, ec);
4962      }
4963    else
4964      wl_signal_emit(&PRI(ec)->events.kill_request, ec);
4965 }
4966
4967 ////////////////////////////////////////////
4968
4969 EINTERN void
4970 e_client_ping(E_Client *ec)
4971 {
4972    E_OBJECT_CHECK(ec);
4973    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4974
4975    if (!e_config->ping_clients) return;
4976
4977    EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(ec)));
4978
4979    ec->ping_ok = 0;
4980    wl_signal_emit(&PRI(ec)->events.ping, ec);
4981    ec->ping = ecore_loop_time_get();
4982    if (ec->ping_poller) ecore_poller_del(ec->ping_poller);
4983    ec->ping_poller = ecore_poller_add(ECORE_POLLER_CORE,
4984                                       e_config->ping_clients_interval,
4985                                       _e_client_cb_ping_poller, ec);
4986 }
4987
4988 ////////////////////////////////////////////
4989 E_API void
4990 e_client_cursor_map_apply(E_Client *ec, int rotation, int x, int y)
4991 {
4992    // TODO: remove(deprecate) this e_client_cursor_map_apply.
4993 }
4994
4995 EINTERN void
4996 e_client_move_cancel(void)
4997 {
4998    if (!ecmove) return;
4999    if (ecmove->cur_mouse_action)
5000      {
5001         E_Client *ec;
5002
5003         ec = ecmove;
5004         e_object_ref(E_OBJECT(ec));
5005         if (ec->cur_mouse_action->func.end_mouse)
5006           ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", NULL);
5007         else if (ec->cur_mouse_action->func.end)
5008           ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
5009         e_object_unref(E_OBJECT(ec->cur_mouse_action));
5010         ec->cur_mouse_action = NULL;
5011         e_object_unref(E_OBJECT(ec));
5012      }
5013    else
5014      _e_client_move_end(ecmove);
5015 }
5016
5017 EINTERN void
5018 e_client_resize_cancel(void)
5019 {
5020    if (!ecresize) return;
5021    if (ecresize->cur_mouse_action)
5022      {
5023         E_Client *ec;
5024
5025         ec = ecresize;
5026         e_object_ref(E_OBJECT(ec));
5027         if (ec->cur_mouse_action->func.end_mouse)
5028           ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", NULL);
5029         else if (ec->cur_mouse_action->func.end)
5030           ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
5031         e_object_unref(E_OBJECT(ec->cur_mouse_action));
5032         ec->cur_mouse_action = NULL;
5033         e_object_unref(E_OBJECT(ec));
5034      }
5035    else
5036      _e_client_resize_end(ecresize);
5037 }
5038
5039 EINTERN Eina_Bool
5040 e_client_resize_begin(E_Client *ec)
5041 {
5042    if ((ec->fullscreen) || (ec->lock_user_size))
5043      goto error;
5044    if (!_e_client_action_input_win_new()) goto error;
5045    ecresize = ec;
5046    if (ec->manage_resize.enable_aspect_ratio)
5047      {
5048         ELOGF("RESIZE", "Set resize aspect ratio.. ratio(%dx%d)", ec, ec->w, ec->h);
5049         ec->manage_resize.aw = ec->w;
5050         ec->manage_resize.ah = ec->h - ec->manage_resize.header_h - ec->manage_resize.footer_h;
5051      }
5052
5053    wl_signal_emit(&PRI(ec)->events.move_begin, NULL);
5054    _e_client_hook_call(E_CLIENT_HOOK_RESIZE_BEGIN, ec);
5055    if (ec->transformed)
5056      _e_client_transform_resize_begin(ec);
5057    if (!e_client_util_resizing_get(ec))
5058      {
5059         if (ecresize == ec) ecresize = NULL;
5060         _e_client_action_input_win_del();
5061         return EINA_FALSE;
5062      }
5063    if (!ec->lock_user_stacking)
5064      {
5065         if (e_config->border_raise_on_mouse_action)
5066           e_client_raise(ec);
5067      }
5068
5069    if (e_comp->hwc)
5070      e_comp_client_override_add(ec);
5071
5072    return EINA_TRUE;
5073 error:
5074    ec->resize_mode = E_POINTER_RESIZE_NONE;
5075    return EINA_FALSE;
5076 }
5077
5078
5079 ////////////////////////////////////////////
5080
5081 EINTERN void
5082 e_client_signal_move_begin(E_Client *ec, const char *sig, const char *src EINA_UNUSED)
5083 {
5084    E_OBJECT_CHECK(ec);
5085    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5086
5087    if (e_client_util_resizing_get(ec) || (ec->moving)) return;
5088    _e_client_moveinfo_gather(ec, sig);
5089    if (!_e_client_move_begin(ec)) return;
5090 }
5091
5092 EINTERN void
5093 e_client_signal_move_end(E_Client *ec, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
5094 {
5095    E_OBJECT_CHECK(ec);
5096    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5097    if (!ec->moving) return;
5098    _e_client_move_end(ec);
5099 }
5100
5101 EINTERN void
5102 e_client_signal_resize_begin(E_Client *ec, const char *dir, const char *sig, const char *src EINA_UNUSED)
5103 {
5104    int resize_mode = E_POINTER_RESIZE_BR;
5105
5106    E_OBJECT_CHECK(ec);
5107    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5108
5109    if (e_client_util_resizing_get(ec) || (ec->moving)) return;
5110    if (!strcmp(dir, "tl"))
5111      {
5112         resize_mode = E_POINTER_RESIZE_TL;
5113      }
5114    else if (!strcmp(dir, "t"))
5115      {
5116         resize_mode = E_POINTER_RESIZE_T;
5117      }
5118    else if (!strcmp(dir, "tr"))
5119      {
5120         resize_mode = E_POINTER_RESIZE_TR;
5121      }
5122    else if (!strcmp(dir, "r"))
5123      {
5124         resize_mode = E_POINTER_RESIZE_R;
5125      }
5126    else if (!strcmp(dir, "br"))
5127      {
5128         resize_mode = E_POINTER_RESIZE_BR;
5129      }
5130    else if (!strcmp(dir, "b"))
5131      {
5132         resize_mode = E_POINTER_RESIZE_B;
5133      }
5134    else if (!strcmp(dir, "bl"))
5135      {
5136         resize_mode = E_POINTER_RESIZE_BL;
5137      }
5138    else if (!strcmp(dir, "l"))
5139      {
5140         resize_mode = E_POINTER_RESIZE_L;
5141      }
5142    ec->resize_mode = resize_mode;
5143    _e_client_moveinfo_gather(ec, sig);
5144    if (!e_client_resize_begin(ec))
5145      return;
5146 }
5147
5148 EINTERN void
5149 e_client_signal_resize_end(E_Client *ec, const char *dir EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
5150 {
5151    E_OBJECT_CHECK(ec);
5152    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5153    if (!e_client_util_resizing_get(ec)) return;
5154    _e_client_resize_handle(ec);
5155    _e_client_resize_end(ec);
5156    ec->changes.reset_gravity = 1;
5157    EC_CHANGED(ec);
5158 }
5159
5160 ////////////////////////////////////////////
5161
5162 EINTERN void
5163 e_client_resize_limit(E_Client *ec, int *w, int *h)
5164 {
5165    E_OBJECT_CHECK(ec);
5166    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5167
5168    if (ec->frame)
5169      e_comp_object_frame_wh_unadjust(ec->frame, *w, *h, w, h);
5170    if (*h < 1) *h = 1;
5171    if (*w < 1) *w = 1;
5172
5173    if ((ec->icccm.max_w > 0) && (*w > ec->icccm.max_w)) *w = ec->icccm.max_w;
5174    else if (*w < ec->icccm.min_w)
5175      *w = ec->icccm.min_w;
5176    if ((ec->icccm.max_h > 0) && (*h > ec->icccm.max_h)) *h = ec->icccm.max_h;
5177    else if (*h < ec->icccm.min_h)
5178      *h = ec->icccm.min_h;
5179
5180    if (ec->frame)
5181      e_comp_object_frame_wh_adjust(ec->frame, *w, *h, w, h);
5182 }
5183
5184 ////////////////////////////////////////////
5185
5186
5187
5188 EINTERN E_Client *
5189 e_client_under_pointer_get(E_Desk *desk, E_Client *exclude)
5190 {
5191    int x, y;
5192
5193    /* We need to ensure that we can get the comp window for the
5194     * zone of either the given desk or the desk of the excluded
5195     * window, so return if neither is given */
5196    if (desk)
5197      e_input_device_pointer_xy_get(NULL, &x, &y);
5198    else if (exclude)
5199      e_input_device_pointer_xy_get(NULL, &x, &y);
5200    else
5201      return NULL;
5202
5203    if (!desk)
5204      {
5205         desk = exclude->desk;
5206         if (!desk)
5207           {
5208              if (exclude->zone)
5209                desk = e_desk_current_get(exclude->zone);
5210              else
5211                desk = e_desk_current_get(e_zone_current_get());
5212           }
5213      }
5214
5215    return desk ? _e_client_under_pointer_helper(desk, exclude, x, y) : NULL;
5216 }
5217
5218 E_API E_Client *e_client_under_position_get(E_Desk *desk, int x, int y, E_Client *exclude)
5219 {
5220    if (!desk) return NULL;
5221
5222    return _e_client_under_pointer_helper(desk, exclude, x, y);
5223 }
5224
5225 E_API E_Client *e_client_under_position_input_get(E_Desk *desk, int x, int y)
5226 {
5227    if (!desk) return NULL;
5228
5229    return _e_client_under_pointer_input_helper(desk, x, y);
5230 }
5231
5232 ////////////////////////////////////////////
5233
5234 ////////////////////////////////////////////
5235
5236 E_API void
5237 e_client_redirected_set(E_Client *ec, Eina_Bool set)
5238 {
5239    EINA_SAFETY_ON_NULL_RETURN(ec);
5240    if (ec->input_only) return;
5241    set = !!set;
5242    if (ec->redirected == set) return;
5243    if (set)
5244      {
5245         wl_signal_emit(&PRI(ec)->events.redirect, NULL);
5246         if (!_e_client_hook_call(E_CLIENT_HOOK_REDIRECT, ec)) return;
5247      }
5248    else
5249      {
5250         wl_signal_emit(&PRI(ec)->events.unredirect, NULL);
5251         if (!_e_client_hook_call(E_CLIENT_HOOK_UNREDIRECT, ec)) return;
5252      }
5253    e_comp_object_redirected_set(ec->frame, set);
5254    ec->redirected = !!set;
5255 }
5256
5257 ////////////////////////////////////////////
5258
5259 E_API void
5260 e_client_transform_update(E_Client *ec)
5261 {
5262    if (e_client_util_resizing_get(ec))
5263      _e_client_transform_resize(ec);
5264 }
5265
5266 ////////////////////////////////////////////
5267
5268 EINTERN void
5269 e_client_transform_apply(E_Client *ec, double angle, double zoom, int cx, int cy)
5270 {
5271    E_Map *map;
5272    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
5273    E_Client *subc;
5274    Eina_List *l;
5275
5276    if (e_comp_wl_subsurface_check(ec))
5277      return;
5278
5279    /* check if it's different with current state */
5280    if ((ec->transform.angle == angle) &&
5281        (ec->transform.zoom == zoom) &&
5282        (ec->transform.center.x == cx) &&
5283        (ec->transform.center.y == cy))
5284      return;
5285
5286    /* use previous value if any required value is invalid */
5287    if (angle == -1.0)
5288      angle = ec->transform.angle;
5289    if (zoom == -1.0)
5290      zoom = ec->transform.zoom;
5291    if (!E_INSIDE(cx, cy,
5292                  ec->client.x, ec->client.y,
5293                  ec->client.w, ec->client.h))
5294      {
5295         cx = ec->transform.center.x;
5296         cy = ec->transform.center.y;
5297      }
5298
5299    if ((angle == 0) && (zoom == 1.0))
5300      {
5301         e_client_transform_clear(ec);
5302         return;
5303      }
5304
5305    map = e_map_new_with_direct_render(ec->transform_core.direct_render);
5306    e_map_util_points_populate_from_object_full(map, ec->frame, 0);
5307
5308    e_map_util_rotate(map, angle, cx, cy);
5309    _e_client_transform_geometry_save(ec, map);
5310
5311    e_map_util_zoom(map, zoom, zoom, cx, cy);
5312
5313    e_map_util_object_move_sync_set(map, EINA_TRUE);
5314    e_client_map_set(ec, map);
5315    e_client_map_enable_set(ec, EINA_TRUE);
5316
5317    EINA_LIST_FOREACH(cdata->sub.list, l, subc)
5318      _e_client_transform_sub_apply(subc, ec, zoom);
5319    EINA_LIST_REVERSE_FOREACH(cdata->sub.below_list, l, subc)
5320      _e_client_transform_sub_apply(subc, ec, zoom);
5321
5322    e_map_free(map);
5323
5324    ec->transform.zoom = zoom;
5325    ec->transform.angle = angle;
5326    ec->transform.center.x = cx;
5327    ec->transform.center.y = cy;
5328    ec->transformed = EINA_TRUE;
5329 }
5330
5331 ////////////////////////////////////////////
5332
5333 EINTERN void
5334 e_client_transform_clear(E_Client *ec)
5335 {
5336    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
5337    E_Client *subc;
5338    Eina_List *l;
5339
5340    e_client_map_enable_set(ec, EINA_FALSE);
5341    e_client_map_set(ec, NULL);
5342
5343    EINA_LIST_FOREACH(cdata->sub.list, l, subc)
5344      _e_client_transform_sub_apply(subc, ec, 1.0);
5345    EINA_LIST_REVERSE_FOREACH(cdata->sub.below_list, l, subc)
5346      _e_client_transform_sub_apply(subc, ec, 1.0);
5347
5348    ec->transform.zoom = 1.0;
5349    ec->transform.angle = 0.0;
5350    ec->transformed = EINA_FALSE;
5351 }
5352
5353 E_API Eina_Bool
5354 e_client_transform_core_enable_get(E_Client *ec)
5355 {
5356    if (!ec) return EINA_FALSE;
5357    return ec->transform_core.result.enable;
5358 }
5359
5360 E_API void
5361 e_client_transform_core_add(E_Client *ec, E_Util_Transform *transform)
5362 {
5363    if (!ec) return;
5364    if (!transform) return;
5365
5366    // duplication check
5367    if (ec->transform_core.transform_list &&
5368        eina_list_data_find(ec->transform_core.transform_list, transform) == transform)
5369      {
5370         return;
5371      }
5372
5373    ec->transform_core.transform_list = eina_list_append(ec->transform_core.transform_list, transform);
5374    ec->transform_core.changed = EINA_TRUE;
5375    e_util_transform_ref(transform);
5376   // e_client_transform_core_update(ec);
5377 }
5378
5379 E_API void
5380 e_client_transform_core_remove(E_Client *ec, E_Util_Transform *transform)
5381 {
5382    if (!ec) return;
5383    if (!transform) return;
5384
5385    if (ec->transform_core.transform_list &&
5386        eina_list_data_find(ec->transform_core.transform_list, transform) == transform)
5387      {
5388         ec->transform_core.transform_list = eina_list_remove(ec->transform_core.transform_list, transform);
5389         e_util_transform_unref(transform);
5390         ec->transform_core.changed = EINA_TRUE;
5391      }
5392
5393    e_client_transform_core_update(ec);
5394 }
5395
5396 E_API void
5397 e_client_transform_core_update(E_Client *ec)
5398 {
5399    if (!ec) return;
5400    if (ec->new_client) return;
5401    if (!_e_client_transform_core_check_change(ec)) return;
5402
5403    if (ec->transform_core.transform_list || ec->transform_core.parent.enable)
5404      {
5405         E_Util_Transform_Rect source_rect;
5406         E_Util_Transform_Matrix matrix, boundary_matrix;
5407         E_Util_Transform_Zoom zoom;
5408         Eina_List *l;
5409         Eina_Bool background;
5410         E_Util_Transform *temp_trans;
5411
5412         // 1. init state
5413         ec->transform_core.result.enable = EINA_TRUE;
5414         e_util_transform_rect_client_rect_get(&source_rect, ec);
5415         e_util_transform_init(&ec->transform_core.result.transform);
5416
5417         // 2. merge transform
5418         EINA_LIST_FOREACH(ec->transform_core.transform_list, l, temp_trans)
5419           {
5420              e_util_transform_merge(&ec->transform_core.result.transform, temp_trans);
5421           }
5422         zoom = ec->transform_core.result.transform.zoom;
5423
5424         // 2.5 check viewport
5425         if (e_util_transform_viewport_flag_get(&ec->transform_core.result.transform))
5426           {
5427              int vx = 0, vy = 0, vw = 0, vh = 0;
5428              e_util_transform_viewport_get(&ec->transform_core.result.transform, &vx, &vy, &vw, &vh);
5429              e_util_transform_rect_init(&source_rect, vx, vy, vw, vh);
5430           }
5431
5432         // 3. apply background transform
5433         matrix = e_util_transform_convert_to_matrix(&ec->transform_core.result.transform, &source_rect);
5434
5435         if (e_util_transform_bg_transform_flag_get(&ec->transform_core.result.transform))
5436           {
5437              boundary_matrix = e_util_transform_bg_convert_to_matrix(&ec->transform_core.result.transform, &source_rect);
5438              background = EINA_TRUE;
5439           }
5440         else
5441           {
5442              background = EINA_FALSE;
5443              boundary_matrix = matrix;
5444           }
5445
5446         if (background != ec->transform_core.background)
5447           {
5448              if (background)
5449                {
5450                   e_comp_object_transform_bg_set(ec->frame, EINA_TRUE);
5451                }
5452              else
5453                {
5454                   e_comp_object_transform_bg_set(ec->frame, EINA_FALSE);
5455                }
5456
5457              ec->transform_core.background = background;
5458           }
5459
5460         // 3.1 if 24bit window then set transp rect
5461         if (!ec->argb)
5462           {
5463              int angle = 0;
5464
5465              e_util_transform_rotation_round_get(&ec->transform_core.result.transform, 0, 0, &angle);
5466              angle %= 90;
5467
5468              if (angle == 0) // when transform angle is 0, 90, 180, 270, 360. then set transp rect
5469                e_comp_object_transform_transp_set(ec->frame, EINA_TRUE);
5470              else
5471                e_comp_object_transform_transp_set(ec->frame, EINA_FALSE);
5472           }
5473         else
5474           e_comp_object_transform_transp_set(ec->frame, EINA_FALSE);
5475
5476         // 3.5 parent matrix multiply
5477         if (ec->transform_core.parent.enable)
5478           {
5479              matrix = e_util_transform_matrix_multiply(&ec->transform_core.parent.matrix,
5480                                                        &matrix);
5481              boundary_matrix = e_util_transform_matrix_multiply(&ec->transform_core.parent.matrix,
5482                                                                 &boundary_matrix);
5483
5484              ec->transform_core.result.transform.use_zoom = EINA_TRUE;
5485              zoom.zoom_x *= ec->transform_core.parent.zoom.zoom_x;
5486              zoom.zoom_y *= ec->transform_core.parent.zoom.zoom_y;
5487              zoom.cx += ec->transform_core.parent.zoom.cx;
5488              zoom.cy += ec->transform_core.parent.zoom.cy;
5489           }
5490
5491         // 4. apply matrix to vertices
5492         ec->transform_core.result.matrix = matrix;
5493         ec->transform_core.result.inv_matrix = e_util_transform_matrix_inverse_get(&matrix);
5494         ec->transform_core.result.vertices = e_util_transform_rect_to_vertices(&source_rect);
5495         ec->transform_core.result.boundary.vertices = e_util_transform_rect_to_vertices(&source_rect);
5496         ec->transform_core.result.vertices = e_util_transform_matrix_multiply_rect_vertex(&matrix,
5497                                                                                           &ec->transform_core.result.vertices);
5498         ec->transform_core.result.boundary.vertices = e_util_transform_matrix_multiply_rect_vertex(&boundary_matrix,
5499                                                                                                    &ec->transform_core.result.boundary.vertices);
5500         ec->transform_core.result.transform.zoom = zoom;
5501
5502         // 5. apply vertices
5503         if (ec->transform_core.result.transform.use_zoom)
5504           {
5505              // TODO: apply zoom values to vertices
5506              e_comp_object_transform_transp_vertices_set_with_zoom(ec->frame, &ec->transform_core.result.vertices,
5507                                                                    ec->transform_core.result.transform.zoom);
5508              e_comp_object_transform_bg_vertices_set_with_zoom(ec->frame, &ec->transform_core.result.boundary.vertices,
5509                                                                ec->transform_core.result.transform.zoom);
5510              _e_client_transform_core_boundary_update(ec, &ec->transform_core.result.boundary.vertices);
5511              _e_client_transform_core_vertices_apply_with_zoom(ec, ec->frame, &ec->transform_core.result.vertices, &ec->transform_core.result.transform,
5512                                                                ec->transform_core.result.transform.zoom);
5513           }
5514         else
5515           {
5516              e_comp_object_transform_transp_vertices_set(ec->frame, &ec->transform_core.result.vertices);
5517              e_comp_object_transform_bg_vertices_set(ec->frame, &ec->transform_core.result.boundary.vertices);
5518              _e_client_transform_core_boundary_update(ec, &ec->transform_core.result.boundary.vertices);
5519              _e_client_transform_core_vertices_apply(ec, ec->frame, &ec->transform_core.result.vertices, &ec->transform_core.result.transform);
5520           }
5521
5522         // 6. subsurface update
5523         _e_client_transform_core_sub_update(ec, &ec->transform_core.result.vertices);
5524
5525         if (!e_object_is_del(E_OBJECT(ec)))
5526           {
5527              wl_signal_emit(&PRI(ec)->events.transform_change, NULL);
5528              _e_client_hook_call(E_CLIENT_HOOK_TRANSFORM_CHANGE, ec);
5529           }
5530      }
5531    else
5532      {
5533         if (ec->transform_core.result.enable)
5534           {
5535              ec->transform_core.result.enable = EINA_FALSE;
5536              _e_client_transform_core_vertices_apply(ec, ec->frame, NULL, NULL);
5537              e_comp_object_transform_bg_set(ec->frame, EINA_FALSE);
5538              ec->transform_core.background = EINA_FALSE;
5539              e_comp_object_transform_transp_set(ec->frame, EINA_FALSE);
5540              _e_client_transform_core_sub_update(ec, NULL);
5541
5542              if (!e_object_is_del(E_OBJECT(ec)))
5543                {
5544                   wl_signal_emit(&PRI(ec)->events.transform_change, NULL);
5545                   _e_client_hook_call(E_CLIENT_HOOK_TRANSFORM_CHANGE, ec);
5546                }
5547           }
5548      }
5549
5550    e_comp_visibility_calculation_set(EINA_TRUE);
5551 }
5552
5553 E_API int
5554 e_client_transform_core_transform_count_get(E_Client *ec)
5555 {
5556    if (!ec) return 0;
5557    if (!ec->transform_core.transform_list) return 0;
5558    return eina_list_count(ec->transform_core.transform_list);
5559 }
5560
5561 E_API E_Util_Transform*
5562 e_client_transform_core_transform_get(E_Client *ec, int index)
5563 {
5564    if (!ec) return NULL;
5565    if (!ec->transform_core.transform_list) return NULL;
5566    if (index < 0 || index >= e_client_transform_core_transform_count_get(ec))
5567       return NULL;
5568
5569    return (E_Util_Transform*)eina_list_nth(ec->transform_core.transform_list, index);
5570 }
5571
5572 E_API void
5573 e_client_transform_core_input_transform(E_Client *ec, int x, int y, int *out_x, int *out_y)
5574 {
5575    E_Util_Transform_Vertex vertex, result_vertex;
5576
5577    if (!ec) return;
5578    if (!e_client_transform_core_enable_get(ec)) return;
5579
5580    e_util_transform_vertex_init(&vertex, x, y, 0.0, 1.0);
5581
5582    result_vertex = e_util_transform_matrix_multiply_vertex(&ec->transform_core.result.inv_matrix, &vertex);
5583    e_util_transform_vertex_pos_round_get(&result_vertex, out_x, out_y, NULL, NULL);
5584 }
5585
5586 E_API void
5587 e_client_transform_core_input_inv_transform(E_Client *ec, int x, int y, int *out_x, int *out_y)
5588 {
5589    E_Util_Transform_Vertex vertex, result_vertex;
5590
5591    if (!ec) return;
5592    if (!e_client_transform_core_enable_get(ec)) return;
5593
5594    e_util_transform_vertex_init(&vertex, x, y, 0.0, 1.0);
5595
5596    result_vertex = e_util_transform_matrix_multiply_vertex(&ec->transform_core.result.matrix, &vertex);
5597    e_util_transform_vertex_pos_round_get(&result_vertex, out_x, out_y, NULL, NULL);
5598 }
5599
5600 EINTERN void
5601 e_client_transform_core_input_inv_rect_transform(E_Client *ec, int x, int y, int *out_x, int *out_y)
5602 {
5603    int gw = 0, gh = 0;
5604    if (!ec) return;
5605    if (!e_client_transform_core_enable_get(ec)) return;
5606    e_client_geometry_get(ec, NULL, NULL, &gw, &gh);
5607
5608    e_util_transform_matrix_inv_rect_coords_get(&ec->transform_core.result.transform,
5609                                                &ec->transform_core.result.vertices,
5610                                                gw, gh,
5611                                                x, y, out_x, out_y);
5612 }
5613
5614 E_API void
5615 e_client_transform_core_direct_render_set(E_Client *ec, Eina_Bool set)
5616 {
5617    EINA_SAFETY_ON_NULL_RETURN(ec);
5618
5619    if (ec->transform_core.direct_render == set) return;
5620
5621    ec->transform_core.direct_render = set;
5622    ec->transform_core.changed = EINA_TRUE;
5623
5624    e_client_transform_core_update(ec);
5625 }
5626
5627 EINTERN E_Pixmap *
5628 e_client_pixmap_change(E_Client *ec, E_Pixmap *newcp)
5629 {
5630    E_Pixmap_Type oldtype, newtype;
5631    E_Pixmap *oldcp;
5632
5633    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
5634    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->pixmap, NULL);
5635    EINA_SAFETY_ON_NULL_RETURN_VAL(newcp, NULL);
5636
5637    oldcp = ec->pixmap;
5638
5639    oldtype = e_pixmap_type_get(oldcp);
5640    if (oldtype >= E_PIXMAP_TYPE_MAX) return NULL;
5641
5642    newtype = e_pixmap_type_get(newcp);
5643    if (newtype >= E_PIXMAP_TYPE_MAX) return NULL;
5644
5645    if (eina_hash_find(clients_hash[oldtype], &oldcp))
5646      eina_hash_del_by_key(clients_hash[oldtype], &oldcp);
5647    e_pixmap_client_set(oldcp, NULL);
5648
5649    ec->pixmap = newcp;
5650    e_pixmap_client_set(newcp, ec);
5651
5652    eina_hash_add(clients_hash[newtype], &newcp, ec);
5653
5654    return oldcp;
5655 }
5656
5657 E_API void
5658 e_client_window_role_set(E_Client *ec, const char *role)
5659 {
5660    EINA_SAFETY_ON_NULL_RETURN(ec);
5661
5662    if (eina_stringshare_replace(&ec->icccm.window_role, role))
5663      {
5664         wl_signal_emit(&PRI(ec)->events.window_role_change, NULL);
5665         _e_client_hook_call(E_CLIENT_HOOK_WINDOW_ROLE_CHANGE, ec);
5666      }
5667 }
5668
5669 EINTERN Eina_Bool
5670 e_client_key_send(E_Client *ec, int keycode, Eina_Bool pressed, Ecore_Device *dev, unsigned int time)
5671 {
5672    Eina_Bool res;
5673
5674    res = e_comp_wl_key_send(ec, keycode, pressed, dev, time);
5675
5676    return res;
5677 }
5678
5679 EINTERN Eina_Bool
5680 e_client_key_cancel(E_Client *ec, int keycode, Ecore_Device *dev, unsigned int time)
5681 {
5682    Eina_Bool res;
5683
5684    res = e_comp_wl_key_cancel(ec, keycode, dev, time);
5685
5686    return res;
5687 }
5688
5689 EINTERN Eina_Bool
5690 e_client_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, unsigned int time)
5691 {
5692    Eina_Bool res;
5693
5694    res = e_comp_wl_touch_send(ec, idx, x, y, pressed, dev, radius_x, radius_y, pressure, angle, time);
5695
5696    return res;
5697 }
5698
5699 EINTERN Eina_Bool
5700 e_client_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, unsigned int time)
5701 {
5702    Eina_Bool res;
5703
5704    res = e_comp_wl_touch_update_send(ec, idx, x, y, dev, radius_x, radius_y, pressure, angle, time);
5705
5706    return res;
5707 }
5708
5709 EINTERN Eina_Bool
5710 e_client_touch_cancel_send(E_Client *ec)
5711 {
5712    Eina_Bool res;
5713
5714    res = e_comp_wl_touch_cancel_send(ec);
5715
5716    return res;
5717 }
5718
5719 EINTERN Eina_Bool
5720 e_client_mouse_button_send(E_Client *ec, int buttons, Eina_Bool pressed, Ecore_Device *dev, unsigned int time)
5721 {
5722    Eina_Bool res;
5723
5724    res = e_comp_wl_mouse_button_send(ec, buttons, pressed, dev, time);
5725
5726    return res;
5727 }
5728
5729 EINTERN Eina_Bool
5730 e_client_mouse_move_send(E_Client *ec, int x, int y, Ecore_Device *dev, unsigned int time)
5731 {
5732    Eina_Bool res;
5733
5734    res = e_comp_wl_mouse_move_send(ec, x, y, dev, time);
5735
5736    return res;
5737 }
5738
5739 EINTERN Eina_Bool
5740 e_client_mouse_wheel_send(E_Client *ec, int direction, int z, Ecore_Device *dev, unsigned int time)
5741 {
5742    Eina_Bool res;
5743
5744    res = e_comp_wl_mouse_wheel_send(ec, direction, z, dev, time);
5745
5746    return res;
5747 }
5748
5749 EINTERN Eina_Bool
5750 e_client_mouse_in_send(E_Client *ec, int x, int y, Ecore_Device *dev, unsigned int time)
5751 {
5752    Eina_Bool res;
5753
5754    res = e_comp_wl_mouse_in_send(ec, x, y, dev, time);
5755
5756    return res;
5757 }
5758
5759 EINTERN Eina_Bool
5760 e_client_mouse_out_send(E_Client *ec, Ecore_Device *dev, unsigned int time)
5761 {
5762    Eina_Bool res;
5763
5764    res = e_comp_wl_mouse_out_send(ec, dev, time);
5765
5766    return res;
5767 }
5768
5769 E_API Eina_Bool
5770 e_client_video_client_has(E_Client *ec)
5771 {
5772    return e_comp_wl_video_subsurface_has(ec);
5773 }
5774
5775 E_API Eina_Bool
5776 e_client_normal_client_has(E_Client *ec)
5777 {
5778    return e_comp_wl_normal_subsurface_has(ec);
5779 }
5780
5781 E_API Eina_Bool
5782 e_client_cursor_hide(E_Client *ec)
5783 {
5784    return e_comp_wl_cursor_hide(ec);
5785 }
5786
5787 E_API void
5788 e_client_visibility_force_obscured_set(E_Client *ec, Eina_Bool set)
5789 {
5790    if (!ec) return;
5791
5792    ELOGF("TZVIS", "VIS_FORCE_OBSCURED :%d", ec, set);
5793
5794    ec->visibility.force_obscured = set;
5795    e_comp_visibility_calculation_set(EINA_TRUE);
5796 }
5797
5798 EINTERN E_Capture_Save_State
5799 e_client_image_save(E_Client *ec, const char *dir, const char *name, E_Capture_Client_Save_End_Cb func_end, void *data, Eina_Bool skip_child)
5800 {
5801    return e_comp_wl_capture_client_image_save(ec, dir, name, func_end, data, skip_child);
5802 }
5803
5804 static void
5805 _e_client_base_output_resolution_hook_subsurf_create(void *data, E_Client *subc)
5806 {
5807    E_Client *ec, *parent;
5808
5809    ec = data;
5810    if (ec != subc)
5811      return;
5812
5813    ec->base_output_resolution.use = 0;
5814    ec->base_output_resolution.w = 0;
5815    ec->base_output_resolution.h = 0;
5816    if (ec->base_output_resolution.transform)
5817      {
5818         e_client_transform_core_remove(ec, ec->base_output_resolution.transform);
5819         E_FREE_FUNC(ec->base_output_resolution.transform, e_util_transform_del);
5820         ELOGF("POL_APPINFO", "Cancel TRANSFORM for subsurface", ec);
5821      }
5822
5823    /* Update transform for toplevel surface.
5824     * The transform of subsurface will be updated by its parent accordingly. */
5825    parent = e_comp_wl_topmost_parent_get(ec);
5826    if (parent)
5827      {
5828         parent->transform_core.changed = EINA_TRUE;
5829         e_client_transform_core_update(parent);
5830      }
5831
5832    /* TODO: Do we need to apply it again if subsurface is destroyed? */
5833 }
5834
5835 static void
5836 _e_client_base_output_resolution_set(E_Client *ec, int width, int height)
5837 {
5838    if (!ec) return;
5839    ec->base_output_resolution.use = 1;
5840    ec->base_output_resolution.w = width;
5841    ec->base_output_resolution.h = height;
5842    ec->base_output_resolution.transform = e_util_transform_new();
5843    e_util_transform_role_set(ec->base_output_resolution.transform, "base_output_resolution");
5844    e_client_transform_core_add(ec, ec->base_output_resolution.transform);
5845
5846    if (!ec->base_output_resolution.hook_subsurf_create)
5847      {
5848         ec->base_output_resolution.hook_subsurf_create =
5849            e_comp_wl_hook_add(E_COMP_WL_HOOK_SUBSURFACE_CREATE,
5850                               _e_client_base_output_resolution_hook_subsurf_create,
5851                               ec);
5852      }
5853 }
5854
5855 E_API void
5856 e_client_base_output_resolution_transform_adjust(E_Client *ec)
5857 {
5858    E_Desk *desk;
5859
5860    EINA_SAFETY_ON_NULL_RETURN(ec);
5861    if (!ec->base_output_resolution.use) return;
5862    if (!ec->base_output_resolution.transform) return;
5863
5864    desk = e_comp_desk_find_by_ec(ec);
5865    EINA_SAFETY_ON_NULL_RETURN(desk);
5866
5867    ELOGF("POL_APPINFO", "Apply TRANSFORM... desk:(%dx%d), ec:(%dx%d)",
5868          ec, desk->geom.w, desk->geom.h, ec->w, ec->h);
5869
5870    e_util_transform_scale(ec->base_output_resolution.transform,
5871                           (double)desk->geom.w /(double)ec->base_output_resolution.w,
5872                           (double)desk->geom.h /(double)ec->base_output_resolution.h,
5873                           1.0);
5874    e_client_transform_core_update(ec);
5875 }
5876
5877 E_API Eina_Bool
5878 e_client_base_output_resolution_update(E_Client *ec)
5879 {
5880    E_Appinfo *eai = NULL;
5881    int configured_width, configured_height;
5882    int width, height;
5883    E_Desk *desk;
5884
5885    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
5886
5887   if (!e_config->configured_output_resolution.use) return EINA_TRUE;
5888   if (ec->base_output_resolution.use) return EINA_TRUE;
5889
5890   /* Check whether it's subsurface or not
5891    * The resolution of subsurface will follow the resolution of its toplevel surface.
5892    * Transform for subsurface will be applied when toplevel surface does by
5893    * implementation of e_client_transform_core.
5894    */
5895   if (e_comp_wl_subsurface_check(ec))
5896     return EINA_FALSE;
5897
5898    desk = e_comp_desk_find_by_ec(ec);
5899    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
5900
5901   configured_width = e_config->configured_output_resolution.w;
5902   configured_height = e_config->configured_output_resolution.h;
5903
5904   if (!ec->netwm.pid)
5905     {
5906        ELOGF("POL_APPINFO", "NO PID... USE configured_output_resolution(%d,%d) pid:%d", ec,
5907              configured_width, configured_height, ec->netwm.pid);
5908        goto use_configured;
5909     }
5910
5911    eai = e_appinfo_find_with_pid(ec->netwm.pid);
5912    if (!eai)
5913      {
5914         ELOGF("POL_APPINFO", "NO APPINFO... USE configured_output_resolution(%d,%d) pid:%d", ec,
5915               configured_width, configured_height, ec->netwm.pid);
5916         goto use_configured;
5917      }
5918
5919    if (!e_appinfo_base_output_resolution_available_get(eai))
5920      {
5921         ELOGF("POL_APPINFO", "NO AVAILABLE BASE SCREEN RESOLUTION... QUERY base_output_resolution", ec);
5922         e_policy_base_output_resolution_info_update(ec->netwm.pid);
5923      }
5924
5925    if (!e_appinfo_base_output_resolution_get(eai, &width, &height))
5926      {
5927         ELOGF("POL_APPINFO", "NO BASE SCREEN RESOLUTION... USE configured_output_resolution(%d,%d) pid:%d", ec,
5928               configured_width, configured_height, ec->netwm.pid);
5929         goto use_configured;
5930       }
5931
5932    if ((width == 0) && (height == 0))
5933      {
5934         ELOGF("POL_APPINFO", "SKIP SET BASE SCREEN RESOLUTION... base_output_resolution size:(%d,%d) pid:%d", ec, width, height, ec->netwm.pid);
5935         return EINA_TRUE;
5936      }
5937
5938    if ((desk->geom.w == width) && (desk->geom.h == height))
5939      {
5940         ELOGF("POL_APPINFO", "SKIP SET BASE SCREEN RESOLUTION... base_output_resolution is same with desk size:(%d,%d), pid:%d", ec, width, height, ec->netwm.pid);
5941         return EINA_TRUE;
5942      }
5943
5944    /* set the base_output_resolution of the e_client */
5945    _e_client_base_output_resolution_set(ec, width, height);
5946
5947    ELOGF("POL_APPINFO", "USE base_output_resolution(%d,%d) pid:%d", ec, width, height, ec->netwm.pid);
5948
5949    return EINA_TRUE;
5950
5951 use_configured:
5952
5953    if ((desk->geom.w == configured_width) && (desk->geom.h == configured_height))
5954      {
5955         ELOGF("POL_APPINFO", "SKIP use configured_output_resolution (same with desk size:(%d,%d), pid:%d)", ec, configured_width, configured_height, ec->netwm.pid);
5956      }
5957    else
5958      {
5959         /* set the base_output_resolution of the e_client as a default */
5960         _e_client_base_output_resolution_set(ec, configured_width, configured_height);
5961      }
5962
5963    return EINA_TRUE;
5964 }
5965
5966 E_API Eina_Bool
5967 e_client_base_output_resolution_useful_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
5968 {
5969    int zx, zy, zw, zh;
5970    E_Zone *zone;
5971
5972    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
5973
5974    zone = e_comp_zone_find_by_ec(ec);
5975    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
5976
5977    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
5978
5979    if (x) *x = zx;
5980    if (y) *y = zy;
5981    if (w) *w = zw;
5982    if (h) *h = zh;
5983
5984    if (ec->base_output_resolution.use)
5985      {
5986         if (w) *w = ec->base_output_resolution.w;
5987         if (h) *h = ec->base_output_resolution.h;
5988      }
5989
5990    return EINA_TRUE;
5991 }
5992
5993 E_API Eina_Bool
5994 e_client_base_output_resolution_desk_useful_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h, Eina_Bool consider_obstacle_area)
5995 {
5996    int zx, zy, zw, zh;
5997    E_Zone *zone;
5998
5999    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
6000
6001    zone = e_comp_zone_find_by_ec(ec);
6002    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
6003
6004    e_zone_desk_useful_geometry_get(zone, ec->desk, &zx, &zy, &zw, &zh, consider_obstacle_area);
6005
6006    if (x) *x = zx;
6007    if (y) *y = zy;
6008    if (w) *w = zw;
6009    if (h) *h = zh;
6010
6011    if (ec->base_output_resolution.use)
6012      {
6013         // TODO: Consider obstacle area
6014         if (w) *w = ec->base_output_resolution.w;
6015         if (h) *h = ec->base_output_resolution.h;
6016      }
6017
6018    return EINA_TRUE;
6019 }
6020
6021 /* change the base_output_resolution of the bind_ec by checking the base_output_resolution of provider_ec's appinfo */
6022 EINTERN Eina_Bool
6023 e_client_base_output_resolution_rsm_update(E_Client *bind_ec, E_Client *provider_ec)
6024 {
6025    E_Appinfo *epai = NULL;
6026    int configured_width, configured_height;
6027    int width, height;
6028    E_Desk *bind_ec_desk;
6029
6030    EINA_SAFETY_ON_NULL_RETURN_VAL(bind_ec, EINA_FALSE);
6031    EINA_SAFETY_ON_NULL_RETURN_VAL(provider_ec, EINA_FALSE);
6032
6033    bind_ec_desk = e_comp_desk_find_by_ec(bind_ec);
6034    EINA_SAFETY_ON_NULL_RETURN_VAL(bind_ec_desk, EINA_FALSE);
6035
6036   if (!e_config->configured_output_resolution.use) return EINA_TRUE;
6037
6038   configured_width = e_config->configured_output_resolution.w;
6039   configured_height = e_config->configured_output_resolution.h;
6040
6041   if (bind_ec->base_output_resolution.use)
6042     {
6043        ELOGF("POL_APPINFO", "DELETE EXISTED BINDER BASE SCREEN RESOLUTION... base_output_resolution is same with desk size:(%d,%d), bind_pid:%d", bind_ec,
6044              bind_ec->base_output_resolution.w, bind_ec->base_output_resolution.h, bind_ec->netwm.pid);
6045
6046        bind_ec->base_output_resolution.use = 0;
6047        bind_ec->base_output_resolution.w = 0;
6048        bind_ec->base_output_resolution.h = 0;
6049        e_client_transform_core_remove(bind_ec, bind_ec->base_output_resolution.transform);
6050        E_FREE_FUNC(bind_ec->base_output_resolution.transform, e_util_transform_del);
6051     }
6052
6053   if (!provider_ec->netwm.pid)
6054     {
6055        ELOGF("POL_APPINFO", "NO PROVIDER PID... USE configured_output_resolution(%d,%d) provider_pid:%d", provider_ec,
6056              configured_width, configured_height, provider_ec->netwm.pid);
6057        goto use_configured;
6058     }
6059
6060    epai = e_appinfo_find_with_pid(provider_ec->netwm.pid);
6061    if (!epai)
6062      {
6063         ELOGF("POL_APPINFO", "NO PROVIDER APPINFO... USE configured_output_resolution(%d,%d) provider_pid:%d", provider_ec,
6064               configured_width, configured_height, provider_ec->netwm.pid);
6065         goto use_configured;
6066      }
6067
6068    if (!e_appinfo_base_output_resolution_get(epai, &width, &height))
6069      {
6070         ELOGF("POL_APPINFO", "NO PROVIDER APPINFO BASE SCREEN RESOLUTION... USE configured_output_resolution(%d,%d) provider_pid:%d", provider_ec,
6071               configured_width, configured_height, provider_ec->netwm.pid);
6072         goto use_configured;
6073       }
6074
6075    if ((width == 0) && (height == 0))
6076      {
6077         ELOGF("POL_APPINFO", "NO PROVIDER WIDTH and HEIGHT... SKIP base_output_resolution due to size:(%d,%d) provider_pid:%d", provider_ec,
6078              width, height, provider_ec->netwm.pid);
6079         return EINA_TRUE;
6080      }
6081
6082    if ((bind_ec_desk->geom.w == width) && (bind_ec_desk->geom.h == height))
6083      {
6084         ELOGF("POL_APPINFO", "SKIP SET BINDER BASE SCREEN RESOLUTION... base_output_resolution is same with desk size:(%d,%d), bind_pid:%d", bind_ec,
6085             width, height, bind_ec->netwm.pid);
6086         return EINA_TRUE;
6087      }
6088
6089    /* set the base_output_resolution of the e_client */
6090    _e_client_base_output_resolution_set(bind_ec, width, height);
6091    e_client_base_output_resolution_transform_adjust(bind_ec);
6092
6093    ELOGF("POL_APPINFO", "USE BINDER base_output_resolution(%d,%d) bind_pid:%d", bind_ec, width, height, bind_ec->netwm.pid);
6094
6095    return EINA_TRUE;
6096
6097 use_configured:
6098
6099    if ((bind_ec_desk->geom.w == configured_width) && (bind_ec_desk->geom.h == configured_height))
6100      {
6101         ELOGF("POL_APPINFO", "SKIP BINDER use configured_output_resolution (same with desk size:(%d,%d), bind_pid:%d)", bind_ec,
6102              configured_width, configured_height, bind_ec->netwm.pid);
6103      }
6104    else
6105      {
6106         /* set the base_output_resolution of the e_client as a default */
6107         _e_client_base_output_resolution_set(bind_ec, configured_width, configured_height);
6108      }
6109
6110    return EINA_TRUE;
6111 }
6112
6113 /* tizen_move_resize */
6114 EINTERN Eina_Bool
6115 e_client_pending_geometry_has(E_Client *ec)
6116 {
6117    if (!eina_list_count(ec->surface_sync.pending_geometry))
6118      return EINA_FALSE;
6119
6120    return ec->surface_sync.wait_commit;
6121 }
6122
6123 EINTERN void
6124 e_client_pending_geometry_flush(E_Client *ec)
6125 {
6126    E_Client_Pending_Geometry *geo;
6127
6128    if (!eina_list_count(ec->surface_sync.pending_geometry))
6129      {
6130         EINA_LIST_FREE(ec->surface_sync.pending_geometry, geo)
6131           {
6132              E_FREE(geo);
6133           }
6134         ec->surface_sync.wait_commit = EINA_FALSE;
6135         ELOGF("POSSIZE", "pending geometry has flushed", ec);
6136      }
6137 }
6138
6139 EINTERN void
6140 e_client_pending_geometry_last_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
6141 {
6142    Eina_List *l;
6143    E_Client_Pending_Geometry *geo;
6144    int gx = 0;
6145    int gy = 0;
6146    int gw = 0;
6147    int gh = 0;
6148
6149    EINA_LIST_REVERSE_FOREACH(ec->surface_sync.pending_geometry, l, geo)
6150      {
6151         gx = geo->x;
6152         gy = geo->y;
6153         gw = geo->w;
6154         gh = geo->h;
6155         break;
6156      }
6157
6158    if (x) *x = gx;
6159    if (y) *y = gy;
6160    if (w) *w = gw;
6161    if (h) *h = gh;
6162 }
6163
6164 E_API void
6165 e_client_frame_focus_set(E_Client *ec, Eina_Bool focus)
6166 {
6167    if (!ec) return;
6168    evas_object_focus_set(ec->frame, focus);
6169 }
6170
6171 EINTERN void
6172 e_client_frame_geometry_set(E_Client *ec, int x, int y, int w, int h)
6173 {
6174    if (!ec) return;
6175
6176    if (ec->internal || ec->input_only)
6177      {
6178         evas_object_geometry_set(ec->frame, x, y, w, h);
6179      }
6180    else
6181      {
6182         if ((ec->w != w) || (ec->h != h))
6183           {
6184              ELOGF("POSSIZE", "Set move_after_resize. old(%d,%d,%dx%d), new(%d,%d,%dx%d)", ec, ec->x, ec->y, ec->w, ec->h, x, y, w, h);
6185              ec->move_after_resize = EINA_TRUE;
6186
6187              e_client_pos_set(ec, x, y);
6188              evas_object_resize(ec->frame, w, h);
6189           }
6190         else
6191           evas_object_geometry_set(ec->frame, x, y, w, h);
6192      }
6193 }
6194
6195 EAPI void
6196 e_client_util_move_resize_without_frame(E_Client *ec, int x, int y, int w, int h)
6197 {
6198    if (!ec) return;
6199
6200    if (ec->internal || ec->input_only)
6201      {
6202         e_client_util_move_without_frame(ec, x, y);
6203         e_client_util_resize_without_frame(ec, w, h);
6204      }
6205    else
6206      {
6207         if ((ec->w != w) || (ec->h != h))
6208           {
6209              ELOGF("POSSIZE", "Set move_after_resize. old(%d,%d,%dx%d), new(%d,%d,%dx%d)", ec, ec->x, ec->y, ec->w, ec->h, x, y, w, h);
6210              ec->move_after_resize = EINA_TRUE;
6211
6212              e_comp_object_frame_xy_adjust(ec->frame, x, y, &x, &y);
6213              e_client_pos_set(ec, x, y);
6214              e_client_util_resize_without_frame(ec, w, h);
6215           }
6216         else
6217           {
6218              e_client_util_move_without_frame(ec, x, y);
6219              e_client_util_resize_without_frame(ec, w, h);
6220           }
6221      }
6222 }
6223
6224 static void
6225 _e_input_thread_client_layer_set(void *data)
6226 {
6227    E_Input_Thread_Request_EClient_Data *ec_data = data;
6228    EINA_SAFETY_ON_NULL_RETURN(ec_data);
6229
6230    INF("[input thread|%s] ec(%p), layer(%d)\n", __func__, ec_data->ec, ec_data->layer);
6231    e_input_thread_client_layer_set(e_input_thread_client_get(ec_data->ec), ec_data->layer);
6232 }
6233
6234 EINTERN void
6235 e_client_input_thread_layer_set(E_Client *ec, E_Layer layer)
6236 {
6237    EINA_SAFETY_ON_NULL_RETURN(ec);
6238
6239    E_Input_Thread_Request_EClient_Data ec_data;
6240    memset(&ec_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
6241
6242    ec_data.ec = ec;
6243    ec_data.layer = layer;
6244
6245    INF("[%s] ec(%p), layer(%d)\n", __func__, ec, layer);
6246    e_input_thread_safe_call(_e_input_thread_client_layer_set, &ec_data, sizeof(E_Input_Thread_Request_EClient_Data));
6247 }
6248
6249 E_API Eina_Bool
6250 e_client_layer_set(E_Client *ec,
6251                    E_Layer layer)
6252 {
6253    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
6254    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
6255    if (!ec->frame) return EINA_FALSE;
6256
6257    if (e_comp_canvas_client_layer_map(layer) == 9999)
6258      return EINA_FALSE; //invalid layer is not allowed
6259
6260 #ifdef REFACTOR_DESK_AREA
6261 #else
6262    if (ec->desk_area.enable)
6263      {
6264         if (e_client_layer_set_by_desk_area(ec, layer))
6265           {
6266              // restack according to desk group rule
6267              e_desk_area_ec_rearrange(ec->desk_area.desk_area, ec);
6268              return EINA_TRUE;
6269           }
6270      }
6271    ec->desk_area.layer_backup = layer;
6272 #endif
6273
6274    evas_object_layer_set(ec->frame, layer);
6275    if (ec->layer != layer)
6276      {
6277         /* check exceptional case */
6278         if ((ec->fullscreen) &&
6279             (ec->saved.layer != layer))
6280           {
6281              ELOGF("LAYER", "(%d) fail to backup at saved.layer for fullscreen", ec, layer);
6282              return EINA_FALSE;
6283           }
6284         // if e_comp_object fail to change ec->layer due to ec->layer_pending or block
6285         // leave log and apply ec->layer according to set
6286         // as a result it restores back to given layer when pending or block is free
6287         ELOGF("LAYER", "change layer from %d to %d if in case layer pending(%d) or block(%d)",
6288               ec, ec->layer, layer, ec->layer_pending, ec->layer_block);
6289         if (ec->layer_pending || ec->layer_block)
6290           {
6291              ec->layer = layer;
6292              e_client_input_thread_layer_set(ec, layer);
6293              return EINA_TRUE;
6294           }
6295      }
6296
6297    wl_signal_emit(&PRI(ec)->events.set_layer, NULL);
6298
6299    return EINA_TRUE;
6300 }
6301
6302 E_API E_Layer
6303 e_client_layer_get(E_Client *ec)
6304 {
6305    short layer;
6306
6307    E_OBJECT_CHECK_RETURN(ec, E_LAYER_BOTTOM);
6308    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, E_LAYER_BOTTOM);
6309    if (!ec->frame) return E_LAYER_BOTTOM;
6310
6311    layer = evas_object_layer_get(ec->frame);
6312    if (ec->layer != layer)
6313      {
6314         /* client could be on temperory layer while pending or block,
6315          * in that case, client restores back to ec->layer after pending/block finish */
6316         if (ec->layer_block || ec->layer_pending)
6317           return ec->layer;
6318
6319         /* otherwise, client is on unexpected layer */
6320         ELOGF("LAYER", "layer dismatch ec->layer %d | evas obj layer %d ",
6321               ec, ec->layer, layer);
6322
6323         if (e_comp_canvas_client_layer_map(layer) == 9999)
6324           return E_LAYER_BOTTOM; //not on E_LAYER_CLIENT
6325      }
6326
6327    return ec->layer;
6328 }
6329
6330 #ifdef REFACTOR_DESK_AREA
6331 #else
6332 static void
6333 _e_client_desk_area_original_layer_save(E_Client *ec, E_Layer layer)
6334 {
6335    E_OBJECT_CHECK(ec);
6336    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6337    ec->desk_area.layer_backup = layer;
6338 }
6339
6340 EINTERN Eina_Bool
6341 e_client_layer_set_by_desk_area(E_Client *ec, E_Layer layer)
6342 {
6343    E_Desk_Area *eda;
6344    E_Layer edg_layer;
6345    E_Layer org_layer;
6346
6347    if (!ec) return EINA_FALSE;
6348    if (!ec->frame) return EINA_FALSE;
6349    if (!ec->desk_area.enable) return EINA_FALSE;
6350    if (!ec->desk_area.desk_area) return EINA_FALSE;
6351
6352    eda = ec->desk_area.desk_area;
6353
6354    // save original layer
6355    _e_client_desk_area_original_layer_save(ec, layer);
6356
6357    // get desk_area layer
6358    edg_layer = (E_Layer)e_desk_area_layer_get(eda);
6359    org_layer = e_client_desk_area_original_layer_get(ec);
6360
6361    ELOGF("EDG", "layer_set by desk_area... layer:%d, org_layer:%d, new_layer:%d", ec, layer, org_layer, edg_layer);
6362    if (org_layer == edg_layer)
6363      {
6364         e_client_raise(ec);
6365      }
6366    else
6367      {
6368         evas_object_layer_set(ec->frame, edg_layer);
6369         if (edg_layer == ec->layer)
6370           e_client_raise(ec);
6371      }
6372
6373    return EINA_TRUE;
6374 }
6375
6376 EINTERN void
6377 e_client_desk_area_original_layer_restore(E_Client *ec)
6378 {
6379    if (!ec) return;
6380
6381    // Do we need to check ec->desk_area.enable?
6382    // if ec->desk_area.enable is true, then e_client_layer_set calls
6383    // e_desk_area_ec_edg_layer_set(). that's too bad. :(
6384    // so, we MUST make a policy for ordering of the desk group layer restore
6385    // and the desk group enable.
6386    if (ec->desk_area.enable) return;
6387    e_client_layer_set(ec, ec->desk_area.layer_backup);
6388 }
6389
6390 EINTERN E_Layer
6391 e_client_desk_area_original_layer_get(E_Client *ec)
6392 {
6393    if (!ec) return E_LAYER_DESKTOP;
6394
6395    if (ec->desk_area.enable)
6396      return ec->desk_area.layer_backup;
6397    else
6398      return ec->layer;
6399 }
6400
6401 EINTERN Eina_Bool
6402 e_client_desk_area_client_layer_set(E_Client *ec, E_Desk_Area_Client_Layer edgc_layer)
6403 {
6404    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
6405    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
6406    if ((edgc_layer < E_DESK_AREA_CLIENT_LAYER_DESKTOP) ||
6407        (edgc_layer >= E_DESK_AREA_CLIENT_LAYER_MAX))
6408      return EINA_FALSE;
6409
6410    ec->desk_area.edgc_layer = edgc_layer;
6411    return EINA_TRUE;
6412 }
6413
6414 EINTERN E_Desk_Area_Client_Layer
6415 e_client_desk_area_client_layer_get(E_Client *ec)
6416 {
6417    E_OBJECT_CHECK_RETURN(ec, E_DESK_AREA_CLIENT_LAYER_DESKTOP);
6418
6419    return ec->desk_area.edgc_layer;
6420 }
6421
6422 //FIXME: use e_desk_area_ec_reassign(eda, ec) instead of this api
6423 E_API Eina_Bool
6424 e_client_desk_area_set(E_Client *ec, E_Desk_Area *eda)
6425 {
6426    E_Desk_Area *old_edg;
6427
6428    if (!ec) return EINA_FALSE;
6429
6430 #if 0 // if this is removed.. then below if (eda != old_edg) is removed also...
6431    if (ec->desk_area.desk_area == eda)
6432      return EINA_TRUE;
6433 #endif
6434
6435    ELOGF("EDG", "Desk Group Set (new:%p, old:%p)", ec, eda, ec->desk_area.desk_area);
6436    old_edg = ec->desk_area.desk_area;
6437    if (old_edg)
6438      e_desk_area_ec_remove(old_edg, ec);
6439
6440    ec->desk_area.desk_area = eda;
6441    e_desk_area_ec_add(eda, ec);
6442
6443 #if 0 // if this is removed.. then above if (ec->desk_area.desk_area == eda) is removed also...
6444    if (eda != old_edg)
6445 #endif
6446      {
6447         e_desk_area_ec_update(eda, ec);
6448         e_desk_area_ec_rearrange(ec->desk_area.desk_area, ec);
6449      }
6450
6451    return EINA_TRUE;
6452 }
6453 #endif
6454
6455 static void
6456 _raise_between_sibling_under_parent(E_Client *ec)
6457 {
6458    ELOGF("POL", "RAISE child window between sibling. So, stack below under the parent (win:%zx, ec:%p)", ec, e_client_util_win_get(ec->parent), ec->parent);
6459    e_client_stack_below(ec, ec->parent);
6460 }
6461
6462 static void
6463 _raise_between_sibling_on_parent(E_Client *ec)
6464 {
6465    E_Client *top_child = NULL;
6466    top_child = e_client_transient_child_top_get(ec->parent, EINA_FALSE);
6467    if (!top_child)
6468      {
6469         ELOGF("POL", "RAISE child window... Stack above on the parent (win:%zx, ec:%p)", ec, e_client_util_win_get(ec->parent), ec->parent);
6470         e_client_stack_above(ec, ec->parent);
6471      }
6472    else
6473      {
6474         if (top_child != ec)
6475           {
6476              ELOGF("POL", "RAISE child window between sibling... Stack above on the top child (win:%zx, ec:%p)", ec, e_client_util_win_get(top_child), top_child);
6477              e_client_stack_above(ec, top_child);
6478           }
6479         else
6480           ELOGF("POL", "RAISE child window between sibling... already on the top. STAY", ec);
6481      }
6482 }
6483
6484 static void
6485 _raise_belong_to_parent(E_Client *ec)
6486 {
6487    if (e_client_transient_policy_get(ec) == E_TRANSIENT_BELOW)
6488      _raise_between_sibling_under_parent(ec);
6489    else
6490      _raise_between_sibling_on_parent(ec);
6491 }
6492
6493 E_API void
6494 e_client_raise(E_Client *ec)
6495 {
6496    if (!ec) return;
6497
6498 #ifdef REFACTOR_DESK_AREA
6499 #else
6500    if (ec->desk_area.enable)
6501      {
6502         E_Desk_Area *eda;
6503         eda = ec->desk_area.desk_area;
6504         if (eda)
6505           {
6506              e_desk_area_ec_raise(eda, ec);
6507              return;
6508           }
6509      }
6510 #endif
6511
6512    if (ec->parent && e_client_is_belong_to_parent(ec))
6513      _raise_belong_to_parent(ec);
6514    else
6515      evas_object_raise(ec->frame);
6516
6517    wl_signal_emit(&PRI(ec)->events.raise, NULL);
6518 }
6519
6520 static void
6521 _e_client_transient_for_below_group_make(E_Client *ec, Eina_List **list)
6522 {
6523    // list : Head is the bottommost child
6524    E_Client *child;
6525    Eina_List *l;
6526
6527    if (!ec) return;
6528
6529    EINA_LIST_REVERSE_FOREACH(ec->transients, l, child)
6530      {
6531         if (!child) continue;
6532         if (e_client_transient_policy_get(child) != E_TRANSIENT_BELOW) continue;
6533         if (!e_client_is_belong_to_parent(child)) continue;
6534
6535         *list = eina_list_prepend(*list, child);
6536         _e_client_transient_for_group_make(child, list);
6537      }
6538 }
6539
6540 E_API E_Client *
6541 e_client_transient_child_bottom_get(E_Client *ec)
6542 {
6543    E_Client *bottom_ec = NULL;
6544    Eina_List *transient_below_list = NULL;
6545    Eina_List *l = NULL;
6546
6547    _e_client_transient_for_below_group_make(ec, &transient_below_list);
6548
6549    if (transient_below_list)
6550      {
6551         E_Client *temp_ec = NULL;
6552         E_Client *temp_ec2 = NULL;
6553
6554         E_CLIENT_FOREACH(temp_ec)
6555           {
6556              if (bottom_ec) break;
6557
6558              if (temp_ec == ec)
6559                {
6560                   bottom_ec = ec;
6561                   break;
6562                }
6563
6564              EINA_LIST_FOREACH(transient_below_list, l, temp_ec2)
6565                {
6566                   if (temp_ec == temp_ec2)
6567                     {
6568                        bottom_ec = temp_ec2;
6569                        break;
6570                     }
6571                }
6572           }
6573         eina_list_free(transient_below_list);
6574      }
6575    return bottom_ec;
6576 }
6577
6578 static void
6579 _lower_between_sibling_under_parent(E_Client *ec)
6580 {
6581    E_Client *bottom_child = NULL;
6582    bottom_child = e_client_transient_child_bottom_get(ec->parent);
6583    if (!bottom_child)
6584      {
6585         ELOGF("POL", "LOWER child window between sibling... Stack below under the parent (win:%zx, ec:%p)", ec, e_client_util_win_get(ec->parent), ec->parent);
6586         e_client_stack_below(ec, ec->parent);
6587      }
6588    else
6589      {
6590         if (bottom_child != ec)
6591           {
6592              ELOGF("POL", "LOWER child window between sibling... Stack below under the bottom child (win:%zx, ec:%p)", ec, e_client_util_win_get(bottom_child), bottom_child);
6593              e_client_stack_below(ec, bottom_child);
6594           }
6595         else
6596           ELOGF("POL", "LOWER child window between sibling... already under the bottom. STAY", ec);
6597      }
6598 }
6599
6600 static void
6601 _lower_between_sibling_on_parent(E_Client *ec)
6602 {
6603    ELOGF("POL", "LOWER child window between sibling... So, stack above on the parent (win:%zx, ec:%p)", ec, e_client_util_win_get(ec->parent), ec->parent);
6604    e_client_stack_above(ec, ec->parent);
6605 }
6606
6607 static void
6608 _lower_belong_to_parent(E_Client *ec)
6609 {
6610    if (e_client_transient_policy_get(ec) == E_TRANSIENT_BELOW)
6611      _lower_between_sibling_under_parent(ec);
6612    else
6613      _lower_between_sibling_on_parent(ec);
6614 }
6615
6616 E_API void
6617 e_client_lower(E_Client *ec)
6618 {
6619    if (!ec) return;
6620
6621 #ifdef REFACTOR_DESK_AREA
6622 #else
6623    if (ec->desk_area.enable)
6624      {
6625         E_Desk_Area *eda;
6626         eda = ec->desk_area.desk_area;
6627         if (eda)
6628           {
6629              e_desk_area_ec_lower(eda, ec);
6630
6631              wl_signal_emit(&PRI(ec)->events.lower, NULL);
6632              return;
6633           }
6634      }
6635 #endif
6636
6637    if (ec->parent && e_client_is_belong_to_parent(ec))
6638      _lower_belong_to_parent(ec);
6639    else
6640      evas_object_lower(ec->frame);
6641
6642    wl_signal_emit(&PRI(ec)->events.lower, NULL);
6643 }
6644
6645 E_API void
6646 e_client_stack_above(E_Client *ec, E_Client *above)
6647 {
6648    if (!ec) return;
6649    if (!ec->frame) return;
6650    if (!above) return;
6651    if (!above->frame) return;
6652
6653 #ifdef REFACTOR_DESK_AREA
6654 #else
6655    if (ec->desk_area.enable)
6656      {
6657         E_Desk_Area *eda;
6658         eda = ec->desk_area.desk_area;
6659         if (eda)
6660           {
6661              e_desk_area_ec_stack_above(eda, ec, above);
6662              return;
6663           }
6664      }
6665 #endif
6666
6667    evas_object_stack_above(ec->frame, above->frame);
6668
6669    wl_signal_emit(&PRI(ec)->events.stack_above, NULL);
6670 }
6671
6672 E_API void
6673 e_client_stack_below(E_Client *ec, E_Client *below)
6674 {
6675    if (!ec) return;
6676    if (!ec->frame) return;
6677    if (!below) return;
6678    if (!below->frame) return;
6679
6680 #ifdef REFACTOR_DESK_AREA
6681 #else
6682    if (ec->desk_area.enable)
6683      {
6684         E_Desk_Area *eda;
6685         eda = ec->desk_area.desk_area;
6686         if (eda)
6687           {
6688              e_desk_area_ec_stack_below(eda, ec, below);
6689              return;
6690           }
6691      }
6692 #endif
6693
6694    evas_object_stack_below(ec->frame, below->frame);
6695
6696    wl_signal_emit(&PRI(ec)->events.stack_below, NULL);
6697 }
6698
6699 E_API int
6700 e_client_show_pending_set(E_Client *ec)
6701 {
6702    if (!ec) return 0;
6703
6704    ec->show_pending.count++;
6705    ELOGF("E_CLIENT", "SET show_pending. (count:%d, run:%d)", ec, ec->show_pending.count, ec->show_pending.running);
6706    return ec->show_pending.count;
6707 }
6708
6709 E_API int
6710 e_client_show_pending_unset(E_Client *ec)
6711 {
6712    if (!ec) return 0;
6713    if (ec->show_pending.count <= 0) return 0;
6714
6715    ec->show_pending.count--;
6716    ELOGF("E_CLIENT", "UNSET show_pending. (count:%d, run:%d)", ec, ec->show_pending.count, ec->show_pending.running);
6717    if (ec->show_pending.count == 0 && ec->show_pending.running)
6718      {
6719         ec->show_pending.running = EINA_FALSE;
6720         if (ec->frame)
6721           {
6722              ELOGF("E_CLIENT", "evas_object_show by unset show_pending", ec);
6723              evas_object_show(ec->frame);
6724              //e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
6725              EC_CHANGED(ec);
6726           }
6727      }
6728
6729    return ec->show_pending.count;
6730 }
6731
6732 static Eina_Bool
6733 _e_client_surface_tree_foreach_helper(E_Client *ec, E_Client_Surface_Tree_Foreach func, void *data)
6734 {
6735    E_Client *subc;
6736    Eina_List *l, *ll;
6737    Eina_Bool res = EINA_TRUE;
6738    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
6739
6740    if (!cdata)
6741      return res;
6742
6743    EINA_LIST_FOREACH_SAFE(cdata->sub.below_list, l, ll, subc)
6744      {
6745         res = _e_client_surface_tree_foreach_helper(subc, func, data);
6746         if (!res)
6747           break;
6748      }
6749
6750    if (res)
6751      {
6752         res = func(data, ec);
6753         if (res)
6754           {
6755              EINA_LIST_FOREACH_SAFE(cdata->sub.list, l, ll, subc)
6756                {
6757                   res = _e_client_surface_tree_foreach_helper(subc,
6758                                                               func,
6759                                                               data);
6760                   if (!res)
6761                     break;
6762                }
6763           }
6764      }
6765
6766    return res;
6767 }
6768
6769 E_API void
6770 e_client_surface_tree_foreach(E_Client *ec, E_Client_Surface_Tree_Foreach func, void *data)
6771 {
6772    EINA_SAFETY_ON_NULL_RETURN(ec);
6773    EINA_SAFETY_ON_NULL_RETURN(func);
6774
6775    _e_client_surface_tree_foreach_helper(ec, func, data);
6776 }
6777
6778 EINTERN E_Comp_Wl_Client_Data *
6779 e_client_cdata_new(E_Client *ec)
6780 {
6781    E_Comp_Wl_Client_Data *cdata;
6782
6783    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
6784
6785    if (!(cdata = E_NEW(E_Comp_Wl_Client_Data, 1)))
6786      {
6787         ERR("Could not allocate new E_Comp_Wl_Client_Data structure");
6788         return NULL;
6789      }
6790    ec->comp_data = cdata;
6791
6792    return cdata;
6793 }
6794
6795 EINTERN void
6796 e_client_cdata_free(E_Client *ec)
6797 {
6798   EINA_SAFETY_ON_NULL_RETURN(ec);
6799   if (!ec->comp_data) return;
6800
6801   E_FREE(ec->comp_data);
6802 }
6803
6804 EINTERN E_Comp_Wl_Client_Data *
6805 e_client_cdata_get(E_Client *ec)
6806 {
6807    if (!ec) return NULL;
6808
6809    return ec->comp_data;
6810 }
6811
6812 EINTERN Eina_Bool
6813 e_client_map_set(E_Client *ec, E_Map *em)
6814 {
6815    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
6816
6817    return e_map_set_to_comp_object(em, ec->frame);
6818 }
6819
6820 E_API E_Map *
6821 e_client_map_get(const E_Client *ec)
6822 {
6823    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
6824
6825    return e_map_get_from_comp_object(ec->frame);
6826 }
6827
6828 EINTERN Eina_Bool
6829 e_client_map_enable_set(E_Client *ec, Eina_Bool enable)
6830 {
6831    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
6832    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, EINA_FALSE);
6833
6834    evas_object_map_enable_set(ec->frame, enable);
6835
6836    return EINA_TRUE;
6837 }
6838
6839 EINTERN void
6840 e_client_belong_to_parent_set(E_Client *ec, Eina_Bool set)
6841 {
6842    if (!ec) return;
6843    ec->belong_to_parent = set;
6844 }
6845
6846 EINTERN Eina_Bool
6847 e_client_is_belong_to_parent(E_Client *ec)
6848 {
6849    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
6850    return ec->belong_to_parent;
6851 }
6852
6853 EINTERN void
6854 e_client_transient_policy_set(E_Client *ec, E_Transient policy)
6855 {
6856    if (!ec) return;
6857    ec->transient_policy = policy;
6858 }
6859
6860 E_API E_Transient
6861 e_client_transient_policy_get(E_Client *ec)
6862 {
6863    if (!ec) return E_TRANSIENT_ABOVE;
6864    return ec->transient_policy;
6865 }
6866
6867 EINTERN void
6868 e_client_resize_object_create_cb_set(E_Client_Resize_Object_Create_Cb cb)
6869 {
6870    if (_e_client_resize_object_create_cb && cb)
6871      CRI("ATTEMPTING TO OVERWRITE EXISTING CLIENT RESIZE OBJECT CREATE HOOK!!!");
6872    _e_client_resize_object_create_cb = cb;
6873 }
6874
6875 EINTERN void
6876 e_client_resize_unit_size_set(E_Client *ec, unsigned int unit_size)
6877 {
6878    if (!ec) return;
6879
6880    // FYI, we consider 0 and 1 to be the same value as a default unit size.
6881    ec->manage_resize.unit_size = unit_size;
6882 }
6883
6884 EINTERN void
6885 e_client_desk_zoom_enable_set(E_Client *ec, Eina_Bool enable)
6886 {
6887    if (!ec) return;
6888    ec->desk_zoom.enable = enable;
6889 }
6890
6891 EINTERN Eina_Bool
6892 e_client_desk_zoom_enable_get(E_Client *ec)
6893 {
6894    if (!ec) return EINA_FALSE;
6895    return ec->desk_zoom.enable;
6896 }
6897
6898 EINTERN void
6899 e_client_layout_apply(E_Client *ec, Eina_Bool apply)
6900 {
6901    if (!ec) return;
6902    ec->apply_layout = apply;
6903 }
6904
6905 EINTERN Eina_Bool
6906 e_client_is_layout_apply(E_Client *ec)
6907 {
6908    if (!ec) return EINA_FALSE;
6909    return ec->apply_layout;
6910 }
6911
6912 E_API E_Client *
6913 e_client_from_surface_resource(struct wl_resource *surface_resource)
6914 {
6915    EINA_SAFETY_ON_NULL_RETURN_VAL(surface_resource, NULL);
6916
6917    return e_comp_wl_util_client_from_surface_resource(surface_resource);
6918 }
6919
6920 EINTERN void
6921 e_client_fps_update(E_Client *ec)
6922 {
6923    double dt;
6924    double tim;
6925
6926    EINA_SAFETY_ON_NULL_RETURN(ec);
6927
6928    if (!ec->fps.enabled) return;
6929
6930    tim = ecore_time_get();
6931
6932    dt = tim - ec->fps.frametimes[0];
6933
6934    ec->fps.frametimes[0] = tim;
6935    ec->fps.time += dt;
6936    ec->fps.cframes++;
6937
6938    if (ec->fps.lapse == 0.0)
6939      {
6940         ec->fps.lapse = tim;
6941         ec->fps.flapse = ec->fps.cframes;
6942      }
6943    else if ((tim - ec->fps.lapse) >= 0.5)
6944      {
6945         ec->fps.fps = (ec->fps.cframes - ec->fps.flapse) /
6946                       (tim - ec->fps.lapse);
6947         ec->fps.lapse = tim;
6948         ec->fps.flapse = ec->fps.cframes;
6949         ec->fps.time = 0.0;
6950      }
6951 }
6952
6953 EINTERN Eina_Bool
6954 e_client_fps_get(E_Client *ec, double *fps)
6955 {
6956    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
6957
6958    if (ec->fps.old_fps == ec->fps.fps)
6959      return EINA_FALSE;
6960
6961    if (ec->fps.fps > 0.0)
6962      {
6963         *fps = ec->fps.fps;
6964         ec->fps.old_fps = ec->fps.fps;
6965         return EINA_TRUE;
6966      }
6967
6968    return EINA_FALSE;
6969 }
6970
6971 EINTERN void
6972 e_client_fps_enable(E_Client *ec, Eina_Bool enable)
6973 {
6974    EINA_SAFETY_ON_NULL_RETURN(ec);
6975
6976    ec->fps.enabled = enable;
6977 }
6978
6979 EINTERN Eina_Bool
6980 e_client_explicit_sync_get(E_Client *ec)
6981 {
6982    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
6983
6984    return ec->explicit_sync;
6985 }
6986
6987 EINTERN Eina_Bool
6988 e_client_explicit_sync_set(E_Client *ec, Eina_Bool enable)
6989 {
6990    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
6991
6992    ec->explicit_sync = enable;
6993
6994    return EINA_TRUE;
6995 }
6996
6997 EINTERN int
6998 e_client_explicit_sync_acquire_fence_fd_get(E_Client *ec)
6999 {
7000    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, -1);
7001
7002    return ec->acquire_fence_fd;
7003 }
7004
7005 EINTERN Eina_Bool
7006 e_client_explicit_sync_acquire_fence_fd_set(E_Client *ec, int fd)
7007 {
7008   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
7009
7010   ec->acquire_fence_fd = fd;
7011
7012   return EINA_TRUE;
7013 }
7014
7015 EINTERN Eina_Bool
7016 e_client_intercept_hook_auto_placement_call(E_Client *ec)
7017 {
7018   // no need to call the intercept hook if ec is NULL.
7019   if (!ec) return EINA_FALSE;
7020
7021   if (!_e_client_intercept_hook_call(E_CLIENT_INTERCEPT_HOOK_AUTO_PLACEMENT, ec))
7022     {
7023        ELOGF("FOCUS", "E_CLIENT_INTERCEPT_HOOK_AUTO_PLACEMENT Intercepted.", ec);
7024        return EINA_TRUE;
7025     }
7026
7027   return EINA_FALSE;
7028 }
7029
7030 EINTERN void
7031 e_client_iconify_event_send(E_Client *ec)
7032 {
7033    EINA_SAFETY_ON_NULL_RETURN(ec);
7034
7035    _e_client_event_simple(ec, E_EVENT_CLIENT_ICONIFY);
7036 }
7037
7038 EINTERN void
7039 e_client_uniconify_event_send(E_Client *ec)
7040 {
7041    EINA_SAFETY_ON_NULL_RETURN(ec);
7042
7043    _e_client_event_simple(ec, E_EVENT_CLIENT_UNICONIFY);
7044 }
7045
7046 EINTERN void
7047 e_client_stack_transient_for_done_notify(E_Client *ec)
7048 {
7049    EINA_SAFETY_ON_NULL_RETURN(ec);
7050
7051    wl_signal_emit(&PRI(ec)->events.stack_transient_for_done, NULL);
7052 }
7053
7054 #ifdef REFACTOR_DESK_AREA
7055 EINTERN void
7056 e_client_subsurface_stack_update(E_Client *ec)
7057 {
7058    EINA_SAFETY_ON_NULL_RETURN(ec);
7059
7060    wl_signal_emit(&PRI(ec)->events.subsurface_stack_update, ec);
7061 }
7062 #endif
7063
7064 EINTERN void
7065 e_client_eval_pre_fetch_listener_add(E_Client *ec, struct wl_listener *listener)
7066 {
7067    API_ENTRY;
7068    wl_signal_add(&priv->events.eval_pre_fetch, listener);
7069 }
7070
7071 EINTERN void
7072 e_client_eval_fetch_listener_add(E_Client *ec, struct wl_listener *listener)
7073 {
7074    API_ENTRY;
7075    wl_signal_add(&priv->events.eval_fetch, listener);
7076 }
7077
7078 EINTERN void
7079 e_client_eval_pre_post_fetch_listener_add(E_Client *ec, struct wl_listener *listener)
7080 {
7081    API_ENTRY;
7082    wl_signal_add(&priv->events.eval_pre_post_fetch, listener);
7083 }
7084
7085 EINTERN void
7086 e_client_eval_post_fetch_listener_add(E_Client *ec, struct wl_listener *listener)
7087 {
7088    API_ENTRY;
7089    wl_signal_add(&priv->events.eval_post_fetch, listener);
7090 }
7091
7092 EINTERN void
7093 e_client_eval_pre_frame_assign_listener_add(E_Client *ec, struct wl_listener *listener)
7094 {
7095    API_ENTRY;
7096    wl_signal_add(&priv->events.eval_pre_frame_assign, listener);
7097 }
7098
7099 EINTERN void
7100 e_client_eval_post_frame_assign_listener_add(E_Client *ec, struct wl_listener *listener)
7101 {
7102    API_ENTRY;
7103    wl_signal_add(&priv->events.eval_post_frame_assign, listener);
7104 }
7105
7106 EINTERN void
7107 e_client_eval_pre_new_client_listener_add(E_Client *ec, struct wl_listener *listener)
7108 {
7109    API_ENTRY;
7110    wl_signal_add(&priv->events.eval_pre_new_client, listener);
7111 }
7112
7113 EINTERN void
7114 e_client_eval_post_new_client_listener_add(E_Client *ec, struct wl_listener *listener)
7115 {
7116    API_ENTRY;
7117    wl_signal_add(&priv->events.eval_post_new_client, listener);
7118 }
7119
7120 EINTERN void
7121 e_client_eval_visibility_listener_add(E_Client *ec, struct wl_listener *listener)
7122 {
7123    API_ENTRY;
7124    wl_signal_add(&priv->events.eval_visibility, listener);
7125 }
7126
7127 EINTERN void
7128 e_client_eval_visibility_end_listener_add(E_Client *ec, struct wl_listener *listener)
7129 {
7130    API_ENTRY;
7131    wl_signal_add(&priv->events.eval_visibility_end, listener);
7132 }
7133
7134 EINTERN void
7135 e_client_eval_end_listener_add(E_Client *ec, struct wl_listener *listener)
7136 {
7137    API_ENTRY;
7138    wl_signal_add(&priv->events.eval_end, listener);
7139 }
7140
7141 EINTERN void
7142 e_client_move_begin_listener_add(E_Client *ec, struct wl_listener *listener)
7143 {
7144    API_ENTRY;
7145    wl_signal_add(&priv->events.move_begin, listener);
7146 }
7147
7148 EINTERN void
7149 e_client_move_update_listener_add(E_Client *ec, struct wl_listener *listener)
7150 {
7151    API_ENTRY;
7152    wl_signal_add(&priv->events.move_update, listener);
7153 }
7154
7155 EINTERN void
7156 e_client_move_end_listener_add(E_Client *ec, struct wl_listener *listener)
7157 {
7158    API_ENTRY;
7159    wl_signal_add(&priv->events.move_end, listener);
7160 }
7161
7162 EINTERN void
7163 e_client_move_resize_begin_listener_add(E_Client *ec, struct wl_listener *listener)
7164 {
7165    API_ENTRY;
7166    wl_signal_add(&priv->events.move_resize_begin, listener);
7167 }
7168
7169 EINTERN void
7170 e_client_move_resize_update_listener_add(E_Client *ec, struct wl_listener *listener)
7171 {
7172    API_ENTRY;
7173    wl_signal_add(&priv->events.move_resize_update, listener);
7174 }
7175
7176 EINTERN void
7177 e_client_move_resize_end_listener_add(E_Client *ec, struct wl_listener *listener)
7178 {
7179    API_ENTRY;
7180    wl_signal_add(&priv->events.move_resize_end, listener);
7181 }
7182
7183 EINTERN void
7184 e_client_destroy_listener_add(E_Client *ec, struct wl_listener *listener)
7185 {
7186    API_ENTRY;
7187    wl_signal_add(&priv->events.destroy, listener);
7188 }
7189
7190 EINTERN void
7191 e_client_new_client_listener_add(E_Client *ec, struct wl_listener *listener)
7192 {
7193    API_ENTRY;
7194    wl_signal_add(&priv->events.new_client, listener);
7195 }
7196
7197 EINTERN void
7198 e_client_new_client_post_listener_add(E_Client *ec, struct wl_listener *listener)
7199 {
7200    API_ENTRY;
7201    wl_signal_add(&priv->events.new_client_post, listener);
7202 }
7203
7204 EINTERN void
7205 e_client_unredirect_listener_add(E_Client *ec, struct wl_listener *listener)
7206 {
7207    API_ENTRY;
7208    wl_signal_add(&priv->events.unredirect, listener);
7209 }
7210
7211 EINTERN void
7212 e_client_redirect_listener_add(E_Client *ec, struct wl_listener *listener)
7213 {
7214    API_ENTRY;
7215    wl_signal_add(&priv->events.redirect, listener);
7216 }
7217
7218 EINTERN void
7219 e_client_aux_hint_change_listener_add(E_Client *ec, struct wl_listener *listener)
7220 {
7221    API_ENTRY;
7222    wl_signal_add(&priv->events.aux_hint_change, listener);
7223 }
7224
7225 EINTERN void
7226 e_client_window_role_change_listener_add(E_Client *ec, struct wl_listener *listener)
7227 {
7228    API_ENTRY;
7229    wl_signal_add(&priv->events.window_role_change, listener);
7230 }
7231
7232 EINTERN void
7233 e_client_transform_change_listener_add(E_Client *ec, struct wl_listener *listener)
7234 {
7235    API_ENTRY;
7236    wl_signal_add(&priv->events.transform_change, listener);
7237 }
7238
7239 EINTERN void
7240 e_client_activate_done_listener_add(E_Client *ec, struct wl_listener *listener)
7241 {
7242    API_ENTRY;
7243    wl_signal_add(&priv->events.activate_done, listener);
7244 }
7245
7246 EINTERN void
7247 e_client_mouse_in_listener_add(E_Client *ec, struct wl_listener *listener)
7248 {
7249    API_ENTRY;
7250    wl_signal_add(&priv->events.mouse_in, listener);
7251 }
7252
7253 EINTERN void
7254 e_client_mouse_out_listener_add(E_Client *ec, struct wl_listener *listener)
7255 {
7256    API_ENTRY;
7257    wl_signal_add(&priv->events.mouse_out, listener);
7258 }
7259
7260 EINTERN void
7261 e_client_mouse_down_listener_add(E_Client *ec, struct wl_listener *listener)
7262 {
7263    API_ENTRY;
7264    wl_signal_add(&priv->events.mouse_down, listener);
7265 }
7266
7267 EINTERN void
7268 e_client_focus_set_listener_add(E_Client *ec, struct wl_listener *listener)
7269 {
7270    API_ENTRY;
7271    wl_signal_add(&priv->events.focus_set, listener);
7272 }
7273
7274 EINTERN void
7275 e_client_focus_unset_listener_add(E_Client *ec, struct wl_listener *listener)
7276 {
7277    API_ENTRY;
7278    wl_signal_add(&priv->events.focus_unset, listener);
7279 }
7280
7281 EINTERN void
7282 e_client_focus_defer_set_listener_add(E_Client *ec, struct wl_listener *listener)
7283 {
7284    API_ENTRY;
7285    wl_signal_add(&priv->events.focus_defer_set, listener);
7286 }
7287
7288 EINTERN void
7289 e_client_focus_latest_set_listener_add(E_Client *ec, struct wl_listener *listener)
7290 {
7291    API_ENTRY;
7292    wl_signal_add(&priv->events.focus_latest_set, listener);
7293 }
7294
7295 EINTERN void
7296 e_client_iconify_listener_add(E_Client *ec, struct wl_listener *listener)
7297 {
7298    API_ENTRY;
7299    wl_signal_add(&priv->events.iconify, listener);
7300 }
7301
7302 EINTERN void
7303 e_client_uniconify_listener_add(E_Client *ec, struct wl_listener *listener)
7304 {
7305    API_ENTRY;
7306    wl_signal_add(&priv->events.uniconify, listener);
7307 }
7308
7309 EINTERN void
7310 e_client_maximize_listener_add(E_Client *ec, struct wl_listener *listener)
7311 {
7312    API_ENTRY;
7313    wl_signal_add(&priv->events.maximize, listener);
7314 }
7315
7316 EINTERN void
7317 e_client_unmaximize_listener_add(E_Client *ec, struct wl_listener *listener)
7318 {
7319    API_ENTRY;
7320    wl_signal_add(&priv->events.unmaximize, listener);
7321 }
7322
7323 EINTERN void
7324 e_client_fullscreen_pre_listener_add(E_Client *ec, struct wl_listener *listener)
7325 {
7326    API_ENTRY;
7327    wl_signal_add(&priv->events.fullscreen_pre, listener);
7328 }
7329
7330 EINTERN void
7331 e_client_fullscreen_listener_add(E_Client *ec, struct wl_listener *listener)
7332 {
7333    API_ENTRY;
7334    wl_signal_add(&priv->events.fullscreen, listener);
7335 }
7336
7337 EINTERN void
7338 e_client_unfullscreen_listener_add(E_Client *ec, struct wl_listener *listener)
7339 {
7340    API_ENTRY;
7341    wl_signal_add(&priv->events.unfullscreen, listener);
7342 }
7343
7344 EINTERN void
7345 e_client_move_listener_add(E_Client *ec, struct wl_listener *listener)
7346 {
7347    API_ENTRY;
7348    wl_signal_add(&priv->events.move, listener);
7349 }
7350
7351 EINTERN void
7352 e_client_raise_listener_add(E_Client *ec, struct wl_listener *listener)
7353 {
7354    API_ENTRY;
7355    wl_signal_add(&priv->events.raise, listener);
7356 }
7357
7358 EINTERN void
7359 e_client_lower_listener_add(E_Client *ec, struct wl_listener *listener)
7360 {
7361    API_ENTRY;
7362    wl_signal_add(&priv->events.lower, listener);
7363 }
7364
7365 EINTERN void
7366 e_client_stack_below_listener_add(E_Client *ec, struct wl_listener *listener)
7367 {
7368    API_ENTRY;
7369    wl_signal_add(&priv->events.stack_below, listener);
7370 }
7371
7372 EINTERN void
7373 e_client_stack_above_listener_add(E_Client *ec, struct wl_listener *listener)
7374 {
7375    API_ENTRY;
7376    wl_signal_add(&priv->events.stack_above, listener);
7377 }
7378
7379 EINTERN void
7380 e_client_set_layer_listener_add(E_Client *ec, struct wl_listener *listener)
7381 {
7382    API_ENTRY;
7383    wl_signal_add(&priv->events.set_layer, listener);
7384 }
7385
7386 EINTERN void
7387 e_client_stack_transient_for_done_listener_add(E_Client *ec, struct wl_listener *listener)
7388 {
7389    API_ENTRY;
7390    wl_signal_add(&priv->events.stack_transient_for_done, listener);
7391 }
7392
7393 EINTERN void
7394 e_client_stick_listener_add(E_Client *ec, struct wl_listener *listener)
7395 {
7396    API_ENTRY;
7397    wl_signal_add(&priv->events.stick, listener);
7398 }
7399
7400 EINTERN void
7401 e_client_unstick_listener_add(E_Client *ec, struct wl_listener *listener)
7402 {
7403    API_ENTRY;
7404    wl_signal_add(&priv->events.unstick, listener);
7405 }
7406
7407 EINTERN struct wl_listener *
7408 e_client_destroy_listener_get(E_Client *ec, wl_notify_func_t notify)
7409 {
7410    API_ENTRY_VAL(NULL);
7411    return wl_signal_get(&priv->events.destroy, notify);
7412 }
7413
7414 #ifdef REFACTOR_DESK_AREA
7415 EINTERN void
7416 e_client_get_above_listener_add(E_Client *ec, struct wl_listener *listener)
7417 {
7418    API_ENTRY;
7419    wl_signal_add(&priv->events.get_above, listener);
7420 }
7421
7422 EINTERN void
7423 e_client_get_below_listener_add(E_Client *ec, struct wl_listener *listener)
7424 {
7425    API_ENTRY;
7426    wl_signal_add(&priv->events.get_below, listener);
7427 }
7428
7429 EINTERN void
7430 e_client_get_visible_above_listener_add(E_Client *ec, struct wl_listener *listener)
7431 {
7432    API_ENTRY;
7433    wl_signal_add(&priv->events.get_visible_above, listener);
7434 }
7435
7436 EINTERN void
7437 e_client_get_visible_below_listener_add(E_Client *ec, struct wl_listener *listener)
7438 {
7439    API_ENTRY;
7440    wl_signal_add(&priv->events.get_visible_below, listener);
7441 }
7442
7443 EINTERN void
7444 e_client_subsurface_stack_update_listener_add(E_Client *ec, struct wl_listener *listener)
7445 {
7446    API_ENTRY;
7447    wl_signal_add(&priv->events.subsurface_stack_update, listener);
7448 }
7449 #endif
7450
7451 EINTERN void
7452 e_client_delete_request_listener_add(E_Client *ec, struct wl_listener *listener)
7453 {
7454    API_ENTRY;
7455    wl_signal_add(&priv->events.delete_request, listener);
7456 }
7457
7458 EINTERN void
7459 e_client_kill_request_listener_add(E_Client *ec, struct wl_listener *listener)
7460 {
7461    API_ENTRY;
7462    wl_signal_add(&priv->events.kill_request, listener);
7463 }
7464
7465 EINTERN void
7466 e_client_ping_listener_add(E_Client *ec, struct wl_listener *listener)
7467 {
7468    API_ENTRY;
7469    wl_signal_add(&priv->events.ping, listener);
7470 }
7471
7472 EINTERN void
7473 e_client_shell_configure_send(E_Client *ec, uint32_t edges, int32_t width, int32_t height)
7474 {
7475    EINA_SAFETY_ON_NULL_RETURN(ec);
7476    EINA_SAFETY_ON_NULL_RETURN(ec->comp_data);
7477
7478    if ((!ec->comp_data->shell.surface) ||
7479        (!ec->comp_data->shell.configure_send))
7480      return;
7481
7482    ec->comp_data->shell.configure_send(ec->comp_data->shell.surface, edges, width, height);
7483 }
7484
7485 EINTERN void
7486 e_client_shell_configure(E_Client *ec, Evas_Coord x, Evas_Coord y, Evas_Coord width, Evas_Coord height)
7487 {
7488    EINA_SAFETY_ON_NULL_RETURN(ec);
7489    EINA_SAFETY_ON_NULL_RETURN(ec->comp_data);
7490
7491    if ((!ec->comp_data->shell.surface) ||
7492        (!ec->comp_data->shell.configure))
7493      return;
7494
7495    ec->comp_data->shell.configure(ec->comp_data->shell.surface, x, y, width, height);
7496 }
7497
7498 EINTERN void
7499 e_client_shell_ping(E_Client *ec)
7500 {
7501    EINA_SAFETY_ON_NULL_RETURN(ec);
7502    EINA_SAFETY_ON_NULL_RETURN(ec->comp_data);
7503
7504    if ((!ec->comp_data->shell.surface) ||
7505        (!ec->comp_data->shell.ping))
7506      return;
7507
7508    ec->comp_data->shell.ping(ec->comp_data->shell.surface);
7509 }
7510
7511 static void
7512 _e_input_thread_client_icccm_name_set(void *data)
7513 {
7514    E_Input_Thread_Request_EClient_Data *ec_data = data;
7515    EINA_SAFETY_ON_NULL_RETURN(ec_data);
7516
7517    INF("[input thread|%s] ec(%p), name(%s)\n", __func__, ec_data->ec, ec_data->icccm_name);
7518    e_input_thread_client_icccm_name_set(e_input_thread_client_get(ec_data->ec), ec_data->icccm_name);
7519 }
7520
7521 EINTERN void
7522 e_client_icccm_name_set(E_Client *ec, const char *name)
7523 {
7524    E_Input_Thread_Request_EClient_Data ec_data;
7525    memset(&ec_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
7526
7527    EINA_SAFETY_ON_NULL_RETURN(ec);
7528
7529    if (eina_stringshare_replace(&ec->icccm.name, name))
7530      {
7531         ec->changes.title = EINA_TRUE;
7532
7533         ec_data.ec = ec;
7534         ec_data.wl_surface = ec->comp_data ? ec->comp_data->wl_surface : NULL;
7535         ec_data.is_video = EINA_FALSE;
7536
7537         if (name)
7538           strncpy(ec_data.icccm_name, name, sizeof(ec_data.icccm_name)-1);
7539
7540         INF("[%s] ec(%p), surface(%p), name(%s)\n", __func__, ec, ec_data.wl_surface, name);
7541         e_input_thread_safe_call(_e_input_thread_client_icccm_name_set, &ec_data, sizeof(E_Input_Thread_Request_EClient_Data));
7542      }
7543 }
7544
7545 E_API Eina_Stringshare *
7546 e_client_icccm_name_get(E_Client *ec)
7547 {
7548    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
7549
7550    return ec->icccm.name;
7551 }
7552
7553 static void
7554 _e_input_thread_client_netwm_name_set(void *data)
7555 {
7556    E_Input_Thread_Request_EClient_Data *ec_data = data;
7557    EINA_SAFETY_ON_NULL_RETURN(ec_data);
7558
7559    INF("[input thread|%s] ec(%p), name(%p)\n", __func__, ec_data->ec, ec_data->netwm_name);
7560    e_input_thread_client_netwm_name_set(e_input_thread_client_get(ec_data->ec), ec_data->netwm_name);
7561 }
7562
7563 EINTERN void
7564 e_client_netwm_name_set(E_Client *ec, const char *name)
7565 {
7566    E_Input_Thread_Request_EClient_Data ec_data = { NULL, NULL, EINA_FALSE, EINA_FALSE };
7567    memset(&ec_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
7568
7569    EINA_SAFETY_ON_NULL_RETURN(ec);
7570
7571    eina_stringshare_replace(&ec->netwm.name, name);
7572
7573    ec_data.ec = ec;
7574    ec_data.wl_surface = ec->comp_data ? ec->comp_data->wl_surface : NULL;
7575
7576    if (name)
7577      strncpy(ec_data.netwm_name, name, sizeof(ec_data.netwm_name)-1);
7578
7579    INF("[%s] ec(%p), surface(%p), name(%s)\n", __func__, ec, ec_data.wl_surface, ec_data.netwm_name);
7580    e_input_thread_safe_call(_e_input_thread_client_netwm_name_set, &ec_data, sizeof(E_Input_Thread_Request_EClient_Data));
7581 }
7582
7583 E_API Eina_Stringshare *
7584 e_client_netwm_name_get(E_Client *ec)
7585 {
7586    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
7587
7588    return ec->netwm.name;
7589 }
7590
7591 static void
7592 _e_input_thread_client_icccm_title_set(void *data)
7593 {
7594    E_Input_Thread_Request_EClient_Data *ec_data = data;
7595    EINA_SAFETY_ON_NULL_RETURN(ec_data);
7596
7597    INF("[input thread|%s] ec(%p), title(%s)\n", __func__, ec_data->ec, ec_data->icccm_title);
7598    e_input_thread_client_icccm_title_set(e_input_thread_client_get(ec_data->ec), ec_data->icccm_title);
7599 }
7600
7601 EINTERN void
7602 e_client_icccm_title_set(E_Client *ec, const char *title)
7603 {
7604    E_Input_Thread_Request_EClient_Data ec_data;
7605    memset(&ec_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
7606
7607    EINA_SAFETY_ON_NULL_RETURN(ec);
7608
7609    if (eina_stringshare_replace(&ec->icccm.title, title))
7610      {
7611         ec->changes.title = EINA_TRUE;
7612
7613         ec_data.ec = ec;
7614         ec_data.wl_surface = ec->comp_data ? ec->comp_data->wl_surface : NULL;
7615         if (title)
7616           strncpy(ec_data.icccm_title, title, sizeof(ec_data.icccm_title)-1);
7617
7618         INF("[%s] ec(%p), surface(%p)\n", __func__, ec, ec_data.wl_surface);
7619         e_input_thread_safe_call(_e_input_thread_client_icccm_title_set, &ec_data, sizeof(E_Input_Thread_Request_EClient_Data));
7620      }
7621 }
7622
7623 E_API Eina_Stringshare *
7624 e_client_icccm_title_get(E_Client *ec)
7625 {
7626    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
7627
7628    return ec->icccm.title;
7629 }
7630
7631 static void
7632 _e_client_shell_map(E_Client *ec)
7633 {
7634    EINA_SAFETY_ON_NULL_RETURN(ec);
7635    EINA_SAFETY_ON_NULL_RETURN(ec->comp_data);
7636
7637    if ((!ec->comp_data->shell.surface) ||
7638        (!ec->comp_data->shell.map))
7639      return;
7640
7641    ec->comp_data->shell.map(ec->comp_data->shell.surface);
7642 }
7643
7644 EINTERN void
7645 e_client_shell_unmap(E_Client *ec)
7646 {
7647    EINA_SAFETY_ON_NULL_RETURN(ec);
7648    EINA_SAFETY_ON_NULL_RETURN(ec->comp_data);
7649
7650    if ((!ec->comp_data->shell.surface) ||
7651        (!ec->comp_data->shell.unmap))
7652      return;
7653
7654    ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
7655 }
7656
7657 EINTERN void
7658 e_client_show(E_Client *ec)
7659 {
7660    EINA_SAFETY_ON_NULL_RETURN(ec);
7661    EINA_SAFETY_ON_NULL_RETURN(ec->comp_data);
7662
7663    if (ec->comp_data->mapped)
7664      return;
7665
7666    if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.map) &&
7667        (!ec->ignored))
7668      {
7669         ELOGF("E_CLIENT", "Map.", ec);
7670         _e_client_shell_map(ec);
7671      }
7672    else if (ec->internal || e_comp_wl_subsurface_can_show(ec) ||
7673             (ec == e_comp_wl->drag_client))
7674      {
7675         ELOGF("E_CLIENT", "Map. internal:%d, drag:%d",
7676               ec, ec->internal, (ec == e_comp_wl->drag_client));
7677         ec->visible = EINA_TRUE;
7678         ec->ignored = 0;
7679         evas_object_show(ec->frame);
7680         ec->comp_data->mapped = 1;
7681      }
7682 }
7683
7684 EINTERN void
7685 e_client_hide(E_Client *ec)
7686 {
7687    API_ENTRY;
7688
7689    EINA_SAFETY_ON_NULL_RETURN(ec->comp_data);
7690
7691    if (!ec->comp_data->mapped)
7692      return;
7693
7694    if ((ec->comp_data->shell.surface) && (ec->comp_data->shell.unmap))
7695      {
7696         ELOGF("E_CLIENT", "Unmap", ec);
7697
7698         if (priv->hide_by_request)
7699           ELOGF("COMP", "Currenlty hide_by_request state.", ec);
7700
7701         if (ec->show_pending.count > 0)
7702           {
7703              ELOGF("E_CLIENT", "Reset show_pending!!! (count:%d, run:%d)", ec, ec->show_pending.count, ec->show_pending.running);
7704              ec->show_pending.count = 0;
7705              if (ec->show_pending.running)
7706                {
7707                   // need to send visibility false;
7708                   e_client_visibility_set(ec, E_VISIBILITY_UNOBSCURED);
7709                   ELOGF("POL_VIS", "CLIENT VIS ON (fake).  argb:%d, opaque:%2d", ec, ec->argb, ec->visibility.opaque);
7710                   EC_CHANGED(ec);
7711                }
7712              ec->show_pending.running = EINA_FALSE;
7713           }
7714         e_client_shell_unmap(ec);
7715      }
7716    else if ((ec->internal) || (e_comp_wl_subsurface_check(ec)) ||
7717             (ec == e_comp_wl->drag_client))
7718      {
7719         ELOGF("E_CLIENT", "Unmap. internal:%d, sub:%p, drag:%d",
7720               ec, ec->internal, ec->comp_data->sub.data, (ec == e_comp_wl->drag_client));
7721         ec->visible = EINA_FALSE;
7722         evas_object_hide(ec->frame);
7723         ec->comp_data->mapped = 0;
7724      }
7725 }
7726
7727 static void
7728 _e_input_thread_client_video_mode_set(void *data)
7729 {
7730    E_Input_Thread_Request_EClient_Data *ec_data = data;
7731    EINA_SAFETY_ON_NULL_RETURN(ec_data);
7732
7733    INF("[input thread|%s] ec(%p), is_video(%d)\n", __func__, ec_data->ec, ec_data->is_video);
7734    e_input_thread_client_video_set(e_input_thread_client_get(ec_data->ec), ec_data->is_video);
7735 }
7736
7737 EINTERN void
7738 e_client_video_mode_set(E_Client *ec, Eina_Bool is_video)
7739 {
7740    E_Input_Thread_Request_EClient_Data ec_data;
7741    memset(&ec_data, 0, sizeof(E_Input_Thread_Request_EClient_Data));
7742
7743    EINA_SAFETY_ON_NULL_RETURN(ec);
7744    EINA_SAFETY_ON_NULL_RETURN(ec->hwc_window);
7745
7746    ec->hwc_window->is_video = is_video;
7747
7748    ec_data.ec = ec;
7749    ec_data.is_video = is_video;
7750
7751    INF("[%s] ec(%p), is_video(%d)\n", __func__, ec, is_video);
7752    e_input_thread_safe_call(_e_input_thread_client_video_mode_set, &ec_data, sizeof(E_Input_Thread_Request_EClient_Data));
7753 }