diff options
Diffstat (limited to 'shell')
| -rw-r--r-- | shell/ev-daemon.c | 298 | 
1 files changed, 171 insertions, 127 deletions
diff --git a/shell/ev-daemon.c b/shell/ev-daemon.c index ea7f66ef..ae5f2bba 100644 --- a/shell/ev-daemon.c +++ b/shell/ev-daemon.c @@ -2,7 +2,7 @@   *  this file is part of atril, a mate document viewer   *   * Copyright (C) 2009 Carlos Garcia Campos  <[email protected]> - * Copyright © 2010 Christian Persch + * Copyright © 2010, 2012 Christian Persch   *   * Atril is free software; you can redistribute it and/or modify it   * under the terms of the GNU General Public License as published by @@ -43,9 +43,32 @@  #define LOG g_printerr -static GList *ev_daemon_docs = NULL; -static guint kill_timer_id; -static GHashTable *pending_invocations = NULL; + +#define EV_TYPE_DAEMON_APPLICATION              (ev_daemon_application_get_type ()) +#define EV_DAEMON_APPLICATION(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplication)) +#define EV_DAEMON_APPLICATION_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplicationClass)) +#define EV_IS_DAEMON_APPLICATION(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), EV_TYPE_DAEMON_APPLICATION)) +#define EV_IS_DAEMON_APPLICATION_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_DAEMON_APPLICATION)) +#define EV_DAEMON_APPLICATION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplicationClass)) + +typedef struct _EvDaemonApplication        EvDaemonApplication; +typedef struct _EvDaemonApplicationClass   EvDaemonApplicationClass; + +struct _EvDaemonApplicationClass { +        GApplicationClass parent_class; +}; + +struct _EvDaemonApplication +{ +        GApplication parent_instance; + +        EvDaemon   *daemon; +        GHashTable *pending_invocations; +        GList      *docs; +}; + +static GType ev_daemon_application_get_type (void); +G_DEFINE_TYPE (EvDaemonApplication, ev_daemon_application, G_TYPE_APPLICATION)  typedef struct {  	gchar *dbus_name; @@ -69,11 +92,12 @@ ev_doc_free (EvDoc *doc)  }  static EvDoc * -ev_daemon_find_doc (const gchar *uri) +ev_daemon_application_find_doc (EvDaemonApplication *application, +                                const gchar *uri)  {  	GList *l; -	for (l = ev_daemon_docs; l != NULL; l = l->next) { +	for (l = application->docs; l != NULL; l = l->next) {  		EvDoc *doc = (EvDoc *)l->data;  		if (strcmp (doc->uri, uri) == 0) @@ -83,39 +107,6 @@ ev_daemon_find_doc (const gchar *uri)  	return NULL;  } -static void -ev_daemon_stop_killtimer (void) -{ -	if (kill_timer_id != 0) -		g_source_remove (kill_timer_id); -	kill_timer_id = 0; -} - -static gboolean -ev_daemon_shutdown (gpointer user_data) -{ -        GMainLoop *loop = (GMainLoop *) user_data; - -        LOG ("Timeout; exiting daemon.\n"); - -        if (g_main_loop_is_running (loop)) -                g_main_loop_quit (loop); - -        return FALSE; -} - -static void -ev_daemon_maybe_start_killtimer (gpointer data) -{ -	ev_daemon_stop_killtimer (); -        if (ev_daemon_docs != NULL) -                return; - -	kill_timer_id = g_timeout_add_seconds (DAEMON_TIMEOUT, -                                               (GSourceFunc) ev_daemon_shutdown, -                                               data); -} -  static gboolean  spawn_atril (const gchar *uri)  { @@ -153,11 +144,12 @@ name_vanished_cb (GDBusConnection *connection,                    const gchar     *name,                    gpointer         user_data)  { +        EvDaemonApplication *application = EV_DAEMON_APPLICATION (user_data);  	GList *l;          LOG ("Watch name'%s' disappeared\n", name); -        for (l = ev_daemon_docs; l != NULL; l = l->next) { +        for (l = application->docs; l != NULL; l = l->next) {                  EvDoc *doc = (EvDoc *) l->data;                  if (strcmp (doc->dbus_name, name) != 0) @@ -165,23 +157,25 @@ name_vanished_cb (GDBusConnection *connection,                  LOG ("Watch found URI '%s' for name; removing\n", doc->uri); -                ev_daemon_docs = g_list_delete_link (ev_daemon_docs, l); +                application->docs = g_list_delete_link (application->docs, l);                  ev_doc_free (doc); -                ev_daemon_maybe_start_killtimer (user_data); +                g_application_release (G_APPLICATION (application)); +                  return;          }  }  static void -process_pending_invocations (const gchar *uri, -			     const gchar *dbus_name) +process_pending_invocations (EvDaemonApplication *application, +                             const gchar *uri, +                             const gchar *dbus_name)  {  	GList *l;  	GList *uri_invocations;  	LOG ("RegisterDocument process pending invocations for URI %s\n", uri); -	uri_invocations = g_hash_table_lookup (pending_invocations, uri); +	uri_invocations = g_hash_table_lookup (application->pending_invocations, uri);  	for (l = uri_invocations; l != NULL; l = l->next) {  		GDBusMethodInvocation *invocation; @@ -192,7 +186,7 @@ process_pending_invocations (const gchar *uri,  	}  	g_list_free (uri_invocations); -	g_hash_table_remove (pending_invocations, uri); +	g_hash_table_remove (application->pending_invocations, uri);  }  static void @@ -202,27 +196,33 @@ document_loaded_cb (GDBusConnection *connection,  		    const gchar     *interface_name,  		    const gchar     *signal_name,  		    GVariant        *parameters, -		    EvDoc           *doc) +		    gpointer         user_data)  { -	const gchar *uri; +        EvDaemonApplication *application = EV_DAEMON_APPLICATION (user_data); +        const gchar *uri; +        EvDoc *doc;  	g_variant_get (parameters, "(&s)", &uri); -	if (strcmp (uri, doc->uri) == 0) -		process_pending_invocations (uri, sender_name); +        doc = ev_daemon_application_find_doc (application, uri); +        if (doc != NULL && strcmp (uri, doc->uri) == 0) { +		process_pending_invocations (application, uri, sender_name); +        } +  	g_dbus_connection_signal_unsubscribe (connection, doc->loaded_id); +        doc->loaded_id = 0;  }  static gboolean -handle_register_document_cb (EvDaemon *object, +handle_register_document_cb (EvDaemon              *object,                               GDBusMethodInvocation *invocation, -                             const gchar *uri, -                             gpointer user_data) +                             const gchar           *uri, +                             EvDaemonApplication   *application)  {          GDBusConnection *connection;          const char *sender;          EvDoc       *doc; -        doc = ev_daemon_find_doc (uri); +        doc = ev_daemon_application_find_doc (application, uri);          if (doc != NULL) {                  LOG ("RegisterDocument found owner '%s' for URI '%s'\n", doc->dbus_name, uri);                  ev_daemon_complete_register_document (object, invocation, doc->dbus_name); @@ -230,15 +230,17 @@ handle_register_document_cb (EvDaemon *object,                  return TRUE;          } -        ev_daemon_stop_killtimer (); -          sender = g_dbus_method_invocation_get_sender (invocation);          connection = g_dbus_method_invocation_get_connection (invocation); +        LOG ("RegisterDocument registered owner '%s' for URI '%s'\n", sender, uri); +          doc = g_new (EvDoc, 1);          doc->dbus_name = g_strdup (sender);          doc->uri = g_strdup (uri); +        application->docs = g_list_prepend (application->docs, doc); +          doc->loaded_id = g_dbus_connection_signal_subscribe (connection,                                                               doc->dbus_name,                                                               EV_DBUS_WINDOW_INTERFACE_NAME, @@ -246,36 +248,34 @@ handle_register_document_cb (EvDaemon *object,                                                               NULL,                                                               NULL,                                                               0, -                                                             (GDBusSignalCallback) document_loaded_cb, -                                                             doc, -                                                             NULL); +                                                             document_loaded_cb, +                                                             application, NULL);          doc->watch_id = g_bus_watch_name_on_connection (connection,                                                          sender,                                                          G_BUS_NAME_WATCHER_FLAGS_NONE,                                                          name_appeared_cb,                                                          name_vanished_cb, -                                                        user_data, NULL); - -        LOG ("RegisterDocument registered owner '%s' for URI '%s'\n", doc->dbus_name, uri); -        ev_daemon_docs = g_list_prepend (ev_daemon_docs, doc); +                                                        application, NULL);          ev_daemon_complete_register_document (object, invocation, ""); +        g_application_hold (G_APPLICATION (application)); +          return TRUE;  }  static gboolean -handle_unregister_document_cb (EvDaemon *object, +handle_unregister_document_cb (EvDaemon              *object,                                 GDBusMethodInvocation *invocation, -                               const gchar *uri, -                               gpointer user_data) +                               const gchar           *uri, +                               EvDaemonApplication   *application)  {          EvDoc *doc;          const char *sender;          LOG ("UnregisterDocument URI '%s'\n", uri); -        doc = ev_daemon_find_doc (uri); +        doc = ev_daemon_application_find_doc (application, uri);          if (doc == NULL) {                  LOG ("UnregisterDocument URI was not registered!\n");                  g_dbus_method_invocation_return_error_literal (invocation, @@ -297,27 +297,35 @@ handle_unregister_document_cb (EvDaemon *object,                  return TRUE;          } -        ev_daemon_docs = g_list_remove (ev_daemon_docs, doc); +        application->docs = g_list_remove (application->docs, doc); + +        if (doc->loaded_id != 0) { +                g_dbus_connection_signal_unsubscribe (g_dbus_method_invocation_get_connection (invocation), +                                                      doc->loaded_id); +                doc->loaded_id = 0; +        } +          ev_doc_free (doc); -        ev_daemon_maybe_start_killtimer (user_data);          ev_daemon_complete_unregister_document (object, invocation); +        g_application_release (G_APPLICATION (application)); +          return TRUE;  }  static gboolean -handle_find_document_cb (EvDaemon *object, +handle_find_document_cb (EvDaemon              *object,                           GDBusMethodInvocation *invocation, -                         const gchar *uri, -                         gboolean spawn, -                         gpointer user_data) +                         const gchar           *uri, +                         gboolean               spawn, +                         EvDaemonApplication   *application)  {          EvDoc *doc;          LOG ("FindDocument URI '%s' \n", uri); -        doc = ev_daemon_find_doc (uri); +        doc = ev_daemon_application_find_doc (application, uri);          if (doc != NULL) {                  ev_daemon_complete_find_document (object, invocation, doc->dbus_name); @@ -328,7 +336,7 @@ handle_find_document_cb (EvDaemon *object,                  GList *uri_invocations;                  gboolean ret_val = TRUE; -                uri_invocations = g_hash_table_lookup (pending_invocations, uri); +                uri_invocations = g_hash_table_lookup (application->pending_invocations, uri);                  if (uri_invocations == NULL) {                          /* Only spawn once. */ @@ -338,7 +346,7 @@ handle_find_document_cb (EvDaemon *object,                  if (ret_val) {                          /* Only defer DBUS answer if atril was succesfully spawned */                          uri_invocations = g_list_prepend (uri_invocations, invocation); -                        g_hash_table_insert (pending_invocations, +                        g_hash_table_insert (application->pending_invocations,                                               g_strdup (uri),                                               uri_invocations);                          return TRUE; @@ -352,87 +360,123 @@ handle_find_document_cb (EvDaemon *object,          return TRUE;  } -static void -bus_acquired_cb (GDBusConnection *connection, -		 const gchar     *name, -		 gpointer         user_data) +/* ------------------------------------------------------------------------- */ + +static gboolean +ev_daemon_application_dbus_register (GApplication    *gapplication, +                                     GDBusConnection *connection, +                                     const gchar     *object_path, +                                     GError         **error)  { -	GMainLoop *loop = (GMainLoop *) user_data; +        EvDaemonApplication *application = EV_DAEMON_APPLICATION (gapplication);          EvDaemon *skeleton; -	GError    *error = NULL; + +        if (!G_APPLICATION_CLASS (ev_daemon_application_parent_class)->dbus_register (gapplication, +                                                                                      connection, +                                                                                      object_path, +                                                                                      error)) +                return FALSE;          skeleton = ev_daemon_skeleton_new ();          if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),                                                 connection,                                                 EV_DBUS_DAEMON_OBJECT_PATH, -                                               &error)) { -                g_printerr ("Failed to export object: %s\n", error->message); -		g_error_free (error); - -		if (g_main_loop_is_running (loop)) -			g_main_loop_quit (loop); -	} +                                               error)) { +                g_object_unref (skeleton); +                return FALSE; +        } +  +        application->daemon = skeleton;          g_signal_connect (skeleton, "handle-register-document", -                          G_CALLBACK (handle_register_document_cb), loop); +                          G_CALLBACK (handle_register_document_cb), application);          g_signal_connect (skeleton, "handle-unregister-document", -                          G_CALLBACK (handle_unregister_document_cb), loop); +                          G_CALLBACK (handle_unregister_document_cb), application);          g_signal_connect (skeleton, "handle-find-document", -                          G_CALLBACK (handle_find_document_cb), loop); +                          G_CALLBACK (handle_find_document_cb), application); +        return TRUE;  }  static void -name_acquired_cb (GDBusConnection *connection, -                  const gchar     *name, -                  gpointer         user_data) +ev_daemon_application_dbus_unregister (GApplication    *gapplication, +                                       GDBusConnection *connection, +                                       const gchar     *object_path) +{ +        EvDaemonApplication *application = EV_DAEMON_APPLICATION (gapplication); + +        if (application->daemon) { +                g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (application->daemon)); +                g_object_unref (application->daemon); +                application->daemon = NULL; +        } + +        G_APPLICATION_CLASS (ev_daemon_application_parent_class)->dbus_unregister (gapplication, +                                                                                   connection, +                                                                                   object_path); +} + +static void +ev_daemon_application_init (EvDaemonApplication *application)  { -	ev_daemon_maybe_start_killtimer (user_data); +        application->pending_invocations = g_hash_table_new_full (g_str_hash, +                                                                  g_str_equal, +                                                                  (GDestroyNotify) g_free, +                                                                  NULL);  }  static void -name_lost_cb (GDBusConnection *connection, -              const gchar     *name, -              gpointer         user_data) +ev_daemon_application_finalize (GObject *object)  { -          GMainLoop *loop = (GMainLoop *) user_data; +        EvDaemonApplication *application = EV_DAEMON_APPLICATION (object); -          /* Failed to acquire the name; exit daemon */ -          if (g_main_loop_is_running (loop)) -                  g_main_loop_quit (loop); +        g_warn_if_fail (g_hash_table_size (application->pending_invocations) == 0); +        g_hash_table_destroy (application->pending_invocations); + +        g_list_free_full (application->docs, (GDestroyNotify) ev_doc_free); + +        G_OBJECT_CLASS (ev_daemon_application_parent_class)->finalize (object);  } +static void +ev_daemon_application_class_init (EvDaemonApplicationClass *klass) +{ +        GObjectClass *object_class = G_OBJECT_CLASS (klass); +        GApplicationClass *g_application_class = G_APPLICATION_CLASS (klass); + +        object_class->finalize = ev_daemon_application_finalize; + +        g_application_class->dbus_register = ev_daemon_application_dbus_register; +        g_application_class->dbus_unregister = ev_daemon_application_dbus_unregister; +} + +/* ------------------------------------------------------------------------- */ +  gint  main (gint argc, gchar **argv)  { -	GMainLoop *loop; -        guint owner_id; +        GApplication *application; +        const GApplicationFlags flags = G_APPLICATION_IS_SERVICE; +        GError *error = NULL; +        int status;          g_set_prgname ("atril-daemon"); -	loop = g_main_loop_new (NULL, FALSE); - -	pending_invocations = g_hash_table_new_full (g_str_hash, -						     g_str_equal, -						     (GDestroyNotify)g_free, -						     NULL); +        application = g_object_new (EV_TYPE_DAEMON_APPLICATION, +                                    "application-id", EV_DBUS_DAEMON_NAME, +                                    "flags", flags, +                                    NULL); +        g_application_set_inactivity_timeout (application, DAEMON_TIMEOUT); -        owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, -				   EV_DBUS_DAEMON_NAME, -				   G_BUS_NAME_OWNER_FLAGS_NONE, -				   bus_acquired_cb, -				   name_acquired_cb, -				   name_lost_cb, -				   g_main_loop_ref (loop), -				   (GDestroyNotify) g_main_loop_unref); +        if (!g_application_register (application, NULL, &error)) { +                g_printerr ("Failed to register: %s\n", error->message); +                g_error_free (error); +                g_object_unref (application); -        g_main_loop_run (loop); - -        g_bus_unown_name (owner_id); +                return 1; +        } -        g_main_loop_unref (loop); -        g_list_foreach (ev_daemon_docs, (GFunc)ev_doc_free, NULL); -        g_list_free (ev_daemon_docs); -        g_hash_table_destroy (pending_invocations); +        status = g_application_run (application, 0, NULL); +        g_object_unref (application); -	return 0; +	return status;  }  | 
