enlightenment/src/modules/policy_mobile/e_mod_main.c

640 lines
16 KiB
C

#include "e_mod_main.h"
E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Policy-Mobile" };
Mod *_pol_mod = NULL;
Eina_Hash *hash_pol_desks = NULL;
Eina_Hash *hash_pol_clients = NULL;
static Eina_List *handlers = NULL;
static Eina_List *hooks = NULL;
static Pol_Client *_pol_client_add(E_Client *ec);
static void _pol_client_del(Pol_Client *pc);
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_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_cb_desk_data_free(void *data);
static void _pol_cb_client_data_free(void *data);
static Eina_Bool _pol_cb_zone_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
static Eina_Bool _pol_cb_zone_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
static Eina_Bool _pol_cb_zone_move_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
static Eina_Bool _pol_cb_zone_desk_count_set(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
static Eina_Bool _pol_cb_desk_show(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
static Eina_Bool _pol_cb_client_remove(void *data EINA_UNUSED, int type, void *event);
static void
_pol_client_launcher_set(Pol_Client *pc)
{
Pol_Client *pc2;
pc2 = e_mod_pol_client_launcher_get(pc->ec->zone);
if (pc2) return;
if (pc->ec->netwm.type != _pol_mod->conf->launcher.type)
return;
if (e_util_strcmp(pc->ec->icccm.class,
_pol_mod->conf->launcher.clas))
return;
if (e_util_strcmp(pc->ec->icccm.title,
_pol_mod->conf->launcher.title))
{
/* check netwm name instead, because comp_x had ignored
* icccm name when fetching */
if (e_util_strcmp(pc->ec->netwm.name,
_pol_mod->conf->launcher.title))
{
return;
}
}
_pol_mod->launchers = eina_list_append(_pol_mod->launchers, pc);
}
static Pol_Client *
_pol_client_add(E_Client *ec)
{
Pol_Client *pc;
Pol_Desk *pd;
if (e_object_is_del(E_OBJECT(ec))) return NULL;
if (!_pol_client_normal_check(ec)) return NULL;
pc = eina_hash_find(hash_pol_clients, &ec);
if (pc) return NULL;
pd = eina_hash_find(hash_pol_desks, &ec->desk);
if (!pd) return NULL;
pc = E_NEW(Pol_Client, 1);
pc->ec = ec;
#undef _SET
# define _SET(a) pc->orig.a = ec->a
_SET(borderless);
_SET(fullscreen);
_SET(maximized);
_SET(lock_user_location);
_SET(lock_client_location);
_SET(lock_user_size);
_SET(lock_client_size);
_SET(lock_client_stacking);
_SET(lock_user_shade);
_SET(lock_client_shade);
_SET(lock_user_maximize);
_SET(lock_client_maximize);
#undef _SET
_pol_client_launcher_set(pc);
eina_hash_add(hash_pol_clients, &ec, pc);
_pol_client_update(pc);
return pc;
}
static void
_pol_client_del(Pol_Client *pc)
{
E_Client *ec;
Eina_Bool changed = EINA_FALSE;
ec = pc->ec;
if (pc->orig.borderless != ec->borderless)
{
ec->border.changed = 1;
changed = EINA_TRUE;
}
if ((pc->orig.fullscreen != ec->fullscreen) &&
(pc->orig.fullscreen))
{
ec->need_fullscreen = 1;
changed = EINA_TRUE;
}
if (pc->orig.maximized != ec->maximized)
{
if (pc->orig.maximized)
ec->changes.need_maximize = 1;
else
ec->changes.need_unmaximize = 1;
changed = EINA_TRUE;
}
#undef _SET
# define _SET(a) ec->a = pc->orig.a
_SET(borderless);
_SET(fullscreen);
_SET(maximized);
_SET(lock_user_location);
_SET(lock_client_location);
_SET(lock_user_size);
_SET(lock_client_size);
_SET(lock_client_stacking);
_SET(lock_user_shade);
_SET(lock_client_shade);
_SET(lock_user_maximize);
_SET(lock_client_maximize);
#undef _SET
/* only set it if the border is changed or fullscreen/maximize has changed */
if (changed)
EC_CHANGED(pc->ec);
_pol_mod->launchers = eina_list_remove(_pol_mod->launchers, pc);
eina_hash_del_by_key(hash_pol_clients, &pc->ec);
}
static Eina_Bool
_pol_client_normal_check(E_Client *ec)
{
if ((e_client_util_ignored_get(ec)) ||
(!ec->pixmap))
{
return EINA_FALSE;
}
if ((ec->netwm.type == E_WINDOW_TYPE_NORMAL) ||
(ec->netwm.type == E_WINDOW_TYPE_UNKNOWN))
{
return EINA_TRUE;
}
return EINA_FALSE;
}
static void
_pol_client_update(Pol_Client *pc)
{
E_Client *ec;
ec = pc->ec;
if (ec->remember)
{
e_remember_del(ec->remember);
ec->remember = NULL;
}
/* skip hooks of e_remeber for eval_pre_post_fetch and eval_post_new_client */
ec->internal_no_remember = 1;
if (!ec->borderless)
{
ec->borderless = 1;
ec->border.changed = 1;
EC_CHANGED(pc->ec);
}
if (!ec->maximized)
e_client_maximize(ec, E_MAXIMIZE_EXPAND | E_MAXIMIZE_BOTH);
/* do not allow client to change these properties */
ec->lock_user_location = 1;
ec->lock_client_location = 1;
ec->lock_user_size = 1;
ec->lock_client_size = 1;
ec->lock_client_stacking = 1;
ec->lock_user_shade = 1;
ec->lock_client_shade = 1;
ec->lock_user_maximize = 1;
ec->lock_client_maximize = 1;
}
static void
_pol_hook_client_eval_post_fetch(void *d EINA_UNUSED, E_Client *ec)
{
Pol_Client *pc;
Pol_Desk *pd;
if (e_object_is_del(E_OBJECT(ec))) return;
if (!_pol_client_normal_check(ec)) return;
if (ec->new_client) return;
pd = eina_hash_find(hash_pol_desks, &ec->desk);
if (!pd) return;
pc = eina_hash_find(hash_pol_clients, &ec);
if (pc)
{
_pol_client_launcher_set(pc);
return;
}
_pol_client_add(ec);
}
static void
_pol_hook_client_desk_set(void *d EINA_UNUSED, E_Client *ec)
{
Pol_Client *pc;
Pol_Desk *pd;
if (e_object_is_del(E_OBJECT(ec))) return;
if (!_pol_client_normal_check(ec)) return;
if (ec->new_client) return;
pc = eina_hash_find(hash_pol_clients, &ec);
pd = eina_hash_find(hash_pol_desks, &ec->desk);
if ((!pc) && (pd))
_pol_client_add(ec);
else if ((pc) && (!pd))
_pol_client_del(pc);
}
static void
_pol_cb_desk_data_free(void *data)
{
free(data);
}
static void
_pol_cb_client_data_free(void *data)
{
free(data);
}
static Eina_Bool
_pol_cb_zone_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
E_Event_Zone_Add *ev;
E_Zone *zone;
Config_Desk *d;
int i, n;
ev = event;
zone = ev->zone;
n = zone->desk_y_count * zone->desk_x_count;
for (i = 0; i < n; i++)
{
d = e_mod_pol_conf_desk_get_by_nums(_pol_mod->conf,
zone->num,
zone->desks[i]->x,
zone->desks[i]->y);
if (d)
e_mod_pol_desk_add(zone->desks[i]);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_pol_cb_zone_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
E_Event_Zone_Del *ev;
E_Zone *zone;
Pol_Desk *pd;
int i, n;
ev = event;
zone = ev->zone;
n = zone->desk_y_count * zone->desk_x_count;
for (i = 0; i < n; i++)
{
pd = eina_hash_find(hash_pol_desks, &zone->desks[i]);
if (pd) e_mod_pol_desk_del(pd);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_pol_cb_zone_move_resize(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
E_Event_Zone_Move_Resize *ev;
Pol_Softkey *softkey;
ev = event;
if (_pol_mod->conf->use_softkey)
{
softkey = e_mod_pol_softkey_get(ev->zone);
e_mod_pol_softkey_update(softkey);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_pol_cb_zone_desk_count_set(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
E_Event_Zone_Desk_Count_Set *ev;
E_Zone *zone;
E_Desk *desk;
Eina_Iterator *it;
Pol_Desk *pd;
Config_Desk *d;
int i, n;
Eina_Bool found;
Eina_List *desks_del = NULL;
ev = event;
zone = ev->zone;
/* remove deleted desk from hash */
it = eina_hash_iterator_data_new(hash_pol_desks);
while (eina_iterator_next(it, (void **)&pd))
{
if (pd->zone != zone) continue;
found = EINA_FALSE;
n = zone->desk_y_count * zone->desk_x_count;
for (i = 0; i < n; i++)
{
if (pd->desk == zone->desks[i])
{
found = EINA_TRUE;
break;
}
}
if (!found)
desks_del = eina_list_append(desks_del, pd->desk);
}
eina_iterator_free(it);
EINA_LIST_FREE(desks_del, desk)
{
pd = eina_hash_find(hash_pol_desks, &desk);
if (pd) e_mod_pol_desk_del(pd);
}
/* add newly added desk to hash */
n = zone->desk_y_count * zone->desk_x_count;
for (i = 0; i < n; i++)
{
d = e_mod_pol_conf_desk_get_by_nums(_pol_mod->conf,
zone->num,
zone->desks[i]->x,
zone->desks[i]->y);
if (d)
e_mod_pol_desk_add(zone->desks[i]);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_pol_cb_desk_show(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
E_Event_Desk_Show *ev;
Pol_Softkey *softkey;
ev = event;
if (_pol_mod->conf->use_softkey)
{
softkey = e_mod_pol_softkey_get(ev->desk->zone);
if (eina_hash_find(hash_pol_desks, &ev->desk))
e_mod_pol_softkey_show(softkey);
else
e_mod_pol_softkey_hide(softkey);
}
return ECORE_CALLBACK_PASS_ON;
}
static Eina_Bool
_pol_cb_client_remove(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
E_Event_Client *ev;
Pol_Client *pc;
ev = event;
pc = eina_hash_find(hash_pol_clients, &ev->ec);
if (!pc) return ECORE_CALLBACK_PASS_ON;
eina_hash_del_by_key(hash_pol_clients, &ev->ec);
return ECORE_CALLBACK_PASS_ON;
}
void
e_mod_pol_desk_add(E_Desk *desk)
{
Pol_Desk *pd;
E_Client *ec;
Pol_Softkey *softkey;
pd = eina_hash_find(hash_pol_desks, &desk);
if (pd) return;
pd = E_NEW(Pol_Desk, 1);
pd->desk = desk;
pd->zone = desk->zone;
eina_hash_add(hash_pol_desks, &desk, pd);
/* add clients */
E_CLIENT_FOREACH(ec)
{
if (pd->desk == ec->desk)
_pol_client_add(ec);
}
/* add and show softkey */
if (_pol_mod->conf->use_softkey)
{
softkey = e_mod_pol_softkey_get(desk->zone);
if (!softkey)
softkey = e_mod_pol_softkey_add(desk->zone);
if (e_desk_current_get(desk->zone) == desk)
e_mod_pol_softkey_show(softkey);
}
}
void
e_mod_pol_desk_del(Pol_Desk *pd)
{
Eina_Iterator *it;
Pol_Client *pc;
E_Client *ec;
Eina_List *clients_del = NULL;
Pol_Softkey *softkey;
Eina_Bool keep = EINA_FALSE;
int i, n;
/* hide and delete softkey */
if (_pol_mod->conf->use_softkey)
{
softkey = e_mod_pol_softkey_get(pd->zone);
if (e_desk_current_get(pd->zone) == pd->desk)
e_mod_pol_softkey_hide(softkey);
n = pd->zone->desk_y_count * pd->zone->desk_x_count;
for (i = 0; i < n; i++)
{
if (eina_hash_find(hash_pol_desks, &pd->zone->desks[i]))
{
keep = EINA_TRUE;
break;
}
}
if (!keep)
e_mod_pol_softkey_del(softkey);
}
/* remove clients */
it = eina_hash_iterator_data_new(hash_pol_clients);
while (eina_iterator_next(it, (void **)&pc))
{
if (pc->ec->desk == pd->desk)
clients_del = eina_list_append(clients_del, pc->ec);
}
eina_iterator_free(it);
EINA_LIST_FREE(clients_del, ec)
{
pc = eina_hash_find(hash_pol_clients, &ec);
if (pc) _pol_client_del(pc);
}
eina_hash_del_by_key(hash_pol_desks, &pd->desk);
}
Pol_Client *
e_mod_pol_client_launcher_get(E_Zone *zone)
{
Pol_Client *pc;
Eina_List *l;
EINA_LIST_FOREACH(_pol_mod->launchers, l, pc)
{
if (pc->ec->zone == zone)
return pc;
}
return NULL;
}
#undef E_CLIENT_HOOK_APPEND
#define E_CLIENT_HOOK_APPEND(l, t, cb, d) \
do \
{ \
E_Client_Hook *_h; \
_h = e_client_hook_add(t, cb, d); \
assert(_h); \
l = eina_list_append(l, _h); \
} \
while (0)
E_API void *
e_modapi_init(E_Module *m)
{
Mod *mod;
E_Zone *zone;
Config_Desk *d;
const Eina_List *l;
int i, n;
char buf[PATH_MAX];
mod = E_NEW(Mod, 1);
mod->module = m;
_pol_mod = mod;
hash_pol_clients = eina_hash_pointer_new(_pol_cb_client_data_free);
hash_pol_desks = eina_hash_pointer_new(_pol_cb_desk_data_free);
/* initialize configure and config data type */
snprintf(buf, sizeof(buf), "%s/e-module-policy-mobile.edj",
e_module_dir_get(m));
e_configure_registry_category_add("windows", 50, _("Windows"), NULL,
"preferences-system-windows");
e_configure_registry_item_add("windows/policy-mobile", 150,
_("Mobile Policy"), NULL, buf,
e_int_config_pol_mobile);
e_mod_pol_conf_init(mod);
EINA_LIST_FOREACH(e_comp->zones, l, zone)
{
//Eina_Bool home_add = EINA_FALSE;
n = zone->desk_y_count * zone->desk_x_count;
for (i = 0; i < n; i++)
{
d = e_mod_pol_conf_desk_get_by_nums(_pol_mod->conf,
zone->num,
zone->desks[i]->x,
zone->desks[i]->y);
if (d)
{
e_mod_pol_desk_add(zone->desks[i]);
//home_add = EINA_TRUE;
}
}
/* FIXME: should consider the case that illume-home module
* is not loaded yet and make it configurable.
* and also, this code will be enabled when e_policy stuff lands in e.
*/
//if (home_add)
// e_policy_zone_home_add_request(zone);
}
E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_ADD, _pol_cb_zone_add, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DEL, _pol_cb_zone_del, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_MOVE_RESIZE, _pol_cb_zone_move_resize, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_ZONE_DESK_COUNT_SET, _pol_cb_zone_desk_count_set, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_DESK_SHOW, _pol_cb_desk_show, NULL);
E_LIST_HANDLER_APPEND(handlers, E_EVENT_CLIENT_REMOVE, _pol_cb_client_remove, 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,
_pol_hook_client_desk_set, NULL);
return mod;
}
E_API int
e_modapi_shutdown(E_Module *m)
{
Mod *mod = m->data;
Eina_Inlist *l;
Pol_Softkey *softkey;
eina_list_free(mod->launchers);
EINA_INLIST_FOREACH_SAFE(mod->softkeys, l, softkey)
e_mod_pol_softkey_del(softkey);
E_FREE_LIST(hooks, e_client_hook_del);
E_FREE_LIST(handlers, ecore_event_handler_del);
E_FREE_FUNC(hash_pol_desks, eina_hash_free);
E_FREE_FUNC(hash_pol_clients, eina_hash_free);
e_configure_registry_item_del("windows/policy-mobile");
e_configure_registry_category_del("windows");
if (mod->conf_dialog)
{
e_object_del(E_OBJECT(mod->conf_dialog));
mod->conf_dialog = NULL;
}
e_mod_pol_conf_shutdown(mod);
E_FREE(mod);
_pol_mod = NULL;
return 1;
}
E_API int
e_modapi_save(E_Module *m)
{
Mod *mod = m->data;
e_config_domain_save("module.policy-mobile",
mod->conf_edd,
mod->conf);
return 1;
}