# HG changeset patch # User Yoshiki Yazawa # Date 1291818846 -32400 # Node ID 62f6e6796e482e6822009e8f4d827db2347bbc95 # Parent 4635d84e329221ca38b74da2e0e7656329db360c# Parent a78e05f6fe253d69938d2e9fbcfd20c0aa8116a9 merged from im.pidgin.pidgin diff -r 4635d84e3292 -r 62f6e6796e48 ChangeLog --- a/ChangeLog Thu Dec 02 20:17:37 2010 +0900 +++ b/ChangeLog Wed Dec 08 23:34:06 2010 +0900 @@ -10,6 +10,8 @@ of smileys, display the text representation of the smiley properly when it contains HTML-escapable characters (e.g. "<3" was previously displayed as "<3"). + * Drop dependency on GdkGC and use Cairo instead. + * New UI hack to assist in first-time setup of Facebook accounts. libpurple: * Fix multipart parsing when '=' is included in the boundary for @@ -30,7 +32,11 @@ characters. (#8508) * Fix receiving messages from users on Yahoo and other federated services. (#13022) - * Correctly remove old endpoints when they sign out. + * Correctly remove old endpoints from the list when they sign out. + * Add option to disable connections from multiple locations. (#13017) + + XMPP: + * Terminate Jingle sessions with unsupported content types. (#13048) version 2.7.7 (11/23/2010): General: diff -r 4635d84e3292 -r 62f6e6796e48 libpurple/protocols/jabber/jingle/jingle.c --- a/libpurple/protocols/jabber/jingle/jingle.c Thu Dec 02 20:17:37 2010 +0900 +++ b/libpurple/protocols/jabber/jingle/jingle.c Wed Dec 08 23:34:06 2010 +0900 @@ -98,7 +98,8 @@ if (pending_content == NULL) { purple_debug_error("jingle", "Error parsing \"content-add\" content.\n"); - /* XXX: send error here */ + jabber_iq_send(jingle_session_terminate_packet(session, + "unsupported-applications")); } else { jingle_session_add_pending_content(session, pending_content); @@ -127,7 +128,8 @@ g_free(local_senders); } else { purple_debug_error("jingle", "content_modify: unknown content\n"); - /* XXX: send error */ + jabber_iq_send(jingle_session_terminate_packet(session, + "unknown-applications")); } } } @@ -176,7 +178,8 @@ jingle_session_find_content(session, name, creator); if (parsed_content == NULL) { purple_debug_error("jingle", "Error parsing content\n"); - /* XXX: send error */ + jabber_iq_send(jingle_session_terminate_packet(session, + "unsupported-applications")); } else { jingle_content_handle_action(parsed_content, content, JINGLE_DESCRIPTION_INFO); @@ -206,7 +209,8 @@ jingle_session_find_content(session, name, creator); if (parsed_content == NULL) { purple_debug_error("jingle", "Error parsing content\n"); - /* XXX: send error */ + jabber_iq_send(jingle_session_terminate_packet(session, + "unsupported-applications")); } else { jingle_content_handle_action(parsed_content, content, JINGLE_SESSION_ACCEPT); @@ -230,7 +234,8 @@ JingleContent *parsed_content = jingle_content_parse(content); if (parsed_content == NULL) { purple_debug_error("jingle", "Error parsing content\n"); - /* XXX: send error */ + jabber_iq_send(jingle_session_terminate_packet(session, + "unsupported-applications")); } else { jingle_session_add_content(session, parsed_content); jingle_content_handle_action(parsed_content, content, @@ -281,7 +286,8 @@ jingle_session_find_content(session, name, creator); if (parsed_content == NULL) { purple_debug_error("jingle", "Error parsing content\n"); - /* XXX: send error */ + jabber_iq_send(jingle_session_terminate_packet(session, + "unsupported-applications")); } else { jingle_content_handle_action(parsed_content, content, JINGLE_TRANSPORT_INFO); diff -r 4635d84e3292 -r 62f6e6796e48 libpurple/protocols/msn/contact.c --- a/libpurple/protocols/msn/contact.c Thu Dec 02 20:17:37 2010 +0900 +++ b/libpurple/protocols/msn/contact.c Wed Dec 08 23:34:06 2010 +0900 @@ -190,6 +190,8 @@ strcat(buf, "Renaming Group,"); if (action & MSN_UPDATE_INFO) strcat(buf, "Updating Contact Info,"); + if (action & MSN_ANNOTATE_USER) + strcat(buf, "Annotating Contact,"); return buf; } @@ -730,9 +732,9 @@ value = xmlnode_get_data(xmlnode_get_child(annotation, "Value")); if (!strcmp(name, "MSN.IM.MPOP")) { if (!value || atoi(value) != 0) - purple_account_set_bool(session->account, "mpop", TRUE); + session->enable_mpop = TRUE; else - purple_account_set_bool(session->account, "mpop", FALSE); + session->enable_mpop = FALSE; } g_free(name); g_free(value); @@ -1533,6 +1535,97 @@ } static void +msn_annotate_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, + gpointer data) +{ + MsnCallbackState *state = (MsnCallbackState *)data; + xmlnode *fault; + + /* We don't know how to respond to this faultcode, so log it */ + fault = xmlnode_get_child(resp->xml, "Body/Fault"); + if (fault != NULL) { + char *fault_str = xmlnode_to_str(fault, NULL); + purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n", + msn_contact_operation_str(state->action), fault_str); + g_free(fault_str); + return; + } + + purple_debug_info("msn", "Contact annotated successfully\n"); +} + +/* Update a contact's annotations */ +void +msn_annotate_contact(MsnSession *session, const char *passport, ...) +{ + va_list params; + MsnCallbackState *state; + xmlnode *contact; + xmlnode *contact_info; + xmlnode *annotations; + MsnUser *user = NULL; + + g_return_if_fail(passport != NULL); + + if (strcmp(passport, "Me") != 0) { + user = msn_userlist_find_user(session->userlist, passport); + if (!user) + return; + } + + contact_info = xmlnode_new("contactInfo"); + annotations = xmlnode_new_child(contact_info, "annotations"); + + va_start(params, passport); + while (TRUE) { + const char *name; + const char *value; + xmlnode *a, *n, *v; + + name = va_arg(params, const char *); + if (!name) + break; + + value = va_arg(params, const char *); + if (!value) + break; + + a = xmlnode_new_child(annotations, "Annotation"); + n = xmlnode_new_child(a, "Name"); + xmlnode_insert_data(n, name, -1); + v = xmlnode_new_child(a, "Value"); + xmlnode_insert_data(v, value, -1); + } + va_end(params); + + state = msn_callback_state_new(session); + + state->body = xmlnode_from_str(MSN_CONTACT_ANNOTATE_TEMPLATE, -1); + state->action = MSN_ANNOTATE_USER; + state->post_action = MSN_CONTACT_ANNOTATE_SOAP_ACTION; + state->post_url = MSN_ADDRESS_BOOK_POST_URL; + state->cb = msn_annotate_contact_read_cb; + + xmlnode_insert_data(xmlnode_get_child(state->body, + "Header/ABApplicationHeader/PartnerScenario"), + MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1); + + contact = xmlnode_get_child(state->body, "Body/ABContactUpdate/contacts/Contact"); + xmlnode_insert_child(contact, contact_info); + + if (user) { + xmlnode *contactId = xmlnode_new_child(contact, "contactId"); + msn_callback_state_set_uid(state, user->uid); + xmlnode_insert_data(contactId, state->uid, -1); + } else { + xmlnode *contactType = xmlnode_new_child(contact_info, "contactType"); + xmlnode_insert_data(contactType, "Me", -1); + } + + msn_contact_request(state); +} + +static void msn_del_contact_from_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data) { diff -r 4635d84e3292 -r 62f6e6796e48 libpurple/protocols/msn/contact.h --- a/libpurple/protocols/msn/contact.h Thu Dec 02 20:17:37 2010 +0900 +++ b/libpurple/protocols/msn/contact.h Wed Dec 08 23:34:06 2010 +0900 @@ -36,7 +36,8 @@ MSN_ADD_GROUP = 0x10, MSN_DEL_GROUP = 0x20, MSN_RENAME_GROUP = 0x40, - MSN_UPDATE_INFO = 0x80 + MSN_UPDATE_INFO = 0x80, + MSN_ANNOTATE_USER = 0x100 } MsnCallbackAction; typedef enum @@ -428,6 +429,37 @@ ""\ "" +/* Update Contact Annotations */ +#define MSN_CONTACT_ANNOTATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" +#define MSN_CONTACT_ANNOTATE_TEMPLATE ""\ +""\ + ""\ + ""\ + "" MSN_APPLICATION_ID ""\ + "false"\ + ""\ + ""\ + ""\ + "false"\ + "EMPTY"\ + ""\ + ""\ + ""\ + ""\ + "00000000-0000-0000-0000-000000000000"\ + ""\ + ""\ + "Annotation"\ + ""\ + ""\ + ""\ + ""\ +"" + /******************************************************* * Add/Delete contact from lists SOAP actions *******************************************************/ @@ -687,6 +719,8 @@ /* contact SOAP operations */ void msn_update_contact(MsnSession *session, const char *passport, MsnContactUpdateType type, const char* value); +void msn_annotate_contact(MsnSession *session, const char *passport, ...) G_GNUC_NULL_TERMINATED; + void msn_add_contact(MsnSession *session, MsnCallbackState *state, const char *passport); void msn_delete_contact(MsnSession *session, MsnUser *user); diff -r 4635d84e3292 -r 62f6e6796e48 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Thu Dec 02 20:17:37 2010 +0900 +++ b/libpurple/protocols/msn/msn.c Wed Dec 08 23:34:06 2010 +0900 @@ -616,6 +616,67 @@ } static void +enable_mpop_cb(PurpleConnection *pc) +{ + MsnSession *session = purple_connection_get_protocol_data(pc); + + purple_debug_info("msn", "Enabling MPOP\n"); + + session->enable_mpop = TRUE; + msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "1", NULL); + + purple_prpl_got_account_actions(purple_connection_get_account(pc)); +} + +static void +disable_mpop_cb(PurpleConnection *pc) +{ + PurpleAccount *account = purple_connection_get_account(pc); + MsnSession *session = purple_connection_get_protocol_data(pc); + GSList *l; + + purple_debug_info("msn", "Disabling MPOP\n"); + + session->enable_mpop = FALSE; + msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "0", NULL); + + for (l = session->user->endpoints; l; l = l->next) { + MsnUserEndpoint *ep = l->data; + char *user; + + if (ep->id[0] != '\0' && strncasecmp(ep->id + 1, session->guid, 36) == 0) + /* Don't kick myself */ + continue; + + purple_debug_info("msn", "Disconnecting Endpoint %s\n", ep->id); + + user = g_strdup_printf("%s;%s", purple_account_get_username(account), ep->id); + msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye"); + g_free(user); + } + + purple_prpl_got_account_actions(account); +} + +static void +msn_show_set_mpop(PurplePluginAction *action) +{ + PurpleConnection *pc; + + pc = (PurpleConnection *)action->context; + + purple_request_action(pc, NULL, _("Allow multiple logins?"), + _("Do you want to allow or disallow connecting from " + "multiple locations simultaneously?"), + PURPLE_DEFAULT_ACTION_NONE, + purple_connection_get_account(pc), NULL, NULL, + pc, 3, + _("Allow"), G_CALLBACK(enable_mpop_cb), + _("Disallow"), G_CALLBACK(disable_mpop_cb), + _("Cancel"), NULL); +} + +static void msn_show_set_home_phone(PurplePluginAction *action) { PurpleConnection *gc; @@ -1200,8 +1261,7 @@ m = g_list_append(m, act); m = g_list_append(m, NULL); - if (purple_account_get_bool(session->account, "mpop", TRUE) - && session->protocol_ver >= 16) + if (session->enable_mpop && session->protocol_ver >= 16) { act = purple_plugin_action_new(_("View Locations..."), msn_show_locations); @@ -1228,6 +1288,10 @@ m = g_list_append(m, act); #endif + act = purple_plugin_action_new(_("Allow/Disallow Multiple Logins..."), + msn_show_set_mpop); + m = g_list_append(m, act); + act = purple_plugin_action_new(_("Allow/Disallow Mobile Pages..."), msn_show_set_mobile_pages); m = g_list_append(m, act); diff -r 4635d84e3292 -r 62f6e6796e48 libpurple/protocols/msn/msnutils.c --- a/libpurple/protocols/msn/msnutils.c Thu Dec 02 20:17:37 2010 +0900 +++ b/libpurple/protocols/msn/msnutils.c Wed Dec 08 23:34:06 2010 +0900 @@ -182,29 +182,40 @@ * We need this because we're only supposed to encode spaces in the font * names. purple_url_encode() isn't acceptable. */ -static const char * -encode_spaces(const char *str) +gboolean +msn_encode_spaces(const char *str, char *buf, size_t len) { - static char buf[BUF_LEN]; - const char *c; - char *d; + char *nonspace = buf; - g_return_val_if_fail(str != NULL, NULL); + while (isspace(*str)) + str++; - for (c = str, d = buf; *c != '\0'; c++) - { - if (*c == ' ') - { - *d++ = '%'; - *d++ = '2'; - *d++ = '0'; + for (; *str && len > 1; str++) { + if (*str == '%') { + if (len < 4) + break; + *buf++ = '%'; + *buf++ = '2'; + *buf++ = '5'; + len -= 3; + nonspace = buf; + } else if (*str == ' ') { + if (len < 4) + break; + *buf++ = '%'; + *buf++ = '2'; + *buf++ = '0'; + len -= 3; + } else { + *buf++ = *str; + len--; + nonspace = buf; } - else - *d++ = *c; } - *d = '\0'; - return buf; + *nonspace = '\0'; + + return (*str == '\0'); } /* @@ -223,6 +234,7 @@ const char *c; char *msg; char *fontface = NULL; + char fontface_encoded[BUF_LEN]; char fonteffect[5]; char fontcolor[7]; char direction = '0'; @@ -449,8 +461,9 @@ if (fontface == NULL) fontface = g_strdup("Segoe UI"); + msn_encode_spaces(fontface, fontface_encoded, BUF_LEN); *attributes = g_strdup_printf("FN=%s; EF=%s; CO=%s; PF=0; RL=%c", - encode_spaces(fontface), + fontface_encoded, fonteffect, fontcolor, direction); *message = msg; diff -r 4635d84e3292 -r 62f6e6796e48 libpurple/protocols/msn/msnutils.h --- a/libpurple/protocols/msn/msnutils.h Thu Dec 02 20:17:37 2010 +0900 +++ b/libpurple/protocols/msn/msnutils.h Wed Dec 08 23:34:06 2010 +0900 @@ -33,6 +33,18 @@ char *rand_guid(void); /** + * Encodes the spaces in a string + * + * @param str The string to be encoded. + * @param buf The buffer to hold the encoded string. + * @param len The maximum length (including NUL) to put in @buf. + * + * @return Whether @str was able to fit in @buf. + */ +gboolean +msn_encode_spaces(const char *str, char *buf, size_t len); + +/** * Parses the MSN message formatting into a format compatible with Purple. * * @param mime The mime header with the formatting. diff -r 4635d84e3292 -r 62f6e6796e48 libpurple/protocols/msn/notification.c --- a/libpurple/protocols/msn/notification.c Thu Dec 02 20:17:37 2010 +0900 +++ b/libpurple/protocols/msn/notification.c Wed Dec 08 23:34:06 2010 +0900 @@ -1572,7 +1572,7 @@ /* Disconnect others, if MPOP is disabled */ if (is_me - && !purple_account_get_bool(session->account, "mpop", TRUE) + && !session->enable_mpop && strncasecmp(id + 1, session->guid, 36) != 0) { purple_debug_info("msn", "Disconnecting Endpoint %s\n", id); @@ -1599,7 +1599,7 @@ } } - if (is_me && purple_account_get_bool(session->account, "mpop", TRUE)) { + if (is_me && session->enable_mpop) { for (epNode = xmlnode_get_child(payloadNode, "PrivateEndpointData"); epNode; epNode = xmlnode_get_next_twin(epNode)) { diff -r 4635d84e3292 -r 62f6e6796e48 libpurple/protocols/msn/session.c --- a/libpurple/protocols/msn/session.c Thu Dec 02 20:17:37 2010 +0900 +++ b/libpurple/protocols/msn/session.c Wed Dec 08 23:34:06 2010 +0900 @@ -49,6 +49,7 @@ session->oim = msn_oim_new(session); session->protocol_ver = 0; + session->enable_mpop = TRUE; /* Default only */ session->guid = rand_guid(); diff -r 4635d84e3292 -r 62f6e6796e48 libpurple/protocols/msn/session.h --- a/libpurple/protocols/msn/session.h Thu Dec 02 20:17:37 2010 +0900 +++ b/libpurple/protocols/msn/session.h Wed Dec 08 23:34:06 2010 +0900 @@ -83,6 +83,7 @@ gboolean logged_in:1; /**< A temporal flag to ignore local buddy list adds. */ gboolean destroying:1; /**< A flag that states if the session is being destroyed. */ gboolean http_method:1; + gboolean enable_mpop:1; /**< Use Multiple Points of Presence? */ int adl_fqy; /**< A count of ADL/FQY so status is only changed once. */ guint login_timeout; /**< Timeout to force status change if ADL/FQY fail. */ diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/Makefile.mingw --- a/pidgin/Makefile.mingw Thu Dec 02 20:17:37 2010 +0900 +++ b/pidgin/Makefile.mingw Wed Dec 08 23:34:06 2010 +0900 @@ -121,6 +121,7 @@ -lz \ -lgtk-win32-2.0 \ -latk-1.0 \ + -lcairo \ -lpango-1.0 \ -lgdk-win32-2.0 \ -lgdk_pixbuf-2.0 \ diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/gtkaccount.c --- a/pidgin/gtkaccount.c Thu Dec 02 20:17:37 2010 +0900 +++ b/pidgin/gtkaccount.c Wed Dec 08 23:34:06 2010 +0900 @@ -559,10 +559,14 @@ /* Google Talk default domain hackery! */ menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu)); item = gtk_menu_get_active(GTK_MENU(menu)); - if (value == NULL && g_object_get_data(G_OBJECT(item), "fake") && + if (value == NULL && g_object_get_data(G_OBJECT(item), "fakegoogle") && !strcmp(purple_account_user_split_get_text(split), _("Domain"))) value = "gmail.com"; + if (value == NULL && g_object_get_data(G_OBJECT(item), "fakefacebook") && + !strcmp(purple_account_user_split_get_text(split), _("Domain"))) + value = "chat.facebook.com"; + if (value != NULL) gtk_entry_set_text(GTK_ENTRY(entry), value); } @@ -758,7 +762,7 @@ { PurpleAccountOption *option; PurpleAccount *account; - GtkWidget *vbox, *check, *entry, *combo; + GtkWidget *vbox, *check, *entry, *combo, *menu, *item; GList *list, *node; gint i, idx, int_value; GtkListStore *model; @@ -797,6 +801,9 @@ gtk_label_new_with_mnemonic(_("Ad_vanced")), 1); gtk_widget_show(vbox); + menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu)); + item = gtk_menu_get_active(GTK_MENU(menu)); + for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next) { option = (PurpleAccountOption *)l->data; @@ -911,6 +918,10 @@ model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER); opt_entry->widget = combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model)); + if (g_object_get_data(G_OBJECT(item), "fakefacebook") && + !strcmp(opt_entry->setting, "connection_security")) + str_value = "opportunistic_tls"; + /* Loop through list of PurpleKeyValuePair items */ for (node = list; node != NULL; node = node->next) { if (node->data != NULL) { diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/gtkimhtml.c --- a/pidgin/gtkimhtml.c Thu Dec 02 20:17:37 2010 +0900 +++ b/pidgin/gtkimhtml.c Wed Dec 08 23:34:06 2010 +0900 @@ -762,7 +762,7 @@ GtkTextIter start, end, cur; int buf_x, buf_y; GdkRectangle visible_rect; - GdkGC *gc = gdk_gc_new(GDK_DRAWABLE(event->window)); + cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(event->window)); GdkColor gcolor; gtk_text_view_get_visible_rect(GTK_TEXT_VIEW(widget), &visible_rect); @@ -780,16 +780,16 @@ if (GTK_IMHTML(widget)->edit.background) { gdk_color_parse(GTK_IMHTML(widget)->edit.background, &gcolor); - gdk_gc_set_rgb_fg_color(gc, &gcolor); + gdk_cairo_set_source_color(cr, &gcolor); } else { - gdk_gc_set_rgb_fg_color(gc, &(widget->style->base[GTK_WIDGET_STATE(widget)])); + gdk_cairo_set_source_color(cr, &(widget->style->base[GTK_WIDGET_STATE(widget)])); } - gdk_draw_rectangle(event->window, - gc, - TRUE, - visible_rect.x, visible_rect.y, visible_rect.width, visible_rect.height); - g_object_unref(G_OBJECT(gc)); + cairo_rectangle(cr, + visible_rect.x, visible_rect.y, + visible_rect.width, visible_rect.height); + cairo_fill(cr); + cairo_destroy(cr); if (GTK_WIDGET_CLASS (parent_class)->expose_event) return (* GTK_WIDGET_CLASS (parent_class)->expose_event) @@ -860,12 +860,12 @@ if (!gdk_color_parse(tmp, &gcolor)) gdk_color_parse("white", &gcolor); } - gdk_gc_set_rgb_fg_color(gc, &gcolor); - - gdk_draw_rectangle(event->window, - gc, - TRUE, - rect.x, rect.y, rect.width, rect.height); + gdk_cairo_set_source_color(cr, &gcolor); + + cairo_rectangle(cr, + rect.x, rect.y, + rect.width, rect.height); + cairo_fill(cr); gtk_text_iter_backward_char(&cur); /* go back one, in case the end is the begining is the end * note that above, we always moved cur ahead by at least * one character */ @@ -880,7 +880,7 @@ !gtk_text_iter_begins_tag(&cur, NULL)); } - g_object_unref(G_OBJECT(gc)); + cairo_destroy(cr); if (GTK_WIDGET_CLASS (parent_class)->expose_event) return (* GTK_WIDGET_CLASS (parent_class)->expose_event) diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Thu Dec 02 20:17:37 2010 +0900 +++ b/pidgin/gtkutils.c Wed Dec 08 23:34:06 2010 +0900 @@ -684,7 +684,7 @@ GdkPixbuf *pixbuf = NULL; GtkSizeGroup *sg; GList *p; - const char *gtalk_name = NULL; + const char *gtalk_name = NULL, *facebook_name = NULL; int i; aop_menu = g_malloc0(sizeof(AopMenu)); @@ -693,8 +693,10 @@ gtk_widget_show(aop_menu->menu); sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); - if (purple_find_prpl("prpl-jabber")) + if (purple_find_prpl("prpl-jabber")) { gtalk_name = _("Google Talk"); + facebook_name = _("Facebook (XMPP)"); + } for (p = purple_plugins_get_protocols(), i = 0; p != NULL; @@ -712,7 +714,7 @@ gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol")); - g_object_set_data(G_OBJECT(item), "fake", GINT_TO_POINTER(1)); + g_object_set_data(G_OBJECT(item), "fakegoogle", GINT_TO_POINTER(1)); if (pixbuf) g_object_unref(pixbuf); @@ -721,6 +723,25 @@ i++; } + if (facebook_name && strcmp(facebook_name, plugin->info->name) < 0) { + char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", + "16", "facebook.png", NULL); + GtkWidget *item; + + pixbuf = gdk_pixbuf_new_from_file(filename, NULL); + g_free(filename); + + gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), + item = aop_menu_item_new(sg, pixbuf, facebook_name, "prpl-jabber", "protocol")); + g_object_set_data(G_OBJECT(item), "fakefacebook", GINT_TO_POINTER(1)); + + if (pixbuf) + g_object_unref(pixbuf); + + facebook_name = NULL; + i++; + } + pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/gtkwhiteboard.c --- a/pidgin/gtkwhiteboard.c Thu Dec 02 20:17:37 2010 +0900 +++ b/pidgin/gtkwhiteboard.c Wed Dec 08 23:34:06 2010 +0900 @@ -282,6 +282,9 @@ /* Clear graphical memory */ if(gtkwb->pixmap) { + cairo_t *cr = g_object_get_data(G_OBJECT(gtkwb->pixmap), "cairo-context"); + if (cr) + cairo_destroy(cr); g_object_unref(gtkwb->pixmap); gtkwb->pixmap = NULL; } @@ -353,25 +356,29 @@ static gboolean pidgin_whiteboard_configure_event(GtkWidget *widget, GdkEventConfigure *event, gpointer data) { PidginWhiteboard *gtkwb = (PidginWhiteboard*)data; - GdkPixmap *pixmap = gtkwb->pixmap; + cairo_t *cr; - if(pixmap) + if (pixmap) { + cr = g_object_get_data(G_OBJECT(pixmap), "cairo-context"); + if (cr) + cairo_destroy(cr); g_object_unref(pixmap); + } pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); - gtkwb->pixmap = pixmap; - gdk_draw_rectangle(pixmap, - widget->style->white_gc, - TRUE, - 0, 0, - widget->allocation.width, - widget->allocation.height); + cr = gdk_cairo_create(GDK_DRAWABLE(pixmap)); + g_object_set_data(G_OBJECT(pixmap), "cairo-context", cr); + gdk_cairo_set_source_color(cr, &widget->style->white); + cairo_rectangle(cr, + 0, 0, + widget->allocation.width, widget->allocation.height); + cairo_fill(cr); return TRUE; } @@ -380,13 +387,15 @@ { PidginWhiteboard *gtkwb = (PidginWhiteboard*)(data); GdkPixmap *pixmap = gtkwb->pixmap; + cairo_t *cr; - gdk_draw_drawable(widget->window, - widget->style->fg_gc[GTK_WIDGET_STATE(widget)], - pixmap, - event->area.x, event->area.y, - event->area.x, event->area.y, - event->area.width, event->area.height); + cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + gdk_cairo_set_source_pixmap(cr, pixmap, 0, 0); + cairo_rectangle(cr, + event->area.x, event->area.y, + event->area.width, event->area.height); + cairo_fill(cr); + cairo_destroy(cr); return FALSE; } @@ -586,50 +595,24 @@ GtkWidget *widget = gtkwb->drawing_area; GdkPixmap *pixmap = gtkwb->pixmap; - GdkRectangle update_rect; - - GdkGC *gfx_con = gdk_gc_new(pixmap); + cairo_t *gfx_con = g_object_get_data(G_OBJECT(pixmap), "cairo-context"); GdkColor col; - update_rect.x = x - size / 2; - update_rect.y = y - size / 2; - update_rect.width = size; - update_rect.height = size; - /* Interpret and convert color */ pidgin_whiteboard_rgb24_to_rgb48(color, &col); - gdk_gc_set_rgb_fg_color(gfx_con, &col); - /* gdk_gc_set_rgb_bg_color(gfx_con, &col); */ + gdk_cairo_set_source_color(gfx_con, &col); - /* NOTE 5 is a size constant for now... this is because of how poorly the - * gdk_draw_arc draws small circles - */ - if(size < 5) - { - /* Draw a rectangle/square */ - gdk_draw_rectangle(pixmap, - gfx_con, - TRUE, - update_rect.x, update_rect.y, - update_rect.width, update_rect.height); - } - else - { - /* Draw a circle */ - gdk_draw_arc(pixmap, - gfx_con, - TRUE, - update_rect.x, update_rect.y, - update_rect.width, update_rect.height, - 0, FULL_CIRCLE_DEGREES); - } + /* Draw a circle */ + cairo_arc(gfx_con, + x, y, + size / 2.0, + 0.0, 2.0 * M_PI); + cairo_fill(gfx_con); gtk_widget_queue_draw_area(widget, - update_rect.x, update_rect.y, - update_rect.width, update_rect.height); - - g_object_unref(G_OBJECT(gfx_con)); + x - size / 2, y - size / 2, + size, size); } /* Uses Bresenham's algorithm (as provided by Wikipedia) */ @@ -720,13 +703,14 @@ PidginWhiteboard *gtkwb = wb->ui_data; GdkPixmap *pixmap = gtkwb->pixmap; GtkWidget *drawing_area = gtkwb->drawing_area; + cairo_t *cr = g_object_get_data(G_OBJECT(pixmap), "cairo-context"); - gdk_draw_rectangle(pixmap, - drawing_area->style->white_gc, - TRUE, - 0, 0, - drawing_area->allocation.width, - drawing_area->allocation.height); + gdk_cairo_set_source_color(cr, &drawing_area->style->white); + cairo_rectangle(cr, + 0, 0, + drawing_area->allocation.width, + drawing_area->allocation.height); + cairo_fill(cr); gtk_widget_queue_draw_area(drawing_area, 0, 0, diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/pixmaps/Makefile.am --- a/pidgin/pixmaps/Makefile.am Thu Dec 02 20:17:37 2010 +0900 +++ b/pidgin/pixmaps/Makefile.am Wed Dec 08 23:34:06 2010 +0900 @@ -225,6 +225,7 @@ PROTOCOLS_16 = \ protocols/16/aim.png \ protocols/16/bonjour.png \ + protocols/16/facebook.png \ protocols/16/gadu-gadu.png \ protocols/16/google-talk.png \ protocols/16/novell.png \ @@ -281,6 +282,7 @@ PROTOCOLS_22 = \ protocols/22/aim.png \ protocols/22/bonjour.png \ + protocols/22/facebook.png \ protocols/22/gadu-gadu.png \ protocols/22/google-talk.png \ protocols/22/novell.png \ @@ -299,6 +301,7 @@ PROTOCOLS_48 = \ protocols/48/aim.png \ protocols/48/bonjour.png \ + protocols/48/facebook.png \ protocols/48/gadu-gadu.png \ protocols/48/novell.png \ protocols/48/icq.png \ diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/pixmaps/protocols/16/facebook.png Binary file pidgin/pixmaps/protocols/16/facebook.png has changed diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/pixmaps/protocols/22/facebook.png Binary file pidgin/pixmaps/protocols/22/facebook.png has changed diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/pixmaps/protocols/48/facebook.png Binary file pidgin/pixmaps/protocols/48/facebook.png has changed diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/plugins/Makefile.mingw --- a/pidgin/plugins/Makefile.mingw Thu Dec 02 20:17:37 2010 +0900 +++ b/pidgin/plugins/Makefile.mingw Wed Dec 08 23:34:06 2010 +0900 @@ -48,6 +48,7 @@ -lgmodule-2.0 \ -lgdk_pixbuf-2.0 \ -lpango-1.0 \ + -lcairo \ -lintl \ -lws2_32 \ -lpurple \ diff -r 4635d84e3292 -r 62f6e6796e48 pidgin/plugins/markerline.c --- a/pidgin/plugins/markerline.c Thu Dec 02 20:17:37 2010 +0900 +++ b/pidgin/plugins/markerline.c Wed Dec 08 23:34:06 2010 +0900 @@ -79,12 +79,14 @@ if (y >= event->area.y) { GdkColor red = {0, 0xffff, 0, 0}; - GdkGC *gc = gdk_gc_new(GDK_DRAWABLE(event->window)); + cairo_t *cr = gdk_cairo_create(GDK_DRAWABLE(event->window)); - gdk_gc_set_rgb_fg_color(gc, &red); - gdk_draw_line(event->window, gc, - 0, y, visible_rect.width, y); - g_object_unref(G_OBJECT(gc)); + gdk_cairo_set_source_color(cr, &red); + cairo_move_to(cr, 0.0, y + 0.5); + cairo_rel_line_to(cr, visible_rect.width, 0.0); + cairo_set_line_width(cr, 1.0); + cairo_stroke(cr); + cairo_destroy(cr); } return FALSE; }