Brian J. Tarricone wrote:
> Though, to be perfectly frank, no one should have brought up the patent
> issue at all.  If we didn't know about it, and implemented it anyway,
> Apple could certainly sue someone, but they'd be more likely to just
> settle for a C&D letter that requires the feature's removal.  They might
> even not care, it being an OSS project and all.
> 
> Now that we know it's possibly patented, it becomes willful
> infringement, and if Apple chose to, they could kick some ass, at least
> in the US.  Willful infringement carries much larger penalties than
> accidental.
> 
> This is one of the reason most people will recommend that engineers and
> technology innovators not research patents at all.  (Well, up until they
> want to actually patent their work, anyway.)
> 
> But yeah, IANAL.  This is just shit I've heard.

Well, attached is a patch if anybody cares to find out if we'd run into
trouble. The attached patch enables dnd open for the shortcuts pane (the
delay isn't really configurable yet).

>       -b

Benedikt
Index: docs/README.thunarrc
===================================================================
--- docs/README.thunarrc	(revision 20363)
+++ docs/README.thunarrc	(working copy)
@@ -127,6 +127,17 @@
      The last known width of a Thunar window, which will be used as
      default width for newly created windows.
 
+   * MiscDndOpen (FALSE/TRUE)
+
+     Controls whether to enter folders during a Drag'n'Drop operation
+     by hovering them for a certain amount of time.
+
+   * MiscDndpenDelay (0...10000)
+
+     The delay after which folders are opened when hovering them
+     during a Drag'n'Drop operation (in ms). The default is 1000
+     milliseconds.
+
    * MiscFoldersFirst (FALSE/TRUE)
      
      Determines whether folder should be sorted before files.
Index: thunar/thunar-preferences-dialog.c
===================================================================
--- thunar/thunar-preferences-dialog.c	(revision 20363)
+++ thunar/thunar-preferences-dialog.c	(working copy)
@@ -200,7 +200,9 @@
   GtkWidget      *combo;
   GtkWidget      *frame;
   GtkWidget      *label;
+  GtkWidget      *scale;
   GtkWidget      *table;
+  GtkWidget      *hbox;
   GtkWidget      *vbox;
 
   /* grab a reference on the preferences */
@@ -393,7 +395,7 @@
   gtk_frame_set_label_widget (GTK_FRAME (frame), label);
   gtk_widget_show (label);
 
-  table = gtk_table_new (1, 2, FALSE);
+  table = gtk_table_new (2, 1, FALSE);
   gtk_table_set_row_spacings (GTK_TABLE (table), 6);
   gtk_table_set_col_spacings (GTK_TABLE (table), 12);
   gtk_container_set_border_width (GTK_CONTAINER (table), 12);
@@ -412,7 +414,56 @@
   gtk_table_attach (GTK_TABLE (table), button, 0, 1, 1, 2, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
   gtk_widget_show (button);
 
+  frame = g_object_new (GTK_TYPE_FRAME, "border-width", 0, "shadow-type", GTK_SHADOW_NONE, NULL);
+  gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
+  gtk_widget_show (frame);
 
+  label = gtk_label_new (_("Drag and Drop"));
+  gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_bold ());
+  gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+  gtk_widget_show (label);
+
+  table = gtk_table_new (3, 1, FALSE);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 12);
+  gtk_container_add (GTK_CONTAINER (frame), table);
+  gtk_widget_show (table);
+
+  button = gtk_check_button_new_with_mnemonic (_("_Open folders while dragging over them"));
+  exo_mutual_binding_new_with_negation (G_OBJECT (dialog->preferences), "misc-dnd-open", G_OBJECT (button), "active");
+  gtk_table_attach (GTK_TABLE (table), button, 0, 1, 0, 1, GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
+  gtk_widget_show (button);
+
+  label = gtk_label_new (_("Enable this option to open folders by holding the\n"
+                           "mouse pointer over them while dragging files.\n"
+                           "Select the delay before opening folders below:"));
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0f, 0.5f);
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+  gtk_widget_show (label);
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
+  exo_binding_new (G_OBJECT (button), "active", G_OBJECT (hbox), "sensitive");
+  gtk_table_attach (GTK_TABLE (table), hbox, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
+  gtk_widget_show (hbox);
+
+  label = gtk_label_new (_("Short"));
+  gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_small_italic ());
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+
+  scale = gtk_hscale_new_with_range (0.0, 1.0, 0.1);
+  gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
+  gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
+  gtk_widget_show (scale);
+
+  label = gtk_label_new (_("Long"));
+  gtk_label_set_attributes (GTK_LABEL (label), thunar_pango_attr_list_small_italic ());
+  gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+
+
   /*
      Advanced
    */
Index: thunar/thunar-shortcuts-view.c
===================================================================
--- thunar/thunar-shortcuts-view.c	(revision 20363)
+++ thunar/thunar-shortcuts-view.c	(working copy)
@@ -116,6 +116,8 @@
 static gboolean       thunar_shortcuts_view_separator_func        (GtkTreeModel             *model,
                                                                    GtkTreeIter              *iter,
                                                                    gpointer                  user_data);
+static gboolean       thunar_shortcuts_view_enter_timeout         (gpointer                  user_data);
+static void           thunar_shortcuts_view_enter_timeout_destroy (gpointer                  user_data);
 
 
 
@@ -130,22 +132,25 @@
   ThunarPreferences *preferences;
   GtkCellRenderer   *icon_renderer;
 
+  /* drop site support */
+  guint  drop_data_ready : 1; /* whether the drop data was received already */
+  guint  drop_occurred : 1;
+  GList *drop_path_list;      /* the list of URIs that are contained in the drop data */
+
+  /* enter folders using DnD */
+  gint   enter_timeout_id;
+
   /* the currently pressed mouse button, set in the
    * button-press-event handler if the associated
    * button-release-event should activate.
    */
-  gint pressed_button;
+  gint   pressed_button;
 
-  /* drop site support */
-  guint  drop_data_ready : 1; /* whether the drop data was received already */
-  guint  drop_occurred : 1;
-  GList *drop_path_list;      /* the list of URIs that are contained in the drop data */
-
 #if GTK_CHECK_VERSION(2,8,0)
   /* id of the signal used to queue a resize on the
    * column whenever the shortcuts icon size is changed.
    */
-  gint queue_resize_signal_id;
+  gint   queue_resize_signal_id;
 #endif
 };
 
@@ -246,6 +251,8 @@
   GtkTreeViewColumn *column;
   GtkCellRenderer   *renderer;
 
+  view->enter_timeout_id = -1;
+
   /* configure the tree view */
   gtk_tree_view_set_enable_search (GTK_TREE_VIEW (view), FALSE);
   gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE);
@@ -314,6 +321,10 @@
 {
   ThunarShortcutsView *view = THUNAR_SHORTCUTS_VIEW (object);
 
+  /* be sure to cancel any pending enter timeout */
+  if (G_UNLIKELY (view->enter_timeout_id >= 0))
+    g_source_remove (view->enter_timeout_id);
+
   /* release drop path list (if drag_leave wasn't called) */
   thunar_vfs_path_list_free (view->drop_path_list);
 
@@ -702,6 +713,10 @@
       view->drop_path_list = NULL;
     }
 
+  /* be sure to cancel any pending enter timeout */
+  if (G_LIKELY (view->enter_timeout_id >= 0))
+    g_source_remove (view->enter_timeout_id);
+
   /* call the parent's handler */
   return (*GTK_WIDGET_CLASS (thunar_shortcuts_view_parent_class)->drag_leave) (widget, context, time);
 }
@@ -981,11 +996,17 @@
   GtkTreePath       *path;
   GtkTreeIter        iter;
   ThunarFile        *file;
+  gboolean           dnd_open;
+  guint              dnd_open_delay;
   gint               cell_y;
 
   /* determine the shortcuts model */
   model = gtk_tree_view_get_model (GTK_TREE_VIEW (view));
 
+  /* initialize path_return and position_return */
+  *position_return = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
+  *path_return = NULL;
+
   /* determine the path for x/y */
   if (gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (view), x, y, &path, &column, NULL, &cell_y))
     {
@@ -1002,16 +1023,37 @@
             {
               /* check if the file accepts the drop */
               actions = thunar_file_accepts_drop (file, view->drop_path_list, context, action_return);
-              if (G_LIKELY (actions != 0))
+
+              /* check if "misc-dnd-open" is enabled */
+              g_object_get (G_OBJECT (view->preferences), "misc-dnd-open", &dnd_open, NULL);
+
+              /* we can either drop into this location or dnd open it */
+              if (G_LIKELY (actions != 0 || dnd_open))
                 {
-                  /* we can drop into this location */
+                  /* set path and position appropriately */
+                  *path_return = gtk_tree_path_copy (path);
                   *position_return = GTK_TREE_VIEW_DROP_INTO_OR_AFTER;
-                  *path_return = gtk_tree_path_copy (path);
 
-                  /* display a drop icon for the file */
-                  g_object_set (G_OBJECT (view->icon_renderer), "drop-file", file, NULL);
+                  /* display a drop icon for the file if we can drop here */
+                  g_object_set (G_OBJECT (view->icon_renderer), "drop-file", (actions != 0) ? file : NULL, NULL);
                 }
 
+              /* check if we should dnd open the folder */
+              if (G_LIKELY (dnd_open))
+                {
+                  /* cancel any pending enter timeout */
+                  if (G_UNLIKELY (view->enter_timeout_id >= 0))
+                    g_source_remove (view->enter_timeout_id);
+
+                  /* determine the open delay */
+                  g_object_get (G_OBJECT (view->preferences), "misc-dnd-open-delay", &dnd_open_delay, NULL);
+
+                  /* (re)schedule the timeout */
+                  view->enter_timeout_id = g_timeout_add_full (G_PRIORITY_LOW, dnd_open_delay,
+                                                               thunar_shortcuts_view_enter_timeout, view,
+                                                               thunar_shortcuts_view_enter_timeout_destroy);
+                }
+
               /* release the file */
               g_object_unref (G_OBJECT (file));
             }
@@ -1022,7 +1064,7 @@
     }
 
   /* check if we cannot drop into the shortcut */
-  if (G_UNLIKELY (actions == 0))
+  if (G_UNLIKELY (*path_return == NULL))
     {
       /* check the action that should be performed */
       if (context->suggested_action == GDK_ACTION_LINK || (context->actions & GDK_ACTION_LINK) != 0)
@@ -1375,6 +1417,50 @@
 
 
 
+static gboolean
+thunar_shortcuts_view_enter_timeout (gpointer user_data)
+{
+  GtkTreeViewDropPosition position;
+  ThunarShortcutsView    *view = THUNAR_SHORTCUTS_VIEW (user_data);
+  GtkTreeSelection       *selection;
+  GtkTreePath            *path;
+
+  GDK_THREADS_ENTER ();
+
+  /* determine the current drag dest row */
+  gtk_tree_view_get_drag_dest_row (GTK_TREE_VIEW (view), &path, &position);
+  if (G_LIKELY (path != NULL))
+    {
+      /* check if we want to drop into the folder at the path */
+      if (position == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE || position == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
+        {
+          /* select folder at the path... */
+          selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view));
+          gtk_tree_selection_select_path (selection, path);
+
+          /* ...and try to open the folder in the main view */
+          thunar_shortcuts_view_open (view);
+        }
+
+      /* release the path */
+      gtk_tree_path_free (path);
+    }
+
+  GDK_THREADS_LEAVE ();
+
+  return FALSE;
+}
+
+
+
+static void
+thunar_shortcuts_view_enter_timeout_destroy (gpointer user_data)
+{
+  THUNAR_SHORTCUTS_VIEW (user_data)->enter_timeout_id = -1;
+}
+
+
+
 /**
  * thunar_shortcuts_view_new:
  *
Index: thunar/thunar-location-button.c
===================================================================
--- thunar/thunar-location-button.c	(revision 20363)
+++ thunar/thunar-location-button.c	(working copy)
@@ -33,6 +33,7 @@
 #include <thunar/thunar-icon-factory.h>
 #include <thunar/thunar-location-button.h>
 #include <thunar/thunar-pango-extensions.h>
+#include <thunar/thunar-preferences.h>
 
 
 
@@ -678,23 +679,29 @@
                                     ThunarLocationButton *location_button)
 {
   ThunarFileIconState file_icon_state;
+  ThunarPreferences  *preferences;
   GdkDragAction       actions;
-  GtkSettings        *settings;
+  gboolean            dnd_open;
   GdkAtom             target;
-  gint                delay;
+  guint               dnd_open_delay;
 
   g_return_val_if_fail (GTK_IS_BUTTON (button), FALSE);
   g_return_val_if_fail (THUNAR_IS_LOCATION_BUTTON (location_button), FALSE);
 
-  /* schedule the enter timeout if not already done */
-  if (G_UNLIKELY (location_button->enter_timeout_id < 0))
+  /* grab a reference on the preferences */
+  preferences = thunar_preferences_get ();
+
+  /* check if "misc-dnd-open" is enabled */
+  g_object_get (G_OBJECT (preferences), "misc-dnd-open", &dnd_open, NULL);
+
+  /* schedule the enter timeout if not already done and dnd open is enabled */
+  if (G_UNLIKELY (dnd_open && 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);
+      /* determine the dnd open delay */
+      g_object_get (G_OBJECT (preferences), "misc-dnd-open-delay", &dnd_open_delay, NULL);
 
       /* schedule the timeout */
-      location_button->enter_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, delay, thunar_location_button_enter_timeout,
+      location_button->enter_timeout_id = g_timeout_add_full (G_PRIORITY_DEFAULT, dnd_open_delay, thunar_location_button_enter_timeout,
                                                               location_button, thunar_location_button_enter_timeout_destroy);
     }
 
@@ -732,6 +739,9 @@
         }
     }
 
+  /* release the reference on the preferences */
+  g_object_unref (G_OBJECT (preferences));
+
   return FALSE;
 }
 
Index: thunar/thunar-preferences.c
===================================================================
--- thunar/thunar-preferences.c	(revision 20363)
+++ thunar/thunar-preferences.c	(working copy)
@@ -65,6 +65,8 @@
   PROP_LAST_VIEW,
   PROP_LAST_WINDOW_HEIGHT,
   PROP_LAST_WINDOW_WIDTH,
+  PROP_MISC_DND_OPEN,
+  PROP_MISC_DND_OPEN_DELAY,
   PROP_MISC_FOLDERS_FIRST,
   PROP_MISC_HORIZONTAL_WHEEL_NAVIGATES,
   PROP_MISC_RECURSIVE_PERMISSIONS,
@@ -400,8 +402,35 @@
                                                      "last-window-width",
                                                      1, G_MAXINT, 640,
                                                      EXO_PARAM_READWRITE));
+  /**
+   * ThunarPreferences:misc-dnd-open:
+   *
+   * Whether to enter directories during DnD by hovering them
+   * for a certain amount of time.
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_MISC_DND_OPEN,
+                                   g_param_spec_boolean ("misc-dnd-open",
+                                                         "misc-dnd-open",
+                                                         "misc-dnd-open",
+                                                         TRUE,
+                                                         EXO_PARAM_READWRITE));
 
   /**
+   * ThunarPreferences:misc-dnd-open-delay:
+   *
+   * The delay after which folders are opened when hovering
+   * them during DnD (in ms).
+   **/
+  g_object_class_install_property (gobject_class,
+                                   PROP_MISC_DND_OPEN_DELAY,
+                                   g_param_spec_uint ("misc-dnd-open-delay",
+                                                      "misc-dnd-open-delay",
+                                                      "misc-dnd-open-delay",
+                                                      0, G_MAXUINT, 1000,
+                                                      EXO_PARAM_READWRITE));
+
+  /**
    * ThunarPreferences:misc-folders-first:
    *
    * Whether to sort folders before files.
Index: thunar/thunar-gobject-extensions.c
===================================================================
--- thunar/thunar-gobject-extensions.c	(revision 20363)
+++ thunar/thunar-gobject-extensions.c	(working copy)
@@ -42,6 +42,7 @@
 static void transform_string_to_boolean (const GValue *src, GValue *dst);
 static void transform_string_to_enum    (const GValue *src, GValue *dst);
 static void transform_string_to_int     (const GValue *src, GValue *dst);
+static void transform_string_to_uint    (const GValue *src, GValue *dst);
 
 
 
@@ -87,6 +88,15 @@
 
 
 
+static void
+transform_string_to_uint (const GValue *src,
+                          GValue       *dst)
+{
+  g_value_set_uint (dst, strtoul (g_value_get_string (src), NULL, 10));
+}
+
+
+
 /**
  * thunar_g_initialize_transformations:
  *
@@ -101,6 +111,8 @@
     g_value_register_transform_func (G_TYPE_STRING, G_TYPE_BOOLEAN, transform_string_to_boolean);
   if (!g_value_type_transformable (G_TYPE_STRING, G_TYPE_INT))
     g_value_register_transform_func (G_TYPE_STRING, G_TYPE_INT, transform_string_to_int);
+  if (!g_value_type_transformable (G_TYPE_STRING, G_TYPE_UINT))
+    g_value_register_transform_func (G_TYPE_STRING, G_TYPE_UINT, transform_string_to_uint);
   if (!g_value_type_transformable (G_TYPE_STRING, GTK_TYPE_SORT_TYPE))
     g_value_register_transform_func (G_TYPE_STRING, GTK_TYPE_SORT_TYPE, transform_string_to_enum);
 }
_______________________________________________
Thunar-dev mailing list
Thunar-dev@xfce.org
http://foo-projects.org/mailman/listinfo/thunar-dev

Reply via email to