--- a/pidgin/gtkblist.c Wed Sep 12 11:04:26 2007 +0000
+++ b/pidgin/gtkblist.c Wed Sep 12 11:18:57 2007 +0000
@@ -137,12 +137,21 @@
static void pidgin_blist_collapse_contact_cb(GtkWidget *w, PurpleBlistNode *node);
static char *pidgin_get_group_title(PurpleBlistNode *gnode, gboolean expanded);
-struct _pidgin_blist_node {
+ PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE = 1 << 0, /* Whether there's pending message in a conversation */ +typedef struct _pidgin_blist_node { GtkTreeRowReference *row;
gboolean contact_expanded;
gboolean recent_signonoff;
gint recent_signonoff_timer;
+ PurpleConversation *conv; + time_t last_message; /* timestamp for last displayed message */ + PidginBlistNodeFlags flags; static char dim_grey_string[8] = "";
@@ -310,6 +319,23 @@
gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)));
+static void gtk_blist_menu_persistent_cb(GtkWidget *w, PurpleChat *chat) + purple_blist_node_set_bool((PurpleBlistNode*)chat, "gtk-persistent", + gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))); +static PurpleConversation * +find_conversation_with_buddy(PurpleBuddy *buddy) + PidginBlistNode *ui = buddy->node.ui_data; + return purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, + purple_buddy_get_name(buddy), + purple_buddy_get_account(buddy)); static void gtk_blist_join_chat(PurpleChat *chat)
PurpleConversation *conv;
@@ -1254,16 +1280,19 @@
create_chat_menu(PurpleBlistNode *node, PurpleChat *c)
+ gboolean autojoin, persistent; autojoin = (purple_blist_node_get_bool(node, "gtk-autojoin") ||
(purple_blist_node_get_string(node, "gtk-autojoin") != NULL));
+ persistent = purple_blist_node_get_bool(node, "gtk-persistent"); pidgin_new_item_from_stock(menu, _("_Join"), PIDGIN_STOCK_CHAT,
G_CALLBACK(gtk_blist_menu_join_cb), node, 0, 0, NULL);
pidgin_new_check_item(menu, _("Auto-Join"),
G_CALLBACK(gtk_blist_menu_autojoin_cb), node, autojoin);
+ pidgin_new_check_item(menu, _("Persistent"), + G_CALLBACK(gtk_blist_menu_persistent_cb), node, persistent); pidgin_new_item_from_stock(menu, _("View _Log"), NULL,
G_CALLBACK(gtk_blist_menu_showlog_cb), node, 0, 0, NULL);
@@ -3258,17 +3287,17 @@
- PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
- purple_buddy_get_name(buddy),
- purple_buddy_get_account(buddy));
+ PurpleConversation *conv = find_conversation_with_buddy(buddy); PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- if((gtkconv == NULL || pidgin_conv_is_hidden(gtkconv)) && size == PIDGIN_STATUS_ICON_SMALL) {
- return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), PIDGIN_STOCK_STATUS_MESSAGE,
- icon_size, "GtkTreeView");
+ if (gtkconv == NULL && size == PIDGIN_STATUS_ICON_SMALL) { + PidginBlistNode *ui = buddy->node.ui_data; + if (ui == NULL || (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE)) + return gtk_widget_render_icon (GTK_WIDGET(gtkblist->treeview), + PIDGIN_STOCK_STATUS_MESSAGE, icon_size, "GtkTreeView"); @@ -3324,16 +3353,17 @@
struct _pidgin_blist_node *gtkcontactnode = NULL;
char *idletime = NULL, *statustext = NULL;
- PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
- purple_buddy_get_name(b),
- purple_buddy_get_account(b));
- PidginConversation *gtkconv;
+ PurpleConversation *conv = find_conversation_with_buddy(b); gboolean hidden_conv = FALSE;
- gtkconv = PIDGIN_CONVERSATION(conv);
- if(gtkconv == NULL || pidgin_conv_is_hidden(gtkconv)) {
+ PidginBlistNode *ui = b->node.ui_data; + if (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE) + if (PIDGIN_CONVERSATION(conv) == NULL) @@ -3668,7 +3698,7 @@
- convs = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_IM, PIDGIN_UNSEEN_TEXT, TRUE, 0);
+ convs = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_ANY, PIDGIN_UNSEEN_TEXT, TRUE, 0); /* no conversations added, don't show the menu */
@@ -3724,7 +3754,7 @@
gtkblist->menutrayicon = NULL;
- convs = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_IM, PIDGIN_UNSEEN_TEXT, TRUE, 0);
+ convs = pidgin_conversations_find_unseen_list(PURPLE_CONV_TYPE_ANY, PIDGIN_UNSEEN_TEXT, TRUE, 0); GString *tooltip_text = NULL;
@@ -3732,14 +3762,10 @@
tooltip_text = g_string_new("");
- if (PIDGIN_IS_PIDGIN_CONVERSATION(l->data)) {
- PidginConversation *gtkconv = PIDGIN_CONVERSATION((PurpleConversation *)l->data);
- g_string_append_printf(tooltip_text,
- ngettext("%d unread message from %s\n", "%d unread messages from %s\n", gtkconv->unseen_count),
- gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)));
+ int count = GPOINTER_TO_INT(purple_conversation_get_data(l->data, "unseen-count")); + g_string_append_printf(tooltip_text, + ngettext("%d unread message from %s\n", "%d unread messages from %s\n", count), + count, purple_conversation_get_name(l->data)); if(tooltip_text->len > 0) {
@@ -3767,6 +3793,87 @@
conversation_updated_cb(conv, PURPLE_CONV_UPDATE_UNSEEN, gtkblist);
+conversation_deleted_update_ui_cb(PurpleConversation *conv, struct _pidgin_blist_node *ui) + if (ui->conv.conv != conv) + ui->conv.last_message = 0; +written_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message, + PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node) + PidginBlistNode *ui = node->ui_data; + if (ui->conv.conv != conv || PIDGIN_CONVERSATION(conv)) + ui->conv.flags |= PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE; + ui->conv.last_message = time(NULL); /* XXX: for lack of better data */ + pidgin_blist_update(purple_get_blist(), node); +displayed_msg_update_ui_cb(PurpleAccount *account, const char *who, const char *message, + PurpleConversation *conv, PurpleMessageFlags flag, PurpleBlistNode *node) + PidginBlistNode *ui = node->ui_data; + if (ui->conv.conv != conv) + ui->conv.flags &= ~PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE; + pidgin_blist_update(purple_get_blist(), node); +conversation_created_cb(PurpleConversation *conv, PidginBuddyList *gtkblist) + case PURPLE_CONV_TYPE_IM: + GSList *buddies = purple_find_buddies(conv->account, conv->name); + PurpleBlistNode *buddy = buddies->data; + struct _pidgin_blist_node *ui = buddy->ui_data; + buddies = g_slist_delete_link(buddies, buddies); + ui->conv.last_message = 0; + purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", + ui, PURPLE_CALLBACK(conversation_deleted_update_ui_cb), ui); + purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", + ui, PURPLE_CALLBACK(written_msg_update_ui_cb), buddy); + purple_signal_connect(pidgin_conversations_get_handle(), "displayed-im-msg", + ui, PURPLE_CALLBACK(displayed_msg_update_ui_cb), buddy); + case PURPLE_CONV_TYPE_CHAT: + PurpleChat *chat = purple_blist_find_chat(conv->account, conv->name); + struct _pidgin_blist_node *ui; + ui = chat->node.ui_data; + ui->conv.last_message = 0; + purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation", + ui, PURPLE_CALLBACK(conversation_deleted_update_ui_cb), ui); + purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", + ui, PURPLE_CALLBACK(written_msg_update_ui_cb), chat); + purple_signal_connect(pidgin_conversations_get_handle(), "displayed-chat-msg", + ui, PURPLE_CALLBACK(displayed_msg_update_ui_cb), chat); /**********************************************************************************
**********************************************************************************/
@@ -4680,6 +4787,9 @@
purple_signal_connect(purple_conversations_get_handle(), "deleting-conversation",
gtkblist, PURPLE_CALLBACK(conversation_deleting_cb),
+ purple_signal_connect(purple_conversations_get_handle(), "conversation-created", + gtkblist, PURPLE_CALLBACK(conversation_created_cb), gtk_widget_hide(gtkblist->headline_hbox);
gtk_widget_hide(gtkblist->error_buttons);
@@ -4786,6 +4896,7 @@
if(gtknode->recent_signonoff_timer > 0)
purple_timeout_remove(gtknode->recent_signonoff_timer);
+ purple_signals_disconnect_by_handle(node->ui_data); @@ -5210,14 +5321,17 @@
gboolean showicons = purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons");
- const char *name = purple_chat_get_name(chat);
- PurpleConversation *conv =
- purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name, chat->account);
- gboolean hidden = (conv && !PIDGIN_CONVERSATION(conv));
- if(!insert_node(list, node, &iter))
+ PurpleConversation *conv; + if (!insert_node(list, node, &iter)) + hidden = (conv && (ui->conv.flags & PIDGIN_BLIST_NODE_HAS_PENDING_MESSAGE)); status = pidgin_blist_get_status_icon(node,
PIDGIN_STATUS_ICON_SMALL);
emblem = pidgin_blist_get_emblem(node);
--- a/pidgin/gtkconv.c Wed Sep 12 11:04:26 2007 +0000
+++ b/pidgin/gtkconv.c Wed Sep 12 11:18:57 2007 +0000
@@ -69,6 +69,8 @@
#include "gtknickcolors.h"
+#define CLOSE_CONV_TIMEOUT_SECS (10 * 60) #define AUTO_RESPONSE "<AUTO-REPLY> : "
@@ -122,7 +124,6 @@
static GtkWidget *invite_dialog = NULL;
static GtkWidget *warn_close_dialog = NULL;
-static PidginWindow *hidden_convwin = NULL;
static GList *window_list = NULL;
/* Lists of status icons at all available sizes for use as window icons */
@@ -160,6 +161,7 @@
static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv);
static gboolean pidgin_userlist_motion_cb (GtkWidget *w, GdkEventMotion *event, PidginConversation *gtkconv);
static void pidgin_conv_leave_cb (GtkWidget *w, GdkEventCrossing *e, PidginConversation *gtkconv);
+static void hide_conv(PidginConversation *gtkconv, gboolean closetimer); static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y,
@@ -188,12 +190,49 @@
**************************************************************************/
-close_conv_cb(GtkWidget *w, GdkEventButton *event, PidginConversation *gtkconv)
+close_this_sucker(gpointer data) + PidginConversation *gtkconv = data; GList *list = g_list_copy(gtkconv->convs);
g_list_foreach(list, (GFunc)purple_conversation_destroy, NULL);
+close_conv_cb(GtkWidget *w, GdkEventButton *event, PidginConversation *gtkconv) + /* We are going to destroy the conversations immediately only if the 'close immediately' + * preference is selected. Otherwise, close the conversation after a reasonable timeout + * (I am going to consider 10 minutes as a 'reasonable timeout' here. + * For chats, close immediately if the chat is not in the buddylist, or if the chat is + * not marked 'Persistent' */ + PurpleConversation *conv = gtkconv->active_conv; + PurpleAccount *account = purple_conversation_get_account(conv); + const char *name = purple_conversation_get_name(conv); + switch (purple_conversation_get_type(conv)) { + case PURPLE_CONV_TYPE_IM: + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/close_immediately")) + close_this_sucker(gtkconv); + hide_conv(gtkconv, TRUE); + case PURPLE_CONV_TYPE_CHAT: + PurpleChat *chat = purple_blist_find_chat(account, name); + !purple_blist_node_get_bool(&chat->node, "gtk-persistent")) + close_this_sucker(gtkconv); + hide_conv(gtkconv, FALSE); @@ -1304,16 +1343,33 @@
add_remove_cb(NULL, PIDGIN_CONVERSATION(conv));
+close_already(gpointer data) + purple_conversation_destroy(data); -menu_hide_conv_cb(gpointer data, guint action, GtkWidget *widget)
- PidginWindow *win = data;
- PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win);
- PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
+hide_conv(PidginConversation *gtkconv, gboolean closetimer) purple_signal_emit(pidgin_conversations_get_handle(),
"conversation-hiding", gtkconv);
- purple_conversation_set_ui_ops(conv, NULL);
+ for (list = g_list_copy(gtkconv->convs); list; list = g_list_delete_link(list, list)) { + PurpleConversation *conv = list->data; + guint timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); + purple_timeout_remove(timer); + timer = purple_timeout_add_seconds(CLOSE_CONV_TIMEOUT_SECS, close_already, conv); + purple_conversation_set_data(conv, "close-timer", GINT_TO_POINTER(timer)); + purple_conversation_set_ui_ops(conv, NULL); @@ -2326,63 +2382,69 @@
return get_prpl_icon_list(account);
-pidgin_conv_get_tab_icon(PurpleConversation *conv, gboolean small_icon)
- PurpleAccount *account = NULL;
- const char *name = NULL;
- GdkPixbuf *status = NULL;
- PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
- const char *icon_size = small_icon ? PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC : PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL;
- g_return_val_if_fail(conv != NULL, NULL);
- account = purple_conversation_get_account(conv);
- name = purple_conversation_get_name(conv);
- g_return_val_if_fail(account != NULL, NULL);
- g_return_val_if_fail(name != NULL, NULL);
- /* Use the buddy icon, if possible */
- if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
- PurpleBuddy *b = purple_find_buddy(account, name);
+pidgin_conv_get_icon(PurpleConversation *conv, GtkWidget *parent, const char *icon_size) + PurpleAccount *account = NULL; + const char *name = NULL; + GdkPixbuf *status = NULL; + PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); + g_return_val_if_fail(conv != NULL, NULL); + account = purple_conversation_get_account(conv); + name = purple_conversation_get_name(conv); + g_return_val_if_fail(account != NULL, NULL); + g_return_val_if_fail(name != NULL, NULL); + /* Use the buddy icon, if possible */ + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + PurpleBuddy *b = purple_find_buddy(account, name); PurplePresence *p = purple_buddy_get_presence(b);
- /* I hate this hack. It fixes a bug where the pending message icon
- * displays in the conv tab even though it shouldn't.
- * A better solution would be great. */
- if (ops && ops->update)
- ops->update(NULL, (PurpleBlistNode*)b);
+ /* I hate this hack. It fixes a bug where the pending message icon + * displays in the conv tab even though it shouldn't. + * A better solution would be great. */ + if (ops && ops->update) + ops->update(NULL, (PurpleBlistNode*)b); /* XXX Seanegan: We really need a util function to return a pixbuf for a Presence to avoid all this switching */
if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY))
- status = pidgin_create_status_icon(PURPLE_STATUS_AWAY, PIDGIN_CONVERSATION(conv)->icon, icon_size);
+ status = pidgin_create_status_icon(PURPLE_STATUS_AWAY, parent, icon_size); else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY))
- status = pidgin_create_status_icon(PURPLE_STATUS_EXTENDED_AWAY, PIDGIN_CONVERSATION(conv)->icon, icon_size);
- else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE))
- status = pidgin_create_status_icon(PURPLE_STATUS_OFFLINE, PIDGIN_CONVERSATION(conv)->icon, icon_size);
- else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE))
- status = pidgin_create_status_icon(PURPLE_STATUS_AVAILABLE, PIDGIN_CONVERSATION(conv)->icon, icon_size);
- else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE))
- status = pidgin_create_status_icon(PURPLE_STATUS_INVISIBLE, PIDGIN_CONVERSATION(conv)->icon, icon_size);
- else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE))
- status = pidgin_create_status_icon(PURPLE_STATUS_UNAVAILABLE, PIDGIN_CONVERSATION(conv)->icon, icon_size);
- /* If they don't have a buddy icon, then use the PRPL icon */
+ status = pidgin_create_status_icon(PURPLE_STATUS_EXTENDED_AWAY, parent, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) + status = pidgin_create_status_icon(PURPLE_STATUS_OFFLINE, parent, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE)) + status = pidgin_create_status_icon(PURPLE_STATUS_AVAILABLE, parent, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) + status = pidgin_create_status_icon(PURPLE_STATUS_INVISIBLE, parent, icon_size); + else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE)) + status = pidgin_create_status_icon(PURPLE_STATUS_UNAVAILABLE, parent, icon_size); + /* If they don't have a buddy icon, then use the PRPL icon */ GtkIconSize size = gtk_icon_size_from_name(icon_size);
if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
- status = gtk_widget_render_icon (PIDGIN_CONVERSATION(conv)->icon, PIDGIN_STOCK_STATUS_PERSON,
+ status = gtk_widget_render_icon (parent, PIDGIN_STOCK_STATUS_PERSON, - status = gtk_widget_render_icon (PIDGIN_CONVERSATION(conv)->icon, PIDGIN_STOCK_STATUS_CHAT,
+ status = gtk_widget_render_icon (parent, PIDGIN_STOCK_STATUS_CHAT, +pidgin_conv_get_tab_icon(PurpleConversation *conv, gboolean small_icon) + const char *icon_size = small_icon ? PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC : PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL; + return pidgin_conv_get_icon(conv, PIDGIN_CONVERSATION(conv)->icon, icon_size); update_tab_icon(PurpleConversation *conv)
@@ -2734,9 +2796,9 @@
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- if(gtkconv->win==hidden_convwin) {
- pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv);
- pidgin_conv_placement_place(gtkconv);
+ pidgin_conv_attach_to_conversation(conv); + gtkconv = PIDGIN_CONVERSATION(conv); pidgin_conv_switch_active_conversation(conv);
@@ -2769,15 +2831,19 @@
PurpleConversation *conv = (PurpleConversation*)l->data;
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
- if(gtkconv == NULL || gtkconv->active_conv != conv)
+ if (gtkconv != NULL && gtkconv->active_conv != conv)
- if (gtkconv->unseen_state >= min_state
- (hidden_only && gtkconv->win == hidden_convwin))) {
+ !purple_conversation_get_data(conv, "unseen-count")) r = g_list_prepend(r, conv);
+ if (gtkconv->unseen_state >= min_state && !hidden_only) { + r = g_list_prepend(r, conv); @@ -2817,11 +2883,11 @@
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
GtkWidget *icon = gtk_image_new();
- GdkPixbuf *pbuf = pidgin_conv_get_tab_icon(conv, TRUE);
+ GdkPixbuf *pbuf = pidgin_conv_get_icon(conv, icon, PIDGIN_ICON_SIZE_TANGO_MICROSCOPIC); gchar *text = g_strdup_printf("%s (%d)",
- gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)),
- gtkconv->unseen_count);
+ gtkconv ? gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)) : purple_conversation_get_name(conv), + gtkconv ? gtkconv->unseen_count : GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count"))); gtk_image_set_from_pixbuf(GTK_IMAGE(icon), pbuf);
@@ -3079,7 +3145,7 @@
PurpleConversation *conv;
- if (win->window == NULL || win == hidden_convwin)
+ if (win->window == NULL) gtkconv = pidgin_conv_window_get_active_gtkconv(win);
@@ -4928,6 +4994,9 @@
if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) {
if (!g_list_find(gtkconv->convs, conv))
@@ -5025,10 +5094,7 @@
G_CALLBACK(gtk_widget_grab_focus),
- pidgin_conv_window_add_gtkconv(hidden_convwin, gtkconv);
- pidgin_conv_placement_place(gtkconv);
+ pidgin_conv_placement_place(gtkconv); if (nick_colors == NULL) {
nbr_nick_colors = NUM_NICK_COLORS;
@@ -5036,11 +5102,13 @@
pidgin_conv_new_hidden(PurpleConversation *conv)
private_gtkconv_new(conv, TRUE);
pidgin_conv_new(PurpleConversation *conv)
@@ -5053,26 +5121,23 @@
PurpleConversation *conv, PurpleMessageFlags flags)
PurpleConversationUiOps *ui_ops = pidgin_conversations_get_conv_ui_ops();
+ /* XXX sadrul: set _ui_ops for the conversation to NULL, and get rid of the hidden convwindow */ /* create hidden conv if hide_new pref is always */
- if (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "always") == 0)
- ui_ops->create_conversation = pidgin_conv_new_hidden;
- purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender);
- ui_ops->create_conversation = pidgin_conv_new;
- /* create hidden conv if hide_new pref is away and account is away */
- if (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away") == 0 &&
- !purple_status_is_available(purple_account_get_active_status(account)))
- ui_ops->create_conversation = pidgin_conv_new_hidden;
- purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender);
- ui_ops->create_conversation = pidgin_conv_new;
+ /* or if hide_new pref is away and account is away */ + if ((strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "always") == 0) || + (strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away") == 0 && + !purple_status_is_available(purple_account_get_active_status(account)))) { + ui_ops->create_conversation = NULL; + conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender); + purple_conversation_set_ui_ops(conv, NULL); + ui_ops->create_conversation = pidgin_conv_new; + /* new message for an IM */ + if (conv && conv->type == PURPLE_CONV_TYPE_IM) + pidgin_conv_attach_to_conversation(conv); @@ -5081,6 +5146,9 @@
PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
gtkconv->convs = g_list_remove(gtkconv->convs, conv);
/* Don't destroy ourselves until all our convos are gone */
@@ -6553,6 +6621,19 @@
pidgin_conv_update_fields(conv, flags);
+wrote_msg_update_unseen_cb(PurpleAccount *account, const char *who, const char *message, + PurpleConversation *conv, PurpleMessageFlags flag, gpointer null) + if (conv == NULL || PIDGIN_IS_PIDGIN_CONVERSATION(conv)) + if (flag & (PURPLE_MESSAGE_SEND | PURPLE_MESSAGE_RECV)) { + purple_conversation_set_data(conv, "unseen-count", + GINT_TO_POINTER(GPOINTER_TO_INT(purple_conversation_get_data(conv, "unseen-count")) + 1)); + purple_conversation_update(conv, PURPLE_CONV_UPDATE_UNSEEN); static PurpleConversationUiOps conversation_ui_ops =
@@ -7050,6 +7131,7 @@
account_status_changed_cb(PurpleAccount *account, PurpleStatus *oldstatus,
PurpleConversation *conv = NULL;
PidginConversation *gtkconv;
@@ -7059,27 +7141,7 @@
if(purple_status_is_available(oldstatus) || !purple_status_is_available(newstatus))
- while ((l = hidden_convwin->gtkconvs) != NULL)
- conv = gtkconv->active_conv;
- while(l && !purple_status_is_available(
- purple_account_get_active_status(
- purple_conversation_get_account(conv))))
- pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv);
- pidgin_conv_placement_place(gtkconv);
- /* TODO: do we need to do anything for any other conversations that are in the same gtkconv here?
- * I'm a little concerned that not doing so will cause the "pending" indicator in the gtkblist not to be cleared. -DAA*/
- purple_conversation_update(conv, PURPLE_CONV_UPDATE_UNSEEN);
@@ -7087,32 +7149,25 @@
gconstpointer value, gpointer data)
- PurpleConversation *conv = NULL;
- PidginConversation *gtkconv;
gboolean when_away = FALSE;
if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "always")==0)
if(strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new"), "away")==0)
- while ((l = hidden_convwin->gtkconvs) != NULL)
+ for (l = purple_get_conversations(); l; l = l->next)
- conv = gtkconv->active_conv;
+ PurpleConversation *conv = l->data; + PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv); if(when_away && !purple_status_is_available(
purple_account_get_active_status(
purple_conversation_get_account(conv))))
- pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv);
- pidgin_conv_placement_place(gtkconv);
+ pidgin_conv_attach_to_conversation(conv); @@ -7298,6 +7353,10 @@
gtkconv->attach.timer = 0;
while (gtkconv->attach.current && count < 100) { /* XXX: 100 is a random value here */
PurpleConvMessage *msg = gtkconv->attach.current->data;
+ if (gtkconv->attach.when && gtkconv->attach.when < msg->when) { + gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), "<HR>", 0); + gtkconv->attach.when = 0; pidgin_conv_write_conv(gtkconv->active_conv, msg->who, msg->who, msg->what, msg->flags, msg->when);
gtkconv->attach.current = gtkconv->attach.current->prev;
@@ -7317,18 +7376,20 @@
PidginConversation *gtkconv;
if (PIDGIN_IS_PIDGIN_CONVERSATION(conv))
+ purple_conversation_set_data(conv, "unseen-count", NULL); purple_conversation_set_ui_ops(conv, pidgin_conversations_get_conv_ui_ops());
private_gtkconv_new(conv, FALSE);
gtkconv = PIDGIN_CONVERSATION(conv);
list = purple_conversation_get_message_history(conv);
- list = g_list_last(list);
- gtkconv->attach.current = list;
+ gtkconv->attach.when = ((PurpleConvMessage*)(list->data))->when; + gtkconv->attach.current = g_list_last(list); gtkconv->attach.timer = g_idle_add(add_message_history_to_gtkconv, gtkconv);
purple_signal_emit(pidgin_conversations_get_handle(),
@@ -7340,6 +7401,10 @@
pidgin_conv_chat_add_users(conv, PURPLE_CONV_CHAT(conv)->in_room, TRUE);
+ timer = GPOINTER_TO_INT(purple_conversation_get_data(conv, "close-timer")); + purple_timeout_remove(timer); @@ -7405,6 +7470,7 @@
purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons", TRUE);
purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new", "never");
+ purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/close_immediately", FALSE); purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/win32/minimize_new_convs", FALSE);
@@ -7568,9 +7634,6 @@
purple_conversations_set_ui_ops(&conversation_ui_ops);
- hidden_convwin = pidgin_conv_window_new();
- window_list = g_list_remove(window_list, hidden_convwin);
purple_signal_connect(purple_accounts_get_handle(), "account-status-changed",
handle, PURPLE_CALLBACK(account_status_changed_cb), NULL);
@@ -7606,6 +7669,10 @@
purple_signal_connect_priority(purple_conversations_get_handle(), "conversation-updated", handle,
PURPLE_CALLBACK(pidgin_conv_updated), NULL,
PURPLE_SIGNAL_PRIORITY_LOWEST);
+ purple_signal_connect(purple_conversations_get_handle(), "wrote-im-msg", handle, + PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); + purple_signal_connect(purple_conversations_get_handle(), "wrote-chat-msg", handle, + PURPLE_CALLBACK(wrote_msg_update_unseen_cb), NULL); @@ -7614,8 +7681,6 @@
purple_prefs_disconnect_by_handle(pidgin_conversations_get_handle());
purple_signals_disconnect_by_handle(pidgin_conversations_get_handle());
purple_signals_unregister_by_instance(pidgin_conversations_get_handle());
- pidgin_conv_window_destroy(hidden_convwin);
@@ -9032,7 +9097,7 @@
if (win->gtkconvs && win->gtkconvs->next == NULL)
pidgin_conv_tab_pack(win, win->gtkconvs->data);
- if (!win->gtkconvs && win != hidden_convwin)
pidgin_conv_window_destroy(win);
@@ -9571,9 +9636,7 @@
pidgin_conv_is_hidden(PidginConversation *gtkconv)
- g_return_val_if_fail(gtkconv != NULL, FALSE);
- return (gtkconv->win == hidden_convwin);
+ return (gtkconv == NULL);