diff --git a/nautilus-xdg-user-dirs.patch b/nautilus-xdg-user-dirs.patch new file mode 100644 index 0000000..be32ebb --- /dev/null +++ b/nautilus-xdg-user-dirs.patch @@ -0,0 +1,586 @@ +Index: src/file-manager/fm-directory-view.c +=================================================================== +--- src/file-manager/fm-directory-view.c (revision 12767) ++++ src/file-manager/fm-directory-view.c (working copy) +@@ -151,6 +151,7 @@ + #define FM_DIRECTORY_VIEW_POPUP_PATH_LOCATION "/location" + + #define MAX_MENU_LEVELS 5 ++#define TEMPLATE_LIMIT 30 + + enum { + ADD_FILE, +@@ -187,9 +188,6 @@ static gboolean confirm_trash_auto_value + static char *scripts_directory_uri; + static int scripts_directory_uri_length; + +-static char *templates_directory_uri; +-static int templates_directory_uri_length; +- + struct FMDirectoryViewDetails + { + NautilusWindowInfo *window; +@@ -389,6 +387,8 @@ static gboolean activate_check_mime_type + NautilusFile *file, + gboolean warn_on_mismatch); + static GdkDragAction ask_link_action (FMDirectoryView *view); ++static void update_templates_directory (FMDirectoryView *view); ++static void user_dirs_changed (FMDirectoryView *view); + + static void file_get_volume_and_drive (NautilusFile *file, + GnomeVFSVolume **volume, +@@ -1619,17 +1619,6 @@ set_up_scripts_directory_global (void) + } + + static void +-set_up_templates_directory_global (void) +-{ +- if (templates_directory_uri != NULL) { +- return; +- } +- +- templates_directory_uri = nautilus_get_templates_directory_uri (); +- templates_directory_uri_length = strlen (templates_directory_uri); +-} +- +-static void + create_scripts_directory (void) + { + char *gnome1_path, *gnome1_uri_str; +@@ -1912,6 +1901,7 @@ fm_directory_view_init (FMDirectoryView + static gboolean setup_autos = FALSE; + NautilusDirectory *scripts_directory; + NautilusDirectory *templates_directory; ++ char *templates_uri; + + if (!setup_autos) { + setup_autos = TRUE; +@@ -1940,10 +1930,18 @@ fm_directory_view_init (FMDirectoryView + add_directory_to_scripts_directory_list (view, scripts_directory); + nautilus_directory_unref (scripts_directory); + +- set_up_templates_directory_global (); +- templates_directory = nautilus_directory_get (templates_directory_uri); +- add_directory_to_templates_directory_list (view, templates_directory); +- nautilus_directory_unref (templates_directory); ++ if (nautilus_should_use_templates_directory ()) { ++ templates_uri = nautilus_get_templates_directory_uri (); ++ templates_directory = nautilus_directory_get (templates_uri); ++ g_free (templates_uri); ++ add_directory_to_templates_directory_list (view, templates_directory); ++ nautilus_directory_unref (templates_directory); ++ } ++ update_templates_directory (view); ++ g_signal_connect_object (nautilus_signaller_get_current (), ++ "user_dirs_changed", ++ G_CALLBACK (user_dirs_changed), ++ view, G_CONNECT_SWAPPED); + + view->details->sort_directories_first = + eel_preferences_get_boolean (NAUTILUS_PREFERENCES_SORT_DIRECTORIES_FIRST); +@@ -5712,19 +5710,52 @@ add_template_to_templates_menus (FMDirec + g_free (action_name); + } + ++static void ++update_templates_directory (FMDirectoryView *view) ++{ ++ NautilusDirectory *templates_directory; ++ GList *node, *next; ++ char *templates_uri; ++ ++ for (node = view->details->templates_directory_list; node != NULL; node = next) { ++ next = node->next; ++ remove_directory_from_templates_directory_list (view, node->data); ++ } ++ ++ if (nautilus_should_use_templates_directory ()) { ++ templates_uri = nautilus_get_templates_directory_uri (); ++ templates_directory = nautilus_directory_get (templates_uri); ++ g_free (templates_uri); ++ add_directory_to_templates_directory_list (view, templates_directory); ++ nautilus_directory_unref (templates_directory); ++ } ++} ++ ++static void ++user_dirs_changed (FMDirectoryView *view) ++{ ++ update_templates_directory (view); ++ view->details->templates_invalid = TRUE; ++ schedule_update_menus (view); ++} + + static gboolean +-directory_belongs_in_templates_menu (const char *uri) ++directory_belongs_in_templates_menu (const char *templates_directory_uri, ++ const char *uri) + { + int num_levels; + int i; + +- if (!eel_str_has_prefix (uri, templates_directory_uri)) { ++ if (templates_directory_uri == NULL) { ++ return FALSE; ++ } ++ ++ if (!g_str_has_prefix (uri, templates_directory_uri)) { + return FALSE; + } + + num_levels = 0; +- for (i = templates_directory_uri_length; uri[i] != '\0'; i++) { ++ for (i = strlen (templates_directory_uri); uri[i] != '\0'; i++) { + if (uri[i] == '/') { + num_levels++; + } +@@ -5738,7 +5769,9 @@ directory_belongs_in_templates_menu (con + } + + static gboolean +-update_directory_in_templates_menu (FMDirectoryView *view, NautilusDirectory *directory) ++update_directory_in_templates_menu (FMDirectoryView *view, ++ const char *templates_directory_uri, ++ NautilusDirectory *directory) + { + char *menu_path, *popup_bg_path; + GList *file_list, *filtered, *node; +@@ -5747,9 +5780,13 @@ update_directory_in_templates_menu (FMDi + NautilusDirectory *dir; + char *escaped_path; + char *uri; ++ int num; ++ ++ /* We know this directory belongs to the template dir, so it must exist */ ++ g_assert (templates_directory_uri); + + uri = nautilus_directory_get_uri (directory); +- escaped_path = escape_action_path (uri + templates_directory_uri_length); ++ escaped_path = escape_action_path (uri + strlen (templates_directory_uri)); + g_free (uri); + menu_path = g_strconcat (FM_DIRECTORY_VIEW_MENU_PATH_NEW_DOCUMENTS_PLACEHOLDER, + escaped_path, +@@ -5765,13 +5802,14 @@ update_directory_in_templates_menu (FMDi + + file_list = nautilus_file_list_sort_by_display_name (filtered); + ++ num = 0; + any_templates = FALSE; +- for (node = file_list; node != NULL; node = node->next) { ++ for (node = file_list; num < TEMPLATE_LIMIT && node != NULL; node = node->next, num++) { + file = node->data; + + if (nautilus_file_is_directory (file)) { + uri = nautilus_file_get_uri (file); +- if (directory_belongs_in_templates_menu (uri)) { ++ if (directory_belongs_in_templates_menu (templates_directory_uri, uri)) { + dir = nautilus_directory_get (uri); + add_directory_to_templates_directory_list (view, dir); + nautilus_directory_unref (dir); +@@ -5809,6 +5847,13 @@ update_templates_menu (FMDirectoryView * + GtkUIManager *ui_manager; + char *uri; + GtkAction *action; ++ char *templates_directory_uri; ++ ++ if (nautilus_should_use_templates_directory ()) { ++ templates_directory_uri = nautilus_get_templates_directory_uri (); ++ } else { ++ templates_directory_uri = NULL; ++ } + + /* There is a race condition here. If we don't mark the scripts menu as + valid before we begin our task then we can lose template menu updates that +@@ -5833,9 +5878,11 @@ update_templates_menu (FMDirectoryView * + directory = node->data; + + uri = nautilus_directory_get_uri (directory); +- if (!directory_belongs_in_templates_menu (uri)) { ++ if (!directory_belongs_in_templates_menu (templates_directory_uri, uri)) { + remove_directory_from_templates_directory_list (view, directory); +- } else if (update_directory_in_templates_menu (view, directory)) { ++ } else if (update_directory_in_templates_menu (view, ++ templates_directory_uri, ++ directory)) { + any_templates = TRUE; + } + g_free (uri); +@@ -5844,6 +5891,8 @@ update_templates_menu (FMDirectoryView * + + action = gtk_action_group_get_action (view->details->dir_action_group, FM_ACTION_NO_TEMPLATES); + gtk_action_set_visible (action, !any_templates); ++ ++ g_free (templates_directory_uri); + } + + +Index: libnautilus-private/nautilus-file-utilities.c +=================================================================== +--- libnautilus-private/nautilus-file-utilities.c (revision 12767) ++++ libnautilus-private/nautilus-file-utilities.c (working copy) +@@ -31,6 +31,7 @@ + #include "nautilus-metafile.h" + #include "nautilus-file.h" + #include "nautilus-search-directory.h" ++#include "nautilus-signaller.h" + #include + #include + #include +@@ -49,6 +50,7 @@ + #define LEGACY_DESKTOP_DIRECTORY_NAME ".gnome-desktop" + #define DEFAULT_DESKTOP_DIRECTORY_MODE (0755) + ++static void update_xdg_dir_cache (void); + + char * + nautilus_compute_title_for_uri (const char *text_uri) +@@ -148,15 +150,277 @@ nautilus_get_user_directory (void) + return user_directory; + } + ++typedef struct { ++ char *type; ++ char *path; ++ NautilusFile *file; ++} XdgDirEntry; ++ ++ ++static XdgDirEntry * ++parse_xdg_dirs (const char *config_file) ++{ ++ GArray *array; ++ char *config_file_free = NULL; ++ XdgDirEntry dir; ++ char *data; ++ char **lines; ++ char *p, *d; ++ int i; ++ char *type_start, *type_end; ++ char *value, *unescaped; ++ gboolean relative; ++ ++ array = g_array_new (TRUE, TRUE, sizeof (XdgDirEntry)); ++ ++ if (config_file == NULL) ++ { ++ config_file_free = g_build_filename (g_get_user_config_dir (), ++ "user-dirs.dirs", NULL); ++ config_file = (const char *)config_file_free; ++ } ++ ++ if (g_file_get_contents (config_file, &data, NULL, NULL)) ++ { ++ lines = g_strsplit (data, "\n", 0); ++ g_free (data); ++ for (i = 0; lines[i] != NULL; i++) ++ { ++ p = lines[i]; ++ while (g_ascii_isspace (*p)) ++ p++; ++ ++ if (*p == '#') ++ continue; ++ ++ value = strchr (p, '='); ++ if (value == NULL) ++ continue; ++ *value++ = 0; ++ ++ g_strchug (g_strchomp (p)); ++ if (!g_str_has_prefix (p, "XDG_")) ++ continue; ++ if (!g_str_has_suffix (p, "_DIR")) ++ continue; ++ type_start = p + 4; ++ type_end = p + strlen (p) - 4; ++ ++ while (g_ascii_isspace (*value)) ++ value++; ++ ++ if (*value != '"') ++ continue; ++ value++; ++ ++ relative = FALSE; ++ if (g_str_has_prefix (value, "$HOME")) ++ { ++ relative = TRUE; ++ value += 5; ++ while (*value == '/') ++ value++; ++ } ++ else if (*value != '/') ++ continue; ++ ++ d = unescaped = g_malloc (strlen (value) + 1); ++ while (*value && *value != '"') ++ { ++ if ((*value == '\\') && (*(value + 1) != 0)) ++ value++; ++ *d++ = *value++; ++ } ++ *d = 0; ++ ++ *type_end = 0; ++ dir.type = g_strdup (type_start); ++ if (relative) ++ { ++ dir.path = g_build_filename (g_get_home_dir (), unescaped, NULL); ++ g_free (unescaped); ++ } ++ else ++ dir.path = unescaped; ++ ++ g_array_append_val (array, dir); ++ } ++ ++ g_strfreev (lines); ++ } ++ ++ g_free (config_file_free); ++ ++ return (XdgDirEntry *)g_array_free (array, FALSE); ++} ++ ++static XdgDirEntry *cached_xdg_dirs = NULL; ++static GnomeVFSMonitorHandle *cached_xdg_dirs_handle = NULL; ++ ++static void ++xdg_dir_changed (NautilusFile *file, ++ XdgDirEntry *dir) ++{ ++ char *file_uri; ++ char *dir_uri; ++ char *path; ++ ++ file_uri = nautilus_file_get_uri (file); ++ dir_uri = gnome_vfs_get_uri_from_local_path (dir->path); ++ if (file_uri && dir_uri && ++ !gnome_vfs_uris_match (dir_uri, file_uri)) { ++ path = gnome_vfs_get_local_path_from_uri (file_uri); ++ ++ if (path) { ++ char *argv[5]; ++ int i; ++ ++ g_free (dir->path); ++ dir->path = path; ++ ++ i = 0; ++ argv[i++] = "xdg-user-dirs-update"; ++ argv[i++] = "--set"; ++ argv[i++] = dir->type; ++ argv[i++] = dir->path; ++ argv[i++] = NULL; ++ ++ /* We do this sync, to avoid possible race-conditions ++ if multiple dirs change at the same time. Its ++ blocking the main thread, but these updates should ++ be very rare and very fast. */ ++ g_spawn_sync (NULL, ++ argv, NULL, ++ G_SPAWN_SEARCH_PATH | ++ G_SPAWN_STDOUT_TO_DEV_NULL | ++ G_SPAWN_STDERR_TO_DEV_NULL, ++ NULL, NULL, ++ NULL, NULL, NULL, NULL); ++ } ++ } ++ g_free (file_uri); ++ g_free (dir_uri); ++} ++ ++static void ++xdg_dir_cache_changed_cb (GnomeVFSMonitorHandle *handle, ++ const gchar *monitor_uri, ++ const gchar *info_uri, ++ GnomeVFSMonitorEventType event_type, ++ gpointer user_data) ++{ ++ if (event_type == GNOME_VFS_MONITOR_EVENT_CHANGED || ++ event_type == GNOME_VFS_MONITOR_EVENT_CREATED) { ++ update_xdg_dir_cache (); ++ } ++} ++ ++static int user_dirs_changed_tag = 0; ++ ++static gboolean ++emit_user_dirs_changed_idle (gpointer data) ++{ ++ g_signal_emit_by_name (nautilus_signaller_get_current (), ++ "user_dirs_changed"); ++ user_dirs_changed_tag = 0; ++ return FALSE; ++} ++ ++static void ++schedule_user_dirs_changed (void) ++{ ++ if (user_dirs_changed_tag == 0) { ++ user_dirs_changed_tag = g_idle_add (emit_user_dirs_changed_idle, NULL); ++ } ++} ++ ++static void ++update_xdg_dir_cache (void) ++{ ++ static gboolean started_monitor = FALSE; ++ char *config_file, *uri; ++ int i; ++ ++ if (cached_xdg_dirs) { ++ for (i = 0 ; cached_xdg_dirs[i].type != NULL; i++) { ++ if (cached_xdg_dirs[i].file != NULL) { ++ nautilus_file_monitor_remove (cached_xdg_dirs[i].file, ++ &cached_xdg_dirs[i]); ++ g_signal_handlers_disconnect_by_func (cached_xdg_dirs[i].file, ++ G_CALLBACK (xdg_dir_changed), ++ &cached_xdg_dirs[i]); ++ nautilus_file_unref (cached_xdg_dirs[i].file); ++ } ++ g_free (cached_xdg_dirs[i].type); ++ g_free (cached_xdg_dirs[i].path); ++ } ++ g_free (cached_xdg_dirs); ++ ++ schedule_user_dirs_changed (); ++ } ++ ++ if (!started_monitor) { ++ config_file = g_build_filename (g_get_user_config_dir (), ++ "user-dirs.dirs", NULL); ++ uri = gnome_vfs_get_uri_from_local_path (config_file); ++ gnome_vfs_monitor_add (&cached_xdg_dirs_handle, ++ uri, ++ GNOME_VFS_MONITOR_FILE, ++ xdg_dir_cache_changed_cb, ++ NULL); ++ g_free (uri); ++ g_free (config_file); ++ } ++ ++ cached_xdg_dirs = parse_xdg_dirs (NULL); ++ ++ for (i = 0 ; cached_xdg_dirs[i].type != NULL; i++) { ++ cached_xdg_dirs[i].file = NULL; ++ if (strcmp (cached_xdg_dirs[i].path, g_get_home_dir ()) != 0) { ++ uri = gnome_vfs_get_uri_from_local_path (cached_xdg_dirs[i].path); ++ cached_xdg_dirs[i].file = nautilus_file_get (uri); ++ nautilus_file_monitor_add (cached_xdg_dirs[i].file, ++ &cached_xdg_dirs[i], ++ NAUTILUS_FILE_ATTRIBUTE_FILE_TYPE); ++ g_signal_connect (cached_xdg_dirs[i].file, ++ "changed", G_CALLBACK (xdg_dir_changed), &cached_xdg_dirs[i]); ++ g_free (uri); ++ } ++ } ++} ++ ++char * ++nautilus_get_xdg_dir (const char *type) ++{ ++ int i; ++ ++ if (cached_xdg_dirs == NULL) { ++ update_xdg_dir_cache (); ++ } ++ ++ for (i = 0 ; cached_xdg_dirs != NULL && cached_xdg_dirs[i].type != NULL; i++) { ++ if (strcmp (cached_xdg_dirs[i].type, type) == 0) { ++ return g_strdup (cached_xdg_dirs[i].path); ++ } ++ } ++ if (strcmp ("DESKTOP", type) == 0) { ++ return g_build_filename (g_get_home_dir (), DESKTOP_DIRECTORY_NAME, NULL); ++ } ++ if (strcmp ("TEMPLATES", type) == 0) { ++ return g_build_filename (g_get_home_dir (), "Templates", NULL); ++ } ++ ++ return g_strdup (g_get_home_dir ()); ++} ++ + static char * + get_desktop_path (void) + { + if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR)) { + return g_strdup (g_get_home_dir()); + } else { +- return g_build_filename (g_get_home_dir (), DESKTOP_DIRECTORY_NAME, NULL); ++ return nautilus_get_xdg_dir ("DESKTOP"); + } +- + } + + /** +@@ -231,11 +495,22 @@ nautilus_get_home_directory_uri (void) + } + + ++gboolean ++nautilus_should_use_templates_directory (void) ++{ ++ char *dir; ++ gboolean res; ++ ++ dir = nautilus_get_xdg_dir ("TEMPLATES"); ++ res = strcmp (dir, g_get_home_dir ()) != 0; ++ g_free (dir); ++ return res; ++} ++ + char * + nautilus_get_templates_directory (void) + { +- return g_build_filename (g_get_home_dir(), +- "Templates", NULL); ++ return nautilus_get_xdg_dir ("TEMPLATES"); + } + + void +Index: libnautilus-private/nautilus-file-utilities.h +=================================================================== +--- libnautilus-private/nautilus-file-utilities.h (revision 12767) ++++ libnautilus-private/nautilus-file-utilities.h (working copy) +@@ -37,6 +37,7 @@ gboolean nautilus_file_name_matches_back + /* These functions all return something something that needs to be + * freed with g_free, is not NULL, and is guaranteed to exist. + */ ++char * nautilus_get_xdg_dir (const char *type); + char * nautilus_get_user_directory (void); + char * nautilus_get_desktop_directory (void); + char * nautilus_get_desktop_directory_uri (void); +@@ -49,6 +50,7 @@ gboolean nautilus_is_home_directory_file + char * nautilus_get_gmc_desktop_directory (void); + char * nautilus_get_pixmap_directory (void); + ++gboolean nautilus_should_use_templates_directory (void); + char * nautilus_get_templates_directory (void); + char * nautilus_get_templates_directory_uri (void); + void nautilus_create_templates_directory (void); +Index: libnautilus-private/nautilus-signaller.c +=================================================================== +--- libnautilus-private/nautilus-signaller.c (revision 12767) ++++ libnautilus-private/nautilus-signaller.c (working copy) +@@ -39,6 +39,7 @@ enum { + HISTORY_LIST_CHANGED, + EMBLEMS_CHANGED, + POPUP_MENU_CHANGED, ++ USER_DIRS_CHANGED, + LAST_SIGNAL + }; + +@@ -94,4 +95,12 @@ nautilus_signaller_class_init (NautilusS + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); ++ signals[USER_DIRS_CHANGED] = ++ g_signal_new ("user_dirs_changed", ++ G_TYPE_FROM_CLASS (class), ++ G_SIGNAL_RUN_LAST, ++ 0, ++ NULL, NULL, ++ g_cclosure_marshal_VOID__VOID, ++ G_TYPE_NONE, 0); + } diff --git a/nautilus.spec b/nautilus.spec index 3400205..880da46 100644 --- a/nautilus.spec +++ b/nautilus.spec @@ -19,7 +19,7 @@ Name: nautilus Summary: Nautilus is a file manager for GNOME Version: 2.17.92 -Release: 1%{?dist} +Release: 2%{?dist} License: GPL Group: User Interface/Desktops Source: ftp://ftp.gnome.org/pub/GNOME/sources/%{name}/2.17/%{name}-%{version}.tar.bz2 @@ -80,6 +80,8 @@ Patch3: background-no-delay.patch Patch5: nautilus-2.17.90-selinux.patch Patch6: nautilus-2.16.2-dynamic-search.patch +Patch7: nautilus-xdg-user-dirs.patch + %description Nautilus integrates access to files, applications, media, Internet-based resources and the Web. Nautilus delivers a dynamic and @@ -112,6 +114,7 @@ for writing nautilus extensions. %patch3 -p1 -b .no-delay %patch5 -p1 -b .selinux %patch6 -p1 -b .dynamic-search +%patch7 -p0 -b .xdg-user-dirs %build @@ -207,6 +210,9 @@ scrollkeeper-update %{_libdir}/*.so %changelog +* Thu Mar 1 2007 Alexander Larsson - 2.17.92-2 +- Add xdg-user-dirs patch + * Tue Feb 27 2007 Matthias Clasen - 2.17.92-1 - Update to 2.17.92