diff options
author | Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> | 2009-08-01 21:12:42 +0800 |
---|---|---|
committer | Cosimo Cecchi <cosimo.cecchi@collabora.co.uk> | 2009-08-01 21:12:42 +0800 |
commit | 9f9890593181c881b09773d7f8e68a402d8ce7fa (patch) | |
tree | 7c23eb29fefe01a58cc0f716070ed20841e1218e | |
parent | af5cee20d84c3ef3ebf31f7e19b4108f9607aa14 (diff) | |
download | gsoc2013-empathy-9f9890593181c881b09773d7f8e68a402d8ce7fa.tar gsoc2013-empathy-9f9890593181c881b09773d7f8e68a402d8ce7fa.tar.gz gsoc2013-empathy-9f9890593181c881b09773d7f8e68a402d8ce7fa.tar.bz2 gsoc2013-empathy-9f9890593181c881b09773d7f8e68a402d8ce7fa.tar.lz gsoc2013-empathy-9f9890593181c881b09773d7f8e68a402d8ce7fa.tar.xz gsoc2013-empathy-9f9890593181c881b09773d7f8e68a402d8ce7fa.tar.zst gsoc2013-empathy-9f9890593181c881b09773d7f8e68a402d8ce7fa.zip |
Port to libunique
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/bacon-message-connection.c | 412 | ||||
-rw-r--r-- | src/bacon-message-connection.h | 51 | ||||
-rw-r--r-- | src/empathy.c | 151 |
5 files changed, 38 insertions, 578 deletions
diff --git a/configure.ac b/configure.ac index 62e08f0a4..0e11a66d8 100644 --- a/configure.ac +++ b/configure.ac @@ -126,6 +126,7 @@ PKG_CHECK_MODULES(EMPATHY, telepathy-glib >= $TELEPATHY_GLIB_REQUIRED telepathy-farsight gstreamer-0.10 + unique-1.0 ]) PKG_CHECK_MODULES(LIBNOTIFY, libnotify >= $LIBNOTIFY_REQUIRED) diff --git a/src/Makefile.am b/src/Makefile.am index 50d317fbb..01f47d2bb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,7 +49,6 @@ empathy_handwritten_source = \ empathy_SOURCES = \ $(empathy_handwritten_source) \ - bacon-message-connection.c bacon-message-connection.h \ ephy-spinner.c ephy-spinner.h nodist_empathy_SOURCES = $(BUILT_SOURCES) diff --git a/src/bacon-message-connection.c b/src/bacon-message-connection.c deleted file mode 100644 index c9fda4aeb..000000000 --- a/src/bacon-message-connection.c +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright (C) 2003 Bastien Nocera <hadess@hadess.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Totem project hereby grant permission for non-gpl compatible GStreamer - * plugins to be used and distributed together with GStreamer and Totem. This - * permission are above and beyond the permissions granted by the GPL license - * Totem is covered by. - * - * Monday 7th February 2005: Christian Schaller: Add excemption clause. - * See license_change file for details. - * - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <errno.h> - -#include "bacon-message-connection.h" - -#ifndef UNIX_PATH_MAX -#define UNIX_PATH_MAX 108 -#endif - -struct BaconMessageConnection { - /* A server accepts connections */ - gboolean is_server; - - /* The socket path itself */ - char *path; - - /* File descriptor of the socket */ - int fd; - /* Channel to watch */ - GIOChannel *chan; - /* Event id returned by g_io_add_watch() */ - int conn_id; - - /* Connections accepted by this connection */ - GSList *accepted_connections; - - /* callback */ - void (*func) (const char *message, gpointer user_data); - gpointer data; -}; - -static gboolean -test_is_socket (const char *path) -{ - struct stat s; - - if (stat (path, &s) == -1) - return FALSE; - - if (S_ISSOCK (s.st_mode)) - return TRUE; - - return FALSE; -} - -static gboolean -is_owned_by_user_and_socket (const char *path) -{ - struct stat s; - - if (stat (path, &s) == -1) - return FALSE; - - if (s.st_uid != geteuid ()) - return FALSE; - - if ((s.st_mode & S_IFSOCK) != S_IFSOCK) - return FALSE; - - return TRUE; -} - -static gboolean server_cb (GIOChannel *source, - GIOCondition condition, gpointer data); - -static gboolean -setup_connection (BaconMessageConnection *conn) -{ - int fdflags; - - g_return_val_if_fail (conn->chan == NULL, FALSE); - - /* Add CLOEXEC flag on the fd to make sure the socket get closed - * if exec is called. */ - fdflags = fcntl (conn->fd, F_GETFD, 0); - if (fdflags >= 0) { - fdflags |= FD_CLOEXEC; - fcntl (conn->fd, F_SETFD, fdflags); - } - - conn->chan = g_io_channel_unix_new (conn->fd); - if (!conn->chan) { - return FALSE; - } - g_io_channel_set_line_term (conn->chan, "\n", 1); - conn->conn_id = g_io_add_watch (conn->chan, G_IO_IN, server_cb, conn); - - return TRUE; -} - -static void -accept_new_connection (BaconMessageConnection *server_conn) -{ - BaconMessageConnection *conn; - int alen; - - g_return_if_fail (server_conn->is_server); - - conn = g_new0 (BaconMessageConnection, 1); - conn->is_server = FALSE; - conn->func = server_conn->func; - conn->data = server_conn->data; - - conn->fd = accept (server_conn->fd, NULL, (guint *)&alen); - - server_conn->accepted_connections = - g_slist_prepend (server_conn->accepted_connections, conn); - - setup_connection (conn); -} - -static gboolean -server_cb (GIOChannel *source, GIOCondition condition, gpointer data) -{ - BaconMessageConnection *conn = (BaconMessageConnection *)data; - char *message, *subs, buf; - int cd, rc, offset; - gboolean finished; - - offset = 0; - if (conn->is_server && conn->fd == g_io_channel_unix_get_fd (source)) { - accept_new_connection (conn); - return TRUE; - } - message = g_malloc (1); - cd = conn->fd; - rc = read (cd, &buf, 1); - while (rc > 0 && buf != '\n') - { - message = g_realloc (message, rc + offset + 1); - message[offset] = buf; - offset = offset + rc; - rc = read (cd, &buf, 1); - } - if (rc <= 0) { - g_io_channel_shutdown (conn->chan, FALSE, NULL); - g_io_channel_unref (conn->chan); - conn->chan = NULL; - close (conn->fd); - conn->fd = -1; - g_free (message); - conn->conn_id = 0; - - return FALSE; - } - message[offset] = '\0'; - - subs = message; - finished = FALSE; - - while (finished == FALSE && *subs != '\0') - { - if (conn->func != NULL) - (*conn->func) (subs, conn->data); - - subs += strlen (subs) + 1; - if (subs - message >= offset) - finished = TRUE; - } - - g_free (message); - - return TRUE; -} - -static char * -find_file_with_pattern (const char *dir, const char *pattern) -{ - GDir *filedir; - char *found_filename; - const char *filename; - GPatternSpec *pat; - - filedir = g_dir_open (dir, 0, NULL); - if (filedir == NULL) - return NULL; - - pat = g_pattern_spec_new (pattern); - if (pat == NULL) - { - g_dir_close (filedir); - return NULL; - } - - found_filename = NULL; - - while ((filename = g_dir_read_name (filedir))) - { - if (g_pattern_match_string (pat, filename)) - { - char *tmp = g_build_filename (dir, filename, NULL); - if (is_owned_by_user_and_socket (tmp)) - found_filename = g_strdup (filename); - g_free (tmp); - } - - if (found_filename != NULL) - break; - } - - g_pattern_spec_free (pat); - g_dir_close (filedir); - - return found_filename; -} - -static char * -socket_filename (const char *prefix) -{ - char *pattern, *newfile, *path, *filename; - const char *tmpdir; - - pattern = g_strdup_printf ("%s.%s.*", prefix, g_get_user_name ()); - tmpdir = g_get_tmp_dir (); - filename = find_file_with_pattern (tmpdir, pattern); - if (filename == NULL) - { - newfile = g_strdup_printf ("%s.%s.%u", prefix, - g_get_user_name (), g_random_int ()); - path = g_build_filename (tmpdir, newfile, NULL); - g_free (newfile); - } else { - path = g_build_filename (tmpdir, filename, NULL); - g_free (filename); - } - - g_free (pattern); - return path; -} - -static gboolean -try_server (BaconMessageConnection *conn) -{ - struct sockaddr_un uaddr; - - uaddr.sun_family = AF_UNIX; - strncpy (uaddr.sun_path, conn->path, - MIN (strlen(conn->path)+1, UNIX_PATH_MAX)); - conn->fd = socket (PF_UNIX, SOCK_STREAM, 0); - if (bind (conn->fd, (struct sockaddr *) &uaddr, sizeof (uaddr)) == -1) - { - conn->fd = -1; - return FALSE; - } - listen (conn->fd, 5); - - return setup_connection (conn); -} - -static gboolean -try_client (BaconMessageConnection *conn) -{ - struct sockaddr_un uaddr; - - uaddr.sun_family = AF_UNIX; - strncpy (uaddr.sun_path, conn->path, - MIN(strlen(conn->path)+1, UNIX_PATH_MAX)); - conn->fd = socket (PF_UNIX, SOCK_STREAM, 0); - if (connect (conn->fd, (struct sockaddr *) &uaddr, - sizeof (uaddr)) == -1) - { - conn->fd = -1; - return FALSE; - } - - return setup_connection (conn); -} - -BaconMessageConnection * -bacon_message_connection_new (const char *prefix) -{ - BaconMessageConnection *conn; - - g_return_val_if_fail (prefix != NULL, NULL); - - conn = g_new0 (BaconMessageConnection, 1); - conn->path = socket_filename (prefix); - - if (test_is_socket (conn->path) == FALSE) - { - if (!try_server (conn)) - { - bacon_message_connection_free (conn); - return NULL; - } - - conn->is_server = TRUE; - return conn; - } - - if (try_client (conn) == FALSE) - { - unlink (conn->path); - try_server (conn); - if (conn->fd == -1) - { - bacon_message_connection_free (conn); - return NULL; - } - - conn->is_server = TRUE; - return conn; - } - - conn->is_server = FALSE; - return conn; -} - -void -bacon_message_connection_free (BaconMessageConnection *conn) -{ - GSList *child_conn; - - g_return_if_fail (conn != NULL); - /* Only servers can accept other connections */ - g_return_if_fail (conn->is_server != FALSE || - conn->accepted_connections == NULL); - - child_conn = conn->accepted_connections; - while (child_conn != NULL) { - bacon_message_connection_free (child_conn->data); - child_conn = g_slist_next (child_conn); - } - g_slist_free (conn->accepted_connections); - - if (conn->conn_id) { - g_source_remove (conn->conn_id); - conn->conn_id = 0; - } - if (conn->chan) { - g_io_channel_shutdown (conn->chan, FALSE, NULL); - g_io_channel_unref (conn->chan); - } - - if (conn->is_server != FALSE) { - unlink (conn->path); - } - if (conn->fd != -1) { - close (conn->fd); - } - - g_free (conn->path); - g_free (conn); -} - -void -bacon_message_connection_set_callback (BaconMessageConnection *conn, - BaconMessageReceivedFunc func, - gpointer user_data) -{ - g_return_if_fail (conn != NULL); - - conn->func = func; - conn->data = user_data; -} - -void -bacon_message_connection_send (BaconMessageConnection *conn, - const char *message) -{ - g_return_if_fail (conn != NULL); - g_return_if_fail (message != NULL); - - g_io_channel_write_chars (conn->chan, message, strlen (message), - NULL, NULL); - g_io_channel_write_chars (conn->chan, "\n", 1, NULL, NULL); - g_io_channel_flush (conn->chan, NULL); -} - -gboolean -bacon_message_connection_get_is_server (BaconMessageConnection *conn) -{ - g_return_val_if_fail (conn != NULL, FALSE); - - return conn->is_server; -} - diff --git a/src/bacon-message-connection.h b/src/bacon-message-connection.h deleted file mode 100644 index db4a91262..000000000 --- a/src/bacon-message-connection.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2003 Bastien Nocera <hadess@hadess.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Totem project hereby grant permission for non-gpl compatible GStreamer - * plugins to be used and distributed together with GStreamer and Totem. This - * permission are above and beyond the permissions granted by the GPL license - * Totem is covered by. - * - * Monday 7th February 2005: Christian Schaller: Add excemption clause. - * See license_change file for details. - * - */ - -#ifndef BACON_MESSAGE_CONNECTION_H -#define BACON_MESSAGE_CONNECTION_H - -#include <glib.h> - -G_BEGIN_DECLS - -typedef void (*BaconMessageReceivedFunc) (const char *message, - gpointer user_data); - -typedef struct BaconMessageConnection BaconMessageConnection; - -BaconMessageConnection *bacon_message_connection_new (const char *prefix); -void bacon_message_connection_free (BaconMessageConnection *conn); -void bacon_message_connection_set_callback (BaconMessageConnection *conn, - BaconMessageReceivedFunc func, - gpointer user_data); -void bacon_message_connection_send (BaconMessageConnection *conn, - const char *message); -gboolean bacon_message_connection_get_is_server (BaconMessageConnection *conn); - -G_END_DECLS - -#endif /* BACON_MESSAGE_CONNECTION_H */ diff --git a/src/empathy.c b/src/empathy.c index 637470773..3cc494a94 100644 --- a/src/empathy.c +++ b/src/empathy.c @@ -30,6 +30,7 @@ #include <glib/gi18n.h> #include <gtk/gtk.h> #include <gdk/gdkx.h> +#include <unique/unique.h> #if HAVE_LIBCHAMPLAIN #include <clutter-gtk/gtk-clutter-embed.h> @@ -68,7 +69,6 @@ #include "empathy-call-window.h" #include "empathy-chat-window.h" #include "empathy-ft-manager.h" -#include "bacon-message-connection.h" #include "extensions/extensions.h" @@ -77,7 +77,7 @@ #include <gst/gst.h> -static BaconMessageConnection *connection = NULL; +#define COMMAND_ACCOUNTS_DIALOG 1 static void dispatch_cb (EmpathyDispatcher *dispatcher, @@ -403,85 +403,29 @@ migrate_config_to_xdg_dir (void) g_free (old_dir); } -/* 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) +static UniqueResponse +unique_app_message_cb (UniqueApp *unique_app, + gint command, + UniqueMessageData *data, + guint timestamp, + gpointer user_data) { - GtkWidget *window = data; - guint32 startup_timestamp; - - g_return_if_fail (message != NULL); + GtkWidget *window = user_data; - DEBUG ("Other instance launched, presenting the main window. message='%s'", - message); + DEBUG ("Other instance launched, presenting the main window. " + "Command=%d, timestamp %u", command, timestamp); - if (strcmp (message, "accounts") == 0) { - /* accounts dialog requested */ + if (command == COMMAND_ACCOUNTS_DIALOG) { empathy_accounts_dialog_show (GTK_WINDOW (window), NULL); } else { - 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 */ - DEBUG ("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 (gtk_widget_get_window (window)); - } - - gtk_window_present_with_time (GTK_WINDOW (window), startup_timestamp); + gtk_window_set_screen (GTK_WINDOW (window), + unique_message_data_get_screen (data)); + gtk_window_set_startup_id (GTK_WINDOW (window), + unique_message_data_get_startup_id (data)); + gtk_window_present_with_time (GTK_WINDOW (window), 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; + return UNIQUE_RESPONSE_OK; } static gboolean @@ -579,7 +523,6 @@ account_manager_ready_cb (EmpathyAccountManager *manager, int main (int argc, char *argv[]) { - guint32 startup_timestamp; #if HAVE_GEOCLUE EmpathyLocationManager *location_manager = NULL; #endif @@ -598,6 +541,7 @@ main (int argc, char *argv[]) gboolean accounts_dialog = FALSE; GError *error = NULL; TpDBusDaemon *dbus_daemon; + UniqueApp *unique_app; GOptionEntry options[] = { { "no-connect", 'n', 0, G_OPTION_ARG_NONE, &no_connect, @@ -645,39 +589,20 @@ main (int argc, char *argv[]) g_log_set_default_handler (default_log_handler, NULL); #endif - /* Setting up the bacon connection */ - startup_timestamp = get_startup_timestamp (); - connection = bacon_message_connection_new ("empathy"); - if (connection != NULL) { - if (!bacon_message_connection_get_is_server (connection)) { - gchar *message; - - if (accounts_dialog) { - DEBUG ("Showing accounts dialog from existing Empathy instance"); - - message = g_strdup ("accounts"); - - } else { - - DEBUG ("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."); + unique_app = unique_app_new_with_commands ("org.gnome.Empathy", + NULL, + "accounts_dialog", + COMMAND_ACCOUNTS_DIALOG, + NULL); + + if (unique_app_is_running (unique_app)) { + unique_app_send_message (unique_app, + accounts_dialog ? + COMMAND_ACCOUNTS_DIALOG : + UNIQUE_ACTIVATE, + NULL); + g_object_unref (unique_app); + return EXIT_SUCCESS; } /* Take well-known name */ @@ -737,12 +662,9 @@ main (int argc, char *argv[]) window = empathy_main_window_show (); icon = empathy_status_icon_new (GTK_WINDOW (window), hide_contact_list); - if (connection) { - /* We se the callback here because we need window */ - bacon_message_connection_set_callback (connection, - on_bacon_message_received, - window); - } + g_signal_connect (unique_app, "message-received", + G_CALLBACK (unique_app_message_cb), + window); /* Handle channels */ dispatcher = empathy_dispatcher_dup_singleton (); @@ -786,6 +708,7 @@ main (int argc, char *argv[]) g_object_unref (location_manager); #endif g_object_unref (ft_factory); + g_object_unref (unique_app); notify_uninit (); |