pathbar: Reimplement using GtkBox
authorGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>
Thu, 24 Nov 2022 19:17:30 +0000 (16:17 -0300)
committerGeorges Basile Stavracas Neto <georges.stavracas@gmail.com>
Tue, 13 Dec 2022 17:45:15 +0000 (14:45 -0300)
The path bar does a lot of manual management of buttons, mostly to
be able to show navigation arrows when there's not enough space to
show the full path.

Since the GTK4 migration, this is slightly broken in some cases, due
to the 'need_sliders' variable being always set to TRUE. Furthermore,
after the introduction of the Recent button as a special cased fake
root, the allocation of the buttons is generating warnings.

Reimplement the path bar as a GtkBox, inside a GtkScrolledWindow.
This mimics what Nautilus does, and allows us to make navigation more
predictable, and remove most of the complexity from GtkPathBar. It
also prevents it from generating allocation warnings.

The path bar itself now doesn't override GtkWidget.measure nor
GtkWidget.allocate; instead, it delegates layout to the GtkBinLayout
layout manager.

CSS is adjusted to account for the changed hierarchy of buttons.

gtk/gtkpathbar.c
gtk/theme/Default/_common.scss

index e9def304a0e869e3abf20c707620d4a82d16ff4b..c2d2cdc76441a1962a3c637f2899228f761e153f 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <string.h>
 
+#include "gtkbinlayout.h"
 #include "gtkbox.h"
 #include "gtkdragsource.h"
 #include "gtkicontheme.h"
@@ -30,6 +31,7 @@
 #include "gtklabel.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
+#include "gtkscrolledwindow.h"
 #include "gtksettings.h"
 #include "gtktogglebutton.h"
 #include "gtkwidgetprivate.h"
@@ -41,6 +43,9 @@ struct _GtkPathBar
 {
   GtkWidget parent_instance;
 
+  GtkWidget *buttons_box;
+  GtkWidget *scrolled_window;
+
   GFile *root_file;
   GFile *home_file;
   GFile *desktop_file;
@@ -76,11 +81,7 @@ struct _GtkPathBar
   GIcon *desktop_icon;
 
   GList *button_list;
-  GList *first_scrolled_button;
   GList *fake_root;
-  GtkWidget *up_slider_button;
-  GtkWidget *down_slider_button;
-  gint16 slider_width;
 };
 
 typedef struct _GtkPathBarClass GtkPathBarClass;
@@ -136,28 +137,10 @@ G_DEFINE_TYPE (GtkPathBar, gtk_path_bar, GTK_TYPE_WIDGET)
 
 static void gtk_path_bar_finalize                 (GObject          *object);
 static void gtk_path_bar_dispose                  (GObject          *object);
-static void gtk_path_bar_measure (GtkWidget *widget,
-                                  GtkOrientation  orientation,
-                                  int             for_size,
-                                  int            *minimum,
-                                  int            *natural,
-                                  int            *minimum_baseline,
-                                  int            *natural_baseline);
-static void gtk_path_bar_size_allocate            (GtkWidget           *widget,
-                                                   int                  width,
-                                                   int                  height,
-                                                   int                  baseline);
-static void gtk_path_bar_scroll_up                (GtkPathBar       *path_bar);
-static void gtk_path_bar_scroll_down              (GtkPathBar       *path_bar);
 static void gtk_path_bar_update_button_appearance (GtkPathBar       *path_bar,
                                                   ButtonData       *button_data,
                                                   gboolean          current_dir);
 
-static gboolean gtk_path_bar_scroll_controller_scroll (GtkEventControllerScroll *scroll,
-                                                       double                    dx,
-                                                       double                    dy,
-                                                       GtkPathBar               *path_bar);
-
 static void
 add_cancellable (GtkPathBar   *path_bar,
                  GCancellable *cancellable)
@@ -207,37 +190,23 @@ cancel_all_cancellables (GtkPathBar *path_bar)
 static void
 gtk_path_bar_init (GtkPathBar *path_bar)
 {
-  GtkEventController *controller;
   const char *home;
 
-  path_bar->up_slider_button = gtk_button_new_from_icon_name ("pan-start-symbolic");
-  gtk_widget_add_css_class (path_bar->up_slider_button, "slider-button");
-  gtk_widget_set_parent (path_bar->up_slider_button, GTK_WIDGET (path_bar));
-
-  path_bar->down_slider_button = gtk_button_new_from_icon_name ("pan-end-symbolic");
-  gtk_widget_add_css_class (path_bar->down_slider_button, "slider-button");
-  gtk_widget_set_parent (path_bar->down_slider_button, GTK_WIDGET (path_bar));
+  path_bar->scrolled_window = gtk_scrolled_window_new ();
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (path_bar->scrolled_window),
+                                  GTK_POLICY_EXTERNAL, GTK_POLICY_NEVER);
+  gtk_widget_set_hexpand (path_bar->scrolled_window, TRUE);
+  gtk_widget_set_parent (path_bar->scrolled_window, GTK_WIDGET (path_bar));
 
-  /* GtkBuilder won't let us connect 'swapped' without specifying the signal's
-   * user data in the .ui file
-   */
-  g_signal_connect_swapped (path_bar->up_slider_button, "clicked",
-                           G_CALLBACK (gtk_path_bar_scroll_up), path_bar);
-  g_signal_connect_swapped (path_bar->down_slider_button, "clicked",
-                           G_CALLBACK (gtk_path_bar_scroll_down), path_bar);
+  path_bar->buttons_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_widget_add_css_class (path_bar->buttons_box, "linked");
+  gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (path_bar->scrolled_window),
+                                 path_bar->buttons_box);
 
-  gtk_widget_add_css_class (GTK_WIDGET (path_bar), "linked");
 
   path_bar->get_info_cancellable = NULL;
   path_bar->cancellables = NULL;
 
-  controller = gtk_event_controller_scroll_new (GTK_EVENT_CONTROLLER_SCROLL_VERTICAL |
-                                                GTK_EVENT_CONTROLLER_SCROLL_DISCRETE);
-  g_signal_connect (controller, "scroll",
-                    G_CALLBACK (gtk_path_bar_scroll_controller_scroll),
-                    path_bar);
-  gtk_widget_add_controller (GTK_WIDGET (path_bar), controller);
-
   home = g_get_home_dir ();
   if (home != NULL)
     {
@@ -273,9 +242,6 @@ gtk_path_bar_class_init (GtkPathBarClass *path_bar_class)
   gobject_class->finalize = gtk_path_bar_finalize;
   gobject_class->dispose = gtk_path_bar_dispose;
 
-  widget_class->measure = gtk_path_bar_measure;
-  widget_class->size_allocate = gtk_path_bar_size_allocate;
-
   path_bar_signals [PATH_CLICKED] =
     g_signal_new (I_("path-clicked"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
@@ -288,6 +254,7 @@ gtk_path_bar_class_init (GtkPathBarClass *path_bar_class)
                  G_TYPE_FILE,
                  G_TYPE_BOOLEAN);
 
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
   gtk_widget_class_set_css_name (widget_class, "pathbar");
 }
 
@@ -314,10 +281,8 @@ static void
 gtk_path_bar_dispose (GObject *object)
 {
   GtkPathBar *path_bar = GTK_PATH_BAR (object);
-  GtkWidget *w;
 
-  while ((w = gtk_widget_get_first_child (GTK_WIDGET (path_bar))) != NULL)
-    gtk_widget_unparent (w);
+  g_clear_pointer (&path_bar->scrolled_window, gtk_widget_unparent);
 
   path_bar->get_info_cancellable = NULL;
   cancel_all_cancellables (path_bar);
@@ -326,462 +291,31 @@ gtk_path_bar_dispose (GObject *object)
 }
 
 static void
-gtk_path_bar_measure (GtkWidget *widget,
-                      GtkOrientation  orientation,
-                      int             for_size,
-                      int            *minimum,
-                      int            *natural,
-                      int            *minimum_baseline,
-                      int            *natural_baseline)
-{
-  GtkPathBar *path_bar = GTK_PATH_BAR (widget);
-  ButtonData *button_data;
-  GList *list;
-  int child_size;
-  int size = 0;
-  int child_min, child_nat;
-
-  *minimum = 0;
-  *natural = 0;
-
-  if (orientation == GTK_ORIENTATION_HORIZONTAL)
-    {
-      for (list = path_bar->button_list; list; list = list->next)
-        {
-          button_data = BUTTON_DATA (list->data);
-          gtk_widget_measure (button_data->button, GTK_ORIENTATION_HORIZONTAL, -1,
-                              &child_min, &child_nat, NULL, NULL);
-          gtk_widget_measure (button_data->button, GTK_ORIENTATION_VERTICAL, -1,
-                              &child_size, NULL, NULL, NULL);
-          size = MAX (size, child_size);
-
-          if (button_data->type == NORMAL_BUTTON)
-            {
-              /* Use 2*Height as button width because of ellipsized label.  */
-              child_min = MAX (child_min, child_size * 2);
-              child_nat = MAX (child_min, child_size * 2);
-            }
-
-          *minimum = MAX (*minimum, child_min);
-          *natural = *natural + child_nat;
-        }
-
-      /* Add space for slider, if we have more than one path */
-      /* Theoretically, the slider could be bigger than the other button.  But we're
-       * not going to worry about that now.
-       */
-      path_bar->slider_width = 0;
-
-      gtk_widget_measure (path_bar->up_slider_button, GTK_ORIENTATION_HORIZONTAL, -1,
-                          &child_min, &child_nat, NULL, NULL);
-      if (path_bar->button_list && path_bar->button_list->next != NULL)
-        {
-          *minimum += child_min;
-          *natural += child_nat;
-        }
-      path_bar->slider_width = MAX (path_bar->slider_width, child_min);
-
-      gtk_widget_measure (path_bar->down_slider_button, GTK_ORIENTATION_HORIZONTAL, -1,
-                          &child_min, &child_nat, NULL, NULL);
-      if (path_bar->button_list && path_bar->button_list->next != NULL)
-        {
-          *minimum += child_min;
-          *natural += child_nat;
-        }
-      path_bar->slider_width = MAX (path_bar->slider_width, child_min);
-
-    }
-  else /* VERTICAL */
-    {
-      for (list = path_bar->button_list; list; list = list->next)
-        {
-          button_data = BUTTON_DATA (list->data);
-          gtk_widget_measure (button_data->button, GTK_ORIENTATION_VERTICAL, -1,
-                              &child_min, &child_nat, NULL, NULL);
-
-          *minimum = MAX (*minimum, child_min);
-          *natural = MAX (*natural, child_nat);
-        }
-
-      gtk_widget_measure (path_bar->up_slider_button, GTK_ORIENTATION_VERTICAL, -1,
-                          &child_min, &child_nat, NULL, NULL);
-      *minimum = MAX (*minimum, child_min);
-      *natural = MAX (*natural, child_nat);
-
-      gtk_widget_measure (path_bar->up_slider_button, GTK_ORIENTATION_VERTICAL, -1,
-                          &child_min, &child_nat, NULL, NULL);
-      *minimum = MAX (*minimum, child_min);
-      *natural = MAX (*natural, child_nat);
-    }
-}
-
-static void
-gtk_path_bar_update_slider_buttons (GtkPathBar *path_bar)
-{
-  if (path_bar->button_list)
-    {
-      GtkWidget *button;
-
-      button = BUTTON_DATA (path_bar->button_list->data)->button;
-      if (gtk_widget_get_child_visible (button))
-       gtk_widget_set_sensitive (path_bar->down_slider_button, FALSE);
-      else
-       gtk_widget_set_sensitive (path_bar->down_slider_button, TRUE);
-
-      button = BUTTON_DATA (g_list_last (path_bar->button_list)->data)->button;
-      if (gtk_widget_get_child_visible (button))
-       gtk_widget_set_sensitive (path_bar->up_slider_button, FALSE);
-      else
-       gtk_widget_set_sensitive (path_bar->up_slider_button, TRUE);
-    }
-}
-
-/* This is a tad complicated
- */
-static void
-gtk_path_bar_size_allocate (GtkWidget *widget,
-                            int        widget_width,
-                            int        widget_height,
-                            int        baseline)
+gtk_path_bar_clear_buttons (GtkPathBar *path_bar)
 {
-  GtkPathBar *path_bar = GTK_PATH_BAR (widget);
-  GtkWidget *child;
-  GtkTextDirection direction;
-  GtkAllocation child_allocation;
-  GList *list, *first_button;
-  int width;
-  int allocation_width;
-  gboolean need_sliders = TRUE;
-  int up_slider_offset = 0;
-  int down_slider_offset = 0;
-  GtkRequisition child_requisition;
-
-  /* No path is set; we don't have to allocate anything. */
-  if (path_bar->button_list == NULL)
-    return;
-
-  direction = gtk_widget_get_direction (widget);
-  allocation_width = widget_width;
-
-  /* First, we check to see if we need the scrollbars. */
-  if (path_bar->fake_root)
-    width = path_bar->slider_width;
-  else
-    width = 0;
-
-  for (list = path_bar->button_list; list; list = list->next)
-    {
-      child = BUTTON_DATA (list->data)->button;
-
-      gtk_widget_get_preferred_size (child, &child_requisition, NULL);
-
-      width += child_requisition.width;
-      if (list == path_bar->fake_root)
-       break;
-    }
-
-  if (width <= allocation_width)
-    {
-      if (path_bar->fake_root)
-       first_button = path_bar->fake_root;
-      else
-       first_button = g_list_last (path_bar->button_list);
-    }
-  else
-    {
-      gboolean reached_end = FALSE;
-      int slider_space = 2 * path_bar->slider_width;
-
-      if (path_bar->first_scrolled_button)
-       first_button = path_bar->first_scrolled_button;
-      else
-       first_button = path_bar->button_list;
-      need_sliders = TRUE;
-
-      /* To see how much space we have, and how many buttons we can display.
-       * We start at the first button, count forward until hit the new
-       * button, then count backwards.
-       */
-      /* Count down the path chain towards the end. */
-      gtk_widget_get_preferred_size (BUTTON_DATA (first_button->data)->button,
-                                     &child_requisition, NULL);
-
-      width = child_requisition.width;
-      list = first_button->prev;
-      while (list && !reached_end)
-       {
-         child = BUTTON_DATA (list->data)->button;
-
-          gtk_widget_get_preferred_size (child, &child_requisition, NULL);
-
-         if (width + child_requisition.width + slider_space > allocation_width)
-           reached_end = TRUE;
-         else if (list == path_bar->fake_root)
-           break;
-         else
-           width += child_requisition.width;
-
-         list = list->prev;
-       }
-
-      /* Finally, we walk up, seeing how many of the previous buttons we can
-       * add */
-      while (first_button->next && !reached_end)
-       {
-         child = BUTTON_DATA (first_button->next->data)->button;
-
-          gtk_widget_get_preferred_size (child, &child_requisition, NULL);
-
-         if (width + child_requisition.width + slider_space > allocation_width)
-           {
-             reached_end = TRUE;
-           }
-         else
-           {
-             width += child_requisition.width;
-             if (first_button == path_bar->fake_root)
-               break;
-             first_button = first_button->next;
-           }
-       }
-    }
-
-  /* Now, we allocate space to the buttons */
-  child_allocation.y = 0;
-  child_allocation.height = widget_height;
-
-  if (direction == GTK_TEXT_DIR_RTL)
-    {
-      child_allocation.x = widget_width;
-      if (need_sliders || path_bar->fake_root)
-       {
-         child_allocation.x -= path_bar->slider_width;
-         up_slider_offset = widget_width - path_bar->slider_width;
-       }
-    }
-  else
-    {
-      child_allocation.x = 0;
-      if (need_sliders || path_bar->fake_root)
-       {
-         up_slider_offset = 0;
-         child_allocation.x += path_bar->slider_width;
-       }
-    }
-
-  for (list = first_button; list; list = list->prev)
-    {
-      GtkAllocation widget_allocation;
-      ButtonData *button_data;
-
-      button_data = BUTTON_DATA (list->data);
-      child = button_data->button;
-
-      gtk_widget_get_preferred_size (child, &child_requisition, NULL);
-
-      child_allocation.width = MIN (child_requisition.width,
-                                   allocation_width - 2 * path_bar->slider_width);
-
-      if (direction == GTK_TEXT_DIR_RTL)
-       child_allocation.x -= child_allocation.width;
-
-      /* Check to see if we've don't have any more space to allocate buttons */
-      if (need_sliders && direction == GTK_TEXT_DIR_RTL)
-       {
-          gtk_widget_get_allocation (widget, &widget_allocation);
-         if (child_allocation.x - path_bar->slider_width < widget_allocation.x)
-           break;
-       }
-      else if (need_sliders && direction == GTK_TEXT_DIR_LTR)
-       {
-          gtk_widget_get_allocation (widget, &widget_allocation);
-         if (child_allocation.x + child_allocation.width + path_bar->slider_width >
-             widget_allocation.x + allocation_width)
-           break;
-       }
-
-      if (child_allocation.width < child_requisition.width)
-       {
-         if (!gtk_widget_get_has_tooltip (child))
-           gtk_widget_set_tooltip_text (child, button_data->dir_name);
-       }
-      else if (gtk_widget_get_has_tooltip (child))
-       gtk_widget_set_tooltip_text (child, NULL);
-      
-      gtk_widget_set_child_visible (child, TRUE);
-      gtk_widget_size_allocate (child, &child_allocation, baseline);
-
-      if (direction == GTK_TEXT_DIR_RTL)
-        {
-          down_slider_offset = child_allocation.x - path_bar->slider_width;
-        }
-      else
-        {
-          down_slider_offset += child_allocation.width;
-          child_allocation.x += child_allocation.width;
-        }
-    }
-  /* Now we go hide all the widgets that don't fit */
-  while (list)
-    {
-      child = BUTTON_DATA (list->data)->button;
-      gtk_widget_set_child_visible (child, FALSE);
-      list = list->prev;
-    }
-  for (list = first_button->next; list; list = list->next)
-    {
-      child = BUTTON_DATA (list->data)->button;
-      gtk_widget_set_child_visible (child, FALSE);
-    }
-
-  if (need_sliders || path_bar->fake_root)
-    {
-      child_allocation.width = path_bar->slider_width;
-      child_allocation.x = up_slider_offset;
-      gtk_widget_size_allocate (path_bar->up_slider_button,
-                                &child_allocation,
-                                -1);
-
-      gtk_widget_set_child_visible (path_bar->up_slider_button, TRUE);
-      gtk_widget_set_visible (path_bar->up_slider_button, TRUE);
-
-      if (direction == GTK_TEXT_DIR_LTR)
-        down_slider_offset += path_bar->slider_width;
-    }
-  else
-    {
-      gtk_widget_set_child_visible (path_bar->up_slider_button, FALSE);
-    }
-
-  if (need_sliders)
-    {
-      child_allocation.width = path_bar->slider_width;
-      child_allocation.x = down_slider_offset;
-      
-      gtk_widget_size_allocate (path_bar->down_slider_button,
-                                &child_allocation,
-                                -1);
-
-      gtk_widget_set_child_visible (path_bar->down_slider_button, TRUE);
-      gtk_widget_set_visible (path_bar->down_slider_button, TRUE);
-      gtk_path_bar_update_slider_buttons (path_bar);
-    }
-  else
-    {
-      gtk_widget_set_child_visible (path_bar->down_slider_button, FALSE);
-    }
-}
+  GtkWidget *w;
 
-static gboolean
-gtk_path_bar_scroll_controller_scroll (GtkEventControllerScroll *scroll,
-                                       double                    dx,
-                                       double                    dy,
-                                       GtkPathBar               *path_bar)
-{
-  if (dy > 0)
-    gtk_path_bar_scroll_down (path_bar);
-  else if (dy < 0)
-    gtk_path_bar_scroll_up (path_bar);
+  while ((w = gtk_widget_get_first_child (path_bar->buttons_box)) != NULL)
+    gtk_box_remove (GTK_BOX (path_bar->buttons_box), w);
 
-  return GDK_EVENT_STOP;
+  path_bar->fake_root = NULL;
 }
 
 static void
-gtk_path_bar_scroll_down (GtkPathBar *path_bar)
+update_visibility_up_to_next_root (GtkPathBar *path_bar,
+                                   GList      *start_from_button)
 {
-  GtkAllocation allocation, button_allocation;
-  GList *list;
-  GList *down_button = NULL;
-  int space_available;
-
-  if (gtk_widget_get_child_visible (BUTTON_DATA (path_bar->button_list->data)->button))
-    {
-      /* Return if the last button is already visible */
-      return;
-    }
-
-  gtk_widget_queue_resize (GTK_WIDGET (path_bar));
-
-  /* We find the button at the 'down' end that we have to make
-   * visible */
-  for (list = path_bar->button_list; list; list = list->next)
-    {
-      if (list->next && gtk_widget_get_child_visible (BUTTON_DATA (list->next->data)->button))
-       {
-         down_button = list;
-         break;
-       }
-    }
-  g_assert (down_button);
-
-  gtk_widget_get_allocation (GTK_WIDGET (path_bar), &allocation);
-  gtk_widget_get_allocation (BUTTON_DATA (down_button->data)->button, &button_allocation);
-
-  space_available = (allocation.width
-                    - 2 * path_bar->slider_width
-                     - button_allocation.width);
-  path_bar->first_scrolled_button = down_button;
+  gboolean fake_root_found = FALSE;
+  GList *l;
   
-  /* We have space_available free space that's not being used.  
-   * So we walk down from the end, adding buttons until we use all free space.
-   */
-  while (space_available > 0)
-    {
-      path_bar->first_scrolled_button = down_button;
-      down_button = down_button->next;
-      if (!down_button)
-       break;
-      space_available -= button_allocation.width;
-    }
-}
-
-static void
-gtk_path_bar_scroll_up (GtkPathBar *path_bar)
-{
-  GList *list;
-
-  list = g_list_last (path_bar->button_list);
-
-  if (gtk_widget_get_child_visible (BUTTON_DATA (list->data)->button))
+  for (l = start_from_button; l; l = l->next)
     {
-      /* Return if the first button is already visible */
-      return;
-    }
-
-  gtk_widget_queue_resize (GTK_WIDGET (path_bar));
-
-  for ( ; list; list = list->prev)
-    {
-      if (list->prev && gtk_widget_get_child_visible (BUTTON_DATA (list->prev->data)->button))
-       {
-         if (list->prev == path_bar->fake_root)
-           path_bar->fake_root = NULL;
-         path_bar->first_scrolled_button = list;
-         return;
-       }
-    }
-}
-
-static void
-gtk_path_bar_clear_buttons (GtkPathBar *path_bar)
-{
-  GtkWidget *w;
-
-  w = gtk_widget_get_first_child (GTK_WIDGET (path_bar));
-  while (w)
-    {
-      GtkWidget *next = gtk_widget_get_next_sibling (w);
+      GtkWidget *button = BUTTON_DATA (l->data)->button;
 
-      if (w != path_bar->up_slider_button && w != path_bar->down_slider_button)
-        {
-          gtk_widget_unparent (w);
-        }
+      gtk_widget_set_visible (button, !fake_root_found);
 
-      w = next;
+      fake_root_found |= BUTTON_IS_FAKE_ROOT (BUTTON_DATA (l->data));
     }
-
-  path_bar->first_scrolled_button = NULL;
-  path_bar->fake_root = NULL;
 }
 
 static void
@@ -798,7 +332,7 @@ button_clicked_cb (GtkWidget *button,
   if (button_data->ignore_changes)
     return;
 
-  path_bar = GTK_PATH_BAR (gtk_widget_get_parent (button));
+  path_bar = GTK_PATH_BAR (gtk_widget_get_ancestor (button, GTK_TYPE_PATH_BAR));
 
   button_list = g_list_find (path_bar->button_list, button_data);
   g_assert (button_list != NULL);
@@ -809,6 +343,8 @@ button_clicked_cb (GtkWidget *button,
   g_signal_handlers_unblock_by_func (button,
                                     G_CALLBACK (button_clicked_cb), data);
 
+  update_visibility_up_to_next_root (path_bar, button_list);
+
   if (button_list->prev)
     {
       ButtonData *child_data;
@@ -1168,7 +704,6 @@ gtk_path_bar_check_parent_path (GtkPathBar         *path_bar,
 
       if (!gtk_widget_get_child_visible (BUTTON_DATA (current_path->data)->button))
        {
-         path_bar->first_scrolled_button = current_path;
          gtk_widget_queue_resize (GTK_WIDGET (path_bar));
        }
 
@@ -1204,9 +739,11 @@ gtk_path_bar_set_file_finish (struct SetFileInfo *info,
       for (l = info->path_bar->button_list; l; l = l->next)
        {
          GtkWidget *button = BUTTON_DATA (l->data)->button;
-
-          gtk_widget_insert_after (button, GTK_WIDGET (info->path_bar), info->path_bar->up_slider_button);
+          gtk_box_prepend (GTK_BOX (info->path_bar->buttons_box), button);
        }
+
+      update_visibility_up_to_next_root (info->path_bar,
+                                         info->path_bar->button_list);
     }
   else
     {
@@ -1216,7 +753,7 @@ gtk_path_bar_set_file_finish (struct SetFileInfo *info,
         {
           ButtonData *button_data = BUTTON_DATA (l->data);
 
-          gtk_widget_unparent (button_data->button);
+          gtk_box_remove (GTK_BOX (info->path_bar->buttons_box), button_data->button);
         }
 
       g_list_free (info->new_buttons);
index ccd3d56373361acf065b783999dd9c550a0b5024..056d36c8d37e2880282be266ad41d7db65de5cd1 100644 (file)
@@ -1652,7 +1652,15 @@ window.devel {
  * Pathbars *
  ************/
 
-pathbar > button {
+pathbar scrolledwindow undershoot.left {
+  border-left: solid 1px $borders_color;
+}
+
+pathbar scrolledwindow undershoot.right {
+  border-right: solid 1px $borders_color;
+}
+
+pathbar button {
   &.text-button, &.image-button, & {
     padding-left: 4px;
     padding-right: 4px;