[Xfce4-commits] [xfce/thunar] 01/01: Segfault when pressing "folder up" on pathbar (Bug #13987)

noreply at xfce.org noreply at xfce.org
Tue Nov 14 23:07:07 CET 2017


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

a   l   e   x       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 a63b1732d5846652151649073ebe15ac8b0ab2cb
Author: Alexander Schwinn <acs82 at gmx.de>
Date:   Tue Nov 14 23:02:58 2017 +0100

    Segfault when pressing "folder up" on pathbar (Bug #13987)
---
 thunar/thunar-location-buttons.c | 318 ++++++++++++++++++++++-----------------
 1 file changed, 183 insertions(+), 135 deletions(-)

diff --git a/thunar/thunar-location-buttons.c b/thunar/thunar-location-buttons.c
index 36847a8..e240039 100644
--- a/thunar/thunar-location-buttons.c
+++ b/thunar/thunar-location-buttons.c
@@ -51,87 +51,93 @@ enum
 
 
 
-static void           thunar_location_buttons_navigator_init            (ThunarNavigatorIface       *iface);
-static void           thunar_location_buttons_finalize                  (GObject                    *object);
-static void           thunar_location_buttons_get_property              (GObject                    *object,
-                                                                         guint                       prop_id,
-                                                                         GValue                     *value,
-                                                                         GParamSpec                 *pspec);
-static void           thunar_location_buttons_set_property              (GObject                    *object,
-                                                                         guint                       prop_id,
-                                                                         const GValue               *value,
-                                                                         GParamSpec                 *pspec);
-static ThunarFile    *thunar_location_buttons_get_current_directory     (ThunarNavigator            *navigator);
-static void           thunar_location_buttons_set_current_directory     (ThunarNavigator            *navigator,
-                                                                         ThunarFile                 *current_directory);
-static void           thunar_location_buttons_unmap                     (GtkWidget                  *widget);
-static void           thunar_location_buttons_on_filler_clicked         (ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_get_preferred_width       (GtkWidget                  *widget,
-                                                                         gint                       *minimum,
-                                                                         gint                       *natural);
-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,
-                                                                         GtkStateType                previous_state);
-static void           thunar_location_buttons_grab_notify               (GtkWidget                  *widget,
-                                                                         gboolean                    was_grabbed);
-static void           thunar_location_buttons_add                       (GtkContainer               *container,
-                                                                         GtkWidget                  *widget);
-static void           thunar_location_buttons_remove                    (GtkContainer               *container,
-                                                                         GtkWidget                  *widget);
-static void           thunar_location_buttons_forall                    (GtkContainer               *container,
-                                                                         gboolean                    include_internals,
-                                                                         GtkCallback                 callback,
-                                                                         gpointer                    callback_data);
-static GtkWidget     *thunar_location_buttons_make_button               (ThunarLocationButtons      *buttons,
-                                                                         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);
-static void           thunar_location_buttons_update_sliders            (ThunarLocationButtons      *buttons);
-static gboolean       thunar_location_buttons_slider_button_press       (GtkWidget                  *button,
-                                                                         GdkEventButton             *event,
-                                                                         ThunarLocationButtons      *buttons);
-static gboolean       thunar_location_buttons_slider_button_release     (GtkWidget                  *button,
-                                                                         GdkEventButton             *event,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_scroll_left               (GtkWidget                  *button,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_scroll_right              (GtkWidget                  *button,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_clicked                   (ThunarLocationButton       *button,
-                                                                         gboolean                    open_in_tab,
-                                                                         ThunarLocationButtons      *buttons);
-static gboolean       thunar_location_buttons_context_menu              (ThunarLocationButton       *button,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_gone                      (ThunarLocationButton       *button,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_action_create_folder      (GtkAction                  *action,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_action_down_folder        (GtkAction                  *action,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_action_empty_trash        (GtkAction                  *action,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_action_open               (GtkAction                  *action,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_action_open_in_new_tab    (GtkAction                  *action,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_action_open_in_new_window (GtkAction                  *action,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_action_paste_into_folder  (GtkAction                  *action,
-                                                                         ThunarLocationButtons      *buttons);
-static void           thunar_location_buttons_action_properties         (GtkAction                  *action,
-                                                                         ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_navigator_init              (ThunarNavigatorIface       *iface);
+static void           thunar_location_buttons_finalize                    (GObject                    *object);
+static void           thunar_location_buttons_get_property                (GObject                    *object,
+                                                                           guint                       prop_id,
+                                                                           GValue                     *value,
+                                                                           GParamSpec                 *pspec);
+static void           thunar_location_buttons_set_property                (GObject                    *object,
+                                                                           guint                       prop_id,
+                                                                           const GValue               *value,
+                                                                           GParamSpec                 *pspec);
+static ThunarFile    *thunar_location_buttons_get_current_directory       (ThunarNavigator            *navigator);
+static void           thunar_location_buttons_set_current_directory       (ThunarNavigator            *navigator,
+                                                                           ThunarFile                 *current_directory);
+static void           thunar_location_buttons_unmap                       (GtkWidget                  *widget);
+static void           thunar_location_buttons_on_filler_clicked           (ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_get_preferred_width         (GtkWidget                  *widget,
+                                                                           gint                       *minimum,
+                                                                           gint                       *natural);
+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 GList         *thunar_location_buttons_detect_first_visible_button (ThunarLocationButtons      *buttons,
+                                                                           gint                        available_width,
+                                                                           gint                       *resulting_occupied_width);
+static GList         *thunar_location_buttons_detect_last_visible_button  (ThunarLocationButtons      *buttons,
+                                                                           gint                        available_width,
+                                                                           gint                       *resulting_occupied_width);
+static void           thunar_location_buttons_size_allocate               (GtkWidget                  *widget,
+                                                                           GtkAllocation              *allocation);
+static void           thunar_location_buttons_state_changed               (GtkWidget                  *widget,
+                                                                           GtkStateType                previous_state);
+static void           thunar_location_buttons_grab_notify                 (GtkWidget                  *widget,
+                                                                           gboolean                    was_grabbed);
+static void           thunar_location_buttons_add                         (GtkContainer               *container,
+                                                                           GtkWidget                  *widget);
+static void           thunar_location_buttons_remove                      (GtkContainer               *container,
+                                                                           GtkWidget                  *widget);
+static void           thunar_location_buttons_forall                      (GtkContainer               *container,
+                                                                           gboolean                    include_internals,
+                                                                           GtkCallback                 callback,
+                                                                           gpointer                    callback_data);
+static GtkWidget     *thunar_location_buttons_make_button                 (ThunarLocationButtons      *buttons,
+                                                                           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);
+static void           thunar_location_buttons_update_sliders              (ThunarLocationButtons      *buttons);
+static gboolean       thunar_location_buttons_slider_button_press         (GtkWidget                  *button,
+                                                                           GdkEventButton             *event,
+                                                                           ThunarLocationButtons      *buttons);
+static gboolean       thunar_location_buttons_slider_button_release       (GtkWidget                  *button,
+                                                                           GdkEventButton             *event,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_scroll_left                 (GtkWidget                  *button,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_scroll_right                (GtkWidget                  *button,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_clicked                     (ThunarLocationButton       *button,
+                                                                           gboolean                    open_in_tab,
+                                                                           ThunarLocationButtons      *buttons);
+static gboolean       thunar_location_buttons_context_menu                (ThunarLocationButton       *button,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_gone                        (ThunarLocationButton       *button,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_action_create_folder        (GtkAction                  *action,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_action_down_folder          (GtkAction                  *action,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_action_empty_trash          (GtkAction                  *action,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_action_open                 (GtkAction                  *action,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_action_open_in_new_tab      (GtkAction                  *action,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_action_open_in_new_window   (GtkAction                  *action,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_action_paste_into_folder    (GtkAction                  *action,
+                                                                           ThunarLocationButtons      *buttons);
+static void           thunar_location_buttons_action_properties           (GtkAction                  *action,
+                                                                           ThunarLocationButtons      *buttons);
 
 
 
@@ -159,7 +165,8 @@ struct _ThunarLocationButtons
 
   GList             *list;
   GList             *fake_root_button;
-  guint              scroll_count;
+  GList             *first_visible_button;
+  GList             *last_visible_button;
 
   guint              scroll_timeout_id;
 };
@@ -434,8 +441,9 @@ thunar_location_buttons_set_current_directory (ThunarNavigator *navigator,
       while (buttons->list != NULL)
         gtk_container_remove (GTK_CONTAINER (buttons), buttons->list->data);
 
-      /* clear scroll count and fake root buttons */
-      buttons->scroll_count = 0;
+      /* clear scroll positions and fake root button */
+      buttons->first_visible_button = NULL;
+      buttons->last_visible_button = NULL;
       buttons->fake_root_button = NULL;
     }
 
@@ -618,6 +626,58 @@ thunar_location_buttons_child_ordering_changed (ThunarLocationButtons *location_
 
 
 
+static GList*
+thunar_location_buttons_detect_first_visible_button (ThunarLocationButtons *buttons,
+                                                     gint                   available_width,
+                                                     gint                  *resulting_occupied_width)
+{
+  GList *lp;
+  gint   button_width    = 0;
+  gint   resulting_width = 0;
+
+  /* walk all buttons starting by last, until no space is left */
+  for (lp = buttons->last_visible_button; lp != NULL; lp = lp->next)
+    {
+      gtk_widget_get_preferred_width (GTK_WIDGET (lp->data), &button_width, NULL);
+      if (resulting_width + button_width > available_width)
+        {
+          return lp->prev;
+        }
+      resulting_width += button_width;
+      if(resulting_occupied_width != NULL)
+        *resulting_occupied_width = resulting_width;
+    }
+  return g_list_last (buttons->list);
+}
+
+
+
+static GList*
+thunar_location_buttons_detect_last_visible_button (ThunarLocationButtons *buttons,
+                                                    gint                   available_width,
+                                                    gint                  *resulting_occupied_width)
+{
+  GList *lp;
+  gint   button_width    = 0;
+  gint   resulting_width = 0;
+
+  /* walk all buttons starting by first, until no space is left */
+  for (lp = buttons->first_visible_button; lp != NULL; lp = lp->prev)
+    {
+      gtk_widget_get_preferred_width (GTK_WIDGET (lp->data), &button_width, NULL);
+      if (resulting_width + button_width > available_width)
+        {
+          return lp->next;
+        }
+      resulting_width += button_width;
+      if(resulting_occupied_width != NULL)
+        *resulting_occupied_width = resulting_width;
+    }
+  return buttons->list;
+}
+
+
+
 static void
 thunar_location_buttons_size_allocate (GtkWidget     *widget,
                                        GtkAllocation *allocation)
@@ -629,13 +689,10 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
   GtkAllocation          first_slider_allocation;  /* left slider if direction is LTR */
   GtkAllocation          second_slider_allocation; /* right slider if direction is LTR */
   GtkAllocation          filler_allocation;
-  GList                 *first_button = g_list_last (buttons->list);
-  GList                 *last_button = buttons->list;
   GList                 *lp;
   gint                   required_width_total = 0;
   gint                   border_width;
   gint                   temp_width;
-  guint                  scroll_index;
   gboolean               need_reorder = FALSE;
 
   gtk_widget_set_allocation (widget, allocation);
@@ -674,10 +731,6 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
   filler_allocation.height = available_space.height;
   filler_allocation.y = available_space.y;
 
-  /* set default for first button */
-  if (G_LIKELY (buttons->fake_root_button != NULL))
-      first_button = buttons->fake_root_button;
-
   for (lp = buttons->list; lp != NULL; lp = lp->next)
     {
       gtk_widget_get_preferred_width (GTK_WIDGET (lp->data), &temp_width, NULL);
@@ -688,41 +741,38 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
 
   if ( required_width_total <= available_space.width  )
     {
-      /* reset the scroll position */
-      buttons->scroll_count = 0;
+      /* Show full list of buttons, starting by fake root, if available */
+      if (buttons->fake_root_button == NULL)
+        buttons->first_visible_button = g_list_last (buttons->list);
+      else
+        buttons->first_visible_button = buttons->fake_root_button;
+      buttons->last_visible_button = buttons->list;
     }
   else
     {
       /* reset calculation for required_width_total .. we need to cut off some folders */
       required_width_total = first_slider_allocation.width + second_slider_allocation.width + filler_allocation.width;
 
-      if (G_UNLIKELY (buttons->scroll_count != 0))
-        {
-          for (scroll_index = 0; scroll_index < buttons->scroll_count ; scroll_index++)
-            last_button = last_button->next;
-        }
+      /* No scrolling defined ? Use last button as fixed start! */
+      if(buttons->last_visible_button == NULL && buttons->first_visible_button == NULL)
+        buttons->last_visible_button = buttons->list;
 
-      /* find last button for available width */
-      for (lp = last_button; lp != NULL; lp = lp->next)
-        {
-          gtk_widget_get_preferred_width (GTK_WIDGET (lp->data), &temp_width, NULL);
-          if ( required_width_total + temp_width > available_space.width)
-            {
-              first_button = lp->prev;
-              break;
-            }
-          required_width_total += temp_width;
-        }
+      if(buttons->first_visible_button == NULL) /* last button is fixed defined */
+        buttons->first_visible_button = thunar_location_buttons_detect_first_visible_button(buttons, available_space.width - required_width_total, &temp_width);
+      else                                      /* first button is fixed defined */
+        buttons->last_visible_button = thunar_location_buttons_detect_last_visible_button(buttons, available_space.width - required_width_total, &temp_width);
+
+      required_width_total += temp_width;
     }
 
-  /* hide buttons before first_button */
-  for (lp = first_button->next; lp != NULL; lp = lp->next)
+  /* hide buttons before first_visible_button */
+  for (lp = buttons->first_visible_button->next; lp != NULL; lp = lp->next)
     {
       need_reorder |= gtk_widget_get_child_visible (GTK_WIDGET (lp->data)) == TRUE;
       gtk_widget_set_child_visible (GTK_WIDGET (lp->data), FALSE);
     }
-  /* hide buttons after last button */
-  for (lp = last_button->prev; lp != NULL; lp = lp->prev)
+  /* hide buttons after last visible_button */
+  for (lp = buttons->last_visible_button->prev; lp != NULL; lp = lp->prev)
     {
       need_reorder |= gtk_widget_get_child_visible (GTK_WIDGET (lp->data)) == TRUE;
       gtk_widget_set_child_visible (GTK_WIDGET (lp->data), FALSE);
@@ -741,7 +791,7 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
         folder_button_allocation.x = first_slider_allocation.x;
     }
 
-  for (lp = first_button; lp != NULL; lp = lp->prev)
+  for (lp = buttons->first_visible_button; lp != NULL; lp = lp->prev)
     {
       gtk_widget_get_preferred_width (GTK_WIDGET (lp->data), &folder_button_allocation.width, NULL);
 
@@ -755,7 +805,7 @@ thunar_location_buttons_size_allocate (GtkWidget     *widget,
       if (G_LIKELY (direction == GTK_TEXT_DIR_LTR))
         folder_button_allocation.x += folder_button_allocation.width;
 
-      if( lp == last_button )
+      if( lp == buttons->last_visible_button )
         break;
     }
 
@@ -1051,8 +1101,6 @@ static void
 thunar_location_buttons_scroll_left (GtkWidget             *button,
                                      ThunarLocationButtons *buttons)
 {
-  GList *lp;
-
   if (G_UNLIKELY (buttons->ignore_click))
     {
       buttons->ignore_click = FALSE;
@@ -1060,15 +1108,13 @@ thunar_location_buttons_scroll_left (GtkWidget             *button,
     }
 
   gtk_widget_queue_resize (GTK_WIDGET (buttons));
-
-  for (lp = g_list_last (buttons->list); lp != NULL; lp = lp->prev)
-    if (lp->prev != NULL && gtk_widget_get_child_visible (GTK_WIDGET (lp->prev->data)))
-      {
-        if (lp->prev == buttons->fake_root_button)
-          buttons->fake_root_button = NULL;
-        buttons->scroll_count ++;
-        break;
-      }
+  if (buttons->first_visible_button->next != NULL)
+    {
+      if (buttons->first_visible_button == buttons->fake_root_button)
+        buttons->fake_root_button = NULL;
+      buttons->first_visible_button = buttons->first_visible_button->next;
+      buttons->last_visible_button = NULL;
+    }
 }
 
 
@@ -1084,8 +1130,11 @@ thunar_location_buttons_scroll_right (GtkWidget             *button,
     }
 
   gtk_widget_queue_resize (GTK_WIDGET (buttons));
-  if ( buttons->scroll_count > 0 )
-    buttons->scroll_count--;
+  if (buttons->last_visible_button->prev != NULL)
+    {
+      buttons->last_visible_button = buttons->last_visible_button->prev;
+      buttons->first_visible_button = NULL;
+    }
 }
 
 
@@ -1125,13 +1174,12 @@ thunar_location_buttons_clicked (ThunarLocationButton  *button,
   /* check if the button is visible on the button bar */
   if (!gtk_widget_get_child_visible (GTK_WIDGET (button)))
     {
-// ##########
-// FIXME: The auto-scroll feature currently is disabled, since on horizontal small windows it can produce graphical glitches and even seg.faults. To be fixed.
-// ##########
-//      buttons->scroll_count = 0;
-//      /* scroll left till the button is visible */
-//      while(!gtk_widget_get_child_visible (GTK_WIDGET (button)) && buttons->scroll_count < g_list_length(buttons->list) )
-//          thunar_location_buttons_scroll_left (buttons->left_slider, buttons);
+      for (lp = buttons->list; lp != NULL; lp = lp->next)
+        {
+          if( lp->data == button )
+            buttons->first_visible_button = lp;
+        }
+      buttons->last_visible_button = NULL;
     }
 
   /* update all buttons */

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


More information about the Xfce4-commits mailing list