]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtknotebook.c
filechooserbutton: New test for opening the Other item in the combo box and then...
[~andy/gtk] / gtk / gtknotebook.c
index 2d4530c5c2030c37990e975bc632a96605ada474..5f0ce009a8a72123c2ff8dc185c1e7b4c492a163 100644 (file)
@@ -13,9 +13,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 /*
@@ -43,6 +41,9 @@
 #include "gtkdnd.h"
 #include "gtkbuildable.h"
 #include "gtktypebuiltins.h"
+#include "gtkwidgetpath.h"
+#include "gtkwidgetprivate.h"
+#include "a11y/gtknotebookaccessible.h"
 
 
 /**
@@ -149,9 +150,7 @@ struct _GtkNotebookPrivate
 
   guint          dnd_timer;
   guint          switch_tab_timer;
-
-  guint16        tab_hborder;
-  guint16        tab_vborder;
+  GList         *switch_tab;
 
   guint32        timer;
   guint32        timestamp;
@@ -163,8 +162,6 @@ struct _GtkNotebookPrivate
   guint          during_reorder     : 1;
   guint          focus_out          : 1; /* Flag used by ::move-focus-out implementation */
   guint          has_scrolled       : 1;
-  guint          have_visible_child : 1;
-  guint          homogeneous        : 1;
   guint          in_child           : 3;
   guint          need_timer         : 1;
   guint          show_border        : 1;
@@ -326,14 +323,22 @@ 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_get_preferred_width_for_height
+                                             (GtkWidget        *widget,
+                                              gint              height,
+                                              gint             *minimum,
+                                              gint             *natural);
+static void gtk_notebook_get_preferred_height_for_width
+                                             (GtkWidget        *widget,
+                                              gint              width,
+                                              gint             *minimum,
+                                              gint             *natural);
 static void gtk_notebook_size_allocate       (GtkWidget        *widget,
                                               GtkAllocation    *allocation);
 static gint gtk_notebook_draw                (GtkWidget        *widget,
@@ -432,6 +437,7 @@ static GtkNotebook *gtk_notebook_create_window (GtkNotebook    *notebook,
 
 /*** GtkNotebook Private Functions ***/
 static void gtk_notebook_redraw_tabs         (GtkNotebook      *notebook);
+static void gtk_notebook_redraw_tabs_junction (GtkNotebook     *notebook);
 static void gtk_notebook_redraw_arrows       (GtkNotebook      *notebook);
 static void gtk_notebook_real_remove         (GtkNotebook      *notebook,
                                               GList            *list);
@@ -456,7 +462,7 @@ static void gtk_notebook_paint               (GtkWidget        *widget,
 static void gtk_notebook_draw_tab            (GtkNotebook      *notebook,
                                               GtkNotebookPage  *page,
                                               cairo_t          *cr,
-                                              GtkRegionFlags    flags);
+                                              gboolean          use_flags);
 static void gtk_notebook_draw_arrow          (GtkNotebook      *notebook,
                                               cairo_t          *cr,
                                               GtkNotebookArrow  arrow);
@@ -637,6 +643,8 @@ gtk_notebook_class_init (GtkNotebookClass *class)
   widget_class->unrealize = gtk_notebook_unrealize;
   widget_class->get_preferred_width = gtk_notebook_get_preferred_width;
   widget_class->get_preferred_height = gtk_notebook_get_preferred_height;
+  widget_class->get_preferred_width_for_height = gtk_notebook_get_preferred_width_for_height;
+  widget_class->get_preferred_height_for_width = gtk_notebook_get_preferred_height_for_width;
   widget_class->size_allocate = gtk_notebook_size_allocate;
   widget_class->draw = gtk_notebook_draw;
   widget_class->button_press_event = gtk_notebook_button_press;
@@ -1062,7 +1070,7 @@ gtk_notebook_class_init (GtkNotebookClass *class)
    * a notebook where the tab will be attached. It is also
    * responsible for moving/resizing the window and adding the
    * necessary properties to the notebook (e.g. the
-   * #GtkNotebook:group ).
+   * #GtkNotebook:group-name ).
    *
    * Returns: (transfer none): a #GtkNotebook that @page should be
    *     added to, or %NULL.
@@ -1142,6 +1150,8 @@ gtk_notebook_class_init (GtkNotebookClass *class)
   add_tab_bindings (binding_set, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_DIR_TAB_BACKWARD);
 
   g_type_class_add_private (class, sizeof (GtkNotebookPrivate));
+
+  gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_NOTEBOOK_ACCESSIBLE);
 }
 
 static void
@@ -1165,9 +1175,6 @@ gtk_notebook_init (GtkNotebook *notebook)
   priv->event_window = NULL;
   priv->menu = NULL;
 
-  priv->tab_hborder = 2;
-  priv->tab_vborder = 2;
-
   priv->show_tabs = TRUE;
   priv->show_border = TRUE;
   priv->tab_pos = GTK_POS_TOP;
@@ -1177,7 +1184,6 @@ gtk_notebook_init (GtkNotebook *notebook)
   priv->button = 0;
   priv->need_timer = 0;
   priv->child_has_focus = FALSE;
-  priv->have_visible_child = FALSE;
   priv->focus_out = FALSE;
 
   priv->has_before_previous = 1;
@@ -1669,12 +1675,36 @@ gtk_notebook_get_property (GObject         *object,
  * gtk_notebook_drag_data_get
  * gtk_notebook_drag_data_received
  */
+static void
+remove_switch_tab_timer (GtkNotebook *notebook)
+{
+  GtkNotebookPrivate *priv = notebook->priv;
+
+  if (priv->switch_tab_timer)
+    {
+      g_source_remove (priv->switch_tab_timer);
+      priv->switch_tab_timer = 0;
+    }
+}
+
 static void
 gtk_notebook_destroy (GtkWidget *widget)
 {
   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
   GtkNotebookPrivate *priv = notebook->priv;
 
+  if (priv->action_widget[GTK_PACK_START])
+    {
+      gtk_widget_unparent (priv->action_widget[GTK_PACK_START]);
+      priv->action_widget[GTK_PACK_START] = NULL;
+    }
+
+  if (priv->action_widget[GTK_PACK_END])
+    {
+      gtk_widget_unparent (priv->action_widget[GTK_PACK_END]);
+      priv->action_widget[GTK_PACK_END] = NULL;
+    }
+
   if (priv->menu)
     gtk_notebook_popup_disable (notebook);
 
@@ -1684,11 +1714,7 @@ gtk_notebook_destroy (GtkWidget *widget)
       priv->source_targets = NULL;
     }
 
-  if (priv->switch_tab_timer)
-    {
-      g_source_remove (priv->switch_tab_timer);
-      priv->switch_tab_timer = 0;
-    }
+  remove_switch_tab_timer (notebook);
 
   GTK_WIDGET_CLASS (gtk_notebook_parent_class)->destroy (widget);
 }
@@ -1882,7 +1908,7 @@ gtk_notebook_realize (GtkWidget *widget)
 
   priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
                                            &attributes, attributes_mask);
-  gdk_window_set_user_data (priv->event_window, notebook);
+  gtk_widget_register_window (widget, priv->event_window);
 }
 
 static void
@@ -1891,13 +1917,13 @@ gtk_notebook_unrealize (GtkWidget *widget)
   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
   GtkNotebookPrivate *priv = notebook->priv;
 
-  gdk_window_set_user_data (priv->event_window, NULL);
+  gtk_widget_unregister_window (widget, priv->event_window);
   gdk_window_destroy (priv->event_window);
   priv->event_window = NULL;
 
   if (priv->drag_window)
     {
-      gdk_window_set_user_data (priv->drag_window, NULL);
+      gtk_widget_unregister_window (widget, priv->drag_window);
       gdk_window_destroy (priv->drag_window);
       priv->drag_window = NULL;
     }
@@ -1950,30 +1976,83 @@ _gtk_notebook_get_tab_flags (GtkNotebook     *notebook,
   return flags;
 }
 
+static GtkStateFlags
+notebook_tab_prepare_style_context (GtkNotebook *notebook,
+                                    GtkNotebookPage *page,
+                                    GtkStyleContext *context,
+                                    gboolean use_flags)
+{
+  gint tab_pos = get_effective_tab_pos (notebook);
+  GtkRegionFlags flags = 0;
+  GtkStateFlags state = gtk_style_context_get_state (context);
+
+  if (page != NULL &&
+      page == notebook->priv->cur_page)
+    state |= GTK_STATE_FLAG_ACTIVE;
+
+  gtk_style_context_set_state (context, state);
+
+  if (use_flags && (page != NULL))
+    flags = _gtk_notebook_get_tab_flags (notebook, page);
+
+  gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB, flags);
+
+  switch (tab_pos)
+    {
+    case GTK_POS_TOP:
+      gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP);
+      break;
+    case GTK_POS_BOTTOM:
+      gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM);
+      break;
+    case GTK_POS_LEFT:
+      gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
+      break;
+    case GTK_POS_RIGHT:
+      gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
+      break;
+    default:
+      break;
+    }
+
+  return state;
+}
+
 static void
-gtk_notebook_size_request (GtkWidget      *widget,
-                           GtkRequisition *requisition)
+gtk_notebook_get_preferred_tabs_size (GtkNotebook    *notebook,
+                                      GtkRequisition *requisition)
 {
-  GtkNotebook *notebook = GTK_NOTEBOOK (widget);
-  GtkNotebookPrivate *priv = notebook->priv;
-  GtkNotebookPage *page;
+  GtkNotebookPrivate *priv;
+  GtkWidget *widget;
+  gint tab_width = 0;
+  gint tab_height = 0;
+  gint tab_max = 0;
+  gint padding;
+  gint i;
+  gint action_width = 0;
+  gint action_height = 0;
+  guint vis_pages = 0;
   GList *children;
-  GtkRequisition child_requisition;
+  GtkNotebookPage *page;
   GtkRequisition action_widget_requisition[2] = { { 0 }, { 0 } };
-  gboolean switch_page = FALSE;
-  gint vis_pages;
+  GtkRequisition child_requisition;
+  GtkStyleContext *context;
   gint focus_width;
   gint focus_pad;
   gint tab_overlap;
   gint tab_curvature;
   gint arrow_spacing;
+  gint initial_gap;
   gint scroll_arrow_hlength;
   gint scroll_arrow_vlength;
-  guint border_width;
 
+  priv = notebook->priv;
+  widget = GTK_WIDGET (notebook);
+  context = gtk_widget_get_style_context (widget);
   gtk_widget_style_get (widget,
                         "focus-line-width", &focus_width,
                         "focus-padding", &focus_pad,
+                        "initial-gap", &initial_gap,
                         "tab-overlap", &tab_overlap,
                         "tab-curvature", &tab_curvature,
                         "arrow-spacing", &arrow_spacing,
@@ -1981,236 +2060,304 @@ gtk_notebook_size_request (GtkWidget      *widget,
                         "scroll-arrow-vlength", &scroll_arrow_vlength,
                         NULL);
 
-  requisition->width = 0;
-  requisition->height = 0;
-
-  for (children = priv->children, vis_pages = 0; children;
+  for (children = priv->children; children;
        children = children->next)
     {
-      GtkWidget *parent;
       page = children->data;
 
       if (gtk_widget_get_visible (page->child))
         {
+          GtkBorder tab_padding;
+          GtkStateFlags state;
+
           vis_pages++;
-          gtk_widget_get_preferred_size (page->child,
+
+          if (!gtk_widget_get_visible (page->tab_label))
+            gtk_widget_show (page->tab_label);
+
+          gtk_widget_get_preferred_size (page->tab_label,
                                          &child_requisition, NULL);
 
-          requisition->width = MAX (requisition->width,
-                                           child_requisition.width);
-          requisition->height = MAX (requisition->height,
-                                            child_requisition.height);
+          /* Get border/padding for tab */
+          gtk_style_context_save (context);
+          state = notebook_tab_prepare_style_context (notebook, page, context, TRUE);
+          gtk_style_context_get_padding (context, state, &tab_padding);
+          gtk_style_context_restore (context);
 
-          if (priv->menu && page->menu_label)
-            {
-              parent = gtk_widget_get_parent (page->menu_label);
-              if (parent && !gtk_widget_get_visible (parent))
-                gtk_widget_show (parent);
-            }
-        }
-      else
-        {
-          if (page == priv->cur_page)
-            switch_page = TRUE;
+          page->requisition.width = child_requisition.width +
+            tab_padding.left + tab_padding.right + 2 * (focus_width + focus_pad);
 
-          if (priv->menu && page->menu_label)
+          page->requisition.height = child_requisition.height +
+            tab_padding.top + tab_padding.bottom + 2 * (focus_width + focus_pad);
+
+          switch (priv->tab_pos)
             {
-              parent = gtk_widget_get_parent (page->menu_label);
-              if (parent && gtk_widget_get_visible (parent))
-                gtk_widget_hide (parent);
+            case GTK_POS_TOP:
+            case GTK_POS_BOTTOM:
+              tab_height = MAX (tab_height, page->requisition.height);
+              tab_max = MAX (tab_max, page->requisition.width);
+              break;
+            case GTK_POS_LEFT:
+            case GTK_POS_RIGHT:
+              tab_width = MAX (tab_width, page->requisition.width);
+              tab_max = MAX (tab_max, page->requisition.height);
+              break;
             }
         }
+      else if (gtk_widget_get_visible (page->tab_label))
+        gtk_widget_hide (page->tab_label);
     }
 
-  if (priv->show_border || priv->show_tabs)
+  children = priv->children;
+
+  if (vis_pages)
     {
-      GtkStyleContext *context;
-      GtkBorder notebook_padding;
+      for (i = 0; i < N_ACTION_WIDGETS; i++)
+        {
+          if (priv->action_widget[i])
+            {
+              gtk_widget_get_preferred_size (priv->action_widget[i],
+                                             &action_widget_requisition[i], NULL);
+            }
+        }
 
-      context = gtk_widget_get_style_context (widget);
-      gtk_style_context_get_padding (context, 0, &notebook_padding);
+      switch (priv->tab_pos)
+        {
+        case GTK_POS_TOP:
+        case GTK_POS_BOTTOM:
+          if (tab_height == 0)
+            break;
 
-      requisition->width += notebook_padding.left + notebook_padding.right;
-      requisition->height += notebook_padding.top + notebook_padding.bottom;
+          if (priv->scrollable)
+            tab_height = MAX (tab_height, scroll_arrow_hlength);
 
-      if (priv->show_tabs)
-        {
-          gint tab_width = 0;
-          gint tab_height = 0;
-          gint tab_max = 0;
-          gint padding;
-          gint i;
-          gint action_width = 0;
-          gint action_height = 0;
+          tab_height = MAX (tab_height, action_widget_requisition[ACTION_WIDGET_START].height);
+          tab_height = MAX (tab_height, action_widget_requisition[ACTION_WIDGET_END].height);
 
-          for (children = priv->children; children;
-               children = children->next)
+          padding = 2 * tab_curvature - tab_overlap;
+          tab_max += padding;
+          while (children)
             {
               page = children->data;
+              children = children->next;
 
-              if (gtk_widget_get_visible (page->child))
-                {
-                  GtkBorder tab_padding;
+              if (!gtk_widget_get_visible (page->child))
+                continue;
 
-                  if (!gtk_widget_get_visible (page->tab_label))
-                    gtk_widget_show (page->tab_label);
+              page->requisition.width += padding;
 
-                  gtk_widget_get_preferred_size (page->tab_label,
-                                                 &child_requisition, NULL);
+              tab_width += page->requisition.width;
+              page->requisition.height = tab_height;
+            }
 
-                  /* 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);
+          if (priv->scrollable)
+            tab_width = MIN (tab_width,
+                             tab_max + 2 * (scroll_arrow_hlength + arrow_spacing));
 
-                  page->requisition.width = child_requisition.width +
-                    tab_padding.left + tab_padding.right + 2 * (focus_width + focus_pad);
+          action_width += action_widget_requisition[ACTION_WIDGET_START].width;
+          action_width += action_widget_requisition[ACTION_WIDGET_END].width;
+          requisition->width = tab_width + tab_overlap + action_width + initial_gap;
 
-                  page->requisition.height = child_requisition.height +
-                    tab_padding.top + tab_padding.bottom + 2 * (focus_width + focus_pad);
+          requisition->height = tab_height;
+          break;
+        case GTK_POS_LEFT:
+        case GTK_POS_RIGHT:
+          if (tab_width == 0)
+            break;
 
-                  switch (priv->tab_pos)
-                    {
-                    case GTK_POS_TOP:
-                    case GTK_POS_BOTTOM:
-                      page->requisition.height += 2 * priv->tab_vborder;
-                      tab_height = MAX (tab_height, page->requisition.height);
-                      tab_max = MAX (tab_max, page->requisition.width);
-                      break;
-                    case GTK_POS_LEFT:
-                    case GTK_POS_RIGHT:
-                      page->requisition.width += 2 * priv->tab_hborder;
-                      tab_width = MAX (tab_width, page->requisition.width);
-                      tab_max = MAX (tab_max, page->requisition.height);
-                      break;
-                    }
-                }
-              else if (gtk_widget_get_visible (page->tab_label))
-                gtk_widget_hide (page->tab_label);
-            }
+          if (priv->scrollable)
+            tab_width = MAX (tab_width, arrow_spacing + 2 * scroll_arrow_vlength);
 
-          children = priv->children;
+          tab_width = MAX (tab_width, action_widget_requisition[ACTION_WIDGET_START].width);
+          tab_width = MAX (tab_width, action_widget_requisition[ACTION_WIDGET_END].width);
+
+          padding = 2 * tab_curvature - tab_overlap;
+          tab_max += padding;
 
-          if (vis_pages)
+          while (children)
             {
-              for (i = 0; i < N_ACTION_WIDGETS; i++)
-                {
-                  if (priv->action_widget[i])
-                    {
-                      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;
-                    }
-                }
+              page = children->data;
+              children = children->next;
 
-              switch (priv->tab_pos)
-                {
-                case GTK_POS_TOP:
-                case GTK_POS_BOTTOM:
-                  if (tab_height == 0)
-                    break;
+              if (!gtk_widget_get_visible (page->child))
+                continue;
 
-                  if (priv->scrollable && vis_pages > 1 &&
-                      requisition->width < tab_width)
-                    tab_height = MAX (tab_height, scroll_arrow_hlength);
+              page->requisition.width = tab_width;
 
-                  tab_height = MAX (tab_height, action_widget_requisition[ACTION_WIDGET_START].height);
-                  tab_height = MAX (tab_height, action_widget_requisition[ACTION_WIDGET_END].height);
+              page->requisition.height += padding;
 
-                  padding = 2 * (tab_curvature + priv->tab_hborder) - tab_overlap;
-                  tab_max += padding;
-                  while (children)
-                    {
-                      page = children->data;
-                      children = children->next;
+              tab_height += page->requisition.height;
+            }
 
-                      if (!gtk_widget_get_visible (page->child))
-                        continue;
+          if (priv->scrollable)
+            tab_height = MIN (tab_height,
+                              tab_max + (2 * scroll_arrow_vlength + arrow_spacing));
+          action_height += action_widget_requisition[ACTION_WIDGET_START].height;
+          action_height += action_widget_requisition[ACTION_WIDGET_END].height;
 
-                      if (priv->homogeneous)
-                        page->requisition.width = tab_max;
-                      else
-                        page->requisition.width += padding;
+          requisition->height = tab_height + tab_overlap + action_height + initial_gap;
 
-                      tab_width += page->requisition.width;
-                      page->requisition.height = tab_height;
-                    }
+          requisition->height = MAX (requisition->height, tab_max + tab_overlap);
 
-                  if (priv->scrollable && vis_pages > 1 &&
-                      requisition->width < tab_width)
-                    tab_width = tab_max + 2 * (scroll_arrow_hlength + arrow_spacing);
+          requisition->width = tab_width;
+          break;
+        default:
+          g_assert_not_reached ();
+          requisition->width = 0;
+          requisition->height = 0;
+        }
+    }
+  else
+    {
+      requisition->width = 0;
+      requisition->height = 0;
+    }
+}
 
-                  action_width += action_widget_requisition[ACTION_WIDGET_START].width;
-                  action_width += action_widget_requisition[ACTION_WIDGET_END].width;
-                  if (priv->homogeneous && !priv->scrollable)
-                    requisition->width = MAX (requisition->width,
-                                                     vis_pages * tab_max +
-                                                     tab_overlap + action_width);
-                  else
-                    requisition->width = MAX (requisition->width,
-                                                     tab_width + tab_overlap + action_width);
+static void
+get_preferred_size_for_size (GtkWidget      *widget,
+                             GtkOrientation  orientation,
+                             gint            size,
+                             gint           *minimum,
+                             gint           *natural)
+{
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    if (size < 0)
+      gtk_widget_get_preferred_width (widget, minimum, natural);
+    else
+      gtk_widget_get_preferred_width_for_height (widget, size, minimum, natural);
+  else
+    if (size < 0)
+      gtk_widget_get_preferred_height (widget, minimum, natural);
+    else
+      gtk_widget_get_preferred_height_for_width (widget, size, minimum, natural);
+}
 
-                  requisition->height += tab_height;
-                  break;
-                case GTK_POS_LEFT:
-                case GTK_POS_RIGHT:
-                  if (tab_width == 0)
-                    break;
+static void
+get_padding_and_border (GtkNotebook *notebook,
+                        GtkBorder *border)
+{
+  GtkStyleContext *context;
 
-                  if (priv->scrollable && vis_pages > 1 &&
-                      requisition->height < tab_height)
-                    tab_width = MAX (tab_width,
-                                     arrow_spacing + 2 * scroll_arrow_vlength);
+  context = gtk_widget_get_style_context (GTK_WIDGET (notebook));
+  gtk_style_context_get_padding (context, 0, border);
 
-                  tab_width = MAX (tab_width, action_widget_requisition[ACTION_WIDGET_START].width);
-                  tab_width = MAX (tab_width, action_widget_requisition[ACTION_WIDGET_END].width);
+  if (notebook->priv->show_border || notebook->priv->show_tabs)
+    {
+      GtkBorder tmp;
 
-                  padding = 2 * (tab_curvature + priv->tab_vborder) - tab_overlap;
-                  tab_max += padding;
+      gtk_style_context_get_border (context, 0, &tmp);
+      border->top += tmp.top;
+      border->right += tmp.right;
+      border->bottom += tmp.bottom;
+      border->left += tmp.left;
+    }
+}
 
-                  while (children)
-                    {
-                      page = children->data;
-                      children = children->next;
+static void
+gtk_notebook_size_request (GtkWidget      *widget,
+                           GtkOrientation  orientation,
+                           gint            size,
+                           gint           *minimum,
+                           gint           *natural)
+{
+  GtkNotebook *notebook = GTK_NOTEBOOK (widget);
+  GtkNotebookPrivate *priv = notebook->priv;
+  GtkNotebookPage *page;
+  GList *children;
+  gint child_minimum, child_natural;
+  gboolean switch_page = FALSE;
+  gint vis_pages;
+  guint border_width;
 
-                      if (!gtk_widget_get_visible (page->child))
-                        continue;
+  *minimum = 0;
+  *natural = 0;
 
-                      page->requisition.width = tab_width;
+  for (children = priv->children, vis_pages = 0; children;
+       children = children->next)
+    {
+      GtkWidget *parent;
+      page = children->data;
 
-                      if (priv->homogeneous)
-                        page->requisition.height = tab_max;
-                      else
-                        page->requisition.height += padding;
+      if (gtk_widget_get_visible (page->child))
+        {
+          vis_pages++;
+          get_preferred_size_for_size (page->child,
+                                       orientation,
+                                       size, 
+                                       &child_minimum,
+                                       &child_natural);
 
-                      tab_height += page->requisition.height;
-                    }
+          *minimum = MAX (*minimum, child_minimum);
+          *natural = MAX (*natural, child_natural);
 
-                  if (priv->scrollable && vis_pages > 1 &&
-                      requisition->height < tab_height)
-                    tab_height = tab_max + (2 * scroll_arrow_vlength + arrow_spacing);
-                  action_height += action_widget_requisition[ACTION_WIDGET_START].height;
-                  action_height += action_widget_requisition[ACTION_WIDGET_END].height;
+          if (priv->menu && page->menu_label)
+            {
+              parent = gtk_widget_get_parent (page->menu_label);
+              if (parent && !gtk_widget_get_visible (parent))
+                gtk_widget_show (parent);
+            }
+        }
+      else
+        {
+          if (page == priv->cur_page)
+            switch_page = TRUE;
 
-                  if (priv->homogeneous && !priv->scrollable)
-                    requisition->height =
-                      MAX (requisition->height,
-                           vis_pages * tab_max + tab_overlap + action_height);
-                  else
-                    requisition->height =
-                      MAX (requisition->height,
-                           tab_height + tab_overlap + action_height);
+          if (priv->menu && page->menu_label)
+            {
+              parent = gtk_widget_get_parent (page->menu_label);
+              if (parent && gtk_widget_get_visible (parent))
+                gtk_widget_hide (parent);
+            }
+        }
+    }
+
+  if (priv->show_border || priv->show_tabs)
+    {
+      GtkBorder notebook_padding;
 
-                  if (!priv->homogeneous || priv->scrollable)
-                    vis_pages = 1;
-                  requisition->height = MAX (requisition->height,
-                                             vis_pages * tab_max + tab_overlap);
+      get_padding_and_border (notebook, &notebook_padding);
 
-                  requisition->width += tab_width;
-                  break;
+      if (orientation == GTK_ORIENTATION_HORIZONTAL)
+        {
+          *minimum += notebook_padding.left + notebook_padding.right;
+          *natural += notebook_padding.left + notebook_padding.right;
+        }
+      else
+        {
+          *minimum += notebook_padding.top + notebook_padding.bottom;
+          *natural += notebook_padding.top + notebook_padding.bottom;
+        }
+
+      if (priv->show_tabs)
+        {
+          GtkRequisition tabs_requisition = { 0, 0 };
+
+          gtk_notebook_get_preferred_tabs_size (notebook, &tabs_requisition);
+          if (orientation == GTK_ORIENTATION_HORIZONTAL)
+            {
+              if (priv->tab_pos == GTK_POS_TOP || priv->tab_pos == GTK_POS_BOTTOM)
+                {
+                  *minimum = MAX (*minimum, tabs_requisition.width);
+                  *natural = MAX (*minimum, *natural);
+                }
+              else
+                {
+                  *minimum += tabs_requisition.width;
+                  *natural += tabs_requisition.width;
+                }
+            }
+          else
+            {
+              if (priv->tab_pos == GTK_POS_LEFT || priv->tab_pos == GTK_POS_RIGHT)
+                {
+                  *minimum = MAX (*minimum, tabs_requisition.height);
+                  *natural = MAX (*minimum, *natural);
+                }
+              else
+                {
+                  *minimum += tabs_requisition.height;
+                  *natural += tabs_requisition.height;
                 }
             }
         }
@@ -2229,8 +2376,8 @@ gtk_notebook_size_request (GtkWidget      *widget,
 
   border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
 
-  requisition->width += border_width * 2;
-  requisition->height += border_width * 2;
+  *minimum += border_width * 2;
+  *natural += border_width * 2;
 
   if (switch_page)
     {
@@ -2249,8 +2396,7 @@ gtk_notebook_size_request (GtkWidget      *widget,
         }
       else if (gtk_widget_get_visible (widget))
         {
-          requisition->width  = border_width * 2;
-          requisition->height = border_width * 2;
+          *minimum = border_width * 2;
         }
     }
   if (vis_pages && !priv->cur_page)
@@ -2264,17 +2410,30 @@ gtk_notebook_size_request (GtkWidget      *widget,
     }
 }
 
+static void
+gtk_notebook_get_preferred_width_for_height (GtkWidget *widget,
+                                             gint       height,
+                                             gint      *minimum,
+                                             gint      *natural)
+{
+  gtk_notebook_size_request (widget, GTK_ORIENTATION_HORIZONTAL, height, minimum, natural);
+}
+
+static void
+gtk_notebook_get_preferred_height_for_width (GtkWidget *widget,
+                                             gint       width,
+                                             gint      *minimum,
+                                             gint      *natural)
+{
+  gtk_notebook_size_request (widget, GTK_ORIENTATION_VERTICAL, width, minimum, natural);
+}
 
 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;
+  gtk_notebook_size_request (widget, GTK_ORIENTATION_HORIZONTAL, -1, minimum, natural);
 }
 
 static void
@@ -2282,11 +2441,7 @@ gtk_notebook_get_preferred_height (GtkWidget *widget,
                                    gint      *minimum,
                                    gint      *natural)
 {
-  GtkRequisition requisition;
-
-  gtk_notebook_size_request (widget, &requisition);
-
-  *minimum = *natural = requisition.height;
+  gtk_notebook_size_request (widget, GTK_ORIENTATION_VERTICAL, -1, minimum, natural);
 }
 
 static void
@@ -2334,11 +2489,9 @@ gtk_notebook_size_allocate (GtkWidget     *widget,
 
       if (priv->show_tabs || priv->show_border)
         {
-          GtkStyleContext *context;
           GtkBorder padding;
 
-          context = gtk_widget_get_style_context (widget);
-          gtk_style_context_get_padding (context, 0, &padding);
+          get_padding_and_border (notebook, &padding);
 
           child_allocation.x += padding.left;
           child_allocation.y += padding.top;
@@ -2351,6 +2504,7 @@ gtk_notebook_size_allocate (GtkWidget     *widget,
                 {
                 case GTK_POS_TOP:
                   child_allocation.y += priv->cur_page->requisition.height;
+                  /* fall thru */
                 case GTK_POS_BOTTOM:
                   child_allocation.height =
                     MAX (1, child_allocation.height -
@@ -2358,6 +2512,7 @@ gtk_notebook_size_allocate (GtkWidget     *widget,
                   break;
                 case GTK_POS_LEFT:
                   child_allocation.x += priv->cur_page->requisition.width;
+                  /* fall thru */
                 case GTK_POS_RIGHT:
                   child_allocation.width =
                     MAX (1, child_allocation.width -
@@ -2483,27 +2638,12 @@ gtk_notebook_draw (GtkWidget *widget,
   if (priv->operation == DRAG_OPERATION_REORDER &&
       gtk_cairo_should_draw_window (cr, priv->drag_window))
     {
-      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
-       * isn't set, the rounded corners would be black.
-       *
-       * Ideally, these corners should be made transparent, Either by using
-       * ARGB visuals or shape windows.
-       */
-      gtk_style_context_get_background_color (context, 0, &bg_color);
-      gdk_cairo_set_source_rgba (cr, &bg_color);
-      cairo_paint (cr);
 
       gtk_notebook_draw_tab (notebook,
                              priv->cur_page,
-                             cr, 0);
+                             cr, FALSE);
 
       cairo_restore (cr);
 
@@ -2680,14 +2820,14 @@ gtk_notebook_arrow_button_press (GtkNotebook      *notebook,
   priv->button = button;
   priv->click_child = arrow;
 
-  if (button == 1)
+  if (button == GDK_BUTTON_PRIMARY)
     {
       gtk_notebook_do_arrow (notebook, arrow);
       gtk_notebook_set_scroll_timer (notebook);
     }
-  else if (button == 2)
+  else if (button == GDK_BUTTON_MIDDLE)
     gtk_notebook_page_select (notebook, TRUE);
-  else if (button == 3)
+  else if (button == GDK_BUTTON_SECONDARY)
     gtk_notebook_switch_focus_tab (notebook,
                                    gtk_notebook_search_page (notebook,
                                                              NULL,
@@ -2780,14 +2920,14 @@ gtk_notebook_button_press (GtkWidget      *widget,
   if (arrow)
     return gtk_notebook_arrow_button_press (notebook, arrow, event->button);
 
-  if (event->button == 3 && priv->menu)
+  if (priv->menu && gdk_event_triggers_context_menu ((GdkEvent *) event))
     {
       gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL,
                       NULL, NULL, 3, event->time);
       return TRUE;
     }
 
-  if (event->button != 1)
+  if (event->button != GDK_BUTTON_PRIMARY)
     return FALSE;
 
   priv->button = event->button;
@@ -2971,6 +3111,7 @@ show_drag_window (GtkNotebook        *notebook,
     {
       GdkWindowAttr attributes;
       guint attributes_mask;
+      GdkRGBA transparent = {0, 0, 0, 0};
 
       attributes.x = page->allocation.x;
       attributes.y = page->allocation.y;
@@ -2985,7 +3126,8 @@ show_drag_window (GtkNotebook        *notebook,
       priv->drag_window = gdk_window_new (gtk_widget_get_parent_window (widget),
                                           &attributes,
                                           attributes_mask);
-      gdk_window_set_user_data (priv->drag_window, widget);
+      gtk_widget_register_window (widget, priv->drag_window);
+      gdk_window_set_background_rgba (priv->drag_window, &transparent);
     }
 
   g_object_ref (page->tab_label);
@@ -3019,11 +3161,8 @@ hide_drag_window (GtkNotebook        *notebook,
     {
       g_object_ref (page->tab_label);
 
-      if (GTK_IS_WINDOW (parent))
-        {
-          /* parent widget is the drag window */
-          gtk_container_remove (GTK_CONTAINER (parent), page->tab_label);
-        }
+      if (GTK_IS_WINDOW (parent)) /* parent widget is the drag window */
+        gtk_container_remove (GTK_CONTAINER (parent), page->tab_label);
       else
         gtk_widget_unparent (page->tab_label);
 
@@ -3056,7 +3195,7 @@ gtk_notebook_stop_reorder (GtkNotebook *notebook)
     {
       if (priv->during_reorder)
         {
-          gint old_page_num, page_num;
+          gint old_page_num, page_num, i;
           GList *element;
 
           element = get_drop_position (notebook);
@@ -3065,9 +3204,16 @@ gtk_notebook_stop_reorder (GtkNotebook *notebook)
           gtk_notebook_child_reordered (notebook, page);
 
           if (priv->has_scrolled || old_page_num != page_num)
-            g_signal_emit (notebook,
-                           notebook_signals[PAGE_REORDERED], 0,
-                           page->child, page_num);
+           {
+             for (element = priv->children, i = 0; element; element = element->next, i++)
+               {
+                 if (MIN (old_page_num, page_num) <= i && i <= MAX (old_page_num, page_num))
+                   gtk_widget_child_notify (((GtkNotebookPage *) element->data)->child, "position");
+               }
+             g_signal_emit (notebook,
+                            notebook_signals[PAGE_REORDERED], 0,
+                            page->child, page_num);
+           }
 
           priv->has_scrolled = FALSE;
           priv->during_reorder = FALSE;
@@ -3349,6 +3495,8 @@ gtk_notebook_motion_notify (GtkWidget      *widget,
                                   priv->drag_window_y,
                                   page->allocation.width,
                                   page->allocation.height);
+
+          gtk_notebook_redraw_tabs_junction (notebook);
         }
     }
 
@@ -3435,7 +3583,7 @@ on_drag_icon_draw (GtkWidget *widget,
   context = gtk_widget_get_style_context (widget);
 
   gtk_style_context_save (context);
-  gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB, 0);
+  notebook_tab_prepare_style_context (GTK_NOTEBOOK (notebook), NULL, context, FALSE);
 
   gtk_widget_get_preferred_size (widget,
                                  &requisition, NULL);
@@ -3551,20 +3699,20 @@ gtk_notebook_switch_tab_timeout (gpointer data)
 {
   GtkNotebook *notebook = GTK_NOTEBOOK (data);
   GtkNotebookPrivate *priv = notebook->priv;
-  GList *tab;
-  gint x, y;
+  GList *switch_tab;
 
   priv->switch_tab_timer = 0;
-  x = priv->mouse_x;
-  y = priv->mouse_y;
 
-  if ((tab = get_tab_at_pos (notebook, x, y)) != NULL)
+  switch_tab = priv->switch_tab;
+  priv->switch_tab = NULL;
+
+  if (switch_tab)
     {
       /* FIXME: hack, we don't want the
        * focus to move fom the source widget
        */
       priv->child_has_focus = FALSE;
-      gtk_notebook_switch_focus_tab (notebook, tab);
+      gtk_notebook_switch_focus_tab (notebook, switch_tab);
     }
 
   return FALSE;
@@ -3585,6 +3733,8 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
   GtkNotebookArrow arrow;
   guint timeout;
   GdkAtom target, tab_target;
+  GList *tab;
+  gboolean retval = FALSE;
 
   gtk_widget_get_allocation (widget, &allocation);
 
@@ -3596,7 +3746,9 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
       priv->click_child = arrow;
       gtk_notebook_set_scroll_timer (notebook);
       gdk_drag_status (context, 0, time);
-      return TRUE;
+
+      retval = TRUE;
+      goto out;
     }
 
   stop_scrolling (notebook);
@@ -3609,6 +3761,8 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
       GtkNotebook *source;
       GtkWidget *source_child;
 
+      retval = TRUE;
+
       source = GTK_NOTEBOOK (gtk_drag_get_source_widget (context));
       source_child = source->priv->cur_page->child;
 
@@ -3620,7 +3774,7 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
             gtk_widget_is_ancestor (widget, source_child)))
         {
           gdk_drag_status (context, GDK_ACTION_MOVE, time);
-          return TRUE;
+          goto out;
         }
       else
         {
@@ -3635,11 +3789,19 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
 
   if (gtk_notebook_get_event_window_position (notebook, &position) &&
       x >= position.x && x <= position.x + position.width &&
-      y >= position.y && y <= position.y + position.height)
+      y >= position.y && y <= position.y + position.height &&
+      (tab = get_tab_at_pos (notebook, x, y)))
     {
       priv->mouse_x = x;
       priv->mouse_y = y;
 
+      retval = TRUE;
+
+      if (tab != priv->switch_tab)
+        remove_switch_tab_timer (notebook);
+
+      priv->switch_tab = tab;
+
       if (!priv->switch_tab_timer)
         {
           settings = gtk_widget_get_settings (widget);
@@ -3652,14 +3814,11 @@ gtk_notebook_drag_motion (GtkWidget      *widget,
     }
   else
     {
-      if (priv->switch_tab_timer)
-        {
-          g_source_remove (priv->switch_tab_timer);
-          priv->switch_tab_timer = 0;
-        }
+      remove_switch_tab_timer (notebook);
     }
 
-  return (target == tab_target) ? TRUE : FALSE;
+ out:
+  return retval;
 }
 
 static void
@@ -3668,15 +3827,9 @@ gtk_notebook_drag_leave (GtkWidget      *widget,
                          guint           time)
 {
   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
-  GtkNotebookPrivate *priv = notebook->priv;
 
-  if (priv->switch_tab_timer)
-    {
-      g_source_remove (priv->switch_tab_timer);
-      priv->switch_tab_timer = 0;
-    }
-
-  stop_scrolling (GTK_NOTEBOOK (widget));
+  remove_switch_tab_timer (notebook);
+  stop_scrolling (notebook);
 }
 
 static gboolean
@@ -3966,7 +4119,7 @@ gtk_notebook_remove (GtkContainer *container,
   GtkNotebook *notebook = GTK_NOTEBOOK (container);
   GtkNotebookPrivate *priv = notebook->priv;
   GtkNotebookPage *page;
-  GList *children;
+  GList *children, *list;
   gint page_num = 0;
 
   children = priv->children;
@@ -3986,8 +4139,15 @@ gtk_notebook_remove (GtkContainer *container,
 
   g_object_ref (widget);
 
+  list = children->next;
   gtk_notebook_real_remove (notebook, children);
 
+  while (list)
+    {
+      gtk_widget_child_notify (((GtkNotebookPage *)list->data)->child, "position");
+      list = list->next;
+    }
+
   g_signal_emit (notebook,
                  notebook_signals[PAGE_REMOVED],
                  0,
@@ -4005,7 +4165,7 @@ focus_tabs_in (GtkNotebook *notebook)
   if (priv->show_tabs && priv->cur_page)
     {
       gtk_widget_grab_focus (GTK_WIDGET (notebook));
-
+      gtk_notebook_set_focus_child (GTK_CONTAINER (notebook), NULL);
       gtk_notebook_switch_focus_tab (notebook,
                                      g_list_find (priv->children,
                                                   priv->cur_page));
@@ -4361,7 +4521,6 @@ gtk_notebook_get_path_for_child (GtkContainer *container,
   GtkNotebook *notebook;
   GtkNotebookPage *page;
   GtkWidgetPath *path;
-  GtkRegionFlags flags;
   GList *c;
 
   path = GTK_CONTAINER_CLASS (gtk_notebook_parent_class)->get_path_for_child (container, widget);
@@ -4381,8 +4540,10 @@ gtk_notebook_get_path_for_child (GtkContainer *container,
   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);
+  gtk_widget_path_iter_add_region (path, 
+                                   gtk_widget_path_length (path) - 2,
+                                   GTK_STYLE_REGION_TAB,
+                                   _gtk_notebook_get_tab_flags (notebook, page));
 
   return path;
 }
@@ -4434,6 +4595,7 @@ gtk_notebook_real_insert_page (GtkNotebook *notebook,
   GtkNotebookPrivate *priv = notebook->priv;
   GtkNotebookPage *page;
   gint nchildren;
+  GList *list;
 
   gtk_widget_freeze_child_notify (child);
 
@@ -4449,8 +4611,6 @@ gtk_notebook_real_insert_page (GtkNotebook *notebook,
   if (!tab_label)
     {
       page->default_tab = TRUE;
-      if (priv->show_tabs)
-        tab_label = gtk_label_new (NULL);
     }
   page->tab_label = tab_label;
   page->menu_label = menu_label;
@@ -4466,6 +4626,10 @@ gtk_notebook_real_insert_page (GtkNotebook *notebook,
     gtk_notebook_menu_item_create (notebook,
                                    g_list_find (priv->children, page));
 
+  /* child visible will be turned on by switch_page below */
+  if (priv->cur_page != page)
+    gtk_widget_set_child_visible (child, FALSE);
+
   gtk_widget_set_parent (child, GTK_WIDGET (notebook));
   if (tab_label)
     gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
@@ -4475,10 +4639,6 @@ gtk_notebook_real_insert_page (GtkNotebook *notebook,
   if (!priv->first_tab)
     priv->first_tab = priv->children;
 
-  /* child visible will be turned on by switch_page below */
-  if (priv->cur_page != page)
-    gtk_widget_set_child_visible (child, FALSE);
-
   if (tab_label)
     {
       if (priv->show_tabs && gtk_widget_get_visible (child))
@@ -4518,7 +4678,14 @@ gtk_notebook_real_insert_page (GtkNotebook *notebook,
   gtk_widget_child_notify (child, "tab-fill");
   gtk_widget_child_notify (child, "tab-label");
   gtk_widget_child_notify (child, "menu-label");
-  gtk_widget_child_notify (child, "position");
+
+  list = g_list_nth (priv->children, position);
+  while (list)
+    {
+      gtk_widget_child_notify (((GtkNotebookPage *)list->data)->child, "position");
+      list = list->next;
+    }
+
   gtk_widget_thaw_child_notify (child);
 
   /* The page-added handler might have reordered the pages, re-get the position */
@@ -4542,7 +4709,6 @@ gtk_notebook_redraw_tabs (GtkNotebook *notebook)
   GtkAllocation allocation;
   GtkWidget *widget;
   GtkNotebookPage *page;
-  GtkStyleContext *context;
   GdkRectangle redraw_rect;
   gint border;
   gint tab_pos = get_effective_tab_pos (notebook);
@@ -4551,48 +4717,108 @@ gtk_notebook_redraw_tabs (GtkNotebook *notebook)
   widget = GTK_WIDGET (notebook);
   border = gtk_container_get_border_width (GTK_CONTAINER (notebook));
 
-  if (!gtk_widget_get_mapped (widget) || !priv->first_tab)
+  if (!gtk_widget_get_mapped (widget) || !priv->cur_page)
     return;
 
-  page = priv->first_tab->data;
+  page = priv->cur_page;
 
   redraw_rect.x = border;
   redraw_rect.y = border;
 
   gtk_widget_get_allocation (widget, &allocation);
 
-  context = gtk_widget_get_style_context (widget);
-  gtk_style_context_get_padding (context, 0, &padding);
+  get_padding_and_border (notebook, &padding);
 
   switch (tab_pos)
     {
     case GTK_POS_BOTTOM:
       redraw_rect.y = allocation.height - border -
         page->allocation.height - padding.bottom;
-
-      if (page != priv->cur_page)
-        redraw_rect.y -= padding.bottom;
       /* fall through */
     case GTK_POS_TOP:
       redraw_rect.width = allocation.width - 2 * border;
       redraw_rect.height = page->allocation.height + padding.top;
 
-      if (page != priv->cur_page)
-        redraw_rect.height += padding.top;
       break;
     case GTK_POS_RIGHT:
       redraw_rect.x = allocation.width - border -
         page->allocation.width - padding.right;
 
-      if (page != priv->cur_page)
-        redraw_rect.x -= padding.right;
       /* fall through */
     case GTK_POS_LEFT:
       redraw_rect.width = page->allocation.width + padding.left;
       redraw_rect.height = allocation.height - 2 * border;
 
-      if (page != priv->cur_page)
-        redraw_rect.width += padding.left;
+      break;
+    }
+
+  redraw_rect.x += allocation.x;
+  redraw_rect.y += allocation.y;
+
+  gdk_window_invalidate_rect (gtk_widget_get_window (widget),
+                              &redraw_rect, TRUE);
+}
+
+static void
+gtk_notebook_redraw_tabs_junction (GtkNotebook *notebook)
+{
+  GtkNotebookPrivate *priv = notebook->priv;
+  GtkAllocation allocation;
+  GtkWidget *widget;
+  GtkNotebookPage *page;
+  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));
+
+  if (!gtk_widget_get_mapped (widget) || !priv->cur_page)
+    return;
+
+  page = priv->cur_page;
+
+  redraw_rect.x = border;
+  redraw_rect.y = border;
+
+  gtk_widget_get_allocation (widget, &allocation);
+
+  get_padding_and_border (notebook, &padding);
+
+  switch (tab_pos)
+    {
+    case GTK_POS_TOP:
+    case GTK_POS_BOTTOM:
+      redraw_rect.width = allocation.width - 2 * border;
+      if (tab_pos == GTK_POS_TOP)
+        {
+          redraw_rect.y = border + page->allocation.y +
+            page->allocation.height;
+          redraw_rect.height = padding.top;
+        }
+      else
+        {
+          redraw_rect.y = allocation.height - border -
+            page->allocation.height - padding.bottom;
+          redraw_rect.height = padding.bottom;
+        }
+      break;
+    case GTK_POS_LEFT:
+    case GTK_POS_RIGHT:
+      redraw_rect.height = allocation.height - 2 * border;
+
+      if (tab_pos == GTK_POS_LEFT)
+        {
+          redraw_rect.x = border + page->allocation.x + page->allocation.width;
+          redraw_rect.width = padding.left;
+        }
+      else
+        {
+          redraw_rect.x = allocation.width - border -
+            page->allocation.width - padding.right;
+          redraw_rect.width = padding.right;
+        }
       break;
     }
 
@@ -4719,7 +4945,23 @@ gtk_notebook_remove_tab_label (GtkNotebook     *notebook,
       page->mnemonic_activate_signal = 0;
 
       gtk_widget_set_state_flags (page->tab_label, 0, TRUE);
-      gtk_widget_unparent (page->tab_label);
+      if (gtk_widget_get_window (page->tab_label) != gtk_widget_get_window (GTK_WIDGET (notebook)) ||
+          !NOTEBOOK_IS_TAB_LABEL_PARENT (notebook, page))
+        {
+          GtkWidget *parent;
+
+          /* we hit this condition during dnd of a detached tab */
+          parent = gtk_widget_get_parent (page->tab_label);
+          if (GTK_IS_WINDOW (parent))
+            gtk_container_remove (GTK_CONTAINER (parent), page->tab_label);
+          else
+            gtk_widget_unparent (page->tab_label);
+        }
+      else
+        {
+          gtk_widget_unparent (page->tab_label);
+        }
+
       page->tab_label = NULL;
     }
 }
@@ -4752,6 +4994,8 @@ gtk_notebook_real_remove (GtkNotebook *notebook,
 
   if (priv->detached_tab == list->data)
     priv->detached_tab = NULL;
+  if (priv->switch_tab == list)
+    priv->switch_tab = NULL;
 
   if (list == priv->first_tab)
     priv->first_tab = next_list;
@@ -4933,7 +5177,6 @@ gtk_notebook_paint (GtkWidget    *widget,
   gboolean is_rtl;
   gint tab_pos;
   GtkStyleContext *context;
-  GtkRegionFlags tab_flags;
 
   notebook = GTK_NOTEBOOK (widget);
   priv = notebook->priv;
@@ -5090,8 +5333,7 @@ gtk_notebook_paint (GtkWidget    *widget,
           !gtk_widget_get_mapped (page->tab_label))
         continue;
 
-      tab_flags = _gtk_notebook_get_tab_flags (notebook, page);
-      gtk_notebook_draw_tab (notebook, page, cr, tab_flags);
+      gtk_notebook_draw_tab (notebook, page, cr, TRUE);
     }
 
   if (children != NULL)
@@ -5115,9 +5357,7 @@ gtk_notebook_paint (GtkWidget    *widget,
       for (children = other_order; children; children = children->next)
         {
           page = children->data;
-
-          tab_flags = _gtk_notebook_get_tab_flags (notebook, page);
-          gtk_notebook_draw_tab (notebook, page, cr, tab_flags);
+          gtk_notebook_draw_tab (notebook, page, cr, TRUE);
         }
 
       g_list_free (other_order);
@@ -5136,20 +5376,16 @@ gtk_notebook_paint (GtkWidget    *widget,
     }
 
   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, cr, TRUE);
 }
 
 static void
 gtk_notebook_draw_tab (GtkNotebook     *notebook,
                        GtkNotebookPage *page,
                        cairo_t         *cr,
-                       GtkRegionFlags   flags)
+                       gboolean         use_flags)
 {
   GtkNotebookPrivate *priv;
-  GtkStateFlags state = 0;
   GtkWidget *widget;
   GtkStyleContext *context;
 
@@ -5161,13 +5397,9 @@ gtk_notebook_draw_tab (GtkNotebook     *notebook,
   widget = GTK_WIDGET (notebook);
   priv = notebook->priv;
 
-  if (priv->cur_page == page)
-    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);
+  notebook_tab_prepare_style_context (notebook, page, context, use_flags);
 
   gtk_render_extension (context, cr,
                        page->allocation.x,
@@ -5176,7 +5408,7 @@ gtk_notebook_draw_tab (GtkNotebook     *notebook,
                        page->allocation.height,
                        get_tab_gap_pos (notebook));
 
-  if (gtk_widget_has_focus (widget) &&
+  if (gtk_widget_has_visible_focus (widget) &&
       priv->cur_page == page)
     {
       gint focus_width, focus_pad;
@@ -5214,6 +5446,7 @@ gtk_notebook_draw_arrow (GtkNotebook      *notebook,
 
   widget = GTK_WIDGET (notebook);
   context = gtk_widget_get_style_context (widget);
+  state = gtk_widget_get_state_flags (widget);
 
   gtk_notebook_get_arrow_rect (notebook, &arrow_rect, nbarrow);
 
@@ -5226,20 +5459,19 @@ gtk_notebook_draw_arrow (GtkNotebook      *notebook,
                         "scroll-arrow-vlength", &scroll_arrow_vlength,
                         NULL);
 
-  if (priv->in_child == nbarrow)
+  if (priv->focus_tab &&
+      !gtk_notebook_search_page (notebook, priv->focus_tab,
+                                 left ? STEP_PREV : STEP_NEXT, TRUE))
+    {
+      state |= GTK_STATE_FLAG_INSENSITIVE;
+    }
+  else if (priv->in_child == nbarrow)
     {
       state |= GTK_STATE_FLAG_PRELIGHT;
 
       if (priv->click_child == nbarrow)
         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))
-    state = GTK_STATE_FLAG_INSENSITIVE;
 
   if (priv->tab_pos == GTK_POS_LEFT ||
       priv->tab_pos == GTK_POS_RIGHT)
@@ -5282,7 +5514,6 @@ gtk_notebook_tab_space (GtkNotebook *notebook,
   GtkNotebookPrivate *priv = notebook->priv;
   GtkAllocation allocation, action_allocation;
   GtkWidget *widget;
-  GtkStyleContext *context;
   GList *children;
   gint tab_pos = get_effective_tab_pos (notebook);
   gint tab_overlap;
@@ -5299,8 +5530,6 @@ gtk_notebook_tab_space (GtkNotebook *notebook,
   children = priv->children;
   is_rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
 
-  context = gtk_widget_get_style_context (widget);
-
   gtk_widget_style_get (GTK_WIDGET (notebook),
                         "arrow-spacing", &arrow_spacing,
                         "scroll-arrow-hlength", &scroll_arrow_hlength,
@@ -5309,13 +5538,10 @@ 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);
+  get_padding_and_border (notebook, &padding);
 
   gtk_widget_get_allocation (widget, &allocation);
 
-  allocation.x += initial_gap;
-  allocation.width -= 2 * initial_gap;
-
   switch (tab_pos)
     {
     case GTK_POS_TOP:
@@ -5381,6 +5607,9 @@ gtk_notebook_tab_space (GtkNotebook *notebook,
       break;
     }
 
+  *min += initial_gap;
+  *max -= (2 * initial_gap);
+
   if (!priv->scrollable)
     *show_arrows = FALSE;
   else
@@ -5652,10 +5881,6 @@ gtk_notebook_calculate_shown_tabs (GtkNotebook  *notebook,
               (gtk_widget_compute_expand (page->tab_label, tab_expand_orientation)))
             (*n)++;
         }
-
-      /* if notebook is homogeneous, all tabs are expanded */
-      if (priv->homogeneous && *n)
-        *n = c;
     }
 }
 
@@ -5709,7 +5934,6 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
   gboolean gap_left, packing_changed;
   GtkAllocation child_allocation = { 0, };
   GtkOrientation tab_expand_orientation;
-  GtkBorder padding;
 
   widget = GTK_WIDGET (notebook);
   container = GTK_CONTAINER (notebook);
@@ -5762,16 +5986,10 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
   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)
         *children = gtk_notebook_search_page (notebook, *children, direction, TRUE);
       else
@@ -5784,7 +6002,7 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
         continue;
 
       tab_extra_space = 0;
-      if (*expanded_tabs && (showarrow || page->expand || gtk_widget_compute_expand (page->tab_label, tab_expand_orientation) || priv->homogeneous))
+      if (*expanded_tabs && (showarrow || page->expand || gtk_widget_compute_expand (page->tab_label, tab_expand_orientation)))
         {
           tab_extra_space = *remaining_space / *expanded_tabs;
           *remaining_space -= tab_extra_space;
@@ -5906,21 +6124,43 @@ gtk_notebook_calculate_tabs_allocation (GtkNotebook  *notebook,
 
       if (page != priv->cur_page)
         {
+          GtkBorder active_padding, normal_padding, padding;
+
+          /* The active tab is by definition at least the same height as the inactive one.
+           * The padding we're building is the offset between the two tab states, 
+           * so in case the style specifies normal_padding > active_padding we
+           * remove the offset and draw them with the same height.
+           * Note that the padding will still be applied to the tab content though,
+           * see gtk_notebook_page_allocate().
+           */
+          gtk_style_context_save (context);
+          notebook_tab_prepare_style_context (notebook, page, context, TRUE);
+
+          gtk_style_context_get_padding (context, GTK_STATE_FLAG_ACTIVE, &active_padding);
+          gtk_style_context_get_padding (context, GTK_STATE_FLAG_NORMAL, &normal_padding);
+
+          gtk_style_context_restore (context);
+
+          padding.top = MAX (0, active_padding.top - normal_padding.top);
+          padding.right = MAX (0, active_padding.right - normal_padding.right);
+          padding.bottom = MAX (0, active_padding.bottom - normal_padding.bottom);
+          padding.left = MAX (0, active_padding.left - normal_padding.left);
+
           switch (tab_pos)
             {
             case GTK_POS_TOP:
-              page->allocation.y += padding.top;
-              page->allocation.height = MAX (1, page->allocation.height - padding.top);
+              page->allocation.y += padding.top + padding.bottom;
+              page->allocation.height = MAX (1, page->allocation.height - padding.top - padding.bottom);
               break;
             case GTK_POS_BOTTOM:
-              page->allocation.height = MAX (1, page->allocation.height - padding.bottom);
+              page->allocation.height = MAX (1, page->allocation.height - padding.top - padding.bottom);
               break;
             case GTK_POS_LEFT:
-              page->allocation.x += padding.left;
-              page->allocation.width = MAX (1, page->allocation.width - padding.left);
+              page->allocation.x += padding.left + padding.right;
+              page->allocation.width = MAX (1, page->allocation.width - padding.left - padding.right);
               break;
             case GTK_POS_RIGHT:
-              page->allocation.width = MAX (1, page->allocation.width - padding.right);
+              page->allocation.width = MAX (1, page->allocation.width - padding.left - padding.right);
               break;
             }
         }
@@ -5983,8 +6223,6 @@ 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 &&
@@ -6082,6 +6320,7 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
   gboolean tab_allocation_changed;
   gboolean was_visible = page->tab_allocated_visible;
   GtkBorder tab_padding;
+  GtkStateFlags state;
 
   if (!page->tab_label ||
       !gtk_widget_get_visible (page->tab_label) ||
@@ -6094,10 +6333,9 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
   context = gtk_widget_get_style_context (widget);
 
   gtk_style_context_save (context);
-  gtk_style_context_add_region (context, GTK_STYLE_REGION_TAB,
-                                _gtk_notebook_get_tab_flags (notebook, page));
+  state = notebook_tab_prepare_style_context (notebook, page, context, TRUE);
 
-  gtk_style_context_get_padding (context, 0, &tab_padding);
+  gtk_style_context_get_padding (context, state, &tab_padding);
 
   gtk_widget_get_preferred_size (page->tab_label, &tab_requisition, NULL);
   gtk_widget_style_get (widget,
@@ -6110,7 +6348,7 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
     {
     case GTK_POS_TOP:
     case GTK_POS_BOTTOM:
-      padding = tab_curvature + priv->tab_hborder + focus_width + focus_padding;
+      padding = tab_curvature + focus_width + focus_padding;
       if (page->fill)
         {
           child_allocation.x = tab_padding.left + padding;
@@ -6148,18 +6386,16 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
           child_allocation.width = tab_requisition.width;
         }
 
-      child_allocation.y = priv->tab_vborder + page->allocation.y;
-
-      if (tab_pos == GTK_POS_TOP)
-        child_allocation.y += tab_padding.top + focus_width + focus_padding;
+      child_allocation.y = 
+        page->allocation.y + tab_padding.top + focus_width + focus_padding;
 
       child_allocation.height = MAX (1, (page->allocation.height -
                                          tab_padding.top - tab_padding.bottom -
-                                         2 * (priv->tab_vborder + focus_width + focus_padding)));
+                                         2 * (focus_width + focus_padding)));
       break;
     case GTK_POS_LEFT:
     case GTK_POS_RIGHT:
-      padding = tab_curvature + priv->tab_vborder + focus_width + focus_padding;
+      padding = tab_curvature + focus_width + focus_padding;
       if (page->fill)
         {
           child_allocation.y = tab_padding.top + padding;
@@ -6175,7 +6411,7 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
            * coordinate of the allocation too, to position it after
            * the end of the overlap.
            */
-          if (page != priv->cur_page && tab_overlap > tab_curvature)
+          if (page != priv->cur_page && tab_overlap > tab_curvature + MIN (tab_padding.top, tab_padding.bottom))
             {
               if (gtk_notebook_page_num (notebook, page->child) >
                   gtk_notebook_page_num (notebook, priv->cur_page->child))
@@ -6197,37 +6433,15 @@ gtk_notebook_page_allocate (GtkNotebook     *notebook,
           child_allocation.height = tab_requisition.height;
         }
 
-      child_allocation.x = priv->tab_hborder + page->allocation.x;
-
-      if (tab_pos == GTK_POS_LEFT)
-        child_allocation.x += tab_padding.left + focus_width + focus_padding;
+      child_allocation.x =
+        page->allocation.x + tab_padding.left + focus_width + focus_padding;
 
-      child_allocation.width = MAX (1, (page->allocation.width - tab_padding.right -
-                                        2 * (priv->tab_hborder + focus_width + focus_padding)));
+      child_allocation.width = MAX (1, (page->allocation.width -
+                                         tab_padding.left - tab_padding.right -
+                                         2 * (focus_width + focus_padding)));
       break;
     }
 
-  if (page != priv->cur_page)
-    {
-      switch (tab_pos)
-        {
-        case GTK_POS_TOP:
-          child_allocation.y -= tab_padding.top;
-          child_allocation.height += tab_padding.top;
-          break;
-        case GTK_POS_BOTTOM:
-          child_allocation.height += tab_padding.bottom;
-          break;
-        case GTK_POS_LEFT:
-          child_allocation.x -= tab_padding.left;
-          child_allocation.width += tab_padding.left;
-          break;
-        case GTK_POS_RIGHT:
-          child_allocation.width += tab_padding.right;
-          break;
-        }
-    }
-
   gtk_widget_get_allocation (page->tab_label, &label_allocation);
   tab_allocation_changed = (child_allocation.x != label_allocation.x ||
                             child_allocation.y != label_allocation.y ||
@@ -6349,11 +6563,6 @@ gtk_notebook_update_tab_states (GtkNotebook *notebook)
         {
           GtkRegionFlags current_flags;
 
-          if (page == priv->cur_page)
-            gtk_widget_set_state_flags (page->tab_label, GTK_STATE_FLAG_ACTIVE, FALSE);
-          else
-            gtk_widget_unset_state_flags (page->tab_label, GTK_STATE_FLAG_ACTIVE);
-
           /* FIXME: We should store these flags somewhere instead of poking
            * the widget's path */
           if (!gtk_widget_path_iter_has_region (gtk_widget_get_path (page->tab_label),
@@ -6361,7 +6570,7 @@ gtk_notebook_update_tab_states (GtkNotebook *notebook)
                                                 GTK_STYLE_REGION_TAB,
                                                 &current_flags)
               || current_flags != _gtk_notebook_get_tab_flags (notebook, page))
-            gtk_widget_reset_style (page->tab_label);
+            _gtk_widget_invalidate_style_context (page->tab_label, GTK_CSS_CHANGE_PARENT_STATE);
         }
     }
 }
@@ -6413,6 +6622,8 @@ gtk_notebook_real_switch_page (GtkNotebook     *notebook,
     }
 
   gtk_notebook_update_tab_states (notebook);
+  gtk_notebook_pages_allocate (notebook);
+
   gtk_widget_queue_resize (GTK_WIDGET (notebook));
   g_object_notify (G_OBJECT (notebook), "page");
 }
@@ -6501,11 +6712,6 @@ gtk_notebook_switch_focus_tab (GtkNotebook *notebook,
     return;
 
   page = priv->focus_tab->data;
-  if (gtk_widget_get_mapped (page->tab_label))
-    gtk_notebook_redraw_tabs (notebook);
-  else
-    gtk_notebook_pages_allocate (notebook);
-
   gtk_notebook_switch_page (notebook, page);
 }
 
@@ -6562,7 +6768,8 @@ gtk_notebook_menu_item_create (GtkNotebook *notebook,
         page->menu_label = gtk_label_new (gtk_label_get_label (GTK_LABEL (page->tab_label)));
       else
         page->menu_label = gtk_label_new ("");
-      gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
+      gtk_widget_set_halign (page->menu_label, GTK_ALIGN_START);
+      gtk_widget_set_valign (page->menu_label, GTK_ALIGN_CENTER);
     }
 
   gtk_widget_show (page->menu_label);
@@ -7315,13 +7522,15 @@ gtk_notebook_get_scrollable (GtkNotebook *notebook)
  * Return value: horizontal width of a tab border
  *
  * Since: 2.22
+ *
+ * Deprecated: 3.4: this function returns zero
  */
 guint16
 gtk_notebook_get_tab_hborder (GtkNotebook *notebook)
 {
   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
 
-  return notebook->priv->tab_hborder;
+  return 0;
 }
 
 /**
@@ -7333,13 +7542,15 @@ gtk_notebook_get_tab_hborder (GtkNotebook *notebook)
  * Return value: vertical width of a tab border
  *
  * Since: 2.22
+ *
+ * Deprecated: 3.4: this function returns zero
  */
 guint16
 gtk_notebook_get_tab_vborder (GtkNotebook *notebook)
 {
   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
 
-  return notebook->priv->tab_vborder;
+  return 0;
 }
 
 
@@ -7569,7 +7780,7 @@ gtk_notebook_set_tab_label_text (GtkNotebook *notebook,
  *     tab label widget is not a #GtkLabel. The string is owned
  *     by the widget and must not be freed.
  */
-G_CONST_RETURN gchar *
+const gchar *
 gtk_notebook_get_tab_label_text (GtkNotebook *notebook,
                                  GtkWidget   *child)
 {
@@ -7687,7 +7898,8 @@ gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
   if (menu_text)
     {
       menu_label = gtk_label_new (menu_text);
-      gtk_misc_set_alignment (GTK_MISC (menu_label), 0.0, 0.5);
+      gtk_widget_set_halign (menu_label, GTK_ALIGN_START);
+      gtk_widget_set_valign (menu_label, GTK_ALIGN_CENTER);
     }
   gtk_notebook_set_menu_label (notebook, child, menu_label);
   gtk_widget_child_notify (child, "menu-label");
@@ -7706,7 +7918,7 @@ gtk_notebook_set_menu_label_text (GtkNotebook *notebook,
  *     menu label, or the menu label widget is not a #GtkLabel.
  *     The string is owned by the widget and must not be freed.
  */
-G_CONST_RETURN gchar *
+const gchar *
 gtk_notebook_get_menu_label_text (GtkNotebook *notebook,
                                   GtkWidget *child)
 {
@@ -7777,7 +7989,7 @@ gtk_notebook_set_tab_label_packing (GtkNotebook *notebook,
   gtk_widget_child_notify (child, "tab-fill");
   gtk_widget_child_notify (child, "position");
   if (priv->show_tabs)
-    gtk_notebook_pages_allocate (notebook);
+    gtk_widget_queue_resize (GTK_WIDGET (notebook));
   gtk_widget_thaw_child_notify (child);
 }
 
@@ -7823,6 +8035,7 @@ gtk_notebook_reorder_child (GtkNotebook *notebook,
   GtkNotebookPage *page;
   gint old_pos;
   gint max_pos;
+  gint i;
 
   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
   g_return_if_fail (GTK_IS_WIDGET (child));
@@ -7858,7 +8071,12 @@ gtk_notebook_reorder_child (GtkNotebook *notebook,
 
   /* Move around the menu items if necessary */
   gtk_notebook_child_reordered (notebook, page);
-  gtk_widget_child_notify (child, "position");
+
+  for (list = priv->children, i = 0; list; list = list->next, i++)
+    {
+      if (MIN (old_pos, position) <= i && i <= MAX (old_pos, position))
+       gtk_widget_child_notify (((GtkNotebookPage *) list->data)->child, "position");
+    }
 
   if (priv->show_tabs)
     gtk_notebook_pages_allocate (notebook);