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