? eel
Index: tasklist.c
===================================================================
RCS file: /cvs/gnome/libwnck/libwnck/tasklist.c,v
retrieving revision 1.51
diff -u -r1.51 tasklist.c
--- tasklist.c	22 Oct 2003 00:07:37 -0000	1.51
+++ tasklist.c	28 Oct 2003 13:35:56 -0000
@@ -208,6 +208,12 @@
 					     GtkWidget	    *widget);
 static void     wnck_tasklist_free_tasks    (WnckTasklist   *tasklist);
 static void     wnck_tasklist_update_lists  (WnckTasklist   *tasklist);
+static void     wnck_tasklist_try_layout    (GtkAllocation  *allocation,
+					     int             max_width,
+					     int             max_height,
+					     int             n_buttons,
+					     int            *n_cols_out,
+					     int            *n_rows_out);
 static int      wnck_tasklist_layout        (GtkAllocation  *allocation,
 					     int             max_width,
 					     int             max_height,
@@ -565,7 +571,7 @@
 }
 
 /* set the minimum width 
- * use -1 to unset it (resulting in the default width */
+ * use -1 to unset it (resulting in the default width) */
 void 
 wnck_tasklist_set_minimum_width (WnckTasklist *tasklist, gint size)
 {
@@ -590,7 +596,7 @@
 }
 
 /* set the minimum height
- * use -1 to unset it (resulting in the default height */
+ * use -1 to unset it (resulting in the default height) */
 void 
 wnck_tasklist_set_minimum_height (WnckTasklist *tasklist, gint size)
 {
@@ -641,8 +647,28 @@
   tasklist->priv->free_icon_loader_data = free_data_func;  
 }
 
+static void
+wnck_tasklist_try_layout (GtkAllocation *allocation,
+			  int            max_width,
+			  int            max_height,
+			  int            n_buttons,
+		 	  int           *n_cols_out,
+			  int           *n_rows_out)
+{
+  if (allocation->height != -1)
+    {
+      wnck_tasklist_layout (allocation, max_width, max_height, n_buttons,
+			    n_cols_out, n_rows_out);
+    }
+  else
+    {
+      *n_cols_out = n_buttons;
+      *n_rows_out = 1;
+    }
+}
+
 /* returns the maximal possible button width (i.e. if you
- * don't want to stretch the buttons to fill the alloctions
+ * don't want to stretch the buttons to fill the allocations
  * the width can be smaller) */
 static int
 wnck_tasklist_layout (GtkAllocation *allocation,
@@ -761,9 +787,10 @@
   WnckTasklist *tasklist;
   GtkRequisition child_req;
   GtkAllocation  fake_allocation;
+  int req_height;
+  int req_width;
   int max_height = 1;
   int max_width = 1;
-  /* int u_width, u_height; */
   GList *l;
   GArray *array;
   GList *ungrouped_apps;
@@ -772,7 +799,6 @@
   int n_rows;
   int n_cols, last_n_cols;
   int n_grouped_buttons;
-  gboolean score_set;
   int val;
   WnckTask *app_task;
   int lowest_range;
@@ -829,32 +855,18 @@
   tasklist->priv->max_button_width = max_width;
   tasklist->priv->max_button_height = max_height;
 
+  gtk_widget_get_size_request (widget, &req_width, &req_height);
+  if (req_width != -1)
+    requisition->width = req_width;
 
-  /* this snippet of code seems to want to allocate at least
-   * four buttons' worth of height for the widget.  I think this isn't
-   * necessary any more now that we have the minimum_size option, so
-   * I'm commenting this out - thomasvs */
-  /*
-  gtk_widget_get_size_request (widget, &u_width, &u_height);
-
-  if (u_height != -1)
-    {
-      requisition->height = u_height;
-    }
-  else if (u_width != -1)
-    {
-      requisition->width = u_width;
-      requisition->height = 4 * max_height;
-    }
+  if (req_height != -1)
+    requisition->height = req_height;
   
   requisition->width = MAX(requisition->width, tasklist->priv->minimum_width);
   requisition->height = MAX(requisition->height, tasklist->priv->minimum_height);
-  */
-  requisition->width = tasklist->priv->minimum_width;
-  requisition->height = tasklist->priv->minimum_height;
-  
-  fake_allocation.width = requisition->width;
-  fake_allocation.height = requisition->height;
+
+  fake_allocation.width = req_width;
+  fake_allocation.height = req_height;
 
   array = g_array_new (FALSE, FALSE, sizeof (int));
 
@@ -864,17 +876,16 @@
   n_startup_sequences = g_list_length (tasklist->priv->startup_sequences);
   n_grouped_buttons = 0;
   ungrouped_apps = g_list_copy (tasklist->priv->applications);
-  score_set = FALSE;
 
   grouping_limit = MIN (tasklist->priv->grouping_limit,
 			tasklist->priv->max_button_width);
   
   /* Try ungrouped mode */
-  wnck_tasklist_layout (&fake_allocation,
-			tasklist->priv->max_button_width,
-			tasklist->priv->max_button_height,
-			n_windows + n_startup_sequences,
-			&n_cols, &n_rows);
+  wnck_tasklist_try_layout (&fake_allocation,
+			    tasklist->priv->max_button_width,
+			    tasklist->priv->max_button_height,
+			    n_windows + n_startup_sequences,
+			    &n_cols, &n_rows);
 
   last_n_cols = G_MAXINT;
   lowest_range = G_MAXINT;
@@ -889,24 +900,22 @@
       lowest_range = val;
     }
 
+  if (tasklist->priv->grouping != WNCK_TASKLIST_NEVER_GROUP)
+    wnck_tasklist_score_groups (tasklist, ungrouped_apps);
+
   while (ungrouped_apps != NULL &&
 	 tasklist->priv->grouping != WNCK_TASKLIST_NEVER_GROUP)
     {
-      if (!score_set)
-	{
-	  wnck_tasklist_score_groups (tasklist, ungrouped_apps);
-	  score_set = TRUE;
-	}
 
       ungrouped_apps = wnck_task_get_highest_scored (ungrouped_apps, &app_task);
 
       n_grouped_buttons += g_list_length (app_task->windows) - 1;
 
-      wnck_tasklist_layout (&fake_allocation,
-			    tasklist->priv->max_button_width,
-			    tasklist->priv->max_button_height,
-			    n_startup_sequences + n_windows - n_grouped_buttons,
-			    &n_cols, &n_rows);
+      wnck_tasklist_try_layout (&fake_allocation,
+				tasklist->priv->max_button_width,
+				tasklist->priv->max_button_height,
+				n_startup_sequences + n_windows - n_grouped_buttons,
+				&n_cols, &n_rows);
       if (n_cols != last_n_cols &&
 	  (tasklist->priv->grouping == WNCK_TASKLIST_AUTO_GROUP ||
 	   ungrouped_apps == NULL))
@@ -969,12 +978,13 @@
   int n_startup_sequences;
   GList *l;
   int button_width;
-  int total_width;
+  int missing_width;
+  int button_height;
+  int missing_height;
   int n_rows;
   int n_cols;
   int n_grouped_buttons;
   int i;
-  gboolean score_set;
   GList *ungrouped_apps;
   WnckTask *win_task;
   GList *visible_tasks = NULL;
@@ -986,7 +996,6 @@
   n_startup_sequences = g_list_length (tasklist->priv->startup_sequences);
   n_grouped_buttons = 0;
   ungrouped_apps = g_list_copy (tasklist->priv->applications);
-  score_set = FALSE;
 
   grouping_limit = MIN (tasklist->priv->grouping_limit,
 			tasklist->priv->max_button_width);
@@ -997,17 +1006,15 @@
 				       tasklist->priv->max_button_height,
 				       n_startup_sequences + n_windows,
 				       &n_cols, &n_rows);
+
+  if (tasklist->priv->grouping != WNCK_TASKLIST_NEVER_GROUP)
+    wnck_tasklist_score_groups (tasklist, ungrouped_apps);
+
   while (ungrouped_apps != NULL &&
 	 ((tasklist->priv->grouping == WNCK_TASKLIST_ALWAYS_GROUP) ||
 	  ((tasklist->priv->grouping == WNCK_TASKLIST_AUTO_GROUP) &&
 	   (button_width < grouping_limit))))
     {
-      if (!score_set)
-	{
-	  wnck_tasklist_score_groups (tasklist, ungrouped_apps);
-	  score_set = TRUE;
-	}
-
       ungrouped_apps = wnck_task_get_highest_scored (ungrouped_apps, &app_task);
 
       n_grouped_buttons += g_list_length (app_task->windows) - 1;
@@ -1059,21 +1066,54 @@
   /* Allocate children */
   l = visible_tasks;
   i = 0;
-  total_width = tasklist->priv->max_button_width * n_cols;
-  total_width = MIN (total_width, allocation->width);
-  total_width = allocation->width;
+
+  if (allocation->width > tasklist->priv->max_button_width)
+    button_width = MIN (tasklist->priv->max_button_width + (allocation->width % tasklist->priv->max_button_width) / (allocation->width / tasklist->priv->max_button_width),
+                       allocation->width / n_cols);
+  else
+    button_width = allocation->width / n_cols;
+  missing_width = allocation->width - button_width * n_cols;
+
+  if (allocation->height > tasklist->priv->max_button_height)
+    button_height = MIN (tasklist->priv->max_button_height + (allocation->height % tasklist->priv->max_button_height) / (allocation->height / tasklist->priv->max_button_height),
+                       allocation->height / n_rows);
+  else
+    button_height = allocation->height / n_rows;
+  missing_height = allocation->height - button_height * n_rows;
+
   while (l != NULL)
     {
       WnckTask *task = WNCK_TASK (l->data);
-      int col = i % n_cols;
-      int row = i / n_cols;
+      int col = i / n_rows;
+      int row = i % n_rows;
       
-      child_allocation.x = total_width*col / n_cols;
-      child_allocation.y = allocation->height*row / n_rows;
-      child_allocation.width = total_width*(col + 1) / n_cols - child_allocation.x;
-      child_allocation.height = allocation->height*(row + 1) / n_rows - child_allocation.y;
-      child_allocation.x += allocation->x;
-      child_allocation.y += allocation->y;
+      child_allocation.x = button_width * col + allocation->x;
+      child_allocation.y = button_height * row + allocation->y;
+      child_allocation.width = button_width;
+      child_allocation.height = button_height;
+
+      /* we add one pixel for the first missing_height'th rows so we occupy the
+       * whole area */
+      if (row < missing_height)
+        {
+          child_allocation.height++;
+          child_allocation.y += row;
+        }
+      else if (missing_height > 0)
+        {
+          child_allocation.y += missing_height;
+        }
+
+      /* same thing for the width */
+      if (col < missing_width)
+        {
+          child_allocation.width++;
+          child_allocation.x += col;
+        }
+      else if (missing_width > 0)
+        {
+          child_allocation.x += missing_width;
+        }
 
       gtk_widget_size_allocate (task->button, &child_allocation);
       gtk_widget_set_child_visible (GTK_WIDGET (task->button), TRUE);
