Alter the behaviour of the middle button (in icon view). Over an object: don't deselect everything - just toggle whether it is selected, like ROX Filer and, with the right button, the RISC OS filer do. Over empty space: act as Ctrl + left-drag. This is optional. Again, this implements behaviour found in other filers. Signed-off-by: Darren Salt Index: thunar/thunar-preferences-dialog.c =================================================================== --- thunar/thunar-preferences-dialog.c (revision 22271) +++ thunar/thunar-preferences-dialog.c (working copy) @@ -544,6 +544,15 @@ gtk_table_attach (GTK_TABLE (table), button, 0, 1, 2, 3, GTK_EXPAND | GTK_FILL, 0, 0, 0); gtk_widget_show (button); + button = gtk_check_button_new_with_mnemonic (_("_Middle button mouse gestures")); + exo_mutual_binding_new (G_OBJECT (dialog->preferences), "misc-mouse-gestures", G_OBJECT (button), "active"); + g_signal_connect (G_OBJECT (button), "toggled", G_CALLBACK (g_object_notify), "active"); + gtk_tooltips_set_tip (dialog->tooltips, button, _("When mouse gestures are enabled, a middle-button drag from an empty part " + "of the window to perform various actions: back, forward, up, or refresh.\n\n" + "When they are disabled, it allows you to drag a box which toggles whether " + "the enclosed items are selected."), NULL); + gtk_table_attach (GTK_TABLE (table), button, 0, 1, 3, 4, GTK_EXPAND | GTK_FILL, 0, 0, 0); + gtk_widget_show (button); /* Advanced Index: thunar/thunar-preferences.c =================================================================== --- thunar/thunar-preferences.c (revision 22271) +++ thunar/thunar-preferences.c (working copy) @@ -77,6 +77,7 @@ PROP_MISC_SINGLE_CLICK, PROP_MISC_SINGLE_CLICK_TIMEOUT, PROP_MISC_TEXT_BESIDE_ICONS, + PROP_MISC_MOUSE_GESTURES, PROP_SHORTCUTS_ICON_EMBLEMS, PROP_SHORTCUTS_ICON_SIZE, PROP_TREE_ICON_EMBLEMS, @@ -577,6 +578,20 @@ EXO_PARAM_READWRITE)); /** + * ThunarPreferences:misc-mouse-gestures: + * + * Whether the middle button (over empty space) is used for gestures + * or as Ctrl + left button. + **/ + g_object_class_install_property (gobject_class, + PROP_MISC_MOUSE_GESTURES, + g_param_spec_boolean ("misc-mouse-gestures", + "misc-mouse-gestures", + "misc-mouse-gestures", + TRUE, + EXO_PARAM_READWRITE)); + + /** * ThunarPreferences:shortcuts-icon-emblems: * * Whether to display emblems for file icons (if defined) in the Index: thunar/thunar-abstract-icon-view.c =================================================================== --- thunar/thunar-abstract-icon-view.c (revision 22271) +++ thunar/thunar-abstract-icon-view.c (working copy) @@ -535,20 +535,21 @@ } else if ((event->type == GDK_BUTTON_PRESS || event->type == GDK_2BUTTON_PRESS) && event->button == 2) { - /* unselect all currently selected items */ - exo_icon_view_unselect_all (view); + /* unselect all currently selected items if maybe activating an item */ + if (event->type == GDK_2BUTTON_PRESS || exo_icon_view_get_single_click (view)) + exo_icon_view_unselect_all (view); /* determine the path to the item that was middle-clicked */ if (exo_icon_view_get_item_at_pos (view, event->x, event->y, &path, NULL)) { - /* select only the path to the item on which the user clicked */ - exo_icon_view_select_path (view, path); - /* if the event was a double-click or we are in single-click mode, then * we'll open the file or folder (folder's are opened in new windows) */ if (G_LIKELY (event->type == GDK_2BUTTON_PRESS || exo_icon_view_get_single_click (view))) { + /* select only the path to the item on which the user clicked */ + exo_icon_view_select_path (view, path); + /* determine the file for the path */ gtk_tree_model_get_iter (GTK_TREE_MODEL (THUNAR_STANDARD_VIEW (abstract_icon_view)->model), &iter, path); file = thunar_list_model_get_file (THUNAR_STANDARD_VIEW (abstract_icon_view)->model, &iter); @@ -566,23 +567,42 @@ g_object_unref (G_OBJECT (file)); } } + /* otherwise we don't want it selected (effectively a toggle) */ + else if (exo_icon_view_path_is_selected (view, path)) + exo_icon_view_unselect_path (view, path); + else + exo_icon_view_select_path (view, path); /* cleanup */ gtk_tree_path_free (path); } else if (event->type == GDK_BUTTON_PRESS) { - abstract_icon_view->priv->gesture_start_x = abstract_icon_view->priv->gesture_current_x = event->x; - abstract_icon_view->priv->gesture_start_y = abstract_icon_view->priv->gesture_current_y = event->y; - abstract_icon_view->priv->gesture_expose_id = g_signal_connect_after (G_OBJECT (view), "expose-event", - G_CALLBACK (thunar_abstract_icon_view_expose_event), - G_OBJECT (abstract_icon_view)); - abstract_icon_view->priv->gesture_motion_id = g_signal_connect (G_OBJECT (view), "motion-notify-event", - G_CALLBACK (thunar_abstract_icon_view_motion_notify_event), - G_OBJECT (abstract_icon_view)); - abstract_icon_view->priv->gesture_release_id = g_signal_connect (G_OBJECT (view), "button-release-event", - G_CALLBACK (thunar_abstract_icon_view_button_release_event), - G_OBJECT (abstract_icon_view)); + gint gestures; + ThunarPreferences *preferences = thunar_preferences_get (); + g_object_get (G_OBJECT (preferences), "misc-mouse-gestures", &gestures, NULL); + g_object_unref (preferences); + if (gestures) + { + abstract_icon_view->priv->gesture_start_x = abstract_icon_view->priv->gesture_current_x = event->x; + abstract_icon_view->priv->gesture_start_y = abstract_icon_view->priv->gesture_current_y = event->y; + abstract_icon_view->priv->gesture_expose_id = g_signal_connect_after (G_OBJECT (view), "expose-event", + G_CALLBACK (thunar_abstract_icon_view_expose_event), + G_OBJECT (abstract_icon_view)); + abstract_icon_view->priv->gesture_motion_id = g_signal_connect (G_OBJECT (view), "motion-notify-event", + G_CALLBACK (thunar_abstract_icon_view_motion_notify_event), + G_OBJECT (abstract_icon_view)); + abstract_icon_view->priv->gesture_release_id = g_signal_connect (G_OBJECT (view), "button-release-event", + G_CALLBACK (thunar_abstract_icon_view_button_release_event), + G_OBJECT (abstract_icon_view)); + } + else + { + /* we want the default handler but with a modified event */ + event->button = 1; + event->state |= GDK_CONTROL_MASK; + return FALSE; + } } /* don't run the default handler here */