]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcombobox.c
Deprecate widget flag: GTK_WIDGET_MAPPED
[~andy/gtk] / gtk / gtkcombobox.c
index a338257716ac937d2b4cde67e083fd8682985729..22416981e2be7fd5f43a5e52b81031b05fe1ec79 100644 (file)
@@ -81,6 +81,7 @@ struct _GtkComboBoxPrivate
   gint wrap_width;
   GtkShadowType shadow_type;
 
+  gint active; /* Only temporary */
   GtkTreeRowReference *active_row;
 
   GtkWidget *tree_view;
@@ -203,7 +204,8 @@ enum {
   PROP_HAS_FRAME,
   PROP_FOCUS_ON_CLICK,
   PROP_POPUP_SHOWN,
-  PROP_BUTTON_SENSITIVITY
+  PROP_BUTTON_SENSITIVITY,
+  PROP_EDITING_CANCELED
 };
 
 static guint combo_box_signals[LAST_SIGNAL] = {0,};
@@ -378,6 +380,8 @@ static gboolean gtk_combo_box_menu_button_press    (GtkWidget        *widget,
                                                     gpointer          user_data);
 static void     gtk_combo_box_menu_item_activate   (GtkWidget        *item,
                                                     gpointer          user_data);
+
+static void     gtk_combo_box_update_sensitivity   (GtkComboBox      *combo_box);
 static void     gtk_combo_box_menu_row_inserted    (GtkTreeModel     *model,
                                                     GtkTreePath      *path,
                                                     GtkTreeIter      *iter,
@@ -646,6 +650,10 @@ gtk_combo_box_class_init (GtkComboBoxClass *klass)
                                GTK_TYPE_SCROLL_TYPE, GTK_SCROLL_END);
 
   /* properties */
+  g_object_class_override_property (object_class,
+                                    PROP_EDITING_CANCELED,
+                                    "editing-canceled");
+
   /**
    * GtkComboBox:model:
    *
@@ -928,6 +936,7 @@ gtk_combo_box_init (GtkComboBox *combo_box)
   priv->height = 0;
   priv->wrap_width = 0;
 
+  priv->active = -1;
   priv->active_row = NULL;
   priv->col_column = -1;
   priv->row_column = -1;
@@ -956,58 +965,62 @@ gtk_combo_box_set_property (GObject      *object,
 
   switch (prop_id)
     {
-      case PROP_MODEL:
-        gtk_combo_box_set_model (combo_box, g_value_get_object (value));
-        break;
+    case PROP_MODEL:
+      gtk_combo_box_set_model (combo_box, g_value_get_object (value));
+      break;
 
-      case PROP_WRAP_WIDTH:
-        gtk_combo_box_set_wrap_width (combo_box, g_value_get_int (value));
-        break;
+    case PROP_WRAP_WIDTH:
+      gtk_combo_box_set_wrap_width (combo_box, g_value_get_int (value));
+      break;
 
-      case PROP_ROW_SPAN_COLUMN:
-        gtk_combo_box_set_row_span_column (combo_box, g_value_get_int (value));
-        break;
+    case PROP_ROW_SPAN_COLUMN:
+      gtk_combo_box_set_row_span_column (combo_box, g_value_get_int (value));
+      break;
 
-      case PROP_COLUMN_SPAN_COLUMN:
-        gtk_combo_box_set_column_span_column (combo_box, g_value_get_int (value));
-        break;
+    case PROP_COLUMN_SPAN_COLUMN:
+      gtk_combo_box_set_column_span_column (combo_box, g_value_get_int (value));
+      break;
 
-      case PROP_ACTIVE:
-        gtk_combo_box_set_active (combo_box, g_value_get_int (value));
-        break;
+    case PROP_ACTIVE:
+      gtk_combo_box_set_active (combo_box, g_value_get_int (value));
+      break;
 
-      case PROP_ADD_TEAROFFS:
-        gtk_combo_box_set_add_tearoffs (combo_box, g_value_get_boolean (value));
-        break;
+    case PROP_ADD_TEAROFFS:
+      gtk_combo_box_set_add_tearoffs (combo_box, g_value_get_boolean (value));
+      break;
 
-      case PROP_HAS_FRAME:
-        combo_box->priv->has_frame = g_value_get_boolean (value);
-        break;
+    case PROP_HAS_FRAME:
+      combo_box->priv->has_frame = g_value_get_boolean (value);
+      break;
 
-      case PROP_FOCUS_ON_CLICK:
-       gtk_combo_box_set_focus_on_click (combo_box, 
-                                         g_value_get_boolean (value));
-        break;
+    case PROP_FOCUS_ON_CLICK:
+      gtk_combo_box_set_focus_on_click (combo_box,
+                                        g_value_get_boolean (value));
+      break;
 
-      case PROP_TEAROFF_TITLE:
-       gtk_combo_box_set_title (combo_box, g_value_get_string (value));
-        break;
+    case PROP_TEAROFF_TITLE:
+      gtk_combo_box_set_title (combo_box, g_value_get_string (value));
+      break;
 
-      case PROP_POPUP_SHOWN:
-        if (g_value_get_boolean (value))
-          gtk_combo_box_popup (combo_box);
-        else
-          gtk_combo_box_popdown (combo_box);
-        break;
+    case PROP_POPUP_SHOWN:
+      if (g_value_get_boolean (value))
+        gtk_combo_box_popup (combo_box);
+      else
+        gtk_combo_box_popdown (combo_box);
+      break;
 
-      case PROP_BUTTON_SENSITIVITY:
-        gtk_combo_box_set_button_sensitivity (combo_box,
-                                              g_value_get_enum (value));
-        break;
+    case PROP_BUTTON_SENSITIVITY:
+      gtk_combo_box_set_button_sensitivity (combo_box,
+                                            g_value_get_enum (value));
+      break;
 
-      default:
-        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-        break;
+    case PROP_EDITING_CANCELED:
+      combo_box->priv->editing_canceled = g_value_get_boolean (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
     }
 }
 
@@ -1018,6 +1031,7 @@ gtk_combo_box_get_property (GObject    *object,
                             GParamSpec *pspec)
 {
   GtkComboBox *combo_box = GTK_COMBO_BOX (object);
+  GtkComboBoxPrivate *priv = GTK_COMBO_BOX_GET_PRIVATE (combo_box);
 
   switch (prop_id)
     {
@@ -1065,6 +1079,10 @@ gtk_combo_box_get_property (GObject    *object,
         g_value_set_enum (value, combo_box->priv->button_sensitivity);
         break;
 
+      case PROP_EDITING_CANCELED:
+        g_value_set_boolean (value, priv->editing_canceled);
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -1102,7 +1120,7 @@ gtk_combo_box_button_state_changed (GtkWidget    *widget,
        {
          if ((GTK_WIDGET_STATE (widget) == GTK_STATE_INSENSITIVE) !=
              (GTK_WIDGET_STATE (priv->cell_view) == GTK_STATE_INSENSITIVE))
-           gtk_widget_set_sensitive (priv->cell_view, GTK_WIDGET_SENSITIVE (widget));
+           gtk_widget_set_sensitive (priv->cell_view, gtk_widget_get_sensitive (widget));
          
          gtk_widget_set_state (priv->cell_view, 
                                GTK_WIDGET_STATE (widget));
@@ -1468,15 +1486,17 @@ gtk_combo_box_menu_position_below (GtkMenu  *menu,
   
   /* FIXME: is using the size request here broken? */
   child = GTK_BIN (combo_box)->child;
-   
-  gdk_window_get_origin (child->window, &sx, &sy);
-   
-  if (GTK_WIDGET_NO_WINDOW (child))
+
+  sx = sy = 0;
+
+  if (!gtk_widget_get_has_window (child))
     {
       sx += child->allocation.x;
       sy += child->allocation.y;
     }
 
+  gdk_window_get_root_coords (child->window, sx, sy, &sx, &sy);
+
   if (GTK_SHADOW_NONE != combo_box->priv->shadow_type)
     sx -= GTK_WIDGET (combo_box)->style->xthickness;
 
@@ -1535,10 +1555,9 @@ gtk_combo_box_menu_position_over (GtkMenu  *menu,
   menu_width = requisition.width;
 
   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_xpos = widget->allocation.x;
+  menu_ypos = widget->allocation.y + widget->allocation.height / 2 - 2;
 
   if (active != NULL)
     {
@@ -1554,7 +1573,7 @@ gtk_combo_box_menu_position_over (GtkMenu  *menu,
       if (active == child)
        break;
 
-      if (GTK_WIDGET_VISIBLE (child))
+      if (gtk_widget_get_visible (child))
        {
          gtk_widget_get_child_requisition (child, &requisition);
          menu_ypos -= requisition.height;
@@ -1566,6 +1585,9 @@ gtk_combo_box_menu_position_over (GtkMenu  *menu,
   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
     menu_xpos = menu_xpos + widget->allocation.width - menu_width;
 
+  gdk_window_get_root_coords (widget->window, menu_xpos, menu_ypos,
+                             &menu_xpos, &menu_ypos);
+
   /* Clamp the position on screen */
   screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
   
@@ -1605,8 +1627,9 @@ gtk_combo_box_menu_position (GtkMenu  *menu,
       gtk_combo_box_menu_position_over (menu, x, y, push_in, user_data);
     }
 
-  gtk_window_set_type_hint (GTK_WINDOW (GTK_MENU (priv->popup_widget)->toplevel),
-                            GDK_WINDOW_TYPE_HINT_COMBO);
+  if (!gtk_widget_get_visible (GTK_MENU (priv->popup_widget)->toplevel))
+    gtk_window_set_type_hint (GTK_WINDOW (GTK_MENU (priv->popup_widget)->toplevel),
+                              GDK_WINDOW_TYPE_HINT_COMBO);
 }
 
 static void
@@ -1627,14 +1650,16 @@ gtk_combo_box_list_position (GtkComboBox *combo_box,
      see bug #340204 */
   GtkWidget *sample = GTK_WIDGET (combo_box);
 
-  gdk_window_get_origin (sample->window, x, y);
+  *x = *y = 0;
 
-  if (GTK_WIDGET_NO_WINDOW (sample))
+  if (!gtk_widget_get_has_window (sample))
     {
       *x += sample->allocation.x;
       *y += sample->allocation.y;
     }
   
+  gdk_window_get_root_coords (sample->window, *x, *y, x, y);
+
   *width = sample->allocation.width;
 
   hpolicy = vpolicy = GTK_POLICY_NEVER;
@@ -1692,7 +1717,7 @@ cell_view_is_sensitive (GtkCellView *cell_view)
   GList *cells, *list;
   gboolean sensitive;
   
-  cells = gtk_cell_view_get_cell_renderers (cell_view);
+  cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (cell_view));
 
   sensitive = FALSE;
   for (list = cells; list; list = list->next)
@@ -1720,8 +1745,8 @@ tree_column_row_is_sensitive (GtkComboBox *combo_box,
 
   if (priv->row_separator_func)
     {
-      if ((*priv->row_separator_func) (priv->model, iter,
-                                      priv->row_separator_data))
+      if (priv->row_separator_func (priv->model, iter,
+                                    priv->row_separator_data))
        return FALSE;
     }
 
@@ -1729,7 +1754,7 @@ tree_column_row_is_sensitive (GtkComboBox *combo_box,
                                           priv->model,
                                           iter, FALSE, FALSE);
 
-  cells = gtk_tree_view_column_get_cell_renderers (priv->column);
+  cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->column));
 
   sensitive = FALSE;
   for (list = cells; list; list = list->next)
@@ -1889,7 +1914,7 @@ gtk_combo_box_real_popup (GtkComboBox *combo_box)
   if (!GTK_WIDGET_REALIZED (combo_box))
     return;
 
-  if (GTK_WIDGET_MAPPED (priv->popup_widget))
+  if (gtk_widget_get_mapped (priv->popup_widget))
     return;
 
   if (GTK_IS_MENU (priv->popup_widget))
@@ -1937,7 +1962,7 @@ gtk_combo_box_real_popup (GtkComboBox *combo_box)
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->button),
                                 TRUE);
 
-  if (!GTK_WIDGET_HAS_FOCUS (priv->tree_view))
+  if (!gtk_widget_has_focus (priv->tree_view))
     gtk_widget_grab_focus (priv->tree_view);
 
   if (!popup_grab_on_window (priv->popup_window->window,
@@ -2293,6 +2318,23 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
               child.width -= child.x;
             }
 
+          if (gtk_widget_get_visible (priv->popup_widget))
+            {
+              gint width;
+              GtkRequisition requisition;
+
+              /* Warning here, without the check in the position func */
+              gtk_menu_reposition (GTK_MENU (priv->popup_widget));
+              if (priv->wrap_width == 0)
+                {
+                  width = GTK_WIDGET (combo_box)->allocation.width;
+                  gtk_widget_set_size_request (priv->popup_widget, -1, -1);
+                  gtk_widget_size_request (priv->popup_widget, &requisition);
+                  gtk_widget_set_size_request (priv->popup_widget,
+                    MAX (width, requisition.width), -1);
+               }
+            }
+
          child.width = MAX (1, child.width);
          child.height = MAX (1, child.height);
           gtk_widget_size_allocate (GTK_BIN (widget)->child, &child);
@@ -2362,6 +2404,15 @@ gtk_combo_box_size_allocate (GtkWidget     *widget,
           child.width -= delta_x * 2;
           child.height -= delta_y * 2;
         }
+
+      if (gtk_widget_get_visible (priv->popup_window))
+        {
+          gint x, y, width, height;
+          gtk_combo_box_list_position (combo_box, &x, &y, &width, &height);
+          gtk_window_move (GTK_WINDOW (priv->popup_window), x, y);
+          gtk_widget_set_size_request (priv->popup_window, width, height);
+        }
+
       
       child.width = MAX (1, child.width);
       child.height = MAX (1, child.height);
@@ -2461,7 +2512,7 @@ gtk_combo_box_expose_event (GtkWidget      *widget,
   GtkComboBox *combo_box = GTK_COMBO_BOX (widget);
   GtkComboBoxPrivate *priv = combo_box->priv;
 
-  if (GTK_WIDGET_DRAWABLE (widget) &&
+  if (gtk_widget_is_drawable (widget) &&
       GTK_SHADOW_NONE != priv->shadow_type)
     {
       gtk_paint_shadow (widget->style, widget->window,
@@ -2801,18 +2852,19 @@ gtk_combo_box_menu_setup (GtkComboBox *combo_box,
       gtk_widget_show_all (priv->button);
     }
 
-  g_signal_connect (priv->button, "button_press_event",
+  g_signal_connect (priv->button, "button-press-event",
                     G_CALLBACK (gtk_combo_box_menu_button_press),
                     combo_box);
-  g_signal_connect (priv->button, "state_changed",
+  g_signal_connect (priv->button, "state-changed",
                    G_CALLBACK (gtk_combo_box_button_state_changed), 
                    combo_box);
 
   /* create our funky menu */
   menu = gtk_menu_new ();
   gtk_widget_set_name (menu, "gtk-combobox-popup-menu");
+  gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE);
   
-  g_signal_connect (menu, "key_press_event",
+  g_signal_connect (menu, "key-press-event",
                    G_CALLBACK (gtk_combo_box_menu_key_press), combo_box);
   gtk_combo_box_set_popup_widget (combo_box, menu);
 
@@ -2826,6 +2878,7 @@ gtk_combo_box_menu_setup (GtkComboBox *combo_box,
   gtk_combo_box_sync_cells (combo_box, GTK_CELL_LAYOUT (priv->column));
 
   gtk_combo_box_update_title (combo_box);
+  gtk_combo_box_update_sensitivity (combo_box);
 }
 
 static void
@@ -2902,8 +2955,8 @@ gtk_combo_box_menu_fill_level (GtkComboBox *combo_box,
       gtk_tree_model_iter_nth_child (model, &iter, parent, i);
 
       if (priv->row_separator_func)
-       is_separator = (*priv->row_separator_func) (priv->model, &iter,
-                                                   priv->row_separator_data);
+       is_separator = priv->row_separator_func (priv->model, &iter,
+                                                 priv->row_separator_data);
       else
        is_separator = FALSE;
       
@@ -2923,6 +2976,7 @@ gtk_combo_box_menu_fill_level (GtkComboBox *combo_box,
          if (gtk_tree_model_iter_has_child (model, &iter))
            {
              submenu = gtk_menu_new ();
+              gtk_menu_set_reserve_toggle_size (GTK_MENU (submenu), FALSE);
              gtk_widget_show (submenu);
              gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), submenu);
              
@@ -3114,7 +3168,7 @@ gtk_combo_box_menu_button_press (GtkWidget      *widget,
       event->type == GDK_BUTTON_PRESS && event->button == 1)
     {
       if (priv->focus_on_click && 
-         !GTK_WIDGET_HAS_FOCUS (priv->button))
+         !gtk_widget_has_focus (priv->button))
        gtk_widget_grab_focus (priv->button);
 
       gtk_combo_box_menu_popup (combo_box, event->button, event->time);
@@ -3148,7 +3202,9 @@ gtk_combo_box_menu_item_activate (GtkWidget *item,
 
   gtk_tree_path_free (path);
 
-  combo_box->priv->editing_canceled = FALSE;
+  g_object_set (combo_box,
+                "editing-canceled", FALSE,
+                NULL);
 }
 
 static void
@@ -3178,6 +3234,11 @@ gtk_combo_box_update_sensitivity (GtkComboBox *combo_box)
     }
 
   gtk_widget_set_sensitive (combo_box->priv->button, sensitive);
+
+  /* In list-mode, we also need to update sensitivity of the event box */
+  if (GTK_IS_TREE_VIEW (combo_box->priv->tree_view)
+      && combo_box->priv->cell_view)
+    gtk_widget_set_sensitive (combo_box->priv->box, sensitive);
 }
 
 static void
@@ -3267,7 +3328,7 @@ list_popup_resize_idle (gpointer user_data)
   GtkComboBoxPrivate *priv = combo_box->priv;
   gint x, y, width, height;
 
-  if (priv->tree_view && GTK_WIDGET_MAPPED (priv->popup_window))
+  if (priv->tree_view && gtk_widget_get_mapped (priv->popup_window))
     {
       gtk_combo_box_list_position (combo_box, &x, &y, &width, &height);
   
@@ -3433,6 +3494,7 @@ gtk_combo_box_menu_row_inserted (GtkTreeModel *model,
       if (!menu)
        {
          menu = gtk_menu_new ();
+          gtk_menu_set_reserve_toggle_size (GTK_MENU (menu), FALSE);
          gtk_widget_show (menu);
          gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), menu);
          
@@ -3463,8 +3525,8 @@ gtk_combo_box_menu_row_inserted (GtkTreeModel *model,
     }
   
   if (priv->row_separator_func)
-    is_separator = (*priv->row_separator_func) (model, iter,
-                                               priv->row_separator_data);
+    is_separator = priv->row_separator_func (model, iter,
+                                             priv->row_separator_data);
   else
     is_separator = FALSE;
 
@@ -3555,8 +3617,8 @@ gtk_combo_box_menu_row_changed (GtkTreeModel *model,
   item = find_menu_by_path (priv->popup_widget, path, FALSE);
 
   if (priv->row_separator_func)
-    is_separator = (*priv->row_separator_func) (model, iter,
-                                               priv->row_separator_data);
+    is_separator = priv->row_separator_func (model, iter,
+                                             priv->row_separator_data);
   else
     is_separator = FALSE;
 
@@ -3617,7 +3679,7 @@ gtk_combo_box_list_setup (GtkComboBox *combo_box)
   priv->button = gtk_toggle_button_new ();
   gtk_widget_set_parent (priv->button,
                          GTK_BIN (combo_box)->child->parent);
-  g_signal_connect (priv->button, "button_press_event",
+  g_signal_connect (priv->button, "button-press-event",
                     G_CALLBACK (gtk_combo_box_list_button_pressed), combo_box);
   g_signal_connect (priv->button, "toggled",
                     G_CALLBACK (gtk_combo_box_button_toggled), combo_box);
@@ -3654,7 +3716,7 @@ gtk_combo_box_list_setup (GtkComboBox *combo_box)
       gtk_container_add (GTK_CONTAINER (priv->cell_view_frame), priv->box);
       gtk_widget_show_all (priv->cell_view_frame);
 
-      g_signal_connect (priv->box, "button_press_event",
+      g_signal_connect (priv->box, "button-press-event",
                        G_CALLBACK (gtk_combo_box_list_button_pressed), 
                        combo_box);
     }
@@ -3697,26 +3759,28 @@ gtk_combo_box_list_setup (GtkComboBox *combo_box)
   /* set sample/popup widgets */
   gtk_combo_box_set_popup_widget (combo_box, priv->tree_view);
 
-  g_signal_connect (priv->tree_view, "key_press_event",
+  g_signal_connect (priv->tree_view, "key-press-event",
                     G_CALLBACK (gtk_combo_box_list_key_press),
                     combo_box);
-  g_signal_connect (priv->tree_view, "enter_notify_event",
+  g_signal_connect (priv->tree_view, "enter-notify-event",
                     G_CALLBACK (gtk_combo_box_list_enter_notify),
                     combo_box);
-  g_signal_connect (priv->tree_view, "row_expanded",
+  g_signal_connect (priv->tree_view, "row-expanded",
                    G_CALLBACK (gtk_combo_box_model_row_expanded),
                    combo_box);
-  g_signal_connect (priv->tree_view, "row_collapsed",
+  g_signal_connect (priv->tree_view, "row-collapsed",
                    G_CALLBACK (gtk_combo_box_model_row_expanded),
                    combo_box);
-  g_signal_connect (priv->popup_window, "button_press_event",
+  g_signal_connect (priv->popup_window, "button-press-event",
                     G_CALLBACK (gtk_combo_box_list_button_pressed),
                     combo_box);
-  g_signal_connect (priv->popup_window, "button_release_event",
+  g_signal_connect (priv->popup_window, "button-release-event",
                     G_CALLBACK (gtk_combo_box_list_button_released),
                     combo_box);
 
   gtk_widget_show (priv->tree_view);
+
+  gtk_combo_box_update_sensitivity (combo_box);
 }
 
 static void
@@ -3826,7 +3890,7 @@ gtk_combo_box_list_button_pressed (GtkWidget      *widget,
     return FALSE;
 
   if (priv->focus_on_click && 
-      !GTK_WIDGET_HAS_FOCUS (priv->button))
+      !gtk_widget_has_focus (priv->button))
     gtk_widget_grab_focus (priv->button);
 
   gtk_combo_box_popup (combo_box);
@@ -3989,13 +4053,13 @@ gtk_combo_box_list_auto_scroll (GtkComboBox *combo_box,
          adj->lower < adj->value)
        {
          value = adj->value - (tree_view->allocation.x - x + 1);
-         gtk_adjustment_set_value (adj, value);
+         gtk_adjustment_set_value (adj, CLAMP (value, adj->lower, adj->upper - adj->page_size));
        }
       else if (x >= tree_view->allocation.x + tree_view->allocation.width &&
               adj->upper - adj->page_size > adj->value)
        {
          value = adj->value + (x - tree_view->allocation.x - tree_view->allocation.width + 1);
-         gtk_adjustment_set_value (adj, MAX (value, 0.0));
+         gtk_adjustment_set_value (adj, CLAMP (value, 0.0, adj->upper - adj->page_size));
        }
     }
 
@@ -4006,13 +4070,13 @@ gtk_combo_box_list_auto_scroll (GtkComboBox *combo_box,
          adj->lower < adj->value)
        {
          value = adj->value - (tree_view->allocation.y - y + 1);
-         gtk_adjustment_set_value (adj, value);
+         gtk_adjustment_set_value (adj, CLAMP (value, adj->lower, adj->upper - adj->page_size));
        }
       else if (y >= tree_view->allocation.height &&
               adj->upper - adj->page_size > adj->value)
        {
          value = adj->value + (y - tree_view->allocation.height + 1);
-         gtk_adjustment_set_value (adj, MAX (value, 0.0));
+         gtk_adjustment_set_value (adj, CLAMP (value, 0.0, adj->upper - adj->page_size));
        }
     }
 }
@@ -4068,7 +4132,7 @@ gtk_combo_box_list_select_func (GtkTreeSelection *selection,
       gtk_tree_view_column_cell_set_cell_data (column, model, &iter,
                                               FALSE, FALSE);
 
-      cell = cells = gtk_tree_view_column_get_cell_renderers (column);
+      cell = cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column));
       while (cell)
         {
          g_object_get (cell->data,
@@ -4357,8 +4421,8 @@ combo_cell_data_func (GtkCellLayout   *cell_layout,
   if (!info->func)
     return;
 
-  (*info->func) (cell_layout, cell, tree_model, iter, info->func_data);
-  
+  info->func (cell_layout, cell, tree_model, iter, info->func_data);
+
   if (GTK_IS_WIDGET (cell_layout))
     parent = gtk_widget_get_parent (GTK_WIDGET (cell_layout));
   
@@ -4812,6 +4876,14 @@ gtk_combo_box_set_active (GtkComboBox *combo_box,
   g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
   g_return_if_fail (index_ >= -1);
 
+  if (combo_box->priv->model == NULL)
+    {
+      /* Save index, in case the model is set after the index */
+      combo_box->priv->active = index_;
+      if (index_ != -1)
+        return;
+    }
+
   if (index_ != -1)
     path = gtk_tree_path_new_from_indices (index_, -1);
    
@@ -4829,7 +4901,10 @@ gtk_combo_box_set_active_internal (GtkComboBox *combo_box,
   GtkTreePath *active_path;
   gint path_cmp;
 
-  if (path && gtk_tree_row_reference_valid (priv->active_row))
+  /* Remember whether the initially active row is valid. */
+  gboolean is_valid_row_reference = gtk_tree_row_reference_valid (priv->active_row);
+
+  if (path && is_valid_row_reference)
     {
       active_path = gtk_tree_row_reference_get_path (priv->active_row);
       path_cmp = gtk_tree_path_compare (path, active_path);
@@ -4858,6 +4933,13 @@ gtk_combo_box_set_active_internal (GtkComboBox *combo_box,
 
       if (priv->cell_view)
         gtk_cell_view_set_displayed_row (GTK_CELL_VIEW (priv->cell_view), NULL);
+
+      /*
+       *  Do not emit a "changed" signal when an already invalid selection was
+       *  now set to invalid.
+       */
+      if (!is_valid_row_reference)
+        return;
     }
   else
     {
@@ -4919,10 +5001,12 @@ gtk_combo_box_get_active_iter (GtkComboBox     *combo_box,
 /**
  * gtk_combo_box_set_active_iter:
  * @combo_box: A #GtkComboBox
- * @iter: The #GtkTreeIter
+ * @iter: (allow-none): The #GtkTreeIter, or %NULL
  * 
- * Sets the current active item to be the one referenced by @iter. 
- * @iter must correspond to a path of depth one.
+ * Sets the current active item to be the one referenced by @iter, or
+ * unsets the active item if @iter is %NULL.
+ *
+ * @iter must correspond to a path of depth one, or be %NULL.
  * 
  * Since: 2.4
  */
@@ -4930,11 +5014,13 @@ void
 gtk_combo_box_set_active_iter (GtkComboBox     *combo_box,
                                GtkTreeIter     *iter)
 {
-  GtkTreePath *path;
+  GtkTreePath *path = NULL;
 
   g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
 
-  path = gtk_tree_model_get_path (gtk_combo_box_get_model (combo_box), iter);
+  if (iter)
+    path = gtk_tree_model_get_path (gtk_combo_box_get_model (combo_box), iter);
+
   gtk_combo_box_set_active_internal (combo_box, path);
   gtk_tree_path_free (path);
 }
@@ -4942,9 +5028,9 @@ gtk_combo_box_set_active_iter (GtkComboBox     *combo_box,
 /**
  * gtk_combo_box_set_model:
  * @combo_box: A #GtkComboBox
- * @model: A #GtkTreeModel
+ * @model: (allow-none): A #GtkTreeModel
  *
- * Sets the model used by @combo_box to be @model. Will unset a previously set 
+ * Sets the model used by @combo_box to be @model. Will unset a previously set
  * model (if applicable). If model is %NULL, then it will unset the model.
  *
  * Note that this function does not clear the cell renderers, you have to 
@@ -4972,19 +5058,19 @@ gtk_combo_box_set_model (GtkComboBox  *combo_box,
   g_object_ref (combo_box->priv->model);
 
   combo_box->priv->inserted_id =
-    g_signal_connect (combo_box->priv->model, "row_inserted",
+    g_signal_connect (combo_box->priv->model, "row-inserted",
                      G_CALLBACK (gtk_combo_box_model_row_inserted),
                      combo_box);
   combo_box->priv->deleted_id =
-    g_signal_connect (combo_box->priv->model, "row_deleted",
+    g_signal_connect (combo_box->priv->model, "row-deleted",
                      G_CALLBACK (gtk_combo_box_model_row_deleted),
                      combo_box);
   combo_box->priv->reordered_id =
-    g_signal_connect (combo_box->priv->model, "rows_reordered",
+    g_signal_connect (combo_box->priv->model, "rows-reordered",
                      G_CALLBACK (gtk_combo_box_model_rows_reordered),
                      combo_box);
   combo_box->priv->changed_id =
-    g_signal_connect (combo_box->priv->model, "row_changed",
+    g_signal_connect (combo_box->priv->model, "row-changed",
                      G_CALLBACK (gtk_combo_box_model_row_changed),
                      combo_box);
       
@@ -5007,6 +5093,13 @@ gtk_combo_box_set_model (GtkComboBox  *combo_box,
     gtk_cell_view_set_model (GTK_CELL_VIEW (combo_box->priv->cell_view),
                              combo_box->priv->model);
 
+  if (combo_box->priv->active != -1)
+    {
+      /* If an index was set in advance, apply it now */
+      gtk_combo_box_set_active (combo_box, combo_box->priv->active);
+      combo_box->priv->active = -1;
+    }
+
 out:
   gtk_combo_box_update_sensitivity (combo_box);
 
@@ -5019,7 +5112,7 @@ out:
  *
  * Returns the #GtkTreeModel which is acting as data source for @combo_box.
  *
- * Return value: A #GtkTreeModel which was passed during construction.
+ * Return value: (transfer none): A #GtkTreeModel which was passed during construction.
  *
  * Since: 2.4
  */
@@ -5044,7 +5137,7 @@ gtk_combo_box_get_model (GtkComboBox *combo_box)
  * gtk_combo_box_insert_text(), gtk_combo_box_prepend_text() and
  * gtk_combo_box_remove_text().
  *
- * Return value: A new text combo box.
+ * Return value: (transfer none): A new text combo box.
  *
  * Since: 2.4
  */
@@ -5197,10 +5290,11 @@ gtk_combo_box_remove_text (GtkComboBox *combo_box,
  *
  * Returns the currently active string in @combo_box or %NULL if none
  * is selected.  Note that you can only use this function with combo
- * boxes constructed with gtk_combo_box_new_text() and with 
+ * boxes constructed with gtk_combo_box_new_text() and with
  * #GtkComboBoxEntry<!-- -->s.
  *
  * Returns: a newly allocated string containing the currently active text.
+ *     Must be freed with g_free().
  *
  * Since: 2.6
  */
@@ -5214,7 +5308,7 @@ gtk_combo_box_get_active_text (GtkComboBox *combo_box)
   class = GTK_COMBO_BOX_GET_CLASS (combo_box);
 
   if (class->get_active_text)
-    return (* class->get_active_text) (combo_box);
+    return class->get_active_text (combo_box);
 
   return NULL;
 }
@@ -5353,7 +5447,7 @@ gtk_combo_box_destroy (GtkObject *object)
   gtk_combo_box_popdown (combo_box);
 
   if (combo_box->priv->row_separator_destroy)
-    (* combo_box->priv->row_separator_destroy) (combo_box->priv->row_separator_data);
+    combo_box->priv->row_separator_destroy (combo_box->priv->row_separator_data);
 
   combo_box->priv->row_separator_func = NULL;
   combo_box->priv->row_separator_data = NULL;
@@ -5426,8 +5520,9 @@ gtk_cell_editable_key_press (GtkWidget   *widget,
 
   if (event->keyval == GDK_Escape)
     {
-      combo_box->priv->editing_canceled = TRUE;
-
+      g_object_set (combo_box,
+                    "editing-canceled", TRUE,
+                    NULL);
       gtk_cell_editable_editing_done (GTK_CELL_EDITABLE (combo_box));
       gtk_cell_editable_remove_widget (GTK_CELL_EDITABLE (combo_box));
       
@@ -5482,7 +5577,9 @@ popup_idle (gpointer data)
                             combo_box, 0);
   
   /* we unset this if a menu item is activated */
-  combo_box->priv->editing_canceled = TRUE;
+  g_object_set (combo_box,
+                "editing-canceled", TRUE,
+                NULL);
   gtk_combo_box_popup (combo_box);
 
   combo_box->priv->popup_idle_id = 0;
@@ -5502,7 +5599,7 @@ gtk_combo_box_start_editing (GtkCellEditable *cell_editable,
 
   if (combo_box->priv->cell_view)
     {
-      g_signal_connect_object (combo_box->priv->button, "key_press_event",
+      g_signal_connect_object (combo_box->priv->button, "key-press-event",
                               G_CALLBACK (gtk_cell_editable_key_press), 
                               cell_editable, 0);  
 
@@ -5510,12 +5607,12 @@ gtk_combo_box_start_editing (GtkCellEditable *cell_editable,
     }
   else
     {
-      g_signal_connect_object (GTK_BIN (combo_box)->child, "key_press_event",
+      g_signal_connect_object (GTK_BIN (combo_box)->child, "key-press-event",
                               G_CALLBACK (gtk_cell_editable_key_press), 
                               cell_editable, 0);  
 
       gtk_widget_grab_focus (GTK_WIDGET (GTK_BIN (combo_box)->child));
-      GTK_WIDGET_UNSET_FLAGS (combo_box->priv->button, GTK_CAN_FOCUS);
+      gtk_widget_set_can_focus (combo_box->priv->button, FALSE);
     }
 
   /* we do the immediate popup only for the optionmenu-like 
@@ -5643,14 +5740,6 @@ gtk_combo_box_set_title (GtkComboBox *combo_box,
     }
 }
 
-gboolean
-_gtk_combo_box_editing_canceled (GtkComboBox *combo_box)
-{
-  g_return_val_if_fail (GTK_IS_COMBO_BOX (combo_box), TRUE);
-
-  return combo_box->priv->editing_canceled;
-}
-
 /**
  * gtk_combo_box_get_popup_accessible:
  * @combo_box: a #GtkComboBox
@@ -5702,8 +5791,8 @@ gtk_combo_box_get_row_separator_func (GtkComboBox *combo_box)
  * gtk_combo_box_set_row_separator_func:
  * @combo_box: a #GtkComboBox
  * @func: a #GtkTreeViewRowSeparatorFunc
- * @data: user data to pass to @func, or %NULL
- * @destroy: destroy notifier for @data, or %NULL
+ * @data: (allow-none): user data to pass to @func, or %NULL
+ * @destroy: (allow-none): destroy notifier for @data, or %NULL
  * 
  * Sets the row separator function, which is used to determine
  * whether a row should be drawn as a separator. If the row separator
@@ -5720,7 +5809,7 @@ gtk_combo_box_set_row_separator_func (GtkComboBox                 *combo_box,
   g_return_if_fail (GTK_IS_COMBO_BOX (combo_box));
 
   if (combo_box->priv->row_separator_destroy)
-    (* combo_box->priv->row_separator_destroy) (combo_box->priv->row_separator_data);
+    combo_box->priv->row_separator_destroy (combo_box->priv->row_separator_data);
 
   combo_box->priv->row_separator_func = func;
   combo_box->priv->row_separator_data = data;