# HG changeset patch # User Gabriel Schulhof # Date 1179386966 0 # Node ID 150980c9d79db2e197479ec84a5f7b06d83da063 # Parent 7cdc1d7fad5586a507c39c3edd8c5e9e726134a7# Parent b5935a854ccb1f0728bdb66322630ec0e46ec778 propagate from branch 'im.pidgin.pidgin' (head 4398ffa92e9bb0a16dbede7756a4cbc5dfa96602) to branch 'org.maemo.garage.pidgin.pidgin.dbus_uniq' (head d84c40292a3880b1acf3da22ef915e230a883ac5) diff -r b5935a854ccb -r 150980c9d79d COPYRIGHT --- a/COPYRIGHT Wed May 16 20:51:28 2007 +0000 +++ b/COPYRIGHT Thu May 17 07:29:26 2007 +0000 @@ -323,6 +323,7 @@ Phil Snowberger Eddie Sohn (tr1sk) Sony Computer Entertainment America, Inc. +Andy Spencer Mark Spencer Lex Spoon Chris Stafford @@ -360,6 +361,7 @@ James Vega David Vermeille Sid Vicious +Jorge VillaseƱor (Masca) Bjoern Voigt Wan Hing Wah Philip Walford diff -r b5935a854ccb -r 150980c9d79d ChangeLog --- a/ChangeLog Wed May 16 20:51:28 2007 +0000 +++ b/ChangeLog Thu May 17 07:29:26 2007 +0000 @@ -24,9 +24,13 @@ * Identify the account when warning about plaintext auth over an unencrypted channel * Fix XMPP SASL authentication error when using Cyrus and a connect server + * Fix changing tab locations to update properly * Turning off "Show formatting on incoming messages" now ignores formatting in tags too * File transfer progress for transfers on MSN is now correctly displayed + * You can set/change alias of buddies/chats by double-clicking on the + conversation tabs. (Ma Xuan) + * Fix IRC connection bug with dircproxy (xjoe) Finch: * Userlist in chat windows, which can be turned on or off using diff -r b5935a854ccb -r 150980c9d79d libpurple/idle.c --- a/libpurple/idle.c Wed May 16 20:51:28 2007 +0000 +++ b/libpurple/idle.c Thu May 17 07:29:26 2007 +0000 @@ -31,7 +31,6 @@ #include "signals.h" #define IDLEMARK 600 /* 10 minutes! */ -#define IDLE_CHECK_INTERVAL 5 /* 5 seconds */ typedef enum { @@ -92,6 +91,8 @@ purple_presence_set_idle(presence, FALSE, 0); } + +static gint time_until_next_idle_event; /* * This function should be called when you think your idle state * may have changed. Maybe you're over the 10-minute mark and @@ -110,14 +111,17 @@ * 2. Set or unset your auto-away message. * 3. Report your current idle time to the IM server. */ -static gint -check_idleness() + +static void +check_idleness(void) { time_t time_idle; gboolean auto_away; const gchar *idle_reporting; gboolean report_idle; GList *l; + gint away_seconds = 0; + static int no_away = 0; purple_signal_emit(purple_blist_get_handle(), "update-idle"); @@ -153,14 +157,24 @@ time_idle = time(NULL) - last_active_time; } - if (auto_away && - (time_idle > (60 * purple_prefs_get_int("/purple/away/mins_before_away")))) + time_until_next_idle_event = IDLEMARK - time_idle; /* reasonable start upperbound */ + + if (auto_away || !no_away) + away_seconds = 60 * purple_prefs_get_int("/purple/away/mins_before_away"); + + if (auto_away && time_idle > away_seconds) { purple_savedstatus_set_idleaway(TRUE); + no_away = 0; + if (time_idle < away_seconds && (away_seconds - time_idle) < time_until_next_idle_event) + time_until_next_idle_event = away_seconds - time_idle; } - else if (time_idle < 60 * purple_prefs_get_int("/purple/away/mins_before_away")) + else if (!no_away && time_idle < away_seconds) { purple_savedstatus_set_idleaway(FALSE); + no_away = 1; + if (time_idle < away_seconds && (away_seconds - time_idle) < time_until_next_idle_event) + time_until_next_idle_event = away_seconds - time_idle; } /* Idle reporting stuff */ @@ -177,8 +191,21 @@ while (idled_accts != NULL) set_account_unidle(idled_accts->data); } + + if (time_until_next_idle_event < 0) + time_until_next_idle_event = IDLEMARK; +} - return TRUE; + +/* + * Check idle and set the timer to fire at the next idle-worth event + */ +static gint +check_idleness_timer() +{ + check_idleness(); + idle_timer = purple_timeout_add(1000 * (time_until_next_idle_event + 1), check_idleness_timer, NULL); + return FALSE; } static void @@ -241,7 +268,7 @@ purple_idle_init() { /* Add the timer to check if we're idle */ - idle_timer = purple_timeout_add(IDLE_CHECK_INTERVAL * 1000, check_idleness, NULL); + idle_timer = purple_timeout_add(1000 * (IDLEMARK + 1), check_idleness_timer, NULL); purple_signal_connect(purple_conversations_get_handle(), "sent-im-msg", purple_idle_get_handle(), diff -r b5935a854ccb -r 150980c9d79d libpurple/plugin.c diff -r b5935a854ccb -r 150980c9d79d libpurple/plugins/joinpart.c --- a/libpurple/plugins/joinpart.c Wed May 16 20:51:28 2007 +0000 +++ b/libpurple/plugins/joinpart.c Thu May 17 07:29:26 2007 +0000 @@ -156,7 +156,7 @@ static gboolean check_expire_time(struct joinpart_key *key, time_t *last_said, time_t *limit) { - purple_debug_info("joinpart", "Removing key for %s/%s\n", key->conv->name, key->user); + purple_debug_info("joinpart", "Removing key for %s\n", key->user); return (*last_said < *limit); } diff -r b5935a854ccb -r 150980c9d79d libpurple/plugins/perl/Makefile.am --- a/libpurple/plugins/perl/Makefile.am Wed May 16 20:51:28 2007 +0000 +++ b/libpurple/plugins/perl/Makefile.am Thu May 17 07:29:26 2007 +0000 @@ -78,7 +78,8 @@ # common/fallback/const-xs.inc perl_scripts = \ - scripts/function_list.pl + scripts/function_list.pl \ + scripts/signals-test.pl EXTRA_DIST = \ Makefile.mingw \ diff -r b5935a854ccb -r 150980c9d79d libpurple/plugins/perl/scripts/signals-test.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpurple/plugins/perl/scripts/signals-test.pl Thu May 17 07:29:26 2007 +0000 @@ -0,0 +1,80 @@ +$MODULE_NAME = "Signals Test Script in Perl"; + +use Purple; + +%PLUGIN_INFO = ( + perl_api_version => 2, + name => "Perl: $MODULE_NAME", + version => "0.1", + summary => "Signals Test plugin for the Perl interpreter.", + description => "Demonstrate the user of purple signals from " . + "a perl plugin.", + author => "Sadrul Habib Chowdhury ", + url => "http://developer.pidgin.im/wiki/sadrul/", + + load => "plugin_load", + unload => "plugin_unload" +); + +# Accounts +sub account_connecting_cb +{ + my $account = shift; + Purple::Debug::misc("signals test in perl", "account-connecting (" . $account->get_username() . ")\n"); +} + +# Buddylist +sub buddy_signed_on +{ + my $buddy = shift; + Purple::Debug::misc("signals test in perl", "buddy-signed-on (" . $buddy->get_name() . ")\n"); +} + +# Connections +sub signed_on +{ + my $conn = shift; + Purple::Debug::misc("signals test in perl", "signed-on (" . $conn->get_account()->get_username() . ")\n"); +} + +# Conversations +sub conv_received_msg +{ + my ($account, $sender, $message, $conv, $flags, $data) = @_; + Purple::Debug::misc("signals test in perl", "$data (" . $account->get_username() . ", $sender, $message, $flags)\n"); +} + +sub plugin_load +{ + my $plugin = shift; + + # Hook to the signals + + # Accounts + $act_handle = Purple::Accounts::get_handle(); + Purple::Signal::connect($act_handle, "account-connecting", $plugin, + \&account_connecting_cb, 0); + + # Buddy List + $blist = Purple::BuddyList::get_handle(); + Purple::Signal::connect($blist, "buddy-signed-on", $plugin, + \&buddy_signed_on, 0); + + # Connections + $conn = Purple::Connections::get_handle(); + Purple::Signal::connect($conn, "signed-on", $plugin, + \&signed_on, 0); + + # Conversations + $conv = Purple::Conversations::get_handle(); + Purple::Signal::connect($conv, "received-im-msg", $plugin, + \&conv_received_msg, "received im message"); + Purple::Signal::connect($conv, "received-chat-msg", $plugin, + \&conv_received_msg, "received chat message"); +} + +sub plugin_unload +{ + # Nothing to do here for this plugin. +} + diff -r b5935a854ccb -r 150980c9d79d libpurple/protocols/irc/msgs.c --- a/libpurple/protocols/irc/msgs.c Wed May 16 20:51:28 2007 +0000 +++ b/libpurple/protocols/irc/msgs.c Thu May 17 07:29:26 2007 +0000 @@ -35,6 +35,7 @@ static char *irc_mask_userhost(const char *mask); static void irc_chat_remove_buddy(PurpleConversation *convo, char *data[2]); static void irc_buddy_status(char *name, struct irc_buddy *ib, struct irc_conn *irc); +static void irc_connected(struct irc_conn *irc, const char *nick); static void irc_msg_handle_privmsg(struct irc_conn *irc, const char *name, const char *from, const char *to, @@ -70,6 +71,52 @@ g_free(message); } +static void irc_connected(struct irc_conn *irc, const char *nick) +{ + PurpleConnection *gc; + PurpleStatus *status; + PurpleBlistNode *gnode, *cnode, *bnode; + + if ((gc = purple_account_get_connection(irc->account)) == NULL + || PURPLE_CONNECTION_IS_CONNECTED(gc)) + return; + + purple_connection_set_display_name(gc, nick); + purple_connection_set_state(gc, PURPLE_CONNECTED); + + /* If we're away then set our away message */ + status = purple_account_get_active_status(irc->account); + if (!purple_status_get_type(status) != PURPLE_STATUS_AVAILABLE) { + PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); + prpl_info->set_status(irc->account, status); + } + + /* this used to be in the core, but it's not now */ + for (gnode = purple_get_blist()->root; gnode; gnode = gnode->next) { + if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) + continue; + for(cnode = gnode->child; cnode; cnode = cnode->next) { + if(!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) + continue; + for(bnode = cnode->child; bnode; bnode = bnode->next) { + PurpleBuddy *b; + if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) + continue; + b = (PurpleBuddy *)bnode; + if(b->account == gc->account) { + struct irc_buddy *ib = g_new0(struct irc_buddy, 1); + ib->name = g_strdup(b->name); + g_hash_table_insert(irc->buddies, ib->name, ib); + } + } + } + } + + irc_blist_timeout(irc); + if (!irc->timer) + irc->timer = purple_timeout_add(45000, (GSourceFunc)irc_blist_timeout, (gpointer)irc); +} + void irc_msg_default(struct irc_conn *irc, const char *name, const char *from, char **args) { purple_debug(PURPLE_DEBUG_INFO, "irc", "Unrecognized message: %s\n", args[0]); @@ -95,56 +142,16 @@ void irc_msg_luser(struct irc_conn *irc, const char *name, const char *from, char **args) { - PurpleConnection *gc; - PurpleStatus *status; - PurpleBlistNode *gnode, *cnode, *bnode; - - if (!args || !args[0] || !args[1]) - return; - - gc = purple_account_get_connection(irc->account); - if (!gc) + if (!args || !args[0]) return; if (!strcmp(name, "251")) { - /* 251 is required, so we pluck our nick from here */ - purple_connection_set_display_name(gc, args[0]); + /* 251 is required, so we pluck our nick from here and + * finalize connection */ + irc_connected(irc, args[0]); /* Some IRC servers seem to not send a 255 numeric, so * I guess we can't require it; 251 will do. */ /* } else if (!strcmp(name, "255")) { */ - purple_connection_set_state(gc, PURPLE_CONNECTED); - - /* If we're away then set our away message */ - status = purple_account_get_active_status(irc->account); - if (!purple_status_get_type(status) != PURPLE_STATUS_AVAILABLE) { - PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl); - prpl_info->set_status(irc->account, status); - } - - /* this used to be in the core, but it's not now */ - for (gnode = purple_get_blist()->root; gnode; gnode = gnode->next) { - if(!PURPLE_BLIST_NODE_IS_GROUP(gnode)) - continue; - for(cnode = gnode->child; cnode; cnode = cnode->next) { - if(!PURPLE_BLIST_NODE_IS_CONTACT(cnode)) - continue; - for(bnode = cnode->child; bnode; bnode = bnode->next) { - PurpleBuddy *b; - if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode)) - continue; - b = (PurpleBuddy *)bnode; - if(b->account == gc->account) { - struct irc_buddy *ib = g_new0(struct irc_buddy, 1); - ib->name = g_strdup(b->name); - g_hash_table_insert(irc->buddies, ib->name, ib); - } - } - } - } - - irc_blist_timeout(irc); - if (!irc->timer) - irc->timer = purple_timeout_add(45000, (GSourceFunc)irc_blist_timeout, (gpointer)irc); } } @@ -523,6 +530,9 @@ { char *escaped; + if (!args || !args[0]) + return; + if (!irc->motd) irc->motd = g_string_new(""); @@ -532,7 +542,9 @@ irc->motd = g_string_new(""); return; } else if (!strcmp(name, "376")) { - /* We no longer have to do anything for ENDMOTD */ + /* dircproxy 1.0.5 does not send 251 on reconnection, so + * finalize the connection here if it is not already done. */ + irc_connected(irc, args[0]); return; } @@ -541,6 +553,9 @@ return; } + if (!args[1]) + return; + escaped = g_markup_escape_text(args[1], -1); g_string_append_printf(irc->motd, "%s
", escaped); g_free(escaped); diff -r b5935a854ccb -r 150980c9d79d libpurple/protocols/irc/parse.c --- a/libpurple/protocols/irc/parse.c Wed May 16 20:51:28 2007 +0000 +++ b/libpurple/protocols/irc/parse.c Thu May 17 07:29:26 2007 +0000 @@ -227,7 +227,7 @@ enclist = purple_account_get_string(irc->account, "encoding", IRC_DEFAULT_CHARSET); encodings = g_strsplit(enclist, ",", 2); - if (encodings[0] == NULL || !strcasecmp("UTF-8", encodings[0])) { + if (encodings[0] == NULL || !g_ascii_strcasecmp("UTF-8", encodings[0])) { g_strfreev(encodings); return g_strdup(string); } diff -r b5935a854ccb -r 150980c9d79d libpurple/util.c --- a/libpurple/util.c Wed May 16 20:51:28 2007 +0000 +++ b/libpurple/util.c Thu May 17 07:29:26 2007 +0000 @@ -3285,6 +3285,9 @@ gfud->inpa = 0; close(gfud->fd); gfud->fd = -1; + gfud->request_written = 0; + gfud->len = 0; + gfud->data_len = 0; g_free(gfud->website.user); g_free(gfud->website.passwd); @@ -3497,7 +3500,7 @@ } gfud->request_written += len; - if (gfud->request_written != total_len) + if (gfud->request_written < total_len) return; /* We're done writing our request, now start reading the response */ diff -r b5935a854ccb -r 150980c9d79d pidgin/gtkblist.c --- a/pidgin/gtkblist.c Wed May 16 20:51:28 2007 +0000 +++ b/pidgin/gtkblist.c Thu May 17 07:29:26 2007 +0000 @@ -327,7 +327,6 @@ GValue val; PurpleBlistNode *node; const char *text = NULL; - char *esc; path = gtk_tree_path_new_from_string (path_str); gtk_tree_model_get_iter (GTK_TREE_MODEL(gtkblist->treemodel), &iter, path); @@ -350,12 +349,10 @@ g_return_if_reached(); } - esc = g_markup_escape_text(text, -1); if (GTK_IS_ENTRY (editable)) { GtkEntry *entry = GTK_ENTRY (editable); - gtk_entry_set_text(entry, esc); - } - g_free(esc); + gtk_entry_set_text(entry, text); + } } static void gtk_blist_renderer_edited_cb(GtkCellRendererText *text_rend, char *arg1, @@ -3957,6 +3954,9 @@ g_free(primary); gtk_widget_destroy(GTK_WIDGET(widget)); g_hash_table_remove(gtkblist->connection_errors, account); + if (gtk_container_get_children(GTK_CONTAINER(gtkblist->error_buttons)) == NULL) { + gtk_widget_hide(gtkblist->error_buttons); + } } /* Add some buttons that show connection errors */ @@ -3977,7 +3977,7 @@ escaped); g_free(escaped); - hbox = gtk_hbox_new(FALSE, 0); + hbox = gtk_hbox_new(FALSE, 6); /* Create the icon */ if ((status_type = purple_account_get_status_type_with_primitive(account, @@ -3987,8 +3987,7 @@ image = gtk_image_new_from_pixbuf(pixbuf); g_object_unref(pixbuf); - gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, - PIDGIN_HIG_BOX_SPACE); + gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); } } @@ -3999,8 +3998,7 @@ #if GTK_CHECK_VERSION(2,6,0) g_object_set(label, "ellipsize", PANGO_ELLIPSIZE_END, NULL); #endif - gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, - PIDGIN_HIG_BOX_SPACE); + gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); /* Create the actual button and put the icon and text on it */ button = gtk_button_new(); @@ -4011,6 +4009,7 @@ gtk_widget_show_all(button); gtk_box_pack_end(GTK_BOX(gtkblist->error_buttons), button, FALSE, FALSE, 0); + gtk_widget_show_all(gtkblist->error_buttons); } void @@ -4476,7 +4475,8 @@ /* Create an empty vbox used for showing connection errors */ gtkblist->error_buttons = gtk_vbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->error_buttons, FALSE, FALSE, 0); - + gtk_container_set_border_width(GTK_CONTAINER(gtkblist->error_buttons), 3); + /* Add the statusbox */ gtkblist->statusbox = pidgin_status_box_new(); gtk_box_pack_start(GTK_BOX(gtkblist->vbox), gtkblist->statusbox, FALSE, TRUE, 0); @@ -4573,6 +4573,7 @@ gtkblist); gtk_widget_hide(gtkblist->headline_hbox); + gtk_widget_hide(gtkblist->error_buttons); /* emit our created signal */ purple_signal_emit(handle, "gtkblist-created", list); diff -r b5935a854ccb -r 150980c9d79d pidgin/gtkconv.c --- a/pidgin/gtkconv.c Wed May 16 20:51:28 2007 +0000 +++ b/pidgin/gtkconv.c Thu May 17 07:29:26 2007 +0000 @@ -176,6 +176,7 @@ static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); +static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); static GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { static GdkColor col; @@ -3976,6 +3977,12 @@ } else if (PURPLE_BLIST_NODE_IS_BUDDY(node)) update_chat_alias((PurpleBuddy *)node, conv, gc, prpl_info); + else if (PURPLE_BLIST_NODE_IS_CHAT(node) && + purple_conversation_get_account(conv) == ((PurpleChat*)node)->account) + { + if (old_alias == NULL || g_utf8_collate(old_alias, purple_conversation_get_title(conv)) == 0) + pidgin_conv_update_fields(conv, PIDGIN_CONV_SET_TITLE); + } } static void @@ -4590,6 +4597,18 @@ } } +static gboolean +ignore_middle_click(GtkWidget *widget, GdkEventButton *e, gpointer null) +{ + /* A click on the pane is propagated to the notebook containing the pane. + * So if Stu accidentally aims high and middle clicks on the pane-handle, + * it causes a conversation tab to close. Let's stop that from happening. + */ + if (e->button == 2 && e->type == GDK_BUTTON_PRESS) + return TRUE; + return FALSE; +} + /************************************************************************** * Conversation UI operations **************************************************************************/ @@ -4663,6 +4682,8 @@ te, sizeof(te) / sizeof(GtkTargetEntry), GDK_ACTION_COPY); + g_signal_connect(G_OBJECT(pane), "button_press_event", + G_CALLBACK(ignore_middle_click), NULL); g_signal_connect(G_OBJECT(pane), "drag_data_received", G_CALLBACK(conv_dnd_recv), gtkconv); g_signal_connect(G_OBJECT(gtkconv->imhtml), "drag_data_received", @@ -6512,16 +6533,18 @@ tab_side_pref_cb(const char *name, PurplePrefType type, gconstpointer value, gpointer data) { - GList *l; + GList *gtkwins, *gtkconvs; GtkPositionType pos; - PidginWindow *win; + PidginWindow *gtkwin; pos = GPOINTER_TO_INT(value); - for (l = pidgin_conv_windows_get_list(); l != NULL; l = l->next) { - win = l->data; - - gtk_notebook_set_tab_pos(GTK_NOTEBOOK(win->notebook), pos&~8); + for (gtkwins = pidgin_conv_windows_get_list(); gtkwins != NULL; gtkwins = gtkwins->next) { + gtkwin = gtkwins->data; + gtk_notebook_set_tab_pos(GTK_NOTEBOOK(gtkwin->notebook), pos&~8); + for (gtkconvs = gtkwin->gtkconvs; gtkconvs != NULL; gtkconvs = gtkconvs->next) { + pidgin_conv_tab_pack(gtkwin, gtkconvs->data); + } } } @@ -7385,8 +7408,7 @@ PidginWindow *dest_win; GtkNotebook *dest_notebook; GtkWidget *tab; - gint nb_x, nb_y, page_num; - gint arrow1_x, arrow1_y, arrow2_x, arrow2_y; + gint page_num; gboolean horiz_tabs = FALSE; PidginConversation *gtkconv; gboolean to_right = FALSE; @@ -7402,52 +7424,35 @@ dest_notebook = GTK_NOTEBOOK(dest_win->notebook); - gdk_window_get_origin(GTK_WIDGET(dest_notebook)->window, &nb_x, &nb_y); - - arrow1_x = arrow2_x = nb_x; - arrow1_y = arrow2_y = nb_y; - page_num = pidgin_conv_get_tab_at_xy(dest_win, e->x_root, e->y_root, &to_right); to_right = to_right && (win != dest_win); if (gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_TOP || - gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_BOTTOM) { - - horiz_tabs = TRUE; - } + gtk_notebook_get_tab_pos(dest_notebook) == GTK_POS_BOTTOM) { + horiz_tabs = TRUE; + } gtkconv = pidgin_conv_window_get_gtkconv_at_index(dest_win, page_num); tab = gtkconv->tabby; if (horiz_tabs) { - arrow1_x = arrow2_x = nb_x + tab->allocation.x; - if (((gpointer)win == (gpointer)dest_win && win->drag_tab < page_num) || to_right) { - arrow1_x += tab->allocation.width; - arrow2_x += tab->allocation.width; + dnd_hints_show_relative(HINT_ARROW_DOWN, tab, HINT_POSITION_RIGHT, HINT_POSITION_TOP); + dnd_hints_show_relative(HINT_ARROW_UP, tab, HINT_POSITION_RIGHT, HINT_POSITION_BOTTOM); + } else { + dnd_hints_show_relative(HINT_ARROW_DOWN, tab, HINT_POSITION_LEFT, HINT_POSITION_TOP); + dnd_hints_show_relative(HINT_ARROW_UP, tab, HINT_POSITION_LEFT, HINT_POSITION_BOTTOM); } - - arrow1_y = nb_y + tab->allocation.y; - arrow2_y = nb_y + tab->allocation.y + tab->allocation.height; } else { - arrow1_x = nb_x + tab->allocation.x; - arrow2_x = nb_x + tab->allocation.x + tab->allocation.width; - arrow1_y = arrow2_y = nb_y + tab->allocation.y; - if (((gpointer)win == (gpointer)dest_win && win->drag_tab < page_num) || to_right) { - arrow1_y += tab->allocation.height; - arrow2_y += tab->allocation.height; + dnd_hints_show_relative(HINT_ARROW_RIGHT, tab, HINT_POSITION_LEFT, HINT_POSITION_BOTTOM); + dnd_hints_show_relative(HINT_ARROW_LEFT, tab, HINT_POSITION_RIGHT, HINT_POSITION_BOTTOM); + } else { + dnd_hints_show_relative(HINT_ARROW_RIGHT, tab, HINT_POSITION_LEFT, HINT_POSITION_TOP); + dnd_hints_show_relative(HINT_ARROW_LEFT, tab, HINT_POSITION_RIGHT, HINT_POSITION_TOP); } } - - if (horiz_tabs) { - dnd_hints_show(HINT_ARROW_DOWN, arrow1_x, arrow1_y); - dnd_hints_show(HINT_ARROW_UP, arrow2_x, arrow2_y); - } else { - dnd_hints_show(HINT_ARROW_RIGHT, arrow1_x, arrow1_y); - dnd_hints_show(HINT_ARROW_LEFT, arrow2_x, arrow2_y); - } } return TRUE; @@ -7812,6 +7817,105 @@ } static void +remove_edit_entry(PidginConversation *gtkconv, GtkWidget *entry) +{ + g_signal_handlers_disconnect_matched(G_OBJECT(entry), G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, gtkconv); + gtk_widget_show(gtkconv->tab_label); + gtk_widget_grab_focus(gtkconv->entry); + gtk_widget_destroy(entry); +} + +static gboolean +alias_focus_cb(GtkWidget *widget, GdkEventFocus *event, gpointer user_data) +{ + remove_edit_entry(user_data, widget); + return FALSE; +} + +static gboolean +alias_key_press_cb(GtkWidget *widget, GdkEventKey *event, gpointer user_data) +{ + if (event->keyval == GDK_Escape) { + remove_edit_entry(user_data, widget); + return TRUE; + } + return FALSE; +} + +static void +alias_cb(GtkEntry *entry, gpointer user_data) +{ + PidginConversation *gtkconv; + PurpleConversation *conv; + PurpleAccount *account; + const char *name; + + gtkconv = (PidginConversation *)user_data; + if (gtkconv == NULL) { + return; + } + conv = gtkconv->active_conv; + account = purple_conversation_get_account(conv); + name = purple_conversation_get_name(conv); + + if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { + PurpleBuddy *buddy; + buddy = purple_find_buddy(account, name); + if (buddy != NULL) { + purple_blist_alias_buddy(buddy, + gtk_entry_get_text(entry)); + } + serv_alias_buddy(buddy); + } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { + PurpleChat *chat; + + chat = purple_blist_find_chat(account, name); + if (chat != NULL) { + purple_blist_alias_chat(chat, + gtk_entry_get_text(entry)); + } + } + remove_edit_entry(user_data, GTK_WIDGET(entry)); +} + +static gboolean +alias_double_click_cb(GtkNotebook *notebook, GdkEventButton *event, PidginConversation *gtkconv) +{ + GtkWidget *entry = NULL; + + if (event->button != 1 || event->type != GDK_2BUTTON_PRESS) { + return FALSE; + } + + if (!GTK_WIDGET_VISIBLE(gtkconv->tab_label)) { + /* There's already an entry for alias. Let's not create another one. */ + return FALSE; + } + + /* alias label */ + entry = gtk_entry_new(); + gtk_entry_set_has_frame(GTK_ENTRY(entry), FALSE); + gtk_entry_set_width_chars(GTK_ENTRY(entry), 10); + gtk_entry_set_alignment(GTK_ENTRY(entry), 0.5); + + gtk_box_pack_start(GTK_BOX(gtkconv->tabby), entry, TRUE, TRUE, 0); + /* after the tab label */ + gtk_box_reorder_child(GTK_BOX(gtkconv->tabby), entry, 2); + + g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(alias_cb), gtkconv); + g_signal_connect(G_OBJECT(entry), "focus-out-event", G_CALLBACK(alias_focus_cb), gtkconv); + g_signal_connect(G_OBJECT(entry), "key-press-event", G_CALLBACK(alias_key_press_cb), gtkconv); + gtk_entry_set_text(GTK_ENTRY(entry), + gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); + gtk_widget_show(entry); + gtk_widget_hide(gtkconv->tab_label); + gtk_widget_grab_focus(entry); + + return FALSE; +} + +static void switch_conv_cb(GtkNotebook *notebook, GtkWidget *page, gint page_num, gpointer user_data) { @@ -8056,35 +8160,17 @@ { PurpleConversation *conv = gtkconv->active_conv; PidginConversation *focus_gtkconv; - GtkWidget *tabby, *menu_tabby; GtkWidget *tab_cont = gtkconv->tab_cont; GtkWidget *close_image; PurpleConversationType conv_type; const gchar *tmp_lab; gint close_button_width, close_button_height, focus_width, focus_pad; - gboolean tabs_side = FALSE; - gint angle = 0; conv_type = purple_conversation_get_type(conv); - win->gtkconvs = g_list_append(win->gtkconvs, gtkconv); gtkconv->win = win; - if (purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_LEFT || - purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_RIGHT) - tabs_side = TRUE; - else if (purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == (GTK_POS_LEFT|8)) - angle = 90; - else if (purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == (GTK_POS_RIGHT|8)) - angle = 270; - - if (angle) - gtkconv->tabby = tabby = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - else - gtkconv->tabby = tabby = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - gtkconv->menu_tabby = menu_tabby = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); - /* Close button. */ gtkconv->close = gtk_button_new(); gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &close_button_width, &close_button_height); @@ -8128,56 +8214,25 @@ /* Tab label. */ gtkconv->tab_label = gtk_label_new(tmp_lab = purple_conversation_get_title(conv)); -#if GTK_CHECK_VERSION(2,6,0) - if (!angle) - g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_END, NULL); - gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), 6); - if (tabs_side) { - gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), MIN(g_utf8_strlen(tmp_lab, -1), 12)); - } - if (angle) - gtk_label_set_angle(GTK_LABEL(gtkconv->tab_label), angle); -#endif - gtkconv->menu_label = gtk_label_new(purple_conversation_get_title(conv)); -#if 0 - gtk_misc_set_alignment(GTK_MISC(gtkconv->tab_label), 0.00, 0.5); - gtk_misc_set_padding(GTK_MISC(gtkconv->tab_label), 4, 0); -#endif - - /* Pack it all together. */ - if (angle == 90) - gtk_box_pack_start(GTK_BOX(tabby), gtkconv->close, FALSE, FALSE, 0); - else - gtk_box_pack_start(GTK_BOX(tabby), gtkconv->icon, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(menu_tabby), gtkconv->menu_icon, - FALSE, FALSE, 0); - - gtk_widget_show_all(gtkconv->icon); + gtkconv->menu_tabby = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + gtkconv->menu_label = gtk_label_new(purple_conversation_get_title(gtkconv->active_conv)); + gtk_box_pack_start(GTK_BOX(gtkconv->menu_tabby), gtkconv->menu_icon, FALSE, FALSE, 0); + gtk_widget_show_all(gtkconv->menu_icon); - gtk_box_pack_start(GTK_BOX(tabby), gtkconv->tab_label, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(menu_tabby), gtkconv->menu_label, TRUE, TRUE, 0); - gtk_widget_show(gtkconv->tab_label); + gtk_box_pack_start(GTK_BOX(gtkconv->menu_tabby), gtkconv->menu_label, TRUE, TRUE, 0); gtk_widget_show(gtkconv->menu_label); gtk_misc_set_alignment(GTK_MISC(gtkconv->menu_label), 0, 0); - if (angle == 90) - gtk_box_pack_start(GTK_BOX(tabby), gtkconv->icon, FALSE, FALSE, 0); - else - gtk_box_pack_start(GTK_BOX(tabby), gtkconv->close, FALSE, FALSE, 0); - if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs")) - gtk_widget_show(gtkconv->close); - - gtk_widget_show(tabby); - gtk_widget_show(menu_tabby); + gtk_widget_show(gtkconv->menu_tabby); if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) pidgin_conv_update_buddy_icon(conv); - /* Add this pane to the conversation's notebook. */ - gtk_notebook_append_page_menu(GTK_NOTEBOOK(win->notebook), tab_cont, tabby, menu_tabby); - gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), tab_cont, !tabs_side && !angle, TRUE, GTK_PACK_START); - + /* Build and set conversations tab */ + pidgin_conv_tab_pack(win, gtkconv); + + gtk_notebook_set_menu_label(GTK_NOTEBOOK(win->notebook), tab_cont, gtkconv->menu_tabby); gtk_widget_show(tab_cont); @@ -8198,6 +8253,94 @@ update_send_to_selection(win); } +static void +pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv) +{ + gboolean tabs_side = FALSE; + gint angle = 0; + GtkWidget *first, *third, *ebox; + + if (purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_LEFT || + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_RIGHT) + tabs_side = TRUE; + else if (purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == (GTK_POS_LEFT|8)) + angle = 90; + else if (purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == (GTK_POS_RIGHT|8)) + angle = 270; + +#if GTK_CHECK_VERSION(2,6,0) + if (!angle) + g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_END, NULL); + else + g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_NONE, NULL); + gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), 6); + if (tabs_side) { + gtk_label_set_width_chars( + GTK_LABEL(gtkconv->tab_label), + MIN(g_utf8_strlen(gtk_label_get_text(GTK_LABEL(gtkconv->tab_label)), -1), 12) + ); + } + if (angle) + gtk_label_set_angle(GTK_LABEL(gtkconv->tab_label), angle); +#endif + +#if 0 + gtk_misc_set_alignment(GTK_MISC(gtkconv->tab_label), 0.00, 0.5); + gtk_misc_set_padding(GTK_MISC(gtkconv->tab_label), 4, 0); +#endif + + if (angle) + gtkconv->tabby = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + else + gtkconv->tabby = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); + + /* select the correct ordering for verticle tabs */ + if (angle == 90) { + first = gtkconv->close; + third = gtkconv->icon; + } else { + first = gtkconv->icon; + third = gtkconv->close; + } + + ebox = gtk_event_box_new(); + gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE); + gtk_container_add(GTK_CONTAINER(ebox), gtkconv->tabby); + g_signal_connect(G_OBJECT(ebox), "button-press-event", + G_CALLBACK(alias_double_click_cb), gtkconv); + + if (gtkconv->tab_label->parent == NULL) { + /* Pack if it's a new widget */ + gtk_box_pack_start(GTK_BOX(gtkconv->tabby), first, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(gtkconv->tabby), gtkconv->tab_label, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(gtkconv->tabby), third, FALSE, FALSE, 0); + + /* Add this pane to the conversation's notebook. */ + gtk_notebook_append_page(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, ebox); + } else { + /* reparent old widgets on preference changes */ + gtk_widget_reparent(first, gtkconv->tabby); + gtk_widget_reparent(gtkconv->tab_label, gtkconv->tabby); + gtk_widget_reparent(third, gtkconv->tabby); + gtk_box_set_child_packing(GTK_BOX(gtkconv->tabby), first, FALSE, FALSE, 0, GTK_PACK_START); + gtk_box_set_child_packing(GTK_BOX(gtkconv->tabby), gtkconv->tab_label, TRUE, TRUE, 0, GTK_PACK_START); + gtk_box_set_child_packing(GTK_BOX(gtkconv->tabby), third, FALSE, FALSE, 0, GTK_PACK_START); + + /* Reset the tabs label to the new version */ + gtk_notebook_set_tab_label(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, ebox); + } + + gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, !tabs_side && !angle, TRUE, GTK_PACK_START); + + /* show the widgets */ + gtk_widget_show(gtkconv->icon); + gtk_widget_show(gtkconv->tab_label); + if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs")) + gtk_widget_show(gtkconv->close); + gtk_widget_show(gtkconv->tabby); + gtk_widget_show(ebox); +} + void pidgin_conv_window_remove_gtkconv(PidginWindow *win, PidginConversation *gtkconv) { diff -r b5935a854ccb -r 150980c9d79d pidgin/gtkdnd-hints.c --- a/pidgin/gtkdnd-hints.c Wed May 16 20:51:28 2007 +0000 +++ b/pidgin/gtkdnd-hints.c Thu May 17 07:29:26 2007 +0000 @@ -91,8 +91,6 @@ if (w->parent && w->parent->window == w->window) { get_widget_coords(w->parent, &ox, &oy, NULL, NULL); - ox += w->allocation.x; - oy += w->allocation.y; height = w->allocation.height; width = w->allocation.width; } @@ -174,6 +172,8 @@ gint x = 0, y = 0; get_widget_coords(widget, &x1, &y1, &x2, &y2); + x1 += widget->allocation.x; x2 += widget->allocation.x; + y1 += widget->allocation.y; y2 += widget->allocation.y; switch (horiz) { diff -r b5935a854ccb -r 150980c9d79d pidgin/gtkidle.c --- a/pidgin/gtkidle.c Wed May 16 20:51:28 2007 +0000 +++ b/pidgin/gtkidle.c Thu May 17 07:29:26 2007 +0000 @@ -103,14 +103,21 @@ /* Query xscreensaver */ static XScreenSaverInfo *mit_info = NULL; + static int has_extension = -1; int event_base, error_base; - if (XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, &error_base)) { - if (mit_info == NULL) { + + if (has_extension == -1) + has_extension = XScreenSaverQueryExtension(GDK_DISPLAY(), &event_base, &error_base); + + if (has_extension) + { + if (mit_info == NULL) mit_info = XScreenSaverAllocInfo(); - } + XScreenSaverQueryInfo(GDK_DISPLAY(), GDK_ROOT_WINDOW(), mit_info); return (mit_info->idle) / 1000; - } else + } + else return 0; # endif /* !_WIN32 */ # endif /* !HAVE_IOKIT */ diff -r b5935a854ccb -r 150980c9d79d pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Wed May 16 20:51:28 2007 +0000 +++ b/pidgin/gtkimhtml.c Thu May 17 07:29:26 2007 +0000 @@ -3388,7 +3388,7 @@ return FALSE; pix = gdk_pixbuf_animation_get_static_image(anim); - image = gtk_imhtml_image_new(pix, NULL, 0); + image = gtk_imhtml_image_new(pix, smiley->smile, 0); ret = gtk_imhtml_image_clicked(w, event, (GtkIMHtmlImage*)image); g_object_set_data_full(G_OBJECT(w), "image-data", image, (GDestroyNotify)gtk_imhtml_image_free); g_object_unref(G_OBJECT(pix));