[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[E-devel] [PATCH] Refactoring e_remember



The attached patch fixes one of the bugs in the TODO, that of having
fallbacks for matches where Only Match One Window is set. In order to do
this reliably, the process behind e_remember has been rewritten, to use
a scoring system, where the best match is the one that is used.

Remembering borders and locks from there corresponding menus were also a
bit screwy and dependent on order of ops...not nice. So, everything to
do with remembering window properties is now working with this patch. It
should also be faster than the old version as well. 

There is some code at the top of the file that will convert old configs
to the new version and it can be scrapped in the future.

Any comments, criticisms, suggestions etc., you know where to find me.

metrics

P.S. raster, anything that might seem a bit strange has a good reason.
Let me know what you think. I also noticed my name in the About box,
which is tops...any chance of getting my real name in there (Byron
Hillis)?
Index: TODO
===================================================================
RCS file: /var/cvs/e/e17/apps/e/TODO,v
retrieving revision 1.487
diff -u -r1.487 TODO
--- TODO	21 Oct 2006 11:40:17 -0000	1.487
+++ TODO	24 Oct 2006 11:54:33 -0000
@@ -10,7 +10,6 @@
 
 * 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)
 ]]]
Index: src/bin/e_border.c
===================================================================
RCS file: /var/cvs/e/e17/apps/e/src/bin/e_border.c,v
retrieving revision 1.556
diff -u -r1.556 e_border.c
--- src/bin/e_border.c	21 Oct 2006 02:32:13 -0000	1.556
+++ src/bin/e_border.c	24 Oct 2006 11:56:16 -0000
@@ -5309,8 +5309,8 @@
 	  }
 	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);
Index: src/bin/e_config.c
===================================================================
RCS file: /var/cvs/e/e17/apps/e/src/bin/e_config.c,v
retrieving revision 1.211
diff -u -r1.211 e_config.c
--- src/bin/e_config.c	21 Oct 2006 10:28:01 -0000	1.211
+++ src/bin/e_config.c	24 Oct 2006 11:56:50 -0000
@@ -249,6 +249,7 @@
    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);
Index: src/bin/e_int_border_locks.c
===================================================================
RCS file: /var/cvs/e/e17/apps/e/src/bin/e_int_border_locks.c,v
retrieving revision 1.14
diff -u -r1.14 e_int_border_locks.c
--- src/bin/e_int_border_locks.c	14 Aug 2006 15:22:45 -0000	1.14
+++ src/bin/e_int_border_locks.c	24 Oct 2006 11:56:58 -0000
@@ -181,24 +181,19 @@
    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 @@
    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
Index: src/bin/e_int_border_remember.c
===================================================================
RCS file: /var/cvs/e/e17/apps/e/src/bin/e_int_border_remember.c,v
retrieving revision 1.12
diff -u -r1.12 e_int_border_remember.c
--- src/bin/e_int_border_remember.c	21 Aug 2006 16:08:45 -0000	1.12
+++ src/bin/e_int_border_remember.c	24 Oct 2006 11:57:08 -0000
@@ -256,20 +256,13 @@
      {
 	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 @@
 	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 @@
      {
 	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 @@
 	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();
Index: src/bin/e_int_config_borders.c
===================================================================
RCS file: /var/cvs/e/e17/apps/e/src/bin/e_int_config_borders.c,v
retrieving revision 1.1
diff -u -r1.1 e_int_config_borders.c
--- src/bin/e_int_config_borders.c	14 Oct 2006 09:43:12 -0000	1.1
+++ src/bin/e_int_config_borders.c	24 Oct 2006 11:57:09 -0000
@@ -124,23 +124,27 @@
 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 @@
 	       }
 	  }
      }
-   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 *
Index: src/bin/e_remember.c
===================================================================
RCS file: /var/cvs/e/e17/apps/e/src/bin/e_remember.c,v
retrieving revision 1.18
diff -u -r1.18 e_remember.c
--- src/bin/e_remember.c	4 Sep 2006 13:28:39 -0000	1.18
+++ src/bin/e_remember.c	24 Oct 2006 11:57:16 -0000
@@ -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 @@
 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 @@
 	       }
 	  }
      }
+
+#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_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 @@
    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 @@
    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 @@
 }
 
 /* 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 @@
    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;
+}
Index: src/bin/e_remember.h
===================================================================
RCS file: /var/cvs/e/e17/apps/e/src/bin/e_remember.h,v
retrieving revision 1.8
diff -u -r1.8 e_remember.h
--- src/bin/e_remember.h	8 Jun 2006 19:32:29 -0000	1.8
+++ src/bin/e_remember.h	24 Oct 2006 11:57:17 -0000
@@ -41,6 +41,7 @@
    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_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