]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtknotebook.c
Hide GtkTreeViewColumn buttons when header_window is not visible
[~andy/gtk] / gtk / gtknotebook.c
index 9c35d244b107255320c0dd54cc5e9e55a173e2c4..062f337e051bad2be98400e972a73f133af984ff 100644 (file)
@@ -38,7 +38,6 @@
 #include "gtkmenu.h"
 #include "gtkmenuitem.h"
 #include "gtklabel.h"
-#include "gtksizerequest.h"
 #include "gtkintl.h"
 #include "gtkmarshalers.h"
 #include "gtkbindings.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
@@ -263,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,
@@ -275,16 +326,23 @@ 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);
 static void gtk_notebook_unrealize           (GtkWidget        *widget);
 static void gtk_notebook_size_request        (GtkWidget        *widget,
                                              GtkRequisition   *requisition);
+static void gtk_notebook_get_preferred_width (GtkWidget        *widget,
+                                             gint             *minimum,
+                                             gint             *natural);
+static void gtk_notebook_get_preferred_height(GtkWidget        *widget,
+                                             gint             *minimum,
+                                             gint             *natural);
 static void gtk_notebook_size_allocate       (GtkWidget        *widget,
                                              GtkAllocation    *allocation);
-static gint gtk_notebook_expose              (GtkWidget        *widget,
-                                             GdkEventExpose   *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,
@@ -300,12 +358,11 @@ static gint gtk_notebook_focus_out           (GtkWidget        *widget,
                                              GdkEventFocus    *event);
 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_state_flags_changed (GtkWidget          *widget,
+                                             GtkStateFlags       previous_state);
 static gint gtk_notebook_focus               (GtkWidget        *widget,
                                              GtkDirectionType  direction);
-static void gtk_notebook_style_set           (GtkWidget        *widget,
-                                             GtkStyle         *previous);
+static void gtk_notebook_style_updated       (GtkWidget        *widget);
 
 /*** Drag and drop Methods ***/
 static void gtk_notebook_drag_begin          (GtkWidget        *widget,
@@ -314,8 +371,7 @@ static void gtk_notebook_drag_end            (GtkWidget        *widget,
                                              GdkDragContext   *context);
 static gboolean gtk_notebook_drag_failed     (GtkWidget        *widget,
                                              GdkDragContext   *context,
-                                             GtkDragResult     result,
-                                             gpointer          data);
+                                             GtkDragResult     result);
 static gboolean gtk_notebook_drag_motion     (GtkWidget        *widget,
                                              GdkDragContext   *context,
                                              gint              x,
@@ -364,6 +420,8 @@ static void gtk_notebook_forall              (GtkContainer     *container,
                                              gboolean          include_internals,
                                              GtkCallback       callback,
                                              gpointer          callback_data);
+static GtkWidgetPath * gtk_notebook_get_path_for_child (GtkContainer *container,
+                                                        GtkWidget    *widget);
 
 /*** GtkNotebook Methods ***/
 static gint gtk_notebook_real_insert_page    (GtkNotebook      *notebook,
@@ -401,11 +459,13 @@ 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,
+                                              GtkRegionFlags    flags);
 static void gtk_notebook_draw_arrow          (GtkNotebook      *notebook,
+                                              cairo_t          *cr,
                                              GtkNotebookArrow  arrow);
 
 /*** GtkNotebook Size Allocate Functions ***/
@@ -533,37 +593,70 @@ 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->get_preferred_width = gtk_notebook_get_preferred_width;
+  widget_class->get_preferred_height = gtk_notebook_get_preferred_height;
   widget_class->size_allocate = gtk_notebook_size_allocate;
-  widget_class->expose_event = gtk_notebook_expose;
+  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;
   widget_class->leave_notify_event = gtk_notebook_leave_notify;
   widget_class->motion_notify_event = gtk_notebook_motion_notify;
   widget_class->grab_notify = gtk_notebook_grab_notify;
-  widget_class->state_changed = gtk_notebook_state_changed;
+  widget_class->state_flags_changed = gtk_notebook_state_flags_changed;
   widget_class->focus_in_event = gtk_notebook_focus_in;
   widget_class->focus_out_event = gtk_notebook_focus_out;
   widget_class->focus = gtk_notebook_focus;
-  widget_class->style_set = gtk_notebook_style_set;
+  widget_class->style_updated = gtk_notebook_style_updated;
   widget_class->drag_begin = gtk_notebook_drag_begin;
   widget_class->drag_end = gtk_notebook_drag_end;
   widget_class->drag_motion = gtk_notebook_drag_motion;
@@ -571,6 +664,8 @@ 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->drag_failed = gtk_notebook_drag_failed;
+  widget_class->compute_expand = gtk_notebook_compute_expand;
 
   container_class->add = gtk_notebook_add;
   container_class->remove = gtk_notebook_remove;
@@ -579,6 +674,7 @@ gtk_notebook_class_init (GtkNotebookClass *class)
   container_class->get_child_property = gtk_notebook_get_child_property;
   container_class->set_child_property = gtk_notebook_set_child_property;
   container_class->child_type = gtk_notebook_child_type;
+  container_class->get_path_for_child = gtk_notebook_get_path_for_child;
 
   class->switch_page = gtk_notebook_real_switch_page;
   class->insert_page = gtk_notebook_real_insert_page;
@@ -686,6 +782,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", 
@@ -820,6 +923,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),
@@ -891,11 +1002,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
@@ -911,11 +1023,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
@@ -931,11 +1044,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:
@@ -1036,6 +1150,7 @@ static void
 gtk_notebook_init (GtkNotebook *notebook)
 {
   GtkNotebookPrivate *priv;
+  GtkStyleContext *context;
 
   gtk_widget_set_can_focus (GTK_WIDGET (notebook), TRUE);
   gtk_widget_set_has_window (GTK_WIDGET (notebook), FALSE);
@@ -1087,10 +1202,10 @@ gtk_notebook_init (GtkNotebook *notebook)
                     notebook_targets, G_N_ELEMENTS (notebook_targets),
                      GDK_ACTION_MOVE);
 
-  g_signal_connect (G_OBJECT (notebook), "drag-failed",
-                   G_CALLBACK (gtk_notebook_drag_failed), NULL);
-
   gtk_drag_dest_set_track_motion (GTK_WIDGET (notebook), TRUE);
+
+  context = gtk_widget_get_style_context (GTK_WIDGET (notebook));
+  gtk_style_context_add_class (context, GTK_STYLE_CLASS_NOTEBOOK);
 }
 
 static void
@@ -1453,36 +1568,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,
@@ -1564,13 +1654,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
@@ -1579,7 +1670,7 @@ gtk_notebook_get_property (GObject         *object,
  * gtk_notebook_motion_notify
  * gtk_notebook_focus_in
  * gtk_notebook_focus_out
- * gtk_notebook_style_set
+ * gtk_notebook_style_updated
  * gtk_notebook_drag_begin
  * gtk_notebook_drag_end
  * gtk_notebook_drag_failed
@@ -1588,6 +1679,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)
@@ -1703,7 +1818,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]);
     }
@@ -1802,6 +1917,89 @@ gtk_notebook_unrealize (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_notebook_parent_class)->unrealize (widget);
 }
 
+static GtkRegionFlags
+_gtk_notebook_get_tab_flags (GtkNotebook     *notebook,
+                             GtkNotebookPage *page)
+{
+  GtkNotebookPrivate *priv = notebook->priv;
+  gint i = 0, page_num = -1;
+  GtkRegionFlags flags = 0;
+  gboolean is_last = FALSE;
+  GList *pages;
+
+  if (page->pack == GTK_PACK_START)
+    {
+      gint last = -1;
+
+      for (pages = priv->children; pages; pages = pages->next)
+        {
+          GtkNotebookPage *p = pages->data;
+
+          if (!gtk_widget_get_visible (p->tab_label))
+            continue;
+
+          if (p->pack == GTK_PACK_END)
+            last = i;
+
+          if (page->pack == p->pack)
+            i++;
+
+          /* No need to keep counting tabs after it */
+          if (page == p)
+            {
+              page_num = i;
+              is_last = (last == -1 && pages->next == NULL);
+              break;
+            }
+        }
+    }
+  else
+    {
+      gboolean found = FALSE;
+
+      is_last = TRUE;
+
+      /* Count all pack_start tabs from the beginning
+       * of the list until we find the page, then all
+       * items until the end, that should give us the
+       * tab position
+       */
+      for (pages = priv->children; pages; pages = pages->next)
+        {
+          GtkNotebookPage *p = pages->data;
+
+          if (!gtk_widget_get_visible (p->tab_label))
+            continue;
+
+          if (p->pack == GTK_PACK_START || p == page || found)
+            i++;
+
+          if (page == p)
+            found = TRUE;
+          else if (p->pack == GTK_PACK_END && !found)
+            is_last = FALSE;
+        }
+
+      page_num = i;
+    }
+
+  if (page_num < 0)
+    return 0;
+
+  if ((page_num) % 2 == 0)
+    flags |= GTK_REGION_EVEN;
+  else
+    flags |= GTK_REGION_ODD;
+
+  if (page_num == 1)
+    flags |= GTK_REGION_FIRST;
+
+  if (is_last)
+    flags |= GTK_REGION_LAST;
+
+  return flags;
+}
+
 static void
 gtk_notebook_size_request (GtkWidget      *widget,
                           GtkRequisition *requisition)
@@ -1843,8 +2041,8 @@ gtk_notebook_size_request (GtkWidget      *widget,
       if (gtk_widget_get_visible (page->child))
        {
          vis_pages++;
-          gtk_size_request_get_size (GTK_SIZE_REQUEST (page->child),
-                                     &child_requisition, NULL);
+          gtk_widget_get_preferred_size (page->child,
+                                         &child_requisition, NULL);
 
          requisition->width = MAX (requisition->width,
                                           child_requisition.width);
@@ -1874,12 +2072,14 @@ gtk_notebook_size_request (GtkWidget      *widget,
 
   if (priv->show_border || priv->show_tabs)
     {
-      GtkStyle *style;
+      GtkStyleContext *context;
+      GtkBorder notebook_padding;
 
-      style = gtk_widget_get_style (widget);
+      context = gtk_widget_get_style_context (widget);
+      gtk_style_context_get_padding (context, 0, &notebook_padding);
 
-      requisition->width += style->xthickness * 2;
-      requisition->height += style->ythickness * 2;
+      requisition->width += notebook_padding.left + notebook_padding.right;
+      requisition->height += notebook_padding.top + notebook_padding.bottom;
 
       if (priv->show_tabs)
        {
@@ -1898,14 +2098,26 @@ gtk_notebook_size_request (GtkWidget      *widget,
              
              if (gtk_widget_get_visible (page->child))
                {
+                  GtkBorder tab_padding;
+
                  if (!gtk_widget_get_visible (page->tab_label))
                    gtk_widget_show (page->tab_label);
 
-                  gtk_size_request_get_size (GTK_SIZE_REQUEST (page->tab_label),
-                                             &child_requisition, NULL);
+                  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;
+                  /* Get border/padding for tab */
+                  gtk_style_context_save (context);
+                  gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB,
+                                                _gtk_notebook_get_tab_flags (notebook, page));
+                  gtk_style_context_get_padding (context, 0, &tab_padding);
+                  gtk_style_context_restore (context);
+
+                  page->requisition.width = child_requisition.width +
+                    tab_padding.left + tab_padding.right;
+
+                 page->requisition.height = child_requisition.height +
+                    tab_padding.top + tab_padding.bottom;
 
                  switch (priv->tab_pos)
                    {
@@ -1937,10 +2149,10 @@ gtk_notebook_size_request (GtkWidget      *widget,
                 {
                   if (priv->action_widget[i])
                     {
-                      gtk_size_request_get_size (GTK_SIZE_REQUEST (priv->action_widget[i]),
-                                                 &action_widget_requisition[i], NULL);
-                      action_widget_requisition[i].width += style->xthickness;
-                      action_widget_requisition[i].height += style->ythickness;
+                      gtk_widget_get_preferred_size (priv->action_widget[i],
+                                                     &action_widget_requisition[i], NULL);
+                      action_widget_requisition[i].width += notebook_padding.left;
+                      action_widget_requisition[i].height += notebook_padding.top;
                     }
                 }
 
@@ -2105,18 +2317,43 @@ gtk_notebook_size_request (GtkWidget      *widget,
     }
 }
 
+
+static void
+gtk_notebook_get_preferred_width (GtkWidget *widget,
+                                 gint      *minimum,
+                                 gint      *natural)
+{
+  GtkRequisition requisition;
+
+  gtk_notebook_size_request (widget, &requisition);
+
+  *minimum = *natural = requisition.width;
+}
+
+static void
+gtk_notebook_get_preferred_height (GtkWidget *widget,
+                                  gint      *minimum,
+                                  gint      *natural)
+{
+  GtkRequisition requisition;
+
+  gtk_notebook_size_request (widget, &requisition);
+
+  *minimum = *natural = requisition.height;
+}
+
 static void
 gtk_notebook_size_allocate (GtkWidget     *widget,
                            GtkAllocation *allocation)
 {
   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
   GtkNotebookPrivate *priv = notebook->priv;
-  GtkStyle *style;
+  GtkStyleContext *context;
   gint tab_pos = get_effective_tab_pos (notebook);
   gboolean is_rtl;
   gint focus_width;
 
-  style = gtk_widget_get_style (widget);
+  context = gtk_widget_get_style_context (widget);
 
   gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
 
@@ -2153,10 +2390,16 @@ gtk_notebook_size_allocate (GtkWidget     *widget,
 
       if (priv->show_tabs || priv->show_border)
        {
-         child_allocation.x += style->xthickness;
-         child_allocation.y += style->ythickness;
-         child_allocation.width = MAX (1, child_allocation.width - style->xthickness * 2);
-         child_allocation.height = MAX (1, child_allocation.height - style->ythickness * 2);
+          GtkStyleContext *context;
+          GtkBorder padding;
+
+          context = gtk_widget_get_style_context (widget);
+          gtk_style_context_get_padding (context, 0, &padding);
+
+          child_allocation.x += padding.left;
+          child_allocation.y += padding.top;
+          child_allocation.width = MAX (1, child_allocation.width - padding.left - padding.right);
+          child_allocation.height = MAX (1, child_allocation.height - padding.top - padding.bottom);
 
          if (priv->show_tabs && priv->children && priv->cur_page)
            {
@@ -2190,8 +2433,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_size_request_get_size (GTK_SIZE_REQUEST (priv->action_widget[i]),
-                                             &requisition, NULL);
+                  gtk_widget_get_preferred_size (priv->action_widget[i],
+                                                 &requisition, NULL);
 
                  switch (tab_pos)
                    {
@@ -2200,7 +2443,7 @@ gtk_notebook_size_allocate (GtkWidget     *widget,
                      /* fall through */
                    case GTK_POS_TOP:
                      widget_allocation.width = requisition.width;
-                     widget_allocation.height = priv->cur_page->requisition.height - style->ythickness;
+                     widget_allocation.height = priv->cur_page->requisition.height - padding.top;
 
                      if ((i == ACTION_WIDGET_START && is_rtl) ||
                           (i == ACTION_WIDGET_END && !is_rtl))
@@ -2213,7 +2456,7 @@ gtk_notebook_size_allocate (GtkWidget     *widget,
                      /* fall through */
                    case GTK_POS_LEFT:
                      widget_allocation.height = requisition.height;
-                     widget_allocation.width = priv->cur_page->requisition.width - style->xthickness;
+                     widget_allocation.width = priv->cur_page->requisition.width - padding.left;
 
                       if (i == ACTION_WIDGET_END)
                         widget_allocation.y += allocation->height - 2 * border_width - requisition.height;
@@ -2242,16 +2485,27 @@ 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 (gtk_widget_is_drawable (widget))
+  gtk_widget_get_allocation (widget, &allocation);
+
+  window = gtk_widget_get_window (widget);
+  if (gtk_cairo_should_draw_window (cr, window))
     {
-      gtk_notebook_paint (widget, &event->area);
+      cairo_save (cr);
+
+      cairo_translate (cr, -allocation.x, -allocation.y);
+      gtk_notebook_paint (widget, cr);
+
+      cairo_restore (cr);
+
       if (priv->show_tabs)
        {
          GtkNotebookPage *page;
@@ -2261,33 +2515,36 @@ gtk_notebook_expose (GtkWidget      *widget,
             {
              page = GTK_NOTEBOOK_PAGE (pages);
 
-             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 (event->window == priv->drag_window)
+  if (priv->operation == DRAG_OPERATION_REORDER &&
+      gtk_cairo_should_draw_window (cr, priv->drag_window))
     {
-      GdkRectangle area = { 0, };
-      cairo_t *cr;
+      GtkStyleContext *context;
+      GdkRGBA bg_color;
+
+      cairo_save (cr);
+      gtk_cairo_transform_to_window (cr, widget, priv->drag_window);
+      context = gtk_widget_get_style_context (widget);
 
       /* FIXME: This is a workaround to make tabs reordering work better
        * with engines with rounded tabs. If the drag window background
@@ -2296,18 +2553,18 @@ gtk_notebook_expose (GtkWidget      *widget,
        * 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]);
+      gtk_style_context_get_background_color (context, 0, &bg_color);
+      gdk_cairo_set_source_rgba (cr, &bg_color);
       cairo_paint (cr);
-      cairo_destroy (cr);
 
-      gdk_drawable_get_size (priv->drag_window,
-                            &area.width, &area.height);
       gtk_notebook_draw_tab (notebook,
                             priv->cur_page,
-                            &area);
-      gtk_container_propagate_expose (GTK_CONTAINER (notebook),
-                                     priv->cur_page->tab_label, event);
+                            cr, 0);
+
+      cairo_restore (cr);
+
+      gtk_container_propagate_draw (GTK_CONTAINER (notebook),
+                                   priv->cur_page->tab_label, cr);
     }
   
   return FALSE;
@@ -2653,8 +2910,8 @@ popup_position_func (GtkMenu  *menu,
   gdk_window_get_origin (gtk_widget_get_window (w), x, y);
 
   gtk_widget_get_allocation (w, &allocation);
-  gtk_size_request_get_size (GTK_SIZE_REQUEST (menu),
-                             &requisition, NULL);
+  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;
@@ -2952,7 +3209,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)
@@ -3033,7 +3291,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;
@@ -3173,8 +3432,8 @@ gtk_notebook_grab_notify (GtkWidget *widget,
 }
 
 static void
-gtk_notebook_state_changed (GtkWidget    *widget,
-                           GtkStateType  previous_state)
+gtk_notebook_state_flags_changed (GtkWidget     *widget,
+                                  GtkStateFlags  previous_state)
 {
   if (!gtk_widget_is_sensitive (widget))
     stop_scrolling (GTK_NOTEBOOK (widget));
@@ -3199,8 +3458,7 @@ gtk_notebook_focus_out (GtkWidget     *widget,
 }
 
 static void
-gtk_notebook_style_set  (GtkWidget *widget,
-                        GtkStyle  *previous)
+gtk_notebook_style_updated (GtkWidget *widget)
 {
   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
   GtkNotebookPrivate *priv = notebook->priv;
@@ -3222,34 +3480,38 @@ gtk_notebook_style_set  (GtkWidget *widget,
   priv->has_after_previous = has_after_previous;
   priv->has_after_next = has_after_next;
 
-  GTK_WIDGET_CLASS (gtk_notebook_parent_class)->style_set (widget, previous);
+  GTK_WIDGET_CLASS (gtk_notebook_parent_class)->style_updated (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;
+  GtkStyleContext *context;
   gint gap_pos;
 
   notebook = GTK_WIDGET (data);
   child = gtk_bin_get_child (GTK_BIN (widget));
+  context = gtk_widget_get_style_context (widget);
+
+  gtk_style_context_save (context);
+  gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB, 0);
 
-  gtk_size_request_get_size (GTK_SIZE_REQUEST (widget),
-                             &requisition, NULL);
+  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),
-                      GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-                      NULL, widget, "tab",
-                      0, 0,
-                      requisition.width, requisition.height,
-                      gap_pos);
+  gtk_render_extension (context, cr, 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);
+
+  gtk_style_context_restore (context);
 
   return TRUE;
 }
@@ -3286,8 +3548,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);
 }
@@ -3323,8 +3585,7 @@ gtk_notebook_create_window (GtkNotebook *notebook,
 static gboolean
 gtk_notebook_drag_failed (GtkWidget      *widget,
                          GdkDragContext *context,
-                         GtkDragResult   result,
-                         gpointer        data)
+                         GtkDragResult   result)
 {
   if (result == GTK_DRAG_RESULT_NO_TARGET)
     {
@@ -3575,13 +3836,16 @@ gtk_notebook_drag_data_get (GtkWidget        *widget,
                            guint             info,
                            guint             time)
 {
-  if (data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
+  GdkAtom target;
+
+  target = gtk_selection_data_get_target (data);
+  if (target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
     {
       GtkNotebook *notebook = GTK_NOTEBOOK (widget);
       GtkNotebookPrivate *priv = notebook->priv;
 
       gtk_selection_data_set (data,
-                             data->target,
+                             target,
                              8,
                              (void*) &priv->detached_tab->child,
                              sizeof (gpointer));
@@ -3605,9 +3869,9 @@ gtk_notebook_drag_data_received (GtkWidget        *widget,
   source_widget = gtk_drag_get_source_widget (context);
 
   if (source_widget &&
-      data->target == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
+      gtk_selection_data_get_target (data) == gdk_atom_intern_static_string ("GTK_NOTEBOOK_TAB"))
     {
-      child = (void*) data->data;
+      child = (void*) gtk_selection_data_get_data (data);
 
       do_detach_tab (GTK_NOTEBOOK (source_widget), notebook, *child, x, y);
       gtk_drag_finish (context, TRUE, FALSE, time);
@@ -4171,6 +4435,40 @@ gtk_notebook_forall (GtkContainer *container,
   }
 }
 
+static GtkWidgetPath *
+gtk_notebook_get_path_for_child (GtkContainer *container,
+                                 GtkWidget    *widget)
+{
+  GtkNotebookPrivate *priv;
+  GtkNotebook *notebook;
+  GtkNotebookPage *page;
+  GtkWidgetPath *path;
+  GtkRegionFlags flags;
+  GList *c;
+
+  path = GTK_CONTAINER_CLASS (gtk_notebook_parent_class)->get_path_for_child (container, widget);
+
+  notebook = GTK_NOTEBOOK (container);
+  priv = notebook->priv;
+
+  for (c = priv->children; c; c = c->next)
+    {
+      page = c->data;
+
+      if (page->tab_label == widget)
+        break;
+    }
+
+  /* Widget is not a tab label */
+  if (!c)
+    return path;
+
+  flags = _gtk_notebook_get_tab_flags (notebook, page);
+  gtk_widget_path_iter_add_region (path, -1, GTK_STYLE_REGION_TAB, flags);
+
+  return path;
+}
+
 static GType
 gtk_notebook_child_type (GtkContainer     *container)
 {
@@ -4329,10 +4627,11 @@ gtk_notebook_redraw_tabs (GtkNotebook *notebook)
   GtkAllocation allocation;
   GtkWidget *widget;
   GtkNotebookPage *page;
-  GtkStyle *style;
+  GtkStyleContext *context;
   GdkRectangle redraw_rect;
   gint border;
   gint tab_pos = get_effective_tab_pos (notebook);
+  GtkBorder padding;
 
   widget = GTK_WIDGET (notebook);
   border = gtk_container_get_border_width (GTK_CONTAINER (notebook));
@@ -4345,38 +4644,40 @@ gtk_notebook_redraw_tabs (GtkNotebook *notebook)
   redraw_rect.x = border;
   redraw_rect.y = border;
 
-  style = gtk_widget_get_style (widget);
   gtk_widget_get_allocation (widget, &allocation);
 
+  context = gtk_widget_get_style_context (widget);
+  gtk_style_context_get_padding (context, 0, &padding);
+
   switch (tab_pos)
     {
     case GTK_POS_BOTTOM:
       redraw_rect.y = allocation.height - border -
-       page->allocation.height - style->ythickness;
+       page->allocation.height - padding.bottom;
 
       if (page != priv->cur_page)
-       redraw_rect.y -= style->ythickness;
+       redraw_rect.y -= padding.bottom;
       /* fall through */
     case GTK_POS_TOP:
       redraw_rect.width = allocation.width - 2 * border;
-      redraw_rect.height = page->allocation.height + style->ythickness;
+      redraw_rect.height = page->allocation.height + padding.top;
 
       if (page != priv->cur_page)
-       redraw_rect.height += style->ythickness;
+       redraw_rect.height += padding.top;
       break;
     case GTK_POS_RIGHT:
       redraw_rect.x = allocation.width - border -
-       page->allocation.width - style->xthickness;
+       page->allocation.width - padding.right;
 
       if (page != priv->cur_page)
-       redraw_rect.x -= style->xthickness;
+       redraw_rect.x -= padding.right;
       /* fall through */
     case GTK_POS_LEFT:
-      redraw_rect.width = page->allocation.width + style->xthickness;
+      redraw_rect.width = page->allocation.width + padding.left;
       redraw_rect.height = allocation.height - 2 * border;
 
       if (page != priv->cur_page)
-       redraw_rect.width += style->xthickness;
+       redraw_rect.width += padding.left;
       break;
     }
 
@@ -4502,7 +4803,7 @@ gtk_notebook_remove_tab_label (GtkNotebook     *notebook,
                                     page->mnemonic_activate_signal);
       page->mnemonic_activate_signal = 0;
 
-      gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
+      gtk_widget_set_state_flags (page->tab_label, 0, TRUE);
       gtk_widget_unparent (page->tab_label);
       page->tab_label = NULL;
     }
@@ -4517,10 +4818,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)
@@ -4637,7 +4937,7 @@ gtk_notebook_update_labels (GtkNotebook *notebook)
          else
            gtk_label_set_text (GTK_LABEL (page->menu_label), string);
        }
-    }  
+    }
 }
 
 static gint
@@ -4737,7 +5037,7 @@ gtk_notebook_search_page (GtkNotebook *notebook,
  */
 static void
 gtk_notebook_paint (GtkWidget    *widget,
-                   GdkRectangle *area)
+                   cairo_t      *cr)
 {
   GtkNotebook *notebook;
   GtkNotebookPrivate *priv;
@@ -4751,11 +5051,16 @@ gtk_notebook_paint (GtkWidget    *widget,
   gint gap_x = 0, gap_width = 0, step = STEP_PREV;
   gboolean is_rtl;
   gint tab_pos;
-   
+  GtkStyleContext *context;
+  GtkRegionFlags tab_flags;
+  gboolean has_pack_start, has_pack_end;
+
   notebook = GTK_NOTEBOOK (widget);
   priv = notebook->priv;
   is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
   tab_pos = get_effective_tab_pos (notebook);
+  context = gtk_widget_get_style_context (widget);
+  showarrow = has_pack_start = has_pack_end = FALSE;
 
   if ((!priv->show_tabs && !priv->show_border) ||
       !priv->cur_page || !gtk_widget_get_visible (priv->cur_page->child))
@@ -4770,11 +5075,10 @@ 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_STATE_NORMAL, GTK_SHADOW_OUT,
-                    area, widget, "notebook",
-                    x, y, width, height);
+      gtk_render_background (context, cr,
+                             x, y, width, height);
+      gtk_render_frame (context, cr,
+                        x, y, width, height);
       return;
     }
 
@@ -4820,7 +5124,7 @@ gtk_notebook_paint (GtkWidget    *widget,
            gap_x = priv->cur_page->allocation.x - allocation.x - border_width;
 
          gap_width = priv->cur_page->allocation.width;
-         step = is_rtl ? STEP_NEXT : STEP_PREV;
+         step = is_rtl ? STEP_PREV : STEP_NEXT;
          break;
        case GTK_POS_LEFT:
        case GTK_POS_RIGHT:
@@ -4834,52 +5138,124 @@ gtk_notebook_paint (GtkWidget    *widget,
          break;
        }
     }
-  gtk_paint_box_gap (gtk_widget_get_style (widget),
-                     gtk_widget_get_window (widget),
-                    GTK_STATE_NORMAL, GTK_SHADOW_OUT,
-                    area, widget, "notebook",
-                    x, y, width, height,
-                    tab_pos, gap_x, gap_width);
 
-  showarrow = FALSE;
+  for (children = priv->children; children; children = children->next)
+    {
+      page = children->data;
+
+      if (!gtk_widget_get_visible (page->child))
+        continue;
+
+      if (page->pack == GTK_PACK_START)
+        has_pack_start = TRUE;
+      else
+        has_pack_end = TRUE;
+
+      if (!gtk_widget_get_mapped (page->tab_label))
+        showarrow = TRUE;
+
+      /* No point in keeping searching */
+      if (has_pack_start && has_pack_end && showarrow)
+        break;
+    }
+
+  gtk_style_context_save (context);
+
+  if (!showarrow || !priv->scrollable)
+    {
+      GtkJunctionSides junction = 0;
+
+      /* Apply junction sides, if no arrows are shown,
+       * then make corners with connecting tabs square.
+       */
+      switch (tab_pos)
+        {
+        case GTK_POS_TOP:
+          if (has_pack_start)
+            junction |= (is_rtl) ? GTK_JUNCTION_CORNER_TOPRIGHT : GTK_JUNCTION_CORNER_TOPLEFT;
+
+          if (has_pack_end)
+            junction |= (is_rtl) ? GTK_JUNCTION_CORNER_TOPLEFT : GTK_JUNCTION_CORNER_TOPRIGHT;
+          break;
+        case GTK_POS_BOTTOM:
+          if (has_pack_start)
+            junction |= (is_rtl) ? GTK_JUNCTION_CORNER_BOTTOMRIGHT : GTK_JUNCTION_CORNER_BOTTOMLEFT;
+
+          if (has_pack_end)
+            junction |= (is_rtl) ? GTK_JUNCTION_CORNER_BOTTOMLEFT : GTK_JUNCTION_CORNER_BOTTOMRIGHT;
+          break;
+        case GTK_POS_LEFT:
+          if (has_pack_start)
+            junction |= GTK_JUNCTION_CORNER_TOPLEFT;
+
+          if (has_pack_end)
+            junction |= GTK_JUNCTION_CORNER_BOTTOMLEFT;
+          break;
+        case GTK_POS_RIGHT:
+          if (has_pack_start)
+            junction |= GTK_JUNCTION_CORNER_TOPRIGHT;
+
+          if (has_pack_end)
+            junction |= GTK_JUNCTION_CORNER_BOTTOMRIGHT;
+          break;
+        }
+
+      gtk_style_context_set_junction_sides (context, junction);
+    }
+
+  gtk_render_background (context, cr,
+                         x, y, width, height);
+  gtk_render_frame_gap (context, cr,
+                        x, y, width, height,
+                        tab_pos, gap_x, gap_x + gap_width);
+
+  gtk_style_context_restore (context);
+
   children = gtk_notebook_search_page (notebook, NULL, step, TRUE);
+
   while (children)
     {
       page = children->data;
       children = gtk_notebook_search_page (notebook, children,
                                           step, TRUE);
-      if (!gtk_widget_get_visible (page->child))
+      if (!gtk_widget_get_visible (page->child) ||
+          !gtk_widget_get_mapped (page->tab_label))
        continue;
-      if (!gtk_widget_get_mapped (page->tab_label))
-       showarrow = TRUE;
-      else if (page != priv->cur_page)
-       gtk_notebook_draw_tab (notebook, page, area);
+
+      tab_flags = _gtk_notebook_get_tab_flags (notebook, page);
+      gtk_notebook_draw_tab (notebook, page, cr, tab_flags);
     }
 
   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);
+    }
+
+  if (priv->operation != DRAG_OPERATION_REORDER)
+    {
+      tab_flags = _gtk_notebook_get_tab_flags (notebook, priv->cur_page);
+      gtk_notebook_draw_tab (notebook, priv->cur_page, cr, tab_flags);
     }
-  gtk_notebook_draw_tab (notebook, priv->cur_page, area);
 }
 
 static void
 gtk_notebook_draw_tab (GtkNotebook     *notebook,
                       GtkNotebookPage *page,
-                      GdkRectangle    *area)
+                      cairo_t         *cr,
+                       GtkRegionFlags   flags)
 {
   GtkNotebookPrivate *priv;
-  GtkStateType state_type;
-  GdkWindow *window;
+  GtkStateFlags state = 0;
   GtkWidget *widget;
-  
+  GtkStyleContext *context;
+
   if (!NOTEBOOK_IS_TAB_LABEL_PARENT (notebook, page) ||
       !gtk_widget_get_mapped (page->tab_label) ||
       (page->allocation.width == 0) || (page->allocation.height == 0))
@@ -4888,19 +5264,15 @@ 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;
+    state = GTK_STATE_FLAG_ACTIVE;
+
+  context = gtk_widget_get_style_context (widget);
+  gtk_style_context_save (context);
+  gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB, flags);
+  gtk_style_context_set_state (context, state);
 
-  gtk_paint_extension (gtk_widget_get_style (widget), window,
-                       state_type, GTK_SHADOW_OUT,
-                       area, widget, "tab",
+  gtk_render_extension (context, cr,
                        page->allocation.x,
                        page->allocation.y,
                        page->allocation.width,
@@ -4916,87 +5288,81 @@ gtk_notebook_draw_tab (GtkNotebook     *notebook,
       gtk_widget_get_allocation (page->tab_label, &allocation);
       gtk_widget_style_get (widget, "focus-line-width", &focus_width, NULL);
 
-      gtk_paint_focus (gtk_widget_get_style (widget), window, 
-                       gtk_widget_get_state (widget), area, widget, "tab",
-                       allocation.x - focus_width,
-                       allocation.y - focus_width,
-                       allocation.width + 2 * focus_width,
-                       allocation.height + 2 * focus_width);
+      gtk_render_focus (context, cr,
+                        allocation.x - focus_width,
+                        allocation.y - focus_width,
+                        allocation.width + 2 * focus_width,
+                        allocation.height + 2 * focus_width);
     }
+
+  gtk_style_context_restore (context);
 }
 
 static void
 gtk_notebook_draw_arrow (GtkNotebook      *notebook,
+                         cairo_t          *cr,
                         GtkNotebookArrow  nbarrow)
 {
   GtkNotebookPrivate *priv = notebook->priv;
-  GtkStateType state_type;
-  GtkShadowType shadow_type;
+  GtkStyleContext *context;
+  GtkStateFlags state = 0;
   GtkWidget *widget;
   GdkRectangle arrow_rect;
-  GtkArrowType arrow;
   gboolean is_rtl, left;
+  gint scroll_arrow_hlength;
+  gint scroll_arrow_vlength;
+  gint arrow_size;
+  gdouble angle;
 
   widget = GTK_WIDGET (notebook);
+  context = gtk_widget_get_style_context (widget);
 
-  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); 
+  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);
+  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)
-            state_type = GTK_STATE_ACTIVE;
-          else
-            state_type = GTK_STATE_PRELIGHT;
-        }
-      else
-        state_type = gtk_widget_get_state (widget);
+  if (priv->in_child == nbarrow)
+    {
+      state |= GTK_STATE_FLAG_PRELIGHT;
 
       if (priv->click_child == nbarrow)
-        shadow_type = GTK_SHADOW_IN;
-      else
-        shadow_type = GTK_SHADOW_OUT;
+        state |= GTK_STATE_FLAG_ACTIVE;
+    }
+  else
+    state = gtk_widget_get_state_flags (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->focus_tab &&
+      !gtk_notebook_search_page (notebook, priv->focus_tab,
+                                 left ? STEP_PREV : STEP_NEXT, TRUE))
+    state = GTK_STATE_FLAG_INSENSITIVE;
 
-      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->tab_pos == GTK_POS_LEFT ||
+      priv->tab_pos == GTK_POS_RIGHT)
+    {
+      angle = (ARROW_IS_LEFT (nbarrow)) ? 0 : G_PI;
+      arrow_size = scroll_arrow_vlength;
+    }
+  else
+    {
+      angle = (ARROW_IS_LEFT (nbarrow)) ? 3 * (G_PI / 2) : G_PI / 2;
+      arrow_size = scroll_arrow_hlength;
     }
+
+  gtk_style_context_save (context);
+  gtk_style_context_set_state (context, state);
+
+  gtk_render_arrow (context, cr, angle,
+                    arrow_rect.x, arrow_rect.y,
+                    arrow_size);
+
+  gtk_style_context_restore (context);
 }
 
 /* Private GtkNotebook Size Allocate Functions:
@@ -5018,7 +5384,7 @@ gtk_notebook_tab_space (GtkNotebook *notebook,
   GtkNotebookPrivate *priv = notebook->priv;
   GtkAllocation allocation, action_allocation;
   GtkWidget *widget;
-  GtkStyle *style;
+  GtkStyleContext *context;
   GList *children;
   gint tab_pos = get_effective_tab_pos (notebook);
   gint tab_overlap;
@@ -5028,12 +5394,13 @@ gtk_notebook_tab_space (GtkNotebook *notebook,
   gboolean is_rtl;
   gint i;
   guint border_width;
+  GtkBorder padding;
 
   widget = GTK_WIDGET (notebook);
   children = priv->children;
   is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
 
-  style = gtk_widget_get_style (widget);
+  context = gtk_widget_get_style_context (widget);
 
   gtk_widget_style_get (GTK_WIDGET (notebook),
                         "arrow-spacing", &arrow_spacing,
@@ -5042,6 +5409,7 @@ gtk_notebook_tab_space (GtkNotebook *notebook,
                         NULL);
 
   border_width = gtk_container_get_border_width (GTK_CONTAINER (notebook));
+  gtk_style_context_get_padding (context, 0, &padding);
 
   gtk_widget_get_allocation (widget, &allocation);
 
@@ -5060,9 +5428,9 @@ gtk_notebook_tab_space (GtkNotebook *notebook,
 
               if ((i == ACTION_WIDGET_START && !is_rtl) ||
                   (i == ACTION_WIDGET_END && is_rtl))
-                *min += action_allocation.width + style->xthickness;
+                *min += action_allocation.width + padding.left;
               else
-                *max -= action_allocation.width + style->xthickness;
+                *max -= action_allocation.width + padding.right;
             }
         }
 
@@ -5090,9 +5458,9 @@ gtk_notebook_tab_space (GtkNotebook *notebook,
               gtk_widget_get_allocation (priv->action_widget[i], &action_allocation);
 
               if (i == ACTION_WIDGET_START)
-                *min += action_allocation.height + style->ythickness;
+                *min += action_allocation.height + padding.top;
               else
-                *max -= action_allocation.height + style->ythickness;
+                *max -= action_allocation.height + padding.bottom;
             }
         }
 
@@ -5352,9 +5720,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,
@@ -5370,7 +5743,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)++;
        }
 
@@ -5422,14 +5796,15 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
   GtkWidget *widget;
   GtkContainer *container;
   GtkNotebookPage *page;
-  GtkStyle *style;
+  GtkStyleContext *context;
   gboolean allocate_at_bottom;
   gint tab_overlap, tab_pos, tab_extra_space;
   gint left_x, right_x, top_y, bottom_y, anchor;
-  gint xthickness, ythickness;
   guint border_width;
   gboolean gap_left, packing_changed;
   GtkAllocation child_allocation = { 0, };
+  GtkOrientation tab_expand_orientation;
+  GtkBorder padding;
 
   widget = GTK_WIDGET (notebook);
   container = GTK_CONTAINER (notebook);
@@ -5444,9 +5819,7 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
   child_allocation.x = allocation.x + border_width;
   child_allocation.y = allocation.y + border_width;
 
-  style = gtk_widget_get_style (widget);
-  xthickness = style->xthickness;
-  ythickness = style->ythickness;
+  context = gtk_widget_get_style_context (widget);
 
   switch (tab_pos)
     {
@@ -5479,10 +5852,21 @@ 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;
+
+  gtk_style_context_save (context);
+
   while (*children && *children != last_child)
     {
       page = (*children)->data;
 
+      gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB,
+                                    _gtk_notebook_get_tab_flags (notebook, page));
+      gtk_style_context_get_padding (context, 0, &padding);
+
       if (direction == STEP_NEXT && page->pack != GTK_PACK_START)
        {
          if (!showarrow)
@@ -5505,7 +5889,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;
@@ -5634,16 +6018,16 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
          switch (tab_pos)
            {
            case GTK_POS_TOP:
-             page->allocation.y += ythickness;
+             page->allocation.y += padding.top;
              /* fall through */
            case GTK_POS_BOTTOM:
-             page->allocation.height = MAX (1, page->allocation.height - ythickness);
+             page->allocation.height = MAX (1, page->allocation.height - padding.top);
              break;
            case GTK_POS_LEFT:
-             page->allocation.x += xthickness;
+             page->allocation.x += padding.left;
              /* fall through */
            case GTK_POS_RIGHT:
-             page->allocation.width = MAX (1, page->allocation.width - xthickness);
+             page->allocation.width = MAX (1, page->allocation.width - padding.left);
              break;
            }
        }
@@ -5710,6 +6094,8 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
        gtk_widget_set_child_visible (page->tab_label, TRUE);
     }
 
+  gtk_style_context_restore (context);
+
   /* Don't move the current tab past the last position during tabs reordering */
   if (children &&
       priv->operation == DRAG_OPERATION_REORDER &&
@@ -5800,15 +6186,14 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
   GtkNotebookPrivate *priv = notebook->priv;
   GtkAllocation child_allocation, label_allocation;
   GtkRequisition tab_requisition;
-  GtkStyle *style;
-  gint xthickness;
-  gint ythickness;
+  GtkStyleContext *context;
   gint padding;
   gint focus_width;
   gint tab_curvature;
   gint tab_pos = get_effective_tab_pos (notebook);
   gboolean tab_allocation_changed;
   gboolean was_visible = page->tab_allocated_visible;
+  GtkBorder tab_padding;
 
   if (!page->tab_label ||
       !gtk_widget_get_visible (page->tab_label) ||
@@ -5818,12 +6203,15 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
       return was_visible;
     }
 
-  style = gtk_widget_get_style (widget);
-  xthickness = style->xthickness;
-  ythickness = style->ythickness;
+  context = gtk_widget_get_style_context (widget);
 
-  gtk_size_request_get_size (GTK_SIZE_REQUEST (page->tab_label),
-                             &tab_requisition, NULL);
+  gtk_style_context_save (context);
+  gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB,
+                                _gtk_notebook_get_tab_flags (notebook, page));
+
+  gtk_style_context_get_padding (context, 0, &tab_padding);
+
+  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,
@@ -5835,8 +6223,10 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
       padding = tab_curvature + focus_width + priv->tab_hborder;
       if (page->fill)
        {
-         child_allocation.x = xthickness + focus_width + priv->tab_hborder;
-         child_allocation.width = MAX (1, page->allocation.width - 2 * child_allocation.x);
+         child_allocation.x = tab_padding.left + focus_width + priv->tab_hborder;
+         child_allocation.width = MAX (1, (page->allocation.width -
+                                            tab_padding.left - tab_padding.right -
+                                            2 * (focus_width + priv->tab_hborder)));
          child_allocation.x += page->allocation.x;
        }
       else
@@ -5850,9 +6240,10 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
       child_allocation.y = priv->tab_vborder + focus_width + page->allocation.y;
 
       if (tab_pos == GTK_POS_TOP)
-       child_allocation.y += ythickness;
+       child_allocation.y += tab_padding.top;
 
-      child_allocation.height = MAX (1, (page->allocation.height - ythickness -
+      child_allocation.height = MAX (1, (page->allocation.height -
+                                         tab_padding.top - tab_padding.bottom -
                                         2 * (priv->tab_vborder + focus_width)));
       break;
     case GTK_POS_LEFT:
@@ -5860,9 +6251,10 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
       padding = tab_curvature + focus_width + priv->tab_vborder;
       if (page->fill)
        {
-         child_allocation.y = ythickness + padding;
+         child_allocation.y = tab_padding.top + padding;
          child_allocation.height = MAX (1, (page->allocation.height -
-                                            2 * child_allocation.y));
+                                             tab_padding.bottom - tab_padding.top -
+                                             2 * padding));
          child_allocation.y += page->allocation.y;
        }
       else
@@ -5876,9 +6268,9 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
       child_allocation.x = priv->tab_hborder + focus_width + page->allocation.x;
 
       if (tab_pos == GTK_POS_LEFT)
-       child_allocation.x += xthickness;
+       child_allocation.x += tab_padding.left;
 
-      child_allocation.width = MAX (1, (page->allocation.width - xthickness -
+      child_allocation.width = MAX (1, (page->allocation.width - tab_padding.right -
                                        2 * (priv->tab_hborder + focus_width)));
       break;
     }
@@ -5897,6 +6289,8 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
       tab_allocation_changed = TRUE;
     }
 
+  gtk_style_context_restore (context);
+
   return tab_allocation_changed;
 }
 
@@ -6023,9 +6417,11 @@ gtk_notebook_update_tab_states (GtkNotebook *notebook)
       if (page->tab_label)
        {
          if (page == priv->cur_page)
-           gtk_widget_set_state (page->tab_label, GTK_STATE_NORMAL);
-         else
-           gtk_widget_set_state (page->tab_label, GTK_STATE_ACTIVE);
+            gtk_widget_set_state_flags (page->tab_label, GTK_STATE_FLAG_ACTIVE, TRUE);
+          else
+            gtk_widget_set_state_flags (page->tab_label, 0, TRUE);
+
+          gtk_widget_reset_style (page->tab_label);
        }
     }
 }
@@ -7547,7 +7943,8 @@ gtk_notebook_reorder_child (GtkNotebook *notebook,
 /**
  * gtk_notebook_set_group_name:
  * @notebook: a #GtkNotebook
- * @name: (allow-none): the name of 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 name for @notebook.
  *
@@ -7715,8 +8112,8 @@ gtk_notebook_get_tab_detachable (GtkNotebook *notebook,
  *    GtkWidget **child;
  *    
  *    notebook = gtk_drag_get_source_widget (context);
- *    child = (void*) selection_data->data;
- *    
+ *    child = (void*) gtk_selection_data_get_data (selection_data);
+ *
  *    process_widget (*child);
  *    gtk_container_remove (GTK_CONTAINER (notebook), *child);
  *  }