changeset 12288:3897229ccb33

[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 <tailor@pidgin.im>
author Luke Schierer <lschiere@pidgin.im>
date Fri, 02 Dec 2005 00:40:32 +0000
parents e4a9be312854
children d4ffa29eaa4f
files src/gtkconv.c src/gtkdialogs.c src/server.c
diffstat 3 files changed, 59 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- 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)
--- 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
--- 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);