Index: panel-applet-frame.c
===================================================================
--- panel-applet-frame.c	(révision 10470)
+++ panel-applet-frame.c	(copie de travail)
@@ -219,12 +219,12 @@ panel_applet_frame_set_size_hints_from_a
 
 	size_hints = g_new0 (int, seq->_length);
 
-	extra_size = 0;
-	if (frame->priv->has_handle)
+	if (frame->priv->has_handle) {
 		extra_size = HANDLE_SIZE + 1;
 	
-	for (i = 0; i < seq->_length; i++)
-		size_hints [i] = seq->_buffer [i] + extra_size;
+		for (i = 0; i < seq->_length; i++)
+			size_hints [i] = seq->_buffer [i] + extra_size;
+	}
 	
 	panel_widget_set_applet_size_hints (frame->priv->panel,
 					    GTK_WIDGET (frame),
Index: panel-toplevel.c
===================================================================
--- panel-toplevel.c	(révision 10472)
+++ panel-toplevel.c	(copie de travail)
@@ -2195,6 +2195,93 @@ calculate_minimum_height (GtkWidget     
 	return PANGO_PIXELS (ascent + descent) + 2 * (focus_width + focus_pad + thickness);
 }
 
+static int
+panel_toplevel_update_size_from_hints (PanelToplevel  *toplevel,
+				       int             requisition_size,
+				       int             monitor_size,
+				       int             handle_size)
+{
+	int                   nb_size_hints;
+	AppletSizeHints      *applets_hints;
+	AppletSizeHintsAlloc *using_hint;
+
+	int i;
+	int total_size;
+	int full_hints;
+
+	total_size = handle_size + requisition_size;
+
+	nb_size_hints = toplevel->priv->panel_widget->nb_applets_size_hints;
+	if (nb_size_hints <= 0)
+		return total_size;
+
+	applets_hints = toplevel->priv->panel_widget->applets_hints;
+	using_hint = toplevel->priv->panel_widget->applets_using_hint;
+
+	for (i = 0; i < nb_size_hints; i++) {
+		using_hint[i].index = applets_hints[i].len - 2;
+		using_hint[i].size = applets_hints[i].hints[applets_hints[i].len - 1];
+		total_size += using_hint[i].size;
+	}
+
+	if (total_size > monitor_size)
+		return monitor_size;
+
+	full_hints = 0;
+	while (full_hints != nb_size_hints && total_size < monitor_size) {
+		int bonus;
+		int extra_bonus;
+
+		bonus = (monitor_size - total_size)
+			/ (nb_size_hints - full_hints);
+		extra_bonus = (monitor_size - total_size)
+			      % (nb_size_hints - full_hints);
+		full_hints = 0;
+
+		for (i = 0; i < nb_size_hints; i++) {
+			int new_size;
+			int current_bonus;
+
+			current_bonus = bonus;
+
+			while (using_hint[i].index > 0 && applets_hints[i].hints[using_hint[i].index - 1] < using_hint[i].size + current_bonus) {
+				new_size = applets_hints[i].hints[using_hint[i].index - 1];
+				current_bonus = using_hint[i].size
+						+ current_bonus - new_size;
+				total_size = total_size - using_hint[i].size
+					     + new_size;
+
+				using_hint[i].index -= 2;
+				using_hint[i].size = new_size;
+			}
+
+			new_size = MIN (applets_hints[i].hints[using_hint[i].index],
+					using_hint[i].size + current_bonus);
+			if (new_size > using_hint[i].size) {
+				total_size += (new_size - using_hint[i].size);
+				using_hint[i].size = new_size;
+			}
+
+			if (extra_bonus > 0) {
+				new_size = MIN (applets_hints[i].hints[using_hint[i].index],
+						using_hint[i].size + extra_bonus);
+				if (new_size > using_hint[i].size) {
+					total_size += (new_size
+						       - using_hint[i].size);
+					extra_bonus -= (new_size
+							- using_hint[i].size);
+					using_hint[i].size = new_size;
+				}
+			}
+
+			if (using_hint[i].size == applets_hints[i].hints[using_hint[i].index])
+				full_hints++;
+		}
+	}
+
+	return total_size;
+}
+
 static void
 panel_toplevel_update_size (PanelToplevel  *toplevel,
 			    GtkRequisition *requisition)
@@ -2225,9 +2312,19 @@ panel_toplevel_update_size (PanelTopleve
 			width  = monitor_width;
 		else if (!toplevel->priv->buttons_enabled &&
 			 !toplevel->priv->attached)
-			width = MAX (MINIMUM_WIDTH, width + 2 * HANDLE_SIZE);
+			width = panel_toplevel_update_size_from_hints (
+							toplevel,
+							requisition->width,
+							monitor_width,
+							2 * HANDLE_SIZE);
 		else
-			width  = MAX (MINIMUM_WIDTH, width);
+			width = panel_toplevel_update_size_from_hints (
+							toplevel,
+							requisition->width,
+							monitor_width,
+							0);
+
+		width  = MAX (MINIMUM_WIDTH, width);
 	} else {
 		width = MAX (MAX (width, toplevel->priv->size), minimum_height);
 
@@ -2235,9 +2332,19 @@ panel_toplevel_update_size (PanelTopleve
 			height = monitor_height;
 		else if (!toplevel->priv->buttons_enabled &&
 			 !toplevel->priv->attached)
-			height = MAX (MINIMUM_WIDTH, height + 2 * HANDLE_SIZE);
+			height = panel_toplevel_update_size_from_hints (
+							toplevel,
+							requisition->height,
+							monitor_height,
+							2 * HANDLE_SIZE);
 		else
-			height = MAX (MINIMUM_WIDTH, height);
+			height = panel_toplevel_update_size_from_hints (
+							toplevel,
+							requisition->height,
+							monitor_height,
+							0);
+
+		height = MAX (MINIMUM_WIDTH, height);
 	}
 
 	if (toplevel->priv->edges & PANEL_EDGE_TOP)
Index: panel-widget.c
===================================================================
--- panel-widget.c	(révision 10470)
+++ panel-widget.c	(copie de travail)
@@ -1191,6 +1191,8 @@ panel_widget_size_request(GtkWidget *wid
 {
 	PanelWidget *panel;
 	GList *list;
+	GList *ad_with_hints;
+	gboolean dont_fill;
 
 	g_return_if_fail(PANEL_IS_WIDGET(widget));
 	g_return_if_fail(requisition!=NULL);
@@ -1205,6 +1207,8 @@ panel_widget_size_request(GtkWidget *wid
 		requisition->width = panel->sz;
 	}
 
+	ad_with_hints = NULL;
+
 	for(list = panel->applet_list; list!=NULL; list = g_list_next(list)) {
 		AppletData *ad = list->data;
 		GtkRequisition chreq;
@@ -1215,7 +1219,8 @@ panel_widget_size_request(GtkWidget *wid
 				requisition->height = chreq.height;
 
 			if (panel->packed && ad->expand_major && ad->size_hints)
-				requisition->width += MAX (ad->size_hints [0], chreq.width); 
+				ad_with_hints = g_list_prepend (ad_with_hints,
+								ad);
 
 			else if (panel->packed)
 				requisition->width += chreq.width;
@@ -1224,7 +1229,8 @@ panel_widget_size_request(GtkWidget *wid
 				requisition->width = chreq.width;
 
 			if (panel->packed && ad->expand_major && ad->size_hints)
-				requisition->height += MAX (ad->size_hints [0], chreq.height);
+				ad_with_hints = g_list_prepend (ad_with_hints,
+								ad);
 
 			else if (panel->packed)
 				requisition->height += chreq.height;
@@ -1237,12 +1243,48 @@ panel_widget_size_request(GtkWidget *wid
 		} else {
 			requisition->height = panel->size;
 		}
-	} 
+	} else {
+		/* put the list in the correct order: this is important
+		 * since we'll use this order in the size_allocate() */
+		ad_with_hints = g_list_reverse (ad_with_hints);
+
+		panel->nb_applets_size_hints = g_list_length (ad_with_hints);
+		if (panel->nb_applets_size_hints > 0) {
+			int i;
+			panel->applets_hints = g_new0 (AppletSizeHints, panel->nb_applets_size_hints);
+
+			i = 0;
+			for (list = ad_with_hints;
+			     list != NULL;
+			     list = g_list_next (list)) {
+				AppletData *ad = list->data;
+
+				panel->applets_hints[i].hints = ad->size_hints;
+				panel->applets_hints[i].len = ad->size_hints_len;
+				i++;
+			}
+
+			panel->applets_using_hint = g_new0 (AppletSizeHintsAlloc, panel->nb_applets_size_hints);
+		} else {
+			panel->nb_applets_size_hints = 0;
+			panel->applets_hints = NULL;
+			panel->applets_using_hint = NULL;
+		}
+	}
 	
-	if (requisition->width < 12)
-		requisition->width = 12;
-	if (requisition->height < 12)
-		requisition->height = 12;
+	dont_fill = panel->packed && panel->nb_applets_size_hints != 0;
+
+	if (panel->orient == GTK_ORIENTATION_HORIZONTAL) {
+		if (requisition->width < 12 && !dont_fill)
+			requisition->width = 12;
+		if (requisition->height < 12)
+			requisition->height = 12;
+	} else {
+		if (requisition->width < 12)
+			requisition->width = 12;
+		if (requisition->height < 12 && !dont_fill)
+			requisition->height = 12;
+	}
 }
 
 static void
@@ -1276,22 +1318,6 @@ panel_widget_set_background_region (Pane
 		widget->allocation.height);
 }
 
-static int
-panel_widget_count_expanded_applets (PanelWidget *panel)
-{
-	GList *li;
-	int count = 0;
-
-	for (li = panel->applet_list; li != NULL; li = li->next) {
-		AppletData *ad = li->data;
-
-		if (ad->expand_major)
-			count ++;
-	}
-
-	return count;
-}
-
 static void
 panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
 {
@@ -1325,20 +1351,9 @@ panel_widget_size_allocate(GtkWidget *wi
 		panel_widget_right_stick(panel,old_size);
 
 	if (panel->packed) {
-		int compression = 0;
-		int applets_to_compress = 0;
-
-		if (panel->orient == GTK_ORIENTATION_HORIZONTAL &&
-		    widget->requisition.width > allocation->width) {
-			compression = widget->requisition.width - allocation->width;
-		} else if (panel->orient == GTK_ORIENTATION_VERTICAL &&
-			   widget->requisition.height > allocation->height) {
-			compression = widget->requisition.height - allocation->height;
-		}
-
-		if (compression > 0) {
-			applets_to_compress = panel_widget_count_expanded_applets (panel);
-		}
+		/* we're assuming the order is the same as the one that was
+		 * in size_request() */
+		int applet_using_hint_index = 0;
 
 		i = 0;
 		for(list = panel->applet_list;
@@ -1358,15 +1373,9 @@ panel_widget_size_allocate(GtkWidget *wi
 					challoc.height = allocation->height;
 
 				if (ad->expand_major && ad->size_hints) {
-					int width = ad->size_hints [0];
-					if (applets_to_compress > 0) {
-						width -= (compression / applets_to_compress);
-						compression -= (compression / applets_to_compress);
-						applets_to_compress --;
-					}
-					challoc.width = CLAMP (MAX (width, chreq.width),
-							       chreq.width,
-							       allocation->width - i);
+					int width = panel->applets_using_hint[applet_using_hint_index].size;
+					applet_using_hint_index++;
+					challoc.width = MIN (width, allocation->width - i);
 				}
 
 				ad->cells = challoc.width;
@@ -1377,15 +1386,9 @@ panel_widget_size_allocate(GtkWidget *wi
 					challoc.width = allocation->width;
 
 				if (ad->expand_major && ad->size_hints) {
-					int height = ad->size_hints [0];
-					if (applets_to_compress > 0) {
-						height -= (compression / applets_to_compress);
-						compression -= (compression / applets_to_compress);
-						applets_to_compress --;
-					}
-					challoc.height = CLAMP (MAX (height, chreq.height),
-								chreq.height,
-								allocation->height - i);
+					int height = panel->applets_using_hint[applet_using_hint_index].size;
+					applet_using_hint_index++;
+					challoc.height = MIN (height, allocation->height - i);
 				}
 
 				ad->cells = challoc.height;
@@ -1396,6 +1399,18 @@ panel_widget_size_allocate(GtkWidget *wi
 			gtk_widget_size_allocate(ad->applet,&challoc);
 			i += ad->cells;
 		}
+
+		panel->nb_applets_size_hints = 0;
+		if (panel->applets_hints != NULL)
+			g_free (panel->applets_hints);
+		panel->applets_hints = NULL;
+		if (panel->applets_using_hint != NULL)
+			g_free (panel->applets_using_hint);
+		panel->applets_using_hint = NULL;
+
+		/* EEEEK, there might be not enough room and we don't handle
+		 * it: all the applets at the right well be unusable */
+
 	} else { /*not packed*/
 
 		/* First make sure there's enough room on the left */
@@ -1408,12 +1423,17 @@ panel_widget_size_allocate(GtkWidget *wi
 
 			gtk_widget_get_child_requisition(ad->applet,&chreq);
 
-			if(panel->orient == GTK_ORIENTATION_HORIZONTAL)
-				ad->cells = chreq.width;
-			else
-				ad->cells = chreq.height;
+			if (!ad->expand_major || !ad->size_hints) {
+				if(panel->orient == GTK_ORIENTATION_HORIZONTAL)
+					ad->cells = chreq.width;
+				else
+					ad->cells = chreq.height;
 
-			ad->min_cells = ad->cells;
+				ad->min_cells = ad->cells;
+			} else {
+				ad->cells = ad->size_hints [ad->size_hints_len - 1];
+				ad->min_cells = ad->size_hints [ad->size_hints_len - 1];
+			}
 
 			ad->constrained = ad->pos;
 
@@ -1432,7 +1452,7 @@ panel_widget_size_allocate(GtkWidget *wi
 			int cells;
 			
 			if (ad->constrained + ad->min_cells > i)
-				ad->constrained = i - ad->min_cells;
+				ad->constrained = MAX (i - ad->min_cells, 0);
 			
 			if (ad->expand_major) {
 				cells = (i - ad->constrained) - 1;
@@ -1440,6 +1460,7 @@ panel_widget_size_allocate(GtkWidget *wi
 				if (ad->size_hints) 
 					cells = get_size_from_hints (ad, cells);
 				cells = MAX (cells, ad->min_cells);
+				cells = MIN (cells, panel->size);
 
 				ad->cells = cells;
 			}
@@ -1678,6 +1699,10 @@ panel_widget_init (PanelWidget *panel)
 	panel->drop_widget   = widget;
 	panel->open_dialogs  = NULL;
 
+	panel->nb_applets_size_hints = 0;
+	panel->applets_hints = NULL;
+	panel->applets_using_hint = NULL;
+
 	panel_background_init (&panel->background,
 			       (PanelBackgroundChangedNotify) panel_widget_background_changed,
 			       panel);
@@ -2849,8 +2874,13 @@ panel_widget_set_applet_size_hints (Pane
 
 	g_free (ad->size_hints);
 
-	ad->size_hints     = size_hints;
-	ad->size_hints_len = size_hints_len;
+	if (size_hints_len > 0 && (size_hints_len % 2 == 0)) {
+		ad->size_hints     = size_hints;
+		ad->size_hints_len = size_hints_len;
+	} else {
+		g_free (size_hints);
+		ad->size_hints = NULL;
+	}
 
 	gtk_widget_queue_resize (GTK_WIDGET (panel));
 }
Index: panel-widget.h
===================================================================
--- panel-widget.h	(révision 10470)
+++ panel-widget.h	(copie de travail)
@@ -42,6 +42,19 @@ typedef struct _AppletRecord		AppletReco
 typedef struct _AppletData		AppletData;
 typedef struct _DNDRecord		DNDRecord;
 
+typedef struct _AppletSizeHints		AppletSizeHints;
+typedef struct _AppletSizeHintsAlloc	AppletSizeHintsAlloc;
+
+struct _AppletSizeHints {
+	int *hints;
+	int  len;
+};
+
+struct _AppletSizeHintsAlloc {
+	int index;
+	int size;
+};
+
 struct _AppletData
 {
 	GtkWidget *	applet;
@@ -97,6 +110,12 @@ struct _PanelWidget
 	
 	GdkEventKey    *key_event;
 
+	/* helpers to get a good size in packed panels with applets using
+	 * size hints */
+	int                   nb_applets_size_hints;
+	AppletSizeHints      *applets_hints;
+	AppletSizeHintsAlloc *applets_using_hint;
+
 	guint           packed : 1;
 };
 
