diff --git a/src/modules/comp/e_mod_comp.c b/src/modules/comp/e_mod_comp.c index aa66923fd..e5d218289 100644 --- a/src/modules/comp/e_mod_comp.c +++ b/src/modules/comp/e_mod_comp.c @@ -77,6 +77,9 @@ struct _E_Comp_Win double last_visible_time; // last time window was visible double last_draw_time; // last time window was damaged + char *title, *name, *clas, *role; // fetched for override-redirect windowa + Ecore_X_Window_Type primary_type; // fetched for override-redirect windowa + Eina_Bool animating : 1; // it's busy animating - defer hides/dels Eina_Bool force : 1; // force del/hide even if animating Eina_Bool defer_hide : 1; // flag to get hide to work on deferred hide @@ -928,12 +931,159 @@ _e_mod_comp_win_shadow_setup(E_Comp_Win *cw) { int ok = 0; char buf[PATH_MAX]; + Eina_List *list = NULL, *l; + Match *m; + const char *title = NULL, *name = NULL, *clas = NULL, *role = NULL; + Ecore_X_Window_Type primary_type = ECORE_X_WINDOW_TYPE_UNKNOWN; evas_object_image_smooth_scale_set(cw->obj, _comp_mod->conf->smooth_windows); + if (cw->bd) + { + list = _comp_mod->conf->match.borders; + title = cw->bd->client.icccm.title; + if (cw->bd->client.netwm.name) title = cw->bd->client.netwm.name; + name = cw->bd->client.icccm.name; + clas = cw->bd->client.icccm.class; + role = cw->bd->client.icccm.window_role; + primary_type = cw->bd->client.netwm.type; + } + else if (cw->pop) + { + // FIXME: i only added "shelf" as a name for popups that are shelves + // ... need more nmes like for pager popup, evertything, exebuf + // etc. etc. + list = _comp_mod->conf->match.popups; + name = cw->pop->name; + } + else if (cw->menu) + { + // FIXME: e has no way to tell e menus apart... need naming + list = _comp_mod->conf->match.menus; + } + else + { + list = _comp_mod->conf->match.overrides; + title = cw->title; + name = cw->name; + clas = cw->clas; + role = cw->role; + primary_type = cw->primary_type; + } + + EINA_LIST_FOREACH(list, l, m) + { + if (((m->title) && (!title)) || + ((title) && (m->title) && (!e_util_glob_match(title, m->title)))) + continue; + if (((m->name) && (!name)) || + ((name) && (m->name) && (!e_util_glob_match(name, m->name)))) + continue; + if (((m->clas) && (!clas)) || + ((clas) && (m->clas) && (!e_util_glob_match(clas, m->clas)))) + continue; + if (((m->role) && (!role)) || + ((role) && (m->role) && (!e_util_glob_match(role, m->role)))) + continue; + if ((primary_type != ECORE_X_WINDOW_TYPE_UNKNOWN) && + (m->primary_type != ECORE_X_WINDOW_TYPE_UNKNOWN) && + (primary_type != m->primary_type)) + continue; + if (cw->bd) + { + if (m->borderless != 0) + { + int borderless = 0; + + if ((cw->bd->client.mwm.borderless) || (cw->bd->borderless)) + borderless = 1; + if (!(((m->borderless == -1) && (!borderless)) || + ((m->borderless == 1) && ( borderless)))) + continue; + } + if (m->dialog != 0) + { + int dialog = 0; + + if (((cw->bd->client.icccm.transient_for != 0) || + (cw->bd->client.netwm.type == ECORE_X_WINDOW_TYPE_DIALOG))) + dialog = 1; + if (!(((m->dialog == -1) && (!dialog)) || + ((m->dialog == 1) && ( dialog)))) + continue; + } + if (m->accepts_focus != 0) + { + int accepts_focus = 0; + + if (cw->bd->client.icccm.accepts_focus) + accepts_focus = 1; + if (!(((m->accepts_focus == -1) && (!accepts_focus)) || + ((m->accepts_focus == 1) && ( accepts_focus)))) + continue; + } + if (m->vkbd != 0) + { + int vkbd = 0; + + if (cw->bd->client.vkbd.vkbd) + vkbd = 1; + if (!(((m->vkbd == -1) && (!vkbd)) || + ((m->vkbd == 1) && ( vkbd)))) + continue; + } + if (m->quickpanel != 0) + { + int quickpanel = 0; + + if (cw->bd->client.illume.quickpanel.quickpanel) + quickpanel = 1; + if (!(((m->quickpanel == -1) && (!quickpanel)) || + ((m->quickpanel == 1) && ( quickpanel)))) + continue; + } + if (m->argb != 0) + { + if (!(((m->argb == -1) && (!cw->argb)) || + ((m->argb == 1) && ( cw->argb)))) + continue; + } + if (m->fullscreen != 0) + { + int fullscreen = 0; + + if (cw->bd->client.netwm.state.fullscreen) + fullscreen = 1; + if (!(((m->fullscreen == -1) && (!fullscreen)) || + ((m->fullscreen == 1) && ( fullscreen)))) + continue; + } + if (m->modal != 0) + { + int modal = 0; + + if (cw->bd->client.netwm.state.modal) + modal = 1; + if (!(((m->modal == -1) && (!modal)) || + ((m->modal == 1) && ( modal)))) + continue; + } + } + if (m->shadow_style) + { + snprintf(buf, sizeof(buf), "e/comp/%s", + m->shadow_style); + ok = e_theme_edje_object_set(cw->shobj, "base/theme/borders", + buf); + if (ok) break; + } + } // use different shadow objects/group per window type? - if (_comp_mod->conf->shadow_file) - ok = edje_object_file_set(cw->shobj, _comp_mod->conf->shadow_file, - "shadow"); + if (!ok) + { + if (_comp_mod->conf->shadow_file) + ok = edje_object_file_set(cw->shobj, _comp_mod->conf->shadow_file, + "shadow"); + } if (!ok) { if (_comp_mod->conf->shadow_style) @@ -1001,6 +1151,21 @@ _e_mod_comp_win_add(E_Comp *c, Ecore_X_Window win) if (cw->menu) cw->dfn = e_object_delfn_add(E_OBJECT(cw->menu), _e_mod_comp_object_del, cw); + else + { + char *netwm_title = NULL; + + cw->title = ecore_x_icccm_title_get(cw->win); + if (ecore_x_netwm_name_get(cw->win, &netwm_title)) + { + if (cw->title) free(cw->title); + cw->title = netwm_title; + } + ecore_x_icccm_name_class_get(cw->win, &cw->name, &cw->clas); + cw->role = ecore_x_icccm_window_role_get(cw->win); + if (!ecore_x_netwm_window_type_get(cw->win, &cw->primary_type)) + cw->primary_type = ECORE_X_WINDOW_TYPE_UNKNOWN; + } } _e_mod_comp_win_sync_setup(cw, cw->win); } @@ -1174,6 +1339,10 @@ _e_mod_comp_win_del(E_Comp_Win *cw) ecore_x_damage_free(cw->damage); cw->damage = 0; } + if (cw->title) free(cw->title); + if (cw->name) free(cw->name); + if (cw->clas) free(cw->clas); + if (cw->role) free(cw->role); cw->c->wins = eina_inlist_remove(cw->c->wins, EINA_INLIST_GET(cw)); free(cw); } diff --git a/src/modules/comp/e_mod_main.c b/src/modules/comp/e_mod_main.c index edde1d63e..ee142770e 100644 --- a/src/modules/comp/e_mod_main.c +++ b/src/modules/comp/e_mod_main.c @@ -39,6 +39,26 @@ e_modapi_init(E_Module *m) e_configure_registry_category_add("appearance", 10, _("Look"), NULL, "preferences-appearance"); e_configure_registry_item_add("appearance/comp", 120, _("Composite"), NULL, buf, e_int_config_comp_module); + mod->conf_match_edd = E_CONFIG_DD_NEW("Comp_Match", Match); +#undef T +#undef D +#define T Match +#define D mod->conf_match_edd + E_CONFIG_VAL(D, T, title, STR); + E_CONFIG_VAL(D, T, name, STR); + E_CONFIG_VAL(D, T, clas, STR); + E_CONFIG_VAL(D, T, role, STR); + E_CONFIG_VAL(D, T, primary_type, INT); + E_CONFIG_VAL(D, T, borderless, CHAR); + E_CONFIG_VAL(D, T, dialog, CHAR); + E_CONFIG_VAL(D, T, accepts_focus, CHAR); + E_CONFIG_VAL(D, T, vkbd, CHAR); + E_CONFIG_VAL(D, T, quickpanel, CHAR); + E_CONFIG_VAL(D, T, argb, CHAR); + E_CONFIG_VAL(D, T, fullscreen, CHAR); + E_CONFIG_VAL(D, T, modal, CHAR); + E_CONFIG_VAL(D, T, shadow_style, STR); + mod->conf_edd = E_CONFIG_DD_NEW("Comp_Config", Config); #undef T #undef D @@ -63,6 +83,10 @@ e_modapi_init(E_Module *m) E_CONFIG_VAL(D, T, max_unmapped_pixels, INT); E_CONFIG_VAL(D, T, max_unmapped_time, INT); E_CONFIG_VAL(D, T, min_unmapped_time, INT); + E_CONFIG_LIST(D, T, match.popups, mod->conf_match_edd); + E_CONFIG_LIST(D, T, match.borders, mod->conf_match_edd); + E_CONFIG_LIST(D, T, match.overrides, mod->conf_match_edd); + E_CONFIG_LIST(D, T, match.menus, mod->conf_match_edd); mod->conf = e_config_domain_load("module.comp", mod->conf_edd); if (!mod->conf) @@ -87,6 +111,8 @@ e_modapi_init(E_Module *m) mod->conf->max_unmapped_pixels = 32 * 1024; // implement mod->conf->max_unmapped_time = 10 * 3600; // implement mod->conf->min_unmapped_time = 5 * 60; // implement + + // FIXME: add some default matches } _comp_mod = mod; @@ -108,6 +134,22 @@ e_modapi_init(E_Module *m) return mod; } +static void +_match_list_free(Eina_List *list) +{ + Match *m; + + EINA_LIST_FREE(list, m) + { + if (m->title) eina_stringshare_del(m->title); + if (m->name) eina_stringshare_del(m->name); + if (m->clas) eina_stringshare_del(m->clas); + if (m->role) eina_stringshare_del(m->role); + if (m->shadow_style) eina_stringshare_del(m->shadow_style); + free(m); + } +} + EAPI int e_modapi_shutdown(E_Module *m) { @@ -125,7 +167,14 @@ e_modapi_shutdown(E_Module *m) } if (mod->conf->shadow_file) eina_stringshare_del(mod->conf->shadow_file); if (mod->conf->shadow_style) eina_stringshare_del(mod->conf->shadow_style); + + _match_list_free(mod->conf->match.popups); + _match_list_free(mod->conf->match.borders); + _match_list_free(mod->conf->match.overrides); + _match_list_free(mod->conf->match.menus); + free(mod->conf); + E_CONFIG_DD_FREE(mod->conf_match_edd); E_CONFIG_DD_FREE(mod->conf_edd); free(mod); diff --git a/src/modules/comp/e_mod_main.h b/src/modules/comp/e_mod_main.h index 30e7a07a4..a93d4b805 100644 --- a/src/modules/comp/e_mod_main.h +++ b/src/modules/comp/e_mod_main.h @@ -4,6 +4,7 @@ typedef struct _Config Config; typedef struct _Mod Mod; +typedef struct _Match Match; struct _Config { @@ -26,6 +27,13 @@ struct _Config int max_unmapped_pixels; int max_unmapped_time; int min_unmapped_time; + + struct { + Eina_List *popups; // used for e popups + Eina_List *borders; // used for borders + Eina_List *overrides; // used for client menus, tooltips etc. + Eina_List *menus; // used for e menus + } match; }; struct _Mod @@ -33,11 +41,32 @@ struct _Mod E_Module *module; E_Config_DD *conf_edd; + E_Config_DD *conf_match_edd; Config *conf; E_Config_Dialog *config_dialog; }; +struct _Match +{ + const char *title; // glob - used for borders, NULL if not to be used + const char *name; // glob - used for borders, overrides, popups, NULL if not to be used + const char *clas; // glob - used for borders, overrides, NULL if not to be used + const char *role; // glob - used for borders + + int primary_type; // Ecore_X_Window_Type - used for borders, overrides, first one found - ECORE_X_WINDOW_TYPE_UNKNOWN if not to be used + char borderless; // used for borders, 0 == dont use, 1 == borderless, -1 == not borderless + char dialog; // used for borders, 0 == don't use, 1 == dialog, -1 == not dialog + char accepts_focus; // used for borders, 0 == don't use, 1 == accepts focus, -1 == does not accept focus + char vkbd; // used for borders, 0 == don't use, 1 == is vkbd, -1 == not vkbd + char quickpanel; // used for borders, 0 == don't use, 1 == is quickpanel, -1 == not quickpanel + char argb; // used for borders, overrides, popups, 0 == don't use, 1 == is argb, -1 == not argb + char fullscreen; // used for borders, 0 == don't use, 1 == is fullscreen, -1 == not fullscreen + char modal; // used for borders, 0 == don't use, 1 == is modal, -1 == not modal + + const char *shadow_style; // shadow style to use +}; + extern Mod *_comp_mod; EAPI extern E_Module_Api e_modapi;