diff --git a/applets/notification_area/na-tray.c b/applets/notification_area/na-tray.c
index 4f9bcb4..c00c9ae 100644
--- a/applets/notification_area/na-tray.c
+++ b/applets/notification_area/na-tray.c
@@ -33,7 +33,8 @@
 #include "na-tray.h"
 
 #define ICON_SPACING 1
-#define MIN_BOX_SIZE 3
+#define MIN_TABLE_SIZE 3
+#define MIN_ICON_SIZE 22
 
 typedef struct
 {
@@ -48,7 +49,7 @@ struct _NaTrayPrivate
   GdkScreen   *screen;
   TraysScreen *trays_screen;
 
-  GtkWidget *box;
+  GtkWidget *table;
   GtkWidget *frame;
 
   guint idle_redraw_id;
@@ -117,6 +118,92 @@ get_tray (TraysScreen *trays_screen)
   return trays_screen->all_trays->data;
 }
 
+typedef struct _PackData {
+  GtkOrientation orient;
+  guint n_rows;
+  guint n_cols;
+  guint index;
+} PackData;
+
+static void repack_icon_with_data(GtkWidget *icon,
+                                  NaTray *tray,
+                                  PackData *data)
+{
+  NaTrayPrivate *priv;
+  priv = tray->priv;
+  guint row, col;
+  guint left, right, top, bottom;
+
+  /* row / col number depends on whether we are horizontal or vertical */
+  if (data->orient == GTK_ORIENTATION_HORIZONTAL) {
+    col = data->index / data->n_rows;
+    row = data->index %  data->n_rows;
+  } else {
+    row = data->index / data->n_cols;
+    col = data->index %  data->n_cols;
+  }
+  /* only update icon position if has changed from current */
+  gtk_container_child_get (GTK_CONTAINER (priv->table),
+                           icon,
+                           "left-attach", &left,
+                           "right-attach", &right,
+                           "top-attach", &top,
+                           "bottom-attach", &bottom,
+                           NULL);
+  if (left != col || right != col + 1 ||
+      top != row || bottom != row + 1)
+  {
+    gtk_container_child_set (GTK_CONTAINER (priv->table),
+                             icon,
+                             "left-attach", col,
+                             "right-attach", col + 1,
+                             "top-attach", row,
+                             "bottom-attach", row + 1,
+                             NULL);
+  }
+  /* increment to index of next icon */
+  data->index++;
+}
+
+static void
+repack_icon_table(TraysScreen *trays_screen)
+{
+  NaTray *tray;
+  NaTrayPrivate *priv;
+  guint rows, cols;
+  PackData pack_data;
+
+  tray = get_tray (trays_screen);
+  if (tray == NULL)
+    return;
+
+  priv = tray->priv;
+
+  if (trays_screen->icon_table)
+  {
+    if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) {
+      rows = MAX (1, GTK_WIDGET (tray)->allocation.height / MIN_ICON_SIZE);
+      cols = g_hash_table_size (trays_screen->icon_table) / rows;
+      if (g_hash_table_size (trays_screen->icon_table) % rows || cols == 0)
+        cols++;
+    } else {
+      cols = MAX (1, GTK_WIDGET (tray)->allocation.width / MIN_ICON_SIZE);
+      rows = g_hash_table_size (trays_screen->icon_table) / cols;
+      if (g_hash_table_size (trays_screen->icon_table) % cols || rows == 0)
+        rows++;
+    }
+    gtk_table_resize (GTK_TABLE (priv->table), rows, cols);
+    pack_data.n_rows = rows;
+    pack_data.n_cols = cols;
+    pack_data.orient = priv->orientation;
+    pack_data.index = 0;
+
+    g_hash_table_foreach (trays_screen->icon_table,
+                         (GHFunc)repack_icon_with_data,
+                         &pack_data);
+  }
+}
+
 static void
 tray_added (NaTrayManager *manager,
             GtkWidget     *icon,
@@ -124,6 +211,7 @@ tray_added (NaTrayManager *manager,
 {
   NaTray *tray;
   NaTrayPrivate *priv;
+  guint rows, cols;
 
   tray = get_tray (trays_screen);
   if (tray == NULL)
@@ -135,7 +223,23 @@ tray_added (NaTrayManager *manager,
   
   g_hash_table_insert (trays_screen->icon_table, icon, tray);
 
-  gtk_box_pack_end (GTK_BOX (priv->box), icon, FALSE, FALSE, 0);
+  /* append to table */
+  if (priv->orientation == GTK_ORIENTATION_HORIZONTAL) {
+    rows = MAX (1, GTK_WIDGET (tray)->allocation.height / MIN_ICON_SIZE);
+    cols = g_hash_table_size (trays_screen->icon_table) / rows;
+    if (g_hash_table_size (trays_screen->icon_table) % rows || cols == 0)
+      cols++;
+  } else {
+    cols = MAX (1, GTK_WIDGET (tray)->allocation.width / MIN_ICON_SIZE);
+    rows = g_hash_table_size (trays_screen->icon_table) / cols;
+    if (g_hash_table_size (trays_screen->icon_table) % cols || rows == 0)
+      rows++;
+  }
+  gtk_table_resize (GTK_TABLE (priv->table), rows, cols);
+  gtk_table_attach_defaults (GTK_TABLE (priv->table),
+                             icon,
+                             cols - 1, cols,
+                             rows - 1, rows);
 
   gtk_widget_show (icon);
 }
@@ -146,14 +250,19 @@ tray_removed (NaTrayManager *manager,
               TraysScreen   *trays_screen)
 {
   NaTray *tray;
+  NaTrayPrivate *priv;
 
   tray = g_hash_table_lookup (trays_screen->icon_table, icon);
   if (tray == NULL)
     return;
 
+  priv = tray->priv;
   g_assert (tray->priv->trays_screen == trays_screen);
 
   g_hash_table_remove (trays_screen->icon_table, icon);
+  repack_icon_table (trays_screen);
+  gtk_container_remove (GTK_CONTAINER (priv->table), icon);
+
   /* this will also destroy the tip associated to this icon */
   g_hash_table_remove (trays_screen->tip_table, icon);
 }
@@ -396,8 +505,6 @@ update_size_and_orientation (NaTray *tray)
 {
   NaTrayPrivate *priv = tray->priv;
 
-  gtk_orientable_set_orientation (GTK_ORIENTABLE (priv->box), priv->orientation);
-
   /* This only happens when setting the property during object construction */
   if (!priv->trays_screen)
     return;
@@ -413,13 +520,15 @@ update_size_and_orientation (NaTray *tray)
   switch (priv->orientation)
     {
     case GTK_ORIENTATION_VERTICAL:
-      /* Give box a min size so the frame doesn't look dumb */
-      gtk_widget_set_size_request (priv->box, MIN_BOX_SIZE, -1);
+      /* Give table a min size so the frame doesn't look dumb */
+      gtk_widget_set_size_request (priv->table, MIN_TABLE_SIZE, -1);
       break;
     case GTK_ORIENTATION_HORIZONTAL:
-      gtk_widget_set_size_request (priv->box, -1, MIN_BOX_SIZE);
+      gtk_widget_set_size_request (priv->table, -1, MIN_TABLE_SIZE);
       break;
     }
+
+  repack_icon_table (priv->trays_screen);
 }
 
 /* Children with alpha channels have been set to be composited by calling
@@ -441,15 +550,15 @@ na_tray_expose_icon (GtkWidget *widget,
 }
 
 static void
-na_tray_expose_box (GtkWidget      *box,
+na_tray_expose_table (GtkWidget      *table,
 		    GdkEventExpose *event)
 {
-  cairo_t *cr = gdk_cairo_create (box->window);
+  cairo_t *cr = gdk_cairo_create (table->window);
 
   gdk_cairo_region (cr, event->region);
   cairo_clip (cr);
 
-  gtk_container_foreach (GTK_CONTAINER (box), na_tray_expose_icon, cr);
+  gtk_container_foreach (GTK_CONTAINER (table), na_tray_expose_icon, cr);
 
   cairo_destroy (cr);
 }
@@ -468,12 +577,13 @@ na_tray_init (NaTray *tray)
   gtk_container_add (GTK_CONTAINER (tray), priv->frame);
   gtk_widget_show (priv->frame);
 
-  priv->box = g_object_new (na_box_get_type (), NULL);
-  g_signal_connect (priv->box, "expose-event",
-		    G_CALLBACK (na_tray_expose_box), tray);
-  gtk_box_set_spacing (GTK_BOX (priv->box), ICON_SPACING);
-  gtk_container_add (GTK_CONTAINER (priv->frame), priv->box);
-  gtk_widget_show (priv->box);
+  priv->table = gtk_table_new (0, 0, TRUE);
+  g_signal_connect (priv->table, "expose-event",
+                    G_CALLBACK (na_tray_expose_table), tray);
+  gtk_table_set_row_spacings (GTK_TABLE (priv->table), ICON_SPACING);
+  gtk_table_set_col_spacings (GTK_TABLE (priv->table), ICON_SPACING);
+  gtk_container_add (GTK_CONTAINER (priv->frame), priv->table);
+  gtk_widget_show (priv->table);
 }
 
 static GObject *
@@ -634,7 +744,11 @@ static void
 na_tray_size_allocate (GtkWidget        *widget,
                        GtkAllocation    *allocation)
 {
+  NaTray *tray = NA_TRAY (widget);
+
+  widget->allocation = *allocation;
   gtk_widget_size_allocate (gtk_bin_get_child (GTK_BIN (widget)), allocation);
+  repack_icon_table (tray->priv->trays_screen);
 }
 
 static void
@@ -711,7 +825,7 @@ idle_redraw_cb (NaTray *tray)
 {
   NaTrayPrivate *priv = tray->priv;
 
-  gtk_container_foreach (GTK_CONTAINER (priv->box), (GtkCallback)na_tray_child_force_redraw, tray);
+  gtk_container_foreach (GTK_CONTAINER (priv->table), (GtkCallback)na_tray_child_force_redraw, tray);
   
   priv->idle_redraw_id = 0;
 
