e_client: use e_client_visibility_set/get funtions
[platform/upstream/enlightenment.git] / src / bin / e_policy.c
1 #include "e_policy_intern.h"
2 #include "e_policy_wl_intern.h"
3 #include "e_policy_conformant_intern.h"
4 #include "e_policy_visibility_intern.h"
5 #include "e_policy_private_data.h"
6 #include "services/e_service_quickpanel_intern.h"
7 #include "e_comp_wl_subsurface_intern.h"
8 #include "e_comp_intern.h"
9 #include "e_pixmap_intern.h"
10 #include "e_client_intern.h"
11 #include "e_desk_intern.h"
12 #include "e_zone_intern.h"
13 #include "e_config_intern.h"
14 #include "e_utils_intern.h"
15
16 E_Policy *e_policy = NULL;
17 Eina_Hash *hash_policy_desks = NULL;
18 Eina_Hash *hash_policy_clients = NULL;
19 E_Policy_System_Info e_policy_system_info =
20 {
21    {NULL, EINA_FALSE},
22    { -1, -1, EINA_FALSE}
23 };
24
25 static int _e_policy_interceptors_walking = 0;
26 static int _e_policy_interceptors_delete = 0;
27
28 E_Policy_Interceptor *_e_policy_interceptors[] =
29 {
30    [E_POLICY_INTERCEPT_LAUNCHSCREEN_OBJECT_SETUP] = NULL,
31    [E_POLICY_INTERCEPT_STACK_TRANSIENT_FOR] = NULL,
32    [E_POLICY_INTERCEPT_ACTIVATE_ABOVE] = NULL,
33    [E_POLICY_INTERCEPT_ACTIVATE_BELOW] = NULL,
34    [E_POLICY_INTERCEPT_SEND_PRE_VISIBILITY] = NULL,
35 };
36
37 static Eina_List *handlers = NULL;
38 static Eina_List *hooks_ec = NULL;
39 static Eina_List *hooks_cp = NULL;
40 static Ecore_Idle_Enterer *_e_pol_idle_enterer = NULL;
41 static Eina_Bool _e_pol_changed_vis = EINA_FALSE;
42 static Eina_List *_e_pol_changed_zone = NULL;
43 static int _e_policy_hooks_delete = 0;
44 static int _e_policy_hooks_walking = 0;
45
46 static Eina_Inlist *_e_policy_hooks[] =
47 {
48    [E_POLICY_HOOK_CLIENT_POSITION_SET] = NULL,
49    [E_POLICY_HOOK_CLIENT_ACTIVE_REQ] = NULL,
50    [E_POLICY_HOOK_CLIENT_RAISE_REQ] = NULL,
51    [E_POLICY_HOOK_CLIENT_LOWER_REQ] = NULL,
52    [E_POLICY_HOOK_CLIENT_ICONIFY_REQ] = NULL,
53    [E_POLICY_HOOK_CLIENT_UNICONIFY_REQ] = NULL,
54    [E_POLICY_HOOK_CLIENT_NOTILAYER_SET] = NULL,
55    [E_POLICY_HOOK_CLIENT_RAISE_REQ_DONE] = NULL,
56    [E_POLICY_HOOK_CLIENT_ROTATION_GEOMETRY_SET] = NULL,
57    [E_POLICY_HOOK_CLIENT_STACK_MODE_SET] = NULL,
58    [E_POLICY_HOOK_CLIENT_AUX_HINT_CHANGED] = NULL,
59    [E_POLICY_HOOK_CLIENT_TYPE_SET] = NULL,
60 };
61
62 E_API int E_EVENT_POLICY_QUICKPANEL_VISIBLE_STATE_CHANGE = -1;
63
64 static void        _e_policy_client_del(E_Policy_Client *pc);
65 static Eina_Bool   _e_policy_client_normal_check(E_Client *ec);
66 static Eina_Bool   _e_policy_client_maximize_policy_apply(E_Policy_Client *pc);
67 static void        _e_policy_client_maximize_policy_cancel(E_Policy_Client *pc);
68 static void        _e_policy_client_floating_policy_apply(E_Policy_Client *pc);
69 static void        _e_policy_client_floating_policy_cancel(E_Policy_Client *pc);
70 static void        _e_policy_client_launcher_set(E_Policy_Client *pc);
71 static void        _e_policy_desk_client_add_hook_add(E_Policy_Client *pc);
72 static void        _e_policy_desk_client_add_hook_delete(E_Policy_Client *pc);
73
74 static void        _e_policy_cb_hook_client_eval_pre_new_client(void *d EINA_UNUSED, E_Client *ec);
75 static void        _e_policy_cb_hook_client_eval_pre_fetch(void *d EINA_UNUSED, E_Client *ec);
76 static void        _e_policy_cb_hook_client_eval_pre_post_fetch(void *d EINA_UNUSED, E_Client *ec);
77 static void        _e_policy_cb_hook_client_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec);
78 static void        _e_policy_cb_hook_client_eval_post_new_client(void *d EINA_UNUSED, E_Client *ec);
79
80 static void        _e_policy_cb_hook_pixmap_del(void *data EINA_UNUSED, E_Pixmap *cp);
81 static void        _e_policy_cb_hook_pixmap_unusable(void *data EINA_UNUSED, E_Pixmap *cp);
82
83 static void        _e_policy_cb_desk_data_free(void *data);
84 static void        _e_policy_cb_client_data_free(void *data);
85 static Eina_Bool   _e_policy_cb_zone_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
86 static Eina_Bool   _e_policy_cb_zone_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
87 static Eina_Bool   _e_policy_cb_zone_move_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
88 static Eina_Bool   _e_policy_cb_zone_desk_count_set(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
89 static Eina_Bool   _e_policy_cb_zone_display_state_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
90 static Eina_Bool   _e_policy_cb_zone_useful_geometry_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
91 static Eina_Bool   _e_policy_cb_desk_show(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
92 static Eina_Bool   _e_policy_cb_client_add(void *data EINA_UNUSED, int type, void *event);
93 static Eina_Bool   _e_policy_cb_client_move(void *data EINA_UNUSED, int type, void *event);
94 static Eina_Bool   _e_policy_cb_client_resize(void *data EINA_UNUSED, int type, void *event);
95 static Eina_Bool   _e_policy_cb_client_stack(void *data EINA_UNUSED, int type, void *event);
96 static Eina_Bool   _e_policy_cb_client_property(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
97 static Eina_Bool   _e_policy_cb_client_vis_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED);
98 static Eina_Bool   _e_policy_cb_client_show(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
99 static Eina_Bool   _e_policy_cb_client_hide(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
100
101 static Eina_Bool   _e_policy_cb_idle_enterer(void *data EINA_UNUSED);
102
103 static void
104 _e_policy_client_launcher_set(E_Policy_Client *pc)
105 {
106    E_Policy_Client *pc2;
107    E_Zone *zone;
108
109    zone = pc->zone;
110    EINA_SAFETY_ON_NULL_RETURN(zone);
111
112    pc2 = e_policy_client_launcher_get(zone);
113    if (pc2) return;
114
115    if (pc->ec->netwm.type != e_config->launcher.type)
116      return;
117
118 #if defined(__cplusplus) || defined(c_plusplus)
119    if (e_util_strcmp(pc->ec->icccm.cpp_class,
120                      e_config->launcher.clas))
121      return;
122 #else
123    if (e_util_strcmp(pc->ec->icccm.class,
124                      e_config->launcher.clas))
125      return;
126 #endif
127
128    if (e_util_strcmp(pc->ec->icccm.title,
129                      e_config->launcher.title))
130      {
131         /* check netwm name instead, because comp_x had ignored
132          * icccm name when fetching */
133         if (e_util_strcmp(pc->ec->netwm.name,
134                           e_config->launcher.title))
135           {
136              return;
137           }
138      }
139
140    e_policy->launchers = eina_list_append(e_policy->launchers, pc);
141 }
142
143 static void
144 _e_policy_cb_hook_desk_client_add(void *d, E_Desk *desk)
145 {
146    E_Policy_Client *pc;
147    E_Policy_Desk *pd;
148    E_Client *ec;
149
150    EINA_SAFETY_ON_NULL_RETURN(desk);
151
152    pc = (E_Policy_Client *)d;
153    EINA_SAFETY_ON_NULL_RETURN(pc);
154
155    ec = pc->ec;
156    EINA_SAFETY_ON_NULL_GOTO(ec, delete_hook);
157
158    if (!e_desk_has_ec(desk, ec)) goto delete_hook;
159
160    if (e_object_is_del(E_OBJECT(ec))) goto delete_hook;
161    if (!_e_policy_client_normal_check(ec)) goto delete_hook;
162    if (ec->internal) goto delete_hook;
163    if (ec->new_client) goto delete_hook;
164
165    pd = eina_hash_find(hash_policy_desks, &desk);
166    if (pd)
167      _e_policy_client_maximize_policy_apply(pc);
168    else
169      _e_policy_client_maximize_policy_cancel(pc);
170
171 delete_hook:
172    // This function should be executed once when e_client adds on a desk.
173    // Therefore, delete the desk_hooks.client_add.
174    _e_policy_desk_client_add_hook_delete(pc);
175 }
176
177 static void
178 _e_policy_desk_client_add_hook_add(E_Policy_Client *pc)
179 {
180    pc->desk_hooks.client_add = e_desk_hook_add(E_DESK_HOOK_CLIENT_ADD, _e_policy_cb_hook_desk_client_add, pc);
181 }
182
183 static void
184 _e_policy_desk_client_add_hook_delete(E_Policy_Client *pc)
185 {
186    if (pc->desk_hooks.client_add)
187      {
188         e_desk_hook_del(pc->desk_hooks.client_add);
189         pc->desk_hooks.client_add = NULL;
190      }
191 }
192
193 static void
194 _e_policy_client_del(E_Policy_Client *pc)
195 {
196    _e_policy_desk_client_add_hook_delete(pc);
197
198    eina_hash_del_by_key(hash_policy_clients, &pc->ec);
199 }
200
201 static Eina_Bool
202 _e_policy_client_normal_check(E_Client *ec)
203 {
204    E_Policy_Client *pc;
205
206    if ((e_client_util_ignored_get(ec)) ||
207        (!ec->pixmap))
208      {
209         return EINA_FALSE;
210      }
211
212    if (e_policy_client_is_quickpanel(ec))
213      {
214         return EINA_FALSE;
215      }
216
217    if (e_policy_client_is_keyboard(ec) ||
218        e_policy_client_is_keyboard_sub(ec))
219      {
220         e_policy_keyboard_layout_apply(ec);
221         goto cancel_max;
222      }
223    else if (e_policy_client_is_volume_tv(ec))
224      goto cancel_max;
225    else if (!e_util_strcmp("e_demo", ec->icccm.window_role))
226      goto cancel_max;
227    else if (e_policy_client_is_floating(ec))
228      {
229         pc = eina_hash_find(hash_policy_clients, &ec);
230         _e_policy_client_maximize_policy_cancel(pc);
231         _e_policy_client_floating_policy_apply(pc);
232         return EINA_FALSE;
233      }
234    else if (e_policy_client_is_subsurface(ec))
235      goto cancel_max;
236
237    if ((ec->netwm.type == E_WINDOW_TYPE_NORMAL) ||
238        (ec->netwm.type == E_WINDOW_TYPE_UNKNOWN) ||
239        (ec->netwm.type == E_WINDOW_TYPE_NOTIFICATION))
240      {
241         return EINA_TRUE;
242      }
243
244    return EINA_FALSE;
245
246 cancel_max:
247    pc = eina_hash_find(hash_policy_clients, &ec);
248    _e_policy_client_maximize_policy_cancel(pc);
249
250    return EINA_FALSE;
251 }
252
253 static void
254 _e_policy_client_maximize_pre(E_Policy_Client *pc)
255 {
256    E_Client *ec;
257    E_Zone *zone;
258    E_Desk *desk;
259    int zx, zy, zw, zh;
260
261    ec = pc->ec;
262    zone = pc->zone;
263    if (!zone) return;
264
265    desk = e_zone_desk_find_by_ec(zone, ec);
266    EINA_SAFETY_ON_NULL_RETURN(desk);
267
268    if (desk->visible)
269      e_zone_useful_geometry_get(zone, &zx, &zy, &zw, &zh);
270    else
271      {
272         zx = zone->x;
273         zy = zone->y;
274         zw = zone->w;
275         zh = zone->h;
276      }
277
278    ec->client.x = zx;
279    ec->client.y = zy;
280    ec->client.w = zw;
281    ec->client.h = zh;
282    e_client_pos_set(ec, zx, zy);
283    e_client_size_set(ec, zw, zh);
284    EC_CHANGED(ec);
285 }
286
287 static Eina_Bool
288 _e_policy_client_maximize_policy_apply(E_Policy_Client *pc)
289 {
290    E_Client *ec;
291
292    if (!pc) return EINA_FALSE;
293
294    if (pc->max_policy_state) return EINA_TRUE;
295    if (pc->allow_user_geom) return EINA_FALSE;
296
297    ec = pc->ec;
298    if (ec->netwm.type == E_WINDOW_TYPE_UTILITY) return EINA_FALSE;
299
300    pc->max_policy_state = EINA_TRUE;
301
302 #undef _SET
303 # define _SET(a) pc->orig.a = pc->ec->a
304    _SET(borderless);
305    _SET(fullscreen);
306    _SET(maximized);
307    _SET(lock_user_location);
308    _SET(lock_client_location);
309    _SET(lock_user_size);
310    _SET(lock_client_size);
311    _SET(lock_client_stacking);
312    _SET(lock_user_maximize);
313    _SET(lock_client_maximize);
314    _SET(lock_user_fullscreen);
315    _SET(lock_client_fullscreen);
316 #undef _SET
317
318    _e_policy_client_launcher_set(pc);
319
320    if (!ec->borderless)
321      {
322         ec->borderless = 1;
323         ec->border.changed = 1;
324         EC_CHANGED(pc->ec);
325      }
326
327    if (!ec->maximized)
328      {
329         /* This is added to support e_desk_geometry_set().
330          * The geometry of client is calculated based on E_Desk by
331          * e_client_maximize() from now.
332          * But, if we don't set ec->placed, geometry of new client will be
333          * calculated again based on E_Zone by _e_client_eval().
334          * FIXME: we can delete it if calculation of placement is based on
335          * E_Desk.
336          */
337         ec->placed = 1;
338         if ((e_policy_client_is_home_screen(ec)) ||
339             (e_policy_client_is_lockscreen(ec)) ||
340             (e_policy_client_is_quickpanel(ec)) ||
341             (e_policy_client_is_taskbar(ec)))
342           {
343              ec->maximize_type = E_MAXIMIZE_TYPE_FULLSCREEN;
344              ec->maximize_dir = E_MAXIMIZE_DIRECTION_ALL;
345           }
346         else
347           {
348              ec->maximize_type = E_MAXIMIZE_EXPAND;
349              ec->maximize_dir = E_MAXIMIZE_DIRECTION_ALL;
350           }
351
352         e_client_maximize(ec, ec->maximize_type | ec->maximize_dir);
353
354         if (ec->changes.need_maximize)
355           _e_policy_client_maximize_pre(pc);
356      }
357
358    /* do not allow client to change these properties */
359    ec->lock_user_location = 1;
360    ec->lock_client_location = 1;
361    ec->lock_user_size = 1;
362
363    if (!e_policy_client_is_home_screen(ec))
364      ec->lock_client_stacking = 1;
365
366    return EINA_TRUE;
367 }
368
369 static void
370 _e_policy_client_maximize_policy_cancel(E_Policy_Client *pc)
371 {
372    E_Client *ec;
373    Eina_Bool changed = EINA_FALSE;
374
375    if (!pc) return;
376    if (!pc->max_policy_state) return;
377
378    pc->max_policy_state = EINA_FALSE;
379
380    ec = pc->ec;
381
382    if (pc->orig.borderless != ec->borderless)
383      {
384         ec->border.changed = 1;
385         changed = EINA_TRUE;
386      }
387
388    if ((pc->orig.fullscreen != ec->fullscreen) &&
389        (pc->orig.fullscreen))
390      {
391         ec->need_fullscreen = 1;
392         changed = EINA_TRUE;
393      }
394
395    if (pc->orig.maximized != ec->maximized)
396      {
397         if (pc->orig.maximized)
398           ec->changes.need_maximize = 1;
399         else
400           e_client_unmaximize(ec, ec->maximized);
401
402         changed = EINA_TRUE;
403      }
404
405    /* floating mode ec which was launched with fake image is not borderless value.
406     * thus, we should set borderless value to 1 for this ec to prevent choppy
407     * movement of the window when moving the window.
408     */
409    if (ec->floating)
410      {
411         pc->orig.borderless = 1;
412         changed = EINA_TRUE;
413      }
414
415 #undef _SET
416 # define _SET(a) ec->a = pc->orig.a
417    _SET(borderless);
418    _SET(fullscreen);
419    _SET(maximized);
420    _SET(lock_user_location);
421    _SET(lock_client_location);
422    _SET(lock_user_size);
423    _SET(lock_client_size);
424    _SET(lock_client_stacking);
425    _SET(lock_user_maximize);
426    _SET(lock_client_maximize);
427    _SET(lock_user_fullscreen);
428    _SET(lock_client_fullscreen);
429 #undef _SET
430
431    ec->skip_fullscreen = 0;
432
433    /* only set it if the border is changed or fullscreen/maximize has changed */
434    if (changed)
435      EC_CHANGED(pc->ec);
436
437    e_policy->launchers = eina_list_remove(e_policy->launchers, pc);
438 }
439
440 static void
441 _e_policy_client_dialog_policy_apply(E_Policy_Client *pc)
442 {
443    E_Client *ec;
444    int x, y, w, h;
445    int zx, zy, zw, zh;
446
447    if (!pc) return;
448    ec = pc->ec;
449
450    ec->skip_fullscreen = 1;
451    ec->lock_client_stacking = 1;
452    ec->lock_user_maximize = 1;
453    ec->lock_client_maximize = 1;
454    ec->lock_user_fullscreen = 1;
455    ec->lock_client_fullscreen = 1;
456
457    w = ec->w;
458    h = ec->h;
459
460    e_client_base_output_resolution_useful_geometry_get(ec, &zx, &zy, &zw, &zh);
461
462    x = zx + ((zw - w) / 2);
463    y = zy + ((zh - h) / 2);
464
465    if ((x != ec->x) || (y != ec->y))
466      evas_object_move(ec->frame, x, y);
467 }
468
469 static void
470 _e_policy_client_floating_policy_apply(E_Policy_Client *pc)
471 {
472    if (!pc) return;
473    if (pc->flt_policy_state) return;
474
475    pc->flt_policy_state = EINA_TRUE;
476 }
477
478 static void
479 _e_policy_client_floating_policy_cancel(E_Policy_Client *pc)
480 {
481    if (!pc) return;
482    if (!pc->flt_policy_state) return;
483
484    pc->flt_policy_state = EINA_FALSE;
485 }
486
487 E_Config_Policy_Desk *
488 _e_policy_desk_get_by_num(unsigned int zone_num, int x, int y)
489 {
490    Eina_List *l;
491    E_Config_Policy_Desk *d2;
492
493    EINA_LIST_FOREACH(e_config->policy_desks, l, d2)
494      {
495         if ((d2->zone_num == zone_num) &&
496             (d2->x == x) && (d2->y == y))
497           {
498              return d2;
499           }
500      }
501
502    return NULL;
503 }
504
505 static void
506 _e_policy_cb_hook_client_del(void *d EINA_UNUSED, E_Client *ec)
507 {
508    E_Policy_Client *pc;
509
510    if (EINA_UNLIKELY(!ec))
511      return;
512
513    pc = eina_hash_find(hash_policy_clients, &ec);
514    if (!pc) return;
515    if (!pc->zone) return;
516    if (!pc->ec) return;
517
518    e_tzsh_indicator_srv_ower_win_update(pc->zone);
519    e_policy_wl_win_brightness_apply(pc->ec);
520    e_policy_wl_client_del(pc->ec);
521
522    if (e_policy_client_is_lockscreen(pc->ec))
523      e_policy_stack_clients_restack_above_lockscreen(pc->ec, EINA_FALSE);
524
525    e_policy_stack_cb_client_remove(pc->ec);
526    e_comp_visibility_calculation_set(EINA_TRUE);
527
528    _e_policy_client_del(pc);
529 }
530
531 static void
532 _e_policy_cb_hook_client_eval_pre_new_client(void *d EINA_UNUSED, E_Client *ec)
533 {
534    short ly;
535
536    if (e_object_is_del(E_OBJECT(ec))) return;
537
538    if (e_policy_client_is_keyboard_sub(ec))
539      {
540         ec->placed = 1;
541         ec->exp_iconify.skip_iconify = EINA_TRUE;
542
543         EINA_SAFETY_ON_NULL_RETURN(ec->frame);
544         if (ec->layer < E_LAYER_CLIENT_ABOVE)
545           e_client_layer_set(ec, E_LAYER_CLIENT_ABOVE);
546      }
547    if (e_policy_client_is_noti(ec))
548      {
549         if (ec->frame)
550           {
551              ly = evas_object_layer_get(ec->frame);
552              ELOGF("NOTI", "         |ec->layer:%d object->layer:%d", ec, ec->layer, ly);
553              if (ly != ec->layer)
554                e_client_layer_set(ec, ec->layer);
555           }
556      }
557
558    if (e_policy_client_is_dialog(ec))
559      {
560         if (ec->frame && !ec->parent)
561           {
562              if (ec->layer != E_POLICY_DIALOG_LAYER)
563                e_client_layer_set(ec, E_POLICY_DIALOG_LAYER);
564           }
565      }
566
567    if (e_policy_client_is_floating(ec))
568      {
569         if (ec->frame)
570           {
571              if (ec->layer != E_LAYER_CLIENT_ABOVE)
572                e_client_layer_set(ec, E_LAYER_CLIENT_ABOVE);
573           }
574      }
575
576    if (e_policy_client_is_toast_popup(ec))
577      {
578         if (ec->frame)
579           {
580              if (ec->layer != E_POLICY_TOAST_POPUP_LAYER)
581                e_client_layer_set(ec, E_POLICY_TOAST_POPUP_LAYER);
582           }
583      }
584    if (e_policy_client_is_cbhm(ec))
585      {
586         ec->exp_iconify.skip_iconify = EINA_TRUE;
587      }
588
589    if (e_policy_client_is_magnifier(ec))
590      {
591         if (ec->layer != E_LAYER_CLIENT_ALERT_HIGH)
592           e_client_layer_set(ec, E_LAYER_CLIENT_ALERT_HIGH);
593      }
594 }
595
596 static void
597 _e_policy_cb_hook_client_eval_pre_fetch(void *d EINA_UNUSED, E_Client *ec)
598 {
599    if (e_object_is_del(E_OBJECT(ec))) return;
600
601    e_policy_stack_transient_for_fetch(ec);
602 }
603
604 static void
605 _e_policy_cb_hook_client_eval_pre_post_fetch(void *d EINA_UNUSED, E_Client *ec)
606 {
607    if (e_object_is_del(E_OBJECT(ec))) return;
608
609    e_policy_wl_notification_level_fetch(ec);
610 }
611
612 static void
613 _e_policy_cb_hook_client_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec)
614 {
615    E_Policy_Client *pc;
616    E_Policy_Desk *pd;
617    E_Zone *zone;
618    E_Desk *desk;
619
620    if (e_object_is_del(E_OBJECT(ec))) return;
621    /* Following E_Clients will be added to module hash and will be managed.
622     *
623     *  - Not new client: Updating internal info of E_Client has been finished
624     *    by e main evaluation, thus module can classify E_Client and manage it.
625     *
626     *  - New client that has valid buffer: This E_Client has been passed e main
627     *    evaluation, and it has handled first wl_surface::commit request.
628     */
629    if ((ec->new_client) && (!e_pixmap_usable_get(ec->pixmap))) return;
630
631    pc = eina_hash_find(hash_policy_clients, &ec);
632    if (!pc) return;
633
634    zone = pc->zone;
635    if (!zone) return;
636
637    desk = e_zone_desk_find_by_ec(zone, ec);
638    if (!desk) return;
639
640    if (e_policy_client_is_keyboard(ec) ||
641        e_policy_client_is_keyboard_sub(ec))
642      {
643         _e_policy_client_maximize_policy_cancel(pc);
644         e_policy_keyboard_layout_apply(ec);
645      }
646
647    if (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role))
648      {
649         _e_policy_client_maximize_policy_cancel(pc);
650         return;
651      }
652
653    if (e_policy_client_is_floating(ec))
654      {
655         _e_policy_client_maximize_policy_cancel(pc);
656         _e_policy_client_floating_policy_apply(pc);
657         return;
658      }
659
660    if (e_policy_client_is_dialog(ec))
661      {
662         _e_policy_client_maximize_policy_cancel(pc);
663         _e_policy_client_dialog_policy_apply(pc);
664         return;
665      }
666
667    if (!_e_policy_client_normal_check(ec)) return;
668
669    pd = eina_hash_find(hash_policy_desks, &desk);
670    if (!pd) return;
671
672    pc = eina_hash_find(hash_policy_clients, &ec);
673    if (!pc) return;
674
675    if (pc->flt_policy_state)
676      _e_policy_client_floating_policy_cancel(pc);
677
678    _e_policy_client_maximize_policy_apply(pc);
679 }
680
681 static void
682 _e_policy_cb_hook_client_eval_post_new_client(void *d EINA_UNUSED, E_Client *ec)
683 {
684    E_Policy_Client *pc;
685    E_Zone *zone;
686
687    if (e_object_is_del(E_OBJECT(ec))) return;
688    if ((ec->new_client) && (!e_pixmap_usable_get(ec->pixmap))) return;
689
690    pc = eina_hash_find(hash_policy_clients, &ec);
691    EINA_SAFETY_ON_NULL_RETURN(pc);
692    zone = pc->zone;
693    EINA_SAFETY_ON_NULL_RETURN(zone);
694
695    if (e_policy_client_is_lockscreen(ec))
696      e_policy_stack_clients_restack_above_lockscreen(ec, EINA_TRUE);
697 }
698
699 static void
700 _e_policy_cb_hook_client_visibility(void *d EINA_UNUSED, E_Client *ec)
701 {
702    E_Policy_Client *pc;
703    E_Zone *zone;
704    int ex, ey, ew, eh;
705    int ax, ay, aw, ah;
706
707    pc = eina_hash_find(hash_policy_clients, &ec);
708    EINA_SAFETY_ON_NULL_RETURN(pc);
709    zone = pc->zone;
710    EINA_SAFETY_ON_NULL_RETURN(zone);
711
712    if (ec->visibility.changed)
713      {
714         if (e_client_visibility_get(ec) == E_VISIBILITY_UNOBSCURED)
715           {
716              e_policy_client_uniconify_by_visibility(ec);
717              if ((ec->iconic == 0) && (ec->exp_iconify.last_sent_iconic != 0))
718                e_policy_wl_iconify_state_change_send(ec, 0);
719              if (ec->visibility.last_sent_type != E_VISIBILITY_PRE_UNOBSCURED)
720                {
721                   ELOGF("POL_VIS", "SEND pre-unobscured visibility event", ec);
722                   e_vis_client_send_pre_visibility_event(ec);
723                }
724              e_policy_client_visibility_send(ec);
725           }
726         else
727           {
728              if (e_policy_visibility_client_is_uniconify_render_running(ec))
729                {
730                   ELOGF("POL_VIS", "cancel uniconify by visibility job", ec);
731                   e_policy_visibility_client_uniconify_by_visibility_job_cancel(ec);
732                   if ((ec->iconic == 1) && (ec->exp_iconify.last_sent_iconic == 0))
733                     e_policy_wl_iconify_state_change_send(ec, 1);
734                }
735              e_policy_client_visibility_send(ec);
736              e_policy_client_iconify_by_visibility(ec);
737           }
738
739         e_policy_wl_win_brightness_apply(ec);
740
741         _e_pol_changed_vis = EINA_TRUE;
742         if (!eina_list_data_find(_e_pol_changed_zone, zone))
743           _e_pol_changed_zone = eina_list_append(_e_pol_changed_zone, zone);
744      }
745    else
746      {
747         if (e_client_visibility_get(ec) == E_VISIBILITY_FULLY_OBSCURED)
748           {
749              Eina_Bool obscured_by_alpha_opaque = EINA_FALSE;
750              Eina_Bool find_above = EINA_FALSE;
751              E_Client *above_ec;
752              Evas_Object *o;
753
754              if (e_comp_client_zone_is_displaying(ec))
755                {
756                   e_client_geometry_get(ec, &ex, &ey, &ew, &eh);
757                   // crop ec size with zone size
758                   E_RECTS_CLIP_TO_RECT(ex, ey, ew, eh, zone->x, zone->y, zone->w, zone->h);
759
760                   if (!E_INTERSECTS(zone->x, zone->y, zone->w, zone->h, ex, ey, ew, eh))
761                     {
762                        if (ec->visibility.last_sent_type == E_VISIBILITY_PRE_UNOBSCURED)
763                          {
764                             ELOGF("POL_VIS", "SEND unobscured/fully-obscured visibility event because iconify visibility", ec);
765                             e_policy_wl_visibility_send(ec, E_VISIBILITY_UNOBSCURED);
766                             e_policy_wl_visibility_send(ec, E_VISIBILITY_FULLY_OBSCURED);
767                          }
768                        e_policy_client_iconify_by_visibility(ec);
769                        return;
770                     }
771
772                   for (o = evas_object_above_get(ec->frame); o; o = evas_object_above_get(o))
773                     {
774                        above_ec = evas_object_data_get(o, "E_Client");
775                        if (!above_ec) continue;
776                        if (e_client_util_ignored_get(above_ec)) continue;
777                        if (!above_ec->visible) continue;
778
779                        if (e_client_is_iconified_by_client(above_ec)) continue;
780                        if (above_ec->exp_iconify.skip_by_remote) continue;
781                        if (above_ec->bg_state) continue;
782
783                        if (above_ec->argb)
784                          {
785                             if (above_ec->visibility.opaque <= 0)
786                               continue;
787                             else
788                               {
789                                  if (!above_ec->iconic)
790                                    obscured_by_alpha_opaque = EINA_TRUE;
791                               }
792                          }
793
794                        find_above = EINA_TRUE;
795
796                        e_client_geometry_get(above_ec, &ax, &ay, &aw, &ah);
797                        if (E_CONTAINS(ax, ay, aw, ah, ex, ey, ew, eh))
798                          break;
799                     }
800
801                   if (!find_above) return;
802                   if (ec->visibility.last_sent_type == E_VISIBILITY_PRE_UNOBSCURED)
803                      {
804                         if (!e_policy_visibility_client_is_uniconify_render_running(ec))
805                         {
806                            ELOGF("POL_VIS", "SEND unobscured/fully-obscured visibility event because iconify visibility", ec);
807                            e_policy_wl_visibility_send(ec, E_VISIBILITY_UNOBSCURED);
808                            e_policy_wl_visibility_send(ec, E_VISIBILITY_FULLY_OBSCURED);
809                         }
810                      }
811                   if (obscured_by_alpha_opaque)
812                     {
813                        e_policy_client_uniconify_by_visibility(ec);
814                     }
815                   else
816                     {
817                        e_policy_client_iconify_by_visibility(ec);
818                     }
819                }
820              else
821                {
822                   e_policy_client_iconify_by_visibility(ec);
823                }
824           }
825      }
826 }
827
828 static void
829 _e_policy_cb_hook_client_uniconify(void *d EINA_UNUSED, E_Client *ec)
830 {
831    if (e_object_is_del(E_OBJECT(ec))) return;
832    if (!e_policy_wl_iconify_state_supported_get(ec))
833      {
834         ELOGF("TZPOL", "Force Update the client not supporting iconify state",
835               ec);
836
837         /* force render for an iconifed e_client having shm buffer not used yet*/
838         if ((e_pixmap_image_data_get(ec->pixmap)) &&
839             (!e_pixmap_dirty_get(ec->pixmap)))
840           {
841              e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
842              e_comp_object_dirty(ec->frame);
843              e_comp_object_render(ec->frame);
844           }
845      }
846 }
847
848 static void
849 _e_policy_cb_hook_pixmap_del(void *data EINA_UNUSED, E_Pixmap *cp)
850 {
851    e_policy_wl_pixmap_del(cp);
852 }
853
854 static void
855 _e_policy_cb_hook_pixmap_unusable(void *data EINA_UNUSED, E_Pixmap *cp)
856 {
857    E_Client *ec = (E_Client *)e_pixmap_client_get(cp);
858
859    if (!ec) return;
860    if (!ec->iconic) return;
861    if (e_client_is_iconified_by_client(ec)) return;
862    if (ec->exp_iconify.skip_iconify) return;
863    if (ec->exp_iconify.skip_by_remote) return;
864    if (ec->remote_surface.bind_ref > 0) return;
865
866    e_policy_client_unmap(ec);
867 }
868
869 static void
870 _e_policy_cb_desk_data_free(void *data)
871 {
872    free(data);
873 }
874
875 static void
876 _e_policy_cb_client_data_free(void *data)
877 {
878    free(data);
879 }
880
881 static Eina_Bool
882 _e_policy_cb_zone_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
883 {
884    E_Event_Zone_Add *ev;
885    E_Zone *zone;
886    E_Config_Policy_Desk *d;
887    E_Policy_Softkey *softkey;
888    int i, n;
889
890    ev = event;
891    zone = ev->zone;
892    n = zone->desk_y_count * zone->desk_x_count;
893    for (i = 0; i < n; i++)
894      {
895         if (e_config->use_configured_desks)
896           {
897              d = _e_policy_desk_get_by_num(zone->num,
898                                            zone->desks[i]->x,
899                                            zone->desks[i]->y);
900              if (d)
901                e_policy_desk_add(zone->desks[i]);
902           }
903         else
904           e_policy_desk_add(zone->desks[i]);
905      }
906
907    /* add and show softkey */
908    if (e_config->use_softkey)
909      {
910         softkey = e_policy_softkey_get(zone);
911         if (!softkey)
912           softkey = e_policy_softkey_add(zone);
913      }
914
915    return ECORE_CALLBACK_PASS_ON;
916 }
917
918 static Eina_Bool
919 _e_policy_cb_zone_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
920 {
921    E_Event_Zone_Del *ev;
922    E_Zone *zone;
923    E_Policy_Desk *pd;
924    E_Policy_Softkey *softkey;
925
926    int i, n;
927
928    ev = event;
929    zone = ev->zone;
930    n = zone->desk_y_count * zone->desk_x_count;
931    for (i = 0; i < n; i++)
932      {
933         pd = eina_hash_find(hash_policy_desks, &zone->desks[i]);
934         if (pd) e_policy_desk_del(pd);
935      }
936
937    /* add and show softkey */
938    if (e_config->use_softkey)
939      {
940         softkey = e_policy_softkey_get(zone);
941         if (softkey)
942           e_policy_softkey_del(softkey);
943      }
944
945    return ECORE_CALLBACK_PASS_ON;
946 }
947
948 static Eina_Bool
949 _e_policy_cb_zone_move_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
950 {
951    E_Event_Zone_Move_Resize *ev;
952    E_Policy_Softkey *softkey;
953
954    ev = event;
955    if (!ev) return ECORE_CALLBACK_PASS_ON;
956
957    if (e_config->use_softkey)
958      {
959         softkey = e_policy_softkey_get(ev->zone);
960         e_policy_softkey_update(softkey);
961      }
962
963    return ECORE_CALLBACK_PASS_ON;
964 }
965
966 static Eina_Bool
967 _e_policy_cb_zone_desk_count_set(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
968 {
969    E_Event_Zone_Desk_Count_Set *ev;
970    E_Zone *zone;
971    E_Desk *desk;
972    Eina_Iterator *it;
973    E_Policy_Desk *pd;
974    E_Config_Policy_Desk *d;
975    int i, n;
976    Eina_Bool found;
977    Eina_List *desks_del = NULL;
978
979    ev = event;
980    zone = ev->zone;
981
982    /* remove deleted desk from hash */
983    it = eina_hash_iterator_data_new(hash_policy_desks);
984    while (eina_iterator_next(it, (void **)&pd))
985      {
986         if (pd->zone != zone) continue;
987
988         found = EINA_FALSE;
989         n = zone->desk_y_count * zone->desk_x_count;
990         for (i = 0; i < n; i++)
991           {
992              if (pd->desk == zone->desks[i])
993                {
994                   found = EINA_TRUE;
995                   break;
996                }
997           }
998         if (!found)
999           desks_del = eina_list_append(desks_del, pd->desk);
1000      }
1001    eina_iterator_free(it);
1002
1003    EINA_LIST_FREE(desks_del, desk)
1004      {
1005         pd = eina_hash_find(hash_policy_desks, &desk);
1006         if (pd) e_policy_desk_del(pd);
1007      }
1008
1009    /* add newly added desk to hash */
1010    n = zone->desk_y_count * zone->desk_x_count;
1011    for (i = 0; i < n; i++)
1012      {
1013         if (e_config->use_configured_desks)
1014           {
1015              d = _e_policy_desk_get_by_num(zone->num,
1016                                            zone->desks[i]->x,
1017                                            zone->desks[i]->y);
1018              if (d)
1019                e_policy_desk_add(zone->desks[i]);
1020           }
1021         else
1022           e_policy_desk_add(zone->desks[i]);
1023      }
1024
1025    return ECORE_CALLBACK_PASS_ON;
1026 }
1027
1028 static Eina_Bool
1029 _e_policy_cb_zone_display_state_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1030 {
1031    E_Event_Zone_Display_State_Change *ev;
1032
1033    ev = event;
1034    if (!ev) return ECORE_CALLBACK_PASS_ON;
1035
1036    e_comp_visibility_calculation_set(EINA_TRUE);
1037
1038    return ECORE_CALLBACK_PASS_ON;
1039 }
1040
1041 static Eina_Bool
1042 _e_policy_cb_zone_useful_geometry_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1043 {
1044    E_Event_Zone_Useful_Geometry_Change *ev;
1045    E_Policy_Client *pc;
1046    E_Client *ec;
1047
1048    ev = event;
1049    if (!ev) return ECORE_CALLBACK_PASS_ON;
1050
1051    E_CLIENT_FOREACH(ec)
1052      {
1053         pc = eina_hash_find(hash_policy_clients, &ec);
1054         if (!pc) continue;
1055         if (ev->zone != pc->zone) continue;
1056
1057         if (ec->maximized)
1058           e_client_maximize_update(ec);
1059      }
1060
1061    return ECORE_CALLBACK_PASS_ON;
1062 }
1063
1064 static Eina_Bool
1065 _e_policy_cb_desk_show(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1066 {
1067    E_Event_Desk_Show *ev;
1068    E_Policy_Softkey *softkey;
1069
1070    ev = event;
1071
1072    if (e_config->use_softkey)
1073      {
1074         softkey = e_policy_softkey_get(ev->desk->zone);
1075         if (!softkey)
1076           softkey = e_policy_softkey_add(ev->desk->zone);
1077
1078         if (eina_hash_find(hash_policy_desks, &ev->desk))
1079           e_policy_softkey_show(softkey);
1080         else
1081           e_policy_softkey_hide(softkey);
1082      }
1083    return ECORE_CALLBACK_PASS_ON;
1084 }
1085
1086 static Eina_Bool
1087 _e_policy_cb_client_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1088 {
1089    E_Event_Client *ev;
1090
1091    ev = event;
1092    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
1093
1094    e_policy_wl_client_add(ev->ec);
1095
1096    return ECORE_CALLBACK_PASS_ON;
1097 }
1098
1099 static Eina_Bool
1100 _e_policy_cb_client_move(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1101 {
1102    E_Event_Client *ev;
1103    E_Client *ec;
1104    E_Policy_Client *pc;
1105    E_Zone *zone;
1106    int zx, zy, zw, zh;
1107    int ex, ey, ew, eh;
1108
1109    ev = event;
1110    if (!ev) goto end;
1111
1112    ec = ev->ec;
1113    if (!ec) goto end;
1114
1115    pc = eina_hash_find(hash_policy_clients, &ec);
1116    if (!pc) goto end;
1117
1118    zone = pc->zone;
1119    if (!zone) goto end;
1120
1121    e_policy_wl_position_send(ec);
1122    e_comp_visibility_calculation_set(EINA_TRUE);
1123
1124    if (e_policy_client_is_lockscreen(ec))
1125      {
1126         zx = zone->x;
1127         zy = zone->y;
1128         zw = zone->w;
1129         zh = zone->h;
1130
1131         e_client_geometry_get(ec, &ex, &ey, &ew, &eh);
1132
1133         if (E_CONTAINS(ex, ey, ew, eh, zx, zy, zw, zh))
1134           e_policy_stack_clients_restack_above_lockscreen(ev->ec, EINA_TRUE);
1135         else
1136           e_policy_stack_clients_restack_above_lockscreen(ev->ec, EINA_FALSE);
1137      }
1138
1139 end:
1140    return ECORE_CALLBACK_PASS_ON;
1141 }
1142
1143 static Eina_Bool
1144 _e_policy_cb_client_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1145 {
1146    E_Event_Client *ev;
1147    E_Client *ec;
1148    E_Policy_Client *pc;
1149    int zh = 0;
1150
1151    ev = (E_Event_Client *)event;
1152    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
1153
1154    ec = ev->ec;
1155    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, ECORE_CALLBACK_PASS_ON);
1156
1157    pc = eina_hash_find(hash_policy_clients, &ec);
1158    EINA_SAFETY_ON_NULL_RETURN_VAL(pc, ECORE_CALLBACK_PASS_ON);
1159
1160    /* re-calculate window's position with changed size */
1161    if (e_policy_client_is_volume_tv(ec))
1162      {
1163         e_zone_useful_geometry_get(pc->zone, NULL, NULL, NULL, &zh);
1164         evas_object_move(ec->frame, 0, (zh / 2) - (ec->h / 2));
1165
1166         evas_object_pass_events_set(ec->frame, 1);
1167      }
1168
1169    /* calculate e_client visibility */
1170    e_comp_visibility_calculation_set(EINA_TRUE);
1171
1172    return ECORE_CALLBACK_PASS_ON;
1173 }
1174
1175 static void
1176 _e_policy_client_stack_change_send(E_Client *ec)
1177 {
1178    E_Client *above = NULL;
1179    E_Client *below = NULL;
1180    int above_pid = -1;
1181    int below_pid = -1;
1182
1183    above = e_client_visible_above_get(ec);
1184    below = e_client_visible_below_get(ec);
1185
1186    if (above) above_pid = above->netwm.pid;
1187    if (below) below_pid = below->netwm.pid;
1188
1189    ELOGF("TZPOL", "Send stack change.  above(win:%zx, pid:%d), below(win:%zx, pid:%d)",
1190          ec, e_client_util_win_get(above), above_pid, e_client_util_win_get(below), below_pid);
1191
1192    e_policy_aux_message_send_from_int(ec, "stack_changed", "pid", 2, above_pid, below_pid);
1193 }
1194
1195 static Eina_Bool
1196 _e_policy_cb_client_stack(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1197 {
1198    E_Event_Client *ev;
1199
1200    ev = event;
1201    if (!ev) return ECORE_CALLBACK_PASS_ON;
1202    /* calculate e_client visibility */
1203    e_comp_visibility_calculation_set(EINA_TRUE);
1204
1205    // send stack change event
1206    _e_policy_client_stack_change_send(ev->ec);
1207
1208    return ECORE_CALLBACK_PASS_ON;
1209 }
1210
1211 static Eina_Bool
1212 _e_policy_cb_client_property(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1213 {
1214    E_Event_Client_Property *ev;
1215    E_Client *ec;
1216
1217    ev = event;
1218    if (!ev || (!ev->ec)) return ECORE_CALLBACK_PASS_ON;
1219
1220    ec = ev->ec;
1221    if (ev->property & E_CLIENT_PROPERTY_CLIENT_TYPE)
1222      {
1223         if (e_policy_client_is_home_screen(ec))
1224           {
1225              ec->lock_client_stacking = 0;
1226              e_client_desk_iconify_skip_set(ec, EINA_TRUE);
1227              if (ec->maximized)
1228                {
1229                   ec->maximize_type = E_MAXIMIZE_TYPE_FULLSCREEN;
1230                   ec->maximize_dir = E_MAXIMIZE_DIRECTION_ALL;
1231                   e_client_maximize(ec, ec->maximize_type | ec->maximize_dir);
1232                }
1233           }
1234      }
1235
1236    return ECORE_CALLBACK_PASS_ON;
1237 }
1238
1239 static Eina_Bool
1240 _e_policy_cb_client_vis_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event EINA_UNUSED)
1241 {
1242    e_policy_wl_win_scrmode_apply();
1243    return ECORE_CALLBACK_PASS_ON;
1244 }
1245
1246 static Eina_Bool
1247 _e_policy_cb_client_show(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1248 {
1249    E_Event_Client *ev;
1250    E_Client *ec;
1251
1252    ev = event;
1253    if (!ev) return ECORE_CALLBACK_PASS_ON;
1254
1255    ec = ev->ec;
1256    e_policy_stack_check_above_lockscreen(ec, ec->layer);
1257
1258    return ECORE_CALLBACK_PASS_ON;
1259 }
1260
1261 static Eina_Bool
1262 _e_policy_cb_client_hide(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1263 {
1264    E_Event_Client *ev;
1265    E_Client *ec;
1266    E_Policy_Client *pc;
1267
1268    ev = event;
1269    if (!ev) return ECORE_CALLBACK_PASS_ON;
1270
1271    ec = ev->ec;
1272    pc = eina_hash_find(hash_policy_clients, &ec);
1273    if (!pc) return ECORE_CALLBACK_PASS_ON;
1274
1275    e_tzsh_indicator_srv_ower_win_update(pc->zone);
1276
1277    return ECORE_CALLBACK_PASS_ON;
1278 }
1279
1280 static Eina_Bool
1281 _e_policy_cb_client_zone_set(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
1282 {
1283    E_Event_Client_Zone_Set *ev;
1284    E_Policy_Client *pc;
1285
1286    ev = event;
1287
1288    pc = eina_hash_find(hash_policy_clients, &ev->ec);
1289    if (!pc)
1290      goto end;
1291
1292    if (pc->ec != ev->ec)
1293      goto end;
1294
1295    if (pc->zone == ev->zone)
1296      goto end;
1297
1298    ELOGF("CBHM", "Change Zone | e_policy %p old(%p) new(%p)",
1299          ev->ec, pc, pc->zone, ev->zone);
1300
1301    pc->zone = ev->zone;
1302
1303 end:
1304    return ECORE_CALLBACK_PASS_ON;
1305 }
1306
1307
1308 static Eina_Bool
1309 _e_policy_cb_idle_enterer(void *data EINA_UNUSED)
1310 {
1311    E_Zone *zone;
1312
1313    if (_e_pol_changed_vis)
1314      {
1315         EINA_LIST_FREE(_e_pol_changed_zone, zone)
1316           {
1317              e_tzsh_indicator_srv_ower_win_update(zone);
1318           }
1319         _e_pol_changed_zone = NULL;
1320      }
1321    _e_pol_changed_vis = EINA_FALSE;
1322
1323    return ECORE_CALLBACK_RENEW;
1324 }
1325
1326 EINTERN void
1327 e_policy_desk_add(E_Desk *desk)
1328 {
1329    E_Policy_Desk *pd;
1330    E_Client *ec;
1331    E_Policy_Client *pc;
1332
1333    pd = eina_hash_find(hash_policy_desks, &desk);
1334    if (pd) return;
1335
1336    pd = E_NEW(E_Policy_Desk, 1);
1337    if (!pd) return;
1338
1339    pd->desk = desk;
1340    pd->zone = desk->zone;
1341
1342    eina_hash_add(hash_policy_desks, &desk, pd);
1343
1344    /* add clients */
1345    E_CLIENT_FOREACH(ec)
1346      {
1347        if (e_desk_has_ec(pd->desk, ec))
1348          {
1349             pc = eina_hash_find(hash_policy_clients, &ec);
1350             _e_policy_client_maximize_policy_apply(pc);
1351          }
1352      }
1353 }
1354
1355 EINTERN void
1356 e_policy_desk_del(E_Policy_Desk *pd)
1357 {
1358    Eina_Iterator *it;
1359    E_Policy_Client *pc;
1360    E_Client *ec;
1361    Eina_List *clients_del = NULL;
1362    E_Policy_Softkey *softkey;
1363
1364    /* hide and delete softkey */
1365    if (e_config->use_softkey)
1366      {
1367         softkey = e_policy_softkey_get(pd->zone);
1368         if (e_desk_current_get(pd->zone) == pd->desk)
1369           e_policy_softkey_hide(softkey);
1370      }
1371
1372    /* remove clients */
1373    it = eina_hash_iterator_data_new(hash_policy_clients);
1374    while (eina_iterator_next(it, (void **)&pc))
1375      {
1376         if (e_desk_has_ec(pd->desk, pc->ec))
1377           clients_del = eina_list_append(clients_del, pc->ec);
1378      }
1379    eina_iterator_free(it);
1380
1381    EINA_LIST_FREE(clients_del, ec)
1382      {
1383         pc = eina_hash_find(hash_policy_clients, &ec);
1384         _e_policy_client_maximize_policy_cancel(pc);
1385      }
1386
1387    eina_hash_del_by_key(hash_policy_desks, &pd->desk);
1388 }
1389
1390 EINTERN E_Policy_Client *
1391 e_policy_client_launcher_get(E_Zone *zone)
1392 {
1393    E_Policy_Client *pc;
1394    Eina_List *l;
1395
1396    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, NULL);
1397
1398    EINA_LIST_FOREACH(e_policy->launchers, l, pc)
1399      {
1400         if (pc->zone == zone)
1401           return pc;
1402      }
1403    return NULL;
1404 }
1405
1406 EINTERN void
1407 e_policy_client_unmap(E_Client *ec)
1408 {
1409    Eina_Bool send_event = EINA_FALSE;
1410
1411    if (!ec) return;
1412    if (e_object_is_del(E_OBJECT(ec))) return;
1413
1414    ELOGF("TZPOL", "Reset ec information by unmap", ec);
1415
1416    if (ec->iconic)
1417      send_event = EINA_TRUE;
1418
1419    ec->deskshow = 0;
1420    ec->iconic = 0;
1421
1422    ec->exp_iconify.by_client = 0;
1423    e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_NONE);
1424    ec->exp_iconify.not_raise = 0;
1425    ec->exp_iconify.skip_iconify = 0;
1426
1427    if (send_event)
1428      e_policy_wl_iconify_state_change_send(ec, 0);
1429
1430    e_comp_object_effect_set(ec->frame, NULL);
1431 }
1432
1433 EINTERN Eina_Bool
1434 e_policy_client_maximize(E_Client *ec)
1435 {
1436    E_Policy_Desk *pd;
1437    E_Policy_Client *pc;
1438    E_Desk *desk;
1439
1440    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1441    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1442
1443    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1444
1445    if ((e_policy_client_is_keyboard(ec)) ||
1446        (e_policy_client_is_keyboard_sub(ec)) ||
1447        (e_policy_client_is_floating(ec)) ||
1448        (e_policy_client_is_quickpanel(ec)) ||
1449        (e_policy_client_is_volume(ec)) ||
1450        (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role)) ||
1451        (!e_util_strcmp("e_demo", ec->icccm.window_role)))
1452      return EINA_FALSE;
1453
1454    if (e_policy_client_is_subsurface(ec)) return EINA_FALSE;
1455
1456    if ((ec->netwm.type != E_WINDOW_TYPE_NORMAL) &&
1457        (ec->netwm.type != E_WINDOW_TYPE_UNKNOWN) &&
1458        (ec->netwm.type != E_WINDOW_TYPE_NOTIFICATION))
1459      return EINA_FALSE;
1460
1461    pc = eina_hash_find(hash_policy_clients, &ec);
1462    EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
1463
1464    desk = e_zone_desk_find_by_ec(pc->zone, ec);
1465    EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
1466
1467    pd = eina_hash_find(hash_policy_desks, &desk);
1468    if (!pd) return EINA_FALSE;
1469
1470    if (pc->flt_policy_state)
1471      _e_policy_client_floating_policy_cancel(pc);
1472
1473    return _e_policy_client_maximize_policy_apply(pc);
1474 }
1475
1476 EINTERN void
1477 e_policy_keyboard_layout_apply(E_Client *ec EINA_UNUSED)
1478 {
1479 /* FIXME: do not resize and move client.
1480  * ec->e.state.rot.geom[].w/h is always 0,
1481  * then the geometry calculated here is not valid. */
1482 #if 0
1483    int angle;
1484    int angle_id = 0;
1485    int kbd_x, kbd_y, kbd_w, kbd_h;
1486    E_Policy_Client *pc;
1487
1488    if (!e_policy_client_is_keyboard(ec) &&
1489        !e_policy_client_is_keyboard_sub(ec))
1490       return;
1491
1492    angle = e_client_rotation_curr_angle_get(ec);
1493
1494    switch (angle)
1495      {
1496       case 0: angle_id = 0; break;
1497       case 90: angle_id = 1; break;
1498       case 180: angle_id = 2; break;
1499       case 270: angle_id = 3; break;
1500       default: angle_id = 0; break;
1501      }
1502
1503    kbd_w = ec->e.state.rot.geom[angle_id].w;
1504    kbd_h = ec->e.state.rot.geom[angle_id].h;
1505
1506    pc = eina_hash_find(hash_policy_clients, &ec);
1507    if (!pc->ec) return;
1508    if (!pc->zone) return;
1509
1510    switch (angle)
1511      {
1512       case 0:
1513          kbd_x = pc->zone->w - kbd_w;
1514          kbd_y = pc->zone->h - kbd_h;
1515          break;
1516
1517       case 90:
1518          kbd_x = pc->zone->w - kbd_w;
1519          kbd_y = pc->zone->h - kbd_h;
1520          break;
1521
1522       case 180:
1523          kbd_x = 0;
1524          kbd_y = 0;
1525          break;
1526
1527       case 270:
1528          kbd_x = 0;
1529          kbd_y = 0;
1530          break;
1531
1532       default:
1533          kbd_x = pc->zone->w - kbd_w;
1534          kbd_y = pc->zone->h - kbd_h;
1535          break;
1536      }
1537
1538    if ((ec->frame) &&
1539        ((ec->w != kbd_w) || (ec->h != kbd_h)))
1540      e_client_util_resize_without_frame(ec, kbd_w, kbd_h);
1541
1542    if ((e_policy_client_is_keyboard(ec)) &&
1543        (ec->frame) &&
1544        ((ec->x != kbd_x) || (ec->y != kbd_y)))
1545      e_client_util_move_without_frame(ec, kbd_x, kbd_y);
1546 #endif
1547 }
1548
1549 E_API Eina_Bool
1550 e_policy_client_is_lockscreen(E_Client *ec)
1551 {
1552    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1553    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1554
1555    if (ec->client_type == 2)
1556      return EINA_TRUE;
1557
1558    if (!e_util_strcmp(ec->icccm.title, "LOCKSCREEN"))
1559      return EINA_TRUE;
1560
1561    if (!e_util_strcmp(ec->icccm.window_role, "lockscreen"))
1562      return EINA_TRUE;
1563
1564    return EINA_FALSE;
1565 }
1566
1567 E_API Eina_Bool
1568 e_policy_client_is_home_screen(E_Client *ec)
1569 {
1570    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1571    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1572
1573    if (ec->client_type == 1)
1574      return EINA_TRUE;
1575
1576
1577    return EINA_FALSE;
1578 }
1579
1580 E_API Eina_Bool
1581 e_policy_client_is_quickpanel(E_Client *ec)
1582 {
1583    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1584    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1585
1586    if (!e_util_strcmp(ec->icccm.window_role, "quickpanel_system_default"))
1587      return EINA_TRUE;
1588
1589    if (!e_util_strcmp(ec->icccm.window_role, "quickpanel_context_menu"))
1590      return EINA_TRUE;
1591
1592    if (!e_util_strcmp(ec->icccm.window_role, "quickpanel_apps_menu"))
1593      return EINA_TRUE;
1594
1595    return EINA_FALSE;
1596 }
1597
1598 EINTERN Eina_Bool
1599 e_policy_client_is_conformant(E_Client *ec)
1600 {
1601    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1602    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
1603
1604    E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
1605    if (cdata->conformant == 1)
1606      {
1607         return EINA_TRUE;
1608      }
1609
1610    return EINA_FALSE;
1611 }
1612
1613 E_API Eina_Bool
1614 e_policy_client_is_volume(E_Client *ec)
1615 {
1616    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1617    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1618
1619    if (!e_util_strcmp(ec->netwm.name, "volume"))
1620      return EINA_TRUE;
1621
1622    if (!e_util_strcmp(ec->icccm.title, "volume"))
1623      return EINA_TRUE;
1624
1625    return EINA_FALSE;
1626 }
1627
1628 EINTERN Eina_Bool
1629 e_policy_client_is_volume_tv(E_Client *ec)
1630 {
1631    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1632    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1633
1634    if (!e_util_strcmp(ec->icccm.window_role, "tv-volume-popup"))
1635      return EINA_TRUE;
1636
1637    return EINA_FALSE;
1638 }
1639
1640 EINTERN Eina_Bool
1641 e_policy_client_is_noti(E_Client *ec)
1642 {
1643    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1644    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1645
1646    if (!e_util_strcmp(ec->icccm.title, "noti_win"))
1647      return EINA_TRUE;
1648
1649    if (ec->netwm.type == E_WINDOW_TYPE_NOTIFICATION)
1650      return EINA_TRUE;
1651
1652    return EINA_FALSE;
1653 }
1654
1655 EINTERN Eina_Bool
1656 e_policy_client_is_subsurface(E_Client *ec)
1657 {
1658    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1659    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1660
1661    if (e_comp_wl_subsurface_check(ec))
1662      return EINA_TRUE;
1663
1664    return EINA_FALSE;
1665 }
1666
1667 EINTERN Eina_Bool
1668 e_policy_client_is_floating(E_Client *ec)
1669 {
1670    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1671    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1672
1673    return ec->floating;
1674 }
1675
1676 EINTERN Eina_Bool
1677 e_policy_client_is_magnifier(E_Client *ec)
1678 {
1679    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1680    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1681
1682    return ec->is_magnifier;
1683 }
1684
1685 E_API Eina_Bool
1686 e_policy_client_is_cursor(E_Client *ec)
1687 {
1688    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1689    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1690
1691    if (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role))
1692      return EINA_TRUE;
1693
1694    return EINA_FALSE;
1695 }
1696
1697 EINTERN Eina_Bool
1698 e_policy_client_is_cbhm(E_Client *ec)
1699 {
1700    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1701    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1702
1703    if (!e_util_strcmp("cbhm", ec->icccm.window_role))
1704      return EINA_TRUE;
1705
1706    return EINA_FALSE;
1707 }
1708
1709 EINTERN Eina_Bool
1710 e_policy_client_is_toast_popup(E_Client *ec)
1711 {
1712    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1713    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1714
1715 #if defined(__cplusplus) || defined(c_plusplus)
1716    if (!e_util_strcmp("TOAST_POPUP", ec->icccm.cpp_class))
1717      return EINA_TRUE;
1718 #else
1719    if (!e_util_strcmp("TOAST_POPUP", ec->icccm.class))
1720      return EINA_TRUE;
1721 #endif
1722    if (!e_util_strcmp("toast_popup", ec->icccm.window_role))
1723      return EINA_TRUE;
1724
1725    return EINA_FALSE;
1726 }
1727
1728 E_API Eina_Bool
1729 e_policy_client_is_dialog(E_Client *ec)
1730 {
1731    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1732    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1733
1734    if (ec->netwm.type == E_WINDOW_TYPE_DIALOG)
1735      return EINA_TRUE;
1736
1737    return EINA_FALSE;
1738 }
1739
1740 E_API Eina_Bool
1741 e_policy_client_is_keyboard(E_Client *ec)
1742 {
1743    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1744    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1745
1746    if (ec->vkbd.vkbd) return EINA_TRUE;
1747
1748    return EINA_FALSE;
1749 }
1750
1751 E_API Eina_Bool
1752 e_policy_client_is_keyboard_sub(E_Client *ec)
1753 {
1754    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1755    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1756
1757    if (ec->vkbd.vkbd) return EINA_FALSE;
1758
1759 #if defined(__cplusplus) || defined(c_plusplus)
1760    if ((ec->icccm.cpp_class) &&
1761        (!strcmp(ec->icccm.cpp_class, "ISF")))
1762      return EINA_TRUE;
1763 #else
1764    if ((ec->icccm.class) &&
1765        (!strcmp(ec->icccm.class, "ISF")))
1766      return EINA_TRUE;
1767 #endif
1768   if ((ec->icccm.title) &&
1769        ((!strcmp(ec->icccm.title, "ISF Popup")) || (!strcmp(ec->icccm.title, "ISF Magnifier"))))
1770      return EINA_TRUE;
1771
1772    return EINA_FALSE;
1773 }
1774
1775 E_API Eina_Bool
1776 e_policy_client_is_keyboard_magnifier(E_Client *ec)
1777 {
1778    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1779    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1780
1781    if (ec->vkbd.vkbd) return EINA_FALSE;
1782
1783    if ((ec->icccm.title) && (!strcmp(ec->icccm.title, "ISF Magnifier")))
1784      return EINA_TRUE;
1785
1786    return EINA_FALSE;
1787 }
1788
1789 EINTERN Eina_Bool
1790 e_policy_client_is_watch_viewer(E_Client *ec)
1791 {
1792    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1793    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1794
1795    if (!e_util_strcmp(e_client_util_name_get(ec), "WATCH_WINDOW"))
1796      return EINA_TRUE;
1797
1798    return EINA_FALSE;
1799 }
1800
1801 EINTERN Eina_Bool
1802 e_policy_client_is_taskbar(E_Client *ec)
1803 {
1804    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1805    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1806
1807    if (ec->client_type == 3)
1808      return EINA_TRUE;
1809
1810    if (!e_util_strcmp(ec->icccm.title, "TaskBar"))
1811      return EINA_TRUE;
1812
1813    if (!e_util_strcmp(ec->icccm.window_role, "taskbar"))
1814      return EINA_TRUE;
1815
1816    return EINA_FALSE;
1817 }
1818
1819 EINTERN Eina_Bool
1820 e_policy_client_is_KVM(E_Client *ec)
1821 {
1822    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1823
1824    if (!e_util_strcmp(ec->icccm.window_role, "KVM"))
1825      return EINA_TRUE;
1826
1827    return EINA_FALSE;
1828 }
1829
1830 EINTERN Eina_Bool
1831 e_policy_client_is_waydroid(E_Client *ec)
1832 {
1833    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1834
1835    if (!e_util_strcmp(ec->icccm.title, "Waydroid"))
1836      return EINA_TRUE;
1837
1838    return EINA_FALSE;
1839 }
1840
1841 E_API E_Service_Quickpanel_Type
1842 e_policy_quickpanel_type_get(E_Client *ec)
1843 {
1844    E_Service_Quickpanel_Type type = E_SERVICE_QUICKPANEL_TYPE_UNKNOWN;
1845
1846    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1847    E_OBJECT_TYPE_CHECK_RETURN(ec, E_CLIENT_TYPE, EINA_FALSE);
1848
1849    type = e_service_quickpanel_type_get(ec);
1850    return type;
1851 }
1852
1853 EINTERN void
1854 e_policy_base_output_resolution_info_update(pid_t pid)
1855 {
1856    e_policy_wl_base_output_resolution_info_update(pid);
1857 }
1858
1859 EINTERN void
1860 e_policy_interceptors_clean(void)
1861 {
1862    E_Policy_Interceptor *pi;
1863    unsigned int x;
1864
1865    for (x = 0; x < E_POLICY_INTERCEPT_LAST; x++)
1866      {
1867         pi = _e_policy_interceptors[x];
1868         if (!pi->delete_me) continue;
1869         _e_policy_interceptors[x] = NULL;
1870         free(pi);
1871      }
1872 }
1873
1874 /*
1875  * It returns
1876  * EINA_TRUE,
1877  *  if interceptor process something successfully at its intercept point,
1878  * EINA_FALSE,
1879  *  if interceptor failed or there is no interceptor.
1880  */
1881 EINTERN Eina_Bool
1882 e_policy_interceptor_call(E_Policy_Intercept_Point ipoint, E_Client *ec, ...)
1883 {
1884    va_list list;
1885    E_Policy_Interceptor *pi;
1886    Eina_Bool ret = EINA_TRUE;
1887
1888    if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1889    pi = _e_policy_interceptors[ipoint];
1890    if (!pi) return EINA_FALSE;
1891
1892    va_start(list, ec);
1893
1894    e_object_ref(E_OBJECT(ec));
1895    _e_policy_interceptors_walking++;
1896    if (!pi->delete_me)
1897      {
1898         if (!(pi->func(pi->data, ec, list)))
1899           ret = EINA_FALSE;
1900      }
1901    _e_policy_interceptors_walking--;
1902    if ((_e_policy_interceptors_walking == 0) && (_e_policy_interceptors_delete > 0))
1903      e_policy_interceptors_clean();
1904
1905    va_end(list);
1906    e_object_unref(E_OBJECT(ec));
1907    return ret;
1908 }
1909
1910 static void
1911 _e_policy_event_simple_free(void *d EINA_UNUSED, E_Event_Client *ev)
1912 {
1913    e_object_unref(E_OBJECT(ev->ec));
1914    free(ev);
1915 }
1916
1917 EINTERN void
1918 e_policy_event_simple(E_Client *ec, int type)
1919 {
1920    E_Event_Client *ev;
1921
1922    ev = E_NEW(E_Event_Client, 1);
1923    if (!ev) return;
1924
1925    ev->ec = ec;
1926    e_object_ref(E_OBJECT(ec));
1927    ecore_event_add(type, ev, (Ecore_End_Cb)_e_policy_event_simple_free, NULL);
1928 }
1929
1930 EINTERN Eina_Bool
1931 e_policy_aux_message_use_get(E_Client *ec)
1932 {
1933    E_OBJECT_CHECK_RETURN(ec, EINA_FALSE);
1934    EINA_SAFETY_ON_NULL_RETURN_VAL(ec->comp_data, EINA_FALSE);
1935
1936    E_Comp_Wl_Client_Data *cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
1937    if (cdata->aux_hint.use_msg)
1938      {
1939         return EINA_TRUE;
1940      }
1941
1942    return EINA_FALSE;
1943 }
1944
1945 E_API void
1946 e_policy_aux_message_send_from_int(E_Client *ec, const char *key, const char *val, int count, ...)
1947 {
1948    char option[4096];
1949    char *str_itor;
1950    Eina_List *options_list = NULL;
1951    va_list opt_args;
1952    int opt;
1953    int itor;
1954
1955    va_start(opt_args, count);
1956    for(itor = 0; itor < count; itor ++)
1957     {
1958        opt = va_arg(opt_args, int);
1959        eina_convert_itoa(opt, option);
1960        options_list = eina_list_append(options_list, eina_stringshare_add(option));
1961     }
1962    va_end(opt_args);
1963
1964    e_policy_aux_message_send(ec, key, val, options_list);
1965
1966    EINA_LIST_FREE(options_list, str_itor)
1967     {
1968        eina_stringshare_del(str_itor);
1969     }
1970 }
1971
1972 E_API void
1973 e_policy_aux_message_send(E_Client *ec, const char *key, const char *val, Eina_List *options)
1974 {
1975    E_OBJECT_CHECK(ec);
1976    E_OBJECT_TYPE_CHECK(ec, E_CLIENT_TYPE);
1977
1978    e_policy_wl_aux_message_send(ec, key, val, options);
1979 }
1980
1981 E_API E_Policy_Interceptor *
1982 e_policy_interceptor_add(E_Policy_Intercept_Point ipoint, E_Policy_Intercept_Cb func, const void *data)
1983 {
1984    E_Policy_Interceptor *pi;
1985
1986    EINA_SAFETY_ON_TRUE_RETURN_VAL(ipoint >= E_POLICY_INTERCEPT_LAST, NULL);
1987    EINA_SAFETY_ON_TRUE_RETURN_VAL(!!_e_policy_interceptors[ipoint], NULL);
1988    pi = E_NEW(E_Policy_Interceptor, 1);
1989    if (!pi) return NULL;
1990    pi->ipoint = ipoint;
1991    pi->func = func;
1992    pi->data = (void*)data;
1993    _e_policy_interceptors[ipoint] = pi;
1994    return pi;
1995 }
1996
1997 E_API void
1998 e_policy_interceptor_del(E_Policy_Interceptor *pi)
1999 {
2000    pi->delete_me = 1;
2001    if (_e_policy_interceptors_walking == 0)
2002      {
2003         _e_policy_interceptors[pi->ipoint] = NULL;
2004         free(pi);
2005      }
2006    else
2007      _e_policy_interceptors_delete++;
2008 }
2009
2010 E_API E_Policy_Hook *
2011 e_policy_hook_add(E_Policy_Hook_Point hookpoint, E_Policy_Hook_Cb func, const void *data)
2012 {
2013    E_Policy_Hook *ph;
2014
2015    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_POLICY_HOOK_LAST, NULL);
2016    ph = E_NEW(E_Policy_Hook, 1);
2017    if (!ph) return NULL;
2018    ph->hookpoint = hookpoint;
2019    ph->func = func;
2020    ph->data = (void*)data;
2021    _e_policy_hooks[hookpoint] = eina_inlist_append(_e_policy_hooks[hookpoint], EINA_INLIST_GET(ph));
2022    return ph;
2023 }
2024
2025 E_API void
2026 e_policy_hook_del(E_Policy_Hook *ph)
2027 {
2028    ph->delete_me = 1;
2029    if (_e_policy_hooks_walking == 0)
2030      {
2031         _e_policy_hooks[ph->hookpoint] = eina_inlist_remove(_e_policy_hooks[ph->hookpoint], EINA_INLIST_GET(ph));
2032         free(ph);
2033      }
2034    else
2035      _e_policy_hooks_delete++;
2036 }
2037
2038 static void
2039 _e_policy_hooks_clean(void)
2040 {
2041    Eina_Inlist *l;
2042    E_Policy_Hook *ph;
2043    unsigned int x;
2044
2045    for (x = 0; x < E_POLICY_HOOK_LAST; x++)
2046      {
2047         EINA_INLIST_FOREACH_SAFE(_e_policy_hooks[x], l, ph)
2048           {
2049              if (!ph->delete_me) continue;
2050              _e_policy_hooks[x] = eina_inlist_remove(_e_policy_hooks[x], EINA_INLIST_GET(ph));
2051              free(ph);
2052           }
2053      }
2054 }
2055
2056 E_API Eina_Bool
2057 e_policy_hook_call(E_Policy_Hook_Point hookpoint, E_Client *ec)
2058 {
2059    E_Policy_Hook *ch;
2060
2061    e_object_ref(E_OBJECT(ec));
2062    _e_policy_hooks_walking++;
2063
2064    EINA_INLIST_FOREACH(_e_policy_hooks[hookpoint], ch)
2065      {
2066         if (ch->delete_me) continue;
2067         ch->func(ch->data, ec);
2068      }
2069    _e_policy_hooks_walking--;
2070    if ((_e_policy_hooks_walking == 0) && (_e_policy_hooks_delete > 0))
2071      _e_policy_hooks_clean();
2072    return !!e_object_unref(E_OBJECT(ec));
2073 }
2074
2075 EINTERN void
2076 e_policy_user_geometry_set(E_Client *ec,
2077                            E_Policy_Allow_User_Geometry type,
2078                            Eina_Bool set)
2079 {
2080    E_Policy_Client *pc;
2081
2082    if (EINA_UNLIKELY(!ec))
2083      return;
2084
2085    pc = eina_hash_find(hash_policy_clients, &ec);
2086    if (EINA_UNLIKELY(!pc))
2087      return;
2088
2089    if (set)
2090      pc->user_geom_state |= type;
2091    else
2092      pc->user_geom_state &= ~(type);
2093
2094    if (pc->user_geom_state)
2095      e_policy_allow_user_geometry_set(ec, EINA_TRUE);
2096    else
2097      e_policy_allow_user_geometry_set(ec, EINA_FALSE);
2098 }
2099
2100 E_API void
2101 e_policy_allow_user_geometry_set(E_Client *ec, Eina_Bool set)
2102 {
2103    E_Policy_Client *pc;
2104
2105    if (EINA_UNLIKELY(!ec))
2106      return;
2107
2108    pc = eina_hash_find(hash_policy_clients, &ec);
2109    if (EINA_UNLIKELY(!pc))
2110      return;
2111
2112    if (set &&  !pc->allow_user_geom)
2113      {
2114         pc->allow_user_geom = EINA_TRUE;
2115
2116         if (!e_policy_client_is_noti(ec))
2117           {
2118              ec->netwm.type = E_WINDOW_TYPE_UTILITY;
2119              ec->lock_client_location = EINA_FALSE;
2120           }
2121
2122         _e_policy_client_maximize_policy_cancel(pc);
2123
2124         ec->lock_client_location = EINA_FALSE;
2125         ec->lock_client_size = EINA_FALSE;
2126         ec->placed = 1;
2127
2128         EC_CHANGED(ec);
2129      }
2130    else if (!set && pc->allow_user_geom)
2131      {
2132         pc->allow_user_geom = EINA_FALSE;
2133
2134         ec->lock_client_location = EINA_TRUE;
2135         ec->lock_client_size = EINA_TRUE;
2136         ec->placed = 0;
2137         ec->netwm.type = E_WINDOW_TYPE_NORMAL;
2138
2139         e_client_pending_geometry_flush(ec);
2140         ec->icccm.min_w = ec->icccm.min_h = 0;
2141         ec->icccm.max_w = ec->icccm.max_h = 0;
2142         EC_CHANGED(ec);
2143      }
2144 }
2145
2146 E_API Eina_Bool
2147 e_policy_allow_user_geometry_get(E_Client *ec)
2148 {
2149    E_Policy_Client *pc;
2150
2151    if (EINA_UNLIKELY(!ec))
2152      return EINA_FALSE;
2153
2154    pc = eina_hash_find(hash_policy_clients, &ec);
2155    if (EINA_UNLIKELY(!pc))
2156      return EINA_FALSE;
2157
2158    return pc->allow_user_geom;
2159 }
2160
2161 EINTERN void
2162 e_policy_animatable_lock(E_Client *ec,
2163                          E_Policy_Animatable_Lock lock,
2164                          Eina_Bool set)
2165 {
2166    E_Policy_Client *pc;
2167
2168    if (EINA_UNLIKELY(!ec))
2169      return;
2170
2171    pc = eina_hash_find(hash_policy_clients, &ec);
2172    if (EINA_UNLIKELY(!pc))
2173      return;
2174
2175    if (set)
2176      pc->lock_animatable |= lock;
2177    else
2178      pc->lock_animatable &= ~(lock);
2179
2180    if (pc->lock_animatable)
2181      ec->animatable = EINA_FALSE;
2182    else
2183      ec->animatable = EINA_TRUE;
2184
2185    ELOGF("TZPOL","EFFECT(animatable:%d) due to %d is applied on the state %d --> result:%d", ec,
2186         ec->animatable, set, lock, pc->lock_animatable);
2187 }
2188
2189 EINTERN void
2190 e_policy_deferred_job(void)
2191 {
2192    if (!e_policy) return;
2193
2194    e_policy_wl_defer_job();
2195 }
2196
2197 EINTERN E_Policy_Client *
2198 e_policy_client_add(E_Client *ec)
2199 {
2200    E_Policy_Client *pc;
2201
2202    if (e_object_is_del(E_OBJECT(ec))) return NULL;
2203
2204    pc = eina_hash_find(hash_policy_clients, &ec);
2205    if (pc) return pc;
2206
2207    pc = E_NEW(E_Policy_Client, 1);
2208    if (!pc) return NULL;
2209
2210    pc->ec = ec;
2211    pc->zone = e_comp_zone_find_by_ec(ec);
2212
2213    eina_hash_add(hash_policy_clients, &ec, pc);
2214
2215    // This client_add hook of desk will be deleted at the hook callback for it.
2216    _e_policy_desk_client_add_hook_add(pc);
2217
2218    return pc;
2219 }
2220
2221 EINTERN int
2222 e_policy_init(void)
2223 {
2224    E_Policy *pol;
2225    E_Zone *zone;
2226    E_Config_Policy_Desk *d;
2227    const Eina_List *l;
2228    int i, n;
2229
2230    pol = E_NEW(E_Policy, 1);
2231    EINA_SAFETY_ON_NULL_RETURN_VAL(pol, EINA_FALSE);
2232
2233    e_policy = pol;
2234
2235    hash_policy_clients = eina_hash_pointer_new(_e_policy_cb_client_data_free);
2236    hash_policy_desks = eina_hash_pointer_new(_e_policy_cb_desk_data_free);
2237
2238    E_EVENT_POLICY_QUICKPANEL_VISIBLE_STATE_CHANGE = ecore_event_type_new();
2239
2240    e_policy_stack_init();
2241    e_policy_wl_init();
2242    e_policy_wl_aux_hint_init();
2243
2244    EINA_LIST_FOREACH(e_comp->zones, l, zone)
2245      {
2246         n = zone->desk_y_count * zone->desk_x_count;
2247         for (i = 0; i < n; i++)
2248           {
2249              if (e_config->use_configured_desks)
2250                {
2251                   d = _e_policy_desk_get_by_num(zone->num,
2252                                                 zone->desks[i]->x,
2253                                                 zone->desks[i]->y);
2254                   if (d)
2255                     e_policy_desk_add(zone->desks[i]);
2256                }
2257              else
2258                e_policy_desk_add(zone->desks[i]);
2259           }
2260      }
2261
2262    E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_ADD,                  _e_policy_cb_zone_add,                        NULL);
2263    E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DEL,                  _e_policy_cb_zone_del,                        NULL);
2264    E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_MOVE_RESIZE,          _e_policy_cb_zone_move_resize,                NULL);
2265    E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DESK_COUNT_SET,       _e_policy_cb_zone_desk_count_set,             NULL);
2266    E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DISPLAY_STATE_CHANGE, _e_policy_cb_zone_display_state_change,       NULL);
2267    E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_USEFUL_GEOMETRY_CHANGE, _e_policy_cb_zone_useful_geometry_change,   NULL);
2268    E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_SHOW,                 _e_policy_cb_desk_show,                       NULL);
2269    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ADD,                _e_policy_cb_client_add,                      NULL);
2270    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_MOVE,               _e_policy_cb_client_move,                     NULL);
2271    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_RESIZE,             _e_policy_cb_client_resize,                   NULL);
2272    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_STACK,              _e_policy_cb_client_stack,                    NULL);
2273    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_PROPERTY,           _e_policy_cb_client_property,                 NULL);
2274    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_VISIBILITY_CHANGE,  _e_policy_cb_client_vis_change,               NULL);
2275    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_SHOW,               _e_policy_cb_client_show,                     NULL);
2276    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_HIDE,               _e_policy_cb_client_hide,                     NULL);
2277    E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_ZONE_SET,           _e_policy_cb_client_zone_set,                 NULL);
2278
2279    E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_DEL,                 _e_policy_cb_hook_client_del,                 NULL);
2280    E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_PRE_NEW_CLIENT, _e_policy_cb_hook_client_eval_pre_new_client, NULL);
2281    E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_PRE_FETCH,      _e_policy_cb_hook_client_eval_pre_fetch,      NULL);
2282    E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_PRE_POST_FETCH, _e_policy_cb_hook_client_eval_pre_post_fetch, NULL);
2283    E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_POST_FETCH,     _e_policy_cb_hook_client_eval_post_fetch,     NULL);
2284    E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_POST_NEW_CLIENT,_e_policy_cb_hook_client_eval_post_new_client,NULL);
2285    E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_EVAL_VISIBILITY,     _e_policy_cb_hook_client_visibility,          NULL);
2286    E_CLIENT_HOOK_APPEND(hooks_ec,  E_CLIENT_HOOK_UNICONIFY,           _e_policy_cb_hook_client_uniconify,           NULL);
2287
2288    E_PIXMAP_HOOK_APPEND(hooks_cp,  E_PIXMAP_HOOK_DEL,                 _e_policy_cb_hook_pixmap_del,                 NULL);
2289    E_PIXMAP_HOOK_APPEND(hooks_cp,  E_PIXMAP_HOOK_UNUSABLE,            _e_policy_cb_hook_pixmap_unusable,            NULL);
2290
2291    _e_pol_idle_enterer = ecore_idle_enterer_add(_e_policy_cb_idle_enterer, NULL);
2292
2293    e_policy_conformant_init();
2294    e_policy_visibility_init();
2295
2296    return EINA_TRUE;
2297 }
2298
2299 EINTERN int
2300 e_policy_shutdown(void)
2301 {
2302    E_Policy *pol = e_policy;
2303    Eina_Inlist *l;
2304    E_Policy_Softkey *softkey;
2305
2306    eina_list_free(_e_pol_changed_zone);
2307    eina_list_free(pol->launchers);
2308    EINA_INLIST_FOREACH_SAFE(pol->softkeys, l, softkey)
2309      e_policy_softkey_del(softkey);
2310
2311    E_FREE_LIST(hooks_cp, e_pixmap_hook_del);
2312    E_FREE_LIST(hooks_ec, e_client_hook_del);
2313    E_FREE_LIST(handlers, ecore_event_handler_del);
2314
2315    E_FREE_FUNC(hash_policy_desks, eina_hash_free);
2316    E_FREE_FUNC(hash_policy_clients, eina_hash_free);
2317
2318    e_policy_stack_shutdown();
2319    e_policy_wl_shutdown();
2320
2321    e_policy_conformant_shutdown();
2322    e_policy_visibility_shutdown();
2323
2324    E_FREE(pol);
2325
2326    e_policy = NULL;
2327
2328    return 1;
2329 }