Index: search/Beagle.Search/Category.cs
===================================================================
--- search/Beagle.Search/Category.cs.orig	2008-02-10 13:24:20.000000000 -0700
+++ search/Beagle.Search/Category.cs	2011-07-01 11:34:23.781000149 -0600
@@ -18,17 +18,14 @@ namespace Beagle.Search {
 
 	public abstract class Category : Container {
 
-		private SortedTileList tiles = null;
-		private int page = 0;
-
 		protected Gtk.HBox header;
+		private SortedTileList tiles;
 		private Gtk.Label position;
 		private Gtk.Button prev, next;
 		private Gtk.Expander headerExpander;
-		private int fewRows, manyRows, columns;
-		private int few, many;
 		private bool extended, expanded;
 		private ScopeType scope;
+		private int columns, tileIndex, tileHeight;
 
 		public Category (Tiles.TileGroupInfo info, int columns)
 		{
@@ -60,14 +57,9 @@ namespace Beagle.Search {
 			header.SizeRequested += HeaderSizeRequested;
 
 			tiles = new SortedTileList (Beagle.Search.SortType.Relevance);
-			page = 0;
-
-			fewRows = info.Rows;
-			manyRows = info.Rows * 2;
 			Columns = columns;
 
 			UpdateButtons ();
-			//headerExpander.Expanded = true;
 			Expanded = true;	
 		}
 
@@ -91,7 +83,7 @@ namespace Beagle.Search {
 				expanded = value;
 
 				if (expanded)
-					ShowTiles (false);
+					ShowTiles ();
 				else
 					HideTiles ();
 
@@ -103,12 +95,10 @@ namespace Beagle.Search {
 			get { return columns; }
 			set {
 				HideTiles ();
-
 				columns = value;
-				few = fewRows * columns;
-				many = manyRows * columns;
 
-				ShowTiles (true);
+				if (Expanded)
+					ShowTiles ();
 			}
 		}
 
@@ -127,14 +117,9 @@ namespace Beagle.Search {
 			args.Requisition = req;
 		}
 
-		void UpdateButtons ()
+		private void UpdateButtons ()
 		{
-			if (tiles.Count <= FirstVisible && page > 0) {
-				// The page we were viewing disappeared
-				page--;
-			}
-
-			prev.Sensitive = (page != 0);
+			prev.Sensitive = tileIndex != 0;
 			next.Sensitive = (tiles.Count > LastVisible + 1);
 
 			if (tiles.Count > 0) {
@@ -156,7 +141,7 @@ namespace Beagle.Search {
 			tiles.Add ((Tiles.Tile)widget);
 
 			if (Expanded)
-				ShowTiles (true);
+				ShowTiles ();
 		}
 
 		protected override void OnRemoved (Gtk.Widget widget)
@@ -168,41 +153,31 @@ namespace Beagle.Search {
 			tiles.Remove ((Tiles.Tile)widget);
 
 			if (Expanded)
-				ShowTiles (true);
+				ShowTiles ();
 		}
 
 		private Tiles.Tile lastTarget;
 		private bool hadFocus;
 
-		void HideTiles ()
+		private void HideTiles ()
 		{
 			lastTarget = null;
-			foreach (Tiles.Tile tile in VisibleTiles) {
+			foreach (Tiles.Tile tile in AllTiles) {
 				if (tile.HasFocus || lastTarget == null) {
 					lastTarget = tile;
 					hadFocus = tile.HasFocus;
 				}
 				tile.ChildVisible = false;
 			}
+
 			QueueResize ();
 		}
 
-		void ShowTiles (bool recenter)
+		private void ShowTiles ()
 		{
-			if (recenter && lastTarget != null) {
-				int index = tiles.IndexOf (lastTarget);
-				if (hadFocus || page > 0) {
-					if (index < few)
-						page = 0;
-					else if (extended)
-						page = index / (manyRows * columns);
-					else
-						page = ((index - few) / (manyRows * columns)) + 1;
-				}
-			}
-
 			foreach (Tiles.Tile tile in VisibleTiles) {
 				tile.ChildVisible = true;
+
 				if (tile == lastTarget && hadFocus && !tile.HasFocus)
 					tile.GrabFocus ();
 			}
@@ -211,33 +186,26 @@ namespace Beagle.Search {
 			QueueResize ();
 		}
 
-		private bool showingMany {
-			get {
-				// Show extra tiles on every page after the first, unless
-				// there are only two pages and the second one only has
-				// enough tiles to fit the "fewer" size.
-				return (page > 0 && tiles.Count > 2 * few) || extended;
-			}
-		}
-
-		void OnPrev (object obj, EventArgs args)
+		private void OnPrev (object obj, EventArgs args)
 		{
 			HideTiles ();
-			page--;
+			tileIndex = Math.Max (0, tileIndex - PageSize);
+			
 			if (!Expanded)
 				OnActivated (obj, args);
 			else
-				ShowTiles (false);
+				ShowTiles ();
 		}
 
-		void OnNext (object obj, EventArgs args)
+		private void OnNext (object obj, EventArgs args)
 		{
 			HideTiles ();
-			page++;
+			tileIndex = Math.Min (tiles.Count - 1, tileIndex + PageSize);
+			
 			if (!Expanded)
 				OnActivated (obj, args);
 			else
-				ShowTiles (false);
+				ShowTiles ();
 		}
 
 		protected void OnActivated (object obj, EventArgs args)
@@ -246,27 +214,56 @@ namespace Beagle.Search {
 			CategoryToggle (scope);
 		}
 
+		public void SetMaxDisplayHeight (int height)
+		{
+			if (tileHeight != height) {
+				tileHeight = height;
+				HideTiles ();
+
+				if (Expanded)
+					ShowTiles ();
+			}
+		}
+
+		public int GetPotentialDisplayHeight ()
+		{
+			if (tiles.Count == 0)
+				return 0;
+
+			Requisition headerReq = header.SizeRequest ();
+			Requisition tileReq = tiles[0].SizeRequest ();
+			return headerReq.Height + (tiles.Count / Columns) * tileReq.Height;
+		}
+		
 		public delegate void CategoryToggleDelegate (ScopeType scope);
 		public event CategoryToggleDelegate CategoryToggle;
 
 		protected int PageSize {
 			get {
-				return Math.Min (showingMany ? many : few, tiles.Count);
+				if (tiles.Count == 0)
+					return 0;
+
+				if (tileHeight == 0)
+					return Math.Min (2 * Columns, tiles.Count);
+
+				Requisition sizeReq = tiles[0].SizeRequest ();
+				int ps = Math.Min (tileHeight / sizeReq.Height * Columns, tiles.Count);
+				
+				// Display at least two rows if we have the hits for it.
+				if (ps < 2 * Columns)
+					ps = Math.Min (2 * Columns, tiles.Count);
+                
+				return ps;
 			}
 		}
 
-		protected int FirstVisible {
+		private int FirstVisible {
 			get {
-				if (page == 0)
-					return 0;
-				else if (extended)
-					return page * many;
-				else
-					return few + (page - 1) * many;
+				return tileIndex;
 			}
 		}
 
-		protected int LastVisible {
+		private int LastVisible {
 			get {
 				return Math.Min (FirstVisible + PageSize, tiles.Count) - 1;
 			}
@@ -337,7 +334,7 @@ namespace Beagle.Search {
 			set {
 				HideTiles ();
 				tiles.SortType = value;
-				ShowTiles (true);
+				ShowTiles ();
 			}
 		}
 
@@ -346,7 +343,7 @@ namespace Beagle.Search {
 			if (extended) {
 				HideTiles ();
 				this.extended = extended;
-				ShowTiles (false);
+				ShowTiles ();
 			}
 			if (focus && !Empty)
 				((Gtk.Widget)VisibleTiles[0]).GrabFocus ();
Index: search/Beagle.Search/GroupView.cs
===================================================================
--- search/Beagle.Search/GroupView.cs.orig	2008-04-25 10:46:12.000000000 -0600
+++ search/Beagle.Search/GroupView.cs	2011-07-01 11:34:23.781000149 -0600
@@ -25,6 +25,9 @@ namespace Beagle.Search {
 		private Gtk.SizeGroup tileSizeGroup;
 		private Gtk.Widget selection;
 
+		private int[] maxHeight;
+		private int[] displayHeight;
+
 		public event CategoryToggledDelegate CategoryToggled;
 		public event TileHandler TileSelected;
 
@@ -47,8 +50,68 @@ namespace Beagle.Search {
 
 				categories [info.Group] = box;
 			}
+
+			maxHeight = new int[Children.Length];
+			displayHeight = new int[Children.Length];
 		}
 		
+        public void AdjustCategories (int height)
+        {
+			Category last = null;
+			int visible = 0, totalHeight = height, childLen = Children.Length;
+			ulong mask = ~0UL;
+
+			for (int i = 0; i < childLen; i++) {
+				displayHeight[i] = maxHeight[i] = 0;
+				Category c = (Category) Children[i];
+				if (!c.Expanded || c.Count == 0) {
+					mask ^= 1UL << i;
+					continue;
+				}
+                
+				last = c;
+				visible++;
+				maxHeight[i] = c.GetPotentialDisplayHeight ();
+			}
+
+			if (visible == 0) {
+				return;
+			} else if (visible == 1) {
+				last.SetMaxDisplayHeight (height);
+				return;
+			}
+
+			// Split the available height among the visible categories
+			for (int active = visible; active > 0 && totalHeight > active;) {
+				int avg_height = totalHeight / active;
+
+				for (int i = 0; i < childLen; i++) {
+					if ((mask & 1UL << i) == 0)
+						continue;
+
+					int diff = maxHeight[i] - displayHeight[i];
+					if (diff <= avg_height) {
+						displayHeight[i] += diff;
+						totalHeight -= diff;
+						mask ^= 1UL << i;
+					} else {
+						displayHeight[i] += avg_height;
+						totalHeight -= avg_height;
+					}
+				}
+
+				for (int j = active = 0; j < childLen; j++)
+					if ((mask & 1UL << j) != 0)
+						active++;
+			}
+
+			// Tell each category how much height it has to work with
+			for (int i = 0; i < childLen; i++) {
+				Category c = (Category) Children[i];
+				c.SetMaxDisplayHeight (displayHeight[i]);
+			}
+		}
+
 		public void AddHit (Tile tile)
 		{
 			tile.Show ();
Index: search/Beagle.Search/Panes.cs
===================================================================
--- search/Beagle.Search/Panes.cs.orig	2008-02-10 13:24:20.000000000 -0700
+++ search/Beagle.Search/Panes.cs	2011-07-01 11:34:23.788000149 -0600
@@ -92,6 +92,10 @@ namespace Beagle.Search {
 				Gtk.Widget focusChild = mainChild.FocusChild;
 				mainChild.FocusChild = null;
 				mainChild.FocusChild = focusChild;
+
+				GroupView gv = mainChild as GroupView;
+				if (gv != null)
+					gv.AdjustCategories (args.Allocation.Height);
 			}
 		}
 
