[Xfce4-commits] [xfce/thunar] 16/46: thunar-location-buttons: Modernize

noreply at xfce.org noreply at xfce.org
Tue Aug 15 02:35:24 CEST 2017


This is an automated email from the git hooks/post-receive script.

a   n   d   r   e       p   u   s   h   e   d       a       c   o   m   m   i   t       t   o       b   r   a   n   c   h       m   a   s   t   e   r   
   in repository xfce/thunar.

commit a90fb8a4d9c9c21507917cbaa7b4b050c50092be
Author: Jonas Kümmerlin <rgcjonas at gmail.com>
Date:   Wed Aug 19 15:45:42 2015 +0200

    thunar-location-buttons: Modernize
    
    No more deprecated APIs (modulo GtkAction) and now looking gorgeous
    using linked buttons.
---
 thunar/thunar-location-button.c  | 351 ++++++++++++++-------------------------
 thunar/thunar-location-button.h  |   6 -
 thunar/thunar-location-buttons.c | 261 ++++++++++++++++++++++-------
 3 files changed, 330 insertions(+), 288 deletions(-)

diff --git a/thunar/thunar-location-button.c b/thunar/thunar-location-button.c
index e143cec..b843adb 100644
--- a/thunar/thunar-location-button.c
+++ b/thunar/thunar-location-button.c
@@ -40,11 +40,14 @@
 
 
 
+#define THUNAR_LOCATION_BUTTON_MAX_WIDTH 250
+
+
+
 /* Property identifiers */
 enum
 {
   PROP_0,
-  PROP_ACTIVE,
   PROP_FILE,
 };
 
@@ -52,7 +55,6 @@ enum
 enum
 {
   CLICKED,
-  CONTEXT_MENU,
   GONE,
   LAST_SIGNAL,
 };
@@ -68,68 +70,59 @@ static void           thunar_location_button_set_property           (GObject
                                                                      guint                       prop_id,
                                                                      const GValue               *value,
                                                                      GParamSpec                 *pspec);
-static void           thunar_location_button_style_set              (GtkWidget                  *widget,
-                                                                     GtkStyle                   *previous_style);
 static GdkDragAction  thunar_location_button_get_dest_actions       (ThunarLocationButton       *location_button,
                                                                      GdkDragContext             *context,
                                                                      GtkWidget                  *button,
                                                                      guint                       timestamp);
+static void           thunar_location_button_active_changed         (ThunarLocationButton       *location_button);
 static void           thunar_location_button_file_changed           (ThunarLocationButton       *location_button,
                                                                      ThunarFile                 *file);
 static void           thunar_location_button_file_destroy           (ThunarLocationButton       *location_button,
                                                                      ThunarFile                 *file);
-static void           thunar_location_button_align_size_request     (GtkWidget                  *align,
-                                                                     GtkRequisition             *requisition,
-                                                                     ThunarLocationButton       *location_button);
+static void           thunar_location_button_apply_label_size       (ThunarLocationButton       *location_button);
 static gboolean       thunar_location_button_button_press_event     (GtkWidget                  *button,
-                                                                     GdkEventButton             *event,
-                                                                     ThunarLocationButton       *location_button);
+                                                                     GdkEventButton             *event);
 static gboolean       thunar_location_button_button_release_event   (GtkWidget                  *button,
-                                                                     GdkEventButton             *event,
-                                                                     ThunarLocationButton       *location_button);
+                                                                     GdkEventButton             *event);
 static gboolean       thunar_location_button_drag_drop              (GtkWidget                  *button,
                                                                      GdkDragContext             *context,
                                                                      gint                        x,
                                                                      gint                        y,
-                                                                     guint                       timestamp,
-                                                                     ThunarLocationButton       *location_button);
+                                                                     guint                       timestamp);
 static void           thunar_location_button_drag_data_get          (GtkWidget                  *button,
                                                                      GdkDragContext             *context,
                                                                      GtkSelectionData           *selection_data,
                                                                      guint                       info,
-                                                                     guint                       timestamp,
-                                                                     ThunarLocationButton       *location_button);
+                                                                     guint                       timestamp);
 static void           thunar_location_button_drag_data_received     (GtkWidget                  *button,
                                                                      GdkDragContext             *context,
                                                                      gint                        x,
                                                                      gint                        y,
                                                                      GtkSelectionData           *selection_data,
                                                                      guint                       info,
-                                                                     guint                       timestamp,
-                                                                     ThunarLocationButton       *location_button);
+                                                                     guint                       timestamp);
 static void           thunar_location_button_drag_leave             (GtkWidget                  *button,
                                                                      GdkDragContext             *context,
-                                                                     guint                       timestamp,
-                                                                     ThunarLocationButton       *location_button);
+                                                                     guint                       timestamp);
 static gboolean       thunar_location_button_drag_motion            (GtkWidget                  *button,
                                                                      GdkDragContext             *context,
                                                                      gint                        x,
                                                                      gint                        y,
-                                                                     guint                       timestamp,
-                                                                     ThunarLocationButton       *location_button);
+                                                                     guint                       timestamp);
 static gboolean       thunar_location_button_enter_timeout          (gpointer                    user_data);
 static void           thunar_location_button_enter_timeout_destroy  (gpointer                    user_data);
+static void           thunar_location_button_clicked                (ThunarLocationButton       *button);
 
 
 
 struct _ThunarLocationButtonClass
 {
-  GtkAlignmentClass __parent__;
+  GtkToggleButtonClass __parent__;
 };
 
 struct _ThunarLocationButton
 {
-  GtkAlignment __parent__;
+  GtkToggleButton __parent__;
 
   GtkWidget          *image;
   GtkWidget          *label;
@@ -146,7 +139,6 @@ struct _ThunarLocationButton
   guint               drop_occurred : 1;
 
   /* public properties */
-  guint               active : 1;
   ThunarFile         *file;
 };
 
@@ -161,7 +153,7 @@ static guint location_button_signals[LAST_SIGNAL];
 
 
 
-G_DEFINE_TYPE (ThunarLocationButton, thunar_location_button, GTK_TYPE_ALIGNMENT)
+G_DEFINE_TYPE (ThunarLocationButton, thunar_location_button, GTK_TYPE_TOGGLE_BUTTON)
 
 
 
@@ -176,22 +168,6 @@ thunar_location_button_class_init (ThunarLocationButtonClass *klass)
   gobject_class->get_property = thunar_location_button_get_property;
   gobject_class->set_property = thunar_location_button_set_property;
 
-  gtkwidget_class = GTK_WIDGET_CLASS (klass);
-  gtkwidget_class->style_set = thunar_location_button_style_set;
-
-  /**
-   * ThunarLocationButton:active:
-   *
-   * Whether the location button is currently active.
-   **/
-  g_object_class_install_property (gobject_class,
-                                   PROP_ACTIVE,
-                                   g_param_spec_boolean ("active",
-                                                         "active",
-                                                         "active",
-                                                         FALSE,
-                                                         EXO_PARAM_READWRITE));
-
   /**
    * ThunarLocationButton:file:
    *
@@ -206,15 +182,14 @@ thunar_location_button_class_init (ThunarLocationButtonClass *klass)
                                                         EXO_PARAM_READWRITE));
 
   /**
-   * ThunarLocationButton::clicked:
+   * ThunarLocationButton::location-button-clicked:
    * @location_button : a #ThunarLocationButton.
    *
    * Emitted by @location_button when the user clicks on the
-   * @location_button or thunar_location_button_clicked() is
-   * called.
+   * @location_button or gtk_button_clicked() is called.
    **/
   location_button_signals[CLICKED] =
-    g_signal_new (I_("clicked"),
+    g_signal_new (I_("location-button-clicked"),
                   G_TYPE_FROM_CLASS (klass),
                   G_SIGNAL_RUN_LAST,
                   0, NULL, NULL,
@@ -223,22 +198,6 @@ thunar_location_button_class_init (ThunarLocationButtonClass *klass)
                   G_TYPE_BOOLEAN);
 
   /**
-   * ThunarLocationButton::context-menu:
-   * @location_button : a #ThunarLocationButton.
-   * @event           : a #GdkEventButton.
-   *
-   * Emitted by @location_button when the user requests to open
-   * the context menu for @location_button.
-   **/
-  location_button_signals[CONTEXT_MENU] =
-    g_signal_new (I_("context-menu"),
-                  G_TYPE_FROM_CLASS (klass),
-                  G_SIGNAL_RUN_LAST,
-                  0, NULL, NULL,
-                  g_cclosure_marshal_VOID__BOXED,
-                  G_TYPE_NONE, 1, GDK_TYPE_EVENT);
-
-  /**
    * ThunarLocationButton::gone:
    * @location_button : a #ThunarLocationButton.
    *
@@ -257,52 +216,40 @@ thunar_location_button_class_init (ThunarLocationButtonClass *klass)
 
 
 static void
-thunar_location_button_init (ThunarLocationButton *location_button)
+thunar_location_button_init (ThunarLocationButton *button)
 {
-  GtkWidget *align;
-  GtkWidget *button;
   GtkWidget *hbox;
 
-  /* create the toggle button */
-  button = gtk_toggle_button_new ();
-  gtk_widget_set_can_focus (button, FALSE);
-  g_signal_connect_swapped (G_OBJECT (button), "clicked", G_CALLBACK (thunar_location_button_clicked), location_button);
-  exo_mutual_binding_new (G_OBJECT (location_button), "active", G_OBJECT (button), "active");
-  gtk_container_add (GTK_CONTAINER (location_button), button);
-  gtk_widget_show (button);
+  /* initialize the toggle button */
+  g_signal_connect (button, "notify::active", G_CALLBACK (thunar_location_button_active_changed), NULL);
+  g_signal_connect (button, "clicked", G_CALLBACK (thunar_location_button_clicked), NULL);
 
   /* setup drag support for the button */
   gtk_drag_source_set (GTK_WIDGET (button), GDK_BUTTON1_MASK, drag_targets, G_N_ELEMENTS (drag_targets), GDK_ACTION_LINK);
   gtk_drag_dest_set (GTK_WIDGET (button), GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_MOTION, drag_targets,
                      G_N_ELEMENTS (drag_targets), GDK_ACTION_ASK | GDK_ACTION_COPY | GDK_ACTION_LINK | GDK_ACTION_MOVE);
-  g_signal_connect (G_OBJECT (button), "button-press-event", G_CALLBACK (thunar_location_button_button_press_event), location_button);
-  g_signal_connect (G_OBJECT (button), "button-release-event", G_CALLBACK (thunar_location_button_button_release_event), location_button);
-  g_signal_connect (G_OBJECT (button), "drag-drop", G_CALLBACK (thunar_location_button_drag_drop), location_button);
-  g_signal_connect (G_OBJECT (button), "drag-data-get", G_CALLBACK (thunar_location_button_drag_data_get), location_button);
-  g_signal_connect (G_OBJECT (button), "drag-data-received", G_CALLBACK (thunar_location_button_drag_data_received), location_button);
-  g_signal_connect (G_OBJECT (button), "drag-leave", G_CALLBACK (thunar_location_button_drag_leave), location_button);
-  g_signal_connect (G_OBJECT (button), "drag-motion", G_CALLBACK (thunar_location_button_drag_motion), location_button);
+  g_signal_connect (G_OBJECT (button), "button-press-event", G_CALLBACK (thunar_location_button_button_press_event), NULL);
+  g_signal_connect (G_OBJECT (button), "button-release-event", G_CALLBACK (thunar_location_button_button_release_event), NULL);
+  g_signal_connect (G_OBJECT (button), "drag-drop", G_CALLBACK (thunar_location_button_drag_drop), NULL);
+  g_signal_connect (G_OBJECT (button), "drag-data-get", G_CALLBACK (thunar_location_button_drag_data_get), NULL);
+  g_signal_connect (G_OBJECT (button), "drag-data-received", G_CALLBACK (thunar_location_button_drag_data_received), NULL);
+  g_signal_connect (G_OBJECT (button), "drag-leave", G_CALLBACK (thunar_location_button_drag_leave), NULL);
+  g_signal_connect (G_OBJECT (button), "drag-motion", G_CALLBACK (thunar_location_button_drag_motion), NULL);
 
   /* create the horizontal box */
-  hbox = gtk_hbox_new (FALSE, 2);
+  hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
   gtk_container_add (GTK_CONTAINER (button), hbox);
   gtk_widget_show (hbox);
 
   /* create the button image */
-  location_button->image = gtk_image_new ();
-  gtk_box_pack_start (GTK_BOX (hbox), location_button->image, TRUE, FALSE, 0);
-  gtk_widget_show (location_button->image);
-
-  /* create the button label alignment */
-  align = gtk_alignment_new (0.5f, 0.5f, 1.0f, 1.0f);
-  g_signal_connect (G_OBJECT (align), "size-request", G_CALLBACK (thunar_location_button_align_size_request), location_button);
-  gtk_box_pack_start (GTK_BOX (hbox), align, TRUE, TRUE, 0);
-  gtk_widget_show (align);
+  button->image = gtk_image_new ();
+  gtk_box_pack_start (GTK_BOX (hbox), button->image, TRUE, FALSE, 0);
+  gtk_widget_show (button->image);
 
   /* create the button label */
-  location_button->label = g_object_new (GTK_TYPE_LABEL, NULL);
-  gtk_container_add (GTK_CONTAINER (align), location_button->label);
-  gtk_widget_show (location_button->label);
+  button->label = g_object_new (GTK_TYPE_LABEL, "xalign", 0.5f, "yalign", 0.5f, NULL);
+  gtk_box_pack_start (GTK_BOX (hbox), button->label, TRUE, TRUE, 0);
+  gtk_widget_show (button->label);
 }
 
 
@@ -337,10 +284,6 @@ thunar_location_button_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_ACTIVE:
-      g_value_set_boolean (value, thunar_location_button_get_active (location_button));
-      break;
-
     case PROP_FILE:
       g_value_set_object (value, thunar_location_button_get_file (location_button));
       break;
@@ -363,10 +306,6 @@ thunar_location_button_set_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_ACTIVE:
-      thunar_location_button_set_active (location_button, g_value_get_boolean (value));
-      break;
-
     case PROP_FILE:
       thunar_location_button_set_file (location_button, g_value_get_object (value));
       break;
@@ -379,21 +318,6 @@ thunar_location_button_set_property (GObject      *object,
 
 
 
-static void
-thunar_location_button_style_set (GtkWidget *widget,
-                                  GtkStyle  *previous_style)
-{
-  ThunarLocationButton *location_button = THUNAR_LOCATION_BUTTON (widget);
-
-  /* update the user interface if we have a file */
-  if (G_LIKELY (location_button->file != NULL))
-    thunar_location_button_file_changed (location_button, location_button->file);
-
-  (*GTK_WIDGET_CLASS (thunar_location_button_parent_class)->style_set) (widget, previous_style);
-}
-
-
-
 static GdkDragAction
 thunar_location_button_get_dest_actions (ThunarLocationButton *location_button,
                                          GdkDragContext       *context,
@@ -442,22 +366,25 @@ thunar_location_button_file_changed (ThunarLocationButton *location_button,
   /* update and show the label widget (hide for the local root folder) */
   if (thunar_file_is_local (file) && thunar_file_is_root (file)) 
     {
-      /* hide the alignment in which the label would otherwise show up */
-      gtk_widget_hide (gtk_widget_get_parent (location_button->label));
+      /* hide the label would otherwise show up */
+      gtk_widget_hide (location_button->label);
     }
   else
     {
-      /* set label to the file's display name and show the alignment (and thereby the label) */
+      /* set label to the file's display name and show the label */
       gtk_label_set_text (GTK_LABEL (location_button->label), thunar_file_get_display_name (file));
-      gtk_widget_show (gtk_widget_get_parent (location_button->label));
+
+      /* set the label's size request in such a way that a bold label will not change the button size */
+      thunar_location_button_apply_label_size (location_button);
+
+      gtk_widget_show (location_button->label);
     }
 
   /* the image is only visible for certain special paths */
   if (thunar_file_is_home (file) || thunar_file_is_desktop (file) || thunar_file_is_root (file))
     {
       /* determine the icon size for menus (to be compatible with GtkPathBar) */
-      settings = gtk_settings_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (location_button)));
-      if (gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU, &width, &height))
+      if (gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height))
         size = MAX (width, height);
       else
         size = 16;
@@ -485,12 +412,12 @@ thunar_location_button_file_changed (ThunarLocationButton *location_button,
   custom_icon = thunar_file_get_custom_icon (file);
   if (custom_icon != NULL)
     {
-      gtk_drag_source_set_icon_name (gtk_bin_get_child (GTK_BIN (location_button)), custom_icon);
+      gtk_drag_source_set_icon_name (GTK_WIDGET (location_button), custom_icon);
     }
   else
     {
       icon_name = thunar_file_get_icon_name (file, location_button->file_icon_state, icon_theme);
-      gtk_drag_source_set_icon_name (gtk_bin_get_child (GTK_BIN (location_button)), icon_name);
+      gtk_drag_source_set_icon_name (GTK_WIDGET (location_button), icon_name);
     }
 }
 
@@ -511,45 +438,57 @@ thunar_location_button_file_destroy (ThunarLocationButton *location_button,
 
 
 static void
-thunar_location_button_align_size_request (GtkWidget            *align,
-                                           GtkRequisition       *requisition,
-                                           ThunarLocationButton *location_button)
+thunar_location_button_apply_label_size (ThunarLocationButton *location_button)
 {
-  PangoLayout *layout;
-  gint         normal_height;
-  gint         normal_width;
-  gint         bold_height;
-  gint         bold_width;
+  GtkRequisition normal_size;
+  GtkRequisition bold_size;
+  gint           width, height;
+  PangoAttrList *original_attrs;
+
+  original_attrs = pango_attr_list_ref (gtk_label_get_attributes (GTK_LABEL (location_button->label)));
 
-  /* allocate a pango layout for the label text */
-  layout = gtk_widget_create_pango_layout (location_button->label, gtk_label_get_text (GTK_LABEL (location_button->label)));
+  /* determine the normal size */
+  gtk_label_set_attributes (GTK_LABEL (location_button->label), NULL);
+  gtk_widget_get_preferred_size (location_button->label, NULL, &normal_size);
 
-  /* determine the normal pixel size */
-  pango_layout_get_pixel_size (layout, &normal_width, &normal_height);
+  /* determine the bold size */
+  gtk_label_set_attributes (GTK_LABEL (location_button->label), thunar_pango_attr_list_bold());
+  gtk_widget_get_preferred_size (location_button->label, NULL, &bold_size);
 
-  /* determine the bold pixel size */
-  pango_layout_set_attributes (layout, thunar_pango_attr_list_bold ());
-  pango_layout_get_pixel_size (layout, &bold_width, &bold_height);
+  /* restore original attributes */
+  gtk_label_set_attributes (GTK_LABEL (location_button->label), original_attrs);
+  pango_attr_list_unref (original_attrs);
 
   /* request the maximum of the pixel sizes, to make sure
    * the button always requests the same size, no matter if
    * the label is bold or not.
    */
-  requisition->width = MAX (bold_width, normal_width);
-  requisition->height = MAX (bold_height, normal_height);
+  width = MAX (normal_size.width, bold_size.width);
+  height = MAX (normal_size.height, bold_size.height);
 
-  /* cleanup */
-  g_object_unref (G_OBJECT (layout));
+  if (width >= THUNAR_LOCATION_BUTTON_MAX_WIDTH)
+    {
+      /* if the size is too big, enable ellipsizing */
+      gtk_label_set_ellipsize (GTK_LABEL (location_button->label), PANGO_ELLIPSIZE_MIDDLE);
+      gtk_widget_set_size_request (GTK_WIDGET (location_button->label), THUNAR_LOCATION_BUTTON_MAX_WIDTH, height);
+    }
+  else
+    {
+      /* don't enable ellipsizing: In some borderline cases, the size calculated
+       * is actually off by 1 or 2 pixels and the label will ellipsize unnecessarily
+       * TODO: check what we did wrong */
+      gtk_widget_set_size_request (GTK_WIDGET (location_button->label), width, height);
+    }
 }
 
 
 
 static gboolean
 thunar_location_button_button_press_event (GtkWidget            *button,
-                                           GdkEventButton       *event,
-                                           ThunarLocationButton *location_button)
+                                           GdkEventButton       *event)
 {
-  _thunar_return_val_if_fail (THUNAR_IS_LOCATION_BUTTON (location_button), FALSE);
+  _thunar_return_val_if_fail (THUNAR_IS_LOCATION_BUTTON (button), FALSE);
+  gboolean popup_menu_return;
 
   /* check if we can handle the button event */
   if (G_UNLIKELY (event->button == 2))
@@ -559,8 +498,8 @@ thunar_location_button_button_press_event (GtkWidget            *button,
     }
   else if (event->button == 3)
     {
-      /* emit the "context-menu" signal and let the surrounding ThunarLocationButtons popup a menu */
-      g_signal_emit (G_OBJECT (location_button), location_button_signals[CONTEXT_MENU], 0, event);
+      /* emit the "popup-menu" signal and let the surrounding ThunarLocationButtons popup a menu */
+      g_signal_emit_by_name (G_OBJECT (button), "popup-menu", &popup_menu_return);
       return TRUE;
     }
 
@@ -571,14 +510,13 @@ thunar_location_button_button_press_event (GtkWidget            *button,
 
 static gboolean
 thunar_location_button_button_release_event (GtkWidget            *button,
-                                             GdkEventButton       *event,
-                                             ThunarLocationButton *location_button)
+                                             GdkEventButton       *event)
 {
   ThunarApplication *application;
   ThunarPreferences *preferences;
   gboolean           open_in_tab;
 
-  _thunar_return_val_if_fail (THUNAR_IS_LOCATION_BUTTON (location_button), FALSE);
+  _thunar_return_val_if_fail (THUNAR_IS_LOCATION_BUTTON (button), FALSE);
 
   /* reset inconsistent button state after releasing the middle-mouse-button */
   if (G_UNLIKELY (event->button == 2))
@@ -587,7 +525,7 @@ thunar_location_button_button_release_event (GtkWidget            *button,
       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), FALSE);
 
       /* verify that we still have a valid file */
-      if (G_LIKELY (location_button->file != NULL))
+      if (G_LIKELY (THUNAR_LOCATION_BUTTON (button)->file != NULL))
         {
           preferences = thunar_preferences_get ();
           g_object_get (preferences, "misc-middle-click-in-tab", &open_in_tab, NULL);
@@ -596,13 +534,13 @@ thunar_location_button_button_release_event (GtkWidget            *button,
           if (open_in_tab)
             {
               /* open in tab */
-              g_signal_emit (G_OBJECT (location_button), location_button_signals[CLICKED], 0, TRUE);
+              g_signal_emit_by_name (G_OBJECT (button), "location-button-clicked", 0, TRUE);
             }
           else
             {
               /* open a new window for the folder */
               application = thunar_application_get ();
-              thunar_application_open_window (application, location_button->file, gtk_widget_get_screen (GTK_WIDGET (location_button)), NULL);
+              thunar_application_open_window (application, THUNAR_LOCATION_BUTTON (button)->file, gtk_widget_get_screen (button), NULL);
               g_object_unref (G_OBJECT (application));
             }
         }
@@ -618,13 +556,12 @@ thunar_location_button_drag_drop (GtkWidget            *button,
                                   GdkDragContext       *context,
                                   gint                  x,
                                   gint                  y,
-                                  guint                 timestamp,
-                                  ThunarLocationButton *location_button)
+                                  guint                 timestamp)
 {
   GdkAtom target;
 
   _thunar_return_val_if_fail (GTK_IS_WIDGET (button), FALSE);
-  _thunar_return_val_if_fail (THUNAR_IS_LOCATION_BUTTON (location_button), FALSE);
+  _thunar_return_val_if_fail (THUNAR_IS_LOCATION_BUTTON (button), FALSE);
 
   /* determine the DnD target and see if we can handle it */
   target = gtk_drag_dest_find_target (button, context, NULL);
@@ -634,7 +571,7 @@ thunar_location_button_drag_drop (GtkWidget            *button,
   /* set state so drag-data-received knows that
    * this is really a drop this time.
    */
-  location_button->drop_occurred = TRUE;
+  THUNAR_LOCATION_BUTTON (button)->drop_occurred = TRUE;
 
   /* request the drag data from the source */
   gtk_drag_get_data (button, context, target, timestamp);
@@ -650,21 +587,20 @@ thunar_location_button_drag_data_get (GtkWidget            *button,
                                       GdkDragContext       *context,
                                       GtkSelectionData     *selection_data,
                                       guint                 info,
-                                      guint                 timestamp,
-                                      ThunarLocationButton *location_button)
+                                      guint                 timestamp)
 {
   gchar **uris;
   GList   path_list;
 
   _thunar_return_if_fail (GTK_IS_WIDGET (button));
-  _thunar_return_if_fail (THUNAR_IS_LOCATION_BUTTON (location_button));
+  _thunar_return_if_fail (THUNAR_IS_LOCATION_BUTTON (button));
 
   /* verify that we have a valid file */
-  if (G_LIKELY (location_button->file != NULL))
+  if (G_LIKELY (THUNAR_LOCATION_BUTTON (button)->file != NULL))
     {
       /* transform the path into an uri list string */
       path_list.next = path_list.prev = NULL;
-      path_list.data = thunar_file_get_file (location_button->file);
+      path_list.data = thunar_file_get_file (THUNAR_LOCATION_BUTTON (button)->file);
 
       /* set the uri list for the drag selection */
       uris = thunar_g_file_list_to_stringv (&path_list);
@@ -682,12 +618,12 @@ thunar_location_button_drag_data_received (GtkWidget            *button,
                                            gint                  y,
                                            GtkSelectionData     *selection_data,
                                            guint                 info,
-                                           guint                 timestamp,
-                                           ThunarLocationButton *location_button)
+                                           guint                 timestamp)
 {
-  GdkDragAction actions;
-  GdkDragAction action;
-  gboolean      succeed = FALSE;
+  GdkDragAction         actions;
+  GdkDragAction         action;
+  gboolean              succeed = FALSE;
+  ThunarLocationButton *location_button = THUNAR_LOCATION_BUTTON (button);
 
   /* check if we don't already know the drop data */
   if (G_LIKELY (!location_button->drop_data_ready))
@@ -724,7 +660,7 @@ thunar_location_button_drag_data_received (GtkWidget            *button,
       gtk_drag_finish (context, succeed, FALSE, timestamp);
 
       /* disable the highlighting and release the drag data */
-      thunar_location_button_drag_leave (button, context, timestamp, location_button);
+      thunar_location_button_drag_leave (button, context, timestamp);
     }
 }
 
@@ -733,11 +669,12 @@ thunar_location_button_drag_data_received (GtkWidget            *button,
 static void
 thunar_location_button_drag_leave (GtkWidget            *button,
                                    GdkDragContext       *context,
-                                   guint                 timestamp,
-                                   ThunarLocationButton *location_button)
+                                   guint                 timestamp)
 {
   _thunar_return_if_fail (GTK_IS_BUTTON (button));
-  _thunar_return_if_fail (THUNAR_IS_LOCATION_BUTTON (location_button));
+  _thunar_return_if_fail (THUNAR_IS_LOCATION_BUTTON (button));
+
+  ThunarLocationButton *location_button = THUNAR_LOCATION_BUTTON (button);
 
   /* reset the file icon state to default appearance */
   if (G_LIKELY (location_button->file_icon_state != THUNAR_FILE_ICON_STATE_DEFAULT))
@@ -770,14 +707,14 @@ thunar_location_button_drag_motion (GtkWidget            *button,
                                     GdkDragContext       *context,
                                     gint                  x,
                                     gint                  y,
-                                    guint                 timestamp,
-                                    ThunarLocationButton *location_button)
+                                    guint                 timestamp)
 {
-  ThunarFileIconState file_icon_state;
-  GdkDragAction       actions;
-  GtkSettings        *settings;
-  GdkAtom             target;
-  gint                delay;
+  ThunarFileIconState   file_icon_state;
+  ThunarLocationButton *location_button = THUNAR_LOCATION_BUTTON (button);
+  GdkDragAction         actions;
+  GtkSettings          *settings;
+  GdkAtom               target;
+  gint                  delay;
 
   _thunar_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
   _thunar_return_val_if_fail (THUNAR_IS_LOCATION_BUTTON (location_button), FALSE);
@@ -785,13 +722,15 @@ thunar_location_button_drag_motion (GtkWidget            *button,
   /* schedule the enter timeout if not already done */
   if (G_UNLIKELY (location_button->enter_timeout_id == 0))
     {
-      /* we use the gtk-menu-popdown-delay here, which seems to be sane for our purpose */
-      settings = gtk_settings_get_for_screen (gtk_widget_get_screen (button));
-      g_object_get (G_OBJECT (settings), "gtk-menu-popdown-delay", &delay, NULL);
+      /* we used to use gtk-menu-popdown-delay here, but this was never right and is now deprecated */
+      /* therefore, we hardcode the value instead. */
+      delay = 1000;
 
       /* schedule the timeout */
-      location_button->enter_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, delay, thunar_location_button_enter_timeout,
-                                                              location_button, thunar_location_button_enter_timeout_destroy);
+      location_button->enter_timeout_id = gdk_threads_add_timeout_full (G_PRIORITY_DEFAULT, delay,
+                                                                        thunar_location_button_enter_timeout,
+                                                                        location_button,
+                                                                        thunar_location_button_enter_timeout_destroy);
     }
 
   /* request the drop on-demand (if we don't have it already) */
@@ -838,8 +777,6 @@ thunar_location_button_enter_timeout (gpointer user_data)
 {
   ThunarLocationButton *location_button = THUNAR_LOCATION_BUTTON (user_data);
 
-  GDK_THREADS_ENTER ();
-
   /* We emulate a "clicked" event here, because else the buttons
    * would be destroyed and replaced by new buttons, which causes
    * the Gtk DND code to dump core once the mouse leaves the area
@@ -848,9 +785,7 @@ thunar_location_button_enter_timeout (gpointer user_data)
    * Besides that, handling this as "clicked" event allows the user
    * to go back to the initial directory.
    */
-  thunar_location_button_clicked (location_button);
-
-  GDK_THREADS_LEAVE ();
+  gtk_button_clicked (GTK_BUTTON (location_button));
 
   return FALSE;
 }
@@ -880,44 +815,15 @@ thunar_location_button_new (void)
 
 
 
-/**
- * thunar_location_button_get_active:
- * @location_button : a #ThunarLocationButton.
- *
- * Returns %TRUE if @location_button is currently active.
- *
- * Return value: %TRUE if @location_button is currently active.
- **/
-gboolean
-thunar_location_button_get_active (ThunarLocationButton *location_button)
-{
-  _thunar_return_val_if_fail (THUNAR_IS_LOCATION_BUTTON (location_button), FALSE);
-  return location_button->active;
-}
-
-
-
-/**
- * thunar_location_button_set_active:
- * @location_button : a #ThunarLocationButton.
- * @active          : %TRUE if @location_button should be active.
- *
- * Sets the active state of @location_button to @active.
- **/
-void
-thunar_location_button_set_active (ThunarLocationButton *location_button,
-                                   gboolean              active)
+static void
+thunar_location_button_active_changed (ThunarLocationButton *location_button)
 {
   _thunar_return_if_fail (THUNAR_IS_LOCATION_BUTTON (location_button));
 
-  /* apply the new state */
-  location_button->active = active;
+  gboolean active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (location_button));
 
   /* use a bold label for active location buttons */
   gtk_label_set_attributes (GTK_LABEL (location_button->label), active ? thunar_pango_attr_list_bold () : NULL);
-
-  /* notify listeners */
-  g_object_notify (G_OBJECT (location_button), "active");
 }
 
 
@@ -985,9 +891,8 @@ thunar_location_button_set_file (ThunarLocationButton *location_button,
       g_signal_connect_swapped (G_OBJECT (file), "changed", G_CALLBACK (thunar_location_button_file_changed), location_button);
       g_signal_connect_swapped (G_OBJECT (file), "destroy", G_CALLBACK (thunar_location_button_file_destroy), location_button);
 
-      /* update our internal state for the new file (if realized) */
-      if (gtk_widget_get_realized (GTK_WIDGET (location_button)))
-        thunar_location_button_file_changed (location_button, file);
+      /* update our internal state for the new file */
+      thunar_location_button_file_changed (location_button, file);
     }
 
   /* notify listeners */
@@ -1000,7 +905,7 @@ thunar_location_button_set_file (ThunarLocationButton *location_button,
  * thunar_location_button_clicked:
  * @location_button : a #ThunarLocationButton.
  *
- * Emits the ::clicked signal on @location_button.
+ * Emits the ::location-button-clicked signal on @location_button.
  **/
 void
 thunar_location_button_clicked (ThunarLocationButton *location_button)
diff --git a/thunar/thunar-location-button.h b/thunar/thunar-location-button.h
index f00d4b6..adecf9a 100644
--- a/thunar/thunar-location-button.h
+++ b/thunar/thunar-location-button.h
@@ -38,16 +38,10 @@ GType       thunar_location_button_get_type   (void) G_GNUC_CONST;
 
 GtkWidget  *thunar_location_button_new        (void) G_GNUC_MALLOC;
 
-gboolean    thunar_location_button_get_active (ThunarLocationButton *location_button);
-void        thunar_location_button_set_active (ThunarLocationButton *location_button,
-                                               gboolean              active);
-
 ThunarFile *thunar_location_button_get_file   (ThunarLocationButton *location_button);
 void        thunar_location_button_set_file   (ThunarLocationButton *location_button,
                                                ThunarFile           *file);
 
-void        thunar_location_button_clicked    (ThunarLocationButton *location_button);
-
 G_END_DECLS;
 
 #endif /* !__THUNAR_LOCATION_BUTTON_H__ */
diff --git a/thunar/thunar-location-buttons.c b/thunar/thunar-location-buttons.c
index 057b91a..86a063a 100644
--- a/thunar/thunar-location-buttons.c
+++ b/thunar/thunar-location-buttons.c
@@ -79,6 +79,9 @@ static void           thunar_location_buttons_get_preferred_width       (GtkWidg
 static void           thunar_location_buttons_get_preferred_height      (GtkWidget                  *widget,
                                                                          gint                       *minimum,
                                                                          gint                       *natural);
+static GtkWidgetPath *thunar_location_buttons_get_path_for_child        (GtkContainer               *container,
+                                                                         GtkWidget                  *child);
+static void           thunar_location_buttons_child_ordering_changed    (ThunarLocationButtons      *buttons);
 static void           thunar_location_buttons_size_allocate             (GtkWidget                  *widget,
                                                                          GtkAllocation              *allocation);
 static void           thunar_location_buttons_state_changed             (GtkWidget                  *widget,
@@ -97,6 +100,8 @@ static GtkWidget     *thunar_location_buttons_make_button               (ThunarL
                                                                          ThunarFile                 *file);
 static void           thunar_location_buttons_remove_1                  (GtkContainer               *container,
                                                                          GtkWidget                  *widget);
+static gboolean       thunar_location_buttons_draw                      (GtkWidget                  *buttons,
+                                                                         cairo_t                    *cr);
 static gboolean       thunar_location_buttons_scroll_timeout            (gpointer                    user_data);
 static void           thunar_location_buttons_scroll_timeout_destroy    (gpointer                    user_data);
 static void           thunar_location_buttons_stop_scrolling            (ThunarLocationButtons      *buttons);
@@ -114,8 +119,7 @@ static void           thunar_location_buttons_scroll_right              (GtkWidg
 static void           thunar_location_buttons_clicked                   (ThunarLocationButton       *button,
                                                                          gboolean                    open_in_tab,
                                                                          ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_context_menu              (ThunarLocationButton       *button,
-                                                                         GdkEventButton             *event,
+static gboolean       thunar_location_buttons_context_menu              (ThunarLocationButton       *button,
                                                                          ThunarLocationButtons      *buttons);
 static void           thunar_location_buttons_gone                      (ThunarLocationButton       *button,
                                                                          ThunarLocationButtons      *buttons);
@@ -207,6 +211,7 @@ thunar_location_buttons_class_init (ThunarLocationButtonsClass *klass)
   gobject_class->set_property = thunar_location_buttons_set_property;
 
   gtkwidget_class = GTK_WIDGET_CLASS (klass);
+  gtkwidget_class->draw = thunar_location_buttons_draw;
   gtkwidget_class->unmap = thunar_location_buttons_unmap;
   gtkwidget_class->get_preferred_width = thunar_location_buttons_get_preferred_width;
   gtkwidget_class->get_preferred_height = thunar_location_buttons_get_preferred_height;
@@ -218,6 +223,7 @@ thunar_location_buttons_class_init (ThunarLocationButtonsClass *klass)
   gtkcontainer_class->add = thunar_location_buttons_add;
   gtkcontainer_class->remove = thunar_location_buttons_remove;
   gtkcontainer_class->forall = thunar_location_buttons_forall;
+  gtkcontainer_class->get_path_for_child = thunar_location_buttons_get_path_for_child;
 
   /* Override ThunarNavigator's properties */
   g_object_class_override_property (gobject_class, PROP_CURRENT_DIRECTORY, "current-directory");
@@ -292,7 +298,7 @@ thunar_location_buttons_init (ThunarLocationButtons *buttons)
   gtk_container_add (GTK_CONTAINER (buttons), buttons->left_slider);
   gtk_widget_show (buttons->left_slider);
 
-  arrow = gtk_arrow_new (GTK_ARROW_LEFT, GTK_SHADOW_OUT);
+  arrow = gtk_image_new_from_icon_name ("pan-start-symbolic", GTK_ICON_SIZE_BUTTON);
   gtk_container_add (GTK_CONTAINER (buttons->left_slider), arrow);
   gtk_widget_show (arrow);
 
@@ -303,9 +309,15 @@ thunar_location_buttons_init (ThunarLocationButtons *buttons)
   gtk_container_add (GTK_CONTAINER (buttons), buttons->right_slider);
   gtk_widget_show (buttons->right_slider);
 
-  arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_OUT);
+  arrow = gtk_image_new_from_icon_name ("pan-end-symbolic", GTK_ICON_SIZE_BUTTON);
   gtk_container_add (GTK_CONTAINER (buttons->right_slider), arrow);
   gtk_widget_show (arrow);
+
+  /* setup style classes */
+  gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (buttons)),
+                               GTK_STYLE_CLASS_LINKED);
+  gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (buttons)),
+                               "path-bar");
 }
 
 
@@ -479,7 +491,7 @@ thunar_location_buttons_set_current_directory (ThunarNavigator *navigator,
   if (G_UNLIKELY (lp != NULL))
     {
       /* fake a "clicked" event for that button */
-      thunar_location_button_clicked (THUNAR_LOCATION_BUTTON (lp->data));
+      gtk_button_clicked (GTK_BUTTON (lp->data));
     }
   else
     {
@@ -503,8 +515,6 @@ thunar_location_buttons_set_current_directory (ThunarNavigator *navigator,
         {
           g_object_ref (G_OBJECT (current_directory));
 
-          gtk_widget_push_composite_child ();
-
           /* add the new buttons */
           for (file = current_directory; file != NULL; file = file_parent)
             {
@@ -523,8 +533,6 @@ thunar_location_buttons_set_current_directory (ThunarNavigator *navigator,
               if (G_LIKELY (file != current_directory))
                 g_object_unref (G_OBJECT (file));
             }
-
-          gtk_widget_pop_composite_child ();
         }
     }
 
@@ -594,6 +602,108 @@ thunar_location_buttons_get_preferred_height (GtkWidget *widget,
 
 
 
+static GtkWidgetPath *
+thunar_location_buttons_get_path_for_child (GtkContainer *container,
+                                            GtkWidget    *child)
+{
+  ThunarLocationButtons *path_bar = THUNAR_LOCATION_BUTTONS (container);
+  GtkWidgetPath *path;
+
+  path = gtk_widget_path_copy (gtk_widget_get_path (GTK_WIDGET (path_bar)));
+
+  if (gtk_widget_get_visible (child) &&
+      gtk_widget_get_child_visible (child))
+    {
+      GtkWidgetPath *sibling_path;
+      GList *visible_children;
+      GList *l;
+      int pos;
+
+      /* 1. Build the list of visible children, in visually left-to-right order
+        * (i.e. independently of the widget's direction).  Note that our
+        * list is stored in innermost-to-outermost path order!
+        */
+      visible_children = NULL;
+
+      if (gtk_widget_get_visible (path_bar->right_slider) &&
+          gtk_widget_get_child_visible (path_bar->right_slider))
+        {
+          visible_children = g_list_prepend (visible_children, path_bar->right_slider);
+        }
+
+      for (l = path_bar->list; l; l = l->next)
+        {
+          if (gtk_widget_get_visible (GTK_WIDGET (l->data)) &&
+              gtk_widget_get_child_visible (GTK_WIDGET (l->data)))
+            visible_children = g_list_prepend (visible_children, l->data);
+        }
+
+      if (gtk_widget_get_visible (path_bar->left_slider) &&
+          gtk_widget_get_child_visible (path_bar->left_slider))
+        {
+          visible_children = g_list_prepend (visible_children, path_bar->left_slider);
+        }
+
+      if (gtk_widget_get_direction (GTK_WIDGET (path_bar)) == GTK_TEXT_DIR_RTL)
+        {
+          visible_children = g_list_reverse (visible_children);
+        }
+
+      /* 2. Find the index of the child within that list */
+      pos = 0;
+
+      for (l = visible_children; l; l = l->next)
+        {
+          GtkWidget *button = l->data;
+
+          if (button == child)
+            break;
+
+          pos++;
+        }
+
+      /* 3. Build the path */
+      sibling_path = gtk_widget_path_new ();
+
+      for (l = visible_children; l; l = l->next)
+        {
+          gtk_widget_path_append_for_widget (sibling_path, l->data);
+        }
+
+      gtk_widget_path_append_with_siblings (path, sibling_path, pos);
+
+      g_list_free (visible_children);
+      gtk_widget_path_unref (sibling_path);
+    }
+  else
+    {
+      gtk_widget_path_append_for_widget (path, child);
+    }
+
+  return path;
+}
+
+
+
+static void
+thunar_location_buttons_child_ordering_changed (ThunarLocationButtons *location_buttons)
+{
+  GList *lp;
+
+  if (gtk_widget_get_visible (location_buttons->left_slider) &&
+      gtk_widget_get_child_visible (location_buttons->left_slider))
+    gtk_widget_reset_style (location_buttons->right_slider);
+
+  if (gtk_widget_get_visible (location_buttons->right_slider) &&
+      gtk_widget_get_child_visible (location_buttons->right_slider))
+    gtk_widget_reset_style (location_buttons->right_slider);
+
+  for (lp = location_buttons->list; lp; lp = lp->next)
+    gtk_widget_reset_style (GTK_WIDGET (lp->data));
+}
+
+
+
 static void
 thunar_location_buttons_size_allocate (GtkWidget     *widget,
                                        GtkAllocation *allocation)
@@ -603,6 +713,7 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
   GtkAllocation          child_allocation;
   GtkWidget             *child;
   gboolean               need_sliders = FALSE;
+  gboolean               need_reorder = FALSE;
   gboolean               reached_end;
   GList                 *first_button;
   GList                 *lp;
@@ -611,8 +722,8 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
   gint                   allocation_width;
   gint                   border_width;
   gint                   slider_space;
-  gint                   spacing;
   gint                   width;
+  GtkRequisition         child_requisition;
 
   gtk_widget_set_allocation (widget, allocation);
 
@@ -620,21 +731,20 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
   if (G_UNLIKELY (buttons->list == NULL))
     return;
 
-  gtk_widget_style_get (GTK_WIDGET (buttons), "spacing", &spacing, NULL);
-
   direction = gtk_widget_get_direction (widget);
   border_width = gtk_container_get_border_width (GTK_CONTAINER (buttons));
   allocation_width = allocation->width - 2 * border_width;
 
   /* check if we need to display the sliders */
   if (G_LIKELY (buttons->fake_root_button != NULL))
-    width = buttons->slider_width + spacing;
+    width = buttons->slider_width;
   else
     width = 0;
 
   for (lp = buttons->list; lp != NULL; lp = lp->next)
     {
-      width += thunar_gtk_widget_get_requisition_width (GTK_WIDGET (lp->data)) + spacing;
+      gtk_widget_get_preferred_size (GTK_WIDGET (lp->data), &child_requisition, NULL);
+      width += child_requisition.width;
       if (lp == buttons->fake_root_button)
         break;
     }
@@ -645,10 +755,13 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
         first_button = buttons->fake_root_button;
       else
         first_button = g_list_last (buttons->list);
+
+      /* reset the scroll position */
+      buttons->first_scrolled_button = NULL;
     }
   else
     {
-      slider_space = 2 * (spacing + buttons->slider_width);
+      slider_space = 2 * buttons->slider_width;
 
       if (buttons->first_scrolled_button != NULL)
         first_button = buttons->first_scrolled_button;
@@ -660,30 +773,35 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
        * We start at the first button, count forward until hit the new
        * button, then count backwards.
        */
-      width = thunar_gtk_widget_get_requisition_width (GTK_WIDGET (first_button->data));
+      gtk_widget_get_preferred_size (GTK_WIDGET (first_button->data), &child_requisition, NULL);
+      width = child_requisition.width;
       for (lp = first_button->prev, reached_end = FALSE; lp != NULL && !reached_end; lp = lp->prev)
         {
           child = lp->data;
 
-          if (width + thunar_gtk_widget_get_requisition_width (child) + spacing + slider_space > allocation_width)
+          gtk_widget_get_preferred_size (GTK_WIDGET (child), &child_requisition, NULL);
+
+          if (width + child_requisition.width + slider_space > allocation_width)
             reached_end = TRUE;
           else if (lp == buttons->fake_root_button)
             break;
           else
-            width += thunar_gtk_widget_get_requisition_width (child) + spacing;
+            width += child_requisition.width;
         }
 
       while (first_button->next != NULL && !reached_end)
         {
           child = first_button->data;
 
-          if (width + thunar_gtk_widget_get_requisition_width (child) + spacing + slider_space > allocation_width)
+          gtk_widget_get_preferred_size (GTK_WIDGET (child), &child_requisition, NULL);
+
+          if (width + child_requisition.width + slider_space > allocation_width)
             {
               reached_end = TRUE;
             }
           else
             {
-              width += thunar_gtk_widget_get_requisition_width (child) + spacing;
+              width += child_requisition.width;
               if (first_button == buttons->fake_root_button)
                 break;
               first_button = first_button->next;
@@ -700,7 +818,7 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
       child_allocation.x = allocation->x + allocation->width - border_width;
       if (need_sliders || buttons->fake_root_button != NULL)
         {
-          child_allocation.x -= spacing + buttons->slider_width;
+          child_allocation.x -= buttons->slider_width;
           left_slider_offset = allocation->width - border_width - buttons->slider_width;
         }
     }
@@ -710,18 +828,14 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
       if (need_sliders || buttons->fake_root_button != NULL)
         {
           left_slider_offset = border_width;
-          child_allocation.x += spacing + buttons->slider_width;
+          child_allocation.x += buttons->slider_width;
         }
     }
 
   for (lp = first_button; lp != NULL; lp = lp->prev)
     {
-      GtkRequisition child_requisition;
-      GtkAllocation  widget_allocation;
-
       child = lp->data;
-      gtk_widget_get_requisition (child, &child_requisition);
-      gtk_widget_get_allocation (widget, &widget_allocation);
+      gtk_widget_get_preferred_size (child, &child_requisition, NULL);
 
       child_allocation.width = child_requisition.width;
       if (G_UNLIKELY (direction == GTK_TEXT_DIR_RTL))
@@ -730,41 +844,48 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
       /* check to see if we don't have any more space to allocate buttons */
       if (need_sliders && direction == GTK_TEXT_DIR_RTL)
         {
-          if (child_allocation.x - spacing - buttons->slider_width < widget_allocation.x + border_width)
+          if (child_allocation.x - buttons->slider_width < allocation->x + border_width)
             break;
         }
       else if (need_sliders && direction == GTK_TEXT_DIR_LTR)
         {
-          if (child_allocation.x + child_allocation.width + spacing + buttons->slider_width > widget_allocation.x + border_width + allocation_width)
+          if (child_allocation.x + child_allocation.width + buttons->slider_width > allocation->x + border_width + allocation_width)
             break;
         }
 
+      need_reorder |= gtk_widget_get_child_visible (GTK_WIDGET (lp->data)) == FALSE;
       gtk_widget_set_child_visible (GTK_WIDGET (lp->data), TRUE);
       gtk_widget_size_allocate (child, &child_allocation);
 
       if (direction == GTK_TEXT_DIR_RTL)
         {
-          child_allocation.x -= spacing;
           right_slider_offset = border_width;
         }
       else
         {
-          child_allocation.x += child_allocation.width + spacing;
+          child_allocation.x += child_allocation.width;
           right_slider_offset = allocation->width - border_width - buttons->slider_width;
         }
     }
 
   /* now we go hide all the buttons that don't fit */
   for (; lp != NULL; lp = lp->prev)
-    gtk_widget_set_child_visible (GTK_WIDGET (lp->data), FALSE);
+    {
+      need_reorder |= gtk_widget_get_child_visible (GTK_WIDGET (lp->data)) == TRUE;
+      gtk_widget_set_child_visible (GTK_WIDGET (lp->data), FALSE);
+    }
   for (lp = first_button->next; lp != NULL; lp = lp->next)
-    gtk_widget_set_child_visible (GTK_WIDGET (lp->data), FALSE);
+    {
+      need_reorder |= gtk_widget_get_child_visible (GTK_WIDGET (lp->data)) == TRUE;
+      gtk_widget_set_child_visible (GTK_WIDGET (lp->data), FALSE);
+    }
 
   if (need_sliders || buttons->fake_root_button != NULL)
     {
       child_allocation.width = buttons->slider_width;
       child_allocation.x = left_slider_offset + allocation->x;
       gtk_widget_size_allocate (buttons->left_slider, &child_allocation);
+      need_reorder |= gtk_widget_get_child_visible (buttons->left_slider) == FALSE;
       gtk_widget_set_child_visible (buttons->left_slider, TRUE);
       gtk_widget_show_all (buttons->left_slider);
 
@@ -772,6 +893,7 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
     }
   else
     {
+      need_reorder |= gtk_widget_get_child_visible (buttons->left_slider) == TRUE;
       gtk_widget_set_child_visible (buttons->left_slider, FALSE);
     }
 
@@ -780,6 +902,7 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
       child_allocation.width = buttons->slider_width;
       child_allocation.x = right_slider_offset + allocation->x;
       gtk_widget_size_allocate (buttons->right_slider, &child_allocation);
+      need_reorder |= gtk_widget_get_child_visible (buttons->right_slider) == FALSE;
       gtk_widget_set_child_visible (buttons->right_slider, TRUE);
       gtk_widget_show_all (buttons->right_slider);
 
@@ -787,8 +910,30 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
     }
   else
     {
+      need_reorder |= gtk_widget_get_child_visible (buttons->right_slider) == TRUE;
       gtk_widget_set_child_visible (buttons->right_slider, FALSE);
     }
+
+  if (need_reorder)
+    thunar_location_buttons_child_ordering_changed (buttons);
+}
+
+
+
+static gboolean
+thunar_location_buttons_draw (GtkWidget *widget,
+                              cairo_t   *cr)
+{
+  GtkStyleContext *context;
+  GtkAllocation alloc;
+
+  context = gtk_widget_get_style_context (widget);
+  gtk_widget_get_allocation (widget, &alloc);
+
+  gtk_render_background (context, cr, 0, 0, alloc.width, alloc.height);
+  gtk_render_frame (context, cr, 0, 0, alloc.width, alloc.height);
+
+  return GTK_WIDGET_CLASS (thunar_location_buttons_parent_class)->draw (widget, cr);
 }
 
 
@@ -899,12 +1044,12 @@ thunar_location_buttons_make_button (ThunarLocationButtons *buttons,
   thunar_location_button_set_file (THUNAR_LOCATION_BUTTON (button), file);
 
   /* the current directory is active */
-  thunar_location_button_set_active (THUNAR_LOCATION_BUTTON (button), (file == buttons->current_directory));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), (file == buttons->current_directory));
 
   /* connect signal handlers */
-  g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (thunar_location_buttons_clicked), buttons);
+  g_signal_connect (G_OBJECT (button), "location-button-clicked", G_CALLBACK (thunar_location_buttons_clicked), buttons);
   g_signal_connect (G_OBJECT (button), "gone", G_CALLBACK (thunar_location_buttons_gone), buttons);
-  g_signal_connect (G_OBJECT (button), "context-menu", G_CALLBACK (thunar_location_buttons_context_menu), buttons);
+  g_signal_connect (G_OBJECT (button), "popup-menu", G_CALLBACK (thunar_location_buttons_context_menu), buttons);
 
   return button;
 }
@@ -928,15 +1073,11 @@ thunar_location_buttons_scroll_timeout (gpointer user_data)
 {
   ThunarLocationButtons *buttons = THUNAR_LOCATION_BUTTONS (user_data);
 
-  GDK_THREADS_ENTER ();
-
   if (gtk_widget_has_focus (buttons->left_slider))
     thunar_location_buttons_scroll_left (buttons->left_slider, buttons);
   else if (gtk_widget_has_focus (buttons->right_slider))
     thunar_location_buttons_scroll_right (buttons->right_slider, buttons);
 
-  GDK_THREADS_LEAVE ();
-
   return TRUE;
 }
 
@@ -1012,9 +1153,10 @@ thunar_location_buttons_slider_button_press (GtkWidget             *button,
 
   if (G_LIKELY (buttons->scroll_timeout_id == 0))
     {
-      buttons->scroll_timeout_id = g_timeout_add_full (G_PRIORITY_LOW, THUNAR_LOCATION_BUTTONS_SCROLL_TIMEOUT,
-                                                       thunar_location_buttons_scroll_timeout, buttons,
-                                                       thunar_location_buttons_scroll_timeout_destroy);
+      buttons->scroll_timeout_id = gdk_threads_add_timeout_full (G_PRIORITY_LOW,
+                                                                 THUNAR_LOCATION_BUTTONS_SCROLL_TIMEOUT,
+                                                                 thunar_location_buttons_scroll_timeout, buttons,
+                                                                 thunar_location_buttons_scroll_timeout_destroy);
     }
 
   return FALSE;
@@ -1075,7 +1217,6 @@ thunar_location_buttons_scroll_right (GtkWidget             *button,
   gint             space_available;
   gint             space_needed;
   gint             border_width;
-  gint             spacing;
 
   if (G_UNLIKELY (buttons->ignore_click))
     {
@@ -1083,10 +1224,6 @@ thunar_location_buttons_scroll_right (GtkWidget             *button,
       return;
     }
 
-  gtk_widget_style_get (GTK_WIDGET (buttons),
-                        "spacing", &spacing,
-                        NULL);
-
   gtk_widget_queue_resize (GTK_WIDGET (buttons));
 
   border_width = gtk_container_get_border_width (GTK_CONTAINER (buttons));
@@ -1111,15 +1248,18 @@ thunar_location_buttons_scroll_right (GtkWidget             *button,
         break;
       }
 
-  space_needed = thunar_gtk_widget_get_allocation_width (GTK_WIDGET (right_button->data)) + spacing;
+  space_needed = thunar_gtk_widget_get_allocation_width (GTK_WIDGET (right_button->data));
   if (direction == GTK_TEXT_DIR_RTL)
     {
-      space_available = thunar_gtk_widget_get_allocation_x (buttons->right_slider) - thunar_gtk_widget_get_allocation_x (GTK_WIDGET (buttons));
+      space_available = thunar_gtk_widget_get_allocation_x (right_button->next->data) -
+                        thunar_gtk_widget_get_allocation_x (buttons->right_slider) -
+                        thunar_gtk_widget_get_allocation_width (buttons->right_slider);
     }
   else
     {
-      space_available = (thunar_gtk_widget_get_allocation_x (GTK_WIDGET (buttons)) + thunar_gtk_widget_get_allocation_width (GTK_WIDGET (buttons)) - border_width)
-                      - (thunar_gtk_widget_get_allocation_x (buttons->right_slider) + thunar_gtk_widget_get_allocation_width (buttons->right_slider));
+      space_available = thunar_gtk_widget_get_allocation_x (buttons->right_slider) -
+                        thunar_gtk_widget_get_allocation_x (right_button->next->data) -
+                        thunar_gtk_widget_get_allocation_width (right_button->next->data);
     }
 
   if (G_UNLIKELY (left_button == NULL))
@@ -1132,7 +1272,7 @@ thunar_location_buttons_scroll_right (GtkWidget             *button,
    */
   while (space_available < space_needed)
     {
-      space_available += thunar_gtk_widget_get_allocation_width (GTK_WIDGET (left_button->data)) + spacing;
+      space_available += thunar_gtk_widget_get_allocation_width (GTK_WIDGET (left_button->data));
       left_button = left_button->prev;
       buttons->first_scrolled_button = left_button;
     }
@@ -1202,7 +1342,7 @@ thunar_location_buttons_clicked (ThunarLocationButton  *button,
 
       /* update the location button state (making sure to not recurse with the "clicked" handler) */
       g_signal_handlers_block_by_func (G_OBJECT (button), thunar_location_buttons_clicked, buttons);
-      thunar_location_button_set_active (button, directory == buttons->current_directory);
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), directory == buttons->current_directory);
       g_signal_handlers_unblock_by_func (G_OBJECT (button), thunar_location_buttons_clicked, buttons);
     }
 
@@ -1230,9 +1370,8 @@ thunar_location_buttons_gone (ThunarLocationButton  *button,
 
 
 
-static void
+static gboolean
 thunar_location_buttons_context_menu (ThunarLocationButton  *button,
-                                      GdkEventButton        *event,
                                       ThunarLocationButtons *buttons)
 {
   ThunarClipboardManager *clipboard;
@@ -1301,13 +1440,17 @@ thunar_location_buttons_context_menu (ThunarLocationButton  *button,
 
           /* run the menu on the screen on the buttons' screen */
           menu = gtk_ui_manager_get_widget (buttons->ui_manager, "/location-buttons-context-menu");
-          thunar_gtk_menu_run (GTK_MENU (menu), GTK_WIDGET (buttons), NULL, NULL, event->button, event->time);
+          thunar_gtk_menu_run (GTK_MENU (menu), GTK_WIDGET (buttons), NULL, NULL, 0, gtk_get_current_event_time ());
 
           /* cleanup */
           g_object_unref (G_OBJECT (buttons));
           g_object_unref (G_OBJECT (clipboard));
+
+          return TRUE;
         }
     }
+
+  return FALSE;
 }
 
 
@@ -1366,13 +1509,13 @@ thunar_location_buttons_action_down_folder (GtkAction             *action,
 
   /* lookup the active button */
   for (lp = buttons->list; lp != NULL; lp = lp->next)
-    if (thunar_location_button_get_active (lp->data))
+    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (lp->data)))
       {
         /* check if we have a folder below that one */
         if (G_LIKELY (lp->prev != NULL))
           {
             /* enter that folder */
-            thunar_location_button_clicked (lp->prev->data);
+            gtk_button_clicked (GTK_BUTTON (lp->prev->data));
           }
 
         break;

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list