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