e_desk_area: make e_desk_area_ec_reassign
[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         if (ec->override)
4417           e_client_layer_set(ec, E_LAYER_CLIENT_ABOVE);
4418         else
4419           e_client_layer_set(ec, E_LAYER_CLIENT_NORMAL);
4420      }
4421
4422 #ifdef REFACTOR_ZONE_DESK
4423 #else
4424    if (ec->override)
4425      _e_client_zone_update(ec);
4426    else
4427      e_client_desk_set(ec, e_desk_current_get(e_zone_current_get()));
4428 #endif
4429
4430    wl_signal_emit_mutable(&PRI(ec)->events.new_client_post, NULL);
4431 #ifdef _F_E_CLIENT_NEW_CLIENT_POST_HOOK_
4432    _e_client_hook_call(E_CLIENT_HOOK_NEW_CLIENT_POST, ec);
4433 #endif
4434
4435    ec->manage_resize.resize_obj = NULL;
4436    ec->manage_resize.x = ec->manage_resize.y = ec->manage_resize.w = ec->manage_resize.h = 0;
4437    ec->manage_resize.enable_aspect_ratio = EINA_FALSE;
4438    ec->manage_resize.aw = ec->manage_resize.ah = 0;
4439    ec->manage_resize.header_h = 0;
4440    ec->manage_resize.footer_h = 0;
4441
4442    ec->visibility.ignore_geometry = e_config->calc_vis_ignore_geometry;
4443
4444    return ec;
4445 }
4446
4447 E_API Eina_Bool e_client_is_internal(E_Client *ec)
4448 {
4449    E_OBJECT_CHECK_RETURN(ec, EINA_TRUE);
4450    return ec->internal;
4451 }
4452
4453 #ifdef REFACTOR_ZONE_DESK
4454 #else
4455 EINTERN void
4456 e_client_desk_set(E_Client *ec, E_Desk *desk)
4457 {
4458    E_Event_Client_Desk_Set *ev;
4459    E_Desk *old_desk;
4460    E_Zone *zone;
4461
4462    E_OBJECT_CHECK(ec);
4463    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4464    E_OBJECT_CHECK(desk);
4465    E_OBJECT_TYPE_CHECK(desk, E_DESK_TYPE);
4466    if (e_desk_has_ec(desk, ec)) return;
4467
4468    if (ec->fullscreen)
4469      {
4470         ec->desk->fullscreen_clients = eina_list_remove(ec->desk->fullscreen_clients, ec);
4471         desk->fullscreen_clients = eina_list_append(desk->fullscreen_clients, ec);
4472      }
4473    old_desk = ec->desk;
4474    if (old_desk)
4475      e_desk_client_del(old_desk, ec);
4476    ec->desk = desk;
4477    e_desk_client_add(desk, ec);
4478    if (!ec->new_client)
4479      {
4480         if (ec->frame)
4481           {
4482              e_comp_object_effect_unclip(ec->frame);
4483              e_comp_object_effect_set(ec->frame, NULL);
4484           }
4485         if (desk->visible || ec->sticky)
4486           {
4487              if ((!ec->hidden) && (!ec->iconic))
4488                evas_object_show(ec->frame);
4489           }
4490         else
4491           {
4492              ec->hidden = 1;
4493              evas_object_hide(ec->frame);
4494           }
4495      }
4496    e_client_comp_hidden_set(ec, (!desk->visible) && (!ec->sticky));
4497    e_client_zone_set(ec, desk->zone);
4498
4499    if (old_desk)
4500      {
4501         ev = E_NEW(E_Event_Client_Desk_Set, 1);
4502         if (ev)
4503           {
4504              ev->ec = ec;
4505              UNREFD(ec, 4);
4506              e_object_ref(E_OBJECT(ec));
4507              ev->desk = old_desk;
4508              e_object_ref(E_OBJECT(old_desk));
4509              ecore_event_add(E_EVENT_CLIENT_DESK_SET, ev, (Ecore_End_Cb)_e_client_event_desk_set_free, NULL);
4510           }
4511
4512         zone = e_comp_zone_find_by_ec(ec);
4513         if (old_desk->zone == zone)
4514           {
4515              e_client_res_change_geometry_save(ec);
4516              e_client_res_change_geometry_restore(ec);
4517              ec->pre_res_change.valid = 0;
4518           }
4519      }
4520
4521    if (e_config->transient.desktop)
4522      {
4523         E_Client *child;
4524         const Eina_List *l;
4525
4526         EINA_LIST_FOREACH(ec->transients, l, child)
4527           e_client_desk_set(child, ec->desk);
4528      }
4529
4530    _e_client_hook_call(E_CLIENT_HOOK_DESK_SET, ec);
4531    evas_object_smart_callback_call(ec->frame, "desk_change", ec);
4532
4533    if (ec->desk->desk_area.enable)
4534      {
4535         if (!ec->desk_area.desk_area)
4536           {
4537              E_Desk_Area *eda;
4538              eda = e_desk_desk_area_base_get(ec->desk);
4539              e_client_desk_area_set(ec, eda);
4540           }
4541
4542         e_client_desk_area_enable_set(ec, EINA_TRUE);
4543      }
4544 }
4545 #endif
4546
4547 EINTERN void
4548 e_client_desk_iconify_skip_set(E_Client *ec, Eina_Bool skip)
4549 {
4550    if (!ec) return;
4551    ec->user_skip_winlist = skip;
4552 }
4553
4554 EINTERN Eina_Bool
4555 e_client_desk_iconify_skip_get(E_Client *ec)
4556 {
4557    if (!ec) return EINA_FALSE;
4558    return ec->user_skip_winlist;
4559 }
4560
4561 EINTERN Eina_Bool
4562 e_client_comp_grabbed_get(void)
4563 {
4564    return comp_grabbed;
4565 }
4566
4567 EINTERN E_Client *
4568 e_client_action_get(void)
4569 {
4570    return action_client;
4571 }
4572
4573
4574 //////////////////////////////////////////////////////////
4575
4576 EINTERN void
4577 e_client_mouse_in(E_Client *ec, int x, int y)
4578 {
4579    E_Desk *desk;
4580
4581    if (comp_grabbed) return;
4582    if (e_object_is_del(E_OBJECT(ec))) return;
4583    desk = e_comp_desk_find_by_ec(ec);
4584    if (desk && desk->animate_count) return;
4585    ec->mouse.current.mx = x;
4586    ec->mouse.current.my = y;
4587    ec->mouse.in = 1;
4588
4589 #ifdef REFACTOR_FOCUS_POLICY
4590    wl_signal_emit_mutable(&PRI(ec)->events.mouse_in, NULL);
4591    _e_client_hook_call(E_CLIENT_HOOK_MOUSE_IN, ec);
4592 #else
4593    if ((!ec->iconic) && (!e_client_util_ignored_get(ec)))
4594      e_focus_event_mouse_in(ec);
4595 #endif
4596 }
4597
4598 EINTERN void
4599 e_client_mouse_out(E_Client *ec, int x, int y)
4600 {
4601    E_Desk *desk;
4602
4603    if (comp_grabbed) return;
4604    if (ec->fullscreen) return;
4605    if (e_object_is_del(E_OBJECT(ec))) return;
4606    desk = e_comp_desk_find_by_ec(ec);
4607    if (desk && desk->animate_count) return;
4608
4609    ec->mouse.current.mx = x;
4610    ec->mouse.current.my = y;
4611    ec->mouse.in = 0;
4612
4613 #ifdef REFACTOR_FOCUS_POLICY
4614    wl_signal_emit_mutable(&PRI(ec)->events.mouse_out, NULL);
4615    _e_client_hook_call(E_CLIENT_HOOK_MOUSE_OUT, ec);
4616 #else
4617    if ((!ec->iconic) && (!e_client_util_ignored_get(ec)))
4618      e_focus_event_mouse_out(ec);
4619 #endif
4620 }
4621
4622 EINTERN void
4623 e_client_mouse_wheel(E_Client *ec, Evas_Point *output, E_Binding_Event_Wheel *ev)
4624 {
4625    EINA_SAFETY_ON_NULL_RETURN(ec);
4626    if (action_client) return;
4627    ec->mouse.current.mx = output->x;
4628    ec->mouse.current.my = output->y;
4629 }
4630
4631 EINTERN void
4632 e_client_mouse_down(E_Client *ec, int button, Evas_Point *output, E_Binding_Event_Mouse_Button *ev)
4633 {
4634 #ifdef REFACTOR_FOCUS_POLICY
4635 #else
4636    E_Client *focused;
4637 #endif
4638
4639    EINA_SAFETY_ON_NULL_RETURN(ec);
4640    if (action_client || ec->iconic || e_client_util_ignored_get(ec)) return;
4641    if ((button >= 1) && (button <= 3))
4642      {
4643         ec->mouse.last_down[button - 1].mx = output->x;
4644         ec->mouse.last_down[button - 1].my = output->y;
4645         ec->mouse.last_down[button - 1].x = ec->x;
4646         ec->mouse.last_down[button - 1].y = ec->y;
4647         ec->mouse.last_down[button - 1].w = ec->w;
4648         ec->mouse.last_down[button - 1].h = ec->h;
4649      }
4650    else
4651      {
4652         ec->moveinfo.down.x = ec->x;
4653         ec->moveinfo.down.y = ec->y;
4654         ec->moveinfo.down.w = ec->w;
4655         ec->moveinfo.down.h = ec->h;
4656      }
4657    ec->mouse.current.mx = output->x;
4658    ec->mouse.current.my = output->y;
4659    if ((button >= 1) && (button <= 3))
4660      {
4661         ec->mouse.last_down[button - 1].mx = output->x;
4662         ec->mouse.last_down[button - 1].my = output->y;
4663         ec->mouse.last_down[button - 1].x = ec->x;
4664         ec->mouse.last_down[button - 1].y = ec->y;
4665         ec->mouse.last_down[button - 1].w = ec->w;
4666         ec->mouse.last_down[button - 1].h = ec->h;
4667      }
4668    else
4669      {
4670         ec->moveinfo.down.x = ec->x;
4671         ec->moveinfo.down.y = ec->y;
4672         ec->moveinfo.down.w = ec->w;
4673         ec->moveinfo.down.h = ec->h;
4674      }
4675    ec->mouse.current.mx = output->x;
4676    ec->mouse.current.my = output->y;
4677
4678 #ifdef REFACTOR_FOCUS_POLICY
4679    wl_signal_emit_mutable(&PRI(ec)->events.mouse_down, NULL);
4680    _e_client_hook_call(E_CLIENT_HOOK_MOUSE_DOWN, ec);
4681 #else
4682    focused = e_client_focused_get();
4683    if ((focused) && (ec != focused))
4684      {
4685         e_focus_event_mouse_down(ec);
4686      }
4687 #endif
4688 }
4689
4690 EINTERN void
4691 e_client_mouse_up(E_Client *ec, int button, Evas_Point *output, E_Binding_Event_Mouse_Button* ev)
4692 {
4693    EINA_SAFETY_ON_NULL_RETURN(ec);
4694    if (ec->iconic || e_client_util_ignored_get(ec)) return;
4695    if ((button >= 1) && (button <= 3))
4696      {
4697         ec->mouse.last_up[button - 1].mx = output->x;
4698         ec->mouse.last_up[button - 1].my = output->y;
4699         ec->mouse.last_up[button - 1].x = ec->x;
4700         ec->mouse.last_up[button - 1].y = ec->y;
4701      }
4702    ec->mouse.current.mx = output->x;
4703    ec->mouse.current.my = output->y;
4704    /* also we don't pass the same params that went in - then again that */
4705    /* should be ok as we are just ending the action if it has an end */
4706    if (ec->cur_mouse_action)
4707      {
4708         if (ec->cur_mouse_action->func.end_mouse)
4709           ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", ev);
4710         else if (ec->cur_mouse_action->func.end)
4711           ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
4712         e_object_unref(E_OBJECT(ec->cur_mouse_action));
4713         ec->cur_mouse_action = NULL;
4714      }
4715
4716    if ((button >= 1) && (button <= 3))
4717      {
4718         ec->mouse.last_up[button - 1].mx = output->x;
4719         ec->mouse.last_up[button - 1].my = output->y;
4720         ec->mouse.last_up[button - 1].x = ec->x;
4721         ec->mouse.last_up[button - 1].y = ec->y;
4722      }
4723 }
4724
4725 E_API void
4726 e_client_stay_within_canvas_margin(E_Client *ec)
4727 {
4728    int new_x = ec->x;
4729    int new_y = ec->y;
4730
4731    if (ec->floating)
4732      {
4733         _e_client_stay_within_canvas_margin(ec, ec->x, ec->y, &new_x, &new_y);
4734
4735         if ((ec->x != new_x) || (ec->y != new_y))
4736           evas_object_move(ec->frame, new_x, new_y);
4737      }
4738 }
4739
4740 EINTERN void
4741 e_client_mouse_move(E_Client *ec, Evas_Point *output)
4742 {
4743    EINA_SAFETY_ON_NULL_RETURN(ec);
4744    if (ec->iconic || e_client_util_ignored_get(ec)) return;
4745    ec->mouse.current.mx = output->x;
4746    ec->mouse.current.my = output->y;
4747    if (e_client_util_moving_get(ec))
4748      {
4749         _e_client_move_handle(ec);
4750      }
4751    else if (e_client_util_resizing_get(ec))
4752      {
4753         _e_client_resize_handle(ec);
4754      }
4755 }
4756 ///////////////////////////////////////////////////////
4757
4758 EINTERN void
4759 e_client_res_change_geometry_save(E_Client *ec)
4760 {
4761    E_OBJECT_CHECK(ec);
4762    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4763
4764    if (ec->pre_res_change.valid) return;
4765    ec->pre_res_change.valid = 1;
4766    ec->pre_res_change.x = ec->x;
4767    ec->pre_res_change.y = ec->y;
4768    ec->pre_res_change.w = ec->w;
4769    ec->pre_res_change.h = ec->h;
4770    ec->pre_res_change.saved.x = ec->saved.x;
4771    ec->pre_res_change.saved.y = ec->saved.y;
4772    ec->pre_res_change.saved.w = ec->saved.w;
4773    ec->pre_res_change.saved.h = ec->saved.h;
4774 }
4775
4776 EINTERN void
4777 e_client_res_change_geometry_restore(E_Client *ec)
4778 {
4779    E_Zone *zone;
4780
4781    struct
4782    {
4783       unsigned char valid : 1;
4784       int           x, y, w, h;
4785       struct
4786       {
4787          int x, y, w, h;
4788       } saved;
4789    } pre_res_change;
4790
4791    E_OBJECT_CHECK(ec);
4792    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4793    if (!ec->pre_res_change.valid) return;
4794    if (ec->new_client) return;
4795
4796    zone = e_comp_zone_find_by_ec(ec);
4797    if (!zone) return;
4798
4799    memcpy(&pre_res_change, &ec->pre_res_change, sizeof(pre_res_change));
4800
4801    if (ec->fullscreen)
4802      {
4803         e_client_unfullscreen(ec);
4804         e_client_fullscreen(ec, e_config->fullscreen_policy);
4805      }
4806    else if (ec->maximized != E_MAXIMIZE_NONE)
4807      {
4808         E_Maximize max;
4809
4810         max = ec->maximized;
4811         e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
4812         e_client_maximize(ec, max);
4813      }
4814    else
4815      {
4816         int x, y, w, h, zx, zy, zw, zh;
4817
4818         ec->saved.x = ec->pre_res_change.saved.x;
4819         ec->saved.y = ec->pre_res_change.saved.y;
4820         ec->saved.w = ec->pre_res_change.saved.w;
4821         ec->saved.h = ec->pre_res_change.saved.h;
4822
4823         e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
4824
4825         if (ec->saved.w > zw)
4826           ec->saved.w = zw;
4827         if ((ec->saved.x + ec->saved.w) > (zx + zw))
4828           ec->saved.x = zx + zw - ec->saved.w;
4829
4830         if (ec->saved.h > zh)
4831           ec->saved.h = zh;
4832         if ((ec->saved.y + ec->saved.h) > (zy + zh))
4833           ec->saved.y = zy + zh - ec->saved.h;
4834
4835         x = ec->pre_res_change.x;
4836         y = ec->pre_res_change.y;
4837         w = ec->pre_res_change.w;
4838         h = ec->pre_res_change.h;
4839         if (w > zw)
4840           w = zw;
4841         if (h > zh)
4842           h = zh;
4843         if ((x + w) > (zx + zw))
4844           x = zx + zw - w;
4845         if ((y + h) > (zy + zh))
4846           y = zy + zh - h;
4847         evas_object_geometry_set(ec->frame, x, y, w, h);
4848      }
4849    memcpy(&ec->pre_res_change, &pre_res_change, sizeof(pre_res_change));
4850 }
4851
4852 #ifdef REFACTOR_ZONE_DESK
4853 #else
4854 EINTERN void
4855 e_client_zone_set(E_Client *ec, E_Zone *zone)
4856 {
4857    E_Event_Client_Zone_Set *ev;
4858
4859    E_OBJECT_CHECK(ec);
4860    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4861    E_OBJECT_CHECK(zone);
4862    E_OBJECT_TYPE_CHECK(zone, E_ZONE_TYPE);
4863    if (e_zone_has_ec(zone, ec)) return;
4864
4865    ev = E_NEW(E_Event_Client_Zone_Set, 1);
4866    if (!ev) return;
4867
4868    /* if the window does not lie in the new zone, move it so that it does */
4869    if (!E_INTERSECTS(ec->x, ec->y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h))
4870      {
4871         int x, y;
4872
4873         x = ec->x, y = ec->y;
4874
4875         /* keep window from hanging off bottom and left */
4876         if (x + ec->w > zone->x + zone->w) x += (zone->x + zone->w) - (x + ec->w);
4877         if (y + ec->h > zone->y + zone->h) y += (zone->y + zone->h) - (y + ec->h);
4878
4879         /* make sure to and left are on screen (if the window is larger than the zone, it will hang off the bottom / right) */
4880         if (x < zone->x) x = zone->x;
4881         if (y < zone->y) y = zone->y;
4882
4883         if (!E_INTERSECTS(x, y, ec->w, ec->h, zone->x, zone->y, zone->w, zone->h))
4884           {
4885              /* still not in zone at all, so just move it to closest edge */
4886              if (x < zone->x) x = zone->x;
4887              if (x >= zone->x + zone->w) x = zone->x + zone->w - ec->w;
4888              if (y < zone->y) y = zone->y;
4889              if (y >= zone->y + zone->h) y = zone->y + zone->h - ec->h;
4890           }
4891         evas_object_move(ec->frame, x, y);
4892      }
4893
4894    // TODO: NEED TO DELETE LINE BELOW
4895    ec->zone = zone;
4896
4897    ev->ec = ec;
4898    REFD(ec, 5);
4899    e_object_ref(E_OBJECT(ec));
4900    ev->zone = zone;
4901    e_object_ref(E_OBJECT(zone));
4902
4903    ecore_event_add(E_EVENT_CLIENT_ZONE_SET, ev, (Ecore_End_Cb)_e_client_event_zone_set_free, NULL);
4904
4905    // TODO: change all use of e_client_zone_set() to e_zone_client_add()
4906    e_zone_client_add(zone, ec);
4907 }
4908 #endif
4909
4910 EINTERN void
4911 e_client_pos_set(E_Client *ec, int x, int y)
4912 {
4913    if (!ec) return;
4914    ec->x = x;
4915    ec->y = y;
4916 }
4917
4918 EINTERN void
4919 e_client_pos_get(E_Client *ec, int *x, int *y)
4920 {
4921    int ex = 0;
4922    int ey = 0;
4923
4924    if (ec)
4925      {
4926         ex = ec->x;
4927         ey = ec->y;
4928      }
4929
4930    if (x) *x = ex;
4931    if (y) *y = ey;
4932 }
4933
4934 E_API void
4935 e_client_size_set(E_Client *ec, int w, int h)
4936 {
4937    if (!ec) return;
4938    ec->w = w;
4939    ec->h = h;
4940 }
4941
4942 E_API void
4943 e_client_size_get(E_Client *ec, int *w, int *h)
4944 {
4945    int ew = 0;
4946    int eh = 0;
4947
4948    if (ec)
4949      {
4950         ew = ec->w;
4951         eh = ec->h;
4952      }
4953
4954    if (w) *w = ew;
4955    if (h) *h = eh;
4956 }
4957
4958 E_API void
4959 e_client_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
4960 {
4961    int gx = 0;
4962    int gy = 0;
4963    int gw = 0;
4964    int gh = 0;
4965
4966    E_OBJECT_CHECK(ec);
4967    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
4968
4969    if (e_client_transform_core_enable_get(ec))
4970      {
4971         gx = ec->transform_core.result.boundary.x;
4972         gy = ec->transform_core.result.boundary.y;
4973         gw = ec->transform_core.result.boundary.w;
4974         gh = ec->transform_core.result.boundary.h;
4975      }
4976    else
4977      {
4978         if (ec->frame)
4979           {
4980              evas_object_geometry_get(ec->frame, &gx, &gy, &gw, &gh);
4981              if (gw == 0 && gh == 0)
4982                {
4983                   /* In this case, there is no image buffer in e_comp_object, thus it
4984                    * should return geometry value of ec itself. It usually happens if
4985                    * new ec is not mapped yet.
4986                    */
4987                   gw = ec->w;
4988                   gh = ec->h;
4989                   gx = ec->x;
4990                   gy = ec->y;
4991                }
4992           }
4993         else
4994           {
4995              gx = ec->x;
4996              gy = ec->y;
4997              gw = ec->w;
4998              gh = ec->h;
4999           }
5000      }
5001
5002    if (x) *x = gx;
5003    if (y) *y = gy;
5004    if (w) *w = gw;
5005    if (h) *h = gh;
5006 }
5007
5008 E_API E_Client *
5009 e_client_above_get(const E_Client *ec)
5010 {
5011    unsigned int x;
5012    E_Client *ec2;
5013
5014    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
5015    if (EINA_INLIST_GET(ec)->next) //check current layer
5016      {
5017         EINA_INLIST_FOREACH(EINA_INLIST_GET(ec)->next, ec2)
5018           {
5019              if (ec == ec2)
5020                {
5021                   ELOGF("FATAL", "CHECK the ec inlist next", ec);
5022                   continue;
5023                }
5024              if (!e_object_is_del(E_OBJECT(ec2)))
5025                return ec2;
5026           }
5027      }
5028    if (ec->layer == E_LAYER_CLIENT_CURSOR) return NULL;
5029    if (e_comp_canvas_client_layer_map(ec->layer) == 9999) return NULL;
5030
5031    /* go up the layers until we find one */
5032    for (x = e_comp_canvas_layer_map(ec->layer) + 1; x <= e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR); x++)
5033      {
5034         if (!e_comp->layers[x].clients) continue;
5035         EINA_INLIST_FOREACH(e_comp->layers[x].clients, ec2)
5036           {
5037              if (ec == ec2)
5038                {
5039                   ELOGF("FATAL", "EC exist above layer. ec layer_map:%d, cur layer_map:%d",
5040                         ec, e_comp_canvas_layer_map(ec->layer), x);
5041                   continue;
5042                }
5043              if (!e_object_is_del(E_OBJECT(ec2)))
5044                return ec2;
5045           }
5046      }
5047    return NULL;
5048 }
5049
5050 E_API E_Client *
5051 e_client_below_get(const E_Client *ec)
5052 {
5053    unsigned int x;
5054    E_Client *ec2;
5055    Eina_Inlist *l;
5056    E_Layer ec_layer, ec_layer_cw;
5057    int cw_layer;
5058
5059    E_OBJECT_CHECK_RETURN(ec, NULL);
5060    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, NULL);
5061
5062    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
5063    if (EINA_INLIST_GET(ec)->prev) //check current layer
5064      {
5065         for (l = EINA_INLIST_GET(ec)->prev; l; l = l->prev)
5066           {
5067              ec2 = EINA_INLIST_CONTAINER_GET(l, E_Client);
5068              if (ec == ec2)
5069                {
5070                   ELOGF("FATAL", "CHECK the ec inlist prev", ec);
5071                   continue;
5072                }
5073              if (!e_object_is_del(E_OBJECT(ec2)))
5074                return ec2;
5075           }
5076      }
5077
5078    // check layer validation
5079    ec_layer = ec->layer;
5080    if (ec->layer_block || ec->layer_pending)
5081      {
5082         cw_layer = e_comp_object_layer_get(ec->frame);
5083         if (cw_layer >= 0)
5084           {
5085              ec_layer_cw = e_comp_canvas_layer_map_to(cw_layer);
5086              if (ec_layer != ec_layer_cw)
5087                {
5088                   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);
5089                   ec_layer = ec_layer_cw;
5090                }
5091           }
5092      }
5093
5094    if (ec_layer == E_LAYER_CLIENT_DESKTOP) return NULL;
5095    if (e_comp_canvas_client_layer_map(ec_layer) == 9999) return NULL;
5096
5097    /* go down the layers until we find one */
5098    x = e_comp_canvas_layer_map(ec_layer);
5099    if (x > 0) x--;
5100
5101    for (; x >= e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); x--)
5102      {
5103         if (!e_comp->layers[x].clients) continue;
5104         EINA_INLIST_REVERSE_FOREACH(e_comp->layers[x].clients, ec2)
5105           {
5106              if (ec == ec2)
5107                {
5108                   ELOGF("FATAL", "EC exist below layer. ec layer_map:%d, cur layer_map:%d",
5109                         ec, e_comp_canvas_layer_map(ec_layer), x);
5110                   continue;
5111                }
5112              if (!e_object_is_del(E_OBJECT(ec2)))
5113                return ec2;
5114           }
5115      }
5116    return NULL;
5117 }
5118
5119 E_API E_Client *
5120 e_client_bottom_get(void)
5121 {
5122    unsigned int x;
5123    for (x = e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); x <= e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR); x++)
5124      {
5125         E_Client *ec2;
5126
5127         if (!e_comp->layers[x].clients) continue;
5128         EINA_INLIST_FOREACH(e_comp->layers[x].clients, ec2)
5129           if (!e_object_is_del(E_OBJECT(ec2)))
5130             return ec2;
5131      }
5132    return NULL;
5133 }
5134
5135 E_API E_Client *
5136 e_client_top_get(void)
5137 {
5138    unsigned int x;
5139    for (x = e_comp_canvas_layer_map(E_LAYER_CLIENT_CURSOR); x >= e_comp_canvas_layer_map(E_LAYER_CLIENT_DESKTOP); x--)
5140      {
5141         E_Client *ec2;
5142
5143         if (!e_comp->layers[x].clients) continue;
5144         EINA_INLIST_REVERSE_FOREACH(e_comp->layers[x].clients, ec2)
5145           if (!e_object_is_del(E_OBJECT(ec2)))
5146             return ec2;
5147      }
5148    return NULL;
5149 }
5150
5151 EINTERN unsigned int
5152 e_clients_count(void)
5153 {
5154    return eina_list_count(e_comp->clients);
5155 }
5156
5157
5158 /**
5159  * Set a callback which will be called just prior to updating the
5160  * move coordinates for a border
5161  */
5162 EINTERN void
5163 e_client_move_intercept_cb_set(E_Client *ec, E_Client_Move_Intercept_Cb cb)
5164 {
5165    ec->move_intercept_cb = cb;
5166 }
5167
5168 ///////////////////////////////////////
5169
5170 E_API E_Client_Hook *
5171 e_client_hook_add(E_Client_Hook_Point hookpoint, E_Client_Hook_Cb func, const void *data)
5172 {
5173    E_Client_Hook *ch;
5174
5175    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_CLIENT_HOOK_LAST, NULL);
5176    ch = E_NEW(E_Client_Hook, 1);
5177    if (!ch) return NULL;
5178    ch->hookpoint = hookpoint;
5179    ch->func = func;
5180    ch->data = (void*)data;
5181    _e_client_hooks[hookpoint] = eina_inlist_append(_e_client_hooks[hookpoint], EINA_INLIST_GET(ch));
5182    return ch;
5183 }
5184
5185 E_API void
5186 e_client_hook_del(E_Client_Hook *ch)
5187 {
5188    ch->delete_me = 1;
5189    if (_e_client_hooks_walking == 0)
5190      {
5191         _e_client_hooks[ch->hookpoint] = eina_inlist_remove(_e_client_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
5192         free(ch);
5193      }
5194    else
5195      _e_client_hooks_delete++;
5196 }
5197
5198 ///////////////////////////////////////
5199
5200 E_API E_Client_Intercept_Hook *
5201 e_client_intercept_hook_add(E_Client_Intercept_Hook_Point hookpoint, E_Client_Intercept_Hook_Cb func, const void *data)
5202 {
5203    E_Client_Intercept_Hook *ch;
5204
5205    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_CLIENT_INTERCEPT_HOOK_LAST, NULL);
5206    ch = E_NEW(E_Client_Intercept_Hook, 1);
5207    if (!ch) return NULL;
5208    ch->hookpoint = hookpoint;
5209    ch->func = func;
5210    ch->data = (void*)data;
5211    _e_client_intercept_hooks[hookpoint] = eina_inlist_append(_e_client_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
5212    return ch;
5213 }
5214
5215 E_API void
5216 e_client_intercept_hook_del(E_Client_Intercept_Hook *ch)
5217 {
5218    if (!ch) return;
5219
5220    ch->delete_me = 1;
5221    if (_e_client_intercept_hooks_walking == 0)
5222      {
5223         _e_client_intercept_hooks[ch->hookpoint] =
5224            eina_inlist_remove(_e_client_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
5225         free(ch);
5226      }
5227    else
5228      _e_client_intercept_hooks_delete++;
5229 }
5230
5231 #ifdef REFACTOR_FOCUS_POLICY
5232 #else
5233 EINTERN void
5234 e_client_focus_stack_lower(E_Client *ec)
5235 {
5236    Eina_List *l = NULL;
5237    E_Client *ec2 = NULL;
5238
5239    EINA_SAFETY_ON_NULL_RETURN(ec);
5240
5241    focus_stack = eina_list_remove(focus_stack, ec);
5242
5243    EINA_LIST_REVERSE_FOREACH(focus_stack, l, ec2)
5244      {
5245         if (ec2 == NULL) continue;
5246         if (ec2->layer < ec->layer) continue;
5247
5248         focus_stack = eina_list_append_relative_list(focus_stack, ec, l);
5249         return;
5250      }
5251
5252    focus_stack = eina_list_prepend(focus_stack, ec);
5253    return;
5254 }
5255 #endif
5256
5257 E_API void
5258 e_client_focus_latest_set(E_Client *ec)
5259 {
5260    EINA_SAFETY_ON_NULL_RETURN(ec);
5261
5262 #ifdef REFACTOR_FOCUS_POLICY
5263    wl_signal_emit_mutable(&PRI(ec)->events.focus_latest_set, NULL);
5264    _e_client_hook_call(E_CLIENT_HOOK_FOCUS_LATEST_SET, ec);
5265 #else
5266    focus_stack = eina_list_remove(focus_stack, ec);
5267    focus_stack = eina_list_prepend(focus_stack, ec);
5268 #endif
5269 }
5270
5271 #ifdef REFACTOR_FOCUS_POLICY
5272 #else
5273 EINTERN void
5274 e_client_focus_stack_append_current_focused(E_Client *ec)
5275 {
5276    Eina_List *l = NULL;
5277    E_Client *temp_ec = NULL;
5278
5279    if (!ec) CRI("ACK");
5280
5281    focus_stack = eina_list_remove(focus_stack, ec);
5282
5283    EINA_LIST_FOREACH(focus_stack, l, temp_ec)
5284      {
5285         if (temp_ec != focused) continue;
5286
5287         focus_stack = eina_list_append_relative_list(focus_stack, ec, l);
5288         return;
5289      }
5290
5291    focus_stack = eina_list_prepend(focus_stack, ec);
5292    return;
5293 }
5294 #endif
5295
5296 E_API void
5297 e_client_focus_defer_set(E_Client *ec)
5298 {
5299    EINA_SAFETY_ON_NULL_RETURN(ec);
5300 #ifdef REFACTOR_FOCUS_POLICY
5301    wl_signal_emit_mutable(&PRI(ec)->events.focus_defer_set, NULL);
5302    _e_client_hook_call(E_CLIENT_HOOK_FOCUS_DEFER_SET, ec);
5303 #else
5304    if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK) return;
5305
5306    ELOGF("FOCUS", "focus defer set", ec);
5307
5308    defer_focus_stack = eina_list_remove(defer_focus_stack, ec);
5309    defer_focus_stack = eina_list_prepend(defer_focus_stack, ec);
5310 #endif
5311 }
5312
5313 #ifdef REFACTOR_FOCUS_POLICY
5314 #else
5315 EINTERN void
5316 e_client_focus_defer_unset(E_Client *ec)
5317 {
5318    EINA_SAFETY_ON_NULL_RETURN(ec);
5319    if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK) return;
5320
5321    ELOGF("FOCUS", "focus defer unset", ec);
5322
5323    defer_focus_stack = eina_list_remove(defer_focus_stack, ec);
5324 }
5325
5326 EINTERN void
5327 e_client_focus_defer_clear(void)
5328 {
5329    if (!defer_focus_stack) return;
5330
5331    ELOGF("FOCUS", "focus defer clear", NULL);
5332
5333    defer_focus_stack = eina_list_free(defer_focus_stack);
5334 }
5335
5336 EINTERN void
5337 e_client_refocus(void)
5338 {
5339    E_Client *ec;
5340    const Eina_List *l;
5341    E_Desk *desk;
5342
5343    if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK) return;
5344
5345    EINA_LIST_FOREACH(e_client_focus_stack_get(), l, ec)
5346      {
5347         desk = e_comp_desk_find_by_ec(ec);
5348         if (!desk) continue;
5349         if (desk->visible && (!ec->iconic))
5350           {
5351              g_mutex_lock(&e_comp->input_key_grabs_mutex);
5352              if (e_comp->input_key_grabs || e_comp->input_mouse_grabs)
5353                {
5354                   g_mutex_unlock(&e_comp->input_key_grabs_mutex);
5355                   break;
5356                }
5357              g_mutex_unlock(&e_comp->input_key_grabs_mutex);
5358              ELOGF("FOCUS", "focus set   | refocus", ec);
5359              e_client_frame_focus_set(ec, EINA_TRUE);
5360              break;
5361           }
5362      }
5363 }
5364
5365
5366 /*
5367  * Sets the focus to the given client if necessary
5368  * There are 3 cases of different focus_policy-configurations:
5369  *
5370  * - E_FOCUS_CLICK: just set the focus, the most simple one
5371  *
5372  * - E_FOCUS_MOUSE: focus is where the mouse is, so try to
5373  *   warp the pointer to the window. If this fails (because
5374  *   the pointer is already in the window), just set the focus.
5375  *
5376  * - E_FOCUS_SLOPPY: focus is where the mouse is or on the
5377  *   last window which was focused, if the mouse is on the
5378  *   desktop. So, we need to look if there is another window
5379  *   under the pointer and warp to pointer to the right
5380  *   one if so (also, we set the focus afterwards). In case
5381  *   there is no window under pointer, the pointer is on the
5382  *   desktop and so we just set the focus.
5383  *
5384  *
5385  * This function is to be called when setting the focus was not
5386  * explicitly triggered by the user (by moving the mouse or
5387  * clicking for example), but implicitly (by closing a window,
5388  * the last focused window should get focus).
5389  *
5390  */
5391 EINTERN void
5392 e_client_focus_set_with_pointer(E_Client *ec)
5393 {
5394    E_OBJECT_CHECK(ec);
5395    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5396    /* note: this is here as it seems there are enough apps that do not even
5397     * expect us to emulate a look of focus but not actually set x input
5398     * focus as we do - so simply abort any focuse set on such windows */
5399    /* be strict about accepting focus hint */
5400    if (e_config->focus_policy_ext == E_FOCUS_EXT_TOP_STACK) return;
5401
5402    if ((!ec->icccm.accepts_focus) &&
5403        (!ec->icccm.take_focus)) return;
5404    if (ec->lock_focus_out) return;
5405    if (ec == focused) return;
5406
5407    TRACE_DS_BEGIN(CLIENT:FOCUS SET WITH POINTER);
5408    ELOGF("FOCUS", "focus set   | focus with pointer", ec);
5409    e_client_frame_focus_set(ec, EINA_TRUE);
5410
5411    if (e_config->focus_policy == E_FOCUS_CLICK)
5412      {
5413         TRACE_DS_END();
5414         return;
5415      }
5416    if (!ec->visible)
5417      {
5418         TRACE_DS_END();
5419         return;
5420      }
5421
5422    TRACE_DS_END();
5423 }
5424 #endif
5425
5426 EINTERN void
5427 e_client_focused_set(E_Client *ec)
5428 {
5429 #ifdef REFACTOR_FOCUS_POLICY
5430    E_Client *focused_ec;
5431    E_Zone *zone;
5432
5433    if (ec)
5434      ELOGF("FOCUS", "CLIENT FOCUSED_SET : SET", ec);
5435    else
5436      ELOGF("FOCUS", "CLIENT FOCUSED_SET : UNSET", NULL);
5437
5438   focused_ec = e_comp_focused_ec_get();
5439   if (ec == focused_ec) return;
5440
5441    TRACE_DS_BEGIN(CLIENT:FOCUSED SET);
5442
5443    // unset the current focused_ec if focused_ec is not being deleted
5444    if (focused_ec)
5445      {
5446        if (!e_object_is_del(E_OBJECT(focused_ec)))
5447          {
5448             // FIXME: Remove focus_unset event of client.
5449             //        Instead, make zone focus_unset event and use it.
5450             wl_signal_emit_mutable(&PRI(focused_ec)->events.focus_unset, NULL);
5451             _e_client_hook_call(E_CLIENT_HOOK_FOCUS_UNSET, focused_ec);
5452
5453             if (e_object_ref_get(E_OBJECT(focused_ec)) > 0)
5454               {
5455                  _e_client_event_simple(focused_ec, E_EVENT_CLIENT_FOCUS_OUT);
5456                  e_client_urgent_set(focused_ec, focused_ec->icccm.urgent);
5457               }
5458          }
5459      }
5460
5461    // clear the current focused_ec when ec is NULL
5462    if (!ec)
5463      {
5464         zone = e_comp_zone_find_by_ec(focused_ec);
5465         e_zone_focus_clear(zone);
5466         TRACE_DS_END();
5467         return;
5468      }
5469
5470    // FIXME: Remove focus_set event of client.
5471    //        Instead, make zone focus_set event and use it.
5472    // set the new current focused_ec
5473    wl_signal_emit_mutable(&PRI(ec)->events.focus_set, NULL);
5474    _e_client_hook_call(E_CLIENT_HOOK_FOCUS_SET, ec);
5475
5476    // send the client_focuse_in event
5477    _e_client_event_simple(ec, E_EVENT_CLIENT_FOCUS_IN);
5478
5479 #ifdef REFACTOR_ZONE_DESK
5480 #else
5481    // TODO: This is not for focus, but for Window Placement policy.
5482    //       Move this code to the better place.
5483    if (ec->sticky && ec->desk && (!ec->desk->visible))
5484      e_client_desk_set(ec, e_desk_current_get(zone));
5485 #endif
5486
5487    TRACE_DS_END();
5488 #else
5489    E_Client *ec2, *ec_unfocus = focused;
5490    Eina_List *l, *ll;
5491    E_Zone *zone;
5492
5493    if (ec == focused) return;
5494
5495    TRACE_DS_BEGIN(CLIENT:FOCUSED SET);
5496
5497    ELOGF("FOCUS", "CLIENT FOCUS_SET", ec);
5498
5499    g_mutex_lock(&focused_ec_mutex);
5500    focused = ec;
5501    g_mutex_unlock(&focused_ec_mutex);
5502
5503    zone = e_comp_zone_find_by_ec(ec);
5504    if (zone)
5505      {
5506         ec->focused = 1;
5507         e_client_urgent_set(ec, 0);
5508         int x, total = zone->desk_x_count * zone->desk_y_count;
5509
5510         for (x = 0; x < total; x++)
5511           {
5512              E_Desk *desk = zone->desks[x];
5513              /* if there's any fullscreen non-parents on this desk, unfullscreen them */
5514              EINA_LIST_FOREACH_SAFE(desk->fullscreen_clients, l, ll, ec2)
5515                {
5516                   if (ec2 == ec) continue;
5517                   if (e_object_is_del(E_OBJECT(ec2))) continue;
5518                   /* but only if it's the same desk or one of the clients is sticky */
5519                   if ((e_desk_has_ec(desk, ec)) || (ec->sticky || ec2->sticky))
5520                     {
5521                        if (!eina_list_data_find(ec->transients, ec2))
5522                          e_client_unfullscreen(ec2);
5523                     }
5524                }
5525           }
5526      }
5527
5528    while ((ec_unfocus) && (ec_unfocus->zone))
5529      {
5530         ec_unfocus->want_focus = ec_unfocus->focused = 0;
5531         if (ec_unfocus->mouse.in && ec && (!e_client_util_is_popup(ec)) &&
5532             (e_config->focus_policy != E_FOCUS_CLICK))
5533           e_client_mouse_out(ec_unfocus, ec_unfocus->x - 1, ec_unfocus->y - 1);
5534
5535         /* if there unfocus client is fullscreen and visible */
5536         if ((ec_unfocus->fullscreen) && (!ec_unfocus->iconic) && (!ec_unfocus->hidden) &&
5537             (ec_unfocus->zone == e_zone_current_get()) &&
5538             ((ec_unfocus->desk == e_desk_current_get(ec_unfocus->zone)) || (ec_unfocus->sticky)))
5539           {
5540              Eina_Bool have_vis_child = EINA_FALSE;
5541
5542              /* if any of its children are visible */
5543              EINA_LIST_FOREACH(ec_unfocus->transients, l, ec2)
5544                {
5545                   if ((ec2->zone == ec_unfocus->zone) &&
5546                       ((ec2->desk == ec_unfocus->desk) ||
5547                        (ec2->sticky) || (ec_unfocus->sticky)))
5548                     {
5549                        have_vis_child = EINA_TRUE;
5550                        break;
5551                     }
5552                }
5553              /* if no children are visible, unfullscreen */
5554              if ((!e_object_is_del(E_OBJECT(ec_unfocus))) && (!have_vis_child))
5555                e_client_unfullscreen(ec_unfocus);
5556           }
5557
5558         if (!e_object_is_del(E_OBJECT(ec_unfocus)))
5559           {
5560              wl_signal_emit_mutable(&PRI(ec)->events.focus_unset, focused_ec);
5561              _e_client_hook_call(E_CLIENT_HOOK_FOCUS_UNSET, ec_unfocus);
5562           }
5563         /* only send event here if we're not being deleted */
5564         if ((!e_object_is_del(E_OBJECT(ec_unfocus))) &&
5565            (e_object_ref_get(E_OBJECT(ec_unfocus)) > 0))
5566           {
5567              _e_client_event_simple(ec_unfocus, E_EVENT_CLIENT_FOCUS_OUT);
5568              e_client_urgent_set(ec_unfocus, ec_unfocus->icccm.urgent);
5569           }
5570
5571         e_client_focus_defer_unset(ec_unfocus);
5572         break;
5573      }
5574    if (!ec)
5575      {
5576         TRACE_DS_END();
5577         return;
5578      }
5579
5580    wl_signal_emit_mutable(&PRI(ec)->events.focus_set, ec);
5581    _e_client_hook_call(E_CLIENT_HOOK_FOCUS_SET, ec);
5582
5583    e_client_focus_latest_set(ec);
5584
5585    _e_client_event_simple(ec, E_EVENT_CLIENT_FOCUS_IN);
5586
5587 #ifdef REFACTOR_ZONE_DESK
5588 #else
5589    if (ec->sticky && ec->desk && (!ec->desk->visible))
5590      e_client_desk_set(ec, e_desk_current_get(zone));
5591 #endif
5592
5593    TRACE_DS_END();
5594 #endif
5595 }
5596
5597 EINTERN void
5598 e_client_activate(E_Client *ec)
5599 {
5600    E_OBJECT_CHECK(ec);
5601    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5602
5603    TRACE_DS_BEGIN(CLIENT:ACTIVATE);
5604
5605    ELOGF("COMP", "Set launching flag..", ec);
5606    ec->launching = EINA_TRUE;
5607
5608    ec->exp_iconify.not_raise = 0;
5609
5610    if (ec->iconic)
5611      {
5612          if (!ec->lock_user_iconify)
5613            e_client_uniconify(ec);
5614      }
5615    ELOGF("COMP", "Un-Set ICONIFY BY CLIENT", ec);
5616    ec->exp_iconify.by_client = 0;
5617    e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_NONE);
5618
5619 #ifdef REFACTOR_ZONE_DESK
5620 #else
5621    if ((!ec->iconic) && (!ec->sticky))
5622      {
5623         e_desk_show(ec->desk);
5624      }
5625    if (!ec->lock_user_stacking)
5626      e_client_raise(ec);
5627    if (ec->shaded || ec->shading)
5628      e_client_unshade(ec, ec->shade_dir);
5629 #endif
5630
5631 #ifdef REFACTOR_FOCUS_POLICY
5632     // This code will be executed at E_CLIENT_HOOK_ACTIVATE_DONE callback at e_focus_policy_history.c
5633 #else
5634    if (!ec->lock_focus_out)
5635      {
5636         E_Client *focus_ec = NULL;
5637         E_Client *obscured_above = NULL;
5638
5639         if (ec->transients)
5640           focus_ec = e_client_transient_child_top_get(ec, EINA_TRUE);
5641
5642         if (!focus_ec)
5643           focus_ec = ec;
5644         else
5645           {
5646             e_client_focus_latest_set(ec);
5647             e_client_focus_latest_set(focus_ec);
5648             e_client_focus_defer_unset(ec);
5649           }
5650
5651         obscured_above = e_client_check_fully_contain_by_above(focus_ec, EINA_FALSE);
5652         if (!obscured_above)
5653           {
5654             if (!e_policy_visibility_client_is_uniconic(ec))
5655               {
5656                   e_client_focus_defer_set(focus_ec);
5657                   e_client_focus_latest_set(focus_ec);
5658               }
5659             else
5660               {
5661                   if (e_config->focus_policy_ext != E_FOCUS_EXT_TOP_STACK)
5662                     {
5663                       ELOGF("FOCUS", "focus set   | client activate", focus_ec);
5664                       e_client_frame_focus_set(focus_ec, EINA_TRUE);
5665                     }
5666               }
5667           }
5668         else
5669           {
5670             e_client_focus_defer_set(focus_ec);
5671             e_client_focus_latest_set(focus_ec);
5672           }
5673      }
5674 #endif
5675
5676 #ifdef REFACTOR_ZONE_DESK
5677 #else
5678   if (!e_client_desk_iconify_skip_get(ec))
5679     {
5680         e_desk_visible_client_iconified_list_remove_all(ec->desk);
5681     }
5682 #endif
5683
5684    wl_signal_emit_mutable(&PRI(ec)->events.activate_done, NULL);
5685    _e_client_hook_call(E_CLIENT_HOOK_ACTIVATE_DONE, ec);
5686
5687    TRACE_DS_END();
5688 }
5689
5690 E_API E_Client *
5691 e_client_focused_get(void)
5692 {
5693 #ifdef REFACTOR_FOCUS_POLICY
5694    return e_comp_focused_ec_get();
5695 #else
5696    E_Client *focused_ec = NULL;
5697
5698    g_mutex_lock(&focused_ec_mutex);
5699    focused_ec = focused;
5700    g_mutex_unlock(&focused_ec_mutex);
5701
5702    return focused_ec;
5703 #endif
5704 }
5705
5706 #ifdef REFACTOR_FOCUS_POLICY
5707 #else
5708 EINTERN Eina_List *
5709 e_client_focus_stack_get(void)
5710 {
5711    return focus_stack;
5712 }
5713
5714 EINTERN Eina_List *
5715 e_client_defer_focus_stack_get(void)
5716 {
5717    return defer_focus_stack;
5718 }
5719
5720 YOLO EINTERN void
5721 e_client_focus_stack_set(Eina_List *l)
5722 {
5723    focus_stack = l;
5724 }
5725
5726 EINTERN void
5727 e_client_focus_stack_clear(void)
5728 {
5729    if (!focus_stack) return;
5730
5731    focus_stack = eina_list_free(focus_stack);
5732 }
5733 #endif
5734
5735 EINTERN Eina_List *
5736 e_client_lost_windows_get(E_Zone *zone)
5737 {
5738    Eina_List *list = NULL;
5739    const Eina_List *l;
5740    E_Client *ec;
5741    int loss_overlap = 5;
5742
5743    E_OBJECT_CHECK_RETURN(zone, NULL);
5744    E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, NULL);
5745    EINA_LIST_FOREACH(e_comp->clients, l, ec)
5746      {
5747         if (!e_zone_has_ec(zone, ec)) continue;
5748         if (e_client_util_ignored_get(ec)) continue;
5749
5750         if (!E_INTERSECTS(zone->x + loss_overlap,
5751                           zone->y + loss_overlap,
5752                           zone->w - (2 * loss_overlap),
5753                           zone->h - (2 * loss_overlap),
5754                           ec->x, ec->y, ec->w, ec->h))
5755           {
5756              list = eina_list_append(list, ec);
5757           }
5758      }
5759    return list;
5760 }
5761
5762 ///////////////////////////////////////
5763
5764 EINTERN void
5765 e_client_shade(E_Client *ec, E_Direction dir)
5766 {
5767    E_OBJECT_CHECK(ec);
5768    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5769    if ((ec->shaded) || (ec->shading) || (ec->fullscreen) ||
5770        ((ec->maximized) && (!e_config->allow_manip))) return;
5771    if (!e_util_strcmp("borderless", ec->bordername)) return;
5772    if (!e_comp_object_frame_allowed(ec->frame)) return;
5773
5774    ec->take_focus = 0;
5775    ec->shading = 1;
5776    ec->shade_dir = dir;
5777
5778    evas_object_smart_callback_call(ec->frame, "shaded", (uintptr_t*)dir);
5779 }
5780
5781 EINTERN void
5782 e_client_unshade(E_Client *ec, E_Direction dir)
5783 {
5784    E_OBJECT_CHECK(ec);
5785    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5786    if ((!ec->shaded) || (ec->shading))
5787      return;
5788
5789    ec->shading = 1;
5790    ec->shade_dir = 0;
5791
5792    evas_object_smart_callback_call(ec->frame, "unshaded", (uintptr_t*)dir);
5793 }
5794
5795 ///////////////////////////////////////
5796
5797 EINTERN void
5798 e_client_maximized_geometry_set(E_Client *ec, int x, int y, int w, int h)
5799 {
5800    if (!ec) return;
5801
5802    ec->maximized_info.x = x;
5803    ec->maximized_info.y = y;
5804    ec->maximized_info.w = w;
5805    ec->maximized_info.h = h;
5806
5807    e_client_frame_geometry_set(ec, x, y, w, h);
5808 }
5809
5810 EINTERN void
5811 e_client_maximized_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
5812 {
5813    if (!ec) return;
5814
5815    if (x) *x = ec->maximized_info.x;
5816    if (y) *y = ec->maximized_info.y;
5817    if (w) *w = ec->maximized_info.w;
5818    if (h) *h = ec->maximized_info.h;
5819 }
5820
5821 EINTERN void
5822 e_client_maximize_update(E_Client *ec)
5823 {
5824    E_Maximize max;
5825
5826    E_OBJECT_CHECK(ec);
5827    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5828
5829    if (ec->maximized)
5830      {
5831         max = ec->maximized;
5832         ec->maximized = 0;
5833         e_client_maximize(ec, max);
5834      }
5835 }
5836
5837 E_API void
5838 e_client_maximize(E_Client *ec, E_Maximize max)
5839 {
5840 #ifdef REFACTOR_ZONE_DESK
5841    E_OBJECT_CHECK(ec);
5842    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5843
5844    if (!(max & E_MAXIMIZE_DIRECTION)) max |= E_MAXIMIZE_BOTH;
5845
5846    if ((ec->shaded) || (ec->shading)) return;
5847
5848    if ((ec->maximized & E_MAXIMIZE_DIRECTION) == (max & E_MAXIMIZE_DIRECTION))
5849      {
5850         if ((ec->maximized & E_MAXIMIZE_TYPE) == (max & E_MAXIMIZE_TYPE))
5851           return;
5852      }
5853
5854    if (ec->new_client)
5855      {
5856         ec->changes.need_maximize = 1;
5857         ec->maximized &= ~E_MAXIMIZE_TYPE;
5858         ec->maximized |= max;
5859         EC_CHANGED(ec);
5860         return;
5861      }
5862
5863    // store the E_Maximize value requested
5864    ec->requested_max = max;
5865
5866    // call the maximize hook of a client
5867    wl_signal_emit_mutable(&PRI(ec)->events.maximize, &max);
5868    _e_client_hook_call(E_CLIENT_HOOK_MAXIMIZE, ec);
5869
5870    // clear the E_Maximize value requested
5871    ec->requested_max = E_MAXIMIZE_NONE;
5872
5873    // store the E_Maximize value
5874    ec->maximized = max;
5875    ec->changes.need_unmaximize = 0;
5876
5877    evas_object_smart_callback_call(ec->frame, "maximize_done", NULL);
5878 #else
5879   int desk_x, desk_y;
5880   E_Zone *zone;
5881
5882    E_OBJECT_CHECK(ec);
5883    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5884
5885    zone = e_comp_zone_find_by_ec(ec);
5886    if (!zone) return;
5887    if (!(max & E_MAXIMIZE_DIRECTION)) max |= E_MAXIMIZE_BOTH;
5888
5889    if ((ec->shaded) || (ec->shading)) return;
5890
5891    if ((ec->maximized & E_MAXIMIZE_DIRECTION) == (max & E_MAXIMIZE_DIRECTION))
5892      {
5893         if ((ec->maximized & E_MAXIMIZE_TYPE) == (max & E_MAXIMIZE_TYPE))
5894           return;
5895      }
5896
5897    if (ec->new_client)
5898      {
5899         ec->changes.need_maximize = 1;
5900         ec->maximized &= ~E_MAXIMIZE_TYPE;
5901         ec->maximized |= max;
5902         EC_CHANGED(ec);
5903         return;
5904      }
5905
5906    if (ec->desk_area.enable && ec->desk_area.desk_area)
5907      {
5908         desk_x = ec->desk_area.desk_area->x;
5909         desk_y = ec->desk_area.desk_area->y;
5910      }
5911     else
5912     {
5913         desk_x = ec->desk->geom.x;
5914         desk_y = ec->desk->geom.y;
5915     }
5916
5917    evas_object_smart_callback_call(ec->frame, "maximize_pre", NULL);
5918
5919    if (ec->fullscreen)
5920      e_client_unfullscreen(ec);
5921    ec->pre_res_change.valid = 0;
5922    if (!(ec->maximized & E_MAXIMIZE_HORIZONTAL))
5923      {
5924         /* Horizontal hasn't been set */
5925         ec->saved.x = ec->client.x - desk_x;
5926         ec->saved.w = ec->client.w;
5927      }
5928    if (!(ec->maximized & E_MAXIMIZE_VERTICAL))
5929      {
5930         /* Vertical hasn't been set */
5931         ec->saved.y = ec->client.y - desk_y;
5932         ec->saved.h = ec->client.h;
5933      }
5934
5935    ec->saved.zone = zone->num;
5936
5937    _e_client_maximize(ec, max);
5938
5939    ec->maximized = max;
5940    ec->changes.need_unmaximize = 0;
5941
5942    evas_object_smart_callback_call(ec->frame, "maximize_done", NULL);
5943 #endif
5944 }
5945
5946 E_API void
5947 e_client_unmaximize(E_Client *ec, E_Maximize max)
5948 {
5949 #ifdef REFACTOR_ZONE_DESK
5950    E_OBJECT_CHECK(ec);
5951    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5952
5953    if (!(max & E_MAXIMIZE_DIRECTION))
5954      {
5955         CRI("BUG: Unmaximize call without direction!");
5956         return;
5957      }
5958    if (ec->new_client)
5959      {
5960         ec->changes.need_unmaximize = 1;
5961         EC_CHANGED(ec);
5962         return;
5963      }
5964
5965    if ((ec->shaded) || (ec->shading)) return;
5966
5967    /* Remove directions not used */
5968    max &= (ec->maximized & E_MAXIMIZE_DIRECTION);
5969    /* Can only remove existing maximization directions */
5970    if (!max) return;
5971
5972    evas_object_smart_callback_call(ec->frame, "unmaximize_pre", NULL);
5973
5974    // store the E_Maximize value requested
5975    ec->requested_max = max;
5976
5977    // call the unmaximize hook of a client
5978    wl_signal_emit_mutable(&PRI(ec)->events.unmaximize, &max);
5979    _e_client_hook_call(E_CLIENT_HOOK_UNMAXIMIZE, ec);
5980
5981    // clear the E_Maximize value requested
5982    ec->requested_max = E_MAXIMIZE_NONE;
5983
5984    evas_object_smart_callback_call(ec->frame, "unmaximize_done", NULL);
5985    ec->changes.need_unmaximize = 0;
5986 #else
5987    E_Zone *zone;
5988
5989    E_OBJECT_CHECK(ec);
5990    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
5991
5992    zone = e_comp_zone_find_by_ec(ec);
5993    if (!zone) return;
5994    if (!(max & E_MAXIMIZE_DIRECTION))
5995      {
5996         CRI("BUG: Unmaximize call without direction!");
5997         return;
5998      }
5999    if (ec->new_client)
6000      {
6001         ec->changes.need_unmaximize = 1;
6002         EC_CHANGED(ec);
6003         return;
6004      }
6005
6006    if ((ec->shaded) || (ec->shading)) return;
6007
6008    /* Remove directions not used */
6009    max &= (ec->maximized & E_MAXIMIZE_DIRECTION);
6010    /* Can only remove existing maximization directions */
6011    if (!max) return;
6012
6013    evas_object_smart_callback_call(ec->frame, "unmaximize_pre", NULL);
6014
6015    if (ec->maximized & E_MAXIMIZE_TYPE)
6016      {
6017         ec->pre_res_change.valid = 0;
6018         ec->changes.need_maximize = 0;
6019
6020         if ((ec->maximized & E_MAXIMIZE_TYPE) == E_MAXIMIZE_FULLSCREEN)
6021           {
6022              E_Maximize tmp_max = ec->maximized;
6023
6024              //un-set maximized state for updating frame.
6025              ec->maximized = E_MAXIMIZE_NONE;
6026              _e_client_frame_update(ec);
6027              // re-set maximized state for unmaximize smart callback.
6028              ec->maximized = tmp_max;
6029              evas_object_smart_callback_call(ec->frame, "unfullscreen", NULL);
6030              // un-set maximized state.
6031              ec->maximized = E_MAXIMIZE_NONE;
6032              e_client_util_move_resize_without_frame(ec,
6033                                                      ec->saved.x + zone->x,
6034                                                      ec->saved.y + zone->y,
6035                                                      ec->saved.w, ec->saved.h);
6036              ec->saved.x = ec->saved.y = ec->saved.w = ec->saved.h = 0;
6037           }
6038         else
6039           {
6040              int w, h, x, y;
6041              Eina_Bool horiz = EINA_FALSE, vert = EINA_FALSE;
6042
6043              w = ec->client.w;
6044              h = ec->client.h;
6045              x = ec->client.x;
6046              y = ec->client.y;
6047
6048              if (max & E_MAXIMIZE_VERTICAL)
6049                {
6050                   /* Remove vertical */
6051                   h = ec->saved.h;
6052                   vert = EINA_TRUE;
6053                   y = ec->saved.y + zone->y;
6054                   if ((max & E_MAXIMIZE_VERTICAL) == E_MAXIMIZE_VERTICAL)
6055                     {
6056                        ec->maximized &= ~E_MAXIMIZE_VERTICAL;
6057                        ec->maximized &= ~E_MAXIMIZE_LEFT;
6058                        ec->maximized &= ~E_MAXIMIZE_RIGHT;
6059                     }
6060                   if ((max & E_MAXIMIZE_LEFT) == E_MAXIMIZE_LEFT)
6061                     ec->maximized &= ~E_MAXIMIZE_LEFT;
6062                   if ((max & E_MAXIMIZE_RIGHT) == E_MAXIMIZE_RIGHT)
6063                     ec->maximized &= ~E_MAXIMIZE_RIGHT;
6064                }
6065              if (max & E_MAXIMIZE_HORIZONTAL)
6066                {
6067                   /* Remove horizontal */
6068                   w = ec->saved.w;
6069                   x = ec->saved.x + zone->x;
6070                   horiz = EINA_TRUE;
6071                   ec->maximized &= ~E_MAXIMIZE_HORIZONTAL;
6072                }
6073
6074              if (!(ec->maximized & E_MAXIMIZE_DIRECTION))
6075                {
6076                   ec->maximized = E_MAXIMIZE_NONE;
6077                   _e_client_frame_update(ec);
6078                   evas_object_smart_callback_call(ec->frame, "unmaximize", NULL);
6079                   e_client_resize_limit(ec, &w, &h);
6080                   e_client_pos_set(ec, x, y);
6081                   if ((ec->saved.w != 0) && (ec->saved.h != 0))
6082                     {
6083                        if ((w != ec->saved.w) || (h != ec->saved.h))
6084                          {
6085                             e_policy_visibility_client_defer_move(ec);
6086                          }
6087                     }
6088                }
6089              else
6090                {
6091                   evas_object_smart_callback_call(ec->frame, "unmaximize", NULL);
6092                   e_client_resize_limit(ec, &w, &h);
6093                   e_client_pos_set(ec, x, y);
6094                   if ((ec->saved.w != 0) && (ec->saved.h != 0))
6095                     {
6096                        if ((w != ec->saved.w) || (h != ec->saved.h))
6097                          {
6098                             e_policy_visibility_client_defer_move(ec);
6099                          }
6100                     }
6101                }
6102              if (vert)
6103                ec->saved.h = ec->saved.y = 0;
6104              if (horiz)
6105                ec->saved.w = ec->saved.x = 0;
6106           }
6107      }
6108    evas_object_smart_callback_call(ec->frame, "unmaximize_done", NULL);
6109    ec->changes.need_unmaximize = 0;
6110 #endif
6111 }
6112
6113 EINTERN void
6114 e_client_fullscreen(E_Client *ec, E_Fullscreen policy)
6115 {
6116 #ifdef REFACTOR_ZONE_DESK
6117    E_OBJECT_CHECK(ec);
6118    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6119
6120    if ((ec->shaded) || (ec->shading) || (ec->fullscreen)) return;
6121
6122    // call the fullscreen_pre hook of a client
6123    wl_signal_emit_mutable(&PRI(ec)->events.fullscreen_pre, NULL);
6124    _e_client_hook_call(E_CLIENT_HOOK_FULLSCREEN_PRE, ec);
6125
6126    ec->fullscreen_policy = policy;
6127
6128    // call the fullscreen hook of a client
6129    wl_signal_emit_mutable(&PRI(ec)->events.fullscreen, &policy);
6130    _e_client_hook_call(E_CLIENT_HOOK_FULLSCREEN, ec);
6131
6132    _e_client_event_simple(ec, E_EVENT_CLIENT_FULLSCREEN);
6133 #else
6134    int x, y, w, h;
6135    E_Zone *zone;
6136
6137    E_OBJECT_CHECK(ec);
6138    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6139
6140    zone = e_comp_zone_find_by_ec(ec);
6141    if (!zone) return;
6142
6143    if ((ec->shaded) || (ec->shading) || (ec->fullscreen)) return;
6144
6145    wl_signal_emit_mutable(&PRI(ec)->events.fullscreen_pre, NULL);
6146    _e_client_hook_call(E_CLIENT_HOOK_FULLSCREEN_PRE, ec);
6147
6148    if (ec->skip_fullscreen) return;
6149    if (!ec->desk->visible) return;
6150    if (ec->new_client)
6151      {
6152         ec->need_fullscreen = 1;
6153         return;
6154      }
6155    if (e_comp->nocomp_ec && (ec->desk == e_comp->nocomp_ec->desk))
6156      e_comp->nocomp_ec = ec;
6157    ec->desk->fullscreen_clients = eina_list_append(ec->desk->fullscreen_clients, ec);
6158    ec->pre_res_change.valid = 0;
6159
6160    if (ec->maximized)
6161      {
6162         x = ec->saved.x;
6163         y = ec->saved.y;
6164         w = ec->saved.w;
6165         h = ec->saved.h;
6166      }
6167    else
6168      {
6169         ec->saved.x = ec->client.x - zone->x;
6170         ec->saved.y = ec->client.y - zone->y;
6171         ec->saved.w = ec->client.w;
6172         ec->saved.h = ec->client.h;
6173      }
6174    ec->saved.maximized = ec->maximized;
6175    ec->saved.zone = zone->num;
6176
6177    if (ec->maximized)
6178      {
6179         e_client_unmaximize(ec, E_MAXIMIZE_BOTH);
6180         ec->saved.x = x;
6181         ec->saved.y = y;
6182         ec->saved.w = w;
6183         ec->saved.h = h;
6184      }
6185
6186    ec->saved.layer = ec->layer;
6187    e_client_layer_set(ec, E_LAYER_CLIENT_FULLSCREEN);
6188
6189    ec->fullscreen = 1;
6190    if ((eina_list_count(e_comp->zones) > 1) ||
6191        (policy == E_FULLSCREEN_RESIZE))
6192      {
6193         e_client_frame_geometry_set(ec, zone->x, zone->y, zone->w, zone->h);
6194      }
6195    else if (policy == E_FULLSCREEN_ZOOM)
6196      {
6197         /* compositor backends! */
6198         evas_object_smart_callback_call(ec->frame, "fullscreen_zoom", NULL);
6199      }
6200
6201    if (!e_client_util_ignored_get(ec))
6202      _e_client_frame_update(ec);
6203    ec->fullscreen_policy = policy;
6204    evas_object_smart_callback_call(ec->frame, "fullscreen", NULL);
6205
6206    wl_signal_emit_mutable(&PRI(ec)->events.fullscreen, &policy);
6207    _e_client_event_simple(ec, E_EVENT_CLIENT_FULLSCREEN);
6208 #endif
6209 }
6210
6211 EINTERN void
6212 e_client_unfullscreen(E_Client *ec)
6213 {
6214 #ifdef REFACTOR_ZONE_DESK
6215    E_OBJECT_CHECK(ec);
6216    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6217
6218    if ((ec->shaded) || (ec->shading)) return;
6219    if (!ec->fullscreen) return;
6220
6221    // call the unfullscreen hook of a client
6222    wl_signal_emit_mutable(&PRI(ec)->events.unfullscreen, NULL);
6223    _e_client_hook_call(E_CLIENT_HOOK_UNFULLSCREEN, ec);
6224
6225    _e_client_event_simple(ec, E_EVENT_CLIENT_UNFULLSCREEN);
6226 #else
6227    E_Zone *zone;
6228
6229    E_OBJECT_CHECK(ec);
6230    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6231
6232    zone = e_comp_zone_find_by_ec(ec);
6233    if (!zone) return;
6234    if ((ec->shaded) || (ec->shading)) return;
6235    if (!ec->fullscreen) return;
6236    ec->pre_res_change.valid = 0;
6237    ec->fullscreen = 0;
6238    ec->need_fullscreen = 0;
6239    ec->desk->fullscreen_clients = eina_list_remove(ec->desk->fullscreen_clients, ec);
6240
6241    if (ec->fullscreen_policy == E_FULLSCREEN_ZOOM)
6242      evas_object_smart_callback_call(ec->frame, "unfullscreen_zoom", NULL);
6243
6244    if (!e_client_util_ignored_get(ec))
6245      _e_client_frame_update(ec);
6246    ec->fullscreen_policy = 0;
6247    evas_object_smart_callback_call(ec->frame, "unfullscreen", NULL);
6248    e_client_util_move_resize_without_frame(ec, zone->x + ec->saved.x,
6249                                            zone->y + ec->saved.y,
6250                                            ec->saved.w, ec->saved.h);
6251
6252    if (ec->saved.maximized)
6253      e_client_maximize(ec, (e_config->maximize_policy & E_MAXIMIZE_TYPE) |
6254                        ec->saved.maximized);
6255
6256    e_client_layer_set(ec, ec->saved.layer);
6257
6258    _e_client_event_simple(ec, E_EVENT_CLIENT_UNFULLSCREEN);
6259
6260    if (!ec->desk->fullscreen_clients)
6261      e_comp_render_queue();
6262 #endif
6263 }
6264
6265 ///////////////////////////////////////
6266 #ifdef REFACTOR_ZONE_DESK
6267 EINTERN Eina_Bool
6268 e_client_is_parent_iconify_by_client(E_Client *ec)
6269 #else
6270 static Eina_Bool
6271 _e_client_is_parent_iconify_by_client(E_Client *ec)
6272 #endif
6273 {
6274    E_Client *parent = ec->parent;
6275    if (!parent) return EINA_FALSE;
6276
6277    if ((parent->exp_iconify.type == E_ICONIFIED_TYPE_ICONIFY_BY_CLIENT) ||
6278        (parent->exp_iconify.type == E_ICONIFIED_TYPE_PARENT_ICONIFY_BY_CLIENT))
6279      return EINA_TRUE;
6280
6281    return EINA_FALSE;
6282 }
6283
6284 E_API void
6285 e_client_iconify(E_Client *ec)
6286 {
6287    E_OBJECT_CHECK(ec);
6288    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6289
6290    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
6291    Eina_Bool iconified_by_client = e_client_is_iconified_by_client(ec);
6292
6293    ELOGF("TZVIS", "ICONIFY  |iconic:%d  |argb:%d       |not_raise:%d   |by_client:%d, type:%d",
6294          ec, ec->iconic, ec->argb, (unsigned int)ec->exp_iconify.not_raise,
6295          ec->exp_iconify.by_client, ec->exp_iconify.type);
6296
6297    if (ec->shading || ec->iconic) return;
6298    if (ec->exp_iconify.skip_iconify && !iconified_by_client) return;
6299    if (ec->exp_iconify.skip_by_remote) return;
6300    if (!cdata || !cdata->mapped)
6301      {
6302         if (!iconified_by_client)
6303           {
6304              ELOGF("TZVIS", "Not mapped.. So, don't iconify", ec);
6305              return;
6306           }
6307         else
6308           {
6309              ELOGF("TZVIS", "Not mapped.. But, iconify by user request", ec);
6310           }
6311      }
6312
6313    TRACE_DS_BEGIN(CLIENT:ICONIFY);
6314
6315 #ifdef REFACTOR_ZONE_DESK
6316 #else
6317    e_comp_wl_remote_surface_image_save(ec);
6318
6319    ec->iconic = 1;
6320    ec->want_focus = ec->take_focus = 0;
6321    ec->changes.visible = 0;
6322    if (ec->fullscreen)
6323      ec->desk->fullscreen_clients = eina_list_remove(ec->desk->fullscreen_clients, ec);
6324    e_client_comp_hidden_set(ec, 1);
6325    evas_object_hide(ec->frame);
6326    e_client_urgent_set(ec, ec->icccm.urgent);
6327
6328    _e_client_event_simple(ec, E_EVENT_CLIENT_ICONIFY);
6329
6330    if (e_config->transient.iconify)
6331      {
6332         E_Client *child;
6333         Eina_List *list = eina_list_clone(ec->transients);
6334
6335         EINA_LIST_FREE(list, child)
6336           {
6337              if ((child->exp_iconify.type != E_ICONIFIED_TYPE_ICONIFY_BY_CLIENT) &&
6338                  (_e_client_is_parent_iconify_by_client(child)))
6339                {
6340                   e_client_iconified_type_set(child, E_ICONIFIED_TYPE_PARENT_ICONIFY_BY_CLIENT);
6341                   child->exp_iconify.by_client = 1;
6342                   e_policy_client_iconic_state_change_send(child, 1);
6343                }
6344              e_client_iconify(child);
6345           }
6346      }
6347
6348 #endif
6349
6350    wl_signal_emit_mutable(&PRI(ec)->events.iconify, NULL);
6351    _e_client_hook_call(E_CLIENT_HOOK_ICONIFY, ec);
6352
6353    TRACE_DS_END();
6354 }
6355
6356 E_API void
6357 e_client_uniconify(E_Client *ec)
6358 {
6359 #ifdef REFACTOR_ZONE_DESK
6360    E_Comp_Wl_Client_Data *cdata;
6361
6362    E_OBJECT_CHECK(ec);
6363    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6364
6365    cdata = e_client_cdata_get(ec);
6366
6367    ELOGF("TZVIS", "UNICONIFY|iconic:%d  |argb:%d       |not_raise:%d  |by_client:%d, type:%d |mapped:%d",
6368          ec, ec->iconic, ec->argb, (unsigned int)ec->exp_iconify.not_raise,
6369          ec->exp_iconify.by_client, ec->exp_iconify.type,
6370          cdata ? cdata->mapped : 0);
6371
6372    if (ec->shading || (!ec->iconic)) return;
6373
6374    TRACE_DS_BEGIN(CLIENT:UNICONIFY);
6375
6376     // call the uniconify hook of a client
6377    wl_signal_emit_mutable(&PRI(ec)->events.uniconify, NULL);
6378    _e_client_hook_call(E_CLIENT_HOOK_UNICONIFY, ec);
6379
6380    TRACE_DS_END();
6381 #else
6382    E_Desk *desk;
6383    Eina_Bool not_raise;
6384
6385    E_OBJECT_CHECK(ec);
6386    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6387
6388    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
6389
6390    ELOGF("TZVIS", "UNICONIFY|iconic:%d  |argb:%d       |not_raise:%d  |by_client:%d, type:%d |mapped:%d",
6391          ec, ec->iconic, ec->argb, (unsigned int)ec->exp_iconify.not_raise,
6392          ec->exp_iconify.by_client, ec->exp_iconify.type,
6393          cdata ? cdata->mapped : 0);
6394
6395    if (ec->shading || (!ec->iconic)) return;
6396
6397    TRACE_DS_BEGIN(CLIENT:UNICONIFY);
6398
6399    e_comp_wl_remote_surface_image_save_cancel(ec);
6400
6401    desk = e_desk_current_get(ec->desk->zone);
6402    e_client_desk_set(ec, desk);
6403    not_raise = ec->exp_iconify.not_raise;
6404
6405    ec->exp_iconify.by_client = 0;
6406    e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_NONE);
6407
6408    if (e_config->transient.iconify)
6409      {
6410         E_Client *child;
6411         Eina_List *list = eina_list_clone(ec->transients);
6412
6413         EINA_LIST_FREE(list, child)
6414           {
6415              if (e_client_transient_policy_get(child) == E_TRANSIENT_BELOW)
6416                {
6417                   child->exp_iconify.not_raise = not_raise;
6418                   e_client_uniconify(child);
6419                }
6420           }
6421      }
6422
6423    if (!not_raise)
6424      e_client_raise(ec);
6425
6426    if (ec->internal)
6427      {
6428         ELOGF("TZVIS", "UNICONIFY|internal object force show", ec);
6429         evas_object_show(ec->frame);
6430      }
6431
6432    if (ec->pixmap)
6433      {
6434         if (e_pixmap_usable_get(ec->pixmap))
6435           {
6436              if (cdata && cdata->mapped)
6437                {
6438                   ELOGF("TZVIS", "UNICONIFY|object show. frame_visible:%d", ec, evas_object_visible_get(ec->frame));
6439                   evas_object_show(ec->frame);
6440                }
6441              else
6442                {
6443                   ELOGF("TZVIS", "UNICONIFY|object no show. currently unmapped", ec);
6444                }
6445           }
6446         else
6447           {
6448              if (!ec->exp_iconify.buffer_flush &&
6449                  !ec->exp_iconify.deiconify_update)
6450                {
6451                   if (cdata && cdata->mapped)
6452                     {
6453                        ELOGF("TZVIS", "UNICONIFY|object show. no use buffer flush. frame_visible:%d", ec, evas_object_visible_get(ec->frame));
6454                        evas_object_show(ec->frame);
6455                     }
6456                }
6457           }
6458      }
6459    e_client_comp_hidden_set(ec, 0);
6460    ec->deskshow = ec->iconic = 0;
6461
6462 #if 0 // focus should be set to the top window not uniconify window
6463    if (ec->pixmap && e_pixmap_usable_get(ec->pixmap))
6464       e_client_frame_focus_set(ec, EINA_TRUE);
6465 #endif
6466
6467    _e_client_event_simple(ec, E_EVENT_CLIENT_UNICONIFY);
6468
6469    if (e_config->transient.iconify)
6470      {
6471         E_Client *child;
6472         Eina_List *list = eina_list_clone(ec->transients);
6473
6474         EINA_LIST_FREE(list, child)
6475           {
6476              if (e_client_transient_policy_get(child) == E_TRANSIENT_ABOVE)
6477                {
6478                   if (child->exp_iconify.type == E_ICONIFIED_TYPE_PARENT_ICONIFY_BY_CLIENT)
6479                     e_policy_client_iconic_state_change_send(child, 0);
6480                   child->exp_iconify.not_raise = not_raise;
6481                   e_client_uniconify(child);
6482                }
6483           }
6484      }
6485
6486    wl_signal_emit_mutable(&PRI(ec)->events.uniconify, NULL);
6487    _e_client_hook_call(E_CLIENT_HOOK_UNICONIFY, ec);
6488
6489    ec->exp_iconify.not_raise = 0;
6490
6491    TRACE_DS_END();
6492 #endif
6493 }
6494
6495 E_API void
6496 e_client_iconified_type_set(E_Client *ec, E_Iconified_Type type)
6497 {
6498    if (!ec) return;
6499    ec->exp_iconify.type = type;
6500 }
6501
6502 EINTERN E_Iconified_Type
6503 e_client_iconified_type_get(E_Client *ec)
6504 {
6505    if (!ec) return E_ICONIFIED_TYPE_NONE;
6506    return ec->exp_iconify.type;
6507 }
6508
6509 E_API Eina_Bool e_client_is_iconified_by_client(E_Client *ec)
6510 {
6511    if (!ec) return EINA_FALSE;
6512
6513    if (ec->exp_iconify.type == E_ICONIFIED_TYPE_ICONIFY_BY_CLIENT)
6514      return EINA_TRUE;
6515
6516    if (ec->exp_iconify.type == E_ICONIFIED_TYPE_DESK_ICONIFY_BY_CLIENT)
6517      return EINA_TRUE;
6518
6519    if (ec->exp_iconify.type == E_ICONIFIED_TYPE_PARENT_ICONIFY_BY_CLIENT)
6520      return EINA_TRUE;
6521
6522    if (ec->exp_iconify.by_client)
6523      {
6524         ELOGF("POL", "CHECK. mismatch value. by_client:%d, type:%d", ec, ec->exp_iconify.by_client, ec->exp_iconify.type);
6525         return EINA_TRUE;
6526      }
6527
6528    return EINA_FALSE;
6529 }
6530
6531 ///////////////////////////////////////
6532
6533 EINTERN void
6534 e_client_urgent_set(E_Client *ec, Eina_Bool urgent)
6535 {
6536    E_OBJECT_CHECK(ec);
6537    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6538
6539    urgent = !!urgent;
6540    if (urgent == ec->urgent) return;
6541    _e_client_event_property(ec, E_CLIENT_PROPERTY_URGENCY);
6542    if (urgent && (!ec->focused) && (!ec->want_focus))
6543      {
6544         e_comp_object_signal_emit(ec->frame, "e,state,urgent", "e");
6545         ec->urgent = urgent;
6546      }
6547    else
6548      {
6549         e_comp_object_signal_emit(ec->frame, "e,state,not_urgent", "e");
6550         ec->urgent = 0;
6551      }
6552 }
6553
6554 ///////////////////////////////////////
6555
6556 EINTERN void
6557 e_client_stick(E_Client *ec)
6558 {
6559 #ifdef REFACTOR_ZONE_DESK
6560    E_OBJECT_CHECK(ec);
6561    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6562    if (ec->sticky) return;
6563
6564    // call the stick hook of a client
6565    wl_signal_emit_mutable(&PRI(ec)->events.stick, NULL);
6566    _e_client_hook_call(E_CLIENT_HOOK_STICK, ec);
6567
6568    // send the sticky property event of a client
6569    _e_client_event_property(ec, E_CLIENT_PROPERTY_STICKY);
6570 #else
6571    E_Desk *desk;
6572
6573    E_OBJECT_CHECK(ec);
6574    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6575    if (ec->sticky) return;
6576    desk = ec->desk;
6577    ec->desk = NULL;
6578    ec->sticky = 1;
6579    ec->hidden = 0;
6580    e_client_desk_set(ec, desk);
6581    evas_object_smart_callback_call(ec->frame, "stick", NULL);
6582
6583    if (e_config->transient.desktop)
6584      {
6585         E_Client *child;
6586         Eina_List *list = eina_list_clone(ec->transients);
6587
6588         EINA_LIST_FREE(list, child)
6589           {
6590              child->sticky = 1;
6591              evas_object_show(ec->frame);
6592           }
6593      }
6594
6595    _e_client_event_property(ec, E_CLIENT_PROPERTY_STICKY);
6596 #endif
6597 }
6598
6599 EINTERN void
6600 e_client_unstick(E_Client *ec)
6601 {
6602 #ifdef REFACTOR_ZONE_DESK
6603    E_OBJECT_CHECK(ec);
6604    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6605
6606    if (!ec->sticky) return;
6607
6608    // call the unstick hook of a client
6609    wl_signal_emit_mutable(&PRI(ec)->events.unstick, NULL);
6610    _e_client_hook_call(E_CLIENT_HOOK_UNSTICK, ec);
6611
6612   // send the sticky property event of a client
6613    _e_client_event_property(ec, E_CLIENT_PROPERTY_STICKY);
6614 #else
6615    E_Desk *desk;
6616    E_Zone *zone;
6617
6618    E_OBJECT_CHECK(ec);
6619    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6620    /* Set the desk before we unstick the client */
6621    if (!ec->sticky) return;
6622
6623    zone = e_comp_zone_find_by_ec(ec);
6624    desk = e_desk_current_get(zone);
6625    ec->desk = NULL;
6626    ec->hidden = ec->sticky = 0;
6627    e_client_desk_set(ec, desk);
6628    evas_object_smart_callback_call(ec->frame, "unstick", NULL);
6629
6630    if (e_config->transient.desktop)
6631      {
6632         E_Client *child;
6633         Eina_List *list = eina_list_clone(ec->transients);
6634
6635         EINA_LIST_FREE(list, child)
6636           {
6637              child->sticky = 0;
6638           }
6639      }
6640
6641    _e_client_event_property(ec, E_CLIENT_PROPERTY_STICKY);
6642
6643    e_client_desk_set(ec, e_desk_current_get(zone));
6644 #endif
6645 }
6646
6647 EINTERN void
6648 e_client_pinned_set(E_Client *ec, Eina_Bool set)
6649 {
6650    E_Layer layer;
6651
6652    EINA_SAFETY_ON_NULL_RETURN(ec);
6653    if (set)
6654      layer = E_LAYER_CLIENT_ABOVE;
6655    else
6656      layer = E_LAYER_CLIENT_NORMAL;
6657
6658    e_client_layer_set(ec, layer);
6659
6660    EC_CHANGED(ec);
6661 }
6662
6663 ///////////////////////////////////////
6664
6665 EINTERN Eina_Bool
6666 e_client_border_set(E_Client *ec, const char *name)
6667 {
6668    Eina_Stringshare *pborder;
6669
6670    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
6671    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
6672    if (!e_comp_object_frame_allowed(ec->frame)) return EINA_FALSE;
6673    if (ec->border.changed)
6674      CRI("CALLING WHEN border.changed SET!");
6675
6676    if (!e_util_strcmp(ec->border.name, name)) return EINA_TRUE;
6677    if (ec->mwm.borderless && name && strcmp(name, "borderless"))
6678      {
6679         CRI("border change attempted for MWM borderless client!");
6680      }
6681    pborder = ec->border.name;
6682    ec->border.name = eina_stringshare_add(name);
6683    if (e_comp_object_frame_theme_set(ec->frame, name))
6684      {
6685         eina_stringshare_del(pborder);
6686         return EINA_TRUE;
6687      }
6688    eina_stringshare_del(ec->border.name);
6689    ec->border.name = pborder;
6690    return EINA_FALSE;
6691 }
6692
6693 ///////////////////////////////////////
6694
6695 EINTERN void
6696 e_client_comp_hidden_set(E_Client *ec, Eina_Bool hidden)
6697 {
6698    E_OBJECT_CHECK(ec);
6699    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6700
6701    hidden = !!hidden;
6702    if (ec->comp_hidden == hidden) return;
6703    ec->comp_hidden = hidden;
6704    evas_object_smart_callback_call(ec->frame, "comp_hidden", NULL);
6705 }
6706
6707 ///////////////////////////////////////
6708
6709 EINTERN void
6710 e_client_act_move_keyboard(E_Client *ec)
6711 {
6712    EINA_SAFETY_ON_NULL_RETURN(ec);
6713
6714    if (!_e_client_move_begin(ec))
6715      return;
6716
6717    _e_client_action_init(ec);
6718    _e_client_action_move_timeout_add();
6719
6720    wl_signal_emit_mutable(&PRI(ec)->events.move_update, NULL);
6721    if (!_e_client_hook_call(E_CLIENT_HOOK_MOVE_UPDATE, ec)) return;
6722    evas_object_freeze_events_set(ec->frame, 1);
6723
6724    if (!action_handler_mouse)
6725      action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_client_move_mouse_down, NULL);
6726 }
6727
6728 EINTERN void
6729 e_client_act_resize_keyboard(E_Client *ec)
6730 {
6731    EINA_SAFETY_ON_NULL_RETURN(ec);
6732
6733    ec->resize_mode = E_POINTER_RESIZE_TL;
6734    ec->keyboard_resizing = 1;
6735    if (!e_client_resize_begin(ec))
6736      {
6737         ec->keyboard_resizing = 0;
6738         return;
6739      }
6740
6741    _e_client_action_init(ec);
6742    _e_client_action_resize_timeout_add();
6743    evas_object_freeze_events_set(ec->frame, 1);
6744
6745    if (!action_handler_mouse)
6746      action_handler_mouse = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_DOWN, _e_client_resize_mouse_down, NULL);
6747 }
6748
6749 EINTERN void
6750 e_client_act_move_begin(E_Client *ec, E_Binding_Event_Mouse_Button *ev)
6751 {
6752    E_OBJECT_CHECK(ec);
6753    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6754    if (e_client_util_resizing_get(ec) || (ec->moving)) return;
6755    if (ev)
6756      {
6757         char source[256];
6758
6759         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->button);
6760         _e_client_moveinfo_gather(ec, source);
6761      }
6762    if (!_e_client_move_begin(ec))
6763      return;
6764
6765    _e_client_action_init(ec);
6766 }
6767
6768 E_API void
6769 e_client_act_move_end(E_Client *ec, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
6770 {
6771    E_OBJECT_CHECK(ec);
6772    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6773    if (!ec->moving) return;
6774    _e_client_move_end(ec);
6775    _e_client_action_finish();
6776 }
6777
6778 EINTERN void
6779 e_client_act_resize_begin(E_Client *ec, E_Binding_Event_Mouse_Button *ev, E_Pointer_Mode resize_mode)
6780 {
6781    E_OBJECT_CHECK(ec);
6782    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6783    if (ec->lock_user_size || ec->shaded || ec->shading) return;
6784    if (e_client_util_resizing_get(ec) || (ec->moving)) return;
6785    if (ev)
6786      {
6787         char source[256];
6788         snprintf(source, sizeof(source) - 1, "mouse,down,%i", ev->button);
6789         _e_client_moveinfo_gather(ec, source);
6790
6791         if (resize_mode != E_POINTER_RESIZE_NONE)
6792           {
6793              ec->resize_mode = resize_mode;
6794           }
6795         else
6796           {
6797              /* Use canvas.x, canvas.y of event.
6798               * Transformed coordinates has to be considered for accurate resize_mode
6799               * rather than absolute coordinates. */
6800              if ((ev->canvas.x > (ec->x + ec->w / 5)) &&
6801                  (ev->canvas.x < (ec->x + ec->w * 4 / 5)))
6802                {
6803                   if (ev->canvas.y < (ec->y + ec->h / 2)) ec->resize_mode = E_POINTER_RESIZE_T;
6804                   else ec->resize_mode = E_POINTER_RESIZE_B;
6805                }
6806              else if (ev->canvas.x < (ec->x + ec->w / 2))
6807                {
6808                   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;
6809                   else if (ev->canvas.y < (ec->y + ec->h / 2)) ec->resize_mode = E_POINTER_RESIZE_TL;
6810                   else ec->resize_mode = E_POINTER_RESIZE_BL;
6811                }
6812              else
6813                {
6814                   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;
6815                   else if (ev->canvas.y < (ec->y + ec->h / 2)) ec->resize_mode = E_POINTER_RESIZE_TR;
6816                   else ec->resize_mode = E_POINTER_RESIZE_BR;
6817                }
6818           }
6819      }
6820    if (!e_client_resize_begin(ec))
6821      return;
6822    _e_client_action_init(ec);
6823 }
6824
6825 EINTERN void
6826 e_client_act_resize_end(E_Client *ec, E_Binding_Event_Mouse_Button *ev EINA_UNUSED)
6827 {
6828    E_OBJECT_CHECK(ec);
6829    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6830    if (e_client_util_resizing_get(ec))
6831      {
6832         _e_client_resize_end(ec);
6833         ec->changes.reset_gravity = 1;
6834         if (!e_object_is_del(E_OBJECT(ec)))
6835           EC_CHANGED(ec);
6836      }
6837    _e_client_action_finish();
6838 }
6839
6840 EINTERN void
6841 e_client_act_menu_begin(E_Client *ec, E_Binding_Event_Mouse_Button *ev, int key)
6842 {
6843    E_OBJECT_CHECK(ec);
6844    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6845 }
6846
6847 EINTERN void
6848 e_client_act_close_begin(E_Client *ec)
6849 {
6850    E_OBJECT_CHECK(ec);
6851    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6852    if (ec->lock_close) return;
6853    if (ec->icccm.delete_request)
6854      {
6855         ec->delete_requested = 1;
6856         evas_object_smart_callback_call(ec->frame, "delete_request", NULL);
6857      }
6858    else if (e_config->kill_if_close_not_possible)
6859      {
6860         e_client_act_kill_begin(ec);
6861      }
6862 }
6863
6864 EINTERN void
6865 e_client_act_kill_begin(E_Client *ec)
6866 {
6867    E_OBJECT_CHECK(ec);
6868    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6869    if (ec->internal) return;
6870    if (ec->lock_close) return;
6871    if ((ec->netwm.pid > 1) && (e_config->kill_process))
6872      {
6873         kill(ec->netwm.pid, SIGINT);
6874         ec->kill_timer = ecore_timer_add(e_config->kill_timer_wait,
6875                                          _e_client_cb_kill_timer, ec);
6876      }
6877    else
6878      evas_object_smart_callback_call(ec->frame, "kill_request", NULL);
6879 }
6880
6881 ////////////////////////////////////////////
6882
6883 EINTERN void
6884 e_client_ping(E_Client *ec)
6885 {
6886    E_OBJECT_CHECK(ec);
6887    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
6888
6889    if (!e_config->ping_clients) return;
6890
6891    EINA_SAFETY_ON_TRUE_RETURN(e_object_is_del(E_OBJECT(ec)));
6892
6893    ec->ping_ok = 0;
6894    evas_object_smart_callback_call(ec->frame, "ping", NULL);
6895    ec->ping = ecore_loop_time_get();
6896    if (ec->ping_poller) ecore_poller_del(ec->ping_poller);
6897    ec->ping_poller = ecore_poller_add(ECORE_POLLER_CORE,
6898                                       e_config->ping_clients_interval,
6899                                       _e_client_cb_ping_poller, ec);
6900 }
6901
6902 ////////////////////////////////////////////
6903 E_API void
6904 e_client_cursor_map_apply(E_Client *ec, int rotation, int x, int y)
6905 {
6906    // TODO: remove(deprecate) this e_client_cursor_map_apply.
6907 }
6908
6909 EINTERN void
6910 e_client_move_cancel(void)
6911 {
6912    if (!ecmove) return;
6913    if (ecmove->cur_mouse_action)
6914      {
6915         E_Client *ec;
6916
6917         ec = ecmove;
6918         e_object_ref(E_OBJECT(ec));
6919         if (ec->cur_mouse_action->func.end_mouse)
6920           ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", NULL);
6921         else if (ec->cur_mouse_action->func.end)
6922           ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
6923         e_object_unref(E_OBJECT(ec->cur_mouse_action));
6924         ec->cur_mouse_action = NULL;
6925         e_object_unref(E_OBJECT(ec));
6926      }
6927    else
6928      _e_client_move_end(ecmove);
6929 }
6930
6931 EINTERN void
6932 e_client_resize_cancel(void)
6933 {
6934    if (!ecresize) return;
6935    if (ecresize->cur_mouse_action)
6936      {
6937         E_Client *ec;
6938
6939         ec = ecresize;
6940         e_object_ref(E_OBJECT(ec));
6941         if (ec->cur_mouse_action->func.end_mouse)
6942           ec->cur_mouse_action->func.end_mouse(E_OBJECT(ec), "", NULL);
6943         else if (ec->cur_mouse_action->func.end)
6944           ec->cur_mouse_action->func.end(E_OBJECT(ec), "");
6945         e_object_unref(E_OBJECT(ec->cur_mouse_action));
6946         ec->cur_mouse_action = NULL;
6947         e_object_unref(E_OBJECT(ec));
6948      }
6949    else
6950      _e_client_resize_end(ecresize);
6951 }
6952
6953 EINTERN Eina_Bool
6954 e_client_resize_begin(E_Client *ec)
6955 {
6956    if ((ec->shaded) || (ec->shading) ||
6957        (ec->fullscreen) || (ec->lock_user_size))
6958      goto error;
6959    if (!_e_client_action_input_win_new()) goto error;
6960    ecresize = ec;
6961    if (ec->manage_resize.enable_aspect_ratio)
6962      {
6963         ELOGF("RESIZE", "Set resize aspect ratio.. ratio(%dx%d)", ec, ec->w, ec->h);
6964         ec->manage_resize.aw = ec->w;
6965         ec->manage_resize.ah = ec->h - ec->manage_resize.header_h - ec->manage_resize.footer_h;
6966      }
6967
6968    wl_signal_emit_mutable(&PRI(ec)->events.move_begin, NULL);
6969    _e_client_hook_call(E_CLIENT_HOOK_RESIZE_BEGIN, ec);
6970    if (ec->transformed)
6971      _e_client_transform_resize_begin(ec);
6972    if (!e_client_util_resizing_get(ec))
6973      {
6974         if (ecresize == ec) ecresize = NULL;
6975         _e_client_action_input_win_del();
6976         return EINA_FALSE;
6977      }
6978    if (!ec->lock_user_stacking)
6979      {
6980         if (e_config->border_raise_on_mouse_action)
6981           e_client_raise(ec);
6982      }
6983
6984    if (e_comp->hwc)
6985      e_comp_client_override_add(ec);
6986
6987    return EINA_TRUE;
6988 error:
6989    ec->resize_mode = E_POINTER_RESIZE_NONE;
6990    return EINA_FALSE;
6991 }
6992
6993
6994 ////////////////////////////////////////////
6995
6996 EINTERN void
6997 e_client_frame_recalc(E_Client *ec)
6998 {
6999    EINA_SAFETY_ON_NULL_RETURN(ec);
7000    if (!ec->frame) return;
7001    evas_object_smart_callback_call(ec->frame, "frame_recalc", NULL);
7002 }
7003
7004 ////////////////////////////////////////////
7005
7006 EINTERN void
7007 e_client_signal_move_begin(E_Client *ec, const char *sig, const char *src EINA_UNUSED)
7008 {
7009    E_OBJECT_CHECK(ec);
7010    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
7011
7012    if (e_client_util_resizing_get(ec) || (ec->moving)) return;
7013    _e_client_moveinfo_gather(ec, sig);
7014    if (!_e_client_move_begin(ec)) return;
7015 }
7016
7017 EINTERN void
7018 e_client_signal_move_end(E_Client *ec, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
7019 {
7020    E_OBJECT_CHECK(ec);
7021    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
7022    if (!ec->moving) return;
7023    _e_client_move_end(ec);
7024 }
7025
7026 EINTERN void
7027 e_client_signal_resize_begin(E_Client *ec, const char *dir, const char *sig, const char *src EINA_UNUSED)
7028 {
7029    int resize_mode = E_POINTER_RESIZE_BR;
7030
7031    E_OBJECT_CHECK(ec);
7032    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
7033
7034    if (e_client_util_resizing_get(ec) || (ec->moving)) return;
7035    if (!strcmp(dir, "tl"))
7036      {
7037         resize_mode = E_POINTER_RESIZE_TL;
7038      }
7039    else if (!strcmp(dir, "t"))
7040      {
7041         resize_mode = E_POINTER_RESIZE_T;
7042      }
7043    else if (!strcmp(dir, "tr"))
7044      {
7045         resize_mode = E_POINTER_RESIZE_TR;
7046      }
7047    else if (!strcmp(dir, "r"))
7048      {
7049         resize_mode = E_POINTER_RESIZE_R;
7050      }
7051    else if (!strcmp(dir, "br"))
7052      {
7053         resize_mode = E_POINTER_RESIZE_BR;
7054      }
7055    else if (!strcmp(dir, "b"))
7056      {
7057         resize_mode = E_POINTER_RESIZE_B;
7058      }
7059    else if (!strcmp(dir, "bl"))
7060      {
7061         resize_mode = E_POINTER_RESIZE_BL;
7062      }
7063    else if (!strcmp(dir, "l"))
7064      {
7065         resize_mode = E_POINTER_RESIZE_L;
7066      }
7067    ec->resize_mode = resize_mode;
7068    _e_client_moveinfo_gather(ec, sig);
7069    if (!e_client_resize_begin(ec))
7070      return;
7071 }
7072
7073 EINTERN void
7074 e_client_signal_resize_end(E_Client *ec, const char *dir EINA_UNUSED, const char *sig EINA_UNUSED, const char *src EINA_UNUSED)
7075 {
7076    E_OBJECT_CHECK(ec);
7077    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
7078    if (!e_client_util_resizing_get(ec)) return;
7079    _e_client_resize_handle(ec);
7080    _e_client_resize_end(ec);
7081    ec->changes.reset_gravity = 1;
7082    EC_CHANGED(ec);
7083 }
7084
7085 ////////////////////////////////////////////
7086
7087 EINTERN void
7088 e_client_resize_limit(E_Client *ec, int *w, int *h)
7089 {
7090    double a;
7091    Eina_Bool inc_h;
7092
7093    E_OBJECT_CHECK(ec);
7094    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
7095
7096    inc_h = (*h - ec->h > 0);
7097    if (ec->frame)
7098      e_comp_object_frame_wh_unadjust(ec->frame, *w, *h, w, h);
7099    if (*h < 1) *h = 1;
7100    if (*w < 1) *w = 1;
7101    if ((ec->icccm.base_w >= 0) &&
7102        (ec->icccm.base_h >= 0))
7103      {
7104         int tw, th;
7105
7106         tw = *w - ec->icccm.base_w;
7107         th = *h - ec->icccm.base_h;
7108         if (tw < 1) tw = 1;
7109         if (th < 1) th = 1;
7110         a = (double)(tw) / (double)(th);
7111         if ((ec->icccm.min_aspect != 0.0) &&
7112             (a < ec->icccm.min_aspect))
7113           {
7114              if (inc_h)
7115                tw = th * ec->icccm.min_aspect;
7116              else
7117                th = tw / ec->icccm.max_aspect;
7118              *w = tw + ec->icccm.base_w;
7119              *h = th + ec->icccm.base_h;
7120           }
7121         else if ((ec->icccm.max_aspect != 0.0) &&
7122                  (a > ec->icccm.max_aspect))
7123           {
7124              tw = th * ec->icccm.max_aspect;
7125              *w = tw + ec->icccm.base_w;
7126           }
7127      }
7128    else
7129      {
7130         a = (double)*w / (double)*h;
7131         if ((ec->icccm.min_aspect != 0.0) &&
7132             (a < ec->icccm.min_aspect))
7133           {
7134              if (inc_h)
7135                *w = *h * ec->icccm.min_aspect;
7136              else
7137                *h = *w / ec->icccm.min_aspect;
7138           }
7139         else if ((ec->icccm.max_aspect != 0.0) &&
7140                  (a > ec->icccm.max_aspect))
7141           *w = *h * ec->icccm.max_aspect;
7142      }
7143    if (ec->icccm.step_w > 0)
7144      {
7145         if (ec->icccm.base_w >= 0)
7146           *w = ec->icccm.base_w +
7147             (((*w - ec->icccm.base_w) / ec->icccm.step_w) *
7148              ec->icccm.step_w);
7149         else
7150           *w = ec->icccm.min_w +
7151             (((*w - ec->icccm.min_w) / ec->icccm.step_w) *
7152              ec->icccm.step_w);
7153      }
7154    if (ec->icccm.step_h > 0)
7155      {
7156         if (ec->icccm.base_h >= 0)
7157           *h = ec->icccm.base_h +
7158             (((*h - ec->icccm.base_h) / ec->icccm.step_h) *
7159              ec->icccm.step_h);
7160         else
7161           *h = ec->icccm.min_h +
7162             (((*h - ec->icccm.min_h) / ec->icccm.step_h) *
7163              ec->icccm.step_h);
7164      }
7165
7166    if (*h < 1) *h = 1;
7167    if (*w < 1) *w = 1;
7168
7169    if ((ec->icccm.max_w > 0) && (*w > ec->icccm.max_w)) *w = ec->icccm.max_w;
7170    else if (*w < ec->icccm.min_w)
7171      *w = ec->icccm.min_w;
7172    if ((ec->icccm.max_h > 0) && (*h > ec->icccm.max_h)) *h = ec->icccm.max_h;
7173    else if (*h < ec->icccm.min_h)
7174      *h = ec->icccm.min_h;
7175
7176    if (ec->frame)
7177      e_comp_object_frame_wh_adjust(ec->frame, *w, *h, w, h);
7178 }
7179
7180 ////////////////////////////////////////////
7181
7182
7183
7184 EINTERN E_Client *
7185 e_client_under_pointer_get(E_Desk *desk, E_Client *exclude)
7186 {
7187    int x, y;
7188
7189    /* We need to ensure that we can get the comp window for the
7190     * zone of either the given desk or the desk of the excluded
7191     * window, so return if neither is given */
7192    if (desk)
7193      e_input_device_pointer_xy_get(NULL, &x, &y);
7194    else if (exclude)
7195      e_input_device_pointer_xy_get(NULL, &x, &y);
7196    else
7197      return NULL;
7198
7199    if (!desk)
7200      {
7201         desk = exclude->desk;
7202         if (!desk)
7203           {
7204              if (exclude->zone)
7205                desk = e_desk_current_get(exclude->zone);
7206              else
7207                desk = e_desk_current_get(e_zone_current_get());
7208           }
7209      }
7210
7211    return desk ? _e_client_under_pointer_helper(desk, exclude, x, y) : NULL;
7212 }
7213
7214 E_API E_Client *e_client_under_position_get(E_Desk *desk, int x, int y, E_Client *exclude)
7215 {
7216    if (!desk) return NULL;
7217
7218    return _e_client_under_pointer_helper(desk, exclude, x, y);
7219 }
7220
7221 E_API E_Client *e_client_under_position_input_get(E_Desk *desk, int x, int y)
7222 {
7223    if (!desk) return NULL;
7224
7225    return _e_client_under_pointer_input_helper(desk, x, y);
7226 }
7227
7228 EINTERN E_Client *
7229 e_client_input_rect_under_pointer_get(E_Desk *desk, E_Client *exclude)
7230 {
7231    int x, y;
7232
7233    /* We need to ensure that we can get the comp window for the
7234     * zone of either the given desk or the desk of the excluded
7235     * window, so return if neither is given */
7236    if (desk)
7237      e_input_device_pointer_xy_get(NULL, &x, &y);
7238    else if (exclude)
7239      e_input_device_pointer_xy_get(NULL, &x, &y);
7240    else
7241      return NULL;
7242
7243    if (!desk)
7244      {
7245         desk = exclude->desk;
7246         if (!desk)
7247           {
7248              if (exclude->zone)
7249                desk = e_desk_current_get(exclude->zone);
7250              else
7251                desk = e_desk_current_get(e_zone_current_get());
7252           }
7253      }
7254
7255    return desk ? _e_client_input_rect_under_pointer_helper(desk, exclude, x, y) : NULL;
7256 }
7257
7258 ////////////////////////////////////////////
7259
7260 ////////////////////////////////////////////
7261
7262 E_API void
7263 e_client_redirected_set(E_Client *ec, Eina_Bool set)
7264 {
7265    EINA_SAFETY_ON_NULL_RETURN(ec);
7266    if (ec->input_only) return;
7267    set = !!set;
7268    if (ec->redirected == set) return;
7269    if (set)
7270      {
7271         e_client_frame_recalc(ec);
7272
7273         wl_signal_emit_mutable(&PRI(ec)->events.redirect, NULL);
7274         if (!_e_client_hook_call(E_CLIENT_HOOK_REDIRECT, ec)) return;
7275      }
7276    else
7277      {
7278         wl_signal_emit_mutable(&PRI(ec)->events.unredirect, NULL);
7279         if (!_e_client_hook_call(E_CLIENT_HOOK_UNREDIRECT, ec)) return;
7280      }
7281    e_comp_object_redirected_set(ec->frame, set);
7282    ec->redirected = !!set;
7283 }
7284
7285 ////////////////////////////////////////////
7286
7287 EINTERN Eina_Bool
7288 e_client_is_stacking(const E_Client *ec)
7289 {
7290    return e_comp->layers[e_comp_canvas_layer_map(ec->layer)].obj == ec->frame;
7291 }
7292
7293 ////////////////////////////////////////////
7294
7295 E_API void
7296 e_client_transform_update(E_Client *ec)
7297 {
7298    if (e_client_util_resizing_get(ec))
7299      _e_client_transform_resize(ec);
7300 }
7301
7302 ////////////////////////////////////////////
7303
7304 EINTERN void
7305 e_client_transform_apply(E_Client *ec, double angle, double zoom, int cx, int cy)
7306 {
7307    E_Map *map;
7308    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
7309    E_Client *subc;
7310    Eina_List *l;
7311
7312    if (e_comp_wl_subsurface_check(ec))
7313      return;
7314
7315    /* check if it's different with current state */
7316    if ((ec->transform.angle == angle) &&
7317        (ec->transform.zoom == zoom) &&
7318        (ec->transform.center.x == cx) &&
7319        (ec->transform.center.y == cy))
7320      return;
7321
7322    /* use previous value if any required value is invalid */
7323    if (angle == -1.0)
7324      angle = ec->transform.angle;
7325    if (zoom == -1.0)
7326      zoom = ec->transform.zoom;
7327    if (!E_INSIDE(cx, cy,
7328                  ec->client.x, ec->client.y,
7329                  ec->client.w, ec->client.h))
7330      {
7331         cx = ec->transform.center.x;
7332         cy = ec->transform.center.y;
7333      }
7334
7335    if ((angle == 0) && (zoom == 1.0))
7336      {
7337         e_client_transform_clear(ec);
7338         return;
7339      }
7340
7341    map = e_map_new_with_direct_render(ec->transform_core.direct_render);
7342    e_map_util_points_populate_from_object_full(map, ec->frame, 0);
7343
7344    e_map_util_rotate(map, angle, cx, cy);
7345    _e_client_transform_geometry_save(ec, map);
7346
7347    e_map_util_zoom(map, zoom, zoom, cx, cy);
7348
7349    e_map_util_object_move_sync_set(map, EINA_TRUE);
7350    e_client_map_set(ec, map);
7351    e_client_map_enable_set(ec, EINA_TRUE);
7352
7353    EINA_LIST_FOREACH(cdata->sub.list, l, subc)
7354      _e_client_transform_sub_apply(subc, ec, zoom);
7355    EINA_LIST_REVERSE_FOREACH(cdata->sub.below_list, l, subc)
7356      _e_client_transform_sub_apply(subc, ec, zoom);
7357
7358    e_map_free(map);
7359
7360    ec->transform.zoom = zoom;
7361    ec->transform.angle = angle;
7362    ec->transform.center.x = cx;
7363    ec->transform.center.y = cy;
7364    ec->transformed = EINA_TRUE;
7365 }
7366
7367 ////////////////////////////////////////////
7368
7369 EINTERN void
7370 e_client_transform_clear(E_Client *ec)
7371 {
7372    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
7373    E_Client *subc;
7374    Eina_List *l;
7375
7376    e_client_map_enable_set(ec, EINA_FALSE);
7377    e_client_map_set(ec, NULL);
7378
7379    EINA_LIST_FOREACH(cdata->sub.list, l, subc)
7380      _e_client_transform_sub_apply(subc, ec, 1.0);
7381    EINA_LIST_REVERSE_FOREACH(cdata->sub.below_list, l, subc)
7382      _e_client_transform_sub_apply(subc, ec, 1.0);
7383
7384    ec->transform.zoom = 1.0;
7385    ec->transform.angle = 0.0;
7386    ec->transformed = EINA_FALSE;
7387 }
7388
7389 E_API Eina_Bool
7390 e_client_transform_core_enable_get(E_Client *ec)
7391 {
7392    if (!ec) return EINA_FALSE;
7393    return ec->transform_core.result.enable;
7394 }
7395
7396 E_API void
7397 e_client_transform_core_add(E_Client *ec, E_Util_Transform *transform)
7398 {
7399    if (!ec) return;
7400    if (!transform) return;
7401
7402    // duplication check
7403    if (ec->transform_core.transform_list &&
7404        eina_list_data_find(ec->transform_core.transform_list, transform) == transform)
7405      {
7406         return;
7407      }
7408
7409    ec->transform_core.transform_list = eina_list_append(ec->transform_core.transform_list, transform);
7410    ec->transform_core.changed = EINA_TRUE;
7411    e_util_transform_ref(transform);
7412   // e_client_transform_core_update(ec);
7413 }
7414
7415 E_API void
7416 e_client_transform_core_remove(E_Client *ec, E_Util_Transform *transform)
7417 {
7418    if (!ec) return;
7419    if (!transform) return;
7420
7421    if (ec->transform_core.transform_list &&
7422        eina_list_data_find(ec->transform_core.transform_list, transform) == transform)
7423      {
7424         ec->transform_core.transform_list = eina_list_remove(ec->transform_core.transform_list, transform);
7425         e_util_transform_unref(transform);
7426         ec->transform_core.changed = EINA_TRUE;
7427      }
7428
7429    e_client_transform_core_update(ec);
7430 }
7431
7432 E_API void
7433 e_client_transform_core_update(E_Client *ec)
7434 {
7435    if (!ec) return;
7436    if (ec->new_client) return;
7437    if (!_e_client_transform_core_check_change(ec)) return;
7438
7439    if (ec->transform_core.transform_list || ec->transform_core.parent.enable)
7440      {
7441         E_Util_Transform_Rect source_rect;
7442         E_Util_Transform_Matrix matrix, boundary_matrix;
7443         E_Util_Transform_Zoom zoom;
7444         Eina_List *l;
7445         Eina_Bool background;
7446         E_Util_Transform *temp_trans;
7447
7448         // 1. init state
7449         ec->transform_core.result.enable = EINA_TRUE;
7450         e_util_transform_rect_client_rect_get(&source_rect, ec);
7451         e_util_transform_init(&ec->transform_core.result.transform);
7452
7453         // 2. merge transform
7454         EINA_LIST_FOREACH(ec->transform_core.transform_list, l, temp_trans)
7455           {
7456              e_util_transform_merge(&ec->transform_core.result.transform, temp_trans);
7457           }
7458         zoom = ec->transform_core.result.transform.zoom;
7459
7460         // 2.5 check viewport
7461         if (e_util_transform_viewport_flag_get(&ec->transform_core.result.transform))
7462           {
7463              int vx = 0, vy = 0, vw = 0, vh = 0;
7464              e_util_transform_viewport_get(&ec->transform_core.result.transform, &vx, &vy, &vw, &vh);
7465              e_util_transform_rect_init(&source_rect, vx, vy, vw, vh);
7466           }
7467
7468         // 3. apply background transform
7469         matrix = e_util_transform_convert_to_matrix(&ec->transform_core.result.transform, &source_rect);
7470
7471         if (e_util_transform_bg_transform_flag_get(&ec->transform_core.result.transform))
7472           {
7473              boundary_matrix = e_util_transform_bg_convert_to_matrix(&ec->transform_core.result.transform, &source_rect);
7474              background = EINA_TRUE;
7475           }
7476         else
7477           {
7478              background = EINA_FALSE;
7479              boundary_matrix = matrix;
7480           }
7481
7482         if (background != ec->transform_core.background)
7483           {
7484              if (background)
7485                {
7486                   e_comp_object_transform_bg_set(ec->frame, EINA_TRUE);
7487                }
7488              else
7489                {
7490                   e_comp_object_transform_bg_set(ec->frame, EINA_FALSE);
7491                }
7492
7493              ec->transform_core.background = background;
7494           }
7495
7496         // 3.1 if 24bit window then set transp rect
7497         if (!ec->argb)
7498           {
7499              int angle = 0;
7500
7501              e_util_transform_rotation_round_get(&ec->transform_core.result.transform, 0, 0, &angle);
7502              angle %= 90;
7503
7504              if (angle == 0) // when transform angle is 0, 90, 180, 270, 360. then set transp rect
7505                e_comp_object_transform_transp_set(ec->frame, EINA_TRUE);
7506              else
7507                e_comp_object_transform_transp_set(ec->frame, EINA_FALSE);
7508           }
7509         else
7510           e_comp_object_transform_transp_set(ec->frame, EINA_FALSE);
7511
7512         // 3.5 parent matrix multiply
7513         if (ec->transform_core.parent.enable)
7514           {
7515              matrix = e_util_transform_matrix_multiply(&ec->transform_core.parent.matrix,
7516                                                        &matrix);
7517              boundary_matrix = e_util_transform_matrix_multiply(&ec->transform_core.parent.matrix,
7518                                                                 &boundary_matrix);
7519
7520              ec->transform_core.result.transform.use_zoom = EINA_TRUE;
7521              zoom.zoom_x *= ec->transform_core.parent.zoom.zoom_x;
7522              zoom.zoom_y *= ec->transform_core.parent.zoom.zoom_y;
7523              zoom.cx += ec->transform_core.parent.zoom.cx;
7524              zoom.cy += ec->transform_core.parent.zoom.cy;
7525           }
7526
7527         // 4. apply matrix to vertices
7528         ec->transform_core.result.matrix = matrix;
7529         ec->transform_core.result.inv_matrix = e_util_transform_matrix_inverse_get(&matrix);
7530         ec->transform_core.result.vertices = e_util_transform_rect_to_vertices(&source_rect);
7531         ec->transform_core.result.boundary.vertices = e_util_transform_rect_to_vertices(&source_rect);
7532         ec->transform_core.result.vertices = e_util_transform_matrix_multiply_rect_vertex(&matrix,
7533                                                                                           &ec->transform_core.result.vertices);
7534         ec->transform_core.result.boundary.vertices = e_util_transform_matrix_multiply_rect_vertex(&boundary_matrix,
7535                                                                                                    &ec->transform_core.result.boundary.vertices);
7536         ec->transform_core.result.transform.zoom = zoom;
7537
7538         // 5. apply vertices
7539         if (ec->transform_core.result.transform.use_zoom)
7540           {
7541              // TODO: apply zoom values to vertices
7542              e_comp_object_transform_transp_vertices_set_with_zoom(ec->frame, &ec->transform_core.result.vertices,
7543                                                                    ec->transform_core.result.transform.zoom);
7544              e_comp_object_transform_bg_vertices_set_with_zoom(ec->frame, &ec->transform_core.result.boundary.vertices,
7545                                                                ec->transform_core.result.transform.zoom);
7546              _e_client_transform_core_boundary_update(ec, &ec->transform_core.result.boundary.vertices);
7547              _e_client_transform_core_vertices_apply_with_zoom(ec, ec->frame, &ec->transform_core.result.vertices, &ec->transform_core.result.transform,
7548                                                                ec->transform_core.result.transform.zoom);
7549           }
7550         else
7551           {
7552              e_comp_object_transform_transp_vertices_set(ec->frame, &ec->transform_core.result.vertices);
7553              e_comp_object_transform_bg_vertices_set(ec->frame, &ec->transform_core.result.boundary.vertices);
7554              _e_client_transform_core_boundary_update(ec, &ec->transform_core.result.boundary.vertices);
7555              _e_client_transform_core_vertices_apply(ec, ec->frame, &ec->transform_core.result.vertices, &ec->transform_core.result.transform);
7556           }
7557
7558         // 6. subsurface update
7559         _e_client_transform_core_sub_update(ec, &ec->transform_core.result.vertices);
7560
7561         if (!e_object_is_del(E_OBJECT(ec)))
7562           {
7563              wl_signal_emit_mutable(&PRI(ec)->events.transform_change, NULL);
7564              _e_client_hook_call(E_CLIENT_HOOK_TRANSFORM_CHANGE, ec);
7565           }
7566      }
7567    else
7568      {
7569         if (ec->transform_core.result.enable)
7570           {
7571              ec->transform_core.result.enable = EINA_FALSE;
7572              _e_client_transform_core_vertices_apply(ec, ec->frame, NULL, NULL);
7573              e_comp_object_transform_bg_set(ec->frame, EINA_FALSE);
7574              ec->transform_core.background = EINA_FALSE;
7575              e_comp_object_transform_transp_set(ec->frame, EINA_FALSE);
7576              _e_client_transform_core_sub_update(ec, NULL);
7577
7578              if (!e_object_is_del(E_OBJECT(ec)))
7579                {
7580                   wl_signal_emit_mutable(&PRI(ec)->events.transform_change, NULL);
7581                   _e_client_hook_call(E_CLIENT_HOOK_TRANSFORM_CHANGE, ec);
7582                }
7583           }
7584      }
7585
7586    e_comp_visibility_calculation_set(EINA_TRUE);
7587 }
7588
7589 E_API int
7590 e_client_transform_core_transform_count_get(E_Client *ec)
7591 {
7592    if (!ec) return 0;
7593    if (!ec->transform_core.transform_list) return 0;
7594    return eina_list_count(ec->transform_core.transform_list);
7595 }
7596
7597 E_API E_Util_Transform*
7598 e_client_transform_core_transform_get(E_Client *ec, int index)
7599 {
7600    if (!ec) return NULL;
7601    if (!ec->transform_core.transform_list) return NULL;
7602    if (index < 0 || index >= e_client_transform_core_transform_count_get(ec))
7603       return NULL;
7604
7605    return (E_Util_Transform*)eina_list_nth(ec->transform_core.transform_list, index);
7606 }
7607
7608 E_API void
7609 e_client_transform_core_input_transform(E_Client *ec, int x, int y, int *out_x, int *out_y)
7610 {
7611    E_Util_Transform_Vertex vertex, result_vertex;
7612
7613    if (!ec) return;
7614    if (!e_client_transform_core_enable_get(ec)) return;
7615
7616    e_util_transform_vertex_init(&vertex, x, y, 0.0, 1.0);
7617
7618    result_vertex = e_util_transform_matrix_multiply_vertex(&ec->transform_core.result.inv_matrix, &vertex);
7619    e_util_transform_vertex_pos_round_get(&result_vertex, out_x, out_y, NULL, NULL);
7620 }
7621
7622 E_API void
7623 e_client_transform_core_input_inv_transform(E_Client *ec, int x, int y, int *out_x, int *out_y)
7624 {
7625    E_Util_Transform_Vertex vertex, result_vertex;
7626
7627    if (!ec) return;
7628    if (!e_client_transform_core_enable_get(ec)) return;
7629
7630    e_util_transform_vertex_init(&vertex, x, y, 0.0, 1.0);
7631
7632    result_vertex = e_util_transform_matrix_multiply_vertex(&ec->transform_core.result.matrix, &vertex);
7633    e_util_transform_vertex_pos_round_get(&result_vertex, out_x, out_y, NULL, NULL);
7634 }
7635
7636 EINTERN void
7637 e_client_transform_core_input_inv_rect_transform(E_Client *ec, int x, int y, int *out_x, int *out_y)
7638 {
7639    int gw = 0, gh = 0;
7640    if (!ec) return;
7641    if (!e_client_transform_core_enable_get(ec)) return;
7642    e_client_geometry_get(ec, NULL, NULL, &gw, &gh);
7643
7644    e_util_transform_matrix_inv_rect_coords_get(&ec->transform_core.result.transform,
7645                                                &ec->transform_core.result.vertices,
7646                                                gw, gh,
7647                                                x, y, out_x, out_y);
7648 }
7649
7650 E_API void
7651 e_client_transform_core_direct_render_set(E_Client *ec, Eina_Bool set)
7652 {
7653    EINA_SAFETY_ON_NULL_RETURN(ec);
7654
7655    if (ec->transform_core.direct_render == set) return;
7656
7657    ec->transform_core.direct_render = set;
7658    ec->transform_core.changed = EINA_TRUE;
7659
7660    e_client_transform_core_update(ec);
7661 }
7662
7663 EINTERN E_Pixmap *
7664 e_client_pixmap_change(E_Client *ec, E_Pixmap *newcp)
7665 {
7666    E_Pixmap_Type oldtype, newtype;
7667    E_Pixmap *oldcp;
7668
7669    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
7670    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->pixmap, NULL);
7671    EINA_SAFETY_ON_NULL_RETURN_VAL(newcp, NULL);
7672
7673    oldcp = ec->pixmap;
7674
7675    oldtype = e_pixmap_type_get(oldcp);
7676    if (oldtype >= E_PIXMAP_TYPE_MAX) return NULL;
7677
7678    newtype = e_pixmap_type_get(newcp);
7679    if (newtype >= E_PIXMAP_TYPE_MAX) return NULL;
7680
7681    if (eina_hash_find(clients_hash[oldtype], &oldcp))
7682      eina_hash_del_by_key(clients_hash[oldtype], &oldcp);
7683    e_pixmap_client_set(oldcp, NULL);
7684
7685    ec->pixmap = newcp;
7686    e_pixmap_client_set(newcp, ec);
7687
7688    eina_hash_add(clients_hash[newtype], &newcp, ec);
7689
7690    return oldcp;
7691 }
7692
7693 E_API void
7694 e_client_window_role_set(E_Client *ec, const char *role)
7695 {
7696    EINA_SAFETY_ON_NULL_RETURN(ec);
7697
7698    if (eina_stringshare_replace(&ec->icccm.window_role, role))
7699      {
7700         wl_signal_emit_mutable(&PRI(ec)->events.window_role_change, NULL);
7701         _e_client_hook_call(E_CLIENT_HOOK_WINDOW_ROLE_CHANGE, ec);
7702      }
7703 }
7704
7705 EINTERN Eina_Bool
7706 e_client_key_send(E_Client *ec, int keycode, Eina_Bool pressed, Ecore_Device *dev, unsigned int time)
7707 {
7708    Eina_Bool res;
7709
7710    res = e_comp_wl_key_send(ec, keycode, pressed, dev, time);
7711
7712    return res;
7713 }
7714
7715 EINTERN Eina_Bool
7716 e_client_key_cancel(E_Client *ec, int keycode, Ecore_Device *dev, unsigned int time)
7717 {
7718    Eina_Bool res;
7719
7720    res = e_comp_wl_key_cancel(ec, keycode, dev, time);
7721
7722    return res;
7723 }
7724
7725 EINTERN Eina_Bool
7726 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)
7727 {
7728    Eina_Bool res;
7729
7730    res = e_comp_wl_touch_send(ec, idx, x, y, pressed, dev, radius_x, radius_y, pressure, angle, time);
7731
7732    return res;
7733 }
7734
7735 EINTERN Eina_Bool
7736 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)
7737 {
7738    Eina_Bool res;
7739
7740    res = e_comp_wl_touch_update_send(ec, idx, x, y, dev, radius_x, radius_y, pressure, angle, time);
7741
7742    return res;
7743 }
7744
7745 EINTERN Eina_Bool
7746 e_client_touch_cancel_send(E_Client *ec)
7747 {
7748    Eina_Bool res;
7749
7750    res = e_comp_wl_touch_cancel_send(ec);
7751
7752    return res;
7753 }
7754
7755 EINTERN Eina_Bool
7756 e_client_mouse_button_send(E_Client *ec, int buttons, Eina_Bool pressed, Ecore_Device *dev, unsigned int time)
7757 {
7758    Eina_Bool res;
7759
7760    res = e_comp_wl_mouse_button_send(ec, buttons, pressed, dev, time);
7761
7762    return res;
7763 }
7764
7765 EINTERN Eina_Bool
7766 e_client_mouse_move_send(E_Client *ec, int x, int y, Ecore_Device *dev, unsigned int time)
7767 {
7768    Eina_Bool res;
7769
7770    res = e_comp_wl_mouse_move_send(ec, x, y, dev, time);
7771
7772    return res;
7773 }
7774
7775 EINTERN Eina_Bool
7776 e_client_mouse_wheel_send(E_Client *ec, int direction, int z, Ecore_Device *dev, unsigned int time)
7777 {
7778    Eina_Bool res;
7779
7780    res = e_comp_wl_mouse_wheel_send(ec, direction, z, dev, time);
7781
7782    return res;
7783 }
7784
7785 EINTERN Eina_Bool
7786 e_client_mouse_in_send(E_Client *ec, int x, int y, Ecore_Device *dev, unsigned int time)
7787 {
7788    Eina_Bool res;
7789
7790    res = e_comp_wl_mouse_in_send(ec, x, y, dev, time);
7791
7792    return res;
7793 }
7794
7795 EINTERN Eina_Bool
7796 e_client_mouse_out_send(E_Client *ec, Ecore_Device *dev, unsigned int time)
7797 {
7798    Eina_Bool res;
7799
7800    res = e_comp_wl_mouse_out_send(ec, dev, time);
7801
7802    return res;
7803 }
7804
7805 E_API Eina_Bool
7806 e_client_video_client_has(E_Client *ec)
7807 {
7808    return e_comp_wl_video_subsurface_has(ec);
7809 }
7810
7811 E_API Eina_Bool
7812 e_client_normal_client_has(E_Client *ec)
7813 {
7814    return e_comp_wl_normal_subsurface_has(ec);
7815 }
7816
7817 E_API Eina_Bool
7818 e_client_cursor_hide(E_Client *ec)
7819 {
7820    return e_comp_wl_cursor_hide(ec);
7821 }
7822
7823 E_API void
7824 e_client_visibility_force_obscured_set(E_Client *ec, Eina_Bool set)
7825 {
7826    if (!ec) return;
7827
7828    ELOGF("TZVIS", "VIS_FORCE_OBSCURED :%d", ec, set);
7829
7830    ec->visibility.force_obscured = set;
7831    e_comp_visibility_calculation_set(EINA_TRUE);
7832 }
7833
7834 EINTERN E_Capture_Save_State
7835 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)
7836 {
7837    return e_comp_wl_capture_client_image_save(ec, dir, name, func_end, data, skip_child);
7838 }
7839
7840 static void
7841 _e_client_base_output_resolution_hook_subsurf_create(void *data, E_Client *subc)
7842 {
7843    E_Client *ec, *parent;
7844
7845    ec = data;
7846    if (ec != subc)
7847      return;
7848
7849    ec->base_output_resolution.use = 0;
7850    ec->base_output_resolution.w = 0;
7851    ec->base_output_resolution.h = 0;
7852    if (ec->base_output_resolution.transform)
7853      {
7854         e_client_transform_core_remove(ec, ec->base_output_resolution.transform);
7855         E_FREE_FUNC(ec->base_output_resolution.transform, e_util_transform_del);
7856         ELOGF("POL_APPINFO", "Cancel TRANSFORM for subsurface", ec);
7857      }
7858
7859    /* Update transform for toplevel surface.
7860     * The transform of subsurface will be updated by its parent accordingly. */
7861    parent = e_comp_wl_topmost_parent_get(ec);
7862    if (parent)
7863      {
7864         parent->transform_core.changed = EINA_TRUE;
7865         e_client_transform_core_update(parent);
7866      }
7867
7868    /* TODO: Do we need to apply it again if subsurface is destroyed? */
7869 }
7870
7871 static void
7872 _e_client_base_output_resolution_set(E_Client *ec, int width, int height)
7873 {
7874    if (!ec) return;
7875    ec->base_output_resolution.use = 1;
7876    ec->base_output_resolution.w = width;
7877    ec->base_output_resolution.h = height;
7878    ec->base_output_resolution.transform = e_util_transform_new();
7879    e_util_transform_role_set(ec->base_output_resolution.transform, "base_output_resolution");
7880    e_client_transform_core_add(ec, ec->base_output_resolution.transform);
7881
7882    if (!ec->base_output_resolution.hook_subsurf_create)
7883      {
7884         ec->base_output_resolution.hook_subsurf_create =
7885            e_comp_wl_hook_add(E_COMP_WL_HOOK_SUBSURFACE_CREATE,
7886                               _e_client_base_output_resolution_hook_subsurf_create,
7887                               ec);
7888      }
7889 }
7890
7891 E_API void
7892 e_client_base_output_resolution_transform_adjust(E_Client *ec)
7893 {
7894    E_Desk *desk;
7895
7896    EINA_SAFETY_ON_NULL_RETURN(ec);
7897    if (!ec->base_output_resolution.use) return;
7898    if (!ec->base_output_resolution.transform) return;
7899
7900    desk = e_comp_desk_find_by_ec(ec);
7901    EINA_SAFETY_ON_NULL_RETURN(desk);
7902
7903    ELOGF("POL_APPINFO", "Apply TRANSFORM... desk:(%dx%d), ec:(%dx%d)",
7904          ec, desk->geom.w, desk->geom.h, ec->w, ec->h);
7905
7906    e_util_transform_scale(ec->base_output_resolution.transform,
7907                           (double)desk->geom.w /(double)ec->base_output_resolution.w,
7908                           (double)desk->geom.h /(double)ec->base_output_resolution.h,
7909                           1.0);
7910    e_client_transform_core_update(ec);
7911 }
7912
7913 E_API Eina_Bool
7914 e_client_base_output_resolution_update(E_Client *ec)
7915 {
7916    E_Appinfo *eai = NULL;
7917    int configured_width, configured_height;
7918    int width, height;
7919    E_Desk *desk;
7920
7921    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
7922
7923   if (!e_config->configured_output_resolution.use) return EINA_TRUE;
7924   if (ec->base_output_resolution.use) return EINA_TRUE;
7925
7926   /* Check whether it's subsurface or not
7927    * The resolution of subsurface will follow the resolution of its toplevel surface.
7928    * Transform for subsurface will be applied when toplevel surface does by
7929    * implementation of e_client_transform_core.
7930    */
7931   if (e_comp_wl_subsurface_check(ec))
7932     return EINA_FALSE;
7933
7934    desk = e_comp_desk_find_by_ec(ec);
7935    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
7936
7937   configured_width = e_config->configured_output_resolution.w;
7938   configured_height = e_config->configured_output_resolution.h;
7939
7940   if (!ec->netwm.pid)
7941     {
7942        ELOGF("POL_APPINFO", "NO PID... USE configured_output_resolution(%d,%d) pid:%d", ec,
7943              configured_width, configured_height, ec->netwm.pid);
7944        goto use_configured;
7945     }
7946
7947    eai = e_appinfo_find_with_pid(ec->netwm.pid);
7948    if (!eai)
7949      {
7950         ELOGF("POL_APPINFO", "NO APPINFO... USE configured_output_resolution(%d,%d) pid:%d", ec,
7951               configured_width, configured_height, ec->netwm.pid);
7952         goto use_configured;
7953      }
7954
7955    if (!e_appinfo_base_output_resolution_get(eai, &width, &height))
7956      {
7957         ELOGF("POL_APPINFO", "NO BASE SCREEN RESOLUTION... USE configured_output_resolution(%d,%d) pid:%d", ec,
7958               configured_width, configured_height, ec->netwm.pid);
7959         goto use_configured;
7960       }
7961
7962    if ((width == 0) && (height == 0))
7963      {
7964         ELOGF("POL_APPINFO", "SKIP SET BASE SCREEN RESOLUTION... base_output_resolution size:(%d,%d) pid:%d", ec, width, height, ec->netwm.pid);
7965         return EINA_TRUE;
7966      }
7967
7968    if ((desk->geom.w == width) && (desk->geom.h == height))
7969      {
7970         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);
7971         return EINA_TRUE;
7972      }
7973
7974    /* set the base_output_resolution of the e_client */
7975    _e_client_base_output_resolution_set(ec, width, height);
7976
7977    ELOGF("POL_APPINFO", "USE base_output_resolution(%d,%d) pid:%d", ec, width, height, ec->netwm.pid);
7978
7979    return EINA_TRUE;
7980
7981 use_configured:
7982
7983    if ((desk->geom.w == configured_width) && (desk->geom.h == configured_height))
7984      {
7985         ELOGF("POL_APPINFO", "SKIP use configured_output_resolution (same with desk size:(%d,%d), pid:%d)", ec, configured_width, configured_height, ec->netwm.pid);
7986      }
7987    else
7988      {
7989         /* set the base_output_resolution of the e_client as a default */
7990         _e_client_base_output_resolution_set(ec, configured_width, configured_height);
7991      }
7992
7993    return EINA_TRUE;
7994 }
7995
7996 E_API Eina_Bool
7997 e_client_base_output_resolution_useful_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
7998 {
7999    int zx, zy, zw, zh;
8000    E_Zone *zone;
8001
8002    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
8003
8004    zone = e_comp_zone_find_by_ec(ec);
8005    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
8006
8007    e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
8008
8009    if (x) *x = zx;
8010    if (y) *y = zy;
8011    if (w) *w = zw;
8012    if (h) *h = zh;
8013
8014    if (ec->base_output_resolution.use)
8015      {
8016         if (w) *w = ec->base_output_resolution.w;
8017         if (h) *h = ec->base_output_resolution.h;
8018      }
8019
8020    return EINA_TRUE;
8021 }
8022
8023 E_API Eina_Bool
8024 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)
8025 {
8026    int zx, zy, zw, zh;
8027    E_Zone *zone;
8028
8029    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
8030
8031    zone = e_comp_zone_find_by_ec(ec);
8032    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
8033
8034    e_zone_desk_useful_geometry_get(zone, ec->desk, &zx, &zy, &zw, &zh, consider_obstacle_area);
8035
8036    if (x) *x = zx;
8037    if (y) *y = zy;
8038    if (w) *w = zw;
8039    if (h) *h = zh;
8040
8041    if (ec->base_output_resolution.use)
8042      {
8043         // TODO: Consider obstacle area
8044         if (w) *w = ec->base_output_resolution.w;
8045         if (h) *h = ec->base_output_resolution.h;
8046      }
8047
8048    return EINA_TRUE;
8049 }
8050
8051 /* change the base_output_resolution of the bind_ec by checking the base_output_resolution of provider_ec's appinfo */
8052 EINTERN Eina_Bool
8053 e_client_base_output_resolution_rsm_update(E_Client *bind_ec, E_Client *provider_ec)
8054 {
8055    E_Appinfo *epai = NULL;
8056    int configured_width, configured_height;
8057    int width, height;
8058    E_Desk *bind_ec_desk;
8059
8060    EINA_SAFETY_ON_NULL_RETURN_VAL(bind_ec, EINA_FALSE);
8061    EINA_SAFETY_ON_NULL_RETURN_VAL(provider_ec, EINA_FALSE);
8062
8063    bind_ec_desk = e_comp_desk_find_by_ec(bind_ec);
8064    EINA_SAFETY_ON_NULL_RETURN_VAL(bind_ec_desk, EINA_FALSE);
8065
8066   if (!e_config->configured_output_resolution.use) return EINA_TRUE;
8067
8068   configured_width = e_config->configured_output_resolution.w;
8069   configured_height = e_config->configured_output_resolution.h;
8070
8071   if (bind_ec->base_output_resolution.use)
8072     {
8073        ELOGF("POL_APPINFO", "DELETE EXISTED BINDER BASE SCREEN RESOLUTION... base_output_resolution is same with desk size:(%d,%d), bind_pid:%d", bind_ec,
8074              bind_ec->base_output_resolution.w, bind_ec->base_output_resolution.h, bind_ec->netwm.pid);
8075
8076        bind_ec->base_output_resolution.use = 0;
8077        bind_ec->base_output_resolution.w = 0;
8078        bind_ec->base_output_resolution.h = 0;
8079        e_client_transform_core_remove(bind_ec, bind_ec->base_output_resolution.transform);
8080        E_FREE_FUNC(bind_ec->base_output_resolution.transform, e_util_transform_del);
8081     }
8082
8083   if (!provider_ec->netwm.pid)
8084     {
8085        ELOGF("POL_APPINFO", "NO PROVIDER PID... USE configured_output_resolution(%d,%d) provider_pid:%d", provider_ec,
8086              configured_width, configured_height, provider_ec->netwm.pid);
8087        goto use_configured;
8088     }
8089
8090    epai = e_appinfo_find_with_pid(provider_ec->netwm.pid);
8091    if (!epai)
8092      {
8093         ELOGF("POL_APPINFO", "NO PROVIDER APPINFO... USE configured_output_resolution(%d,%d) provider_pid:%d", provider_ec,
8094               configured_width, configured_height, provider_ec->netwm.pid);
8095         goto use_configured;
8096      }
8097
8098    if (!e_appinfo_base_output_resolution_get(epai, &width, &height))
8099      {
8100         ELOGF("POL_APPINFO", "NO PROVIDER APPINFO BASE SCREEN RESOLUTION... USE configured_output_resolution(%d,%d) provider_pid:%d", provider_ec,
8101               configured_width, configured_height, provider_ec->netwm.pid);
8102         goto use_configured;
8103       }
8104
8105    if ((width == 0) && (height == 0))
8106      {
8107         ELOGF("POL_APPINFO", "NO PROVIDER WIDTH and HEIGHT... SKIP base_output_resolution due to size:(%d,%d) provider_pid:%d", provider_ec,
8108              width, height, provider_ec->netwm.pid);
8109         return EINA_TRUE;
8110      }
8111
8112    if ((bind_ec_desk->geom.w == width) && (bind_ec_desk->geom.h == height))
8113      {
8114         ELOGF("POL_APPINFO", "SKIP SET BINDER BASE SCREEN RESOLUTION... base_output_resolution is same with desk size:(%d,%d), bind_pid:%d", bind_ec,
8115             width, height, bind_ec->netwm.pid);
8116         return EINA_TRUE;
8117      }
8118
8119    /* set the base_output_resolution of the e_client */
8120    _e_client_base_output_resolution_set(bind_ec, width, height);
8121    e_client_base_output_resolution_transform_adjust(bind_ec);
8122
8123    ELOGF("POL_APPINFO", "USE BINDER base_output_resolution(%d,%d) bind_pid:%d", bind_ec, width, height, bind_ec->netwm.pid);
8124
8125    return EINA_TRUE;
8126
8127 use_configured:
8128
8129    if ((bind_ec_desk->geom.w == configured_width) && (bind_ec_desk->geom.h == configured_height))
8130      {
8131         ELOGF("POL_APPINFO", "SKIP BINDER use configured_output_resolution (same with desk size:(%d,%d), bind_pid:%d)", bind_ec,
8132              configured_width, configured_height, bind_ec->netwm.pid);
8133      }
8134    else
8135      {
8136         /* set the base_output_resolution of the e_client as a default */
8137         _e_client_base_output_resolution_set(bind_ec, configured_width, configured_height);
8138      }
8139
8140    return EINA_TRUE;
8141 }
8142
8143 /* tizen_move_resize */
8144 EINTERN Eina_Bool
8145 e_client_pending_geometry_has(E_Client *ec)
8146 {
8147    if (!eina_list_count(ec->surface_sync.pending_geometry))
8148      return EINA_FALSE;
8149
8150    return ec->surface_sync.wait_commit;
8151 }
8152
8153 EINTERN void
8154 e_client_pending_geometry_flush(E_Client *ec)
8155 {
8156    E_Client_Pending_Geometry *geo;
8157
8158    if (!eina_list_count(ec->surface_sync.pending_geometry))
8159      {
8160         EINA_LIST_FREE(ec->surface_sync.pending_geometry, geo)
8161           {
8162              E_FREE(geo);
8163           }
8164         ec->surface_sync.wait_commit = EINA_FALSE;
8165         ELOGF("POSSIZE", "pending geometry has flushed", ec);
8166      }
8167 }
8168
8169 EINTERN void
8170 e_client_pending_geometry_last_geometry_get(E_Client *ec, int *x, int *y, int *w, int *h)
8171 {
8172    Eina_List *l;
8173    E_Client_Pending_Geometry *geo;
8174    int gx = 0;
8175    int gy = 0;
8176    int gw = 0;
8177    int gh = 0;
8178
8179    EINA_LIST_REVERSE_FOREACH(ec->surface_sync.pending_geometry, l, geo)
8180      {
8181         gx = geo->x;
8182         gy = geo->y;
8183         gw = geo->w;
8184         gh = geo->h;
8185         break;
8186      }
8187
8188    if (x) *x = gx;
8189    if (y) *y = gy;
8190    if (w) *w = gw;
8191    if (h) *h = gh;
8192 }
8193
8194 E_API void
8195 e_client_frame_focus_set(E_Client *ec, Eina_Bool focus)
8196 {
8197    if (!ec) return;
8198    evas_object_focus_set(ec->frame, focus);
8199 }
8200
8201 EINTERN void
8202 e_client_frame_geometry_set(E_Client *ec, int x, int y, int w, int h)
8203 {
8204    if (!ec) return;
8205
8206    if (ec->internal || ec->input_only)
8207      {
8208         evas_object_geometry_set(ec->frame, x, y, w, h);
8209      }
8210    else
8211      {
8212         if ((ec->w != w) || (ec->h != h))
8213           {
8214              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);
8215              ec->move_after_resize = EINA_TRUE;
8216
8217              e_client_pos_set(ec, x, y);
8218              evas_object_resize(ec->frame, w, h);
8219           }
8220         else
8221           evas_object_geometry_set(ec->frame, x, y, w, h);
8222      }
8223 }
8224
8225 EAPI void
8226 e_client_util_move_resize_without_frame(E_Client *ec, int x, int y, int w, int h)
8227 {
8228    if (!ec) return;
8229
8230    if (ec->internal || ec->input_only)
8231      {
8232         e_client_util_move_without_frame(ec, x, y);
8233         e_client_util_resize_without_frame(ec, w, h);
8234      }
8235    else
8236      {
8237         if ((ec->w != w) || (ec->h != h))
8238           {
8239              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);
8240              ec->move_after_resize = EINA_TRUE;
8241
8242              e_comp_object_frame_xy_adjust(ec->frame, x, y, &x, &y);
8243              e_client_pos_set(ec, x, y);
8244              e_client_util_resize_without_frame(ec, w, h);
8245           }
8246         else
8247           {
8248              e_client_util_move_without_frame(ec, x, y);
8249              e_client_util_resize_without_frame(ec, w, h);
8250           }
8251      }
8252 }
8253
8254 E_API Eina_Bool
8255 e_client_layer_set(E_Client *ec,
8256                    E_Layer layer)
8257 {
8258    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
8259    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
8260    if (!ec->frame) return EINA_FALSE;
8261
8262    if (e_comp_canvas_client_layer_map(layer) == 9999)
8263      return EINA_FALSE; //invalid layer is not allowed
8264
8265    if (ec->desk_area.enable)
8266      {
8267         if (e_client_layer_set_by_desk_area(ec, layer))
8268           {
8269              // restack according to desk group rule
8270              e_desk_area_ec_rearrange(ec->desk_area.desk_area, ec);
8271              return EINA_TRUE;
8272           }
8273      }
8274    ec->desk_area.layer_backup = layer;
8275
8276    evas_object_layer_set(ec->frame, layer);
8277    if (ec->layer != layer)
8278      {
8279         /* check exceptional case */
8280         if ((ec->fullscreen) &&
8281             (ec->saved.layer != layer))
8282           {
8283              ELOGF("LAYER", "(%d) fail to backup at saved.layer for fullscreen", ec, layer);
8284              return EINA_FALSE;
8285           }
8286         // if e_comp_object fail to change ec->layer due to ec->layer_pending or block
8287         // leave log and apply ec->layer according to set
8288         // as a result it restores back to given layer when pending or block is free
8289         ELOGF("LAYER", "change layer from %d to %d if in case layer pending(%d) or block(%d)",
8290               ec, ec->layer, layer, ec->layer_pending, ec->layer_block);
8291         if (ec->layer_pending || ec->layer_block)
8292           {
8293              ec->layer = layer;
8294              return EINA_TRUE;
8295           }
8296      }
8297
8298    wl_signal_emit_mutable(&PRI(ec)->events.layer_set, NULL);
8299
8300    return EINA_TRUE;
8301 }
8302
8303 E_API E_Layer
8304 e_client_layer_get(E_Client *ec)
8305 {
8306    short layer;
8307
8308    E_OBJECT_CHECK_RETURN(ec, E_LAYER_BOTTOM);
8309    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, E_LAYER_BOTTOM);
8310    if (!ec->frame) return E_LAYER_BOTTOM;
8311
8312    layer = evas_object_layer_get(ec->frame);
8313    if (ec->layer != layer)
8314      {
8315         /* client could be on temperory layer while pending or block,
8316          * in that case, client restores back to ec->layer after pending/block finish */
8317         if (ec->layer_block || ec->layer_pending)
8318           return ec->layer;
8319
8320         /* otherwise, client is on unexpected layer */
8321         ELOGF("LAYER", "layer dismatch ec->layer %d | evas obj layer %d ",
8322               ec, ec->layer, layer);
8323
8324         if (e_comp_canvas_client_layer_map(layer) == 9999)
8325           return E_LAYER_BOTTOM; //not on E_LAYER_CLIENT
8326      }
8327
8328    return ec->layer;
8329 }
8330
8331 static void
8332 _e_client_desk_area_original_layer_save(E_Client *ec, E_Layer layer)
8333 {
8334    E_OBJECT_CHECK(ec);
8335    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
8336    ec->desk_area.layer_backup = layer;
8337 }
8338
8339 EINTERN Eina_Bool
8340 e_client_layer_set_by_desk_area(E_Client *ec, E_Layer layer)
8341 {
8342    E_Desk_Area *eda;
8343    E_Layer edg_layer;
8344    E_Layer org_layer;
8345
8346    if (!ec) return EINA_FALSE;
8347    if (!ec->frame) return EINA_FALSE;
8348    if (!ec->desk_area.enable) return EINA_FALSE;
8349    if (!ec->desk_area.desk_area) return EINA_FALSE;
8350
8351    eda = ec->desk_area.desk_area;
8352
8353    // save original layer
8354    _e_client_desk_area_original_layer_save(ec, layer);
8355
8356    // get desk_area layer
8357    edg_layer = (E_Layer)e_desk_area_layer_get(eda);
8358    org_layer = e_client_desk_area_original_layer_get(ec);
8359
8360    ELOGF("EDG", "layer_set by desk_area... layer:%d, org_layer:%d, new_layer:%d", ec, layer, org_layer, edg_layer);
8361    if (org_layer == edg_layer)
8362      {
8363         e_client_raise(ec);
8364      }
8365    else
8366      {
8367         evas_object_layer_set(ec->frame, edg_layer);
8368         if (edg_layer == ec->layer)
8369           e_client_raise(ec);
8370      }
8371
8372    return EINA_TRUE;
8373 }
8374
8375 EINTERN void
8376 e_client_desk_area_original_layer_restore(E_Client *ec)
8377 {
8378    if (!ec) return;
8379
8380    // Do we need to check ec->desk_area.enable?
8381    // if ec->desk_area.enable is true, then e_client_layer_set calls
8382    // e_desk_area_ec_layer_set(). that's too bad. :(
8383    // so, we MUST make a policy for ordering of the desk group layer restore
8384    // and the desk group enable.
8385    if (ec->desk_area.enable) return;
8386    e_client_layer_set(ec, ec->desk_area.layer_backup);
8387 }
8388
8389 EINTERN E_Layer
8390 e_client_desk_area_original_layer_get(E_Client *ec)
8391 {
8392    if (!ec) return E_LAYER_DESKTOP;
8393
8394    if (ec->desk_area.enable)
8395      return ec->desk_area.layer_backup;
8396    else
8397      return ec->layer;
8398 }
8399
8400 EINTERN Eina_Bool
8401 e_client_desk_area_client_layer_set(E_Client *ec, E_Desk_Area_Client_Layer edgc_layer)
8402 {
8403    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
8404    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
8405    if ((edgc_layer < E_DESK_AREA_CLIENT_LAYER_DESKTOP) ||
8406        (edgc_layer >= E_DESK_AREA_CLIENT_LAYER_MAX))
8407      return EINA_FALSE;
8408
8409    ec->desk_area.edgc_layer = edgc_layer;
8410    return EINA_TRUE;
8411 }
8412
8413 EINTERN E_Desk_Area_Client_Layer
8414 e_client_desk_area_client_layer_get(E_Client *ec)
8415 {
8416    E_OBJECT_CHECK_RETURN(ec, E_DESK_AREA_CLIENT_LAYER_DESKTOP);
8417
8418    return ec->desk_area.edgc_layer;
8419 }
8420
8421 EINTERN Eina_Bool
8422 e_client_desk_area_enable_set(E_Client *ec, Eina_Bool enable)
8423 {
8424    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
8425    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
8426
8427    ec->desk_area.enable = enable;
8428
8429    ELOGF("EDG", "Desk group enable set to %d", ec, enable);
8430    if (enable)
8431      {
8432         if (!ec->desk_area.transform)
8433           {
8434              ec->desk_area.transform = e_util_transform_new();
8435              e_util_transform_role_set(ec->desk_area.transform, "desk_area");
8436           }
8437      }
8438    else
8439      {
8440         if (ec->desk_area.transform)
8441           {
8442              e_util_transform_del(ec->desk_area.transform);
8443              ec->desk_area.transform = NULL;
8444           }
8445      }
8446
8447    e_desk_area_ec_update(ec->desk_area.desk_area, ec);
8448    return EINA_TRUE;
8449 }
8450
8451 //FIXME: use e_desk_area_ec_reassign(eda, ec) instead of this api
8452 E_API Eina_Bool
8453 e_client_desk_area_set(E_Client *ec, E_Desk_Area *eda)
8454 {
8455    E_Desk_Area *old_edg;
8456
8457    if (!ec) return EINA_FALSE;
8458
8459 #if 0 // if this is removed.. then below if (eda != old_edg) is removed also...
8460    if (ec->desk_area.desk_area == eda)
8461      return EINA_TRUE;
8462 #endif
8463
8464    ELOGF("EDG", "Desk Group Set (new:%p, old:%p)", ec, eda, ec->desk_area.desk_area);
8465    old_edg = ec->desk_area.desk_area;
8466    if (old_edg)
8467      e_desk_area_ec_remove(old_edg, ec);
8468
8469    ec->desk_area.desk_area = eda;
8470    e_desk_area_ec_add(eda, ec);
8471
8472 #if 0 // if this is removed.. then above if (ec->desk_area.desk_area == eda) is removed also...
8473    if (eda != old_edg)
8474 #endif
8475      {
8476         e_desk_area_ec_update(eda, ec);
8477         e_desk_area_ec_rearrange(ec->desk_area.desk_area, ec);
8478      }
8479
8480    return EINA_TRUE;
8481 }
8482
8483 static void
8484 _raise_between_sibling_under_parent(E_Client *ec)
8485 {
8486    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);
8487    e_client_stack_below(ec, ec->parent);
8488 }
8489
8490 static void
8491 _raise_between_sibling_on_parent(E_Client *ec)
8492 {
8493    E_Client *top_child = NULL;
8494    top_child = e_client_transient_child_top_get(ec->parent, EINA_FALSE);
8495    if (!top_child)
8496      {
8497         ELOGF("POL", "RAISE child window... Stack above on the parent (win:%zx, ec:%p)", ec, e_client_util_win_get(ec->parent), ec->parent);
8498         e_client_stack_above(ec, ec->parent);
8499      }
8500    else
8501      {
8502         if (top_child != ec)
8503           {
8504              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);
8505              e_client_stack_above(ec, top_child);
8506           }
8507         else
8508           ELOGF("POL", "RAISE child window between sibling... already on the top. STAY", ec);
8509      }
8510 }
8511
8512 static void
8513 _raise_belong_to_parent(E_Client *ec)
8514 {
8515    if (e_client_transient_policy_get(ec) == E_TRANSIENT_BELOW)
8516      _raise_between_sibling_under_parent(ec);
8517    else
8518      _raise_between_sibling_on_parent(ec);
8519 }
8520
8521 E_API void
8522 e_client_raise(E_Client *ec)
8523 {
8524    if (!ec) return;
8525
8526    if (ec->desk_area.enable)
8527      {
8528         E_Desk_Area *eda;
8529         eda = ec->desk_area.desk_area;
8530         if (eda)
8531           {
8532              e_desk_area_ec_raise(eda, ec);
8533              return;
8534           }
8535      }
8536
8537    if (ec->parent && e_client_is_belong_to_parent(ec))
8538      _raise_belong_to_parent(ec);
8539    else
8540      evas_object_raise(ec->frame);
8541
8542    wl_signal_emit_mutable(&PRI(ec)->events.raise, NULL);
8543 }
8544
8545 static void
8546 _e_client_transient_for_below_group_make(E_Client *ec, Eina_List **list)
8547 {
8548    // list : Head is the bottommost child
8549    E_Client *child;
8550    Eina_List *l;
8551
8552    if (!ec) return;
8553
8554    EINA_LIST_REVERSE_FOREACH(ec->transients, l, child)
8555      {
8556         if (!child) continue;
8557         if (e_client_transient_policy_get(child) != E_TRANSIENT_BELOW) continue;
8558         if (!e_client_is_belong_to_parent(child)) continue;
8559
8560         *list = eina_list_prepend(*list, child);
8561         _e_client_transient_for_group_make(child, list);
8562      }
8563 }
8564
8565 E_API E_Client *
8566 e_client_transient_child_bottom_get(E_Client *ec)
8567 {
8568    E_Client *bottom_ec = NULL;
8569    Eina_List *transient_below_list = NULL;
8570    Eina_List *l = NULL;
8571
8572    _e_client_transient_for_below_group_make(ec, &transient_below_list);
8573
8574    if (transient_below_list)
8575      {
8576         E_Client *temp_ec = NULL;
8577         E_Client *temp_ec2 = NULL;
8578
8579         E_CLIENT_FOREACH(temp_ec)
8580           {
8581              if (bottom_ec) break;
8582
8583              if (temp_ec == ec)
8584                {
8585                   bottom_ec = ec;
8586                   break;
8587                }
8588
8589              EINA_LIST_FOREACH(transient_below_list, l, temp_ec2)
8590                {
8591                   if (temp_ec == temp_ec2)
8592                     {
8593                        bottom_ec = temp_ec2;
8594                        break;
8595                     }
8596                }
8597           }
8598         eina_list_free(transient_below_list);
8599      }
8600    return bottom_ec;
8601 }
8602
8603 static void
8604 _lower_between_sibling_under_parent(E_Client *ec)
8605 {
8606    E_Client *bottom_child = NULL;
8607    bottom_child = e_client_transient_child_bottom_get(ec->parent);
8608    if (!bottom_child)
8609      {
8610         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);
8611         e_client_stack_below(ec, ec->parent);
8612      }
8613    else
8614      {
8615         if (bottom_child != ec)
8616           {
8617              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);
8618              e_client_stack_below(ec, bottom_child);
8619           }
8620         else
8621           ELOGF("POL", "LOWER child window between sibling... already under the bottom. STAY", ec);
8622      }
8623 }
8624
8625 static void
8626 _lower_between_sibling_on_parent(E_Client *ec)
8627 {
8628    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);
8629    e_client_stack_above(ec, ec->parent);
8630 }
8631
8632 static void
8633 _lower_belong_to_parent(E_Client *ec)
8634 {
8635    if (e_client_transient_policy_get(ec) == E_TRANSIENT_BELOW)
8636      _lower_between_sibling_under_parent(ec);
8637    else
8638      _lower_between_sibling_on_parent(ec);
8639 }
8640
8641 E_API void
8642 e_client_lower(E_Client *ec)
8643 {
8644    if (!ec) return;
8645
8646    if (ec->desk_area.enable)
8647      {
8648         E_Desk_Area *eda;
8649         eda = ec->desk_area.desk_area;
8650         if (eda)
8651           {
8652              e_desk_area_ec_lower(eda, ec);
8653 #ifdef REFACTOR_FOCUS_POLICY
8654             wl_signal_emit_mutable(&PRI(ec)->events.lower, NULL);
8655              _e_client_hook_call(E_CLIENT_HOOK_LOWER, ec);
8656 #endif
8657              return;
8658           }
8659      }
8660
8661    if (ec->parent && e_client_is_belong_to_parent(ec))
8662      _lower_belong_to_parent(ec);
8663    else
8664      evas_object_lower(ec->frame);
8665
8666 #ifdef REFACTOR_FOCUS_POLICY
8667    wl_signal_emit_mutable(&PRI(ec)->events.lower, NULL);
8668    _e_client_hook_call(E_CLIENT_HOOK_LOWER, ec);
8669 #endif
8670 }
8671
8672 E_API void
8673 e_client_stack_above(E_Client *ec, E_Client *above)
8674 {
8675    if (!ec) return;
8676    if (!ec->frame) return;
8677    if (!above) return;
8678    if (!above->frame) return;
8679
8680    if (ec->desk_area.enable)
8681      {
8682         E_Desk_Area *eda;
8683         eda = ec->desk_area.desk_area;
8684         if (eda)
8685           {
8686              e_desk_area_ec_stack_above(eda, ec, above);
8687              return;
8688           }
8689      }
8690
8691    evas_object_stack_above(ec->frame, above->frame);
8692
8693    wl_signal_emit_mutable(&PRI(ec)->events.stack_above, NULL);
8694 }
8695
8696 E_API void
8697 e_client_stack_below(E_Client *ec, E_Client *below)
8698 {
8699    if (!ec) return;
8700    if (!ec->frame) return;
8701    if (!below) return;
8702    if (!below->frame) return;
8703
8704    if (ec->desk_area.enable)
8705      {
8706         E_Desk_Area *eda;
8707         eda = ec->desk_area.desk_area;
8708         if (eda)
8709           {
8710              e_desk_area_ec_stack_below(eda, ec, below);
8711              return;
8712           }
8713      }
8714
8715    evas_object_stack_below(ec->frame, below->frame);
8716
8717    wl_signal_emit_mutable(&PRI(ec)->events.stack_below, NULL);
8718 }
8719
8720 E_API int
8721 e_client_show_pending_set(E_Client *ec)
8722 {
8723    if (!ec) return 0;
8724
8725    ec->show_pending.count++;
8726    ELOGF("E_CLIENT", "SET show_pending. (count:%d, run:%d)", ec, ec->show_pending.count, ec->show_pending.running);
8727    return ec->show_pending.count;
8728 }
8729
8730 E_API int
8731 e_client_show_pending_unset(E_Client *ec)
8732 {
8733    if (!ec) return 0;
8734    if (ec->show_pending.count <= 0) return 0;
8735
8736    ec->show_pending.count--;
8737    ELOGF("E_CLIENT", "UNSET show_pending. (count:%d, run:%d)", ec, ec->show_pending.count, ec->show_pending.running);
8738    if (ec->show_pending.count == 0 && ec->show_pending.running)
8739      {
8740         ec->show_pending.running = EINA_FALSE;
8741         if (ec->frame)
8742           {
8743              ELOGF("E_CLIENT", "evas_object_show by unset show_pending", ec);
8744              evas_object_show(ec->frame);
8745              //e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
8746              EC_CHANGED(ec);
8747           }
8748      }
8749
8750    return ec->show_pending.count;
8751 }
8752
8753 static Eina_Bool
8754 _e_client_surface_tree_foreach_helper(E_Client *ec, E_Client_Surface_Tree_Foreach func, void *data)
8755 {
8756    E_Client *subc;
8757    Eina_List *l, *ll;
8758    Eina_Bool res = EINA_TRUE;
8759    E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
8760
8761    if (!cdata)
8762      return res;
8763
8764    EINA_LIST_FOREACH_SAFE(cdata->sub.below_list, l, ll, subc)
8765      {
8766         res = _e_client_surface_tree_foreach_helper(subc, func, data);
8767         if (!res)
8768           break;
8769      }
8770
8771    if (res)
8772      {
8773         res = func(data, ec);
8774         if (res)
8775           {
8776              EINA_LIST_FOREACH_SAFE(cdata->sub.list, l, ll, subc)
8777                {
8778                   res = _e_client_surface_tree_foreach_helper(subc,
8779                                                               func,
8780                                                               data);
8781                   if (!res)
8782                     break;
8783                }
8784           }
8785      }
8786
8787    return res;
8788 }
8789
8790 E_API void
8791 e_client_surface_tree_foreach(E_Client *ec, E_Client_Surface_Tree_Foreach func, void *data)
8792 {
8793    EINA_SAFETY_ON_NULL_RETURN(ec);
8794    EINA_SAFETY_ON_NULL_RETURN(func);
8795
8796    _e_client_surface_tree_foreach_helper(ec, func, data);
8797 }
8798
8799 EINTERN E_Comp_Wl_Client_Data *
8800 e_client_cdata_new(E_Client *ec)
8801 {
8802    E_Comp_Wl_Client_Data *cdata;
8803
8804    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
8805
8806    if (!(cdata = E_NEW(E_Comp_Wl_Client_Data, 1)))
8807      {
8808         ERR("Could not allocate new E_Comp_Wl_Client_Data structure");
8809         return NULL;
8810      }
8811    ec->comp_data = cdata;
8812
8813    return cdata;
8814 }
8815
8816 EINTERN void
8817 e_client_cdata_free(E_Client *ec)
8818 {
8819   EINA_SAFETY_ON_NULL_RETURN(ec);
8820   if (!ec->comp_data) return;
8821
8822   E_FREE(ec->comp_data);
8823 }
8824
8825 EINTERN E_Comp_Wl_Client_Data *
8826 e_client_cdata_get(E_Client *ec)
8827 {
8828    if (!ec) return NULL;
8829
8830    return ec->comp_data;
8831 }
8832
8833 EINTERN Eina_Bool
8834 e_client_map_set(E_Client *ec, E_Map *em)
8835 {
8836    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
8837
8838    return e_map_set_to_comp_object(em, ec->frame);
8839 }
8840
8841 E_API E_Map *
8842 e_client_map_get(const E_Client *ec)
8843 {
8844    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
8845
8846    return e_map_get_from_comp_object(ec->frame);
8847 }
8848
8849 EINTERN Eina_Bool
8850 e_client_map_enable_set(E_Client *ec, Eina_Bool enable)
8851 {
8852    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
8853    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, EINA_FALSE);
8854
8855    evas_object_map_enable_set(ec->frame, enable);
8856
8857    return EINA_TRUE;
8858 }
8859
8860 EINTERN void
8861 e_client_belong_to_parent_set(E_Client *ec, Eina_Bool set)
8862 {
8863    if (!ec) return;
8864    ec->belong_to_parent = set;
8865 }
8866
8867 EINTERN Eina_Bool
8868 e_client_is_belong_to_parent(E_Client *ec)
8869 {
8870    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
8871    return ec->belong_to_parent;
8872 }
8873
8874 EINTERN void
8875 e_client_transient_policy_set(E_Client *ec, E_Transient policy)
8876 {
8877    if (!ec) return;
8878    ec->transient_policy = policy;
8879 }
8880
8881 E_API E_Transient
8882 e_client_transient_policy_get(E_Client *ec)
8883 {
8884    if (!ec) return E_TRANSIENT_ABOVE;
8885    return ec->transient_policy;
8886 }
8887
8888 EINTERN void
8889 e_client_resize_object_create_cb_set(E_Client_Resize_Object_Create_Cb cb)
8890 {
8891    if (_e_client_resize_object_create_cb && cb)
8892      CRI("ATTEMPTING TO OVERWRITE EXISTING CLIENT RESIZE OBJECT CREATE HOOK!!!");
8893    _e_client_resize_object_create_cb = cb;
8894 }
8895
8896 EINTERN void
8897 e_client_resize_unit_size_set(E_Client *ec, unsigned int unit_size)
8898 {
8899    if (!ec) return;
8900
8901    // FYI, we consider 0 and 1 to be the same value as a default unit size.
8902    ec->manage_resize.unit_size = unit_size;
8903 }
8904
8905 EINTERN void
8906 e_client_desk_zoom_enable_set(E_Client *ec, Eina_Bool enable)
8907 {
8908    if (!ec) return;
8909    ec->desk_zoom.enable = enable;
8910 }
8911
8912 EINTERN Eina_Bool
8913 e_client_desk_zoom_enable_get(E_Client *ec)
8914 {
8915    if (!ec) return EINA_FALSE;
8916    return ec->desk_zoom.enable;
8917 }
8918
8919 EINTERN void
8920 e_client_layout_apply(E_Client *ec, Eina_Bool apply)
8921 {
8922    if (!ec) return;
8923    ec->apply_layout = apply;
8924 }
8925
8926 EINTERN Eina_Bool
8927 e_client_is_layout_apply(E_Client *ec)
8928 {
8929    if (!ec) return EINA_FALSE;
8930    return ec->apply_layout;
8931 }
8932
8933 E_API E_Client *
8934 e_client_from_surface_resource(struct wl_resource *surface_resource)
8935 {
8936    EINA_SAFETY_ON_NULL_RETURN_VAL(surface_resource, NULL);
8937
8938    return e_comp_wl_util_client_from_surface_resource(surface_resource);
8939 }
8940
8941 EINTERN void
8942 e_client_fps_update(E_Client *ec)
8943 {
8944    double dt;
8945    double tim;
8946
8947    EINA_SAFETY_ON_NULL_RETURN(ec);
8948
8949    if (!ec->fps.enabled) return;
8950
8951    tim = ecore_time_get();
8952
8953    dt = tim - ec->fps.frametimes[0];
8954
8955    ec->fps.frametimes[0] = tim;
8956    ec->fps.time += dt;
8957    ec->fps.cframes++;
8958
8959    if (ec->fps.lapse == 0.0)
8960      {
8961         ec->fps.lapse = tim;
8962         ec->fps.flapse = ec->fps.cframes;
8963      }
8964    else if ((tim - ec->fps.lapse) >= 0.5)
8965      {
8966         ec->fps.fps = (ec->fps.cframes - ec->fps.flapse) /
8967                       (tim - ec->fps.lapse);
8968         ec->fps.lapse = tim;
8969         ec->fps.flapse = ec->fps.cframes;
8970         ec->fps.time = 0.0;
8971      }
8972 }
8973
8974 EINTERN Eina_Bool
8975 e_client_fps_get(E_Client *ec, double *fps)
8976 {
8977    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
8978
8979    if (ec->fps.old_fps == ec->fps.fps)
8980      return EINA_FALSE;
8981
8982    if (ec->fps.fps > 0.0)
8983      {
8984         *fps = ec->fps.fps;
8985         ec->fps.old_fps = ec->fps.fps;
8986         return EINA_TRUE;
8987      }
8988
8989    return EINA_FALSE;
8990 }
8991
8992 EINTERN void
8993 e_client_fps_enable(E_Client *ec, Eina_Bool enable)
8994 {
8995    EINA_SAFETY_ON_NULL_RETURN(ec);
8996
8997    ec->fps.enabled = enable;
8998 }
8999
9000 EINTERN Eina_Bool
9001 e_client_explicit_sync_get(E_Client *ec)
9002 {
9003    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
9004
9005    return ec->explicit_sync;
9006 }
9007
9008 EINTERN Eina_Bool
9009 e_client_explicit_sync_set(E_Client *ec, Eina_Bool enable)
9010 {
9011    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
9012
9013    ec->explicit_sync = enable;
9014
9015    return EINA_TRUE;
9016 }
9017
9018 EINTERN int
9019 e_client_explicit_sync_acquire_fence_fd_get(E_Client *ec)
9020 {
9021    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, -1);
9022
9023    return ec->acquire_fence_fd;
9024 }
9025
9026 EINTERN Eina_Bool
9027 e_client_explicit_sync_acquire_fence_fd_set(E_Client *ec, int fd)
9028 {
9029   EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
9030
9031   ec->acquire_fence_fd = fd;
9032
9033   return EINA_TRUE;
9034 }
9035
9036 #ifdef REFACTOR_ZONE_DESK
9037 EINTERN Eina_Bool
9038 e_client_intercept_hook_auto_placement_call(E_Client *ec)
9039 {
9040   // no need to call the intercept hook if ec is NULL.
9041   if (!ec) return EINA_FALSE;
9042
9043   if (!_e_client_intercept_hook_call(E_CLIENT_INTERCEPT_HOOK_AUTO_PLACEMENT, ec))
9044     {
9045        ELOGF("FOCUS", "E_CLIENT_INTERCEPT_HOOK_AUTO_PLACEMENT Intercepted.", ec);
9046        return EINA_TRUE;
9047     }
9048
9049   return EINA_FALSE;
9050 }
9051
9052 EINTERN void
9053 e_client_iconify_event_send(E_Client *ec)
9054 {
9055    EINA_SAFETY_ON_NULL_RETURN(ec);
9056
9057    _e_client_event_simple(ec, E_EVENT_CLIENT_ICONIFY);
9058 }
9059
9060 EINTERN void
9061 e_client_uniconify_event_send(E_Client *ec)
9062 {
9063    EINA_SAFETY_ON_NULL_RETURN(ec);
9064
9065    _e_client_event_simple(ec, E_EVENT_CLIENT_UNICONIFY);
9066 }
9067 #endif
9068
9069 EINTERN void
9070 e_client_eval_pre_fetch_listener_add(E_Client *ec, struct wl_listener *listener)
9071 {
9072    API_ENTRY;
9073    wl_signal_add(&priv->events.eval_pre_fetch, listener);
9074 }
9075
9076 EINTERN struct wl_listener *
9077 e_client_eval_pre_fetch_listener_get(E_Client *ec, wl_notify_func_t notify)
9078 {
9079    API_ENTRY_VAL(NULL);
9080    return wl_signal_get(&priv->events.eval_pre_fetch, notify);
9081 }
9082
9083 EINTERN void
9084 e_client_eval_fetch_listener_add(E_Client *ec, struct wl_listener *listener)
9085 {
9086    API_ENTRY;
9087    wl_signal_add(&priv->events.eval_fetch, listener);
9088 }
9089
9090 EINTERN struct wl_listener *
9091 e_client_eval_fetch_listener_get(E_Client *ec, wl_notify_func_t notify)
9092 {
9093    API_ENTRY_VAL(NULL);
9094    return wl_signal_get(&priv->events.eval_fetch, notify);
9095 }
9096
9097 EINTERN void
9098 e_client_eval_pre_post_fetch_listener_add(E_Client *ec, struct wl_listener *listener)
9099 {
9100    API_ENTRY;
9101    wl_signal_add(&priv->events.eval_pre_post_fetch, listener);
9102 }
9103
9104 EINTERN struct wl_listener *
9105 e_client_eval_pre_post_fetch_listener_get(E_Client *ec, wl_notify_func_t notify)
9106 {
9107    API_ENTRY_VAL(NULL);
9108    return wl_signal_get(&priv->events.eval_pre_post_fetch, notify);
9109 }
9110
9111 EINTERN void
9112 e_client_eval_post_fetch_listener_add(E_Client *ec, struct wl_listener *listener)
9113 {
9114    API_ENTRY;
9115    wl_signal_add(&priv->events.eval_post_fetch, listener);
9116 }
9117
9118 EINTERN struct wl_listener *
9119 e_client_eval_post_fetch_listener_get(E_Client *ec, wl_notify_func_t notify)
9120 {
9121    API_ENTRY_VAL(NULL);
9122    return wl_signal_get(&priv->events.eval_post_fetch, notify);
9123 }
9124
9125 EINTERN void
9126 e_client_eval_pre_frame_assign_listener_add(E_Client *ec, struct wl_listener *listener)
9127 {
9128    API_ENTRY;
9129    wl_signal_add(&priv->events.eval_pre_frame_assign, listener);
9130 }
9131
9132 EINTERN struct wl_listener *
9133 e_client_eval_pre_frame_assign_listener_get(E_Client *ec, wl_notify_func_t notify)
9134 {
9135    API_ENTRY_VAL(NULL);
9136    return wl_signal_get(&priv->events.eval_pre_frame_assign, notify);
9137 }
9138
9139 EINTERN void
9140 e_client_eval_post_frame_assign_listener_add(E_Client *ec, struct wl_listener *listener)
9141 {
9142    API_ENTRY;
9143    wl_signal_add(&priv->events.eval_post_frame_assign, listener);
9144 }
9145
9146 EINTERN struct wl_listener *
9147 e_client_eval_post_frame_assign_listener_get(E_Client *ec, wl_notify_func_t notify)
9148 {
9149    API_ENTRY_VAL(NULL);
9150    return wl_signal_get(&priv->events.eval_post_frame_assign, notify);
9151 }
9152
9153 EINTERN void
9154 e_client_eval_pre_new_client_listener_add(E_Client *ec, struct wl_listener *listener)
9155 {
9156    API_ENTRY;
9157    wl_signal_add(&priv->events.eval_pre_new_client, listener);
9158 }
9159
9160 EINTERN struct wl_listener *
9161 e_client_eval_pre_new_client_listener_get(E_Client *ec, wl_notify_func_t notify)
9162 {
9163    API_ENTRY_VAL(NULL);
9164    return wl_signal_get(&priv->events.eval_pre_new_client, notify);
9165 }
9166
9167 EINTERN void
9168 e_client_eval_post_new_client_listener_add(E_Client *ec, struct wl_listener *listener)
9169 {
9170    API_ENTRY;
9171    wl_signal_add(&priv->events.eval_post_new_client, listener);
9172 }
9173
9174 EINTERN struct wl_listener *
9175 e_client_eval_post_new_client_listener_get(E_Client *ec, wl_notify_func_t notify)
9176 {
9177    API_ENTRY_VAL(NULL);
9178    return wl_signal_get(&priv->events.eval_post_new_client, notify);
9179 }
9180
9181 EINTERN void
9182 e_client_eval_visibility_listener_add(E_Client *ec, struct wl_listener *listener)
9183 {
9184    API_ENTRY;
9185    wl_signal_add(&priv->events.eval_visibility, listener);
9186 }
9187
9188 EINTERN struct wl_listener *
9189 e_client_eval_visibility_listener_get(E_Client *ec, wl_notify_func_t notify)
9190 {
9191    API_ENTRY_VAL(NULL);
9192    return wl_signal_get(&priv->events.eval_visibility, notify);
9193 }
9194
9195 EINTERN void
9196 e_client_eval_visibility_end_listener_add(E_Client *ec, struct wl_listener *listener)
9197 {
9198    API_ENTRY;
9199    wl_signal_add(&priv->events.eval_visibility_end, listener);
9200 }
9201
9202 EINTERN struct wl_listener *
9203 e_client_eval_visibility_end_listener_get(E_Client *ec, wl_notify_func_t notify)
9204 {
9205    API_ENTRY_VAL(NULL);
9206    return wl_signal_get(&priv->events.eval_visibility_end, notify);
9207 }
9208
9209 EINTERN void
9210 e_client_eval_end_listener_add(E_Client *ec, struct wl_listener *listener)
9211 {
9212    API_ENTRY;
9213    wl_signal_add(&priv->events.eval_end, listener);
9214 }
9215
9216 EINTERN struct wl_listener *
9217 e_client_eval_end_listener_get(E_Client *ec, wl_notify_func_t notify)
9218 {
9219    API_ENTRY_VAL(NULL);
9220    return wl_signal_get(&priv->events.eval_end, notify);
9221 }
9222
9223 EINTERN void
9224 e_client_move_begin_listener_add(E_Client *ec, struct wl_listener *listener)
9225 {
9226    API_ENTRY;
9227    wl_signal_add(&priv->events.move_begin, listener);
9228 }
9229
9230 EINTERN struct wl_listener *
9231 e_client_move_begin_listener_get(E_Client *ec, wl_notify_func_t notify)
9232 {
9233    API_ENTRY_VAL(NULL);
9234    return wl_signal_get(&priv->events.move_begin, notify);
9235 }
9236
9237 EINTERN void
9238 e_client_move_update_listener_add(E_Client *ec, struct wl_listener *listener)
9239 {
9240    API_ENTRY;
9241    wl_signal_add(&priv->events.move_update, listener);
9242 }
9243
9244 EINTERN struct wl_listener *
9245 e_client_move_update_listener_get(E_Client *ec, wl_notify_func_t notify)
9246 {
9247    API_ENTRY_VAL(NULL);
9248    return wl_signal_get(&priv->events.move_update, notify);
9249 }
9250
9251 EINTERN void
9252 e_client_move_end_listener_add(E_Client *ec, struct wl_listener *listener)
9253 {
9254    API_ENTRY;
9255    wl_signal_add(&priv->events.move_end, listener);
9256 }
9257
9258 EINTERN struct wl_listener *
9259 e_client_move_end_listener_get(E_Client *ec, wl_notify_func_t notify)
9260 {
9261    API_ENTRY_VAL(NULL);
9262    return wl_signal_get(&priv->events.move_end, notify);
9263 }
9264
9265 EINTERN void
9266 e_client_move_resize_begin_listener_add(E_Client *ec, struct wl_listener *listener)
9267 {
9268    API_ENTRY;
9269    wl_signal_add(&priv->events.move_resize_begin, listener);
9270 }
9271
9272 EINTERN struct wl_listener *
9273 e_client_move_resize_begin_listener_get(E_Client *ec, wl_notify_func_t notify)
9274 {
9275    API_ENTRY_VAL(NULL);
9276    return wl_signal_get(&priv->events.move_resize_begin, notify);
9277 }
9278
9279 EINTERN void
9280 e_client_move_resize_update_listener_add(E_Client *ec, struct wl_listener *listener)
9281 {
9282    API_ENTRY;
9283    wl_signal_add(&priv->events.move_resize_update, listener);
9284 }
9285
9286 EINTERN struct wl_listener *
9287 e_client_move_resize_update_listener_get(E_Client *ec, wl_notify_func_t notify)
9288 {
9289    API_ENTRY_VAL(NULL);
9290    return wl_signal_get(&priv->events.move_resize_update, notify);
9291 }
9292
9293 EINTERN void
9294 e_client_move_resize_end_listener_add(E_Client *ec, struct wl_listener *listener)
9295 {
9296    API_ENTRY;
9297    wl_signal_add(&priv->events.move_resize_end, listener);
9298 }
9299
9300 EINTERN struct wl_listener *
9301 e_client_move_resize_end_listener_get(E_Client *ec, wl_notify_func_t notify)
9302 {
9303    API_ENTRY_VAL(NULL);
9304    return wl_signal_get(&priv->events.move_resize_end, notify);
9305 }
9306
9307 EINTERN void
9308 e_client_destroy_listener_add(E_Client *ec, struct wl_listener *listener)
9309 {
9310    API_ENTRY;
9311    wl_signal_add(&priv->events.destroy, listener);
9312 }
9313
9314 EINTERN struct wl_listener *
9315 e_client_destroy_listener_get(E_Client *ec, wl_notify_func_t notify)
9316 {
9317    API_ENTRY_VAL(NULL);
9318    return wl_signal_get(&priv->events.destroy, notify);
9319 }
9320
9321 EINTERN void
9322 e_client_new_client_listener_add(E_Client *ec, struct wl_listener *listener)
9323 {
9324    API_ENTRY;
9325    wl_signal_add(&priv->events.new_client, listener);
9326 }
9327
9328 EINTERN struct wl_listener *
9329 e_client_new_client_listener_get(E_Client *ec, wl_notify_func_t notify)
9330 {
9331    API_ENTRY_VAL(NULL);
9332    return wl_signal_get(&priv->events.new_client, notify);
9333 }
9334
9335 EINTERN void
9336 e_client_new_client_post_listener_add(E_Client *ec, struct wl_listener *listener)
9337 {
9338    API_ENTRY;
9339    wl_signal_add(&priv->events.new_client_post, listener);
9340 }
9341
9342 EINTERN struct wl_listener *
9343 e_client_new_client_post_listener_get(E_Client *ec, wl_notify_func_t notify)
9344 {
9345    API_ENTRY_VAL(NULL);
9346    return wl_signal_get(&priv->events.new_client_post, notify);
9347 }
9348
9349 EINTERN void
9350 e_client_unredirect_listener_add(E_Client *ec, struct wl_listener *listener)
9351 {
9352    API_ENTRY;
9353    wl_signal_add(&priv->events.unredirect, listener);
9354 }
9355
9356 EINTERN struct wl_listener *
9357 e_client_unredirect_listener_get(E_Client *ec, wl_notify_func_t notify)
9358 {
9359    API_ENTRY_VAL(NULL);
9360    return wl_signal_get(&priv->events.unredirect, notify);
9361 }
9362
9363 EINTERN void
9364 e_client_redirect_listener_add(E_Client *ec, struct wl_listener *listener)
9365 {
9366    API_ENTRY;
9367    wl_signal_add(&priv->events.redirect, listener);
9368 }
9369
9370 EINTERN struct wl_listener *
9371 e_client_redirect_listener_get(E_Client *ec, wl_notify_func_t notify)
9372 {
9373    API_ENTRY_VAL(NULL);
9374    return wl_signal_get(&priv->events.redirect, notify);
9375 }
9376
9377 EINTERN void
9378 e_client_aux_hint_change_listener_add(E_Client *ec, struct wl_listener *listener)
9379 {
9380    API_ENTRY;
9381    wl_signal_add(&priv->events.aux_hint_change, listener);
9382 }
9383
9384 EINTERN struct wl_listener *
9385 e_client_aux_hint_change_listener_get(E_Client *ec, wl_notify_func_t notify)
9386 {
9387    API_ENTRY_VAL(NULL);
9388    return wl_signal_get(&priv->events.aux_hint_change, notify);
9389 }
9390
9391 EINTERN void
9392 e_client_window_role_change_listener_add(E_Client *ec, struct wl_listener *listener)
9393 {
9394    API_ENTRY;
9395    wl_signal_add(&priv->events.window_role_change, listener);
9396 }
9397
9398 EINTERN struct wl_listener *
9399 e_client_window_role_change_listener_get(E_Client *ec, wl_notify_func_t notify)
9400 {
9401    API_ENTRY_VAL(NULL);
9402    return wl_signal_get(&priv->events.window_role_change, notify);
9403 }
9404
9405 EINTERN void
9406 e_client_transform_change_listener_add(E_Client *ec, struct wl_listener *listener)
9407 {
9408    API_ENTRY;
9409    wl_signal_add(&priv->events.transform_change, listener);
9410 }
9411
9412 EINTERN struct wl_listener *
9413 e_client_transform_change_listener_get(E_Client *ec, wl_notify_func_t notify)
9414 {
9415    API_ENTRY_VAL(NULL);
9416    return wl_signal_get(&priv->events.transform_change, notify);
9417 }
9418
9419 EINTERN void
9420 e_client_activate_done_listener_add(E_Client *ec, struct wl_listener *listener)
9421 {
9422    API_ENTRY;
9423    wl_signal_add(&priv->events.activate_done, listener);
9424 }
9425
9426 EINTERN struct wl_listener *
9427 e_client_activate_done_listener_get(E_Client *ec, wl_notify_func_t notify)
9428 {
9429    API_ENTRY_VAL(NULL);
9430    return wl_signal_get(&priv->events.activate_done, notify);
9431 }
9432
9433 EINTERN void
9434 e_client_mouse_in_listener_add(E_Client *ec, struct wl_listener *listener)
9435 {
9436    API_ENTRY;
9437    wl_signal_add(&priv->events.mouse_in, listener);
9438 }
9439
9440 EINTERN struct wl_listener *
9441 e_client_mouse_in_listener_get(E_Client *ec, wl_notify_func_t notify)
9442 {
9443    API_ENTRY_VAL(NULL);
9444    return wl_signal_get(&priv->events.mouse_in, notify);
9445 }
9446
9447 EINTERN void
9448 e_client_mouse_out_listener_add(E_Client *ec, struct wl_listener *listener)
9449 {
9450    API_ENTRY;
9451    wl_signal_add(&priv->events.mouse_out, listener);
9452 }
9453
9454 EINTERN struct wl_listener *
9455 e_client_mouse_out_listener_get(E_Client *ec, wl_notify_func_t notify)
9456 {
9457    API_ENTRY_VAL(NULL);
9458    return wl_signal_get(&priv->events.mouse_out, notify);
9459 }
9460
9461 EINTERN void
9462 e_client_mouse_down_listener_add(E_Client *ec, struct wl_listener *listener)
9463 {
9464    API_ENTRY;
9465    wl_signal_add(&priv->events.mouse_down, listener);
9466 }
9467
9468 EINTERN struct wl_listener *
9469 e_client_mouse_down_listener_get(E_Client *ec, wl_notify_func_t notify)
9470 {
9471    API_ENTRY_VAL(NULL);
9472    return wl_signal_get(&priv->events.mouse_down, notify);
9473 }
9474
9475 EINTERN void
9476 e_client_focus_set_listener_add(E_Client *ec, struct wl_listener *listener)
9477 {
9478    API_ENTRY;
9479    wl_signal_add(&priv->events.focus_set, listener);
9480 }
9481
9482 EINTERN struct wl_listener *
9483 e_client_focus_set_listener_get(E_Client *ec, wl_notify_func_t notify)
9484 {
9485    API_ENTRY_VAL(NULL);
9486    return wl_signal_get(&priv->events.focus_set, notify);
9487 }
9488
9489 EINTERN void
9490 e_client_focus_unset_listener_add(E_Client *ec, struct wl_listener *listener)
9491 {
9492    API_ENTRY;
9493    wl_signal_add(&priv->events.focus_unset, listener);
9494 }
9495
9496 EINTERN struct wl_listener *
9497 e_client_focus_unset_listener_get(E_Client *ec, wl_notify_func_t notify)
9498 {
9499    API_ENTRY_VAL(NULL);
9500    return wl_signal_get(&priv->events.focus_unset, notify);
9501 }
9502
9503 EINTERN void
9504 e_client_focus_defer_set_listener_add(E_Client *ec, struct wl_listener *listener)
9505 {
9506    API_ENTRY;
9507    wl_signal_add(&priv->events.focus_defer_set, listener);
9508 }
9509
9510 EINTERN struct wl_listener *
9511 e_client_focus_defer_set_listener_get(E_Client *ec, wl_notify_func_t notify)
9512 {
9513    API_ENTRY_VAL(NULL);
9514    return wl_signal_get(&priv->events.focus_defer_set, notify);
9515 }
9516
9517 EINTERN void
9518 e_client_focus_latest_set_listener_add(E_Client *ec, struct wl_listener *listener)
9519 {
9520    API_ENTRY;
9521    wl_signal_add(&priv->events.focus_latest_set, listener);
9522 }
9523
9524 EINTERN struct wl_listener *
9525 e_client_focus_latest_set_listener_get(E_Client *ec, wl_notify_func_t notify)
9526 {
9527    API_ENTRY_VAL(NULL);
9528    return wl_signal_get(&priv->events.focus_latest_set, notify);
9529 }
9530
9531 EINTERN void
9532 e_client_iconify_listener_add(E_Client *ec, struct wl_listener *listener)
9533 {
9534    API_ENTRY;
9535    wl_signal_add(&priv->events.iconify, listener);
9536 }
9537
9538 EINTERN struct wl_listener *
9539 e_client_iconify_listener_get(E_Client *ec, wl_notify_func_t notify)
9540 {
9541    API_ENTRY_VAL(NULL);
9542    return wl_signal_get(&priv->events.iconify, notify);
9543 }
9544
9545 EINTERN void
9546 e_client_uniconify_listener_add(E_Client *ec, struct wl_listener *listener)
9547 {
9548    API_ENTRY;
9549    wl_signal_add(&priv->events.uniconify, listener);
9550 }
9551
9552 EINTERN struct wl_listener *
9553 e_client_uniconify_listener_get(E_Client *ec, wl_notify_func_t notify)
9554 {
9555    API_ENTRY_VAL(NULL);
9556    return wl_signal_get(&priv->events.uniconify, notify);
9557 }
9558
9559 EINTERN void
9560 e_client_maximize_listener_add(E_Client *ec, struct wl_listener *listener)
9561 {
9562    API_ENTRY;
9563    wl_signal_add(&priv->events.maximize, listener);
9564 }
9565
9566 EINTERN struct wl_listener *
9567 e_client_maximize_listener_get(E_Client *ec, wl_notify_func_t notify)
9568 {
9569    API_ENTRY_VAL(NULL);
9570    return wl_signal_get(&priv->events.maximize, notify);
9571 }
9572
9573 EINTERN void
9574 e_client_unmaximize_listener_add(E_Client *ec, struct wl_listener *listener)
9575 {
9576    API_ENTRY;
9577    wl_signal_add(&priv->events.unmaximize, listener);
9578 }
9579
9580 EINTERN struct wl_listener *
9581 e_client_unmaximize_listener_get(E_Client *ec, wl_notify_func_t notify)
9582 {
9583    API_ENTRY_VAL(NULL);
9584    return wl_signal_get(&priv->events.unmaximize, notify);
9585 }
9586
9587 EINTERN void
9588 e_client_fullscreen_pre_listener_add(E_Client *ec, struct wl_listener *listener)
9589 {
9590    API_ENTRY;
9591    wl_signal_add(&priv->events.fullscreen_pre, listener);
9592 }
9593
9594 EINTERN struct wl_listener *
9595 e_client_fullscreen_pre_listener_get(E_Client *ec, wl_notify_func_t notify)
9596 {
9597    API_ENTRY_VAL(NULL);
9598    return wl_signal_get(&priv->events.fullscreen_pre, notify);
9599 }
9600
9601 EINTERN void
9602 e_client_fullscreen_listener_add(E_Client *ec, struct wl_listener *listener)
9603 {
9604    API_ENTRY;
9605    wl_signal_add(&priv->events.fullscreen, listener);
9606 }
9607
9608 EINTERN struct wl_listener *
9609 e_client_fullscreen_listener_get(E_Client *ec, wl_notify_func_t notify)
9610 {
9611    API_ENTRY_VAL(NULL);
9612    return wl_signal_get(&priv->events.fullscreen, notify);
9613 }
9614
9615 EINTERN void
9616 e_client_unfullscreen_listener_add(E_Client *ec, struct wl_listener *listener)
9617 {
9618    API_ENTRY;
9619    wl_signal_add(&priv->events.unfullscreen, listener);
9620 }
9621
9622 EINTERN struct wl_listener *
9623 e_client_unfullscreen_listener_get(E_Client *ec, wl_notify_func_t notify)
9624 {
9625    API_ENTRY_VAL(NULL);
9626    return wl_signal_get(&priv->events.unfullscreen, notify);
9627 }
9628
9629 EINTERN void
9630 e_client_move_listener_add(E_Client *ec, struct wl_listener *listener)
9631 {
9632    API_ENTRY;
9633    wl_signal_add(&priv->events.move, listener);
9634 }
9635
9636 EINTERN struct wl_listener *
9637 e_client_move_listener_get(E_Client *ec, wl_notify_func_t notify)
9638 {
9639    API_ENTRY_VAL(NULL);
9640    return wl_signal_get(&priv->events.move, notify);
9641 }
9642
9643 EINTERN void
9644 e_client_raise_listener_add(E_Client *ec, struct wl_listener *listener)
9645 {
9646    API_ENTRY;
9647    wl_signal_add(&priv->events.raise, listener);
9648 }
9649
9650 EINTERN struct wl_listener *
9651 e_client_raise_listener_get(E_Client *ec, wl_notify_func_t notify)
9652 {
9653    API_ENTRY_VAL(NULL);
9654    return wl_signal_get(&priv->events.raise, notify);
9655 }
9656
9657 EINTERN void
9658 e_client_lower_listener_add(E_Client *ec, struct wl_listener *listener)
9659 {
9660    API_ENTRY;
9661    wl_signal_add(&priv->events.lower, listener);
9662 }
9663
9664 EINTERN struct wl_listener *
9665 e_client_lower_listener_get(E_Client *ec, wl_notify_func_t notify)
9666 {
9667    API_ENTRY_VAL(NULL);
9668    return wl_signal_get(&priv->events.lower, notify);
9669 }
9670
9671 EINTERN void
9672 e_client_stack_below_listener_add(E_Client *ec, struct wl_listener *listener)
9673 {
9674    API_ENTRY;
9675    wl_signal_add(&priv->events.stack_below, listener);
9676 }
9677
9678 EINTERN struct wl_listener *
9679 e_client_stack_below_listener_get(E_Client *ec, wl_notify_func_t notify)
9680 {
9681    API_ENTRY_VAL(NULL);
9682    return wl_signal_get(&priv->events.stack_below, notify);
9683 }
9684
9685 EINTERN void
9686 e_client_stack_above_listener_add(E_Client *ec, struct wl_listener *listener)
9687 {
9688    API_ENTRY;
9689    wl_signal_add(&priv->events.stack_above, listener);
9690 }
9691
9692 EINTERN struct wl_listener *
9693 e_client_stack_above_listener_get(E_Client *ec, wl_notify_func_t notify)
9694 {
9695    API_ENTRY_VAL(NULL);
9696    return wl_signal_get(&priv->events.stack_above, notify);
9697 }
9698
9699 EINTERN void
9700 e_client_layer_set_listener_add(E_Client *ec, struct wl_listener *listener)
9701 {
9702    API_ENTRY;
9703    wl_signal_add(&priv->events.layer_set, listener);
9704 }
9705
9706 EINTERN struct wl_listener *
9707 e_client_layer_set_listener_get(E_Client *ec, wl_notify_func_t notify)
9708 {
9709    API_ENTRY_VAL(NULL);
9710    return wl_signal_get(&priv->events.layer_set, notify);
9711 }
9712
9713 EINTERN void
9714 e_client_stack_transient_for_done_listener_add(E_Client *ec, struct wl_listener *listener)
9715 {
9716    API_ENTRY;
9717    wl_signal_add(&priv->events.stack_transient_for_done, listener);
9718 }
9719
9720 EINTERN struct wl_listener *
9721 e_client_stack_transient_for_done_listener_get(E_Client *ec, wl_notify_func_t notify)
9722 {
9723    API_ENTRY_VAL(NULL);
9724    return wl_signal_get(&priv->events.stack_transient_for_done, notify);
9725 }
9726
9727 EINTERN void
9728 e_client_stick_listener_add(E_Client *ec, struct wl_listener *listener)
9729 {
9730    API_ENTRY;
9731    wl_signal_add(&priv->events.stick, listener);
9732 }
9733
9734 EINTERN struct wl_listener *
9735 e_client_stick_listener_get(E_Client *ec, wl_notify_func_t notify)
9736 {
9737    API_ENTRY_VAL(NULL);
9738    return wl_signal_get(&priv->events.stick, notify);
9739 }
9740
9741 EINTERN void
9742 e_client_unstick_listener_add(E_Client *ec, struct wl_listener *listener)
9743 {
9744    API_ENTRY;
9745    wl_signal_add(&priv->events.unstick, listener);
9746 }
9747
9748 EINTERN struct wl_listener *
9749 e_client_unstick_listener_get(E_Client *ec, wl_notify_func_t notify)
9750 {
9751    API_ENTRY_VAL(NULL);
9752    return wl_signal_get(&priv->events.unstick, notify);
9753 }