Index: libwnck/tasklist.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/tasklist.c,v
retrieving revision 1.90
diff -u -r1.90 tasklist.c
--- libwnck/tasklist.c	19 Dec 2005 18:18:27 -0000	1.90
+++ libwnck/tasklist.c	1 Jan 2006 20:56:45 -0000
@@ -153,6 +153,7 @@
   gboolean include_all_workspaces;
   
   /* Calculated by update_lists */
+  GList *recently_grouped_class_groups;
   GList *class_groups;
   GList *windows;
 
@@ -692,6 +693,7 @@
   
   tasklist->priv->win_hash = g_hash_table_new (NULL, NULL);
   tasklist->priv->class_group_hash = g_hash_table_new (NULL, NULL);
+  tasklist->priv->recently_grouped_class_groups = NULL;
   
   tasklist->priv->grouping = WNCK_TASKLIST_AUTO_GROUP;
   tasklist->priv->grouping_limit = DEFAULT_GROUPING_LIMIT;
@@ -782,6 +784,8 @@
   g_hash_table_destroy (tasklist->priv->class_group_hash);
   tasklist->priv->class_group_hash = NULL;
   
+  g_list_free (tasklist->priv->recently_grouped_class_groups);
+  
   if (tasklist->priv->activate_timeout_id != 0)
     gtk_timeout_remove (tasklist->priv->activate_timeout_id);
   
@@ -989,62 +993,47 @@
 
 static void
 wnck_tasklist_score_groups (WnckTasklist *tasklist,
-			    GList        *ungrouped_class_groups)
+			    GList        *class_groups)
 {
   WnckTask *class_group_task;
-  WnckTask *win_task;
+  WnckWindow *window;
   GList *l, *w;
-  const char *first_name = NULL;
+  gdouble active_score;
   int n_windows;
-  int n_same_title;
-  double same_window_ratio;
 
-  l = ungrouped_class_groups;
+  l = class_groups;
   while (l != NULL)
     {
       class_group_task = WNCK_TASK (l->data);
 
       n_windows = g_list_length (class_group_task->windows);
-
-      n_same_title = 0;
-      w = class_group_task->windows;
+ 
+      w = wnck_class_group_get_windows (class_group_task->class_group);
+      active_score = 0;
       while (w != NULL)
-	{
-	  win_task = WNCK_TASK (w->data);
-
-	  if (first_name == NULL)
-	    {
-	      first_name = wnck_window_get_icon_name (win_task->window);
-	      n_same_title++;
-	    }
-	  else
-	    {
-	      if (strcmp (wnck_window_get_icon_name (win_task->window),
-			  first_name) == 0)
-		n_same_title++;
-	    }
-	  
-	  w = w->next;
-	}
-      same_window_ratio = (double)n_same_title/(double)n_windows;
-
-      /* FIXME: This is fairly bogus and should be researched more.
-       *        XP groups by least used, so we probably want to add
-       *        total focused time to this expression.
-       */
-      class_group_task->grouping_score = -same_window_ratio * 5 + n_windows;
-
+        {
+          window = WNCK_WINDOW (w->data);
+          
+          active_score += wnck_window_get_active_score (window);
+          
+          w = w->next;
+        }
+      
+      class_group_task->grouping_score = sqrt (active_score) / (float) n_windows;
+      if (g_list_find (tasklist->priv->recently_grouped_class_groups, class_group_task) != NULL)
+        class_group_task->grouping_score -= 1.5;
+      
       l = l->next;
     }
 }
 
 static GList *
-wnck_task_get_highest_scored (GList     *ungrouped_class_groups,
-			      WnckTask **class_group_task_out)
+wnck_task_get_lowest_scored (GList     *ungrouped_class_groups,
+			     WnckTask **class_group_task_out)
 {
   WnckTask *class_group_task;
   WnckTask *best_task = NULL;
-  double max_score = -1000000000.0; /* Large negative score */
+  double lowest_score = 1000; /* cannot be more than that */
   GList *l;
  
   l = ungrouped_class_groups;
@@ -1052,9 +1041,9 @@
     {
       class_group_task = WNCK_TASK (l->data);
 
-      if (class_group_task->grouping_score >= max_score)
+      if (class_group_task->grouping_score <= lowest_score)
 	{
-	  max_score = class_group_task->grouping_score;
+	  lowest_score = class_group_task->grouping_score;
 	  best_task = class_group_task;
 	}
       
@@ -1210,7 +1199,7 @@
 	  score_set = TRUE;
 	}
 
-      ungrouped_class_groups = wnck_task_get_highest_scored (ungrouped_class_groups, &class_group_task);
+      ungrouped_class_groups = wnck_task_get_lowest_scored (ungrouped_class_groups, &class_group_task);
 
       n_grouped_buttons += g_list_length (class_group_task->windows) - 1;
 
@@ -1294,6 +1283,7 @@
   GList *visible_tasks = NULL;
   GList *windows_sorted = NULL;
   int grouping_limit;
+  GList *new_recently_grouped = NULL;
   
   tasklist = WNCK_TASKLIST (widget);
 
@@ -1323,7 +1313,8 @@
 	  score_set = TRUE;
 	}
 
-      ungrouped_class_groups = wnck_task_get_highest_scored (ungrouped_class_groups, &class_group_task);
+      ungrouped_class_groups = wnck_task_get_lowest_scored (ungrouped_class_groups, &class_group_task);
+      new_recently_grouped = g_list_append (new_recently_grouped, class_group_task);
 
       n_grouped_buttons += g_list_length (class_group_task->windows) - 1;
 
@@ -1369,6 +1360,9 @@
 					   n_startup_sequences + n_windows - n_grouped_buttons,
 					   &n_cols, &n_rows);
     }
+  
+  g_list_free (tasklist->priv->recently_grouped_class_groups);
+  tasklist->priv->recently_grouped_class_groups = new_recently_grouped;
 
   /* Add all ungrouped windows to visible_tasks, and hide their class groups */
   l = ungrouped_class_groups;
Index: libwnck/window.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/window.c,v
retrieving revision 1.61
diff -u -r1.61 window.c
--- libwnck/window.c	19 Sep 2005 16:22:53 -0000	1.61
+++ libwnck/window.c	1 Jan 2006 20:56:49 -0000
@@ -21,6 +21,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include <math.h>
 #include <string.h>
 #include "window.h"
 #include "class-group.h"
@@ -128,6 +129,10 @@
   guint need_update_startup_id : 1;
   guint need_update_wmclass : 1;
   guint need_update_wmhints : 1;
+  
+  gdouble  active_score;
+  GTimer  *update_score_timer;
+  gulong   active_changed_handler_id;
 };
 
 enum {
@@ -155,6 +160,7 @@
                                     WnckWindowActions new_actions);
 static void emit_geometry_changed  (WnckWindow      *window);
 
+static void update_active_score (WnckWindow *window);
 static void update_name      (WnckWindow *window);
 static void update_state     (WnckWindow *window);
 static void update_wm_state  (WnckWindow *window);
@@ -312,8 +318,12 @@
   if (window->priv->app)
     g_object_unref (G_OBJECT (window->priv->app));
 
-  g_free (window->priv);
+  g_timer_destroy (window->priv->update_score_timer);
+  g_signal_handler_disconnect (window->priv->screen,
+                               window->priv->active_changed_handler_id);
 
+  g_free (window->priv);
+  
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -411,6 +421,14 @@
   window->priv->need_update_startup_id = TRUE;
   window->priv->need_update_wmclass = TRUE;
   window->priv->need_update_wmhints = TRUE;
+  
+  window->priv->active_score = 0;
+  window->priv->update_score_timer = g_timer_new ();
+  
+  window->priv->active_changed_handler_id =
+    g_signal_connect_swapped (screen, "active_window_changed",
+                              G_CALLBACK (update_active_score), window);
+  
   force_update_now (window);
 
   return window;
@@ -1418,6 +1436,24 @@
 }
 
 /**
+ * wnck_window_get_active_score:
+ * @window: a #WnckWindow
+ *
+ * This function will update the value of the activity score, and return it.
+ *
+ * Return value: The activity score of the window.
+ **/
+gfloat
+wnck_window_get_active_score (WnckWindow *window)
+{
+  g_return_val_if_fail (WNCK_IS_WINDOW (window), 0.0);
+  
+  update_active_score (window);
+  return window->priv->active_score;
+}
+
+
+/**
  * wnck_window_get_actions:
  * @window: a #WnckWindow
  * 
@@ -2205,6 +2241,20 @@
 
   window->priv->need_update_wmhints = FALSE;
 }
+
+static void
+update_active_score (WnckWindow *window)
+{
+  gdouble elapsed_time;
+  
+  elapsed_time = g_timer_elapsed (window->priv->update_score_timer, NULL);
+  g_timer_reset (window->priv->update_score_timer);
+  window->priv->active_score *= pow (0.9977, elapsed_time);
+  
+  if (window == wnck_screen_get_previously_active_window (window->priv->screen))
+    window->priv->active_score += MIN(elapsed_time, 300.0);
+}
+
 
 static void
 force_update_now (WnckWindow *window)
Index: libwnck/window.h
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/window.h,v
retrieving revision 1.35
diff -u -r1.35 window.h
--- libwnck/window.h	19 Jul 2005 10:18:04 -0000	1.35
+++ libwnck/window.h	1 Jan 2006 20:56:49 -0000
@@ -210,6 +210,7 @@
 GdkPixbuf* wnck_window_get_mini_icon (WnckWindow *window);
 
 gboolean wnck_window_get_icon_is_fallback (WnckWindow *window);
+gfloat   wnck_window_get_active_score     (WnckWindow *window);
 
 void wnck_window_set_icon_geometry        (WnckWindow *window,
 					   int         x,
