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