2 * activity : The client which has full screen size and normal type.
3 * foreground : The client which is unobscured.
4 * background : The client which is fully obscured by others.
7 #include "e_policy_visibility_intern.h"
8 #include "e_policy_intern.h"
9 #include "e_comp_wl_rsm_intern.h"
10 #include "e_comp_intern.h"
11 #include "e_policy_wl_intern.h"
12 #include "e_client_intern.h"
13 #include "e_comp_object_intern.h"
14 #include "e_config_intern.h"
18 # undef TRACE_DS_BEGIN
21 # define TRACE_DS_BEGIN(NAME) traceBegin(TTRACE_TAG_WINDOW_MANAGER, "DS:POL:"#NAME)
22 # define TRACE_DS_END() traceEnd(TTRACE_TAG_WINDOW_MANAGER)
24 # define TRACE_DS_BEGIN(NAME)
25 # define TRACE_DS_END()
28 typedef enum _E_Pol_Vis_Type
30 E_POL_VIS_TYPE_NON_ALPHA,
32 E_POL_VIS_TYPE_ALPHA_OPAQUE,
35 struct _E_Pol_Vis_Hook
38 E_Pol_Vis_Hook_Type type;
44 static Eina_Bool _e_policy_check_transient_child_visible(E_Client *ancestor_ec, E_Client *ec);
45 static Eina_Bool _e_policy_check_above_alpha_opaque(E_Client *ec);
46 static void _e_policy_client_iconify_by_visibility(E_Client *ec);
47 static void _e_policy_client_ancestor_uniconify(E_Client *ec);
48 static void _e_policy_client_below_uniconify(E_Client *ec);
49 static void _e_policy_client_uniconify_by_visibility(E_Client *ec);
51 static inline Eina_Bool _e_vis_client_is_grabbed(E_Vis_Client *vc);
52 static void _e_vis_client_grab_remove(E_Vis_Client *vc, E_Vis_Grab *grab);
53 static Eina_Bool _e_vis_client_grab_cancel(E_Vis_Client *vc);
54 static void _e_vis_client_job_exec(E_Vis_Client *vc, E_Vis_Job_Type type);
55 static Eina_Bool _e_vis_grab_job_filter(E_Vis_Grab *grab, E_Vis_Job_Type type);
56 static Eina_Bool _e_vis_ec_activity_check(E_Client *ec, Eina_Bool check_alpha, Eina_Bool check_fullsize);
57 static void _e_vis_client_job_exec_by_type(E_Vis_Client *vc, E_Vis_Job_Type type);
58 static void _e_vis_ec_setup(E_Client *ec);
59 static void _e_vis_ec_reset(E_Client *ec);
60 static E_Pol_Vis_Type _e_vis_ec_above_visible_type(E_Client *ec, Eina_Bool check_child);
61 static Eina_Bool _e_vis_ec_below_uniconify(E_Client *ec, E_Pol_Vis_Type above_vis_type);
62 static void _e_vis_cb_child_launch_done(void *data, Evas_Object *obj, const char *signal, const char *source);
63 static void _e_vis_update_foreground_job_queue(void);
64 static void _e_vis_update_forground_list(void);
65 static Eina_Bool _e_vis_client_check_send_pre_visibility(E_Vis_Client *vc, Eina_Bool raise);
67 static E_Vis *pol_vis = NULL;
68 /* the list for E_Vis_Job */
69 static E_Vis_Job_Group *pol_job_group = NULL;
70 /* the head of list for E_Vis_Job_Group */
71 static Eina_Clist pol_job_group_head = EINA_CLIST_INIT(pol_job_group_head);
73 static Eina_Bool pol_job_exec_walking = EINA_FALSE;
74 static Eina_Bool pol_vis_disable_norender = EINA_FALSE;
76 static Eina_Inlist *_e_pol_vis_hooks[] =
78 [E_POL_VIS_HOOK_TYPE_FG_SET] = NULL,
79 [E_POL_VIS_HOOK_TYPE_UNICONIFY_RENDER_RUNNING] = NULL,
80 [E_POL_VIS_HOOK_TYPE_LOWER] = NULL,
81 [E_POL_VIS_HOOK_TYPE_HIDE] = NULL,
84 static int _e_pol_vis_hooks_delete = 0;
85 static int _e_pol_vis_hooks_walking = 0;
87 static inline Eina_Bool
88 _e_vis_client_is_grabbed(E_Vis_Client *vc)
90 return !!vc->job.grab_list;
93 static inline Eina_Bool
94 _e_vis_client_is_iconic(E_Vis_Client *vc)
96 return (vc->state == E_VIS_ICONIFY_STATE_ICONIC);
99 static inline Eina_Bool
100 _e_vis_client_is_uniconic(E_Vis_Client *vc)
102 return (vc->state == E_VIS_ICONIFY_STATE_UNICONIC);
105 static inline Eina_Bool
106 _e_vis_client_is_uniconify_render_running(E_Vis_Client *vc)
108 return (vc->state == E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY);
111 static inline Eina_Bool
112 _e_vis_client_is_uniconify_render_running_done(E_Vis_Client *vc)
114 return (vc->state == E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY_RENDER_DONE);
118 _e_vis_client_below_uniconify_skip_set(E_Vis_Client *vc, Eina_Bool skip)
120 vc->skip_below_uniconify = skip;
123 static inline Eina_Bool
124 _e_vis_client_is_below_uniconify_skip(E_Vis_Client *vc)
126 return (vc->skip_below_uniconify == EINA_TRUE);
130 _e_pol_vis_hooks_clean(void)
136 for (x = 0; x < E_POL_VIS_HOOK_TYPE_LAST; x++)
137 EINA_INLIST_FOREACH_SAFE(_e_pol_vis_hooks[x], l, h)
139 if (!h->delete_me) continue;
140 _e_pol_vis_hooks[x] = eina_inlist_remove(_e_pol_vis_hooks[x],
147 _e_pol_vis_hook_call(E_Pol_Vis_Hook_Type type, E_Client *ec)
151 e_object_ref(E_OBJECT(ec));
153 _e_pol_vis_hooks_walking++;
154 EINA_INLIST_FOREACH(_e_pol_vis_hooks[type], h)
156 if (h->delete_me) continue;
159 _e_pol_vis_hooks_walking--;
161 if ((_e_pol_vis_hooks_walking == 0) &&
162 (_e_pol_vis_hooks_delete > 0))
163 _e_pol_vis_hooks_clean();
165 return !!e_object_unref(E_OBJECT(ec));
169 _e_policy_check_transient_child_visible(E_Client *ancestor_ec, E_Client *ec)
171 Eina_Bool visible = EINA_FALSE;
172 Eina_List *list = NULL;
173 E_Client *child_ec = NULL;
174 int anc_x, anc_y, anc_w, anc_h;
175 int child_x, child_y, child_w, child_h;
177 if (!ancestor_ec) return EINA_FALSE;
179 e_client_geometry_get(ancestor_ec, &anc_x, &anc_y, &anc_w, &anc_h);
181 list = eina_list_clone(ec->transients);
182 EINA_LIST_FREE(list, child_ec)
184 if (visible == EINA_TRUE) continue;
186 if (!child_ec->comp_data) continue;
187 if (!child_ec->comp_data->mapped && !child_ec->use_splash) continue;
188 if (e_client_transient_policy_get(child_ec) == E_TRANSIENT_BELOW) continue;
190 if ((child_ec->exp_iconify.skip_iconify == EINA_TRUE) ||
191 (child_ec->exp_iconify.skip_by_remote == EINA_TRUE))
193 if (e_client_visibility_get(child_ec) == E_VISIBILITY_UNOBSCURED)
195 ELOGF("Find visible child", "ancestor(win:0x%08zx, ec:%p), child(win:0x%08zx, ec:%p)",
197 e_client_util_win_get(ancestor_ec), ancestor_ec,
198 e_client_util_win_get(child_ec), child_ec);
203 if (!child_ec->iconic)
205 e_client_geometry_get(child_ec, &child_x, &child_y, &child_w, &child_h);
206 if (E_CONTAINS(child_x, child_y, child_w, child_h, anc_x, anc_y, anc_w, anc_h))
208 ELOGF("Find visible child", "ancestor(win:0x%08zx, ec:%p), child(win:0x%08zx, ec:%p)",
210 e_client_util_win_get(ancestor_ec), ancestor_ec,
211 e_client_util_win_get(child_ec), child_ec);
219 if ((!child_ec->iconic && (e_client_visibility_get(child_ec) != E_VISIBILITY_UNKNOWN)) ||
220 (e_client_visibility_get(child_ec) == E_VISIBILITY_UNOBSCURED))
222 ELOGF("Find visible child", "ancestor(win:0x%08zx, ec:%p), child(win:0x%08zx, ec:%p, iconic:%d, vis:%d)",
224 e_client_util_win_get(ancestor_ec), ancestor_ec,
225 e_client_util_win_get(child_ec), child_ec, child_ec->iconic, e_client_visibility_get(child_ec));
230 visible = _e_policy_check_transient_child_visible(ancestor_ec, child_ec);
237 _e_policy_check_above_alpha_opaque(E_Client *ec)
241 Eina_Bool alpha_opaque = EINA_FALSE;
245 e_client_geometry_get(ec, &ex, &ey, &ew, &eh);
247 for (o = evas_object_above_get(ec->frame); o; o = evas_object_above_get(o))
249 above_ec = evas_object_data_get(o, "E_Client");
250 if (!above_ec) continue;
251 if (e_client_util_ignored_get(above_ec)) continue;
252 if (above_ec->comp_data && !above_ec->comp_data->mapped) continue;
254 e_client_geometry_get(above_ec, &ax, &ay, &aw, &ah);
255 if (!E_CONTAINS(ax, ay, aw, ah, ex, ey, ew, eh)) continue;
259 if (above_ec->visibility.opaque <= 0)
263 if (e_client_visibility_get(above_ec) == E_VISIBILITY_UNOBSCURED)
265 alpha_opaque = EINA_TRUE;
269 if (!above_ec->iconic)
271 if (above_ec->comp_data && above_ec->comp_data->mapped)
272 alpha_opaque = EINA_TRUE;
284 _e_policy_client_iconify_by_visibility(E_Client *ec)
286 int skip_iconify = 0;
288 if (e_config->transient.iconify)
290 if (_e_policy_check_transient_child_visible(ec, ec))
296 if (e_comp_client_zone_is_displaying(ec))
298 // check above window is alpha opaque or not
299 if (_e_policy_check_above_alpha_opaque(ec))
307 ELOGF("SKIP.. ICONIFY_BY_WM", "win:0x%08zx cause_type:%d", ec, e_client_util_win_get(ec), skip_iconify);
309 _e_vis_update_forground_list();
313 ELOGF("ICONIFY_BY_WM", "win:0x%08zx", ec, e_client_util_win_get(ec));
314 e_policy_wl_iconify_state_change_send(ec, 1);
315 e_client_iconified_type_set(ec, E_ICONIFIED_TYPE_VISIBILITY);
316 e_client_iconify(ec);
318 /* if client has obscured parent, try to iconify the parent also */
321 if (e_client_visibility_get(ec->parent) == E_VISIBILITY_FULLY_OBSCURED)
323 e_policy_client_iconify_by_visibility(ec->parent);
325 E_VIS_CLIENT_GET(vc, ec->parent);
328 if (_e_vis_client_is_uniconify_render_running(vc))
330 VS_INF(ec, "Uniconify render because parent(win:%zx, ec:%p)", e_client_util_win_get(ec->parent), ec->parent);
331 e_policy_visibility_client_uniconify(ec, !ec->parent->exp_iconify.not_raise);
339 _e_policy_client_ancestor_uniconify(E_Client *ec)
341 Eina_List *list = NULL;
343 E_Client *parent = NULL;
344 int transient_iconify = 0;
346 Eina_Bool ret = EINA_FALSE;
349 if (e_object_is_del(E_OBJECT(ec))) return;
350 if (!ec->iconic) return;
351 if (e_client_is_iconified_by_client(ec)) return;
352 if (ec->bg_state) return;
353 if (ec->exp_iconify.skip_iconify) return;
354 if (ec->exp_iconify.skip_by_remote) return;
361 // something strange state.
362 ELOGF("CHECK transient_for tree", "win:0x%08zx, parent:0x%08zx", NULL, e_client_util_win_get(ec), e_client_util_win_get(parent));
366 if (e_object_is_del(E_OBJECT(parent))) break;
367 if (!parent->iconic) break;
368 if (e_client_is_iconified_by_client(parent)) break;
369 if (parent->bg_state) break;
370 if (parent->exp_iconify.skip_iconify) break;
371 if (parent->exp_iconify.skip_by_remote) break;
373 if (eina_list_data_find(list, parent))
375 // very bad. there are loop for parenting
376 ELOGF("Very BAD. Circling transient_for window", "win:0x%08zx, parent:0x%08zx", NULL, e_client_util_win_get(ec), e_client_util_win_get(parent));
380 list = eina_list_prepend(list, parent);
381 parent = parent->parent;
383 // for preventing infiniting loop
387 transient_iconify = e_config->transient.iconify;
388 e_config->transient.iconify = 0;
391 EINA_LIST_FOREACH(list, l, parent)
393 ELOGF("UNICONIFY_BY_WM", "parent_win:0x%08zx", parent, e_client_util_win_get(parent));
394 ret = e_policy_visibility_client_uniconify(parent, 0);
397 parent->exp_iconify.not_raise = 1;
398 e_client_uniconify(parent);
399 e_policy_wl_iconify_state_change_send(parent, 0);
402 eina_list_free(list);
404 e_config->transient.iconify = transient_iconify;
408 _e_policy_client_below_uniconify(E_Client *ec)
413 for (o = evas_object_below_get(ec->frame); o; o = evas_object_below_get(o))
415 below_ec = evas_object_data_get(o, "E_Client");
416 if (!below_ec) continue;
417 if (e_client_util_ignored_get(below_ec)) continue;
419 if (ec->parent == below_ec) break;
420 if (!below_ec->iconic) break;
422 if (e_client_visibility_get(below_ec) == E_VISIBILITY_FULLY_OBSCURED)
424 e_policy_client_uniconify_by_visibility(below_ec);
432 _e_policy_client_uniconify_by_visibility(E_Client *ec)
434 Eina_Bool ret = EINA_FALSE;
436 _e_policy_client_ancestor_uniconify(ec);
438 ELOGF("UNICONIFY_BY_WM", "win:0x%08zx, argb:%d", ec, e_client_util_win_get(ec), ec->argb);
439 ret = e_policy_visibility_client_uniconify(ec, 0);
442 e_policy_visibility_client_hide_job_cancel(ec);
443 ec->exp_iconify.not_raise = 1;
444 e_client_uniconify(ec);
445 e_policy_wl_iconify_state_change_send(ec, 0);
448 if ((ec->visibility.opaque > 0) && (ec->argb))
450 _e_policy_client_below_uniconify(ec);
455 e_policy_client_visibility_send(E_Client *ec)
457 e_policy_wl_visibility_send(ec, e_client_visibility_get(ec));
461 e_policy_client_iconify_by_visibility(E_Client *ec)
463 E_Comp_Wl_Client_Data *cdata;
466 if (ec->iconic) return;
467 if (ec->bg_state) return;
468 if (ec->exp_iconify.skip_iconify) return;
469 if (ec->exp_iconify.skip_by_remote) return;
470 if (e_client_util_ignored_get(ec)) return;
471 if (e_client_is_iconified_by_client(ec)) return;
473 cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
474 if (cdata && !cdata->mapped) return;
476 _e_policy_client_iconify_by_visibility(ec);
480 e_policy_client_uniconify_by_visibility(E_Client *ec)
482 E_Comp_Wl_Client_Data *cdata;
485 if (e_object_is_del(E_OBJECT(ec))) return;
486 if (!ec->iconic) return;
487 if (e_client_is_iconified_by_client(ec)) return;
488 if (ec->bg_state) return;
489 if (ec->exp_iconify.skip_iconify) return;
490 if (ec->exp_iconify.skip_by_remote) return;
492 cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
493 if (cdata && !cdata->mapped) return;
495 _e_policy_client_uniconify_by_visibility(ec);
499 e_policy_client_iconic_state_change_send(E_Client *ec, int iconic)
502 e_policy_wl_iconify_state_change_send(ec, iconic);
506 _e_vis_clist_unlink(Eina_Clist *elem)
508 if (eina_clist_element_is_linked(elem))
509 eina_clist_remove(elem);
513 _e_vis_clist_clean(Eina_Clist *list, void (*free_func)(Eina_Clist *elem))
517 while ((elem = eina_clist_head(list)) != NULL)
519 eina_clist_remove(elem);
520 if (free_func) free_func(elem);
525 _e_vis_update_forground_list(void)
527 E_Client *ec, *fg_activity = NULL;
529 DBG("VISIBILITY | Update Foreground Client List");
531 /* clear list of fg_clients before updating */
532 E_FREE_FUNC(pol_vis->fg_clients, eina_list_free);
534 /* update foreground client list and find activity client */
535 E_CLIENT_REVERSE_FOREACH(ec)
537 /* TODO: check if client is included to zone of mobile */
538 if (!evas_object_visible_get(ec->frame)) continue;
540 pol_vis->fg_clients = eina_list_append(pol_vis->fg_clients, ec);
541 if (_e_vis_ec_activity_check(ec, EINA_TRUE, EINA_TRUE))
548 if (pol_vis->activity != fg_activity)
550 DBG("VISIBILITY | \tPrev: %s(%p)", pol_vis->activity ? NAME(pol_vis->activity) : "", pol_vis->activity);
551 DBG("VISIBILITY | \tNew : %s(%p)", fg_activity ? NAME(fg_activity) : "", fg_activity);
552 pol_vis->activity = fg_activity;
553 /* TODO do we need to raise event like E_EVENT_VISIBILITY_ACTIVITY_CHANGE? */
554 _e_pol_vis_hook_call(E_POL_VIS_HOOK_TYPE_FG_SET, fg_activity);
559 _e_vis_update_cb_job(void *data EINA_UNUSED)
561 if (pol_vis->job.bg_find)
563 _e_vis_update_forground_list();
564 pol_vis->job.bg_find = EINA_FALSE;
566 pol_vis->job.handler = NULL;
570 _e_vis_update_job_queue(void)
572 if (pol_vis->job.handler)
573 ecore_job_del(pol_vis->job.handler);
574 pol_vis->job.handler = ecore_job_add(_e_vis_update_cb_job, NULL);
578 _e_vis_update_foreground_job_queue(void)
580 pol_vis->job.bg_find = EINA_TRUE;
581 _e_vis_update_job_queue();
585 _e_vis_job_is_grabbed(E_Vis_Client *vc, E_Vis_Job_Type type)
590 EINA_LIST_FOREACH(vc->job.grab_list, l, grab)
592 if (_e_vis_grab_job_filter(grab, type))
600 _e_vis_job_push(E_Vis_Job *job)
604 pol_job_group = E_NEW(E_Vis_Job_Group, 1);
607 eina_clist_init(&pol_job_group->job_head);
609 eina_clist_add_tail(&pol_job_group->job_head, &job->entry);
614 _e_vis_job_find(E_Vis_Client *vc, E_Vis_Job_Type type)
616 E_Vis_Job_Group *group, *tmp_group;
617 E_Vis_Job *job, *tmp_job;
619 EINA_CLIST_FOR_EACH_ENTRY_SAFE(group, tmp_group,
620 &pol_job_group_head, E_Vis_Job_Group, entry)
622 EINA_CLIST_FOR_EACH_ENTRY_SAFE(job, tmp_job,
623 &group->job_head, E_Vis_Job, entry)
625 if (job->vc != vc) continue;
626 if (job->type == type)
635 _e_vis_job_add(E_Vis_Client *vc, E_Vis_Job_Type type, Ecore_Task_Cb timeout_func)
637 E_VIS_ALLOC_RET_VAL(job, E_Vis_Job, 1, EINA_FALSE);
638 if (!_e_vis_job_push(job))
645 job->timer = ecore_timer_add(e_config->deiconify_pending_timeout, timeout_func, job);
646 VS_INF(vc->ec, "NEW JOB:%p, type:%d", job, type);
652 _e_vis_job_del(Eina_Clist *elem)
656 _e_vis_clist_unlink(elem);
657 job = EINA_CLIST_ENTRY(elem, E_Vis_Job, entry);
659 VS_INF(job->vc->ec, "FREE JOB:%p, type:%d", job, job->type);
660 E_FREE_FUNC(job->timer, ecore_timer_del);
665 _e_vis_job_group_del(Eina_Clist *elem)
667 E_Vis_Job_Group *group;
669 _e_vis_clist_unlink(elem);
670 group = EINA_CLIST_ENTRY(elem, E_Vis_Job_Group, entry);
671 _e_vis_clist_clean(&group->job_head, _e_vis_job_del);
676 _e_vis_job_exec(Eina_Clist *elem)
680 _e_vis_clist_unlink(elem);
681 job = EINA_CLIST_ENTRY(elem, E_Vis_Job, entry);
685 VS_INF(job->vc->ec, "EXEC JOB:%p, type:%d (is_del ec:%d)", job, job->type, e_object_is_del(E_OBJECT(job->vc->ec)));
686 /* After calling the function below, ec may have been deleted.
687 * This is because the delayed ec deletion is perfromed in the following function.
688 * Therefore, be careful when leaving out detailed log message about deleted ec
689 * to avoid segmentation fault error.
691 _e_vis_client_job_exec(job->vc, job->type);
694 INF("VISIBILITY | FREE JOB:%p, type:%d", job, job->type);
695 E_FREE_FUNC(job->timer, ecore_timer_del);
700 _e_vis_job_group_exec(E_Vis_Job_Group *group)
702 _e_vis_clist_unlink(&group->entry);
703 _e_vis_clist_clean(&group->job_head, _e_vis_job_exec);
708 _e_vis_job_group_eval(E_Vis_Job_Group *group)
710 E_Vis_Job *job, *tmp;
712 EINA_CLIST_FOR_EACH_ENTRY_SAFE(job, tmp,
713 &group->job_head, E_Vis_Job, entry)
715 if (job->deleted) continue;
716 if (_e_vis_client_is_grabbed(job->vc))
723 _e_vis_job_group_state_update(E_Vis_Job_Group *group)
725 E_Vis_Job *job, *tmp;
726 EINA_CLIST_FOR_EACH_ENTRY_SAFE(job, tmp,
727 &group->job_head, E_Vis_Job, entry)
729 if (job->deleted) continue;
730 if (_e_vis_client_is_uniconify_render_running_done(job->vc))
732 job->vc->state = E_VIS_ICONIFY_STATE_UNICONIC;
733 VS_DBG(job->vc->ec, "\tUPDATE ICONIC STATE: %s", "UNICONIC");
739 _e_vis_job_queue_update(void)
741 if (!pol_job_group) return;
742 eina_clist_add_tail(&pol_job_group_head, &pol_job_group->entry);
743 pol_job_group = NULL;
746 /* FIXME just add a ecore job, and do real evaluate in the job. */
748 _e_vis_job_eval(void)
750 E_Vis_Job_Group *group, *tmp;
752 INF("VISIBILITY | Job Eval Begin");
754 _e_vis_job_queue_update();
756 pol_job_exec_walking = EINA_TRUE;
757 EINA_CLIST_FOR_EACH_ENTRY_SAFE(group, tmp, &pol_job_group_head,
758 E_Vis_Job_Group, entry)
760 /* if all of job in the group is ready */
761 if (!_e_vis_job_group_eval(group))
764 /* updates state to uniconic from render_done */
765 _e_vis_job_group_state_update(group);
767 /* execute all of job in the group */
768 _e_vis_job_group_exec(group);
770 pol_job_exec_walking = EINA_FALSE;
772 INF("VISIBILITY | Job Eval End");
776 _e_vis_job_cancel(E_Vis_Client *vc, E_Vis_Job_Type type)
778 Eina_Bool ret = EINA_FALSE;
779 E_Vis_Job_Group *group, *tmp_group;
780 E_Vis_Job *job, *tmp_job;
782 /* update queue before deleting */
783 _e_vis_job_queue_update();
785 EINA_CLIST_FOR_EACH_ENTRY_SAFE(group, tmp_group,
786 &pol_job_group_head, E_Vis_Job_Group, entry)
788 EINA_CLIST_FOR_EACH_ENTRY_SAFE(job, tmp_job,
789 &group->job_head, E_Vis_Job, entry)
791 if (job->vc != vc) continue;
792 if (job->type != type) continue;
794 VS_INF(vc->ec, "Find Job:%p, type:%d", job, type);
795 _e_vis_job_del(&job->entry);
797 VS_INF(vc->ec, "Decrease VC JOB count:%d by cancel", vc->job.count);
800 if (!eina_clist_empty(&group->job_head)) continue;
801 _e_vis_job_group_del(&group->entry);
804 /* evaluate job list after deleting an element */
811 _e_vis_job_del_by_client(E_Vis_Client *vc)
813 E_Vis_Job_Group *group, *tmp_group;
814 E_Vis_Job *job, *tmp_job;
816 /* update queue before deleting */
817 _e_vis_job_queue_update();
819 EINA_CLIST_FOR_EACH_ENTRY_SAFE(group, tmp_group,
820 &pol_job_group_head, E_Vis_Job_Group, entry)
822 EINA_CLIST_FOR_EACH_ENTRY_SAFE(job, tmp_job,
823 &group->job_head, E_Vis_Job, entry)
825 if (job->vc != vc) continue;
827 if (pol_job_exec_walking)
828 job->deleted = EINA_TRUE;
830 _e_vis_job_del(&job->entry);
832 if (!eina_clist_empty(&group->job_head)) continue;
833 _e_vis_job_group_del(&group->entry);
836 /* evaluate job list after deleting an element */
837 if (!pol_job_exec_walking)
842 _e_vis_grab_new(E_Vis_Client *vc, E_Vis_Job_Type type, const char *name, Ecore_Task_Cb timeout_func)
844 E_VIS_ALLOC_RET_VAL(grab, E_Vis_Grab, 1, NULL);
847 grab->name = eina_stringshare_add(name);
848 grab->timer = ecore_timer_add(e_config->deiconify_pending_timeout, timeout_func, grab);
854 _e_vis_grab_del(E_Vis_Grab *grab)
856 E_FREE_FUNC(grab->timer, ecore_timer_del);
857 E_FREE_FUNC(grab->name, eina_stringshare_del);
862 _e_vis_grab_release(E_Vis_Grab *grab)
865 _e_vis_client_grab_remove(grab->vc, grab);
867 _e_vis_grab_del(grab);
871 _e_vis_grab_job_filter(E_Vis_Grab *grab, E_Vis_Job_Type job_type)
873 return grab->type & job_type;
877 _e_vis_client_cb_buffer_attach(void *data, int type EINA_UNUSED, void *event)
883 E_Client *provider_ec;
888 provider_ec = e_comp_wl_remote_surface_bound_provider_ec_get(vc->ec);
889 if (vc->ec != ev->ec && provider_ec != ev->ec)
894 VS_INF(ec, "FINISH Uniconify render(ev:%p, vc:%p, provider:%p)", ev->ec, vc->ec, provider_ec);
897 * NOTE: this update can invoke some functions related to visibility grab */
898 /* if comp_object is not redirected, the compositor doesn't want to update it */
899 if (e_comp_object_redirected_get(ec->frame))
901 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
902 e_comp_object_dirty(ec->frame);
903 e_comp_object_render(ec->frame);
906 l = eina_list_clone(vc->wait_buf_attach_grab_list);
907 vc->wait_buf_attach_grab_list = eina_list_free(vc->wait_buf_attach_grab_list);
908 EINA_LIST_FREE(l, grab)
910 E_FREE_FUNC(grab, _e_vis_grab_release);
913 E_FREE_FUNC(vc->buf_attach, ecore_event_handler_del);
915 return ECORE_CALLBACK_PASS_ON;
919 _e_vis_client_buffer_attach_handler_add(E_Vis_Client *vc, E_Vis_Grab *grab)
921 vc->wait_buf_attach_grab_list = eina_list_append(vc->wait_buf_attach_grab_list, grab);
927 ecore_event_handler_add(E_EVENT_CLIENT_BUFFER_CHANGE,
928 _e_vis_client_cb_buffer_attach, vc);
932 _e_vis_client_job_exec(E_Vis_Client *vc, E_Vis_Job_Type type)
934 // Check if pol_vis is already deleted.
935 if (!pol_vis) goto done;
936 if (!vc->ec) goto done;
938 // Check if the vc->ec is already deleted and there is no data in clients_hash.
939 if (!eina_hash_find(pol_vis->clients_hash, &vc->ec)) goto done;
943 case E_VIS_JOB_TYPE_ACTIVATE:
944 case E_VIS_JOB_TYPE_UNICONIFY:
945 case E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY:
946 /* check previous state first */
947 if (vc->state != E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY_WAITING_FOR_CHILD)
948 vc->state = E_VIS_ICONIFY_STATE_UNICONIC;
950 case E_VIS_JOB_TYPE_SHOW:
951 vc->state = E_VIS_ICONIFY_STATE_UNICONIC;
957 VS_DBG(vc->ec, "\tUPDATE ICONIC STATE: %s", STATE_STR(vc));
959 _e_vis_client_job_exec_by_type(vc, type);
963 VS_INF(vc->ec, "Decrease VC JOB count:%d", vc->job.count);
965 if (vc->job.count == 0)
967 if (vc->ec && e_object_is_del(E_OBJECT(vc->ec)))
969 /* all of enqueued job is executed */
970 VS_INF(vc->ec, "Deleted Client: UNREF Delay Del");
971 e_pixmap_free(vc->ec->pixmap);
972 e_object_delay_del_unref(E_OBJECT(vc->ec));
978 _e_vis_client_grab_add(E_Vis_Client *vc, E_Vis_Grab *grab)
980 VS_INF(vc->ec, "Add Client Visibility Grab: %p(%s)", grab, grab->name);
982 vc->job.grab_list = eina_list_append(vc->job.grab_list, grab);
986 _e_vis_client_grab_remove(E_Vis_Client *vc, E_Vis_Grab *grab)
988 VS_INF(vc->ec, "Remove Client Visibility Grab: %p(%s)", grab, grab->name);
990 if (!vc->job.grab_list)
992 VS_ERR(vc->ec, "The list of grab is empty");
996 vc->job.grab_list = eina_list_remove(vc->job.grab_list, grab);
997 if (!vc->job.grab_list)
999 if (vc->state == E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY)
1001 vc->state = E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY_RENDER_DONE;
1002 VS_DBG(vc->ec, "\tUPDATE ICONIC STATE: %s", STATE_STR(vc));
1010 _e_vis_client_grab_cb_timeout(void *data)
1012 E_Vis_Grab *grab = data;
1013 if (!grab) return ECORE_CALLBACK_DONE;
1015 ELOGF("POL_VIS", "TIMEOUT(%f) Grab(%p), name: %s", NULL, e_config->deiconify_pending_timeout, grab, grab->name);
1016 ELOGF("POL_VIS", "Info is_del:%d", grab->vc->ec, e_object_is_del(E_OBJECT(grab->vc->ec)));
1019 _e_vis_client_grab_remove(grab->vc, grab);
1021 return ECORE_CALLBACK_DONE;
1025 _e_vis_client_grab_get(E_Vis_Client *vc, E_Vis_Job_Type type, const char *name)
1029 grab = _e_vis_grab_new(vc, type, name, _e_vis_client_grab_cb_timeout);
1033 VS_INF(vc->ec, "Get job Grab(%p), name: %s", grab, name);
1035 _e_vis_client_grab_add(vc, grab);
1041 _e_vis_client_grab_cancel(E_Vis_Client *vc)
1043 EINA_SAFETY_ON_NULL_RETURN_VAL(vc, EINA_FALSE);
1045 if (_e_vis_client_is_uniconify_render_running(vc))
1047 vc->state = E_VIS_ICONIFY_STATE_ICONIC;
1048 VS_DBG(vc->ec, "\tUPDATE ICONIC STATE: %s", STATE_STR(vc));
1050 VS_INF(vc->ec, "Visibility changed while waiting Uniconify. Release grab.");
1051 E_FREE_FUNC(vc->grab, _e_vis_grab_release);
1056 l = eina_list_clone(vc->wait_buf_attach_grab_list);
1057 vc->wait_buf_attach_grab_list = eina_list_free(vc->wait_buf_attach_grab_list);
1058 EINA_LIST_FREE(l, grab)
1060 E_FREE_FUNC(grab, _e_vis_grab_release);
1070 _e_vis_client_cb_evas_show(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1072 OBJ_EC_GET(ec, obj);
1073 VS_DBG(ec, "CALLBACK 'SHOW'...");
1074 _e_vis_update_foreground_job_queue();
1075 E_VIS_CLIENT_GET_OR_RETURN(vc, ec);
1076 if (vc->state != E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY)
1078 vc->state = E_VIS_ICONIFY_STATE_UNICONIC;
1079 VS_DBG(ec, "\tUPDATE ICONIC STATE: %s", "UNICONIC");
1084 _e_vis_client_cb_evas_hide(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1086 OBJ_EC_GET(ec, obj);
1087 VS_DBG(ec, "CALLBACK 'HIDE'...");
1088 _e_vis_update_foreground_job_queue();
1089 E_VIS_CLIENT_GET_OR_RETURN(vc, ec);
1090 vc->state = ec->iconic ? E_VIS_ICONIFY_STATE_ICONIC : E_VIS_ICONIFY_STATE_UNICONIC;
1091 VS_DBG(ec, "\tUPDATE ICONIC STATE: %s", STATE_STR(vc));
1092 vc->prepare_emitted = 0;
1094 if (ec->iconic && ec->exp_iconify.buffer_flush)
1095 e_pixmap_buffer_clear(ec->pixmap, EINA_FALSE);
1099 _e_vis_client_cb_evas_move(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1104 OBJ_EC_GET(ec, obj);
1105 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1106 visible = evas_object_visible_get(obj);
1107 VS_DBG(ec, "CALLBACK 'MOVE'... %d %d (v %d)", x, y, visible);
1108 if (visible) _e_vis_update_foreground_job_queue();
1112 _e_vis_client_cb_evas_resize(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
1117 OBJ_EC_GET(ec, obj);
1118 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1119 visible = evas_object_visible_get(obj);
1120 VS_DBG(ec, "CALLBACK 'RESIZE'... %d %d (v %d)", w, h, visible);
1121 if (visible) _e_vis_update_foreground_job_queue();
1125 _e_vis_client_cb_evas_restack(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
1129 OBJ_EC_GET(ec, obj);
1130 visible = evas_object_visible_get(obj);
1131 VS_DBG(ec, "CALLBACK 'RESTACK'... v %d", visible);
1132 if (visible) _e_vis_update_foreground_job_queue();
1136 _e_vis_client_grab_clear_cb(void *data)
1138 E_Vis_Grab *grab = data;
1139 E_Pol_Vis_Type above_vis_type;
1141 VS_INF(grab->vc->ec, "FORCE CLEAR! Grab %s, cur state:%d", grab->name, grab->vc->state);
1144 if (grab->vc->state == E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY)
1146 above_vis_type = _e_vis_ec_above_visible_type(grab->vc->ec, EINA_FALSE);
1147 if (above_vis_type != E_POL_VIS_TYPE_NON_ALPHA)
1148 _e_vis_ec_below_uniconify(grab->vc->ec, above_vis_type);
1152 _e_vis_client_grab_remove(grab->vc, grab);
1154 return ECORE_CALLBACK_DONE;
1158 _e_vis_client_delay_del(E_Object *obj)
1162 ec = (E_Client *)obj;
1163 E_VIS_CLIENT_GET_OR_RETURN(vc, ec);
1166 VS_INF(ec, "REF Delay Del");
1167 e_pixmap_ref(ec->pixmap);
1168 e_object_delay_del_ref(obj);
1171 E_FREE_FUNC(vc->grab->timer, ecore_timer_del);
1172 vc->grab->timer = ecore_timer_add(E_CLEAR_GRAB_TIMEOUT, _e_vis_client_grab_clear_cb, vc->grab);
1177 EINA_LIST_FOREACH(vc->wait_buf_attach_grab_list, l, grab)
1179 E_FREE_FUNC(grab->timer, ecore_timer_del);
1180 grab->timer = ecore_timer_add(E_CLEAR_GRAB_TIMEOUT, _e_vis_client_grab_clear_cb, grab);
1186 _e_vis_client_job_timeout(void *data)
1188 E_Vis_Job *job = data;
1189 if (!job) return ECORE_CALLBACK_DONE;
1191 ELOGF("POL_VIS", "TIMEOUT(%f) JOB:%p, type:%d", NULL, e_config->deiconify_pending_timeout, job, job->type);
1192 ELOGF("POL_VIS", "Info is_del:%d", job->vc->ec, e_object_is_del(E_OBJECT(job->vc->ec)));
1195 /* FIXME delete all grab and evaluate it instead of exec */
1196 _e_vis_job_exec(&job->entry);
1199 return ECORE_CALLBACK_DONE;
1203 _e_vis_client_job_add(E_Vis_Client *vc, E_Vis_Job_Type type)
1205 VS_DBG(vc->ec, "Add Job: type %d", type);
1207 if (!_e_vis_job_add(vc, type, _e_vis_client_job_timeout))
1211 VS_INF(vc->ec, "Increase VC JOB count:%d", vc->job.count);
1215 _e_vis_client_del(E_Vis_Client *vc)
1220 VS_INF(vc->ec, "CLIENT DEL");
1222 l = eina_list_clone(vc->wait_buf_attach_grab_list);
1223 vc->wait_buf_attach_grab_list = eina_list_free(vc->wait_buf_attach_grab_list);
1224 EINA_LIST_FREE(l, grab)
1226 VS_INF(vc->ec, "Remove remain grab(%p) in wait_buf_attach list", grab);
1227 E_FREE_FUNC(grab, _e_vis_grab_release);
1230 E_FREE_FUNC(vc->grab, _e_vis_grab_release);
1231 E_LIST_REVERSE_FREE(vc->job.grab_list, grab)
1233 VS_INF(vc->ec, "CRI... Not handled grab (%p)", grab);
1237 /* if it's intended normal operation, there is no job to delete. */
1238 _e_vis_job_del_by_client(vc);
1239 /* clear event handler of E_Client */
1240 _e_vis_ec_reset(vc->ec);
1241 /* delete buffer attach handler for client */
1242 E_FREE_FUNC(vc->buf_attach, ecore_event_handler_del);
1248 _e_vis_client_add(E_Client *ec)
1250 VS_DBG(ec, "CLIENT ADD");
1252 if (e_policy_client_is_subsurface(ec))
1255 E_VIS_ALLOC_RET(vc, E_Vis_Client, 1);
1258 _e_vis_ec_setup(ec);
1259 eina_hash_add(pol_vis->clients_hash, &ec, vc);
1263 _e_vis_client_prepare_foreground_signal_emit(E_Vis_Client *vc)
1265 /* TODO should emit signal only if it's real foreground. */
1266 if (vc->prepare_emitted)
1268 vc->prepare_emitted = 1;
1269 evas_object_smart_callback_call(vc->ec->frame, "e,visibility,prepare,foreground", vc->ec);
1273 e_vis_client_send_pre_visibility_event(E_Client *ec)
1275 Eina_Bool intercepted;
1278 if ((ec->visibility.last_sent_type == E_VISIBILITY_PRE_UNOBSCURED) ||
1279 (ec->visibility.last_sent_type == E_VISIBILITY_UNOBSCURED))
1282 intercepted = e_policy_interceptor_call(E_POLICY_INTERCEPT_SEND_PRE_VISIBILITY, ec);
1285 ELOGF("POL_VIS", "Handled by Intercept function", ec);
1289 e_policy_wl_visibility_send(ec, E_VISIBILITY_PRE_UNOBSCURED);
1293 e_vis_client_check_send_pre_visibility_event(E_Client *ec, Eina_Bool raise)
1297 E_VIS_CLIENT_GET_OR_RETURN(vc, ec);
1299 if (_e_vis_client_check_send_pre_visibility(vc, raise))
1301 ELOGF("POL_VIS", "SEND pre-unobscured visibility event", ec);
1302 e_vis_client_send_pre_visibility_event(ec);
1307 _e_vis_client_is_uniconify_render_necessary(E_Vis_Client *vc)
1309 E_Client *ec = NULL;
1310 if (vc) ec = vc->ec;
1311 if (!ec) return EINA_FALSE;
1312 if (!ec->exp_iconify.buffer_flush)
1314 if (ec && ec->exp_iconify.deiconify_update) // hint or conf->deiconify_approve set deiconify update 1
1315 goto need_deiconify_render;
1317 VS_INF(ec, "Not necessary deiconify rendering");
1321 need_deiconify_render:
1322 if (_e_vis_client_is_uniconic(vc))
1324 VS_INF(vc->ec, "Already uniconic state");
1332 _e_vis_client_check_obscured_by_children(E_Client *ec)
1334 Eina_Bool obscured = EINA_FALSE;
1335 E_Client *child = NULL;
1336 const Eina_List *l = NULL;
1340 e_client_geometry_get(ec, &ex, &ey, &ew, &eh);
1342 EINA_LIST_FOREACH(ec->transients, l, child)
1344 if (e_client_transient_policy_get(child) == E_TRANSIENT_BELOW)
1347 e_client_geometry_get(child, &cx, &cy, &cw, &ch);
1348 if (!E_CONTAINS(cx, cy, cw, ch, ex, ey, ew, eh)) continue;
1352 ELOGF("POL_VIS", "Fully Obscured by child (win:%zx, child:%p)",
1353 ec, e_client_util_win_get(child), child);
1354 obscured = EINA_TRUE;
1359 if (child->visibility.opaque > 0)
1361 ELOGF("POL_VIS", "Fully Obscured by alpha opaque child (win:%zx, child:%p)",
1362 ec, e_client_util_win_get(child), child);
1363 obscured = EINA_TRUE;
1373 _e_vis_client_check_obscured_by_same_layer(E_Client *ec)
1375 Eina_Bool obscured = EINA_FALSE;
1376 E_Client *above = NULL;
1380 e_client_geometry_get(ec, &ex, &ey, &ew, &eh);
1382 for (above = e_client_above_get(ec); above; above = e_client_above_get(above))
1384 if (above->layer > ec->layer) break;
1385 if (e_client_util_ignored_get(above)) continue;
1386 if (e_object_is_del(E_OBJECT(above))) continue;
1387 if (above->iconic && e_client_is_iconified_by_client(above)) continue;
1388 if (above->bg_state) continue;
1389 if (above->comp_data && !above->comp_data->mapped) continue;
1391 e_client_geometry_get(above, &ax, &ay, &aw, &ah);
1392 if (!E_CONTAINS(ax, ay, aw, ah, ex, ey, ew, eh)) continue;
1396 ELOGF("POL_VIS", "Fully Obscured by above (win:%zx, ec:%p, layer:%d)",
1397 ec, e_client_util_win_get(above), above, above->layer);
1398 obscured = EINA_TRUE;
1403 if (above->visibility.opaque <= 0)
1407 ELOGF("POL_VIS", "Fully Obscured by alpha opaque above (win:%zx, ec:%p, layer:%d)",
1408 ec, e_client_util_win_get(above), above, above->layer);
1409 obscured = EINA_TRUE;
1419 _e_vis_client_check_obscured_by_above_layers(E_Client *ec)
1421 Eina_Bool obscured = EINA_FALSE;
1422 E_Client *above = NULL;
1426 e_client_geometry_get(ec, &ex, &ey, &ew, &eh);
1428 for (above = e_client_above_get(ec); above; above = e_client_above_get(above))
1430 if (above->layer <= ec->layer) continue;
1431 if (e_client_util_ignored_get(above)) continue;
1432 if (e_object_is_del(E_OBJECT(above))) continue;
1433 if (above->iconic && e_client_is_iconified_by_client(above)) continue;
1434 if (above->bg_state) continue;
1435 if (above->comp_data && !above->comp_data->mapped) continue;
1437 e_client_geometry_get(above, &ax, &ay, &aw, &ah);
1438 if (!E_CONTAINS(ax, ay, aw, ah, ex, ey, ew, eh)) continue;
1442 ELOGF("POL_VIS", "Fully Obscured by above (win:%zx, ec:%p, layer:%d)",
1443 ec, e_client_util_win_get(above), above, above->layer);
1444 obscured = EINA_TRUE;
1449 if (above->visibility.opaque <= 0)
1453 ELOGF("POL_VIS", "Fully Obscured by alpha opaque above (win:%zx, ec:%p, layer:%d)",
1454 ec, e_client_util_win_get(above), above, above->layer);
1455 obscured = EINA_TRUE;
1465 _e_vis_client_check_send_pre_visibility(E_Vis_Client *vc, Eina_Bool raise)
1467 Eina_Bool send_vis_event = EINA_TRUE;
1472 if (_e_vis_client_is_uniconic(vc))
1475 if (!e_comp_client_zone_is_displaying(ec))
1478 // check all windows on above layers, if obscured by above then return FALSE
1479 if (_e_vis_client_check_obscured_by_above_layers(ec))
1481 ELOGF("POL_VIS", "DO NOT Need to SEND pre-visibility.. obscured by above (above layer)", ec);
1487 // check above windows in same layer
1488 if (_e_vis_client_check_obscured_by_same_layer(ec))
1490 ELOGF("POL_VIS", "DO NOT Need to SEND pre-visibility.. obscured by above (same layer)", ec);
1491 send_vis_event = EINA_FALSE;
1498 // check children windows
1499 if (_e_vis_client_check_obscured_by_children(ec))
1501 ELOGF("POL_VIS", "DO NOT Need to SEND pre-visibility.. obscured by child", ec);
1502 send_vis_event = EINA_FALSE;
1507 return send_vis_event;
1511 _e_vis_client_add_uniconify_render_pending(E_Vis_Client *vc, E_Vis_Job_Type type, Eina_Bool raise, Eina_Bool force_send)
1514 Eina_Bool send_vis_event = EINA_TRUE;
1518 if (!e_comp_client_zone_is_displaying(ec))
1520 VS_DBG(ec, "Display off. no need to uniconify render.");
1524 if (ec->comp_data && !ec->comp_data->mapped)
1526 ELOGF("POL_VIS", "Not mapped. no need to uniconify render.", ec);
1530 /* do not add child window which is obscured by 24 bit parent window */
1532 !(ec->parent->argb) &&
1533 (e_client_transient_policy_get(ec) == E_TRANSIENT_BELOW))
1535 VS_INF(ec, "Transient below. no need to uniconify render.");
1539 if (_e_vis_client_is_uniconify_render_running(vc))
1543 send_vis_event = _e_vis_client_check_send_pre_visibility(vc, raise);
1547 ELOGF("POL_VIS", "SEND pre-unobscured visibility event", ec);
1548 e_vis_client_send_pre_visibility_event(ec);
1551 if (!_e_vis_client_is_uniconify_render_necessary(vc))
1554 if (_e_vis_client_is_uniconify_render_running_done(vc))
1557 ec->exp_iconify.not_raise = !raise;
1559 VS_DBG(ec, "BEGIN Uniconify render: raise %d", raise);
1561 _e_vis_client_prepare_foreground_signal_emit(vc);
1562 vc->state = E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY;
1563 VS_DBG(vc->ec, "\tUPDATE ICONIC STATE: %s", STATE_STR(vc));
1564 E_Vis_Grab *grab = _e_vis_client_grab_get(vc, type, __func__);
1565 _e_vis_client_buffer_attach_handler_add(vc, grab);
1567 e_policy_wl_iconify_state_change_send(ec, 0);
1568 _e_pol_vis_hook_call(E_POL_VIS_HOOK_TYPE_UNICONIFY_RENDER_RUNNING, ec);
1571 _e_vis_client_job_add(vc, type);
1577 _e_vis_client_defer_move(E_Vis_Client *vc, E_Vis_Job_Type type)
1579 if (!vc) return EINA_FALSE;
1581 VS_DBG(vc->ec, "\tDEFER MOVE: %s", STATE_STR(vc));
1582 E_Vis_Grab *grab = _e_vis_client_grab_get(vc, type, __func__);
1583 _e_vis_client_buffer_attach_handler_add(vc, grab);
1585 _e_vis_client_job_add(vc, type);
1590 static inline Eina_Bool
1591 _e_vis_ec_special_check(E_Client *ec)
1593 return ((e_policy_client_is_quickpanel(ec) && ec->argb)||
1594 e_policy_client_is_subsurface(ec) ||
1595 e_policy_client_is_keyboard(ec) ||
1596 e_policy_client_is_keyboard_sub(ec) ||
1597 e_policy_client_is_floating(ec));
1601 _e_vis_ec_activity_check(E_Client *ec, Eina_Bool check_alpha, Eina_Bool check_fullsize)
1604 E_Comp_Object_Content_Type type = E_COMP_OBJECT_CONTENT_TYPE_NONE;
1605 int check_mapped = 1;
1608 /* check if ignored */
1609 if (e_client_util_ignored_get(ec)) return EINA_FALSE;
1610 /* check transparent */
1611 if (check_alpha && ((ec->argb) && (ec->visibility.opaque <= 0))) return EINA_FALSE;
1612 /* check deleted client */
1613 if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1614 /* check launchscreen */
1615 if (ec->frame) type = e_comp_object_content_type_get(ec->frame);
1616 if ((type == E_COMP_OBJECT_CONTENT_TYPE_EXT_IMAGE) ||
1617 (type == E_COMP_OBJECT_CONTENT_TYPE_EXT_EDJE))
1619 /* check unmapped client */
1620 if (check_mapped && ec->comp_data && !ec->comp_data->mapped) return EINA_FALSE;
1621 /* check iconify window by client */
1622 if ((ec->iconic) && (e_client_is_iconified_by_client(ec))) return EINA_FALSE;
1623 /* check background state */
1624 if (ec->bg_state) return EINA_FALSE;
1625 /* check special client */
1626 if (_e_vis_ec_special_check(ec)) return EINA_FALSE;
1628 desk = e_comp_desk_find_by_ec(ec);
1629 if (!desk) return EINA_FALSE;
1631 /* check if full screen */
1632 e_client_geometry_get(ec, &x, &y, &w, &h);
1633 E_RECTS_CLIP_TO_RECT(x, y, w, h, desk->geom.x, desk->geom.y, desk->geom.w, desk->geom.h);
1634 if (check_fullsize &&
1635 !E_CONTAINS(x, y, w, h, desk->geom.x, desk->geom.y, desk->geom.w, desk->geom.h)) return EINA_FALSE;
1637 /* check if obscured by force */
1638 if (ec->visibility.force_obscured)
1645 _e_vis_client_job_exec_by_type(E_Vis_Client *vc, E_Vis_Job_Type type)
1647 E_Client *ec = vc->ec;
1649 VS_INF(ec, "Job Run: type %d", type);
1653 case E_VIS_JOB_TYPE_ACTIVATE:
1654 if (ec->visibility.force_obscured) break;
1655 e_client_activate(ec);
1656 if (e_policy_client_is_lockscreen(ec))
1657 e_policy_stack_clients_restack_above_lockscreen(ec, EINA_TRUE);
1659 e_policy_stack_check_above_lockscreen(ec, ec->layer);
1661 case E_VIS_JOB_TYPE_UNICONIFY:
1662 if (ec->visibility.force_obscured) break;
1663 e_client_uniconify(ec);
1665 case E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY:
1666 ec->exp_iconify.not_raise = 1;
1667 e_client_uniconify(ec);
1668 ec->exp_iconify.not_raise = 0;
1670 case E_VIS_JOB_TYPE_LOWER:
1673 case E_VIS_JOB_TYPE_HIDE:
1674 evas_object_hide(ec->frame);
1676 case E_VIS_JOB_TYPE_LAYER_LOWER:
1677 e_client_layer_set(ec, vc->layer);
1679 case E_VIS_JOB_TYPE_ICONIFY:
1680 e_client_iconify(ec);
1682 case E_VIS_JOB_TYPE_SHOW:
1683 /* checks for dectecting hide request after show request */
1684 if ((!e_object_is_del(E_OBJECT(ec))) &&
1685 (ec->visible) && (!ec->hidden) &&
1686 (!ec->iconic) && (!ec->ignored))
1687 evas_object_show(ec->frame);
1689 if (vc->wait_for_child)
1691 e_comp_object_signal_callback_del_full(vc->wait_for_child->frame,
1692 "e,action,launch,done", "e",
1693 _e_vis_cb_child_launch_done, vc);
1694 e_pixmap_free(vc->wait_for_child->pixmap);
1695 e_object_delay_del_unref(E_OBJECT(vc->wait_for_child));
1696 vc->wait_for_child = NULL;
1699 case E_VIS_JOB_TYPE_DEFER_MOVE:
1700 /* handle defered job regarding move */
1701 if ((!e_object_is_del(E_OBJECT(ec))) &&
1702 (ec->visible) && (!ec->hidden) &&
1703 (!ec->iconic) && (!ec->ignored))
1704 evas_object_move(ec->frame, ec->x, ec->y);
1708 VS_ERR(ec, "Unkown job type: %d", type);
1713 static E_Pol_Vis_Type
1714 _e_vis_ec_above_visible_type(E_Client *ec, Eina_Bool check_child)
1717 E_Pol_Vis_Type above_vis_type = E_POL_VIS_TYPE_ALPHA;
1724 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, E_POL_VIS_TYPE_ALPHA);
1725 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_zone_find_by_ec(ec), E_POL_VIS_TYPE_ALPHA);
1727 desk = e_comp_desk_find_by_ec(ec);
1728 EINA_SAFETY_ON_NULL_RETURN_VAL(desk, EINA_FALSE);
1735 e_client_geometry_get(ec, &ex, &ey, &ew, &eh);
1736 e_zone_useful_geometry_get(e_comp_zone_find_by_ec(ec), &zx, &zy, &zw, &zh);
1738 // check whether ec is out of its container or not
1739 if (!E_INTERSECTS(ex, ey, ew, eh, cx, cy, cw, ch))
1740 return E_POL_VIS_TYPE_NON_ALPHA;
1742 // crop ec size with zone size
1743 E_RECTS_CLIP_TO_RECT(ex, ey, ew, eh, zx, zy, zw, zh);
1745 for (above = e_client_above_get(ec); above; above = e_client_above_get(above))
1747 if (e_client_util_ignored_get(above)) continue;
1748 if (above->frame && evas_object_data_get(above->frame, "comp_skip")) continue;
1749 if (check_child && (above->parent == ec)) continue;
1750 if (above->first_mapped)
1752 if (above->comp_data && !above->comp_data->mapped)
1756 if (above->iconic && e_client_is_iconified_by_client(above))
1759 if (above->bg_state)
1762 if (above->e.state.rot.pending_show)
1765 e_client_geometry_get(above, &ax, &ay, &aw, &ah);
1766 if (!E_CONTAINS(ax, ay, aw, ah, ex, ey, ew, eh)) continue;
1768 if (e_client_visibility_get(above) == E_VISIBILITY_UNOBSCURED)
1771 above_vis_type = E_POL_VIS_TYPE_NON_ALPHA;
1774 if (above->visibility.opaque > 0)
1775 above_vis_type = E_POL_VIS_TYPE_ALPHA_OPAQUE;
1782 if (!above->visible)
1785 above_vis_type = E_POL_VIS_TYPE_NON_ALPHA;
1791 return above_vis_type;
1795 _e_vis_client_check_obscure_below(E_Client *ec)
1797 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1799 if (e_client_util_ignored_get(ec)) return EINA_FALSE;
1800 if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1801 if (ec->iconic && e_client_is_iconified_by_client(ec)) return EINA_FALSE;
1802 if (ec->bg_state) return EINA_FALSE;
1803 if (ec->comp_data && !ec->comp_data->mapped) return EINA_FALSE;
1804 if ((ec->argb) && (ec->visibility.opaque <= 0)) return EINA_FALSE;
1805 if (e_client_visibility_get(ec) != E_VISIBILITY_UNOBSCURED) return EINA_FALSE;
1806 if (!ec->visible) return EINA_FALSE;
1812 _e_vis_ec_below_activity_clients_get(E_Client *ec, Eina_List **below_list)
1816 Eina_Tiler *above_tile = NULL;
1817 Eina_Tiler *below_tile = NULL;
1818 Eina_Tiler *temp_tile = NULL;
1820 Eina_Rectangle desk_rect;
1824 desk = e_comp_desk_find_by_ec(ec);
1825 EINA_SAFETY_ON_NULL_RETURN(desk);
1827 EINA_RECTANGLE_SET(&desk_rect, desk->geom.x, desk->geom.y, desk->geom.w, desk->geom.h);
1829 above_tile = eina_tiler_new(desk->geom.w, desk->geom.h);
1830 EINA_SAFETY_ON_NULL_GOTO(above_tile, finish);
1831 below_tile = eina_tiler_new(desk->geom.w, desk->geom.h);
1832 EINA_SAFETY_ON_NULL_GOTO(below_tile, finish);
1833 temp_tile = eina_tiler_new(desk->geom.w, desk->geom.h);
1834 EINA_SAFETY_ON_NULL_GOTO(temp_tile, finish);
1836 eina_tiler_tile_size_set(above_tile, 1, 1);
1837 eina_tiler_tile_size_set(below_tile, 1, 1);
1838 eina_tiler_tile_size_set(temp_tile, 1, 1);
1840 for (above = e_client_above_get(ec); above; above = e_client_above_get(above))
1842 if (_e_vis_client_check_obscure_below(above))
1844 e_client_geometry_get(above, &x, &y, &w, &h);
1845 EINA_RECTANGLE_SET(&r, x, y, w, h);
1846 eina_tiler_rect_add(above_tile, &r);
1850 // if fully obscured by aboves, no need to get below list
1851 eina_tiler_rect_add(temp_tile, &desk_rect);
1852 eina_tiler_subtract(temp_tile, above_tile);
1853 if (eina_tiler_empty(temp_tile))
1856 for (below = e_client_below_get(ec); below; below = e_client_below_get(below))
1858 if (!_e_vis_ec_activity_check(below, EINA_FALSE, EINA_FALSE)) continue;
1859 e_client_geometry_get(below, &x, &y, &w, &h);
1860 EINA_RECTANGLE_SET(&r, x, y, w, h);
1861 eina_tiler_rect_add(below_tile, &r);
1863 // get unobscured region of below ec
1864 eina_tiler_clear(temp_tile);
1865 eina_tiler_union(temp_tile, above_tile);
1866 eina_tiler_union(temp_tile, below_tile);
1867 eina_tiler_subtract(temp_tile, above_tile);
1869 if (eina_tiler_empty(temp_tile)) continue;
1871 E_VIS_CLIENT_GET(vc, below);
1874 if ((e_client_transient_policy_get(below) == E_TRANSIENT_BELOW) &&
1875 (below->parent == ec))
1878 if (!below->internal)
1879 *below_list = eina_list_prepend(*below_list, vc);
1881 if (!(below->argb) || !(below->visibility.opaque <= 0))
1883 eina_tiler_union(above_tile, below_tile);
1885 // if fully obscured by aboves, no need to continue
1886 eina_tiler_rect_add(temp_tile, &desk_rect);
1887 eina_tiler_subtract(temp_tile, above_tile);
1888 if (eina_tiler_empty(temp_tile))
1895 eina_tiler_free(above_tile);
1898 eina_tiler_free(below_tile);
1901 eina_tiler_free(temp_tile);
1905 _e_vis_ec_below_uniconify(E_Client *ec, E_Pol_Vis_Type above_vis_type)
1907 Eina_List *below_list = NULL;
1908 Eina_Bool ret = EINA_FALSE;
1909 E_Vis_Client *below_vc;
1912 if (!ec) return EINA_FALSE;
1914 if (!e_comp_client_zone_is_displaying(ec))
1917 /* find below activity clients */
1918 _e_vis_ec_below_activity_clients_get(ec, &below_list);
1921 VS_INF(ec, "There is NO below activity");
1926 if (above_vis_type == E_POL_VIS_TYPE_ALPHA_OPAQUE)
1927 send_vis = EINA_FALSE;
1929 send_vis = EINA_TRUE;
1931 EINA_LIST_FREE(below_list, below_vc)
1933 Eina_Bool job_added = EINA_FALSE;
1934 E_Client *below_ec = below_vc->ec;
1936 if (below_ec == ec->parent)
1938 /* Check if its parent is waiting for a child's uniconify.
1939 * if so cancel the waiting now.
1941 if (below_vc->state == E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY_WAITING_FOR_CHILD)
1943 E_FREE_FUNC(below_vc->grab, _e_vis_grab_release);
1947 ELOGF("POL_VIS", "SEND pre-unobscured visibility event", below_ec);
1948 e_vis_client_send_pre_visibility_event(below_ec);
1951 job_added = _e_vis_client_add_uniconify_render_pending(below_vc, E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY, 0, send_vis);
1955 if ((below_ec->iconic) && (!e_client_is_iconified_by_client(below_ec)))
1957 // show evas obj if uniconify pending is not necessary
1958 ELOGF("POL_VIS", "Show below iconic client in advance", below_ec);
1959 below_ec->exp_iconify.not_raise = 1;
1960 e_client_uniconify(below_ec);
1961 e_policy_wl_iconify_state_change_send(below_ec, 0);
1973 _e_vis_ec_setup(E_Client *ec)
1975 e_object_delay_del_set(E_OBJECT(ec), _e_vis_client_delay_del);
1976 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_SHOW, _e_vis_client_cb_evas_show, NULL);
1977 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_HIDE, _e_vis_client_cb_evas_hide, NULL);
1978 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_MOVE, _e_vis_client_cb_evas_move, NULL);
1979 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESIZE, _e_vis_client_cb_evas_resize, NULL);
1980 evas_object_event_callback_add(ec->frame, EVAS_CALLBACK_RESTACK, _e_vis_client_cb_evas_restack, NULL);
1984 _e_vis_ec_reset(E_Client *ec)
1986 e_object_delay_del_set(E_OBJECT(ec), NULL);
1987 evas_object_event_callback_del(ec->frame, EVAS_CALLBACK_SHOW, _e_vis_client_cb_evas_show);
1988 evas_object_event_callback_del(ec->frame, EVAS_CALLBACK_HIDE, _e_vis_client_cb_evas_hide);
1989 evas_object_event_callback_del(ec->frame, EVAS_CALLBACK_MOVE, _e_vis_client_cb_evas_move);
1990 evas_object_event_callback_del(ec->frame, EVAS_CALLBACK_RESIZE, _e_vis_client_cb_evas_resize);
1991 evas_object_event_callback_del(ec->frame, EVAS_CALLBACK_RESTACK, _e_vis_client_cb_evas_restack);
1995 _e_vis_hook_new_client_post(void *data EINA_UNUSED, E_Client *ec)
1997 _e_vis_client_add(ec);
2001 _e_vis_client_remove(E_Client *ec)
2003 E_VIS_CLIENT_GET_OR_RETURN(vc, ec);
2004 eina_hash_del_by_key(pol_vis->clients_hash, &ec);
2006 if (pol_vis->activity == ec)
2007 pol_vis->activity = NULL;
2010 _e_vis_update_foreground_job_queue();
2014 _e_vis_hook_client_del(void *data EINA_UNUSED, E_Client *ec)
2016 E_VIS_CLIENT_GET_OR_RETURN(vc, ec);
2017 if (vc->skip_hook_del) return;
2018 _e_vis_client_remove(ec);
2022 _e_vis_cb_client_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
2027 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ev->ec, ECORE_CALLBACK_PASS_ON);
2029 vc->skip_hook_del = EINA_TRUE;
2031 return ECORE_CALLBACK_PASS_ON;
2035 _e_vis_cb_client_remove(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
2040 _e_vis_client_remove(ev->ec);
2042 return ECORE_CALLBACK_PASS_ON;
2046 _e_vis_cb_child_launch_done(void *data, Evas_Object *obj, const char *signal, const char *source)
2049 Evas_Object *comp_obj;
2052 comp_obj = evas_object_data_get(obj, "comp_smart_obj");
2054 E_FREE_FUNC(vc->grab, _e_vis_grab_release);
2056 e_comp_object_signal_callback_del_full(comp_obj, "e,action,launch,done", "e", _e_vis_cb_child_launch_done, vc);
2060 _e_vis_transient_group_make(E_Client *ec, Eina_List **list)
2067 if (e_config->transient.raise)
2069 EINA_LIST_FOREACH(ec->transients, l, child)
2071 if (!child) continue;
2072 if (child->iconic && e_client_is_iconified_by_client(ec))
2074 if (child->bg_state)
2077 if (e_client_transient_policy_get(child) == E_TRANSIENT_ABOVE)
2079 *list = eina_list_prepend(*list, child);
2080 _e_vis_transient_group_make(child, list);
2087 _e_vis_transient_top_get(E_Client *ec)
2089 E_Client *topmost = NULL;
2090 Eina_List *transient_list = NULL;
2092 _e_vis_transient_group_make(ec, &transient_list);
2096 topmost = eina_list_data_get(transient_list);
2097 eina_list_free(transient_list);
2103 _e_vis_intercept_show(void *data EINA_UNUSED, E_Client *ec)
2108 VS_DBG(ec, "INTERCEPT SHOW: new_client %d size %d %d",
2109 ec->new_client, ec->w, ec->h);
2111 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_TRUE);
2113 if (vc->state == E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY_WAITING_FOR_CHILD)
2115 ELOGF("POL", "Waiting child uniconify. running.", ec);
2123 topmost = _e_vis_transient_top_get(ec);
2124 if (!topmost) return EINA_TRUE;
2126 if (e_client_transient_policy_get(topmost) == E_TRANSIENT_BELOW)
2129 /* allow show if topmost child is alpha window or not fully cover region of ec */
2130 e_client_geometry_get(ec, &ex, &ey, &ew, &eh);
2131 e_client_geometry_get(topmost, &tx, &ty, &tw, &th);
2132 if ((topmost->argb) || !(E_CONTAINS(tx, ty, tw, th, ex, ey, ew, eh)))
2135 /* do not show until child is shown */
2136 if (e_config->transient.iconify)
2138 /* wait for child's uniconify */
2139 if (ec->iconic && topmost->iconic)
2141 if (topmost->pixmap && e_pixmap_usable_get(topmost->pixmap))
2143 if ((e_policy_visibility_client_is_uniconic(topmost)) &&
2144 (e_client_visibility_get(topmost) == E_VISIBILITY_UNOBSCURED))
2146 ELOGF("COMP", "Already child(win:0x%08zx ec:%p) uniconify_render done..", ec, e_client_util_win_get(topmost), topmost);
2150 ELOGF("COMP", "Set launching flag..", topmost);
2151 topmost->launching = EINA_TRUE;
2153 vc->state = E_VIS_ICONIFY_STATE_RUNNING_UNICONIFY_WAITING_FOR_CHILD;
2154 VS_DBG(vc->ec, "\tUPDATE ICONIC STATE: %s", STATE_STR(vc));
2155 vc->grab = _e_vis_client_grab_get(vc, E_VIS_JOB_TYPE_SHOW, __func__);
2156 e_comp_object_signal_callback_add(topmost->frame,
2157 "e,action,launch,done",
2159 _e_vis_cb_child_launch_done,
2162 /* do not allow child's removal */
2163 vc->wait_for_child = topmost;
2164 e_pixmap_ref(topmost->pixmap);
2165 e_object_delay_del_ref(E_OBJECT(topmost));
2166 _e_vis_client_job_add(vc, E_VIS_JOB_TYPE_SHOW);
2167 ELOGF("POL", "Waiting child uniconify. new.", ec);
2178 _e_vis_intercept_hide(void *data EINA_UNUSED, E_Client *ec)
2180 E_Pol_Vis_Type above_vis_type;
2181 Eina_Bool pending = EINA_TRUE;
2183 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_TRUE);
2185 VS_DBG(ec, "INTERCEPTOR HIDE");
2187 if (_e_vis_job_find(vc, E_VIS_JOB_TYPE_HIDE))
2189 VS_INF(ec, "Already Pending HIDE...");
2195 VS_DBG(ec, "Window is transparent.");
2196 pending = EINA_FALSE;
2199 if (_e_vis_client_is_below_uniconify_skip(vc))
2201 VS_DBG(ec, "Skip to uniconify below client");
2202 pending = EINA_FALSE;
2205 above_vis_type = _e_vis_ec_above_visible_type(ec, EINA_FALSE);
2206 if ((pending) && (above_vis_type == E_POL_VIS_TYPE_NON_ALPHA))
2208 VS_DBG(ec, "Obscured by above window.");
2209 pending = EINA_FALSE;
2212 if ((pending) && (!_e_vis_ec_below_uniconify(ec, above_vis_type)))
2214 VS_DBG(ec, "Failed to uniconify below client");
2215 pending = EINA_FALSE;
2218 _e_pol_vis_hook_call(E_POL_VIS_HOOK_TYPE_HIDE, ec);
2222 if (!_e_vis_job_is_grabbed(vc, E_VIS_JOB_TYPE_HIDE))
2226 /* add hide job, it will be executed after below activity client finishs updating */
2227 _e_vis_client_job_add(vc, E_VIS_JOB_TYPE_HIDE);
2233 _e_vis_idle_enter(void *data)
2235 _e_vis_job_queue_update();
2236 return ECORE_CALLBACK_PASS_ON;
2240 _e_vis_event_init(void)
2242 E_LIST_HOOK_APPEND(pol_vis->hooks, E_CLIENT_HOOK_NEW_CLIENT_POST, _e_vis_hook_new_client_post, NULL);
2243 E_LIST_HOOK_APPEND(pol_vis->hooks, E_CLIENT_HOOK_DEL, _e_vis_hook_client_del, NULL);
2245 E_LIST_HANDLER_APPEND(pol_vis->handlers, E_EVENT_CLIENT_ADD, _e_vis_cb_client_add, NULL);
2246 E_LIST_HANDLER_APPEND(pol_vis->handlers, E_EVENT_CLIENT_REMOVE, _e_vis_cb_client_remove, NULL);
2248 E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(pol_vis->interceptors, E_COMP_OBJECT_INTERCEPT_HOOK_SHOW_HELPER, _e_vis_intercept_show, NULL);
2249 E_COMP_OBJECT_INTERCEPT_HOOK_APPEND(pol_vis->interceptors, E_COMP_OBJECT_INTERCEPT_HOOK_HIDE, _e_vis_intercept_hide, NULL);
2251 pol_vis->idle_enter = ecore_idle_enterer_add(_e_vis_idle_enter, NULL);
2255 e_policy_visibility_main_activity_get(void)
2257 EINA_SAFETY_ON_NULL_RETURN_VAL(pol_vis, NULL);
2258 return pol_vis->activity;
2262 e_policy_visibility_foreground_clients_get(void)
2264 if (!pol_vis->fg_clients) return NULL;
2265 return eina_list_clone(pol_vis->fg_clients);
2269 e_policy_visibility_client_is_activity(E_Client *ec)
2271 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
2272 return _e_vis_ec_activity_check(ec, EINA_TRUE, EINA_TRUE);
2276 e_policy_visibility_client_grab_get(E_Client *ec, const char *name)
2278 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, NULL);
2281 VS_ERR(ec, "Trying to get the grab without name used hint");
2284 return _e_vis_client_grab_get(vc, E_VIS_JOB_TYPE_ALL, name);
2287 EINTERN E_Vis_Grab *
2288 e_policy_visibility_client_filtered_grab_get(E_Client *ec, E_Vis_Job_Type type, const char *name)
2290 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, NULL);
2293 VS_ERR(ec, "Trying to get the grab without name used hint");
2296 return _e_vis_client_grab_get(vc, type, name);
2300 e_policy_visibility_client_grab_release(E_Vis_Grab *grab)
2302 EINA_SAFETY_ON_NULL_RETURN(grab);
2303 _e_vis_grab_release(grab);
2307 e_policy_visibility_client_grab_cancel(E_Client *ec)
2309 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2310 return _e_vis_client_grab_cancel(vc);
2314 e_policy_visibility_client_hide_job_cancel(E_Client *ec)
2316 if (!ec) return EINA_FALSE;
2317 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2319 VS_INF(ec, "Find and Cancel HIDE job...");
2320 return _e_vis_job_cancel(vc, E_VIS_JOB_TYPE_HIDE);
2324 e_policy_visibility_client_lower_job_cancel(E_Client *ec)
2326 if (!ec) return EINA_FALSE;
2327 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2329 VS_INF(ec, "Find and Cancel LOWER job...");
2330 return _e_vis_job_cancel(vc, E_VIS_JOB_TYPE_LOWER);
2334 e_policy_visibility_client_uniconify_by_visibility_job_cancel(E_Client *ec)
2336 Eina_Bool ret = EINA_FALSE;
2338 if (!ec) return EINA_FALSE;
2339 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2341 VS_INF(ec, "Find and Cancel Uniconify by visibility job...");
2342 ret = _e_vis_job_cancel(vc, E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY);
2344 if (e_policy_visibility_client_is_uniconify_render_running(ec))
2346 vc->state = E_VIS_ICONIFY_STATE_ICONIC;
2347 VS_INF(vc->ec, "UPDATE ICONIC STATE: %s", STATE_STR(vc));
2350 if (!_e_vis_job_is_grabbed(vc, E_VIS_JOB_TYPE_ALL ^ E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY))
2352 vc->state = E_VIS_ICONIFY_STATE_ICONIC;
2353 VS_DBG(vc->ec, "\tUPDATE ICONIC STATE: %s", STATE_STR(vc));
2354 E_FREE_FUNC(vc->grab, _e_vis_grab_release);
2359 l = eina_list_clone(vc->wait_buf_attach_grab_list);
2360 vc->wait_buf_attach_grab_list = eina_list_free(vc->wait_buf_attach_grab_list);
2361 EINA_LIST_FREE(l, grab)
2363 E_FREE_FUNC(grab, _e_vis_grab_release);
2371 e_policy_visibility_client_raising_job_cancel(E_Client *ec)
2373 Eina_Bool ret = EINA_FALSE;
2375 if (!ec) return EINA_FALSE;
2376 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2378 if (_e_vis_job_find(vc, E_VIS_JOB_TYPE_RAISE))
2380 VS_INF(ec, "Find and Cancel raising job: E_VIS_JOB_TYPE_RAISE");
2381 ret = _e_vis_job_cancel(vc, E_VIS_JOB_TYPE_RAISE);
2383 if (_e_vis_job_find(vc, E_VIS_JOB_TYPE_ACTIVATE))
2385 VS_INF(ec, "Find and Cancel raising job: E_VIS_JOB_TYPE_ACTIVATE");
2386 ret = _e_vis_job_cancel(vc, E_VIS_JOB_TYPE_ACTIVATE);
2388 if (_e_vis_job_find(vc, E_VIS_JOB_TYPE_UNICONIFY))
2390 VS_INF(ec, "Find and Cancel raising job: E_VIS_JOB_TYPE_UNICONIFY");
2391 ret = _e_vis_job_cancel(vc, E_VIS_JOB_TYPE_UNICONIFY);
2394 if (ret && e_policy_visibility_client_is_uniconify_render_running(ec))
2396 vc->state = E_VIS_ICONIFY_STATE_ICONIC;
2397 VS_INF(vc->ec, "UPDATE ICONIC STATE: %s", STATE_STR(vc));
2404 e_policy_visibility_client_raise(E_Client *ec)
2408 Eina_Bool ret = EINA_FALSE;
2411 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2413 VS_DBG(ec, "API ENTRY | RAISE");
2415 if (!ec->iconic && !ec->exp_iconify.deiconify_update)
2418 if (e_client_is_iconified_by_client(ec))
2421 if (!ec->iconic && ec->bg_state)
2423 ELOGF("POL", "Currently bg_state. so return...", ec);
2427 ret = _e_vis_client_add_uniconify_render_pending(vc, E_VIS_JOB_TYPE_UNICONIFY, 1, EINA_FALSE);
2429 /* uniconify its transients recursively */
2430 if (e_config->transient.raise)
2432 l = eina_list_clone(ec->transients);
2434 EINA_LIST_FREE(l, child)
2435 ret |= e_policy_visibility_client_raise(child);
2438 /* TODO find topmost activity client and emit signal */
2444 e_policy_visibility_client_lower(E_Client *ec)
2446 E_Pol_Vis_Type above_vis_type;
2447 Eina_Bool ret = EINA_TRUE;
2449 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2451 if ((ec->comp_data) && (!ec->comp_data->mapped))
2453 VS_DBG(ec, "client Unmapped.");
2459 VS_DBG(ec, "client is background state.");
2463 VS_DBG(ec, "API ENTRY | LOWER");
2465 /* if vc has job grab, release them */
2466 _e_vis_client_grab_cancel(vc);
2468 e_policy_visibility_client_raising_job_cancel(ec);
2472 VS_DBG(ec, "Window is transparent.");
2476 above_vis_type = _e_vis_ec_above_visible_type(ec, EINA_TRUE);
2477 if (above_vis_type == E_POL_VIS_TYPE_NON_ALPHA)
2479 VS_DBG(ec, "Obscured by above window.");
2483 if ((ret) && (!_e_vis_ec_below_uniconify(ec, above_vis_type)))
2485 VS_DBG(ec, "Failed to uniconify below client");
2489 _e_pol_vis_hook_call(E_POL_VIS_HOOK_TYPE_LOWER, ec);
2493 if (!_e_vis_job_is_grabbed(vc, E_VIS_JOB_TYPE_LOWER))
2497 /* add lower job, it will be executed after below activity client finishs updating */
2498 _e_vis_client_job_add(vc, E_VIS_JOB_TYPE_LOWER);
2504 e_policy_visibility_client_iconify(E_Client *ec)
2506 E_Pol_Vis_Type above_vis_type;
2508 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2510 VS_DBG(ec, "API ENTRY | ICONIFY");
2512 /* if vc has job grab, release them */
2513 _e_vis_client_grab_cancel(vc);
2517 VS_DBG(ec, "Window is transparent.");
2521 if (ec->iconic) return EINA_FALSE;
2523 above_vis_type = _e_vis_ec_above_visible_type(ec, EINA_TRUE);
2524 if (above_vis_type == E_POL_VIS_TYPE_NON_ALPHA)
2526 VS_DBG(ec, "Obscured by above window.");
2530 if (!_e_vis_ec_below_uniconify(ec, above_vis_type))
2532 VS_DBG(ec, "Failed to uniconify below client");
2536 /* add lower job, it will be executed after below activity client finishs updating */
2537 _e_vis_client_job_add(vc, E_VIS_JOB_TYPE_ICONIFY);
2543 e_policy_visibility_client_uniconify(E_Client *ec, Eina_Bool raise)
2547 Eina_Bool ret = EINA_FALSE;
2549 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2550 if (!ec->iconic && !ec->exp_iconify.deiconify_update)
2555 ELOGF("POL", "UNICONIFY. but NOT MAPPED. So skip...", ec);
2559 if (!ec->iconic && ec->bg_state)
2561 ELOGF("POL", "Currently bg_state. so return...", ec);
2565 VS_DBG(ec, "API ENTRY | UNICONIFY");
2567 /* TODO search clients to be really foreground and uniconify it.
2568 * suppose that transients will be above on the parent. */
2571 ret = _e_vis_client_add_uniconify_render_pending(vc, E_VIS_JOB_TYPE_UNICONIFY, raise, EINA_FALSE);
2573 ret = _e_vis_client_add_uniconify_render_pending(vc, E_VIS_JOB_TYPE_UNICONIFY_BY_VISIBILITY, raise, EINA_FALSE);
2575 /* uniconify its transients recursively */
2576 if (e_config->transient.iconify)
2578 l = eina_list_clone(ec->transients);
2580 EINA_LIST_FREE(l, child)
2582 if (e_client_is_iconified_by_client(child)) continue;
2584 ret |= e_policy_visibility_client_uniconify(child, raise);
2588 /* TODO find topmost activity client and emit signal */
2594 e_policy_visibility_client_wait_child(E_Client *ec, E_Vis_Job_Type type)
2596 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2598 _e_vis_client_job_add(vc, type);
2604 e_policy_visibility_client_activate(E_Client *ec)
2608 Eina_Bool ret = EINA_FALSE;
2609 Eina_Bool ret_child = EINA_FALSE;
2611 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2613 if (!ec->iconic && ec->bg_state)
2615 ELOGF("POL", "Currently bg_state. so return...", ec);
2619 VS_DBG(ec, "API ENTRY | ACTIVATE");
2621 ret = _e_vis_client_add_uniconify_render_pending(vc, E_VIS_JOB_TYPE_ACTIVATE, 1, EINA_FALSE);
2623 /* TODO search clients to be foreground
2624 * suppose that transients will be above on the parent. */
2626 /* uniconify its transients recursively */
2627 if (e_config->transient.iconify)
2629 Eina_Bool pend = EINA_FALSE;
2630 l = eina_list_clone(ec->transients);
2632 EINA_LIST_FREE(l, child)
2634 if (e_client_is_iconified_by_client(child)) continue;
2636 pend = e_policy_visibility_client_uniconify(child, EINA_TRUE);
2639 ELOGF("POL", "uniconify_pending child (win:0x%08zx ec:%p)", ec, e_client_util_win_get(child), child);
2645 if ((ret == EINA_FALSE) && (ret_child == EINA_TRUE))
2647 e_policy_visibility_client_wait_child(ec, E_VIS_JOB_TYPE_ACTIVATE);
2651 /* TODO find topmost activity client and emit signal */
2657 e_policy_visibility_client_layer_lower(E_Client *ec, E_Layer layer)
2659 E_Pol_Vis_Type above_vis_type;
2661 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2663 VS_DBG(ec, "API ENTRY | LAYER LOWER (layer:%d)", layer);
2665 /* if vc has job grab, release them */
2666 _e_vis_client_grab_cancel(vc);
2670 VS_DBG(ec, "Window is transparent.");
2674 above_vis_type = _e_vis_ec_above_visible_type(ec, EINA_TRUE);
2675 if (above_vis_type == E_POL_VIS_TYPE_NON_ALPHA)
2677 VS_DBG(ec, "Obscured by above window.");
2681 if (!_e_vis_ec_below_uniconify(ec, above_vis_type))
2683 VS_DBG(ec, "Failed to uniconify below client");
2687 /* add lower lower job, it will be executed after below activity client finishs updating */
2689 _e_vis_client_job_add(vc, E_VIS_JOB_TYPE_LAYER_LOWER);
2695 e_policy_visibility_client_defer_move(E_Client *ec)
2697 E_VIS_CLIENT_GET_OR_RETURN(vc, ec);
2698 VS_DBG(ec, "API ENTRY | Defered Move");
2700 if (ec->comp_data && !ec->comp_data->mapped)
2702 ELOGF("POL_VIS", "Not mapped. no need to defer move.", ec);
2706 _e_vis_client_defer_move(vc, E_VIS_JOB_TYPE_DEFER_MOVE);
2710 e_policy_visibility_client_is_iconic(E_Client *ec)
2712 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2714 return _e_vis_client_is_iconic(vc);
2718 e_policy_visibility_client_is_uniconic(E_Client *ec)
2720 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2722 return _e_vis_client_is_uniconic(vc);
2726 e_policy_visibility_client_is_uniconify_render_running(E_Client *ec)
2728 Eina_Bool running = EINA_FALSE;
2729 E_VIS_CLIENT_GET_OR_RETURN_VAL(vc, ec, EINA_FALSE);
2731 if ((_e_vis_client_is_uniconify_render_running(vc)) ||
2732 (_e_vis_client_is_uniconify_render_running_done(vc)))
2733 running = EINA_TRUE;
2739 e_policy_visibility_client_below_uniconify_skip_set(E_Client *ec, Eina_Bool skip)
2741 E_VIS_CLIENT_GET_OR_RETURN(vc, ec);
2743 _e_vis_client_below_uniconify_skip_set(vc, skip);
2747 e_policy_visibility_norender_disable_set(Eina_Bool disable)
2749 ELOGF("POL_VIS", "NO RENDER DISABLE SET: %d", NULL, disable);
2750 pol_vis_disable_norender = disable;
2753 E_API E_Pol_Vis_Hook *
2754 e_policy_visibility_hook_add(E_Pol_Vis_Hook_Type type, E_Pol_Vis_Hook_Cb cb, const void *data)
2758 EINA_SAFETY_ON_TRUE_RETURN_VAL(type >= E_POL_VIS_HOOK_TYPE_LAST, NULL);
2760 h = E_NEW(E_Pol_Vis_Hook, 1);
2761 EINA_SAFETY_ON_NULL_RETURN_VAL(h, NULL);
2765 h->data = (void *)data;
2767 _e_pol_vis_hooks[type] = eina_inlist_append(_e_pol_vis_hooks[type],
2768 EINA_INLIST_GET(h));
2774 e_policy_visibility_hook_del(E_Pol_Vis_Hook *h)
2776 h->delete_me = EINA_TRUE;
2777 if (_e_pol_vis_hooks_walking == 0)
2779 _e_pol_vis_hooks[h->type] = eina_inlist_remove(_e_pol_vis_hooks[h->type],
2780 EINA_INLIST_GET(h));
2784 _e_pol_vis_hooks_delete++;
2788 e_policy_visibility_timeout_get(void)
2790 return e_config->deiconify_pending_timeout;
2794 e_policy_visibility_init(void)
2798 INF("Init Visibility Module");
2802 pol_vis = E_NEW(E_Vis, 1);
2805 ERR("Failed to allocate 'E_Vis'");
2809 pol_vis->clients_hash = eina_hash_pointer_new((Eina_Free_Cb)_e_vis_client_del);
2811 E_CLIENT_REVERSE_FOREACH(ec)
2812 _e_vis_client_add(ec);
2814 _e_vis_event_init();
2815 _e_vis_update_forground_list();
2821 e_policy_visibility_shutdown(void)
2823 INF("Shutdown Visibility Module");
2828 _e_vis_clist_clean(&pol_job_group_head, _e_vis_job_group_del);
2830 E_FREE_FUNC(pol_vis->clients_hash, eina_hash_free);
2831 E_FREE_FUNC(pol_vis->idle_enter, ecore_idle_enterer_del);
2832 E_FREE_LIST(pol_vis->hooks, e_client_hook_del);
2833 E_FREE_LIST(pol_vis->handlers, ecore_event_handler_del);
2834 E_FREE_LIST(pol_vis->interceptors, e_comp_object_intercept_hook_del);