Index: thunar/thunar-standard-view.c =================================================================== --- thunar/thunar-standard-view.c (revision 22891) +++ thunar/thunar-standard-view.c (working copy) @@ -3263,42 +3263,56 @@ gboolean pastable; gboolean writable; gboolean trashed; - GList *lp, *selected_files; + GList *selected_files; + GList *np; + GList *op; gint n_selected_files = 0; _thunar_return_if_fail (THUNAR_IS_STANDARD_VIEW (standard_view)); - /* drop any existing "new-files" closure */ - if (G_UNLIKELY (standard_view->priv->new_files_closure != NULL)) - { - g_closure_invalidate (standard_view->priv->new_files_closure); - g_closure_unref (standard_view->priv->new_files_closure); - standard_view->priv->new_files_closure = NULL; - } - - /* release the previously selected files */ - thunar_file_list_free (standard_view->selected_files); - /* determine the new list of selected files (replacing GtkTreePath's with ThunarFile's) */ selected_files = (*THUNAR_STANDARD_VIEW_GET_CLASS (standard_view)->get_selected_items) (standard_view); - for (lp = selected_files; lp != NULL; lp = lp->next, ++n_selected_files) + for (np = selected_files; np != NULL; np = np->next, ++n_selected_files) { /* determine the iterator for the path */ - gtk_tree_model_get_iter (GTK_TREE_MODEL (standard_view->model), &iter, lp->data); + gtk_tree_model_get_iter (GTK_TREE_MODEL (standard_view->model), &iter, np->data); /* release the tree path... */ - gtk_tree_path_free (lp->data); + gtk_tree_path_free (np->data); /* ...and replace it with the file */ - lp->data = thunar_list_model_get_file (standard_view->model, &iter); + np->data = thunar_list_model_get_file (standard_view->model, &iter); } + /* check if we have a valid "new-files" closure */ + if (G_UNLIKELY (standard_view->priv->new_files_closure != NULL)) + { + /* compare the old and new selection lists to avoid invalidating the "new-files" closure if the selection + * did not really change, part of the fix for http://bugzilla.xfce.org/show_bug.cgi?id=2199. + */ + for (np = selected_files, op = standard_view->selected_files; np != NULL && op != NULL; np = np->next, op = op->next) + if (G_LIKELY (np->data != op->data)) + break; + + /* check if the selection really changed */ + if (G_LIKELY (np != NULL || op != NULL)) + { + /* invalidate and drop the existing "new-files" closure */ + g_closure_invalidate (standard_view->priv->new_files_closure); + g_closure_unref (standard_view->priv->new_files_closure); + standard_view->priv->new_files_closure = NULL; + } + } + + /* release the previously selected files */ + thunar_file_list_free (standard_view->selected_files); + /* and setup the new selected files list */ standard_view->selected_files = selected_files; /* enable "Restore" if we have only trashed files (atleast one file) */ - for (lp = selected_files, restorable = (lp != NULL); lp != NULL; lp = lp->next) - if (!thunar_file_is_trashed (lp->data)) + for (np = selected_files, restorable = (np != NULL); np != NULL; np = np->next) + if (!thunar_file_is_trashed (np->data)) { restorable = FALSE; break; Index: thunar-vfs/thunar-vfs-monitor.c =================================================================== --- thunar-vfs/thunar-vfs-monitor.c (revision 22891) +++ thunar-vfs/thunar-vfs-monitor.c (working copy) @@ -171,7 +171,6 @@ thunar_vfs_monitor_init (ThunarVfsMonitor *monitor) { /* initialize the monitor */ - monitor->notifications_timer_id = -1; monitor->cond = g_cond_new (); monitor->lock = g_mutex_new (); @@ -212,7 +211,7 @@ #endif /* drop the notifications timer source */ - if (G_UNLIKELY (monitor->notifications_timer_id >= 0)) + if (G_UNLIKELY (monitor->notifications_timer_id != 0)) g_source_remove (monitor->notifications_timer_id); /* drop all pending notifications */ @@ -249,22 +248,16 @@ const gchar *filename) { ThunarVfsMonitorNotification *notification; + ThunarVfsMonitorNotification *position; gint length; - g_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); - g_return_if_fail (reqnum > 0 && reqnum <= monitor->current_reqnum); + _thunar_vfs_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); + _thunar_vfs_return_if_fail (reqnum > 0 && reqnum <= monitor->current_reqnum); /* check if we already have a matching notification */ for (notification = monitor->notifications; notification != NULL; notification = notification->next) - if (notification->reqnum == reqnum && exo_str_is_equal (filename, notification->filename)) - { - if (tag >= notification->tag) - { - notification->tag = tag; - notification->event = event; - } - return; - } + if (notification->reqnum == reqnum && exo_str_is_equal (filename, notification->filename) && notification->tag == tag && notification->event == event) + return; /* allocate a new notification */ if (G_LIKELY (filename != NULL)) @@ -280,15 +273,31 @@ notification->filename = NULL; } - /* prepend the notification to the queue */ + /* prepare the notification */ notification->reqnum = reqnum; notification->tag = tag; - notification->next = monitor->notifications; notification->event = event; - monitor->notifications = notification; + /* and append it to the list */ + if (monitor->notifications == NULL) + { + /* we have a new head */ + monitor->notifications = notification; + notification->next = NULL; + } + else + { + /* lookup the position where to insert the notification, making sure that FAM events will be sorted after feeded ones... */ + for (position = monitor->notifications; position->next != NULL && position->tag >= tag; position = position->next) + ; + + /* ...and insert the notification */ + notification->next = position->next; + position->next = notification; + } + /* schedule the notification timer if not already active */ - if (G_UNLIKELY (monitor->notifications_timer_id < 0)) + if (G_UNLIKELY (monitor->notifications_timer_id == 0)) monitor->notifications_timer_id = g_timeout_add (THUNAR_VFS_MONITOR_TIMER_INTERVAL, thunar_vfs_monitor_notifications_timer, monitor); } @@ -312,7 +321,7 @@ g_mutex_lock (monitor->lock); /* reset the timer id */ - monitor->notifications_timer_id = -1; + monitor->notifications_timer_id = 0; /* process all pending notifications */ while (monitor->notifications != NULL) @@ -374,8 +383,8 @@ static void thunar_vfs_monitor_fam_cancel (ThunarVfsMonitor *monitor) { - g_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); - g_return_if_fail (monitor->fc_watch_id >= 0); + _thunar_vfs_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); + _thunar_vfs_return_if_fail (monitor->fc_watch_id >= 0); /* close the FAM connection */ FAMClose (&monitor->fc); @@ -704,7 +713,7 @@ g_return_if_fail (THUNAR_VFS_IS_MONITOR (monitor)); g_mutex_lock (monitor->lock); - while (g_atomic_int_get (&monitor->notifications_timer_id) >= 0) + while (g_atomic_int_get (&monitor->notifications_timer_id) != 0) g_cond_timed_wait (monitor->cond, monitor->lock, (GTimeVal *) &tv); g_mutex_unlock (monitor->lock); }