# HG changeset patch # User Luke Schierer # Date 1133484032 0 # Node ID 3897229ccb339b61512db75071b4c87e8f998546 # Parent e4a9be312854fdbdea90559810f6e8c5278c6b9f [gaim-migrate @ 14592] " This patch fixes two serious bugs in the hidden conversation/queuing code. First, it removes the need to explicitly present conversations created under queuing conditions. Instead, when an incoming message is received and a conversation does not exist, a hidden conversation is created in a received-im-msg signal handler by swapping out the create_conversation function in the gtkconv ui_ops. This fixes a bug which could allow conversations to be created in a hidden state when they should be visible (i.e. buddy pounce open an im window action). This required a second search for a conversation in server.c after the signal is emitted. Second, it fixes a bug which would cause gaim to crash when quitting with a queued message. Fixing this simplified the code a bit by removing the private_remove_gtkconv function and instead adding a check in gaim_gtk_conv_window_remove_gtkconv to prevent the hidden_convwin from being destroyed when the last conversation is removed." --charkins committer: Tailor Script diff -r e4a9be312854 -r 3897229ccb33 src/gtkconv.c --- a/src/gtkconv.c Thu Dec 01 21:22:55 2005 +0000 +++ b/src/gtkconv.c Fri Dec 02 00:40:32 2005 +0000 @@ -133,8 +133,6 @@ static void update_typing_icon(GaimGtkConversation *gtkconv); static char *item_factory_translate_func (const char *path, gpointer func_data); gboolean gaim_gtkconv_has_focus(GaimConversation *conv); -static void private_remove_gtkconv(GaimGtkWindow *win, GaimGtkConversation *gtkconv, - gboolean destroy_empty); static GdkColor *get_nick_color(GaimGtkConversation *gtkconv, const char *name) { static GdkColor col; @@ -2389,7 +2387,7 @@ GaimGtkConversation *gtkconv = GAIM_GTK_CONVERSATION(conv); if(gtkconv->win==hidden_convwin) { - private_remove_gtkconv(hidden_convwin, gtkconv, FALSE); + gaim_gtk_conv_window_remove_gtkconv(hidden_convwin, gtkconv); gaim_gtkconv_placement_place(gtkconv); } @@ -3954,8 +3952,8 @@ /************************************************************************** * Conversation UI operations **************************************************************************/ -void -gaim_gtkconv_new(GaimConversation *conv) +static void +private_gtkconv_new(GaimConversation *conv, gboolean hidden) { GaimGtkConversation *gtkconv; GaimConversationType conv_type = gaim_conversation_get_type(conv); @@ -4053,24 +4051,50 @@ G_CALLBACK(gtk_widget_grab_focus), gtkconv->entry); - if (conv_type == GAIM_CONV_TYPE_IM) { - /* put conv in hidden_convwin if hide_new pref is always */ - if(strcmp(gaim_prefs_get_string("/gaim/gtk/conversations/im/hide_new"), "always")==0) { - gaim_gtk_conv_window_add_gtkconv(hidden_convwin, gtkconv); - return; - } - - /* put conv in hidden_convwin if hide_new pref is away and account is away */ - if(strcmp(gaim_prefs_get_string("/gaim/gtk/conversations/im/hide_new"), "away")==0 - && gaim_status_type_get_primitive( - gaim_status_get_type(gaim_account_get_active_status( - gaim_conversation_get_account(conv)))) == GAIM_STATUS_AWAY) { - gaim_gtk_conv_window_add_gtkconv(hidden_convwin, gtkconv); - return; - } - } - - gaim_gtkconv_placement_place(gtkconv); + if (hidden) + gaim_gtk_conv_window_add_gtkconv(hidden_convwin, gtkconv); + else + gaim_gtkconv_placement_place(gtkconv); +} + +static void +gaim_gtkconv_new_hidden(GaimConversation *conv) +{ + private_gtkconv_new(conv, TRUE); +} + +void +gaim_gtkconv_new(GaimConversation *conv) +{ + private_gtkconv_new(conv, FALSE); +} + +static void +received_im_msg_cb(GaimAccount *account, char *sender, char *message, + GaimConversation *conv, int flags) +{ + GaimConversationUiOps *ui_ops = gaim_gtk_conversations_get_conv_ui_ops(); + if(conv) + return; + + /* create hidden conv if hide_new pref is always */ + if(strcmp(gaim_prefs_get_string("/gaim/gtk/conversations/im/hide_new"), "always")==0) { + ui_ops->create_conversation = gaim_gtkconv_new_hidden; + gaim_conversation_new(GAIM_CONV_TYPE_IM, account, sender); + ui_ops->create_conversation = gaim_gtkconv_new; + return; + } + + /* create hidden conv if hide_new pref is away and account is away */ + if(strcmp(gaim_prefs_get_string("/gaim/gtk/conversations/im/hide_new"), "away")==0 + && gaim_status_type_get_primitive( + gaim_status_get_type( + gaim_account_get_active_status(account))) == GAIM_STATUS_AWAY) { + ui_ops->create_conversation = gaim_gtkconv_new_hidden; + gaim_conversation_new(GAIM_CONV_TYPE_IM, account, sender); + ui_ops->create_conversation = gaim_gtkconv_new; + return; + } } static void @@ -5703,7 +5727,7 @@ gaim_conversation_get_account(conv)))) == GAIM_STATUS_AWAY) continue; - private_remove_gtkconv(hidden_convwin, gtkconv, FALSE); + gaim_gtk_conv_window_remove_gtkconv(hidden_convwin, gtkconv); gaim_gtkconv_placement_place(gtkconv); } } @@ -5736,7 +5760,7 @@ gaim_conversation_get_account(conv)))) == GAIM_STATUS_AWAY) continue; - private_remove_gtkconv(hidden_convwin, gtkconv, FALSE); + gaim_gtk_conv_window_remove_gtkconv(hidden_convwin, gtkconv); gaim_gtkconv_placement_place(gtkconv); } } @@ -5916,6 +5940,9 @@ gaim_signal_connect(blist_handle, "buddy-removed", handle, G_CALLBACK(buddy_update_cb), NULL); + gaim_signal_connect(gaim_conversations_get_handle(), "received-im-msg", + handle, G_CALLBACK(received_im_msg_cb), NULL); + gaim_conversations_set_ui_ops(&conversation_ui_ops); hidden_convwin = gaim_gtk_conv_window_new(); @@ -6948,8 +6975,8 @@ update_send_to_selection(win); } -static void -private_remove_gtkconv(GaimGtkWindow *win, GaimGtkConversation *gtkconv, gboolean destroy_empty) +void +gaim_gtk_conv_window_remove_gtkconv(GaimGtkWindow *win, GaimGtkConversation *gtkconv) { unsigned int index; GaimConversationType conv_type; @@ -6970,14 +6997,9 @@ win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv); - if (destroy_empty && !win->gtkconvs) + if (!win->gtkconvs && win != hidden_convwin) gaim_gtk_conv_window_destroy(win); } -void -gaim_gtk_conv_window_remove_gtkconv(GaimGtkWindow *win, GaimGtkConversation *gtkconv) -{ - private_remove_gtkconv(win, gtkconv, TRUE); -} GaimGtkConversation * gaim_gtk_conv_window_get_gtkconv_at_index(const GaimGtkWindow *win, int index) diff -r e4a9be312854 -r 3897229ccb33 src/gtkdialogs.c --- a/src/gtkdialogs.c Thu Dec 01 21:22:55 2005 +0000 +++ b/src/gtkdialogs.c Fri Dec 02 00:40:32 2005 +0000 @@ -541,8 +541,6 @@ if (conv == NULL) conv = gaim_conversation_new(GAIM_CONV_TYPE_IM, account, username); - - gaim_gtkconv_present_conversation(conv); } static gboolean diff -r e4a9be312854 -r 3897229ccb33 src/server.c --- a/src/server.c Thu Dec 01 21:22:55 2005 +0000 +++ b/src/server.c Fri Dec 02 00:40:32 2005 +0000 @@ -476,6 +476,10 @@ gaim_signal_emit(gaim_conversations_get_handle(), "received-im-msg", gc->account, name, message, cnv, flags); + /* search for conversation again in case it was created by received-im-msg handler */ + if (cnv == NULL) + cnv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, name, gc->account); + /* Make sure URLs are clickable */ buffy = gaim_markup_linkify(message); g_free(message);