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