]> 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 2d902ee7bdbbf0750e7cca431e405c6a8cf3849d..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,8 @@
 #include "gtkdnd.h"
 #include "gtkbuildable.h"
 #include "gtktypebuiltins.h"
+#include "gtkwidgetpath.h"
+#include "gtkwidgetprivate.h"
 #include "a11y/gtknotebookaccessible.h"
 
 
@@ -150,6 +150,7 @@ struct _GtkNotebookPrivate
 
   guint          dnd_timer;
   guint          switch_tab_timer;
+  GList         *switch_tab;
 
   guint32        timer;
   guint32        timestamp;
@@ -1069,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.
@@ -1674,6 +1675,18 @@ 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)
 {
@@ -1701,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);
 }
@@ -1899,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
@@ -1908,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;
     }
@@ -1975,11 +1984,11 @@ notebook_tab_prepare_style_context (GtkNotebook *notebook,
 {
   gint tab_pos = get_effective_tab_pos (notebook);
   GtkRegionFlags flags = 0;
-  GtkStateFlags state = GTK_STATE_FLAG_NORMAL;
+  GtkStateFlags state = gtk_style_context_get_state (context);
 
   if (page != NULL &&
       page == notebook->priv->cur_page)
-    state = GTK_STATE_FLAG_ACTIVE;
+    state |= GTK_STATE_FLAG_ACTIVE;
 
   gtk_style_context_set_state (context, state);
 
@@ -2033,6 +2042,7 @@ gtk_notebook_get_preferred_tabs_size (GtkNotebook    *notebook,
   gint tab_overlap;
   gint tab_curvature;
   gint arrow_spacing;
+  gint initial_gap;
   gint scroll_arrow_hlength;
   gint scroll_arrow_vlength;
 
@@ -2042,6 +2052,7 @@ gtk_notebook_get_preferred_tabs_size (GtkNotebook    *notebook,
   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,
@@ -2145,7 +2156,7 @@ gtk_notebook_get_preferred_tabs_size (GtkNotebook    *notebook,
 
           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;
+          requisition->width = tab_width + tab_overlap + action_width + initial_gap;
 
           requisition->height = tab_height;
           break;
@@ -2184,7 +2195,7 @@ gtk_notebook_get_preferred_tabs_size (GtkNotebook    *notebook,
           action_height += action_widget_requisition[ACTION_WIDGET_START].height;
           action_height += action_widget_requisition[ACTION_WIDGET_END].height;
 
-          requisition->height = tab_height + tab_overlap + action_height;
+          requisition->height = tab_height + tab_overlap + action_height + initial_gap;
 
           requisition->height = MAX (requisition->height, tab_max + tab_overlap);
 
@@ -2493,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 -
@@ -2500,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 -
@@ -2625,8 +2638,6 @@ gtk_notebook_draw (GtkWidget *widget,
   if (priv->operation == DRAG_OPERATION_REORDER &&
       gtk_cairo_should_draw_window (cr, priv->drag_window))
     {
-      GtkStyleContext *context;
-
       cairo_save (cr);
       gtk_cairo_transform_to_window (cr, widget, priv->drag_window);
 
@@ -2809,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,
@@ -2916,7 +2927,7 @@ gtk_notebook_button_press (GtkWidget      *widget,
       return TRUE;
     }
 
-  if (event->button != 1)
+  if (event->button != GDK_BUTTON_PRIMARY)
     return FALSE;
 
   priv->button = event->button;
@@ -3115,7 +3126,7 @@ 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);
     }
 
@@ -3150,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);
 
@@ -3187,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);
@@ -3196,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;
@@ -3684,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;
@@ -3718,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);
 
@@ -3729,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);
@@ -3742,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;
 
@@ -3753,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
         {
@@ -3768,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);
@@ -3785,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
@@ -3801,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
@@ -4099,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;
@@ -4119,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,
@@ -4138,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));
@@ -4568,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);
 
@@ -4650,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 */
@@ -4910,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;
     }
 }
@@ -4943,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;
@@ -5393,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);
 
@@ -5405,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)
@@ -6510,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),
@@ -6522,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);
         }
     }
 }
@@ -7987,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));
@@ -8022,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);