]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtknotebook.c
Add GtkScrollable interface
[~andy/gtk] / gtk / gtknotebook.c
index 5585d754338ffba181a401e55058b45093d29594..2827645f9661bc99da8d0bde5453491a7b051710 100644 (file)
 
 #include "config.h"
 
+#include "gtknotebook.h"
+
 #include <stdio.h>
 #include <string.h>
 
 #include <gdk/gdkkeysyms.h>
 
-#include "gtknotebook.h"
 #include "gtkmain.h"
 #include "gtkmenu.h"
 #include "gtkmenuitem.h"
 #include "gtkdnd.h"
 #include "gtkbuildable.h"
 
+
+/**
+ * SECTION:gtknotebook
+ * @Short_description: A tabbed notebook container
+ * @Title: GtkNotebook
+ * @See_also: #GtkContainer
+ *
+ * The #GtkNotebook widget is a #GtkContainer whose children are pages that
+ * can be switched between using tab labels along one edge.
+ *
+ * There are many configuration options for GtkNotebook. Among other
+ * things, you can choose on which edge the tabs appear
+ * (see gtk_notebook_set_tab_pos()), whether, if there are too many
+ * tabs to fit the notebook should be made bigger or scrolling
+ * arrows added (see gtk_notebook_set_scrollable()), and whether there
+ * will be a popup menu allowing the users to switch pages.
+ * (see gtk_notebook_popup_enable(), gtk_notebook_popup_disable())
+ *
+ * <refsect2 id="GtkNotebook-BUILDER-UI">
+ * <title>GtkNotebook as GtkBuildable</title>
+ * <para>
+ * The GtkNotebook implementation of the #GtkBuildable interface
+ * supports placing children into tabs by specifying "tab" as the
+ * "type" attribute of a &lt;child&gt; element. Note that the content
+ * of the tab must be created before the tab can be filled.
+ * A tab child can be specified without specifying a &lt;child&gt;
+ * type attribute.
+ *
+ * To add a child widget in the notebooks action area, specify
+ * "action-start" or "action-end" as the "type" attribute of the &lt;child&gt;
+ * element.
+ * </para>
+ * <example>
+ * <title>A UI definition fragment with GtkNotebook</title>
+ * <programlisting><![CDATA[
+ * <object class="GtkNotebook">
+ *   <child>
+ *     <object class="GtkLabel" id="notebook-content">
+ *       <property name="label">Content</property>
+ *     </object>
+ *   </child>
+ *   <child type="tab">
+ *     <object class="GtkLabel" id="notebook-tab">
+ *       <property name="label">Tab</property>
+ *     </object>
+ *   </child>
+ * </object>
+ * ]]></programlisting>
+ * </example>
+ * </refsect2>
+ */
+
+
 #define SCROLL_DELAY_FACTOR   5
 #define SCROLL_THRESHOLD      12
 #define DND_THRESHOLD_MULTIPLIER 4
@@ -92,7 +146,7 @@ struct _GtkNotebookPrivate
   gint           mouse_y;
   gint           pressed_button;
 
-  gpointer       group;
+  GQuark         group;
 
   guint          dnd_timer;
   guint          switch_tab_timer;
@@ -171,7 +225,7 @@ enum {
   PROP_SCROLLABLE,
   PROP_PAGE,
   PROP_ENABLE_POPUP,
-  PROP_GROUP,
+  PROP_GROUP_NAME
 };
 
 enum {
@@ -261,8 +315,7 @@ static void     gtk_notebook_query_tab_label_packing (GtkNotebook  *notebook,
                                                       gboolean     *fill,
                                                       GtkPackType  *pack_type);
 
-/*** GtkObject Methods ***/
-static void gtk_notebook_destroy             (GtkObject        *object);
+/*** GObject Methods ***/
 static void gtk_notebook_set_property       (GObject         *object,
                                              guint            prop_id,
                                              const GValue    *value,
@@ -273,6 +326,7 @@ static void gtk_notebook_get_property            (GObject         *object,
                                              GParamSpec      *pspec);
 
 /*** GtkWidget Methods ***/
+static void gtk_notebook_destroy             (GtkWidget        *widget);
 static void gtk_notebook_map                 (GtkWidget        *widget);
 static void gtk_notebook_unmap               (GtkWidget        *widget);
 static void gtk_notebook_realize             (GtkWidget        *widget);
@@ -281,10 +335,8 @@ static void gtk_notebook_size_request        (GtkWidget        *widget,
                                              GtkRequisition   *requisition);
 static void gtk_notebook_size_allocate       (GtkWidget        *widget,
                                              GtkAllocation    *allocation);
-static gint gtk_notebook_expose              (GtkWidget        *widget,
-                                             GdkEventExpose   *event);
-static gboolean gtk_notebook_scroll          (GtkWidget        *widget,
-                                              GdkEventScroll   *event);
+static gint gtk_notebook_draw                (GtkWidget        *widget,
+                                              cairo_t          *cr);
 static gint gtk_notebook_button_press        (GtkWidget        *widget,
                                              GdkEventButton   *event);
 static gint gtk_notebook_button_release      (GtkWidget        *widget,
@@ -302,8 +354,6 @@ static void gtk_notebook_grab_notify         (GtkWidget          *widget,
                                              gboolean            was_grabbed);
 static void gtk_notebook_state_changed       (GtkWidget          *widget,
                                              GtkStateType        previous_state);
-static void gtk_notebook_draw_focus          (GtkWidget        *widget,
-                                             GdkEventExpose   *event);
 static gint gtk_notebook_focus               (GtkWidget        *widget,
                                              GtkDirectionType  direction);
 static void gtk_notebook_style_set           (GtkWidget        *widget,
@@ -403,11 +453,12 @@ static void  gtk_notebook_child_reordered    (GtkNotebook      *notebook,
 
 /*** GtkNotebook Drawing Functions ***/
 static void gtk_notebook_paint               (GtkWidget        *widget,
-                                             GdkRectangle     *area);
+                                             cairo_t          *cr);
 static void gtk_notebook_draw_tab            (GtkNotebook      *notebook,
                                              GtkNotebookPage  *page,
-                                             GdkRectangle     *area);
+                                             cairo_t          *cr);
 static void gtk_notebook_draw_arrow          (GtkNotebook      *notebook,
+                                              cairo_t          *cr,
                                              GtkNotebookArrow  arrow);
 
 /*** GtkNotebook Size Allocate Functions ***/
@@ -467,10 +518,6 @@ static void gtk_notebook_buildable_add_child      (GtkBuildable *buildable,
                                                   GObject      *child,
                                                   const gchar  *type);
 
-static GtkNotebookWindowCreationFunc window_creation_hook = NULL;
-static gpointer window_creation_hook_data;
-static GDestroyNotify window_creation_hook_destroy = NULL;
-
 static guint notebook_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE_WITH_CODE (GtkNotebook, gtk_notebook, GTK_TYPE_CONTAINER,
@@ -539,27 +586,58 @@ gtk_object_handled_accumulator (GSignalInvocationHint *ihint,
   return continue_emission;
 }
 
+static void
+gtk_notebook_compute_expand (GtkWidget *widget,
+                             gboolean  *hexpand_p,
+                             gboolean  *vexpand_p)
+{
+  GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+  GtkNotebookPrivate *priv = notebook->priv;
+  gboolean hexpand;
+  gboolean vexpand;
+  GList *list;
+  GtkNotebookPage *page;
+
+  hexpand = FALSE;
+  vexpand = FALSE;
+
+  for (list = priv->children; list; list = list->next)
+    {
+      page = list->data;
+
+      hexpand = hexpand ||
+        gtk_widget_compute_expand (page->child, GTK_ORIENTATION_HORIZONTAL);
+
+      vexpand = vexpand ||
+        gtk_widget_compute_expand (page->child, GTK_ORIENTATION_VERTICAL);
+
+      if (hexpand & vexpand)
+        break;
+    }
+
+  *hexpand_p = hexpand;
+  *vexpand_p = vexpand;
+}
+
 static void
 gtk_notebook_class_init (GtkNotebookClass *class)
 {
   GObjectClass   *gobject_class = G_OBJECT_CLASS (class);
-  GtkObjectClass *object_class = GTK_OBJECT_CLASS (class);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
   GtkBindingSet *binding_set;
   
   gobject_class->set_property = gtk_notebook_set_property;
   gobject_class->get_property = gtk_notebook_get_property;
-  object_class->destroy = gtk_notebook_destroy;
 
+  widget_class->destroy = gtk_notebook_destroy;
   widget_class->map = gtk_notebook_map;
   widget_class->unmap = gtk_notebook_unmap;
   widget_class->realize = gtk_notebook_realize;
   widget_class->unrealize = gtk_notebook_unrealize;
   widget_class->size_request = gtk_notebook_size_request;
   widget_class->size_allocate = gtk_notebook_size_allocate;
-  widget_class->expose_event = gtk_notebook_expose;
-  widget_class->scroll_event = gtk_notebook_scroll;
+  widget_class->draw = gtk_notebook_draw;
   widget_class->button_press_event = gtk_notebook_button_press;
   widget_class->button_release_event = gtk_notebook_button_release;
   widget_class->popup_menu = gtk_notebook_popup_menu;
@@ -578,6 +656,7 @@ gtk_notebook_class_init (GtkNotebookClass *class)
   widget_class->drag_drop = gtk_notebook_drag_drop;
   widget_class->drag_data_get = gtk_notebook_drag_data_get;
   widget_class->drag_data_received = gtk_notebook_drag_data_received;
+  widget_class->compute_expand = gtk_notebook_compute_expand;
 
   container_class->add = gtk_notebook_add;
   container_class->remove = gtk_notebook_remove;
@@ -644,18 +723,19 @@ gtk_notebook_class_init (GtkNotebookClass *class)
                                                         GTK_PARAM_READWRITE));
 
   /**
-   * GtkNotebook:group:
-   *  
-   * Group for tabs drag and drop.
+   * GtkNotebook:group-name:
    *
-   * Since: 2.12
-   */    
+   * Group name for tab drag and drop.
+   *
+   * Since: 2.24
+   */
   g_object_class_install_property (gobject_class,
-                                  PROP_GROUP,
-                                  g_param_spec_pointer ("group",
-                                                        P_("Group"),
-                                                        P_("Group for tabs drag and drop"),
-                                                        GTK_PARAM_READWRITE));
+                                  PROP_GROUP_NAME,
+                                  g_param_spec_string ("group-name",
+                                                       P_("Group Name"),
+                                                       P_("Group name for tab drag and drop"),
+                                                        NULL,
+                                                       GTK_PARAM_READWRITE));
 
   gtk_container_class_install_child_property (container_class,
                                              CHILD_PROP_TAB_LABEL,
@@ -692,6 +772,13 @@ gtk_notebook_class_init (GtkNotebookClass *class)
                                                                    P_("Whether the child's tab should fill the allocated area"),
                                                                    TRUE,
                                                                    GTK_PARAM_READWRITE));
+
+  /**
+   * GtkNotebook:tab-pack:
+   *
+   *  Deprecated: 2.20: The tab packing functionality of children should not
+   *  be used anymore and support will be removed in the future.
+   */
   gtk_container_class_install_child_property (container_class,
                                              CHILD_PROP_TAB_PACK,
                                              g_param_spec_enum ("tab-pack", 
@@ -826,6 +913,14 @@ gtk_notebook_class_init (GtkNotebookClass *class)
                                                              0,
                                                              GTK_PARAM_READABLE));
 
+  /**
+   * GtkNotebook::switch-page:
+   * @notebook: the object which received the signal.
+   * @page: the new current page
+   * @page_num: the index of the page
+   *
+   * Emitted when the user or a function changes the current page.
+   */
   notebook_signals[SWITCH_PAGE] =
     g_signal_new (I_("switch-page"),
                  G_TYPE_FROM_CLASS (gobject_class),
@@ -897,11 +992,12 @@ gtk_notebook_class_init (GtkNotebookClass *class)
     g_signal_new (I_("page-reordered"),
                   G_TYPE_FROM_CLASS (gobject_class),
                   G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                 _gtk_marshal_VOID__OBJECT_UINT,
+                  G_STRUCT_OFFSET (GtkNotebookClass, page_reordered),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__OBJECT_UINT,
                   G_TYPE_NONE, 2,
-                 GTK_TYPE_WIDGET,
-                 G_TYPE_UINT);
+                  GTK_TYPE_WIDGET,
+                  G_TYPE_UINT);
   /**
    * GtkNotebook::page-removed:
    * @notebook: the #GtkNotebook
@@ -917,11 +1013,12 @@ gtk_notebook_class_init (GtkNotebookClass *class)
     g_signal_new (I_("page-removed"),
                   G_TYPE_FROM_CLASS (gobject_class),
                   G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                 _gtk_marshal_VOID__OBJECT_UINT,
+                  G_STRUCT_OFFSET (GtkNotebookClass, page_removed),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__OBJECT_UINT,
                   G_TYPE_NONE, 2,
-                 GTK_TYPE_WIDGET,
-                 G_TYPE_UINT);
+                  GTK_TYPE_WIDGET,
+                  G_TYPE_UINT);
   /**
    * GtkNotebook::page-added:
    * @notebook: the #GtkNotebook
@@ -937,11 +1034,12 @@ gtk_notebook_class_init (GtkNotebookClass *class)
     g_signal_new (I_("page-added"),
                   G_TYPE_FROM_CLASS (gobject_class),
                   G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                 _gtk_marshal_VOID__OBJECT_UINT,
+                  G_STRUCT_OFFSET (GtkNotebookClass, page_added),
+                  NULL, NULL,
+                  _gtk_marshal_VOID__OBJECT_UINT,
                   G_TYPE_NONE, 2,
-                 GTK_TYPE_WIDGET,
-                 G_TYPE_UINT);
+                  GTK_TYPE_WIDGET,
+                  G_TYPE_UINT);
 
   /**
    * GtkNotebook::create-window:
@@ -959,9 +1057,6 @@ gtk_notebook_class_init (GtkNotebookClass *class)
    * necessary properties to the notebook (e.g. the 
    * #GtkNotebook:group ).
    *
-   * The default handler uses the global window creation hook,
-   * if one has been set with gtk_notebook_set_window_creation_hook().
-   *
    * Returns: a #GtkNotebook that @page should be added to, or %NULL.
    *
    * Since: 2.12
@@ -1081,7 +1176,7 @@ gtk_notebook_init (GtkNotebook *notebook)
   priv->has_after_previous  = 0;
   priv->has_after_next      = 1;
 
-  priv->group = NULL;
+  priv->group = 0;
   priv->pressed_button = -1;
   priv->dnd_timer = 0;
   priv->switch_tab_timer = 0;
@@ -1462,36 +1557,11 @@ gtk_notebook_new (void)
   return g_object_new (GTK_TYPE_NOTEBOOK, NULL);
 }
 
-/* Private GtkObject Methods :
- * 
- * gtk_notebook_destroy
- * gtk_notebook_set_arg
- * gtk_notebook_get_arg
+/* Private GObject Methods :
+ *
+ * gtk_notebook_set_property
+ * gtk_notebook_get_property
  */
-static void
-gtk_notebook_destroy (GtkObject *object)
-{
-  GtkNotebook *notebook = GTK_NOTEBOOK (object);
-  GtkNotebookPrivate *priv = notebook->priv;
-
-  if (priv->menu)
-    gtk_notebook_popup_disable (notebook);
-
-  if (priv->source_targets)
-    {
-      gtk_target_list_unref (priv->source_targets);
-      priv->source_targets = NULL;
-    }
-
-  if (priv->switch_tab_timer)
-    {
-      g_source_remove (priv->switch_tab_timer);
-      priv->switch_tab_timer = 0;
-    }
-
-  GTK_OBJECT_CLASS (gtk_notebook_parent_class)->destroy (object);
-}
-
 static void
 gtk_notebook_set_property (GObject         *object,
                           guint            prop_id,
@@ -1525,8 +1595,8 @@ gtk_notebook_set_property (GObject         *object,
     case PROP_TAB_POS:
       gtk_notebook_set_tab_pos (notebook, g_value_get_enum (value));
       break;
-    case PROP_GROUP:
-      gtk_notebook_set_group (notebook, g_value_get_pointer (value));
+    case PROP_GROUP_NAME:
+      gtk_notebook_set_group_name (notebook, g_value_get_string (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1563,8 +1633,8 @@ gtk_notebook_get_property (GObject         *object,
     case PROP_TAB_POS:
       g_value_set_enum (value, priv->tab_pos);
       break;
-    case PROP_GROUP:
-      g_value_set_pointer (value, priv->group);
+    case PROP_GROUP_NAME:
+      g_value_set_string (value, gtk_notebook_get_group_name (notebook));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1573,13 +1643,14 @@ gtk_notebook_get_property (GObject         *object,
 }
 
 /* Private GtkWidget Methods :
- * 
+ *
+ * gtk_notebook_destroy
  * gtk_notebook_map
  * gtk_notebook_unmap
  * gtk_notebook_realize
  * gtk_notebook_size_request
  * gtk_notebook_size_allocate
- * gtk_notebook_expose
+ * gtk_notebook_draw
  * gtk_notebook_scroll
  * gtk_notebook_button_press
  * gtk_notebook_button_release
@@ -1588,7 +1659,6 @@ gtk_notebook_get_property (GObject         *object,
  * gtk_notebook_motion_notify
  * gtk_notebook_focus_in
  * gtk_notebook_focus_out
- * gtk_notebook_draw_focus
  * gtk_notebook_style_set
  * gtk_notebook_drag_begin
  * gtk_notebook_drag_end
@@ -1598,6 +1668,30 @@ gtk_notebook_get_property (GObject         *object,
  * gtk_notebook_drag_data_get
  * gtk_notebook_drag_data_received
  */
+static void
+gtk_notebook_destroy (GtkWidget *widget)
+{
+  GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+  GtkNotebookPrivate *priv = notebook->priv;
+
+  if (priv->menu)
+    gtk_notebook_popup_disable (notebook);
+
+  if (priv->source_targets)
+    {
+      gtk_target_list_unref (priv->source_targets);
+      priv->source_targets = NULL;
+    }
+
+  if (priv->switch_tab_timer)
+    {
+      g_source_remove (priv->switch_tab_timer);
+      priv->switch_tab_timer = 0;
+    }
+
+  GTK_WIDGET_CLASS (gtk_notebook_parent_class)->destroy (widget);
+}
+
 static gboolean
 gtk_notebook_get_event_window_position (GtkNotebook  *notebook,
                                        GdkRectangle *rectangle)
@@ -1713,7 +1807,7 @@ gtk_notebook_map (GtkWidget *widget)
     {
       if (priv->action_widget[i] &&
           gtk_widget_get_visible (priv->action_widget[i]) &&
-          GTK_WIDGET_CHILD_VISIBLE (priv->action_widget[i]) &&
+          gtk_widget_get_child_visible (priv->action_widget[i]) &&
           !gtk_widget_get_mapped (priv->action_widget[i]))
         gtk_widget_map (priv->action_widget[i]);
     }
@@ -1782,8 +1876,7 @@ gtk_notebook_realize (GtkWidget *widget)
   attributes.event_mask = gtk_widget_get_events (widget);
   attributes.event_mask |= (GDK_BUTTON_PRESS_MASK |
                            GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK |
-                           GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK |
-                           GDK_SCROLL_MASK);
+                           GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
   attributes_mask = GDK_WA_X | GDK_WA_Y;
 
   priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
@@ -1854,8 +1947,9 @@ gtk_notebook_size_request (GtkWidget      *widget,
       if (gtk_widget_get_visible (page->child))
        {
          vis_pages++;
-         gtk_widget_size_request (page->child, &child_requisition);
-         
+          gtk_widget_get_preferred_size (page->child,
+                                         &child_requisition, NULL);
+
          requisition->width = MAX (requisition->width,
                                           child_requisition.width);
          requisition->height = MAX (requisition->height,
@@ -1911,8 +2005,8 @@ gtk_notebook_size_request (GtkWidget      *widget,
                  if (!gtk_widget_get_visible (page->tab_label))
                    gtk_widget_show (page->tab_label);
 
-                 gtk_widget_size_request (page->tab_label,
-                                          &child_requisition);
+                  gtk_widget_get_preferred_size (page->tab_label,
+                                                 &child_requisition, NULL);
 
                   page->requisition.width = child_requisition.width + 2 * style->xthickness;
                  page->requisition.height = child_requisition.height + 2 * style->ythickness;
@@ -1947,7 +2041,8 @@ gtk_notebook_size_request (GtkWidget      *widget,
                 {
                   if (priv->action_widget[i])
                     {
-                      gtk_widget_size_request (priv->action_widget[i], &action_widget_requisition[i]);
+                      gtk_widget_get_preferred_size (priv->action_widget[i],
+                                                     &action_widget_requisition[i], NULL);
                       action_widget_requisition[i].width += style->xthickness;
                       action_widget_requisition[i].height += style->ythickness;
                     }
@@ -2199,7 +2294,8 @@ gtk_notebook_size_allocate (GtkWidget     *widget,
                  widget_allocation.y = allocation->y + border_width;
                  is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
 
-                 gtk_widget_get_child_requisition (priv->action_widget[i], &requisition);
+                  gtk_widget_get_preferred_size (priv->action_widget[i],
+                                                 &requisition, NULL);
 
                  switch (tab_pos)
                    {
@@ -2250,78 +2346,83 @@ gtk_notebook_size_allocate (GtkWidget     *widget,
 }
 
 static gint
-gtk_notebook_expose (GtkWidget      *widget,
-                    GdkEventExpose *event)
+gtk_notebook_draw (GtkWidget *widget,
+                   cairo_t   *cr)
 {
   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
   GtkNotebookPrivate *priv = notebook->priv;
+  GtkAllocation allocation;
+  GdkWindow *window;
   gint i;
 
-  if (event->window == priv->drag_window)
+  gtk_widget_get_allocation (widget, &allocation);
+
+  window = gtk_widget_get_window (widget);
+  if (gtk_cairo_should_draw_window (cr, window))
     {
-      GdkRectangle area = { 0, };
-      cairo_t *cr;
+      cairo_save (cr);
 
-      /* FIXME: This is a workaround to make tabs reordering work better
-       * with engines with rounded tabs. If the drag window background
-       * isn't set, the rounded corners would be black.
-       *
-       * Ideally, these corners should be made transparent, Either by using
-       * ARGB visuals or shape windows.
-       */
-      cr = gdk_cairo_create (priv->drag_window);
-      gdk_cairo_set_source_color (cr, &gtk_widget_get_style(widget)->bg [GTK_STATE_NORMAL]);
-      cairo_paint (cr);
-      cairo_destroy (cr);
+      cairo_translate (cr, -allocation.x, -allocation.y);
+      gtk_notebook_paint (widget, cr);
+
+      cairo_restore (cr);
 
-      gdk_drawable_get_size (priv->drag_window,
-                            &area.width, &area.height);
-      gtk_notebook_draw_tab (notebook,
-                            priv->cur_page,
-                            &area);
-      gtk_notebook_draw_focus (widget, event);
-      gtk_container_propagate_expose (GTK_CONTAINER (notebook),
-                                     priv->cur_page->tab_label, event);
-    }
-  else if (gtk_widget_is_drawable (widget))
-    {
-      gtk_notebook_paint (widget, &event->area);
       if (priv->show_tabs)
        {
          GtkNotebookPage *page;
          GList *pages;
 
-         gtk_notebook_draw_focus (widget, event);
-         pages = priv->children;
-
-         while (pages)
-           {
+         for (pages = priv->children; pages; pages = pages->next)
+            {
              page = GTK_NOTEBOOK_PAGE (pages);
-             pages = pages->next;
 
-             if (gtk_widget_get_window (page->tab_label) == event->window &&
-                 gtk_widget_is_drawable (page->tab_label))
-               gtk_container_propagate_expose (GTK_CONTAINER (notebook),
-                                               page->tab_label, event);
+              if (gtk_widget_get_parent (page->tab_label) == widget)
+                gtk_container_propagate_draw (GTK_CONTAINER (notebook),
+                                              page->tab_label, cr);
            }
        }
 
-      if (priv->cur_page)
-       gtk_container_propagate_expose (GTK_CONTAINER (notebook),
-                                       priv->cur_page->child,
-                                       event);
+      if (priv->cur_page && priv->operation != DRAG_OPERATION_REORDER)
+       gtk_container_propagate_draw (GTK_CONTAINER (notebook),
+                                      priv->cur_page->child,
+                                      cr);
       if (priv->show_tabs)
       {
         for (i = 0; i < N_ACTION_WIDGETS; i++)
         {
-          if (priv->action_widget[i] &&
-              gtk_widget_is_drawable (priv->action_widget[i]))
-            gtk_container_propagate_expose (GTK_CONTAINER (notebook),
-                                            priv->action_widget[i], event);
+          if (priv->action_widget[i])
+            gtk_container_propagate_draw (GTK_CONTAINER (notebook),
+                                          priv->action_widget[i], cr);
         }
       }
     }
 
+  if (priv->operation == DRAG_OPERATION_REORDER &&
+      gtk_cairo_should_draw_window (cr, priv->drag_window))
+    {
+      cairo_save (cr);
+      gtk_cairo_transform_to_window (cr, widget, priv->drag_window);
+
+      /* FIXME: This is a workaround to make tabs reordering work better
+       * with engines with rounded tabs. If the drag window background
+       * isn't set, the rounded corners would be black.
+       *
+       * Ideally, these corners should be made transparent, Either by using
+       * ARGB visuals or shape windows.
+       */
+      gdk_cairo_set_source_color (cr, &gtk_widget_get_style (widget)->bg [GTK_STATE_NORMAL]);
+      cairo_paint (cr);
+
+      gtk_notebook_draw_tab (notebook,
+                            priv->cur_page,
+                            cr);
+
+      cairo_restore (cr);
+
+      gtk_container_propagate_draw (GTK_CONTAINER (notebook),
+                                   priv->cur_page->tab_label, cr);
+    }
+  
   return FALSE;
 }
 
@@ -2543,49 +2644,6 @@ get_widget_coordinates (GtkWidget *widget,
     return FALSE;
 }
 
-static gboolean
-gtk_notebook_scroll (GtkWidget      *widget,
-                     GdkEventScroll *event)
-{
-  GtkNotebook *notebook = GTK_NOTEBOOK (widget);
-  GtkNotebookPrivate *priv = notebook->priv;
-  GtkWidget *child, *event_widget;
-  gint i;
-
-  if (!priv->cur_page)
-    return FALSE;
-
-  child = priv->cur_page->child;
-  event_widget = gtk_get_event_widget ((GdkEvent *)event);
-
-  /* ignore scroll events from the content of the page */
-  if (!event_widget || gtk_widget_is_ancestor (event_widget, child) || event_widget == child)
-    return FALSE;
-
-  /* nor from the action area */
-  for (i = 0; i < 2; i++)
-    {
-      if (event_widget == priv->action_widget[i] ||
-          (priv->action_widget[i] &&
-           gtk_widget_is_ancestor (event_widget, priv->action_widget[i])))
-        return FALSE;
-    }
-
-  switch (event->direction)
-    {
-    case GDK_SCROLL_RIGHT:
-    case GDK_SCROLL_DOWN:
-      gtk_notebook_next_page (notebook);
-      break;
-    case GDK_SCROLL_LEFT:
-    case GDK_SCROLL_UP:
-      gtk_notebook_prev_page (notebook);
-      break;
-    }
-
-  return TRUE;
-}
-
 static GList*
 get_tab_at_pos (GtkNotebook *notebook, gint x, gint y)
 {
@@ -2708,7 +2766,8 @@ popup_position_func (GtkMenu  *menu,
   gdk_window_get_origin (gtk_widget_get_window (w), x, y);
 
   gtk_widget_get_allocation (w, &allocation);
-  gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
+  gtk_widget_get_preferred_size (GTK_WIDGET (menu),
+                                 &requisition, NULL);
 
   if (gtk_widget_get_direction (w) == GTK_TEXT_DIR_RTL)
     *x += allocation.x + allocation.width - requisition.width;
@@ -2837,9 +2896,8 @@ show_drag_window (GtkNotebook        *notebook,
       attributes.window_type = GDK_WINDOW_CHILD;
       attributes.wclass = GDK_INPUT_OUTPUT;
       attributes.visual = gtk_widget_get_visual (widget);
-      attributes.colormap = gtk_widget_get_colormap (widget);
       attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK;
-      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+      attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
 
       priv->drag_window = gdk_window_new (gtk_widget_get_parent_window (widget),
                                          &attributes,
@@ -3007,7 +3065,8 @@ get_pointer_position (GtkNotebook *notebook)
     return POINTER_BETWEEN;
 
   gdk_window_get_position (priv->event_window, &wx, &wy);
-  gdk_drawable_get_size (GDK_DRAWABLE (priv->event_window), &width, &height);
+  width = gdk_window_get_width (priv->event_window);
+  height = gdk_window_get_height (priv->event_window);
 
   if (priv->tab_pos == GTK_POS_TOP ||
       priv->tab_pos == GTK_POS_BOTTOM)
@@ -3088,7 +3147,8 @@ check_threshold (GtkNotebook *notebook,
   dnd_threshold *= DND_THRESHOLD_MULTIPLIER;
 
   gdk_window_get_position (priv->event_window, &rectangle.x, &rectangle.y);
-  gdk_drawable_get_size (GDK_DRAWABLE (priv->event_window), &rectangle.width, &rectangle.height);
+  rectangle.width = gdk_window_get_width (priv->event_window);
+  rectangle.height = gdk_window_get_height (priv->event_window);
 
   rectangle.x -= dnd_threshold;
   rectangle.width += 2 * dnd_threshold;
@@ -3253,42 +3313,6 @@ gtk_notebook_focus_out (GtkWidget     *widget,
   return FALSE;
 }
 
-static void
-gtk_notebook_draw_focus (GtkWidget      *widget,
-                        GdkEventExpose *event)
-{
-  GtkNotebook *notebook = GTK_NOTEBOOK (widget);
-  GtkNotebookPrivate *priv = notebook->priv;
-
-  if (gtk_widget_has_focus (widget) && gtk_widget_is_drawable (widget) &&
-      priv->show_tabs && priv->cur_page &&
-      gtk_widget_get_window (priv->cur_page->tab_label) == event->window)
-    {
-      GtkNotebookPage *page;
-
-      page = priv->cur_page;
-
-      if (gtk_widget_intersect (page->tab_label, &event->area, NULL))
-        {
-          GtkAllocation tab_allocation;
-          GdkRectangle area;
-          gint focus_width;
-
-          gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
-
-          gtk_widget_get_allocation (page->tab_label, &tab_allocation);
-          area.x = tab_allocation.x - focus_width;
-          area.y = tab_allocation.y - focus_width;
-          area.width = tab_allocation.width + 2 * focus_width;
-          area.height = tab_allocation.height + 2 * focus_width;
-
-         gtk_paint_focus (gtk_widget_get_style (widget), event->window,
-                           gtk_widget_get_state (widget), NULL, widget, "tab",
-                          area.x, area.y, area.width, area.height);
-        }
-    }
-}
-
 static void
 gtk_notebook_style_set  (GtkWidget *widget,
                         GtkStyle  *previous)
@@ -3317,9 +3341,9 @@ gtk_notebook_style_set  (GtkWidget *widget,
 }
 
 static gboolean
-on_drag_icon_expose (GtkWidget      *widget,
-                    GdkEventExpose *event,
-                    gpointer        data)
+on_drag_icon_draw (GtkWidget *widget,
+                  cairo_t   *cr,
+                  gpointer   data)
 {
   GtkWidget *notebook, *child;
   GtkRequisition requisition;
@@ -3328,18 +3352,19 @@ on_drag_icon_expose (GtkWidget      *widget,
   notebook = GTK_WIDGET (data);
   child = gtk_bin_get_child (GTK_BIN (widget));
 
-  gtk_widget_size_request (widget, &requisition);
+  gtk_widget_get_preferred_size (widget,
+                                 &requisition, NULL);
   gap_pos = get_tab_gap_pos (GTK_NOTEBOOK (notebook));
 
   gtk_paint_extension (gtk_widget_get_style (notebook),
-                       gtk_widget_get_window (widget),
+                       cr,
                       GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-                      NULL, widget, "tab",
+                      widget, "tab",
                       0, 0,
                       requisition.width, requisition.height,
                       gap_pos);
   if (child)
-    gtk_container_propagate_expose (GTK_CONTAINER (widget), child, event);
+    gtk_container_propagate_draw (GTK_CONTAINER (widget), child, cr);
 
   return TRUE;
 }
@@ -3376,8 +3401,8 @@ gtk_notebook_drag_begin (GtkWidget        *widget,
                               priv->detached_tab->allocation.height);
   g_object_unref (tab_label);
 
-  g_signal_connect (G_OBJECT (priv->dnd_window), "expose-event",
-                   G_CALLBACK (on_drag_icon_expose), notebook);
+  g_signal_connect (G_OBJECT (priv->dnd_window), "draw",
+                   G_CALLBACK (on_drag_icon_draw), notebook);
 
   gtk_drag_set_icon_widget (context, priv->dnd_window, -2, -2);
 }
@@ -3407,9 +3432,6 @@ gtk_notebook_create_window (GtkNotebook *notebook,
                             gint         x,
                             gint         y)
 {
-  if (window_creation_hook)
-    return (* window_creation_hook) (notebook, page, x, y, window_creation_hook_data);
-
   return NULL;
 }
 
@@ -3501,19 +3523,19 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
 
   if (target == tab_target)
     {
-      gpointer widget_group, source_widget_group;
-      GtkWidget *source_widget;
+      GQuark group, source_group;
+      GtkNotebook *source;
+      GtkWidget *source_child;
 
-      source_widget = gtk_drag_get_source_widget (context);
-      g_assert (source_widget);
+      source = GTK_NOTEBOOK (gtk_drag_get_source_widget (context));
+      source_child = source->priv->cur_page->child;
 
-      widget_group = gtk_notebook_get_group (notebook);
-      source_widget_group = gtk_notebook_get_group (GTK_NOTEBOOK (source_widget));
+      group = notebook->priv->group;
+      source_group = source->priv->group;
 
-      if (widget_group && source_widget_group &&
-         widget_group == source_widget_group &&
-         !(widget == GTK_NOTEBOOK (source_widget)->priv->cur_page->child ||
-           gtk_widget_is_ancestor (widget, GTK_NOTEBOOK (source_widget)->priv->cur_page->child)))
+      if (group != 0 && group == source_group &&
+         !(widget == source_child ||
+            gtk_widget_is_ancestor (widget, source_child)))
        {
          gdk_drag_status (context, GDK_ACTION_MOVE, time);
          return TRUE;
@@ -4610,10 +4632,9 @@ gtk_notebook_real_remove (GtkNotebook *notebook,
   GList * next_list;
   gint need_resize = FALSE;
   GtkWidget *tab_label;
-
   gboolean destroying;
 
-  destroying = GTK_OBJECT_FLAGS (notebook) & GTK_IN_DESTRUCTION;
+  destroying = gtk_widget_in_destruction (GTK_WIDGET (notebook));
 
   next_list = gtk_notebook_search_page (notebook, list, STEP_NEXT, TRUE);
   if (!next_list)
@@ -4830,7 +4851,7 @@ gtk_notebook_search_page (GtkNotebook *notebook,
  */
 static void
 gtk_notebook_paint (GtkWidget    *widget,
-                   GdkRectangle *area)
+                   cairo_t      *cr)
 {
   GtkNotebook *notebook;
   GtkNotebookPrivate *priv;
@@ -4845,9 +4866,6 @@ gtk_notebook_paint (GtkWidget    *widget,
   gboolean is_rtl;
   gint tab_pos;
    
-  if (!gtk_widget_is_drawable (widget))
-    return;
-
   notebook = GTK_NOTEBOOK (widget);
   priv = notebook->priv;
   is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
@@ -4866,10 +4884,9 @@ gtk_notebook_paint (GtkWidget    *widget,
 
   if (priv->show_border && (!priv->show_tabs || !priv->children))
     {
-      gtk_paint_box (gtk_widget_get_style (widget),
-                     gtk_widget_get_window (widget),
+      gtk_paint_box (gtk_widget_get_style (widget), cr,
                     GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-                    area, widget, "notebook",
+                    widget, "notebook",
                     x, y, width, height);
       return;
     }
@@ -4930,10 +4947,9 @@ gtk_notebook_paint (GtkWidget    *widget,
          break;
        }
     }
-  gtk_paint_box_gap (gtk_widget_get_style (widget),
-                     gtk_widget_get_window (widget),
+  gtk_paint_box_gap (gtk_widget_get_style (widget), cr,
                     GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-                    area, widget, "notebook",
+                    widget, "notebook",
                     x, y, width, height,
                     tab_pos, gap_x, gap_width);
 
@@ -4949,34 +4965,32 @@ gtk_notebook_paint (GtkWidget    *widget,
       if (!gtk_widget_get_mapped (page->tab_label))
        showarrow = TRUE;
       else if (page != priv->cur_page)
-       gtk_notebook_draw_tab (notebook, page, area);
+       gtk_notebook_draw_tab (notebook, page, cr);
     }
 
   if (showarrow && priv->scrollable)
     {
       if (priv->has_before_previous)
-       gtk_notebook_draw_arrow (notebook, ARROW_LEFT_BEFORE);
+       gtk_notebook_draw_arrow (notebook, cr, ARROW_LEFT_BEFORE);
       if (priv->has_before_next)
-       gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_BEFORE);
+       gtk_notebook_draw_arrow (notebook, cr, ARROW_RIGHT_BEFORE);
       if (priv->has_after_previous)
-       gtk_notebook_draw_arrow (notebook, ARROW_LEFT_AFTER);
+       gtk_notebook_draw_arrow (notebook, cr, ARROW_LEFT_AFTER);
       if (priv->has_after_next)
-       gtk_notebook_draw_arrow (notebook, ARROW_RIGHT_AFTER);
+       gtk_notebook_draw_arrow (notebook, cr, ARROW_RIGHT_AFTER);
     }
-  gtk_notebook_draw_tab (notebook, priv->cur_page, area);
+
+  if (priv->operation != DRAG_OPERATION_REORDER)
+    gtk_notebook_draw_tab (notebook, priv->cur_page, cr);
 }
 
 static void
 gtk_notebook_draw_tab (GtkNotebook     *notebook,
                       GtkNotebookPage *page,
-                      GdkRectangle    *area)
+                      cairo_t         *cr)
 {
   GtkNotebookPrivate *priv;
-  GdkRectangle child_area;
-  GdkRectangle page_area;
   GtkStateType state_type;
-  GtkPositionType gap_side;
-  GdkWindow *window;
   GtkWidget *widget;
   
   if (!NOTEBOOK_IS_TAB_LABEL_PARENT (notebook, page) ||
@@ -4987,36 +5001,41 @@ gtk_notebook_draw_tab (GtkNotebook     *notebook,
   widget = GTK_WIDGET (notebook);
   priv = notebook->priv;
 
-  if (priv->operation == DRAG_OPERATION_REORDER && page == priv->cur_page)
-    window = priv->drag_window;
-  else
-    window = gtk_widget_get_window (widget);
+  if (priv->cur_page == page)
+    state_type = GTK_STATE_NORMAL;
+  else 
+    state_type = GTK_STATE_ACTIVE;
 
-  page_area.x = page->allocation.x;
-  page_area.y = page->allocation.y;
-  page_area.width = page->allocation.width;
-  page_area.height = page->allocation.height;
+  gtk_paint_extension (gtk_widget_get_style (widget), cr,
+                       state_type, GTK_SHADOW_OUT,
+                       widget, "tab",
+                       page->allocation.x,
+                       page->allocation.y,
+                       page->allocation.width,
+                       page->allocation.height,
+                       get_tab_gap_pos (notebook));
 
-  if (gdk_rectangle_intersect (&page_area, area, &child_area))
+  if (gtk_widget_has_focus (widget) &&
+      priv->cur_page == page)
     {
-      gap_side = get_tab_gap_pos (notebook);
+      gint focus_width;
+      GtkAllocation allocation;
 
-      if (priv->cur_page == page)
-       state_type = GTK_STATE_NORMAL;
-      else 
-       state_type = GTK_STATE_ACTIVE;
+      gtk_widget_get_allocation (page->tab_label, &allocation);
+      gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
 
-      gtk_paint_extension (gtk_widget_get_style (widget), window,
-                          state_type, GTK_SHADOW_OUT,
-                          area, widget, "tab",
-                          page_area.x, page_area.y,
-                          page_area.width, page_area.height,
-                          gap_side);
+      gtk_paint_focus (gtk_widget_get_style (widget), cr,
+                       gtk_widget_get_state (widget), widget, "tab",
+                       allocation.x - focus_width,
+                       allocation.y - focus_width,
+                       allocation.width + 2 * focus_width,
+                       allocation.height + 2 * focus_width);
     }
 }
 
 static void
 gtk_notebook_draw_arrow (GtkNotebook      *notebook,
+                         cairo_t          *cr,
                         GtkNotebookArrow  nbarrow)
 {
   GtkNotebookPrivate *priv = notebook->priv;
@@ -5026,67 +5045,63 @@ gtk_notebook_draw_arrow (GtkNotebook      *notebook,
   GdkRectangle arrow_rect;
   GtkArrowType arrow;
   gboolean is_rtl, left;
+  gint scroll_arrow_hlength;
+  gint scroll_arrow_vlength;
+  gint arrow_size;
 
   widget = GTK_WIDGET (notebook);
 
-  if (gtk_widget_is_drawable (widget))
-    {
-      gint scroll_arrow_hlength;
-      gint scroll_arrow_vlength;
-      gint arrow_size;
-
-      gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
+  gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
 
-      is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
-      left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
-             (!ARROW_IS_LEFT (nbarrow) && is_rtl); 
-
-      gtk_widget_style_get (widget,
-                            "scroll-arrow-hlength", &scroll_arrow_hlength,
-                            "scroll-arrow-vlength", &scroll_arrow_vlength,
-                            NULL);
+  is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
+  left = (ARROW_IS_LEFT (nbarrow) && !is_rtl) ||
+         (!ARROW_IS_LEFT (nbarrow) && is_rtl); 
 
-      if (priv->in_child == nbarrow)
-        {
-          if (priv->click_child == nbarrow)
-            state_type = GTK_STATE_ACTIVE;
-          else
-            state_type = GTK_STATE_PRELIGHT;
-        }
-      else
-        state_type = gtk_widget_get_state (widget);
+  gtk_widget_style_get (widget,
+                        "scroll-arrow-hlength", &scroll_arrow_hlength,
+                        "scroll-arrow-vlength", &scroll_arrow_vlength,
+                        NULL);
 
+  if (priv->in_child == nbarrow)
+    {
       if (priv->click_child == nbarrow)
-        shadow_type = GTK_SHADOW_IN;
+        state_type = GTK_STATE_ACTIVE;
       else
-        shadow_type = GTK_SHADOW_OUT;
+        state_type = GTK_STATE_PRELIGHT;
+    }
+  else
+    state_type = gtk_widget_get_state (widget);
 
-      if (priv->focus_tab &&
-         !gtk_notebook_search_page (notebook, priv->focus_tab,
-                                    left ? STEP_PREV : STEP_NEXT, TRUE))
-       {
-         shadow_type = GTK_SHADOW_ETCHED_IN;
-         state_type = GTK_STATE_INSENSITIVE;
-       }
-      
-      if (priv->tab_pos == GTK_POS_LEFT ||
-         priv->tab_pos == GTK_POS_RIGHT)
-        {
-          arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
-          arrow_size = scroll_arrow_vlength;
-        }
-      else
-        {
-          arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
-          arrow_size = scroll_arrow_hlength;
-        }
+  if (priv->click_child == nbarrow)
+    shadow_type = GTK_SHADOW_IN;
+  else
+    shadow_type = GTK_SHADOW_OUT;
 
-      gtk_paint_arrow (gtk_widget_get_style (widget),
-                       gtk_widget_get_window (widget), state_type,
-                      shadow_type, NULL, widget, "notebook",
-                      arrow, TRUE, arrow_rect.x, arrow_rect.y, 
-                      arrow_size, arrow_size);
+  if (priv->focus_tab &&
+      !gtk_notebook_search_page (notebook, priv->focus_tab,
+                                 left ? STEP_PREV : STEP_NEXT, TRUE))
+    {
+      shadow_type = GTK_SHADOW_ETCHED_IN;
+      state_type = GTK_STATE_INSENSITIVE;
     }
+  
+  if (priv->tab_pos == GTK_POS_LEFT ||
+      priv->tab_pos == GTK_POS_RIGHT)
+    {
+      arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_UP : GTK_ARROW_DOWN);
+      arrow_size = scroll_arrow_vlength;
+    }
+  else
+    {
+      arrow = (ARROW_IS_LEFT (nbarrow) ? GTK_ARROW_LEFT : GTK_ARROW_RIGHT);
+      arrow_size = scroll_arrow_hlength;
+    }
+  gtk_paint_arrow (gtk_widget_get_style (widget),
+                   cr, state_type, 
+                   shadow_type, widget, "notebook",
+                   arrow, TRUE, arrow_rect.x, arrow_rect.y, 
+                   arrow_size, arrow_size);
 }
 
 /* Private GtkNotebook Size Allocate Functions:
@@ -5442,9 +5457,14 @@ gtk_notebook_calculate_shown_tabs (GtkNotebook *notebook,
     }
   else /* !show_arrows */
     {
+      GtkOrientation tab_expand_orientation;
       gint c = 0;
       *n = 0;
 
+      if (priv->tab_pos == GTK_POS_TOP || priv->tab_pos == GTK_POS_BOTTOM)
+        tab_expand_orientation = GTK_ORIENTATION_HORIZONTAL;
+      else
+        tab_expand_orientation = GTK_ORIENTATION_VERTICAL;
       *remaining_space = max - min - tab_overlap - tab_space;
       children = priv->children;
       priv->first_tab = gtk_notebook_search_page (notebook, NULL,
@@ -5460,7 +5480,8 @@ gtk_notebook_calculate_shown_tabs (GtkNotebook *notebook,
 
          c++;
 
-         if (page->expand)
+         if (page->expand ||
+              (gtk_widget_compute_expand (page->tab_label, tab_expand_orientation)))
            (*n)++;
        }
 
@@ -5520,6 +5541,7 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
   guint border_width;
   gboolean gap_left, packing_changed;
   GtkAllocation child_allocation = { 0, };
+  GtkOrientation tab_expand_orientation;
 
   widget = GTK_WIDGET (notebook);
   container = GTK_CONTAINER (notebook);
@@ -5569,6 +5591,11 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
   bottom_y = top_y + priv->cur_page->allocation.height;
   gap_left = packing_changed = FALSE;
 
+  if (priv->tab_pos == GTK_POS_TOP || priv->tab_pos == GTK_POS_BOTTOM)
+    tab_expand_orientation = GTK_ORIENTATION_HORIZONTAL;
+  else
+    tab_expand_orientation = GTK_ORIENTATION_VERTICAL;
+
   while (*children && *children != last_child)
     {
       page = (*children)->data;
@@ -5595,7 +5622,7 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
        continue;
 
       tab_extra_space = 0;
-      if (*expanded_tabs && (showarrow || page->expand || priv->homogeneous))
+      if (*expanded_tabs && (showarrow || page->expand || gtk_widget_compute_expand (page->tab_label, tab_expand_orientation) || priv->homogeneous))
        {
          tab_extra_space = *remaining_space / *expanded_tabs;
          *remaining_space -= tab_extra_space;
@@ -5912,7 +5939,7 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
   xthickness = style->xthickness;
   ythickness = style->ythickness;
 
-  gtk_widget_get_child_requisition (page->tab_label, &tab_requisition);
+  gtk_widget_get_preferred_size (page->tab_label, &tab_requisition, NULL);
   gtk_widget_style_get (widget,
                        "focus-line-width", &focus_width,
                        "tab-curvature", &tab_curvature,
@@ -7339,12 +7366,12 @@ gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
  * gtk_notebook_get_menu_label:
  * @notebook: a #GtkNotebook
  * @child: a widget contained in a page of @notebook
- * 
+ *
  * Retrieves the menu label widget of the page containing @child.
- * 
- * Return value: the menu label, or %NULL if the
- *               notebook page does not have a menu label other
- *               than the default (the tab label).
+ *
+ * Return value: (transfer none): the menu label, or %NULL if the
+ *     notebook page does not have a menu label other than the
+ *     default (the tab label).
  **/
 GtkWidget*
 gtk_notebook_get_menu_label (GtkNotebook *notebook,
@@ -7356,14 +7383,14 @@ gtk_notebook_get_menu_label (GtkNotebook *notebook,
   g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
 
   list = CHECK_FIND_CHILD (notebook, child);
-  if (!list)  
+  if (!list)
     return NULL;
 
   if (GTK_NOTEBOOK_PAGE (list)->default_menu)
     return NULL;
 
   return GTK_NOTEBOOK_PAGE (list)->menu_label;
-}  
+}
 
 /**
  * gtk_notebook_set_menu_label:
@@ -7634,74 +7661,56 @@ gtk_notebook_reorder_child (GtkNotebook *notebook,
 }
 
 /**
- * gtk_notebook_set_window_creation_hook:
- * @func: (allow-none): the #GtkNotebookWindowCreationFunc, or %NULL
- * @data: user data for @func
- * @destroy: (allow-none): Destroy notifier for @data, or %NULL
- *
- * Installs a global function used to create a window
- * when a detached tab is dropped in an empty area.
- * 
- * Since: 2.10
- **/
-void
-gtk_notebook_set_window_creation_hook (GtkNotebookWindowCreationFunc  func,
-                                      gpointer                       data,
-                                       GDestroyNotify                 destroy)
-{
-  if (window_creation_hook_destroy)
-    window_creation_hook_destroy (window_creation_hook_data);
-
-  window_creation_hook = func;
-  window_creation_hook_data = data;
-  window_creation_hook_destroy = destroy;
-}
-
-/**
- * gtk_notebook_set_group:
+ * gtk_notebook_set_group_name:
  * @notebook: a #GtkNotebook
- * @group: (allow-none): a pointer to identify the notebook group, or %NULL to unset it
+ * @group_name: (allow-none): the name of the notebook group,
+ *     or %NULL to unset it
  *
- * Sets a group identificator pointer for @notebook, notebooks sharing
- * the same group identificator pointer will be able to exchange tabs
- * via drag and drop. A notebook with a %NULL group identificator will
+ * Sets a group name for @notebook.
+ *
+ * Notebooks with the same name will be able to exchange tabs
+ * via drag and drop. A notebook with a %NULL group name will
  * not be able to exchange tabs with any other notebook.
- * 
- * Since: 2.12
+ *
+ * Since: 2.24
  */
 void
-gtk_notebook_set_group (GtkNotebook *notebook,
-                       gpointer     group)
+gtk_notebook_set_group_name (GtkNotebook *notebook,
+                             const gchar *group_name)
 {
   GtkNotebookPrivate *priv;
+  GQuark group;
 
   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
 
   priv = notebook->priv;
 
+  group = g_quark_from_string (group_name);
+
   if (priv->group != group)
     {
       priv->group = group;
-      g_object_notify (G_OBJECT (notebook), "group");
+      g_object_notify (G_OBJECT (notebook), "group-name");
     }
 }
 
 /**
- * gtk_notebook_get_group:
+ * gtk_notebook_get_group_name:
  * @notebook: a #GtkNotebook
- * 
- * Gets the current group identificator pointer for @notebook.
- * 
- * Return Value: the group identificator, or %NULL if none is set.
  *
- * Since: 2.12
+ * Gets the current group name for @notebook.
+ *
+ * Return Value: (transfer none): the group name,
+ *     or %NULL if none is set.
+ *
+ * Since: 2.24
  **/
-gpointer
-gtk_notebook_get_group (GtkNotebook *notebook)
+const gchar *
+gtk_notebook_get_group_name (GtkNotebook *notebook)
 {
   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
 
-  return notebook->priv->group;
+  return g_quark_to_string (notebook->priv->group);
 }
 
 /**
@@ -7863,8 +7872,8 @@ gtk_notebook_set_tab_detachable (GtkNotebook *notebook,
  *
  * Gets one of the action widgets. See gtk_notebook_set_action_widget().
  *
- * Returns: The action widget with the given @pack_type or
- *     %NULL when this action widget has not been set
+ * Returns: (transfer none): The action widget with the given @pack_type
+ *     or %NULL when this action widget has not been set
  *
  * Since: 2.20
  */