diff --git a/common/xfdesktop-common.h b/common/xfdesktop-common.h index cfd41e6a..5d7a7622 100644 --- a/common/xfdesktop-common.h +++ b/common/xfdesktop-common.h @@ -64,6 +64,8 @@ #define DESKTOP_ICONS_SHOW_FILESYSTEM "/desktop-icons/file-icons/show-filesystem" #define DESKTOP_ICONS_SHOW_REMOVABLE "/desktop-icons/file-icons/show-removable" +#define DESKTOP_ICONS_CREATE_UNDER_CURSOR "/desktop-icons/create-under-cursor" + #define DESKTOP_MENU_MAX_TEMPLATE_FILES "/desktop-menu/max-template-files" /** diff --git a/doc/README.xfconf b/doc/README.xfconf index 7456eca1..fa7756d9 100644 --- a/doc/README.xfconf +++ b/doc/README.xfconf @@ -48,6 +48,7 @@ the same monitor is plugged in again those settings apply to it. + diff --git a/src/xfdesktop-file-icon-manager.c b/src/xfdesktop-file-icon-manager.c index cbf0ec57..26d4c72a 100644 --- a/src/xfdesktop-file-icon-manager.c +++ b/src/xfdesktop-file-icon-manager.c @@ -94,6 +94,7 @@ typedef enum PROP_SHOW_UNKNOWN_VOLUME, PROP_SHOW_THUMBNAILS, PROP_SHOW_HIDDEN_FILES, + PROP_CREATE_UNDER_CURSOR, PROP_MAX_TEMPLATES, } XfdesktopFileIconManagerProp; @@ -152,6 +153,12 @@ struct _XfdesktopFileIconManagerPrivate XfdesktopThumbnailer *thumbnailer; + gboolean create_under_cursor; + gboolean dropped; + GList *saved_file_list; + gint16 saved_row; + gint16 saved_col; + guint max_templates; guint templates_count; }; @@ -223,6 +230,10 @@ static void xfdesktop_file_icon_manager_update_image(GtkWidget *widget, gchar *thumbfile, XfdesktopFileIconManager *fmanager); +static void +xfdesktop_file_icon_manager_set_create_under_cursor(XfdesktopFileIconManager *manager, + gboolean create_under_cursor); + static void xfdesktop_file_icon_manager_set_max_templates(XfdesktopFileIconManager *manager, gint max_templates); @@ -351,6 +362,12 @@ xfdesktop_file_icon_manager_class_init(XfdesktopFileIconManagerClass *klass) "show-hidden-files", FALSE, XFDESKTOP_PARAM_FLAGS)); + g_object_class_install_property(gobject_class, PROP_CREATE_UNDER_CURSOR, + g_param_spec_boolean("create-under-cursor", + "create-under-cursor", + "create-under-cursor", + FALSE, + XFDESKTOP_PARAM_FLAGS)); g_object_class_install_property(gobject_class, PROP_MAX_TEMPLATES, g_param_spec_uint("max-templates", "max-templates", @@ -377,6 +394,12 @@ xfdesktop_file_icon_manager_init(XfdesktopFileIconManager *fmanager) fmanager->priv->thumbnailer = xfdesktop_thumbnailer_new(); g_signal_connect(G_OBJECT(fmanager->priv->thumbnailer), "thumbnail-ready", G_CALLBACK(xfdesktop_file_icon_manager_update_image), fmanager); + + fmanager->priv->dropped = FALSE; + + fmanager->priv->saved_file_list = NULL; + fmanager->priv->saved_row = -1; + fmanager->priv->saved_col = -1; } static void @@ -430,6 +453,11 @@ xfdesktop_file_icon_manager_set_property(GObject *object, g_value_get_boolean(value)); break; + case PROP_CREATE_UNDER_CURSOR: + xfdesktop_file_icon_manager_set_create_under_cursor(fmanager, + g_value_get_boolean(value)); + break; + case PROP_MAX_TEMPLATES: xfdesktop_file_icon_manager_set_max_templates(fmanager, g_value_get_uint(value)); @@ -492,6 +520,10 @@ xfdesktop_file_icon_manager_get_property(GObject *object, g_value_set_boolean(value, fmanager->priv->show_hidden_files); break; + case PROP_CREATE_UNDER_CURSOR: + g_value_set_boolean(value, fmanager->priv->create_under_cursor); + break; + case PROP_MAX_TEMPLATES: g_value_set_int(value, fmanager->priv->max_templates); break; @@ -520,6 +552,8 @@ xfdesktop_file_icon_manager_finalize(GObject *obj) if(fmanager->priv->volume_monitor != NULL) g_object_unref(fmanager->priv->volume_monitor); + g_list_free(fmanager->priv->saved_file_list); + G_OBJECT_CLASS(xfdesktop_file_icon_manager_parent_class)->finalize(obj); } @@ -2676,6 +2710,75 @@ xfdesktop_file_icon_manager_key_press(GtkWidget *widget, return FALSE; } +static void +lookup_cursor_position(XfdesktopFileIconManager *fmanager, + GFile *file, + gint16 *row, + gint16 *col, + gboolean file_is_launcher) +{ + /* */ + + if(file_is_launcher) { + /* Launcher was created, retrieve clicked position */ + xfdesktop_icon_view_get_clicked_position(fmanager->priv->icon_view, row, col); + + } else if(xfdesktop_file_utils_get_created_file()) { + /* New folder or file from template was created, + * retrieve clicked position */ + xfdesktop_icon_view_get_clicked_position(fmanager->priv->icon_view, row, col); + /* Unset "created file" event */ + xfdesktop_file_utils_set_created_file(FALSE); + + } else if(fmanager->priv->dropped) { + /* Files were dragged and dropped onto the desktop, + * this includes transferred media from web browsers */ + + /* Load saved position from DnD event */ + *row = fmanager->priv->saved_row; + *col = fmanager->priv->saved_col; + + if(fmanager->priv->saved_file_list) { + GList *l; + gchar *basename = g_file_get_basename(file); + gboolean found = FALSE; + + /* Check if file is in list of transferred files */ + for(l = fmanager->priv->saved_file_list; l; l = l->next) { + gchar *basename_tmp = g_file_get_basename(l->data); + if(g_strcmp0(basename, basename_tmp) == 0) { + fmanager->priv->saved_file_list = g_list_remove( + fmanager->priv->saved_file_list, l->data); + found = TRUE; + } + g_free(basename_tmp); + } + + g_free(basename); + + if(found) { + /* Find next free slot */ + xfdesktop_icon_view_get_next_free_slot(fmanager->priv->icon_view, + row, col); + fmanager->priv->saved_row = *row; + fmanager->priv->saved_col = *col; + + return; + } else { + /* File not found, unset list */ + g_list_free(fmanager->priv->saved_file_list); + fmanager->priv->saved_file_list = NULL; + } + } + + } else { + *row = -1; + *col = -1; + } + + fmanager->priv->dropped = FALSE; +} + static void xfdesktop_file_icon_manager_file_changed(GFileMonitor *monitor, GFile *file, @@ -2745,6 +2848,14 @@ xfdesktop_file_icon_manager_file_changed(GFileMonitor *monitor, } if(file_info) { + /* Check if the icon should be placed under the cursor */ + if(fmanager->priv->create_under_cursor + && xfdesktop_file_utils_is_desktop_file(file_info)) + { + lookup_cursor_position(fmanager, file, &row, &col, TRUE); + } else + row = col = -1; + /* Add the icon adding the row/col info */ icon = xfdesktop_file_icon_manager_add_regular_icon(fmanager, other_file, @@ -2801,10 +2912,20 @@ xfdesktop_file_icon_manager_file_changed(GFileMonitor *monitor, file_info = g_file_query_info(file, XFDESKTOP_FILE_INFO_NAMESPACE, G_FILE_QUERY_INFO_NONE, NULL, NULL); if(file_info) { - xfdesktop_file_icon_manager_add_regular_icon(fmanager, - file, file_info, - -1, -1, - TRUE); + /* Check if the icon should be placed under the cursor */ + if(fmanager->priv->create_under_cursor) + lookup_cursor_position(fmanager, file, &row, &col, FALSE); + else + row = col = -1; + + icon = xfdesktop_file_icon_manager_add_regular_icon(fmanager, + file, + file_info, + row, + col, + TRUE); + if(icon && fmanager->priv->create_under_cursor) + xfdesktop_file_icon_position_changed(icon, fmanager); g_object_unref(file_info); } @@ -3471,6 +3592,8 @@ xfdesktop_file_icon_manager_drag_drop(XfdesktopIconViewManager *manager, GDK_PROP_MODE_REPLACE, (const guchar *)uri, strlen(uri)); + fmanager->priv->dropped = TRUE; + g_free(prop_text); g_free(uri); } @@ -3487,6 +3610,10 @@ xfdesktop_file_icon_manager_drag_drop(XfdesktopIconViewManager *manager, } } + /* save drop position */ + fmanager->priv->saved_row = row; + fmanager->priv->saved_col = col; + TRACE("target good"); gtk_drag_get_data(widget, context, target, time_); @@ -3787,6 +3914,10 @@ xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager g_object_unref(base_dest_file); if(dest_file_list) { + /* update saved file list */ + g_list_free(fmanager->priv->saved_file_list); + fmanager->priv->saved_file_list = file_list; + dest_file_list = g_list_reverse(dest_file_list); drop_ok = xfdesktop_file_utils_transfer_files(action, @@ -3804,6 +3935,9 @@ xfdesktop_file_icon_manager_drag_data_received(XfdesktopIconViewManager *manager } } + if(drop_ok) + fmanager->priv->dropped = TRUE; + XF_DEBUG("finishing drop on desktop from external source: drop_ok=%s, copy_only=%s", drop_ok?"TRUE":"FALSE", copy_only?"TRUE":"FALSE"); @@ -3979,6 +4113,8 @@ xfdesktop_file_icon_manager_new(GFile *folder, G_OBJECT(fmanager), "show-thumbnails"); xfconf_g_property_bind(channel, DESKTOP_ICONS_SHOW_HIDDEN_FILES, G_TYPE_BOOLEAN, G_OBJECT(fmanager), "show-hidden-files"); + xfconf_g_property_bind(channel, DESKTOP_ICONS_CREATE_UNDER_CURSOR, G_TYPE_BOOLEAN, + G_OBJECT(fmanager), "create-under-cursor"); xfconf_g_property_bind(channel, DESKTOP_MENU_MAX_TEMPLATE_FILES, G_TYPE_INT, G_OBJECT(fmanager), "max-templates"); @@ -4103,6 +4239,20 @@ xfdesktop_file_icon_manager_set_show_hidden_files(XfdesktopFileIconManager *mana g_signal_emit(G_OBJECT(manager), fmanager_signals[HIDDEN_STATE_CHANGED], 0); } +static void +xfdesktop_file_icon_manager_set_create_under_cursor(XfdesktopFileIconManager *manager, + gboolean create_under_cursor) +{ + g_return_if_fail(XFDESKTOP_IS_FILE_ICON_MANAGER(manager)); + + TRACE("entering create_under_cursor %s", create_under_cursor ? "TRUE" : "FALSE"); + + if(create_under_cursor == manager->priv->create_under_cursor) + return; + + manager->priv->create_under_cursor = create_under_cursor; +} + static void xfdesktop_file_icon_manager_set_max_templates(XfdesktopFileIconManager *manager, gint max_templates) diff --git a/src/xfdesktop-file-utils.c b/src/xfdesktop-file-utils.c index 86856d56..ed96f0d0 100644 --- a/src/xfdesktop-file-utils.c +++ b/src/xfdesktop-file-utils.c @@ -85,6 +85,20 @@ static XfdesktopThunar *xfdesktop_file_utils_peek_thunar_proxy(void); static gpointer xfdesktop_file_utils_peek_thunar_proxy(void); #endif +static gboolean xfdesktop_file_utils_created_file = FALSE; + +gboolean +xfdesktop_file_utils_get_created_file() +{ + return xfdesktop_file_utils_created_file; +} + +void +xfdesktop_file_utils_set_created_file(gboolean created_file) +{ + xfdesktop_file_utils_created_file = created_file; +} + gboolean xfdesktop_file_utils_is_desktop_file(GFileInfo *info) { @@ -1001,8 +1015,10 @@ static void create_file_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; - if (!xfdesktop_file_manager_call_create_file_finish(XFDESKTOP_FILE_MANAGER(source_object), res, &error)) + if (!xfdesktop_file_manager_call_create_file_finish(XFDESKTOP_FILE_MANAGER(source_object), res, &error)) { xfdesktop_file_utils_async_handle_error(error, user_data); + xfdesktop_file_utils_created_file = FALSE; + } } void @@ -1025,6 +1041,8 @@ xfdesktop_file_utils_create_file(GFile *parent_folder, gchar *display_name = g_strdup(gdk_display_get_name(gdk_screen_get_display(screen))); gchar *startup_id = g_strdup_printf("_TIME%d", gtk_get_current_event_time()); + xfdesktop_file_utils_created_file = TRUE; + xfdesktop_file_utils_set_window_cursor(parent, GDK_WATCH); @@ -1056,8 +1074,10 @@ static void create_file_from_template_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; - if (!xfdesktop_file_manager_call_create_file_from_template_finish(XFDESKTOP_FILE_MANAGER(source_object), res, &error)) + if (!xfdesktop_file_manager_call_create_file_from_template_finish(XFDESKTOP_FILE_MANAGER(source_object), res, &error)) { xfdesktop_file_utils_async_handle_error(error, user_data); + xfdesktop_file_utils_created_file = FALSE; + } } void @@ -1082,6 +1102,8 @@ xfdesktop_file_utils_create_file_from_template(GFile *parent_folder, gchar *display_name = g_strdup(gdk_display_get_name(gdk_screen_get_display(screen))); gchar *startup_id = g_strdup_printf("_TIME%d", gtk_get_current_event_time()); + xfdesktop_file_utils_created_file = TRUE; + xfdesktop_file_utils_set_window_cursor(parent, GDK_WATCH); diff --git a/src/xfdesktop-file-utils.h b/src/xfdesktop-file-utils.h index 1fb2591b..c2e85d87 100644 --- a/src/xfdesktop-file-utils.h +++ b/src/xfdesktop-file-utils.h @@ -115,6 +115,8 @@ gboolean xfdesktop_file_utils_transfer_files(GdkDragAction action, gboolean xfdesktop_file_utils_dbus_init(void); void xfdesktop_file_utils_dbus_cleanup(void); +gboolean xfdesktop_file_utils_get_created_file(); +void xfdesktop_file_utils_set_created_file(gboolean value); #ifdef HAVE_THUNARX diff --git a/src/xfdesktop-icon-view.c b/src/xfdesktop-icon-view.c index a21a7ad0..1ce0d1a7 100644 --- a/src/xfdesktop-icon-view.c +++ b/src/xfdesktop-icon-view.c @@ -194,6 +194,9 @@ struct _XfdesktopIconViewPrivate gboolean single_click; gint gravity; + + gint16 clicked_row; + gint16 clicked_col; }; static void xfce_icon_view_set_property(GObject *object, @@ -681,6 +684,9 @@ xfdesktop_icon_view_init(XfdesktopIconView *icon_view) context = gtk_widget_get_style_context(GTK_WIDGET(icon_view)); gtk_style_context_add_class(context, GTK_STYLE_CLASS_VIEW); + + icon_view->priv->clicked_row = -1; + icon_view->priv->clicked_col = -1; } static void @@ -933,6 +939,11 @@ xfdesktop_icon_view_button_press(GtkWidget *widget, /* Since we're not over any icons this won't be the start of a * drag so we can pop up menu */ if(evt->button == 3 || (evt->button == 1 && (evt->state & GDK_SHIFT_MASK))) { + /* save clicked position */ + xfdesktop_xy_to_rowcol(icon_view, evt->x, evt->y, + &(icon_view->priv->clicked_row), + &(icon_view->priv->clicked_col)); + xfce_desktop_popup_root_menu(XFCE_DESKTOP(widget), evt->button, evt->time); return TRUE; } @@ -4431,6 +4442,30 @@ xfdesktop_icon_view_get_window_widget(XfdesktopIconView *icon_view) return icon_view->priv->parent_window; } +void +xfdesktop_icon_view_get_clicked_position(XfdesktopIconView *icon_view, + gint16 *row, + gint16 *col) +{ + g_return_if_fail(XFDESKTOP_IS_ICON_VIEW(icon_view)); + + *col = icon_view->priv->clicked_col; + *row = icon_view->priv->clicked_row; +} + +void +xfdesktop_icon_view_get_next_free_slot(XfdesktopIconView *icon_view, + gint16 *row, + gint16 *col) +{ + g_return_if_fail(XFDESKTOP_IS_ICON_VIEW(icon_view)); + + /* Find the next available slot for an icon */ + while(!xfdesktop_grid_is_free_position(icon_view, *row, *col)) { + xfdesktop_next_slot(icon_view, col, row, icon_view->priv->ncols, icon_view->priv->nrows); + } +} + #if defined(DEBUG) && DEBUG > 0 guint _xfdesktop_icon_view_n_items(XfdesktopIconView *icon_view) diff --git a/src/xfdesktop-icon-view.h b/src/xfdesktop-icon-view.h index 94d1f423..95578df2 100644 --- a/src/xfdesktop-icon-view.h +++ b/src/xfdesktop-icon-view.h @@ -125,6 +125,13 @@ void xfdesktop_icon_view_set_center_text (XfdesktopIconView *icon_view, GtkWidget *xfdesktop_icon_view_get_window_widget(XfdesktopIconView *icon_view); +void xfdesktop_icon_view_get_clicked_position(XfdesktopIconView *icon_view, + gint16 *row, + gint16 *col); +void xfdesktop_icon_view_get_next_free_slot(XfdesktopIconView *icon_view, + gint16 *row, + gint16 *col); + gboolean xfdesktop_get_workarea_single(XfdesktopIconView *icon_view, guint ws_num,