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