# HG changeset patch # User Richard Laager # Date 1179686458 0 # Node ID 1e674c0886b11942c60f6af031031963e24b5474 # Parent 2c10f77c2378f533a5e7ad403a13324238778c77# Parent ddf759c28d0b349a1dc0a0ac6ff5946e8f1f8be1 propagate from branch 'im.pidgin.pidgin' (head b917cc2cf9c46c7163ad3345b312dac1eea896cf) to branch 'im.pidgin.rlaager.merging.for_2_1_0' (head 6d4701b6ce24327540b11d93b4e203334a042c6e) diff -r ddf759c28d0b -r 1e674c0886b1 ChangeLog --- a/ChangeLog Sun May 20 18:32:40 2007 +0000 +++ b/ChangeLog Sun May 20 18:40:58 2007 +0000 @@ -1,5 +1,18 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.1.0 (??/??/????): + libpurple: + * Core changes to allow UIs to use second-granularity for scheduling. + Pidgin and Finch, which use the glib event loop, were changed to use + g_timeout_add_seconds() on glib >= 2.14 when possible. This allows + glib to properly group our longer timers to increase power efficiency. + (Arjan van de Ven with Intel Corporation) + + Pidgin: + * Ensure only one copy of Pidgin is running with a given configuration + directory. The net effect of this is that trying to start Pidgin a + second time will raise the buddy list. (Gabriel Schulhof) + version 2.0.1 (??/??/????): * Buddy list update speedups when buddy icons are not being displayed. (Scott Wolchok) diff -r ddf759c28d0b -r 1e674c0886b1 ChangeLog.API --- a/ChangeLog.API Sun May 20 18:32:40 2007 +0000 +++ b/ChangeLog.API Sun May 20 18:40:58 2007 +0000 @@ -1,5 +1,19 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.1.0 (??/??/????): + Added: + * PurpleEventLoopUiOps.timeout_add_seconds + UIs can now use better scheduling for whole-second timers. For + example, clients based on the glib event loop can now use + g_timeout_add_seconds(). + * pidgin_create_window() + * purple_core_ensure_single_instance() + This is for UIs to use to ensure only one copy is running. + * purple_dbus_is_owner() + * purple_timeout_add_seconds() + Callers should prefer this to purple_timeout_add() for timers + longer than 1 second away. Be aware of the rounding, though. + version 2.0.0 (5/3/2007): Please note all functions, defines, and data structures have been re-namespaced to match the new names of Pidgin, Finch, and libpurple. diff -r ddf759c28d0b -r 1e674c0886b1 configure.ac --- a/configure.ac Sun May 20 18:32:40 2007 +0000 +++ b/configure.ac Sun May 20 18:40:58 2007 +0000 @@ -43,10 +43,10 @@ # # Make sure to update finch/libgnt/configure.ac with libgnt version changes. # -m4_define([purple_lt_current], [0]) +m4_define([purple_lt_current], [1]) m4_define([purple_major_version], [2]) -m4_define([purple_minor_version], [0]) -m4_define([purple_micro_version], [1]) +m4_define([purple_minor_version], [1]) +m4_define([purple_micro_version], [0]) m4_define([purple_version_suffix], [devel]) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) diff -r ddf759c28d0b -r 1e674c0886b1 finch/finch.c --- a/finch/finch.c Sun May 20 18:32:40 2007 +0000 +++ b/finch/finch.c Sun May 20 18:40:58 2007 +0000 @@ -156,11 +156,15 @@ gnt_input_add, g_source_remove, NULL, /* input_get_error */ +#if GLIB_CHECK_VERSION(2,14,0) + g_timeout_add_seconds, +#else + NULL, +#endif /* padding */ NULL, NULL, - NULL, NULL }; diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/account.c --- a/libpurple/account.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/account.c Sun May 20 18:40:58 2007 +0000 @@ -417,7 +417,7 @@ schedule_accounts_save() { if (save_timer == 0) - save_timer = purple_timeout_add(5000, save_cb, NULL); + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); } diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/blist.c --- a/libpurple/blist.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/blist.c Sun May 20 18:40:58 2007 +0000 @@ -365,7 +365,7 @@ purple_blist_schedule_save() { if (save_timer == 0) - save_timer = purple_timeout_add(5000, save_cb, NULL); + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); } diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/connection.c --- a/libpurple/connection.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/connection.c Sun May 20 18:40:58 2007 +0000 @@ -72,7 +72,7 @@ if (on && !gc->keepalive) { purple_debug_info("connection", "Activating keepalive.\n"); - gc->keepalive = purple_timeout_add(30000, send_keepalive, gc); + gc->keepalive = purple_timeout_add_seconds(30, send_keepalive, gc); } else if (!on && gc->keepalive > 0) { diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/conversation.c --- a/libpurple/conversation.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/conversation.c Sun May 20 18:40:58 2007 +0000 @@ -1010,7 +1010,7 @@ conv = purple_conv_im_get_conversation(im); name = purple_conversation_get_name(conv); - im->typing_timeout = purple_timeout_add(timeout * 1000, reset_typing_cb, conv); + im->typing_timeout = purple_timeout_add_seconds(timeout, reset_typing_cb, conv); } void diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/core.c --- a/libpurple/core.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/core.c Sun May 20 18:40:58 2007 +0000 @@ -48,7 +48,11 @@ #include "util.h" #ifdef HAVE_DBUS +# define DBUS_API_SUBJECT_TO_CHANGE +# include +# include "dbus-purple.h" # include "dbus-server.h" +# include "dbus-bindings.h" #endif struct PurpleCore @@ -276,6 +280,91 @@ return _ops; } +#ifdef HAVE_DBUS +static char *purple_dbus_owner_user_dir(void) +{ + DBusMessage *msg = NULL, *reply = NULL; + DBusConnection *dbus_connection = NULL; + DBusError dbus_error; + char *remote_user_dir = NULL; + + if ((dbus_connection = purple_dbus_get_connection()) == NULL) + return NULL; + + if ((msg = dbus_message_new_method_call(DBUS_SERVICE_PURPLE, DBUS_PATH_PURPLE, DBUS_INTERFACE_PURPLE, "PurpleUserDir")) == NULL) + return NULL; + + dbus_error_init(&dbus_error); + reply = dbus_connection_send_with_reply_and_block(dbus_connection, msg, 5000, &dbus_error); + dbus_message_unref(msg); + dbus_error_free(&dbus_error); + + if (reply) + { + dbus_error_init(&dbus_error); + dbus_message_get_args(reply, &dbus_error, DBUS_TYPE_STRING, &remote_user_dir, DBUS_TYPE_INVALID); + remote_user_dir = g_strdup(remote_user_dir); + dbus_error_free(&dbus_error); + dbus_message_unref(reply); + } + + return remote_user_dir; +} + +static void purple_dbus_owner_show_buddy_list(void) +{ + DBusError dbus_error; + DBusMessage *msg = NULL, *reply = NULL; + DBusConnection *dbus_connection = NULL; + + if ((dbus_connection = purple_dbus_get_connection()) == NULL) + return; + + if ((msg = dbus_message_new_method_call(DBUS_SERVICE_PURPLE, DBUS_PATH_PURPLE, DBUS_INTERFACE_PURPLE, "PurpleBlistShow")) == NULL) + return; + + dbus_error_init(&dbus_error); + if ((reply = dbus_connection_send_with_reply_and_block(dbus_connection, msg, 5000, &dbus_error)) != NULL) + { + dbus_message_unref(msg); + } + dbus_error_free(&dbus_error); +} +#endif /* HAVE_DBUS */ + +gboolean +purple_core_ensure_single_instance() +{ + gboolean is_single_instance = TRUE; +#ifdef HAVE_DBUS + /* in the future, other mechanisms might have already set this to FALSE */ + if (is_single_instance) + { + if (!purple_dbus_is_owner()) + { + const char *user_dir = purple_user_dir(); + char *dbus_owner_user_dir = purple_dbus_owner_user_dir(); + + if (NULL == user_dir && NULL != dbus_owner_user_dir) + is_single_instance = TRUE; + else if (NULL != user_dir && NULL == dbus_owner_user_dir) + is_single_instance = TRUE; + else if (NULL == user_dir && NULL == dbus_owner_user_dir) + is_single_instance = FALSE; + else + is_single_instance = strcmp(dbus_owner_user_dir, user_dir); + + if (!is_single_instance) + purple_dbus_owner_show_buddy_list(); + + g_free(dbus_owner_user_dir); + } + } +#endif /* HAVE_DBUS */ + + return is_single_instance; +} + static gboolean move_and_symlink_dir(const char *path, const char *basename, const char *old_base, const char *new_base, const char *relative) { diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/core.h --- a/libpurple/core.h Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/core.h Sun May 20 18:40:58 2007 +0000 @@ -121,6 +121,16 @@ */ gboolean purple_core_migrate(void); +/** + * Ensures that only one instance is running. + * + * @return A boolean such that @c TRUE indicates that this is the first instance, + * whereas @c FALSE indicates that there is another instance running. + * + * @since 2.1.0 + */ +gboolean purple_core_ensure_single_instance(void); + #ifdef __cplusplus } #endif diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/dbus-server.c --- a/libpurple/dbus-server.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/dbus-server.c Sun May 20 18:40:58 2007 +0000 @@ -65,6 +65,12 @@ static GHashTable *map_id_type; static gchar *init_error; +static int dbus_request_name_reply = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER; + +gboolean purple_dbus_is_owner(void) +{ + return(DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER == dbus_request_name_reply); +} /** * This function initializes the pointer-id traslation system. It @@ -592,6 +598,7 @@ return; } + dbus_request_name_reply = result = dbus_bus_request_name(purple_dbus_connection, DBUS_SERVICE_PURPLE, 0, &error); diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/dbus-server.h --- a/libpurple/dbus-server.h Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/dbus-server.h Sun May 20 18:40:58 2007 +0000 @@ -169,6 +169,13 @@ void *purple_dbus_get_handle(void); /** + * Determines whether this instance owns the DBus service name + * + * @since 2.1.0 + */ +gboolean purple_dbus_is_owner(void); + +/** * Starts Purple's D-BUS server. It is responsible for handling DBUS * requests from other applications. */ diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/eventloop.c --- a/libpurple/eventloop.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/eventloop.c Sun May 20 18:40:58 2007 +0000 @@ -35,6 +35,17 @@ return ops->timeout_add(interval, function, data); } +guint +purple_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data) +{ + PurpleEventLoopUiOps *ops = purple_eventloop_get_ui_ops(); + + if (ops->timeout_add_seconds) + return ops->timeout_add_seconds(interval, function, data); + else + return ops->timeout_add(1000 * interval, function, data); +} + gboolean purple_timeout_remove(guint tag) { diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/eventloop.h --- a/libpurple/eventloop.h Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/eventloop.h Sun May 20 18:40:58 2007 +0000 @@ -48,7 +48,7 @@ struct _PurpleEventLoopUiOps { /** - * Creates a callback timer. + * Creates a callback timer with an interval measured in milliseconds. * @see g_timeout_add, purple_timeout_add **/ guint (*timeout_add)(guint interval, GSourceFunc function, gpointer data); @@ -81,7 +81,20 @@ */ int (*input_get_error)(int fd, int *error); - void (*_purple_reserved1)(void); + /** + * Creates a callback timer with an interval measured in seconds. + * + * This allows UIs to group timers for better power efficiency. For + * this reason, @a interval may be rounded by up to a second. + * + * Implementation of this UI op is optional. If it's not implemented, + * calls to purple_timeout_add_seconds() will be serviced by the + * timeout_add UI op. + * + * @see g_timeout_add_seconds, purple_timeout_add_seconds() + **/ + guint (*timeout_add_seconds)(guint interval, GSourceFunc function, gpointer data); + void (*_purple_reserved2)(void); void (*_purple_reserved3)(void); void (*_purple_reserved4)(void); @@ -93,10 +106,15 @@ /*@{*/ /** * Creates a callback timer. + * * The timer will repeat until the function returns @c FALSE. The * first call will be at the end of the first interval. + * + * If the timer is in a multiple of seconds, use purple_timeout_add_seconds() + * instead as it allows UIs to group timers for power efficiency. + * * @param interval The time between calls of the function, in - * milliseconds. + * milliseconds. * @param function The function to call. * @param data data to pass to @a function. * @return A handle to the timer which can be passed to @@ -105,6 +123,24 @@ guint purple_timeout_add(guint interval, GSourceFunc function, gpointer data); /** + * Creates a callback timer. + * + * The timer will repeat until the function returns @c FALSE. The + * first call will be at the end of the first interval. + * + * This function allows UIs to group timers for better power efficiency. For + * this reason, @a interval may be rounded by up to a second. + * + * @param interval The time between calls of the function, in + * seconds. + * @param function The function to call. + * @param data data to pass to @a function. + * @return A handle to the timer which can be passed to + * purple_timeout_remove to remove the timer. + */ +guint purple_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data); + +/** * Removes a timeout handler. * * @param handle The handle, as returned by purple_timeout_add. diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/example/nullclient.c --- a/libpurple/example/nullclient.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/example/nullclient.c Sun May 20 18:40:58 2007 +0000 @@ -108,11 +108,15 @@ glib_input_add, g_source_remove, NULL, +#if GLIB_CHECK_VERSION(2,14,0) + g_timeout_add_seconds, +#else + NULL, +#endif /* padding */ NULL, NULL, - NULL, NULL }; /*** End of the eventloop functions. ***/ diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/idle.c --- a/libpurple/idle.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/idle.c Sun May 20 18:40:58 2007 +0000 @@ -230,7 +230,11 @@ if (time_until_next_idle_event == 0) idle_timer = 0; else - idle_timer = purple_timeout_add(1000 * (time_until_next_idle_event + 1), check_idleness_timer, NULL); + { + /* +1 for the boundary, + * +1 more for g_timeout_add_seconds rounding. */ + idle_timer = purple_timeout_add_seconds(time_until_next_idle_event + 2, check_idleness_timer, NULL); + } return FALSE; } @@ -309,8 +313,10 @@ void purple_idle_init() { - /* Add the timer to check if we're idle */ - idle_timer = purple_timeout_add(1000 * (IDLEMARK + 1), check_idleness_timer, NULL); + /* Add the timer to check if we're idle. + * IDLEMARK + 1 as the boundary, + * +1 more for g_timeout_add_seconds rounding. */ + idle_timer = purple_timeout_add_seconds((IDLEMARK + 2), check_idleness_timer, NULL); purple_signal_connect(purple_conversations_get_handle(), "sent-im-msg", purple_idle_get_handle(), diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/pounce.c --- a/libpurple/pounce.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/pounce.c Sun May 20 18:40:58 2007 +0000 @@ -273,7 +273,7 @@ schedule_pounces_save(void) { if (save_timer == 0) - save_timer = purple_timeout_add(5000, save_cb, NULL); + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); } diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/prefs.c --- a/libpurple/prefs.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/prefs.c Sun May 20 18:40:58 2007 +0000 @@ -226,7 +226,7 @@ schedule_prefs_save(void) { if (save_timer == 0) - save_timer = purple_timeout_add(5000, save_cb, NULL); + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); } diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/protocols/jabber/auth.c diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/savedstatuses.c --- a/libpurple/savedstatuses.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/savedstatuses.c Sun May 20 18:40:58 2007 +0000 @@ -357,7 +357,7 @@ schedule_save(void) { if (save_timer == 0) - save_timer = purple_timeout_add(5000, save_cb, NULL); + save_timer = purple_timeout_add_seconds(5, save_cb, NULL); } diff -r ddf759c28d0b -r 1e674c0886b1 libpurple/server.c --- a/libpurple/server.c Sun May 20 18:32:40 2007 +0000 +++ b/libpurple/server.c Sun May 20 18:40:58 2007 +0000 @@ -92,7 +92,7 @@ /* because we're modifying or creating a lar, schedule the * function to expire them as the pref dictates */ - purple_timeout_add((SECS_BEFORE_RESENDING_AUTORESPONSE + 1) * 1000, expire_last_auto_responses, NULL); + purple_timeout_add_seconds((SECS_BEFORE_RESENDING_AUTORESPONSE + 1), expire_last_auto_responses, NULL); tmp = last_auto_responses; diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkaccount.c --- a/pidgin/gtkaccount.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkaccount.c Sun May 20 18:40:58 2007 +0000 @@ -1447,17 +1447,8 @@ dialog->prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(dialog->plugin); - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(win), "account"); - - if (type == PIDGIN_ADD_ACCOUNT_DIALOG) - gtk_window_set_title(GTK_WINDOW(win), _("Add Account")); - else - gtk_window_set_title(GTK_WINDOW(win), _("Modify Account")); - - gtk_window_set_resizable(GTK_WINDOW(win), FALSE); - - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); + dialog->window = win = pidgin_create_window((type == PIDGIN_ADD_ACCOUNT_DIALOG) ? _("Add Account") : _("Modify Account"), + PIDGIN_HIG_BORDER, "account", FALSE); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(account_win_destroy_cb), dialog); @@ -2294,7 +2285,6 @@ GtkWidget *button; int width, height; - if (accounts_window != NULL) { gtk_window_present(GTK_WINDOW(accounts_window->window)); return; @@ -2305,11 +2295,8 @@ width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/accounts/dialog/width"); height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/accounts/dialog/height"); - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + dialog->window = win = pidgin_create_window(_("Accounts"), PIDGIN_HIG_BORDER, "accounts", TRUE); gtk_window_set_default_size(GTK_WINDOW(win), width, height); - gtk_window_set_role(GTK_WINDOW(win), "accounts"); - gtk_window_set_title(GTK_WINDOW(win), _("Accounts")); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(accedit_win_destroy_cb), accounts_window); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkblist.c --- a/pidgin/gtkblist.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkblist.c Sun May 20 18:40:58 2007 +0000 @@ -4195,7 +4195,7 @@ {"application/x-im-contact", 0, DRAG_BUDDY}, {"text/x-vcard", 0, DRAG_VCARD }}; if (gtkblist && gtkblist->window) { - purple_blist_set_visible(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_visible")); + purple_blist_set_visible(TRUE); return; } @@ -4204,9 +4204,7 @@ gtkblist->empty_avatar = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 32, 32); gdk_pixbuf_fill(gtkblist->empty_avatar, 0x00000000); - gtkblist->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(gtkblist->window), "buddy_list"); - gtk_window_set_title(GTK_WINDOW(gtkblist->window), _("Buddy List")); + gtkblist->window = pidgin_create_window(_("Buddy List"), 0, "buddy_list", TRUE); g_signal_connect(G_OBJECT(gtkblist->window), "focus-in-event", G_CALLBACK(blist_focus_cb), gtkblist); GTK_WINDOW(gtkblist->window)->allow_shrink = TRUE; diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkconv.c --- a/pidgin/gtkconv.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkconv.c Sun May 20 18:40:58 2007 +0000 @@ -8042,10 +8042,7 @@ window_list = g_list_append(window_list, win); /* Create the window. */ - win->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(win->window), "conversation"); - gtk_window_set_resizable(GTK_WINDOW(win->window), TRUE); - gtk_container_set_border_width(GTK_CONTAINER(win->window), 0); + win->window = pidgin_create_window(NULL, 0, "conversation", TRUE); GTK_WINDOW(win->window)->allow_shrink = TRUE; if (available_list == NULL) { diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkeventloop.c --- a/pidgin/gtkeventloop.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkeventloop.c Sun May 20 18:40:58 2007 +0000 @@ -120,7 +120,11 @@ pidgin_input_add, g_source_remove, NULL, /* input_get_error */ +#if GLIB_CHECK_VERSION(2,14,0) + g_timeout_add_seconds, +#else NULL, +#endif NULL, NULL, NULL diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkft.c --- a/pidgin/gtkft.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkft.c Sun May 20 18:40:58 2007 +0000 @@ -758,10 +758,7 @@ purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/filetransfer/clear_finished"); /* Create the window. */ - dialog->window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(window), "file transfer"); - gtk_window_set_title(GTK_WINDOW(window), _("File Transfers")); - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); + dialog->window = window = pidgin_create_window(_("File Transfers"), PIDGIN_HIG_BORDER, "file transfer", TRUE); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkmain.c --- a/pidgin/gtkmain.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkmain.c Sun May 20 18:40:58 2007 +0000 @@ -730,6 +730,15 @@ abort(); } + if (!purple_core_ensure_single_instance()) { + purple_core_quit(); +#ifdef HAVE_SIGNAL_H + g_free(segfault_message); +#endif + return 0; + } + + /* TODO: Move blist loading into purple_blist_init() */ purple_set_blist(purple_blist_new()); purple_blist_load(); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtknotify.c --- a/pidgin/gtknotify.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtknotify.c Sun May 20 18:40:58 2007 +0000 @@ -577,10 +577,8 @@ char label_text[2048]; char *linked_text, *primary_esc, *secondary_esc; - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), title); + window = pidgin_create_window(title, PIDGIN_HIG_BORDER, NULL, TRUE); gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(formatted_close_cb), NULL); @@ -712,10 +710,8 @@ data->results = results; /* Create the window */ - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(window), (title ? title :_("Search Results"))); + pidgin_create_window(title ? title :_("Search Results"), PIDGIN_HIG_BORDER, NULL, TRUE); gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); g_signal_connect_swapped(G_OBJECT(window), "delete_event", G_CALLBACK(searchresults_close_cb), data); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkpounce.c --- a/pidgin/gtkpounce.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkpounce.c Sun May 20 18:40:58 2007 +0000 @@ -498,15 +498,9 @@ sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); /* Create the window. */ - dialog->window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + dialog->window = window = pidgin_create_window((cur_pounce == NULL ? _("New Buddy Pounce") : _("Edit Buddy Pounce")), + PIDGIN_HIG_BORDER, "buddy_pounce", FALSE) ; gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_window_set_role(GTK_WINDOW(window), "buddy_pounce"); - gtk_window_set_resizable(GTK_WINDOW(window), FALSE); - gtk_window_set_title(GTK_WINDOW(window), - (cur_pounce == NULL - ? _("New Buddy Pounce") : _("Edit Buddy Pounce"))); - - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog); @@ -1323,11 +1317,8 @@ width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/pounces/dialog/width"); height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/pounces/dialog/height"); - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + dialog->window = win = pidgin_create_window(_("Buddy Pounces"), PIDGIN_HIG_BORDER, "pounces", TRUE); gtk_window_set_default_size(GTK_WINDOW(win), width, height); - gtk_window_set_role(GTK_WINDOW(win), "pounces"); - gtk_window_set_title(GTK_WINDOW(win), _("Buddy Pounces")); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(pounces_manager_destroy_cb), dialog); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkprefs.c --- a/pidgin/gtkprefs.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkprefs.c Sun May 20 18:40:58 2007 +0000 @@ -1948,11 +1948,7 @@ /* Back to instant-apply! I win! BU-HAHAHA! */ /* Create the window */ - prefs = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(prefs), "preferences"); - gtk_window_set_title(GTK_WINDOW(prefs), _("Preferences")); - gtk_window_set_resizable (GTK_WINDOW(prefs), FALSE); - gtk_container_set_border_width(GTK_CONTAINER(prefs), PIDGIN_HIG_BORDER); + prefs = pidgin_create_window(_("Preferences"), PIDGIN_HIG_BORDER, "preferences", FALSE); g_signal_connect(G_OBJECT(prefs), "destroy", G_CALLBACK(delete_prefs), NULL); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkprivacy.c --- a/pidgin/gtkprivacy.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkprivacy.c Sun May 20 18:40:58 2007 +0000 @@ -366,11 +366,7 @@ dialog = g_new0(PidginPrivacyDialog, 1); - dialog->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_resizable(GTK_WINDOW(dialog->win), FALSE); - gtk_window_set_role(GTK_WINDOW(dialog->win), "privacy"); - gtk_window_set_title(GTK_WINDOW(dialog->win), _("Privacy")); - gtk_container_set_border_width(GTK_CONTAINER(dialog->win), PIDGIN_HIG_BORDER); + dialog->win = pidgin_create_window(_("Privacy"), PIDGIN_HIG_BORDER, "privacy", FALSE); g_signal_connect(G_OBJECT(dialog->win), "delete_event", G_CALLBACK(destroy_cb), dialog); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkrequest.c --- a/pidgin/gtkrequest.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkrequest.c Sun May 20 18:40:58 2007 +0000 @@ -1069,16 +1069,12 @@ data->cbs[0] = ok_cb; data->cbs[1] = cancel_cb; - data->dialog = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - if (title != NULL) - gtk_window_set_title(GTK_WINDOW(win), title); + #ifdef _WIN32 - gtk_window_set_title(GTK_WINDOW(win), PIDGIN_ALERT_TITLE); -#endif - - gtk_window_set_role(GTK_WINDOW(win), "multifield"); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); + data->dialog = win = pidgin_create_window(PIDGIN_ALERT_TITLE, PIDGIN_HIG_BORDER, "multifield", TRUE) ; +#else /* !_WIN32 */ + data->dialog = win = pidgin_create_window(title, PIDGIN_HIG_BORDER, "multifield", TRUE) ; +#endif /* _WIN32 */ g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(destroy_multifield_cb), data); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkroomlist.c --- a/pidgin/gtkroomlist.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkroomlist.c Sun May 20 18:40:58 2007 +0000 @@ -371,11 +371,7 @@ dialog->account = account; /* Create the window. */ - dialog->window = window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(window), "room list"); - gtk_window_set_title(GTK_WINDOW(window), _("Room List")); - - gtk_container_set_border_width(GTK_CONTAINER(window), PIDGIN_HIG_BORDER); + dialog->window = window = pidgin_create_window(_("Room List"), PIDGIN_HIG_BORDER, "room list", TRUE); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete_win_cb), dialog); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtksavedstatuses.c --- a/pidgin/gtksavedstatuses.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtksavedstatuses.c Sun May 20 18:40:58 2007 +0000 @@ -551,11 +551,8 @@ width = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/status/dialog/width"); height = purple_prefs_get_int(PIDGIN_PREFS_ROOT "/status/dialog/height"); - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); + dialog->window = win = pidgin_create_window(_("Saved Statuses"), PIDGIN_HIG_BORDER, "statuses", TRUE); gtk_window_set_default_size(GTK_WINDOW(win), width, height); - gtk_window_set_role(GTK_WINDOW(win), "statuses"); - gtk_window_set_title(GTK_WINDOW(win), _("Saved Statuses")); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(status_window_destroy_cb), dialog); @@ -1085,11 +1082,7 @@ if (edit) dialog->original_title = g_strdup(purple_savedstatus_get_title(saved_status)); - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(win), "status"); - gtk_window_set_title(GTK_WINDOW(win), _("Status")); - gtk_window_set_resizable(GTK_WINDOW(win), FALSE); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); + dialog->window = win = pidgin_create_window (_("Status"), PIDGIN_HIG_BORDER, "status", FALSE) ; g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(status_editor_destroy_cb), dialog); @@ -1423,13 +1416,9 @@ dialog->status_editor = status_editor; dialog->account = account; - dialog->window = win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(win), "substatus"); tmp = g_strdup_printf(_("Status for %s"), purple_account_get_username(account)); - gtk_window_set_title(GTK_WINDOW(win), tmp); + dialog->window = win = pidgin_create_window(tmp, PIDGIN_HIG_BORDER, "substatus", FALSE) ; g_free(tmp); - gtk_window_set_resizable(GTK_WINDOW(win), FALSE); - gtk_container_set_border_width(GTK_CONTAINER(win), PIDGIN_HIG_BORDER); g_signal_connect(G_OBJECT(win), "delete_event", G_CALLBACK(substatus_editor_destroy_cb), dialog); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkutils.c Sun May 20 18:40:58 2007 +0000 @@ -122,6 +122,22 @@ } GtkWidget * +pidgin_create_window(const char *title, guint border_width, const char *role, gboolean resizable) +{ + GtkWindow *wnd = NULL; + + wnd = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); + if (title) + gtk_window_set_title(wnd, title); + gtk_container_set_border_width(GTK_CONTAINER(wnd), border_width); + if (role) + gtk_window_set_role(wnd, role); + gtk_window_set_resizable(wnd, resizable); + + return GTK_WIDGET(wnd); +} + +GtkWidget * pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret) { GtkWidget *frame; diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkutils.h --- a/pidgin/gtkutils.h Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkutils.h Sun May 20 18:40:58 2007 +0000 @@ -93,6 +93,18 @@ GtkWidget *pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret); /** + * Creates a new window + * + * @param title The window title, or @c NULL + * @param border_width The window's desired border width + * @param role A string indicating what the window is responsible for doing, or @c NULL + * @param resizable Whether the window should be resizable (@c TRUE) or not (@c FALSE) + * + * @since 2.1.0 + */ +GtkWidget *pidgin_create_window(const char *title, guint border_width, const char *role, gboolean resizable); + +/** * Toggles the sensitivity of a widget. * * @param widget @c NULL. Used for signal handlers. diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/gtkwhiteboard.c --- a/pidgin/gtkwhiteboard.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/gtkwhiteboard.c Sun May 20 18:40:58 2007 +0000 @@ -28,6 +28,7 @@ #include "debug.h" #include "gtkwhiteboard.h" +#include "gtkutils.h" /****************************************************************************** * Prototypes @@ -143,21 +144,14 @@ gtkwb->brush_color = 0xff0000; } - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtkwb->window = window; - gtk_widget_set_name(window, wb->who); - /* Try and set window title as the name of the buddy, else just use their * username */ buddy = purple_find_buddy(wb->account, wb->who); - if (buddy != NULL) - gtk_window_set_title((GtkWindow*)(window), purple_buddy_get_contact_alias(buddy)); - else - gtk_window_set_title((GtkWindow*)(window), wb->who); - - gtk_window_set_resizable((GtkWindow*)(window), FALSE); + window = pidgin_create_window(buddy != NULL ? purple_buddy_get_contact_alias(buddy) : wb->who, 0, NULL, FALSE); + gtkwb->window = window; + gtk_widget_set_name(window, wb->who); g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(whiteboard_close_cb), gtkwb); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/plugins/gevolution/add_buddy_dialog.c --- a/pidgin/plugins/gevolution/add_buddy_dialog.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/plugins/gevolution/add_buddy_dialog.c Sun May 20 18:40:58 2007 +0000 @@ -442,10 +442,7 @@ if (username != NULL) dialog->username = g_strdup(username); - dialog->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(dialog->win), "add_buddy"); - gtk_window_set_title(GTK_WINDOW(dialog->win), _("Add Buddy")); - gtk_container_set_border_width(GTK_CONTAINER(dialog->win), 12); + dialog->win = pidgin_create_window(_("Add Buddy"), PIDGIN_HIG_BORDER, "add_buddy", TRUE); gtk_widget_set_size_request(dialog->win, -1, 400); g_signal_connect(G_OBJECT(dialog->win), "delete_event", diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/plugins/gevolution/assoc-buddy.c --- a/pidgin/plugins/gevolution/assoc-buddy.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/plugins/gevolution/assoc-buddy.c Sun May 20 18:40:58 2007 +0000 @@ -329,9 +329,7 @@ dialog->buddy = buddy; - dialog->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(dialog->win), "assoc_buddy"); - gtk_container_set_border_width(GTK_CONTAINER(dialog->win), 12); + dialog->win = pidgin_create_window(NULL, PIDGIN_HIG_BORDER, "assoc_buddy", TRUE); g_signal_connect(G_OBJECT(dialog->win), "delete_event", G_CALLBACK(delete_win_cb), dialog); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/plugins/gevolution/new_person_dialog.c --- a/pidgin/plugins/gevolution/new_person_dialog.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/plugins/gevolution/new_person_dialog.c Sun May 20 18:40:58 2007 +0000 @@ -246,11 +246,7 @@ dialog->book = book; g_object_ref(book); - dialog->win = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_role(GTK_WINDOW(dialog->win), "new_person"); - gtk_window_set_title(GTK_WINDOW(dialog->win), _("New Person")); - gtk_window_set_resizable(GTK_WINDOW(dialog->win), FALSE); - gtk_container_set_border_width(GTK_CONTAINER(dialog->win), 12); + dialog->win = pidgin_create_window(_("New Person"), PIDGIN_HIG_BORDER, "new_person", FALSE); g_signal_connect(G_OBJECT(dialog->win), "delete_event", G_CALLBACK(delete_win_cb), dialog); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/plugins/ticker/ticker.c --- a/pidgin/plugins/ticker/ticker.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/plugins/ticker/ticker.c Sun May 20 18:40:58 2007 +0000 @@ -36,6 +36,7 @@ #include "gtkblist.h" #include "gtkplugin.h" +#include "gtkutils.h" #include "gtkticker.h" @@ -70,12 +71,10 @@ return; } - tickerwindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); + tickerwindow = pidgin_create_window(_("Buddy Ticker"), 0, "ticker", TRUE); gtk_window_set_default_size(GTK_WINDOW(tickerwindow), 500, -1); g_signal_connect(G_OBJECT(tickerwindow), "delete_event", G_CALLBACK (buddy_ticker_destroy_window), NULL); - gtk_window_set_title (GTK_WINDOW(tickerwindow), _("Buddy Ticker")); - gtk_window_set_role (GTK_WINDOW(tickerwindow), "ticker"); ticker = gtk_ticker_new(); gtk_ticker_set_spacing(GTK_TICKER(ticker), 20); diff -r ddf759c28d0b -r 1e674c0886b1 pidgin/plugins/xmppconsole.c --- a/pidgin/plugins/xmppconsole.c Sun May 20 18:32:40 2007 +0000 +++ b/pidgin/plugins/xmppconsole.c Sun May 20 18:40:58 2007 +0000 @@ -29,6 +29,7 @@ #if !GTK_CHECK_VERSION(2,4,0) #include "pidgincombobox.h" #endif +#include "gtkutils.h" typedef struct { PurpleConnection *gc; @@ -741,10 +742,8 @@ console = g_new0(XmppConsole, 1); - console->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(console->window), _("XMPP Console")); + console->window = pidgin_create_window(_("XMPP Console"), PIDGIN_HIG_BORDER, NULL, TRUE); g_signal_connect(G_OBJECT(console->window), "destroy", G_CALLBACK(console_destroy), NULL); - gtk_container_set_border_width(GTK_CONTAINER(console->window), 12); gtk_window_set_default_size(GTK_WINDOW(console->window), 580, 400); gtk_container_add(GTK_CONTAINER(console->window), vbox);