[Xfce4-commits] r30037 - in thunar/branches/migration-to-gio: . thunar

Jannis Pohlmann jannis at xfce.org
Wed Jun 17 01:28:53 CEST 2009


Author: jannis
Date: 2009-06-16 23:28:53 +0000 (Tue, 16 Jun 2009)
New Revision: 30037

Modified:
   thunar/branches/migration-to-gio/ChangeLog
   thunar/branches/migration-to-gio/thunar/main.c
   thunar/branches/migration-to-gio/thunar/thunar-application.c
   thunar/branches/migration-to-gio/thunar/thunar-application.h
Log:
	* thunar/main.c, thunar/thunar-application.{c,h}:
	  thunar_application_process_filenames() now works asynchronously
	  because it might have to mount the enclosing volumes of one of the
	  filenames first (which is only possible asynchronously). Add new
	  method thunar_application_is_processing() which returns whether
	  ThunarApplication is still busy processing filenames or not. In
	  main(), always enter the main loop but schedule an idle source to
	  repeatedly check whether ThunarApplication has finished processing
	  the command line arguments. Once this is the case, exit if there are
	  no open Thunar windows. All in all, this gives us about the same
	  behaviour main() had before, except that it the application might
	  exit with a short delay. The result: Calling "thunar <remote URI>"
	  from the shell works now!

Modified: thunar/branches/migration-to-gio/ChangeLog
===================================================================
--- thunar/branches/migration-to-gio/ChangeLog	2009-06-16 19:34:50 UTC (rev 30036)
+++ thunar/branches/migration-to-gio/ChangeLog	2009-06-16 23:28:53 UTC (rev 30037)
@@ -1,3 +1,19 @@
+2009-06-17	Jannis Pohlmann <jannis at xfce.org>
+
+	* thunar/main.c, thunar/thunar-application.{c,h}: 
+	  thunar_application_process_filenames() now works asynchronously
+	  because it might have to mount the enclosing volumes of one of the
+	  filenames first (which is only possible asynchronously). Add new
+	  method thunar_application_is_processing() which returns whether
+	  ThunarApplication is still busy processing filenames or not. In
+	  main(), always enter the main loop but schedule an idle source to
+	  repeatedly check whether ThunarApplication has finished processing
+	  the command line arguments. Once this is the case, exit if there are
+	  no open Thunar windows. All in all, this gives us about the same 
+	  behaviour main() had before, except that it the application might
+	  exit with a short delay. The result: Calling "thunar <remote URI>"
+	  from the shell works now!
+
 2009-06-16	Jannis Pohlmann <jannis at xfce.org>
 
 	* thunar/thunar-location-entry.c: Split

Modified: thunar/branches/migration-to-gio/thunar/main.c
===================================================================
--- thunar/branches/migration-to-gio/thunar/main.c	2009-06-16 19:34:50 UTC (rev 30036)
+++ thunar/branches/migration-to-gio/thunar/main.c	2009-06-16 23:28:53 UTC (rev 30037)
@@ -39,6 +39,7 @@
 #include <thunar/thunar-dbus-client.h>
 #include <thunar/thunar-dbus-service.h>
 #include <thunar/thunar-gobject-extensions.h>
+#include <thunar/thunar-private.h>
 #include <thunar/thunar-session-client.h>
 #include <thunar/thunar-stock.h>
 
@@ -74,12 +75,43 @@
 
 
 
+static gboolean
+thunar_delayed_exit_check (gpointer user_data)
+{
+  ThunarApplication *application = user_data;
+
+  _thunar_return_val_if_fail (THUNAR_IS_APPLICATION (application), FALSE);
+
+  /* call this function again later if the application is still processing the
+   * command line arguments */
+  if (thunar_application_is_processing (application))
+    return TRUE;
+
+  /* the application has processed all command line arguments. don't call
+   * this function again if it could load at least one of them */
+  if (thunar_application_has_windows (application))
+    {
+      return FALSE;
+    }
+  else
+    {
+      /* no command line arguments opened in Thunar, exit now */
+      gtk_main_quit ();
+
+      /* don't call this function again */
+      return FALSE;
+    }
+  
+}
+
+
+
 int
 main (int argc, char **argv)
 {
   ThunarSessionClient *session_client;
 #ifdef HAVE_DBUS
-  ThunarDBusService   *dbus_service;
+  ThunarDBusService   *dbus_service = NULL;
 #endif
   ThunarApplication   *application;
   GError              *error = NULL;
@@ -241,22 +273,31 @@
   /* connect to the session manager */
   session_client = thunar_session_client_new (opt_sm_client_id);
 
-  /* do not enter the main loop, unless we have atleast one window or we are in daemon mode */
-  if (thunar_application_has_windows (application) || thunar_application_get_daemon (application))
+  /* check if the application should run as a daemon */
+  if (thunar_application_get_daemon (application))
     {
-      /* attach the D-BUS service */
 #ifdef HAVE_DBUS
+      /* attach the D-Bus service */
       dbus_service = g_object_new (THUNAR_TYPE_DBUS_SERVICE, NULL);
 #endif
+    }
+  else
+    {
+      /* processing the command line arguments is done asynchronously. Thus, we
+       * schedule an idle source which repeatedly checks whether we are done
+       * processing. Once we're done, it'll make the application quit if there
+       * are no open windows */
+      g_idle_add_full (G_PRIORITY_LOW, thunar_delayed_exit_check, 
+                       g_object_ref (application), g_object_unref);
+    }
 
-      /* enter the main loop */
-      gtk_main ();
+  /* enter the main loop */
+  gtk_main ();
 
-      /* detach the D-BUS service */
 #ifdef HAVE_DBUS
-      g_object_unref (G_OBJECT (dbus_service));
+  if (dbus_service != NULL)
+    g_object_unref (G_OBJECT (dbus_service));
 #endif
-    }
 
   /* disconnect from the session manager */
   g_object_unref (G_OBJECT (session_client));

Modified: thunar/branches/migration-to-gio/thunar/thunar-application.c
===================================================================
--- thunar/branches/migration-to-gio/thunar/thunar-application.c	2009-06-16 19:34:50 UTC (rev 30036)
+++ thunar/branches/migration-to-gio/thunar/thunar-application.c	2009-06-16 23:28:53 UTC (rev 30037)
@@ -64,56 +64,57 @@
 
 
 
-static void       thunar_application_class_init             (ThunarApplicationClass *klass);
-static void       thunar_application_init                   (ThunarApplication      *application);
-static void       thunar_application_finalize               (GObject                *object);
-static void       thunar_application_get_property           (GObject                *object,
-                                                             guint                   prop_id,
-                                                             GValue                 *value,
-                                                             GParamSpec             *pspec);
-static void       thunar_application_set_property           (GObject                *object,
-                                                             guint                   prop_id,
-                                                             const GValue           *value,
-                                                             GParamSpec             *pspec);
-static void       thunar_application_collect_and_launch     (ThunarApplication      *application,
-                                                             gpointer                parent,
-                                                             const gchar            *icon_name,
-                                                             const gchar            *title,
-                                                             Launcher                launcher,
-                                                             GList                  *source_file_list,
-                                                             GFile                  *target_file,
-                                                             GClosure               *new_files_closure);
-static void       thunar_application_launch                 (ThunarApplication      *application,
-                                                             gpointer                parent,
-                                                             const gchar            *icon_name,
-                                                             const gchar            *title,
-                                                             Launcher                launcher,
-                                                             GList                  *source_path_list,
-                                                             GList                  *target_path_list,
-                                                             GClosure               *new_files_closure);
-static GtkWidget *thunar_application_open_window_with_role  (ThunarApplication      *application,
-                                                             const gchar            *role,
-                                                             ThunarFile             *directory,
-                                                             GdkScreen              *screen);
-static void       thunar_application_window_destroyed       (GtkWidget              *window,
-                                                             ThunarApplication      *application);
-static void       thunar_application_drive_connected        (GVolumeMonitor         *volume_monitor,
-                                                             GDrive                 *drive,
-                                                             ThunarApplication      *application);
-static void       thunar_application_drive_disconnected     (GVolumeMonitor         *volume_monitor,
-                                                             GDrive                 *drive,
-                                                             ThunarApplication      *application);
-static void       thunar_application_drive_eject            (GVolumeMonitor         *volume_monitor,
-                                                             GDrive                 *drive,
-                                                             ThunarApplication      *application);
-static gboolean   thunar_application_volman_idle            (gpointer                user_data);
-static void       thunar_application_volman_idle_destroy    (gpointer                user_data);
-static void       thunar_application_volman_watch           (GPid                    pid,
-                                                             gint                    status,
-                                                             gpointer                user_data);
-static void       thunar_application_volman_watch_destroy   (gpointer                user_data);
-static gboolean   thunar_application_show_dialogs           (gpointer                user_data);
-static void       thunar_application_show_dialogs_destroy   (gpointer                user_data);
+static void           thunar_application_class_init             (ThunarApplicationClass *klass);
+static void           thunar_application_init                   (ThunarApplication      *application);
+static void           thunar_application_finalize               (GObject                *object);
+static void           thunar_application_get_property           (GObject                *object,
+                                                                 guint                   prop_id,
+                                                                 GValue                 *value,
+                                                                 GParamSpec             *pspec);
+static void           thunar_application_set_property           (GObject                *object,
+                                                                 guint                   prop_id,
+                                                                 const GValue           *value,
+                                                                 GParamSpec             *pspec);
+static void           thunar_application_collect_and_launch     (ThunarApplication      *application,
+                                                                 gpointer                parent,
+                                                                 const gchar            *icon_name,
+                                                                 const gchar            *title,
+                                                                 Launcher                launcher,
+                                                                 GList                  *source_file_list,
+                                                                 GFile                  *target_file,
+                                                                 GClosure               *new_files_closure);
+static void           thunar_application_launch                 (ThunarApplication      *application,
+                                                                 gpointer                parent,
+                                                                 const gchar            *icon_name,
+                                                                 const gchar            *title,
+                                                                 Launcher                launcher,
+                                                                 GList                  *source_path_list,
+                                                                 GList                  *target_path_list,
+                                                                 GClosure               *new_files_closure);
+static GtkWidget     *thunar_application_open_window_with_role  (ThunarApplication      *application,
+                                                                 const gchar            *role,
+                                                                 ThunarFile             *directory,
+                                                                 GdkScreen              *screen);
+static void           thunar_application_window_destroyed       (GtkWidget              *window,
+                                                                 ThunarApplication      *application);
+static void           thunar_application_drive_connected        (GVolumeMonitor         *volume_monitor,
+                                                                 GDrive                 *drive,
+                                                                 ThunarApplication      *application);
+static void           thunar_application_drive_disconnected     (GVolumeMonitor         *volume_monitor,
+                                                                 GDrive                 *drive,
+                                                                 ThunarApplication      *application);
+static void           thunar_application_drive_eject            (GVolumeMonitor         *volume_monitor,
+                                                                 GDrive                 *drive,
+                                                                 ThunarApplication      *application);
+static gboolean       thunar_application_volman_idle            (gpointer                user_data);
+static void           thunar_application_volman_idle_destroy    (gpointer                user_data);
+static void           thunar_application_volman_watch           (GPid                    pid,
+                                                                 gint                    status,
+                                                                 gpointer                user_data);
+static void           thunar_application_volman_watch_destroy   (gpointer                user_data);
+static gboolean       thunar_application_show_dialogs           (gpointer                user_data);
+static void           thunar_application_show_dialogs_destroy   (gpointer                user_data);
+static void           thunar_application_process_files          (ThunarApplication      *application);
 
 
 
@@ -138,11 +139,14 @@
   GSList                *volman_udis;
   guint                  volman_idle_id;
   guint                  volman_watch_id;
+
+  GList                 *files_to_launch;
 };
 
 
 
 static GObjectClass *thunar_application_parent_class;
+static GQuark        thunar_application_screen_quark;
 
 
 
@@ -180,6 +184,10 @@
 {
   GObjectClass *gobject_class;
  
+  /* pre-allocate the required quarks */
+  thunar_application_screen_quark = 
+    g_quark_from_static_string ("thunar-application-screen");
+
   /* determine the parent type class */
   thunar_application_parent_class = g_type_class_peek_parent (klass);
 
@@ -215,6 +223,8 @@
   /* initialize the application */
   application->preferences = thunar_preferences_get ();
 
+  application->files_to_launch = NULL;
+
   /* check if we have a saved accel map */
   path = xfce_resource_lookup (XFCE_RESOURCE_CONFIG, "Thunar/accels.scm");
   if (G_LIKELY (path != NULL))
@@ -242,6 +252,9 @@
   gchar             *path;
   GList             *lp;
 
+  /* unqueue all files waiting to be processed */
+  thunar_file_list_free (application->files_to_launch);
+
   /* save the current accel map */
   path = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "Thunar/accels.scm", TRUE);
   if (G_LIKELY (path != NULL))
@@ -1040,6 +1053,107 @@
 
 
 
+static void
+thunar_application_process_files_finish (GObject      *object,
+                                         GAsyncResult *result,
+                                         gpointer      user_data)
+{ 
+  ThunarApplication *application = THUNAR_APPLICATION (user_data);
+  ThunarFile        *file;
+  GdkScreen         *screen;
+  GError            *error = NULL;
+
+  _thunar_return_if_fail (G_IS_FILE (object));
+  _thunar_return_if_fail (G_IS_ASYNC_RESULT (result));
+  _thunar_return_if_fail (THUNAR_IS_APPLICATION (application));
+  _thunar_return_if_fail (application->files_to_launch != NULL);
+  _thunar_return_if_fail (THUNAR_IS_FILE (application->files_to_launch->data));
+
+  /* finish mounting the volume */
+  if (!g_file_mount_enclosing_volume_finish (G_FILE (object), result, &error))
+    {
+      /* ignore already mounted and not supported errors */
+      if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_ALREADY_MOUNTED)
+        g_clear_error (&error);
+      else if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_NOT_SUPPORTED)
+        g_clear_error (&error);
+    }
+
+  /* get the current file */
+  file = THUNAR_FILE (application->files_to_launch->data);
+
+  /* determine and reset the screen of the file */
+  screen = g_object_get_qdata (G_OBJECT (file), thunar_application_screen_quark);
+  g_object_set_qdata (G_OBJECT (file), thunar_application_screen_quark, NULL);
+
+  /* check if mounting succeeded */
+  if (error == NULL)
+    {
+      /* try to open the file or directory */
+      thunar_file_launch (file, screen, &error);
+    }
+
+  if (error != NULL)
+    {
+      /* tell the user that we were unable to launch the file specified */
+      thunar_dialogs_show_error (screen, error, _("Failed to open \"%s\""), 
+                                 thunar_file_get_display_name (file));
+
+      /* stop processing files */
+      thunar_file_list_free (application->files_to_launch);
+      application->files_to_launch = NULL;
+    }
+  else
+    {
+      /* release the file */
+      g_object_unref (file);
+
+      /* remove the file item from the list */
+      application->files_to_launch = g_list_delete_link (application->files_to_launch, 
+                                                         application->files_to_launch);
+
+      /* continue processing the next file */
+      thunar_application_process_files (application);
+    }
+}
+
+
+
+static void
+thunar_application_process_files (ThunarApplication *application)
+{
+  GMountOperation *mount_operation;
+  ThunarFile      *file;
+  GdkScreen       *screen;
+  GFile           *location;
+
+  _thunar_return_if_fail (THUNAR_IS_APPLICATION (application));
+  
+  /* don't do anything if no files are to be processed */
+  if (application->files_to_launch == NULL)
+    return;
+
+  /* get the next file */
+  file = THUNAR_FILE (application->files_to_launch->data);
+
+  /* create a GTK+ mount operation */
+  mount_operation = gtk_mount_operation_new (NULL);
+  screen = g_object_get_qdata (G_OBJECT (file), thunar_application_screen_quark);
+  gtk_mount_operation_set_screen (GTK_MOUNT_OPERATION (mount_operation), screen);
+
+  /* determine the location of the file */
+  location = thunar_file_get_file (file);
+
+  /* try to mount the enclosing volume asynchronously. Thunar will launch files
+   * that are accessible in the mount callback */
+  g_file_mount_enclosing_volume (location, G_MOUNT_MOUNT_NONE,
+                                 mount_operation, NULL,
+                                 thunar_application_process_files_finish,
+                                 application);
+}
+
+
+
 /**
  * thunar_application_process_filenames:
  * @application       : a #ThunarApplication.
@@ -1096,37 +1210,53 @@
 
       /* verify that we have a valid file */
       if (G_LIKELY (file != NULL))
-        file_list = g_list_append (file_list, file);
+        {
+          file_list = g_list_append (file_list, file);
+        }
       else
-        goto failure;
+        {
+          /* tell the user that we were unable to launch the file specified */
+          thunar_dialogs_show_error (screen, derror, _("Failed to open \"%s\""), 
+                                     filenames[n]);
+
+          g_set_error (error, derror->domain, derror->code, 
+                       _("Failed to open \"%s\": %s"), filenames[n], derror->message);
+          g_error_free (derror);
+
+          thunar_file_list_free (file_list);
+
+          return FALSE;
+        }
     }
 
-  /* ok, let's try to launch the given files then */
+  /* loop over all files */
   for (lp = file_list; lp != NULL; lp = lp->next)
     {
-      /* try to launch this file, display an error dialog if that fails */
-      if (!thunar_file_launch (lp->data, screen, &derror))
-        {
-          /* tell the user that we were unable to launch the file specified on the cmdline */
-          thunar_dialogs_show_error (screen, derror, _("Failed to open \"%s\""), thunar_file_get_display_name (lp->data));
-          g_error_free (derror);
-          break;
-        }
+      /* remember the screen to launch the file on */
+      g_object_set_qdata (G_OBJECT (lp->data), thunar_application_screen_quark, screen);
+
+      /* append the file to the list of files we need to launch */
+      application->files_to_launch = g_list_append (application->files_to_launch, 
+                                                    lp->data);
     }
 
-  /* release all files */
-  thunar_file_list_free (file_list);
+  /* start processing files if we have any to launch */
+  if (application->files_to_launch != NULL)
+    thunar_application_process_files (application);
 
+  /* free the file list */
+  g_list_free (file_list);
+
   return TRUE;
+}
 
-failure:
-  /* tell the user that we were unable to launch the file specified on the cmdline */
-  thunar_dialogs_show_error (screen, derror, _("Failed to open \"%s\""), filenames[n]);
 
-  g_set_error (error, derror->domain, derror->code, _("Failed to open \"%s\": %s"), filenames[n], derror->message);
-  thunar_file_list_free (file_list);
-  g_error_free (derror);
-  return FALSE;
+
+gboolean
+thunar_application_is_processing (ThunarApplication *application)
+{
+  _thunar_return_val_if_fail (THUNAR_IS_APPLICATION (application), FALSE);
+  return application->files_to_launch != NULL;
 }
 
 

Modified: thunar/branches/migration-to-gio/thunar/thunar-application.h
===================================================================
--- thunar/branches/migration-to-gio/thunar/thunar-application.h	2009-06-16 19:34:50 UTC (rev 30036)
+++ thunar/branches/migration-to-gio/thunar/thunar-application.h	2009-06-16 23:28:53 UTC (rev 30037)
@@ -68,6 +68,8 @@
                                                          GdkScreen         *screen,
                                                          GError           **error);
 
+gboolean           thunar_application_is_processing     (ThunarApplication *application);
+
 void               thunar_application_copy_to           (ThunarApplication *application,
                                                          gpointer           parent,
                                                          GList             *source_file_list,




More information about the Xfce4-commits mailing list