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