From: MinJeong Kim Date: Thu, 12 Feb 2015 05:47:18 +0000 (+0900) Subject: Handle transient_for property X-Git-Tag: accepted/tizen/common/20150217.085224~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b314912319d611e7f13960aff08b807f0763dad7;p=platform%2Fcore%2Fuifw%2Fe-mod-tizen-wm-policy.git Handle transient_for property Change-Id: I6d75990c97d72276208563e8a18c030ee3418d3e --- diff --git a/src/Makefile.am b/src/Makefile.am index a45884d..80e202c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,8 @@ module_la_SOURCES = e_mod_config.c \ e_mod_rotation.h \ e_mod_utils.h \ e_mod_keyboard.c \ - e_mod_keyboard.h + e_mod_keyboard.h \ + e_mod_stack.c module_la_LIBADD = module_la_CFLAGS = @ENLIGHTENMENT_CFLAGS@ module_la_LDFLAGS = -module -avoid-version @ENLIGHTENMENT_LIBS@ diff --git a/src/e_mod_main.c b/src/e_mod_main.c index ebc213b..72dcb3a 100644 --- a/src/e_mod_main.c +++ b/src/e_mod_main.c @@ -39,6 +39,8 @@ static Eina_Bool _pol_client_normal_check(E_Client *ec); static void _pol_client_update(Pol_Client *pc); static void _pol_client_launcher_set(Pol_Client *pc); +static void _pol_hook_client_eval_pre_fetch(void *d EINA_UNUSED, E_Client *ec); +static void _pol_hook_client_eval_pre_post_fetch(void *d EINA_UNUSED, E_Client *ec); static void _pol_hook_client_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec); static void _pol_hook_client_desk_set(void *d EINA_UNUSED, E_Client *ec); static void _pol_hook_new_client(void *d EINA_UNUSED, E_Client *ec); @@ -267,6 +269,22 @@ _pol_client_update(Pol_Client *pc) } static void +_pol_hook_client_eval_pre_fetch(void *d EINA_UNUSED, E_Client *ec) +{ + if (e_object_is_del(E_OBJECT(ec))) return; + + e_mod_pol_stack_hook_pre_fetch(ec); +} + +static void +_pol_hook_client_eval_pre_post_fetch(void *d EINA_UNUSED, E_Client *ec) +{ + if (e_object_is_del(E_OBJECT(ec))) return; + + e_mod_pol_stack_hook_pre_post_fetch(ec); +} + +static void _pol_hook_client_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec) { Pol_Client *pc; @@ -536,6 +554,7 @@ _pol_cb_client_remove(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) eina_hash_del_by_key(hash_pol_clients, &ev->ec); + e_mod_pol_stack_cb_client_remove(ev->ec); e_mod_pol_client_visibility_del(ev->ec); e_mod_pol_visibility_calc(); @@ -799,6 +818,7 @@ e_modapi_init(E_Module *m) hash_pol_clients = eina_hash_pointer_new(_pol_cb_client_data_free); hash_pol_desks = eina_hash_pointer_new(_pol_cb_desk_data_free); + e_mod_pol_stack_init(); e_mod_pol_visibility_init(); e_mod_pol_atoms_init(); @@ -870,6 +890,10 @@ e_modapi_init(E_Module *m) E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_ROTATION_CHANGE_BEGIN, _pol_cb_zone_rotation_change_begin, NULL); + E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_EVAL_PRE_FETCH, + _pol_hook_client_eval_pre_fetch, NULL); + E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_EVAL_PRE_POST_FETCH, + _pol_hook_client_eval_pre_post_fetch, NULL); E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_EVAL_POST_FETCH, _pol_hook_client_eval_post_fetch, NULL); E_CLIENT_HOOK_APPEND(hooks, E_CLIENT_HOOK_DESK_SET, @@ -921,6 +945,7 @@ e_modapi_shutdown(E_Module *m) E_FREE_FUNC(hash_pol_desks, eina_hash_free); E_FREE_FUNC(hash_pol_clients, eina_hash_free); + e_mod_pol_stack_shutdonw(); e_mod_pol_viisibility_shutdown(); e_configure_registry_item_del("windows/policy-tizen"); diff --git a/src/e_mod_main.h b/src/e_mod_main.h index f9ddba9..d55778c 100644 --- a/src/e_mod_main.h +++ b/src/e_mod_main.h @@ -121,4 +121,10 @@ EINTERN void e_mod_pol_client_visibility_del(E_Client *ec); EINTERN void e_mod_pol_client_window_opaque_set(E_Client *ec); EINTERN Eina_Bool e_mod_pol_visibility_cb_window_property(Ecore_X_Event_Window_Property *ev); +EINTERN void e_mod_pol_stack_init(void); +EINTERN void e_mod_pol_stack_shutdonw(void); +EINTERN void e_mod_pol_stack_cb_client_remove(E_Client *ec); +EINTERN void e_mod_pol_stack_hook_pre_fetch(E_Client *ec); +EINTERN void e_mod_pol_stack_hook_pre_post_fetch(E_Client *ec); + #endif diff --git a/src/e_mod_stack.c b/src/e_mod_stack.c new file mode 100644 index 0000000..ad024b7 --- /dev/null +++ b/src/e_mod_stack.c @@ -0,0 +1,204 @@ +#include "e_mod_main.h" +#include "e_mod_atoms.h" + +typedef struct _Pol_Stack Pol_Stack; + +struct _Pol_Stack +{ + E_Client *ec; + + struct + { + Ecore_Window win; + Eina_Bool fetched; + } transient; +}; + +static Eina_Hash *hash_pol_stack = NULL; + +static void +_pol_stack_cb_data_free(void *data) +{ + E_FREE(data); +} + +Pol_Stack* +_pol_stack_data_add(E_Client *ec) +{ + Pol_Stack *ps; + + if ((ps = eina_hash_find(hash_pol_stack, &ec))) + return ps; + + ps = E_NEW(Pol_Stack, 1); + ps->ec = ec; + eina_hash_add(hash_pol_stack, &ec, ps); + + return ps; +} + +void +_pol_stack_data_del(E_Client *ec) +{ + Pol_Stack *ps; + + if ((ps = eina_hash_find(hash_pol_stack, &ec))) + { + eina_hash_del_by_key(hash_pol_stack, &ec); + } +} + +void +_pol_stack_transient_for_apply(E_Client *ec) +{ + int raise; + E_Client *child, *top; + Eina_List *l; + + ecore_x_window_shadow_tree_flush(); + + if (ec->parent->layer != ec->layer) + { + raise = e_config->transient.raise; + + ec->saved.layer = ec->layer; + ec->layer = ec->parent->layer; + if (e_config->transient.layer) + { + e_config->transient.raise = 1; + EINA_LIST_FOREACH(ec->transients, l, child) + { + if (!child) continue; + child->saved.layer = child->layer; + child->layer = ec->parent->layer; + } + } + + e_config->transient.raise = raise; + } + + top = e_client_top_get(ec->comp); + while (top) + { + if (eina_list_data_find(ec->parent->transients, top)) + break; + + top = e_client_below_get(top); + } + + if ((top) && (top != ec)) + evas_object_stack_above(ec->frame, top->frame); + else + evas_object_stack_above(ec->frame, ec->parent->frame); +} + +Eina_Bool +_pol_stack_transient_for_tree_check(E_Client *child, E_Client *parent) +{ + E_Client *p; + + p = parent->parent; + while (p) + { + if (e_object_is_del(E_OBJECT(p))) return EINA_FALSE; + if (p == child) return EINA_TRUE; + + p = p->parent; + } + + return EINA_FALSE; +} + +void +e_mod_pol_stack_hook_pre_post_fetch(E_Client *ec) +{ + Pol_Stack *ps; + + if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_X) return; + ps = eina_hash_find(hash_pol_stack, &ec); + + if (ps) + { + if ((ps->transient.win) && (ps->transient.fetched)) + { + if ((ec->icccm.transient_for == ps->transient.win) && + (ec->parent)) + _pol_stack_transient_for_apply(ec); + else + ps->transient.win = ec->icccm.transient_for; + + ps->transient.fetched = 0; + } + } +} + +void +e_mod_pol_stack_hook_pre_fetch(E_Client *ec) +{ + Pol_Stack *ps; + + if (e_pixmap_type_get(ec->pixmap) != E_PIXMAP_TYPE_X) return; + ps = eina_hash_find(hash_pol_stack, &ec); + + if (ec->icccm.fetch.transient_for) + { + Ecore_Window transient_for_win; + E_Client *parent = NULL; + Eina_Bool transient_each_other = EINA_FALSE; + + transient_for_win = ecore_x_icccm_transient_for_get(e_client_util_win_get(ec)); + if (transient_for_win) + parent = e_pixmap_find_client(E_PIXMAP_TYPE_X, transient_for_win); + + if (parent) + { + if (!ps) ps = _pol_stack_data_add(ec); + + ps->transient.win = transient_for_win; + ps->transient.fetched = 1; + + /* clients transient for each other */ + transient_each_other = _pol_stack_transient_for_tree_check(ec, parent); + if (transient_each_other) + { + ec->icccm.transient_for = transient_for_win; + ec->icccm.fetch.transient_for = 0; + ps->transient.fetched = 0; + parent = NULL; + } + + /* already set by requested window */ + if ((parent) && (ec->icccm.transient_for == transient_for_win)) + { + if (!ec->parent) ec->parent = parent; + if ((ec->parent) && (!e_object_is_del(E_OBJECT(ec->parent)))) + { + ec->parent->transients = eina_list_remove(ec->parent->transients, ec); + ec->parent->transients = eina_list_append(ec->parent->transients, ec); + } + ec->icccm.fetch.transient_for = 0; + ps->transient.fetched = 0; + parent = NULL; + } + } + } +} + +void +e_mod_pol_stack_cb_client_remove(E_Client *ec) +{ + _pol_stack_data_del(ec); +} + +void +e_mod_pol_stack_shutdonw(void) +{ + eina_hash_free(hash_pol_stack); + hash_pol_stack = NULL; +} + +void +e_mod_pol_stack_init(void) +{ + hash_pol_stack = eina_hash_pointer_new(_pol_stack_cb_data_free); +}