diff --git a/AUTHORS b/AUTHORS index 1cdfc1ec1..2639e1cc2 100644 --- a/AUTHORS +++ b/AUTHORS @@ -14,4 +14,4 @@ Stafford Horne Cedric Bail onefang (David Seikel) LinuxTitan (Stephen Houston) -Metrics +Byron Hillis diff --git a/TODO b/TODO index a94ff1cd2..f725f3a41 100644 --- a/TODO +++ b/TODO @@ -10,7 +10,6 @@ Some of the things (in very short form) that need to be done to E17... * BUG: smart placement seems to screw up if a shelf is at the top of the screen * BUG: e17 screen res diaolg doesnt work under xephyr - why? -* BUG: "match this window only" doesnt fall back to other unused remembers * BUG: xdaliclock -transparent doesnt use shaped border (not handling shape change later) ]]] diff --git a/src/bin/e_border.c b/src/bin/e_border.c index 52237abd9..64cb4daa5 100644 --- a/src/bin/e_border.c +++ b/src/bin/e_border.c @@ -5312,8 +5312,8 @@ _e_border_eval(E_Border *bd) } if (!bd->remember) { - rem = e_remember_find(bd); - if ((rem) && (e_remember_usable_get(rem))) + rem = e_remember_find_usable(bd); + if (rem) { bd->remember = rem; e_remember_use(rem); diff --git a/src/bin/e_config.c b/src/bin/e_config.c index a1785e36e..eb9cdab42 100644 --- a/src/bin/e_config.c +++ b/src/bin/e_config.c @@ -249,6 +249,7 @@ e_config_init(void) E_CONFIG_VAL(D, T, type, INT); E_CONFIG_VAL(D, T, transient, UCHAR); E_CONFIG_VAL(D, T, apply, INT); + E_CONFIG_VAL(D, T, max_score, INT); E_CONFIG_VAL(D, T, prop.pos_x, INT); E_CONFIG_VAL(D, T, prop.pos_y, INT); E_CONFIG_VAL(D, T, prop.res_x, INT); diff --git a/src/bin/e_int_border_locks.c b/src/bin/e_int_border_locks.c index a44e22095..85262cc97 100644 --- a/src/bin/e_int_border_locks.c +++ b/src/bin/e_int_border_locks.c @@ -181,24 +181,19 @@ _basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) flag = cfdata->keep_my_border; cfdata->border->lock_border = flag; - /* FIXME: need to check if the remember stuff will actually work or not - * (see e_int_border_remember.c where it checks and warns) */ if (cfdata->remember_locks) { if (!cfdata->border->remember) { cfdata->border->remember = e_remember_new(); if (cfdata->border->remember) - { e_remember_use(cfdata->border->remember); - e_remember_update(cfdata->border->remember, cfdata->border); - cfdata->border->remember->match |= E_REMEMBER_MATCH_NAME; - cfdata->border->remember->match |= E_REMEMBER_MATCH_CLASS; - cfdata->border->remember->match |= E_REMEMBER_MATCH_ROLE; - cfdata->border->remember->match |= E_REMEMBER_MATCH_TYPE; - cfdata->border->remember->match |= E_REMEMBER_MATCH_TRANSIENT; - cfdata->border->remember->apply |= E_REMEMBER_APPLY_LOCKS; - } + } + if (cfdata->border->remember) + { + cfdata->border->remember->apply |= E_REMEMBER_APPLY_LOCKS; + cfdata->border->remember->match = e_remember_default_match(cfdata->border); + e_remember_update(cfdata->border->remember, cfdata->border); } } else @@ -245,24 +240,20 @@ _advanced_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) cfdata->border->lock_focus_in = cfdata->lock.focus_in; cfdata->border->lock_focus_out = cfdata->lock.focus_out; cfdata->border->lock_life = cfdata->lock.life; - /* FIXME: need to check if the remember stuff will actually work or not - * (see e_int_border_remember.c where it checks and warns) */ + if (cfdata->lock.remember) { if (!cfdata->border->remember) { cfdata->border->remember = e_remember_new(); if (cfdata->border->remember) - { e_remember_use(cfdata->border->remember); - e_remember_update(cfdata->border->remember, cfdata->border); - cfdata->border->remember->match |= E_REMEMBER_MATCH_NAME; - cfdata->border->remember->match |= E_REMEMBER_MATCH_CLASS; - cfdata->border->remember->match |= E_REMEMBER_MATCH_ROLE; - cfdata->border->remember->match |= E_REMEMBER_MATCH_TYPE; - cfdata->border->remember->match |= E_REMEMBER_MATCH_TRANSIENT; - cfdata->border->remember->apply |= E_REMEMBER_APPLY_LOCKS; - } + } + if (cfdata->border->remember) + { + cfdata->border->remember->apply |= E_REMEMBER_APPLY_LOCKS; + cfdata->border->remember->match = e_remember_default_match(cfdata->border); + e_remember_update(cfdata->border->remember, cfdata->border); } } else diff --git a/src/bin/e_int_border_remember.c b/src/bin/e_int_border_remember.c index 9e390a7f6..b7aa39d48 100644 --- a/src/bin/e_int_border_remember.c +++ b/src/bin/e_int_border_remember.c @@ -256,20 +256,13 @@ _basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) { cfdata->border->remember = e_remember_new(); if (cfdata->border->remember) - { e_remember_use(cfdata->border->remember); - e_remember_update(cfdata->border->remember, cfdata->border); - } } + if (cfdata->border->remember) { - if ((cfdata->border->client.icccm.name) && - (cfdata->border->client.icccm.class) && - (cfdata->border->client.icccm.name[0] != 0) && - (cfdata->border->client.icccm.class[0] != 0)) - cfdata->border->remember->match = E_REMEMBER_MATCH_NAME | E_REMEMBER_MATCH_CLASS | E_REMEMBER_MATCH_ROLE | E_REMEMBER_MATCH_TYPE | E_REMEMBER_MATCH_TRANSIENT; - else - cfdata->border->remember->match = E_REMEMBER_MATCH_TITLE | E_REMEMBER_MATCH_ROLE | E_REMEMBER_MATCH_TYPE | E_REMEMBER_MATCH_TRANSIENT; + cfdata->border->remember->match = e_remember_default_match(cfdata->border); + if (cfdata->mode == MODE_GEOMETRY) cfdata->border->remember->apply = E_REMEMBER_APPLY_POS | E_REMEMBER_APPLY_SIZE; else if (cfdata->mode == MODE_LOCKS) @@ -279,6 +272,7 @@ _basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) else if (cfdata->mode == MODE_ALL) cfdata->border->remember->apply = E_REMEMBER_APPLY_POS | E_REMEMBER_APPLY_SIZE | E_REMEMBER_APPLY_LAYER | E_REMEMBER_APPLY_LOCKS | E_REMEMBER_APPLY_BORDER | E_REMEMBER_APPLY_STICKY | E_REMEMBER_APPLY_DESKTOP | E_REMEMBER_APPLY_SHADE | E_REMEMBER_APPLY_ZONE | E_REMEMBER_APPLY_SKIP_WINLIST; cfdata->border->remember->apply_first_only = 0; + e_remember_update(cfdata->border->remember, cfdata->border); } e_config_save_queue(); @@ -380,14 +374,12 @@ _advanced_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) { cfdata->border->remember = e_remember_new(); if (cfdata->border->remember) - { - e_remember_use(cfdata->border->remember); - e_remember_update(cfdata->border->remember, cfdata->border); - } + e_remember_use(cfdata->border->remember); } if (cfdata->border->remember) { cfdata->border->remember->apply = 0; + cfdata->border->remember->match = 0; if (cfdata->remember.match_name) cfdata->border->remember->match |= E_REMEMBER_MATCH_NAME; if (cfdata->remember.match_class) cfdata->border->remember->match |= E_REMEMBER_MATCH_CLASS; if (cfdata->remember.match_title) cfdata->border->remember->match |= E_REMEMBER_MATCH_TITLE; @@ -406,6 +398,7 @@ _advanced_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) if (cfdata->remember.apply_skip_winlist) cfdata->border->remember->apply |= E_REMEMBER_APPLY_SKIP_WINLIST; if (cfdata->remember.apply_run) cfdata->border->remember->apply |= E_REMEMBER_APPLY_RUN; cfdata->border->remember->apply_first_only = cfdata->remember.apply_first_only; + e_remember_update(cfdata->border->remember, cfdata->border); } e_config_save_queue(); diff --git a/src/bin/e_int_config_borders.c b/src/bin/e_int_config_borders.c index cd9532c13..be1d3c03a 100644 --- a/src/bin/e_int_config_borders.c +++ b/src/bin/e_int_config_borders.c @@ -124,23 +124,27 @@ _basic_apply_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) static void _basic_apply_border(E_Config_Dialog_Data *cfdata) { + if ((!cfdata->border->lock_border) && (!cfdata->border->shaded)) + { + if (cfdata->border->bordername) evas_stringshare_del(cfdata->border->bordername); + cfdata->border->bordername = evas_stringshare_add(cfdata->bordername); + cfdata->border->client.border.changed = 1; + cfdata->border->changed = 1; + } if (cfdata->remember_border) { - if (!cfdata->border->remember) - { - cfdata->border->remember = e_remember_new(); - if (cfdata->border->remember) - { - e_remember_use(cfdata->border->remember); - e_remember_update(cfdata->border->remember, cfdata->border); - cfdata->border->remember->match |= E_REMEMBER_MATCH_NAME; - cfdata->border->remember->match |= E_REMEMBER_MATCH_CLASS; - cfdata->border->remember->match |= E_REMEMBER_MATCH_ROLE; - cfdata->border->remember->match |= E_REMEMBER_MATCH_TYPE; - cfdata->border->remember->match |= E_REMEMBER_MATCH_TRANSIENT; - cfdata->border->remember->apply |= E_REMEMBER_APPLY_BORDER; - } - } + if (!cfdata->border->remember) + cfdata->border->remember = e_remember_new(); + { + if (cfdata->border->remember) + e_remember_use(cfdata->border->remember); + } + if (cfdata->border->remember) + { + cfdata->border->remember->apply |= E_REMEMBER_APPLY_BORDER; + cfdata->border->remember->match = e_remember_default_match(cfdata->border); + e_remember_update(cfdata->border->remember, cfdata->border); + } } else { @@ -155,13 +159,6 @@ _basic_apply_border(E_Config_Dialog_Data *cfdata) } } } - if ((!cfdata->border->lock_border) && (!cfdata->border->shaded)) - { - if (cfdata->border->bordername) evas_stringshare_del(cfdata->border->bordername); - cfdata->border->bordername = evas_stringshare_add(cfdata->bordername); - cfdata->border->client.border.changed = 1; - cfdata->border->changed = 1; - } } static Evas_Object * diff --git a/src/bin/e_remember.c b/src/bin/e_remember.c index b192f5c08..ab01123fe 100644 --- a/src/bin/e_remember.c +++ b/src/bin/e_remember.c @@ -3,12 +3,16 @@ */ #include "e.h" +#define REMEMBER_HIERARCHY 1 +#define REMEMBER_SIMPLE 0 + /* local subsystem functions */ static void _e_remember_free(E_Remember *rem); +static int _e_remember_sort_list(void * d1, void * d2); +static E_Remember *_e_remember_find(E_Border *bd, int check_usable); -/* FIXME: match netwm window type - * FIXME: match transient (is it a transient for something or not) - */ + +/* FIXME: match netwm window type */ /* local subsystem globals */ @@ -18,13 +22,14 @@ EAPI int e_remember_init(E_Startup_Mode mode) { Evas_List *l; + int not_updated = 0; if (mode == E_STARTUP_START) { for (l = e_config->remembers; l; l = l->next) { E_Remember *rem; - + rem = l->data; if ((rem->apply & E_REMEMBER_APPLY_RUN) && (rem->prop.command)) @@ -34,6 +39,34 @@ e_remember_init(E_Startup_Mode mode) } } } + +#if 1 + for (l = e_config->remembers; l; l = l->next) + { + E_Remember *rem; + + rem = l->data; + /* Code to bring up old configs to scratch. Can be removed + * after X amount of time, where X is a figure that will be + * decided by whoever remembers to take this out. */ + if (!rem->max_score) + { + int max_count = 0; + if (rem->match & E_REMEMBER_MATCH_NAME) max_count += 2; + if (rem->match & E_REMEMBER_MATCH_CLASS) max_count += 2; + if (rem->match & E_REMEMBER_MATCH_TITLE) max_count += 2; + if (rem->match & E_REMEMBER_MATCH_ROLE) max_count += 2; + if (rem->match & E_REMEMBER_MATCH_TYPE) max_count += 2; + if (rem->match & E_REMEMBER_MATCH_TRANSIENT) max_count +=2; + if (rem->apply_first_only) max_count++; + rem->max_score = max_count; + not_updated = 1; + } + } + + if (not_updated) + e_config->remembers = evas_list_sort(e_config->remembers, evas_list_count(e_config->remembers), _e_remember_sort_list); +#endif return 1; } @@ -100,58 +133,80 @@ e_remember_del(E_Remember *rem) _e_remember_free(rem); } -EAPI E_Remember * +EAPI E_Remember * +e_remember_find_usable(E_Border *bd) +{ + E_Remember * rem; + rem = _e_remember_find(bd, 1); + return rem; +} + +EAPI E_Remember * e_remember_find(E_Border *bd) { - Evas_List *l; - - for (l = e_config->remembers; l; l = l->next) + E_Remember * rem; + rem = _e_remember_find(bd, 0); + return rem; +} + +EAPI void +e_remember_match_update(E_Remember *rem) +{ + int max_count = 0; + + if (rem->match & E_REMEMBER_MATCH_NAME) max_count += 2; + if (rem->match & E_REMEMBER_MATCH_CLASS) max_count += 2; + if (rem->match & E_REMEMBER_MATCH_TITLE) max_count += 2; + if (rem->match & E_REMEMBER_MATCH_ROLE) max_count += 2; + if (rem->match & E_REMEMBER_MATCH_TYPE) max_count += 2; + if (rem->match & E_REMEMBER_MATCH_TRANSIENT) max_count +=2; + if (rem->apply_first_only) max_count++; + + if (max_count != rem->max_score) { - E_Remember *rem; - int required_matches; - int matches; - const char *title = ""; - - rem = l->data; - matches = 0; - required_matches = 0; - if (rem->match & E_REMEMBER_MATCH_NAME) required_matches++; - if (rem->match & E_REMEMBER_MATCH_CLASS) required_matches++; - if (rem->match & E_REMEMBER_MATCH_TITLE) required_matches++; - if (rem->match & E_REMEMBER_MATCH_ROLE) required_matches++; - if (rem->match & E_REMEMBER_MATCH_TYPE) required_matches++; - if (rem->match & E_REMEMBER_MATCH_TRANSIENT) required_matches++; - - if (bd->client.netwm.name) title = bd->client.netwm.name; - else title = bd->client.icccm.title; - - if ((rem->match & E_REMEMBER_MATCH_NAME) && - ((!e_util_strcmp(rem->name, bd->client.icccm.name)) || - (e_util_both_str_empty(rem->name, bd->client.icccm.name)))) - matches++; - if ((rem->match & E_REMEMBER_MATCH_CLASS) && - ((!e_util_strcmp(rem->class, bd->client.icccm.class)) || - (e_util_both_str_empty(rem->class, bd->client.icccm.class)))) - matches++; - if ((rem->match & E_REMEMBER_MATCH_TITLE) && - ((!e_util_strcmp(rem->title, title)) || - (e_util_both_str_empty(rem->title, title)))) - matches++; - if ((rem->match & E_REMEMBER_MATCH_ROLE) && - ((!e_util_strcmp(rem->role, bd->client.icccm.window_role)) || - (e_util_both_str_empty(rem->role, bd->client.icccm.window_role)))) - matches++; - if ((rem->match & E_REMEMBER_MATCH_TYPE) && - (rem->type == bd->client.netwm.type)) - matches++; - if ((rem->match & E_REMEMBER_MATCH_TRANSIENT) && - (((rem->transient) && (bd->client.icccm.transient_for != 0)) || - ((!rem->transient) && (bd->client.icccm.transient_for == 0)))) - matches++; - if ((matches >= required_matches) && (!rem->delete_me)) - return rem; + /* The number of matches for this remember has changed so we + * need to remove from list and insert back into the appropriate + * loction. */ + Evas_List *l; + E_Remember *r; + rem->max_score = max_count; + e_config->remembers = evas_list_remove(e_config->remembers, rem); + + for (l = e_config->remembers; l; l = l->next) + { + r = l->data; + if (r->max_score <= rem->max_score) + break; + } + + if (l) + e_config->remembers = evas_list_prepend_relative_list(e_config->remembers, rem, l); + else + e_config->remembers = evas_list_append(e_config->remembers, rem); } - return NULL; +} + +EAPI int +e_remember_default_match(E_Border *bd) +{ + int match = E_REMEMBER_MATCH_TRANSIENT; + if ((bd->client.icccm.name) && + (bd->client.icccm.class) && + (bd->client.icccm.name[0] != 0) && + (bd->client.icccm.class[0] != 0)) + match |= E_REMEMBER_MATCH_NAME | E_REMEMBER_MATCH_CLASS; + else + if ((e_border_name_get(bd))[0] != 0) + match |= E_REMEMBER_MATCH_TITLE; + + if ((bd->client.icccm.window_role) && + (bd->client.icccm.window_role[0] != 0)) + match |= E_REMEMBER_MATCH_ROLE; + + if (bd->client.netwm.type != ECORE_X_WINDOW_TYPE_UNKNOWN) + match |= E_REMEMBER_MATCH_TYPE; + + return match; } EAPI void @@ -182,6 +237,8 @@ e_remember_update(E_Remember *rem, E_Border *bd) if (bd->client.icccm.window_role) rem->role = evas_stringshare_add(bd->client.icccm.window_role); + e_remember_match_update(rem); + rem->type = bd->client.netwm.type; if (bd->client.icccm.transient_for != 0) @@ -225,9 +282,9 @@ e_remember_update(E_Remember *rem, E_Border *bd) rem->prop.lock_focus_out = bd->lock_focus_out; rem->prop.lock_life = bd->lock_life; - if (bd->client.border.name) - rem->prop.border = evas_stringshare_add(bd->client.border.name); - + if (bd->bordername) + rem->prop.border = evas_stringshare_add(bd->bordername); + rem->prop.sticky = bd->sticky; if (bd->shaded) @@ -285,6 +342,117 @@ e_remember_update(E_Remember *rem, E_Border *bd) } /* local subsystem functions */ +static E_Remember * +_e_remember_find(E_Border *bd, int check_usable) +{ +#if REMEMBER_SIMPLE + Evas_List *l; + + for (l = e_config->remembers; l; l = l->next) + { + E_Remember *rem; + int required_matches; + int matches; + const char *title = ""; + + rem = l->data; + matches = 0; + required_matches = 0; + if (rem->match & E_REMEMBER_MATCH_NAME) required_matches++; + if (rem->match & E_REMEMBER_MATCH_CLASS) required_matches++; + if (rem->match & E_REMEMBER_MATCH_TITLE) required_matches++; + if (rem->match & E_REMEMBER_MATCH_ROLE) required_matches++; + if (rem->match & E_REMEMBER_MATCH_TYPE) required_matches++; + if (rem->match & E_REMEMBER_MATCH_TRANSIENT) required_matches++; + + if (bd->client.netwm.name) title = bd->client.netwm.name; + else title = bd->client.icccm.title; + + if ((rem->match & E_REMEMBER_MATCH_NAME) && + ((!e_util_strcmp(rem->name, bd->client.icccm.name)) || + (e_util_both_str_empty(rem->name, bd->client.icccm.name)))) + matches++; + if ((rem->match & E_REMEMBER_MATCH_CLASS) && + ((!e_util_strcmp(rem->class, bd->client.icccm.class)) || + (e_util_both_str_empty(rem->class, bd->client.icccm.class)))) + matches++; + if ((rem->match & E_REMEMBER_MATCH_TITLE) && + ((!e_util_strcmp(rem->title, title)) || + (e_util_both_str_empty(rem->title, title)))) + matches++; + if ((rem->match & E_REMEMBER_MATCH_ROLE) && + ((!e_util_strcmp(rem->role, bd->client.icccm.window_role)) || + (e_util_both_str_empty(rem->role, bd->client.icccm.window_role)))) + matches++; + if ((rem->match & E_REMEMBER_MATCH_TYPE) && + (rem->type == bd->client.netwm.type)) + matches++; + if ((rem->match & E_REMEMBER_MATCH_TRANSIENT) && + (((rem->transient) && (bd->client.icccm.transient_for != 0)) || + ((!rem->transient) && (bd->client.icccm.transient_for == 0)))) + matches++; + if ((matches >= required_matches) && (!rem->delete_me)) + return rem; + } + return NULL; +#endif +#if REMEMBER_HIERARCHY + Evas_List *l; + E_Remember *best_rem; + int best_score = 0; + + /* This search method finds the best possible match available and is + * based on the fact that the list is sorted, with those remembers + * with the most possible matches at the start of the list. This + * means, as soon as a valid match is found, it is a match + * within the set of best possible matches. */ + for (l = e_config->remembers; l; l = l->next) + { + E_Remember *rem; + const char *title = ""; + int score = 0; + + rem = l->data; + if (check_usable && !e_remember_usable_get(rem)) + continue; + + if (bd->client.netwm.name) title = bd->client.netwm.name; + else title = bd->client.icccm.title; + + /* For each type of match, check whether the match is + * required, and if it is, check whether there's a match. If + * it fails, then go to the next remember */ + if (rem->match & E_REMEMBER_MATCH_NAME && + e_util_strcmp(rem->name, bd->client.icccm.name) && + !e_util_both_str_empty(rem->name, bd->client.icccm.name)) + continue; + if (rem->match & E_REMEMBER_MATCH_CLASS && + e_util_strcmp(rem->class, bd->client.icccm.class) && + !e_util_both_str_empty(rem->class, bd->client.icccm.class)) + continue; + if (rem->match & E_REMEMBER_MATCH_TITLE && + e_util_strcmp(rem->title, title) && + !e_util_both_str_empty(rem->title, title)) + continue; + if (rem->match & E_REMEMBER_MATCH_ROLE && + e_util_strcmp(rem->role, bd->client.icccm.window_role) && + !e_util_both_str_empty(rem->role, bd->client.icccm.window_role)) + continue; + if (rem->match & E_REMEMBER_MATCH_TYPE && + rem->type != bd->client.netwm.type) + continue; + if (rem->match & E_REMEMBER_MATCH_TRANSIENT && + !(rem->transient && bd->client.icccm.transient_for != 0) && + !(!rem->transient) && (bd->client.icccm.transient_for == 0)) + continue; + + return rem; + } + + return NULL; +#endif +} + static void _e_remember_free(E_Remember *rem) { @@ -297,3 +465,16 @@ _e_remember_free(E_Remember *rem) if (rem->prop.command) evas_stringshare_del(rem->prop.command); free(rem); } + +static int +_e_remember_sort_list(void * d1, void * d2) +{ + E_Remember * r1, * r2; + + r1 = d1; + r2 = d2; + if (r1->max_score >= r2->max_score) + return -1; + else + return 1; +} diff --git a/src/bin/e_remember.h b/src/bin/e_remember.h index d44e13f95..ab79b3892 100644 --- a/src/bin/e_remember.h +++ b/src/bin/e_remember.h @@ -41,6 +41,7 @@ struct _E_Remember int type; unsigned char transient; int apply; + int max_score; struct { int pos_x, pos_y; int res_x, res_y; @@ -99,7 +100,10 @@ EAPI void e_remember_use(E_Remember *rem); EAPI void e_remember_unuse(E_Remember *rem); EAPI void e_remember_del(E_Remember *rem); EAPI E_Remember *e_remember_find(E_Border *bd); +EAPI E_Remember *e_remember_find_usable(E_Border *bd); +EAPI void e_remember_match_update(E_Remember *rem); EAPI void e_remember_update(E_Remember *rem, E_Border *bd); +EAPI int e_remember_default_match(E_Border *bd); #endif #endif