[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