--- /data/zzz/gtk-2.6/gtk+-2.6.10/gtk/gtkcombobox.c	2005-08-18 22:10:57.000000000 +0800
+++ gtk/gtkcombobox.c	2006-06-22 11:24:32.000000000 +0800
@@ -54,6 +54,11 @@
 
 /* WELCOME, to THE house of evil code */
 
+#define HILDON_MENU_COMBO_MAX_WIDTH 406
+#define HILDON_MENU_COMBO_MIN_WIDTH 66
+#define HILDON_MENU_COMBO_MAX_HEIGHT 305
+#define HILDON_MENU_COMBO_MIN_HEIGHT 70
+
 typedef struct _ComboCellInfo ComboCellInfo;
 struct _ComboCellInfo
 {
@@ -1199,6 +1204,8 @@ gtk_combo_box_menu_position_below (GtkMe
   gint monitor_num;
   GdkRectangle monitor;
   
+  g_message ("%s", __FUNCTION__);
+
   /* FIXME: is using the size request here broken? */
    child = GTK_BIN (combo_box)->child;
    
@@ -1240,6 +1247,7 @@ gtk_combo_box_menu_position_below (GtkMe
    *push_in = FALSE;
 }
 
+
 static void
 gtk_combo_box_menu_position_over (GtkMenu  *menu,
 				  gint     *x,
@@ -1247,69 +1255,119 @@ gtk_combo_box_menu_position_over (GtkMen
 				  gboolean *push_in,
 				  gpointer  user_data)
 {
-  GtkComboBox *combo_box;
-  GtkWidget *active;
   GtkWidget *child;
   GtkWidget *widget;
+  GtkWidget *active;
   GtkRequisition requisition;
-  GList *children;
-  gint screen_width;
+  gint screen_width, screen_height;
   gint menu_xpos;
   gint menu_ypos;
-  gint menu_width;
+  gint menu_width, menu_height;
+  gint menu_ypad;
+  gint full_menu_height;
+  gint total_y_padding;
 
   g_return_if_fail (GTK_IS_COMBO_BOX (user_data));
-  
-  combo_box = GTK_COMBO_BOX (user_data);
-  widget = GTK_WIDGET (combo_box);
 
-  gtk_widget_get_child_requisition (GTK_WIDGET (menu), &requisition);
+  widget = GTK_WIDGET (user_data);
+  child = GTK_BIN (user_data)->child;
+
+  /* We need to realize the menu, as we are playing with menu item coordinates
+   * inside. */
+  gtk_widget_realize (GTK_WIDGET (menu));
+
+  gtk_widget_get_child_requisition (menu->toplevel, &requisition);
   menu_width = requisition.width;
+  menu_height = requisition.height;
+
+  gtk_widget_get_child_requisition (GTK_WIDGET (menu), &requisition);
+  full_menu_height = requisition.height;
+
+  screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
+  screen_height = gdk_screen_get_height (gtk_widget_get_screen (widget));
+
+  active = gtk_menu_get_active (menu);
 
-  active = gtk_menu_get_active (GTK_MENU (combo_box->priv->popup_widget));
   gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos);
 
   menu_xpos += widget->allocation.x;
-  menu_ypos += widget->allocation.y + widget->allocation.height / 2 - 2;
+  menu_ypos += widget->allocation.y;
 
-  if (active != NULL)
-    {
-      gtk_widget_get_child_requisition (active, &requisition);
-      menu_ypos -= requisition.height / 2;
-    }
+  /* RTL */
+  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+    menu_xpos = menu_xpos + widget->allocation.width - menu_width;
+
+  /* Substract borders */
+  gtk_widget_style_get (GTK_WIDGET (menu),
+                        "vertical-padding", &menu_ypad,
+                        NULL);
 
-  children = GTK_MENU_SHELL (combo_box->priv->popup_widget)->children;
-  while (children)
+  total_y_padding = menu_ypad + GTK_CONTAINER (menu)->border_width +
+                    GTK_WIDGET (menu)->style->ythickness;
+
+  /* Substract scroll arrow height if needed, and calculate
+   * scroll_offset. */
+  if (full_menu_height > HILDON_MENU_COMBO_MAX_HEIGHT)
     {
-      child = children->data;
+      GList *child;
+      int pos;
 
-      if (active == child)
-	break;
+      child = GTK_MENU_SHELL (menu)->children;
+      pos = 0;
 
-      if (GTK_WIDGET_VISIBLE (child))
-	{
-	  gtk_widget_get_child_requisition (child, &requisition);
-	  menu_ypos -= requisition.height;
-	}
+      while (child)
+        {
+          GtkWidget *child_widget = GTK_WIDGET (child->data);
+
+          if (active == child_widget)
+            break;
 
-      children = children->next;
+          if (GTK_WIDGET_VISIBLE (child))
+            {
+              pos += child_widget->allocation.height;
+
+              if (pos > HILDON_MENU_COMBO_MAX_HEIGHT)
+                menu->scroll_offset += child_widget->allocation.height;
+            }
+
+          child = child->next;
+        }
     }
 
-  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
-    menu_xpos = menu_xpos + widget->allocation.width - menu_width;
+  /* Try to get active item and widget lined up */
+  if (active != NULL)
+    {
+      gint new_menu_ypos;
+
+      new_menu_ypos = menu_ypos - active->allocation.y - total_y_padding +
+                      menu->scroll_offset;
+      if (new_menu_ypos < 0 || (new_menu_ypos + menu_height) > screen_height)
+        {
+          /* Menu doesn't fit - try to get the last item lined up. */          
+          new_menu_ypos = menu_ypos - menu_height + total_y_padding +
+                          active->allocation.height;
+        }
+
+      menu_ypos = new_menu_ypos;
+    }
+  else
+    menu_ypos -= total_y_padding; /* Line up with first item */
 
   /* Clamp the position on screen */
-  screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
-  
   if (menu_xpos < 0)
     menu_xpos = 0;
   else if ((menu_xpos + menu_width) > screen_width)
     menu_xpos -= ((menu_xpos + menu_width) - screen_width);
 
+  if (menu_ypos < 0)
+    menu_ypos = 0;
+  else if ((menu_ypos + menu_height) > screen_height)
+    menu_ypos -= ((menu_ypos + menu_height) - screen_height);
+
   *x = menu_xpos;
   *y = menu_ypos;
 
-  *push_in = TRUE;
+  *push_in = FALSE;
 }
 
 static void
@@ -3481,14 +3539,18 @@ gtk_combo_box_key_press (GtkWidget   *wi
 
   switch (event->keyval) 
     {
+    case GDK_Return:
+    case GDK_KP_Enter:
+          gtk_combo_box_popup (combo_box);
+          return TRUE;
     case GDK_Down:
     case GDK_KP_Down:
-      if (gtk_combo_box_get_active_iter (combo_box, &iter))
-	{
-	  found = tree_next (combo_box, combo_box->priv->model, 
-			     &iter, &new_iter, FALSE);
-	  break;
-	}
+        if (!gtk_widget_keynav_failed (GTK_WIDGET(combo_box), GTK_DIR_RIGHT))
+        {
+	  found = FALSE;
+	  gtk_widget_child_focus (gtk_widget_get_toplevel (GTK_WIDGET(combo_box)), GTK_DIR_TAB_FORWARD);
+        }		
+        break;
       /* else fall through */
     case GDK_Page_Up:
     case GDK_KP_Page_Up:
@@ -3496,22 +3558,21 @@ gtk_combo_box_key_press (GtkWidget   *wi
     case GDK_KP_Home:
       found = tree_first (combo_box, combo_box->priv->model, &new_iter, FALSE);
       break;
-
     case GDK_Up:
     case GDK_KP_Up:
-      if (gtk_combo_box_get_active_iter (combo_box, &iter))
-	{
-	  found = tree_prev (combo_box, combo_box->priv->model, 
-			     &iter, &new_iter, FALSE);
-	  break;
-	}
+        if (!gtk_widget_keynav_failed (GTK_WIDGET(combo_box), GTK_DIR_LEFT))
+        {
+	  found = FALSE;
+	  gtk_widget_child_focus (gtk_widget_get_toplevel (GTK_WIDGET(combo_box)), GTK_DIR_TAB_BACKWARD);
+        }		
+        break;
       /* else fall through */      
     case GDK_Page_Down:
     case GDK_KP_Page_Down:
     case GDK_End: 
     case GDK_KP_End:
       found = tree_last (combo_box, combo_box->priv->model, &new_iter, FALSE);
-      break;
+      break;    
     default:
       return FALSE;
     }