From 02a7ab821520e0f33474e10415c488cdc44bb59d Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Sat, 8 Mar 2008 16:18:53 +0000 Subject: Do not run multiple instances of empathy. Fixes bug #501805 (Marco Barisione). svn path=/trunk/; revision=711 --- src/empathy.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) (limited to 'src/empathy.c') diff --git a/src/empathy.c b/src/empathy.c index e16aaf165..863d307f2 100644 --- a/src/empathy.c +++ b/src/empathy.c @@ -23,10 +23,12 @@ #include #include +#include #include #include #include +#include #include #include @@ -45,8 +47,12 @@ #include #include +#include "bacon-message-connection.h" + #define DEBUG_DOMAIN "EmpathyMain" +static BaconMessageConnection *connection = NULL; + static void service_ended_cb (MissionControl *mc, gpointer user_data) @@ -184,9 +190,87 @@ create_salut_account (void) g_object_unref (book); } +/* The code that handles single-instance and startup notification is + * copied from gedit. + * + * Copyright (C) 2005 - Paolo Maggi + */ +static void +on_bacon_message_received (const char *message, + gpointer data) +{ + GtkWidget *window = data; + guint32 startup_timestamp; + + g_return_if_fail (message != NULL); + + empathy_debug (DEBUG_DOMAIN, + "Other instance launched, presenting the main window " + "(message is '%s')", message); + + startup_timestamp = atoi (message); + + /* Set the proper interaction time on the window. + * Fall back to roundtripping to the X server when we + * don't have the timestamp, e.g. when launched from + * terminal. We also need to make sure that the window + * has been realized otherwise it will not work. lame. */ + if (startup_timestamp == 0) { + /* Work if launched from the terminal */ + empathy_debug (DEBUG_DOMAIN, "Using X server timestamp as a fallback"); + + if (!GTK_WIDGET_REALIZED (window)) { + gtk_widget_realize (GTK_WIDGET (window)); + } + + startup_timestamp = gdk_x11_get_server_time (window->window); + } + + gtk_window_present_with_time (GTK_WINDOW (window), startup_timestamp); +} + +static guint32 +get_startup_timestamp () +{ + const gchar *startup_id_env; + gchar *startup_id = NULL; + gchar *time_str; + gchar *end; + gulong retval = 0; + + /* we don't unset the env, since startup-notification + * may still need it */ + startup_id_env = g_getenv ("DESKTOP_STARTUP_ID"); + if (startup_id_env == NULL) { + goto out; + } + + startup_id = g_strdup (startup_id_env); + + time_str = g_strrstr (startup_id, "_TIME"); + if (time_str == NULL) { + goto out; + } + + errno = 0; + + /* Skip past the "_TIME" part */ + time_str += 5; + + retval = strtoul (time_str, &end, 0); + if (end == time_str || errno != 0) + retval = 0; + + out: + g_free (startup_id); + + return (retval > 0) ? retval : 0; +} + int main (int argc, char *argv[]) { + guint32 startup_timestamp; EmpathyStatusIcon *icon; GtkWidget *window; MissionControl *mc; @@ -201,6 +285,8 @@ main (int argc, char *argv[]) bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); + startup_timestamp = get_startup_timestamp (); + if (!gtk_init_with_args (&argc, &argv, _("- Empathy Instant Messenger"), NULL, GETTEXT_PACKAGE, &error)) { @@ -215,6 +301,31 @@ main (int argc, char *argv[]) PKGDATADIR G_DIR_SEPARATOR_S "icons"); gnome_vfs_init (); + /* Setting up the bacon connection */ + connection = bacon_message_connection_new ("empathy"); + if (connection != NULL) { + if (!bacon_message_connection_get_is_server (connection)) { + gchar *message; + + empathy_debug (DEBUG_DOMAIN, "Activating existing instance"); + + message = g_strdup_printf ("%" G_GUINT32_FORMAT, + startup_timestamp); + bacon_message_connection_send (connection, message); + + /* We never popup a window, so tell startup-notification + * that we are done. */ + gdk_notify_startup_complete (); + + g_free (message); + bacon_message_connection_free (connection); + + return EXIT_SUCCESS; + } + } else { + g_warning ("Cannot create the 'empathy' bacon connection."); + } + /* Setting up MC */ monitor = mc_account_monitor_new (); mc = empathy_mission_control_new (); @@ -243,6 +354,13 @@ main (int argc, char *argv[]) window = empathy_main_window_show (); icon = empathy_status_icon_new (GTK_WINDOW (window)); + if (connection) { + /* We se the callback here because we need window */ + bacon_message_connection_set_callback (connection, + on_bacon_message_received, + window); + } + gtk_main (); empathy_idle_set_state (idle, MC_PRESENCE_OFFLINE); -- cgit v1.2.3