diff -r 1edf059a4a26 -r 5af898e91ec2 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Sat May 26 13:48:41 2007 +0000 +++ b/pidgin/gtkutils.c Sun Jul 01 00:55:03 2007 +0000 @@ -94,6 +94,7 @@ void pidgin_setup_imhtml(GtkWidget *imhtml) { + PangoFontDescription *desc = NULL; g_return_if_fail(imhtml != NULL); g_return_if_fail(GTK_IS_IMHTML(imhtml)); @@ -104,10 +105,12 @@ gtk_imhtml_set_funcs(GTK_IMHTML(imhtml), >kimhtml_cbs); - /* Use the GNOME "document" font, if applicable */ - if (purple_running_gnome()) { + if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font")) { + const char *font = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font"); + desc = pango_font_description_from_string(font); + } else if (purple_running_gnome()) { + /* Use the GNOME "document" font, if applicable */ char *path, *font; - PangoFontDescription *desc = NULL; if ((path = g_find_program_in_path("gconftool-2"))) { g_free(path); @@ -118,15 +121,31 @@ } desc = pango_font_description_from_string(font); g_free(font); - - if (desc) { - gtk_widget_modify_font(imhtml, desc); - pango_font_description_free(desc); - } + } + + if (desc) { + gtk_widget_modify_font(imhtml, desc); + pango_font_description_free(desc); } } GtkWidget * +pidgin_create_window(const char *title, guint border_width, const char *role, gboolean resizable) +{ + GtkWindow *wnd = NULL; + + wnd = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); + if (title) + gtk_window_set_title(wnd, title); + gtk_container_set_border_width(GTK_CONTAINER(wnd), border_width); + if (role) + gtk_window_set_role(wnd, role); + gtk_window_set_resizable(wnd, resizable); + + return GTK_WIDGET(wnd); +} + +GtkWidget * pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret) { GtkWidget *frame; @@ -157,7 +176,7 @@ sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), - GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); gtk_widget_show(sw); @@ -242,13 +261,14 @@ gtk_widget_show(to_toggle); } -void pidgin_separator(GtkWidget *menu) +GtkWidget *pidgin_separator(GtkWidget *menu) { GtkWidget *menuitem; menuitem = gtk_separator_menu_item_new(); gtk_widget_show(menuitem); gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + return menuitem; } GtkWidget *pidgin_new_item(GtkWidget *menu, const char *str) @@ -459,7 +479,7 @@ } static GtkWidget * -aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data) +aop_menu_item_new(GtkSizeGroup *sg, GdkPixbuf *pixbuf, const char *lbl, gpointer per_item_data, const char *data) { GtkWidget *item; GtkWidget *hbox; @@ -492,6 +512,7 @@ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); + g_object_set_data(G_OBJECT (item), data, per_item_data); g_object_set_data(G_OBJECT (item), "aop_per_item_data", per_item_data); pidgin_set_accessible_label(item, label); @@ -499,6 +520,41 @@ return item; } +static GdkPixbuf * +pidgin_create_prpl_icon_from_prpl(PurplePlugin *prpl, PidginPrplIconSize size, PurpleAccount *account) +{ + PurplePluginProtocolInfo *prpl_info; + const char *protoname = NULL; + char *tmp; + char *filename = NULL; + GdkPixbuf *pixbuf; + + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); + if (prpl_info->list_icon == NULL) + return NULL; + + protoname = prpl_info->list_icon(account, NULL); + if (protoname == NULL) + return NULL; + + /* + * Status icons will be themeable too, and then it will look up + * protoname from the theme + */ + tmp = g_strconcat(protoname, ".png", NULL); + + filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", + size == PIDGIN_PRPL_ICON_SMALL ? "16" : + size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48", + tmp, NULL); + g_free(tmp); + + pixbuf = gdk_pixbuf_new_from_file(filename, NULL); + g_free(filename); + + return pixbuf; +} + static GtkWidget * aop_option_menu_new(AopMenu *aop_menu, GCallback cb, gpointer user_data) { @@ -549,25 +605,6 @@ } } -static GdkPixbuf * -get_prpl_pixbuf(PurplePluginProtocolInfo *prpl_info) -{ - const char *proto_name; - GdkPixbuf *pixbuf = NULL; - char *filename; - char buf[256]; - - proto_name = prpl_info->list_icon(NULL, NULL); - g_return_val_if_fail(proto_name != NULL, NULL); - - g_snprintf(buf, sizeof(buf), "%s.png", proto_name); - filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", buf, NULL); - pixbuf = gdk_pixbuf_new_from_file(filename, NULL); - g_free(filename); - - return pixbuf; -} - static AopMenu * create_protocols_menu(const char *default_proto_id) { @@ -599,22 +636,26 @@ if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) { char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", "16", "google-talk.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), - aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber")); + item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol")); + g_object_set_data(G_OBJECT(item), "fake", GINT_TO_POINTER(1)); if (pixbuf) g_object_unref(pixbuf); gtalk_name = NULL; + i++; } - pixbuf = get_prpl_pixbuf(prpl_info); + pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL); gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), - aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id)); + aop_menu_item_new(sg, pixbuf, plugin->info->name, plugin->info->id, "protocol")); if (pixbuf) g_object_unref(pixbuf); @@ -666,7 +707,6 @@ sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); for (p = list, i = 0; p != NULL; p = p->next, i++) { - PurplePluginProtocolInfo *prpl_info = NULL; PurplePlugin *plugin; if (show_all) @@ -684,18 +724,12 @@ plugin = purple_find_prpl(purple_account_get_protocol_id(account)); - if (plugin) - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); - - /* Load the image. */ - if (prpl_info) { - pixbuf = get_prpl_pixbuf(prpl_info); - - if (pixbuf) { - if (purple_account_is_disconnected(account) && show_all && - purple_connections_get_all()) - gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); - } + pixbuf = pidgin_create_prpl_icon(account, PIDGIN_PRPL_ICON_SMALL); + + if (pixbuf) { + if (purple_account_is_disconnected(account) && show_all && + purple_connections_get_all()) + gdk_pixbuf_saturate_and_pixelate(pixbuf, pixbuf, 0.0, FALSE); } if (purple_account_get_alias(account)) { @@ -710,7 +744,7 @@ } gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu), - aop_menu_item_new(sg, pixbuf, buf, account)); + aop_menu_item_new(sg, pixbuf, buf, account, "account")); if (pixbuf) g_object_unref(pixbuf); @@ -879,6 +913,44 @@ g_free(filename); } +static void +show_retrieveing_info(PurpleConnection *conn, const char *name) +{ + PurpleNotifyUserInfo *info = purple_notify_user_info_new(); + purple_notify_user_info_add_pair(info, _("Information"), _("Retrieving...")); + purple_notify_userinfo(conn, name, info, NULL, NULL); + purple_notify_user_info_destroy(info); +} + +void pidgin_retrieve_user_info(PurpleConnection *conn, const char *name) +{ + show_retrieveing_info(conn, name); + serv_get_info(conn, name); +} + +void pidgin_retrieve_user_info_in_chat(PurpleConnection *conn, const char *name, int chat) +{ + char *who = NULL; + PurplePluginProtocolInfo *prpl_info = NULL; + + if (chat < 0) { + pidgin_retrieve_user_info(conn, name); + return; + } + + prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(conn->prpl); + if (prpl_info == NULL || prpl_info->get_cb_info == NULL) { + pidgin_retrieve_user_info(conn, name); + return; + } + + if (prpl_info->get_cb_real_name) + who = prpl_info->get_cb_real_name(conn, chat, name); + show_retrieveing_info(conn, who ? who : name); + prpl_info->get_cb_info(conn, chat, name); + g_free(who); +} + gboolean pidgin_parse_x_im_contact(const char *msg, gboolean all_accounts, PurpleAccount **ret_account, char **ret_protocol, @@ -1075,6 +1147,9 @@ acc = gtk_widget_get_accessible (w); label = gtk_widget_get_accessible (l); + /* Make sure mnemonics work */ + gtk_label_set_mnemonic_widget(GTK_LABEL(l), w); + /* If this object has no name, set it's name with the label text */ existing_name = atk_object_get_name (acc); if (!existing_name) { @@ -1098,14 +1173,14 @@ g_object_unref (relation); } -#if GTK_CHECK_VERSION(2,2,0) -static void -pidgin_menu_position_func(GtkMenu *menu, +void +pidgin_menu_position_func_helper(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data) { +#if GTK_CHECK_VERSION(2,2,0) GtkWidget *widget; GtkRequisition requisition; GdkScreen *screen; @@ -1246,9 +1321,9 @@ { *y = monitor.y; } +#endif } -#endif void pidgin_treeview_popup_menu_position_func(GtkMenu *menu, @@ -1270,9 +1345,7 @@ *x += rect.x+rect.width; *y += rect.y+rect.height+ythickness; -#if GTK_CHECK_VERSION(2,2,0) - pidgin_menu_position_func (menu, x, y, push_in, data); -#endif + pidgin_menu_position_func_helper(menu, x, y, push_in, data); } enum { @@ -1454,8 +1527,7 @@ else purple_request_choice(NULL, NULL, _("You have dragged an image"), - (ft ? _("You can send this image as a file transfer or " - "embed it into this message, or use it as the buddy icon for this user.") : + (ft ? _("You can send this image as a file transfer, or use it as the buddy icon for this user.") : _("You can insert this image into this message, or use it as the buddy icon for this user")), (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE), "OK", (GCallback)dnd_image_ok_callback, @@ -1580,40 +1652,13 @@ pidgin_create_prpl_icon(PurpleAccount *account, PidginPrplIconSize size) { PurplePlugin *prpl; - PurplePluginProtocolInfo *prpl_info; - const char *protoname = NULL; - char buf[256]; /* TODO: We should use a define for max file length */ - char *filename = NULL; - GdkPixbuf *pixbuf; g_return_val_if_fail(account != NULL, NULL); prpl = purple_find_prpl(purple_account_get_protocol_id(account)); if (prpl == NULL) return NULL; - - prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl); - if (prpl_info->list_icon == NULL) - return NULL; - - protoname = prpl_info->list_icon(account, NULL); - if (protoname == NULL) - return NULL; - - /* - * Status icons will be themeable too, and then it will look up - * protoname from the theme - */ - g_snprintf(buf, sizeof(buf), "%s.png", protoname); - - filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", - size == PIDGIN_PRPL_ICON_SMALL ? "16" : - size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48", - buf, NULL); - pixbuf = gdk_pixbuf_new_from_file(filename, NULL); - g_free(filename); - - return pixbuf; + return pidgin_create_prpl_icon_from_prpl(prpl, size, account); } static void @@ -1629,62 +1674,63 @@ callback(object, data); } -void +GtkWidget * pidgin_append_menu_action(GtkWidget *menu, PurpleMenuAction *act, gpointer object) { + GtkWidget *menuitem; + if (act == NULL) { - pidgin_separator(menu); - } else { - GtkWidget *menuitem; - - if (act->children == NULL) { - menuitem = gtk_menu_item_new_with_mnemonic(act->label); - - if (act->callback != NULL) { - g_object_set_data(G_OBJECT(menuitem), - "purplecallback", - act->callback); - g_object_set_data(G_OBJECT(menuitem), - "purplecallbackdata", - act->data); - g_signal_connect(G_OBJECT(menuitem), "activate", - G_CALLBACK(menu_action_cb), - object); - } else { - gtk_widget_set_sensitive(menuitem, FALSE); - } - - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + return pidgin_separator(menu); + } + + if (act->children == NULL) { + menuitem = gtk_menu_item_new_with_mnemonic(act->label); + + if (act->callback != NULL) { + g_object_set_data(G_OBJECT(menuitem), + "purplecallback", + act->callback); + g_object_set_data(G_OBJECT(menuitem), + "purplecallbackdata", + act->data); + g_signal_connect(G_OBJECT(menuitem), "activate", + G_CALLBACK(menu_action_cb), + object); } else { - GList *l = NULL; - GtkWidget *submenu = NULL; - GtkAccelGroup *group; - - menuitem = gtk_menu_item_new_with_mnemonic(act->label); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); - - submenu = gtk_menu_new(); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); - - group = gtk_menu_get_accel_group(GTK_MENU(menu)); - if (group) { - char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label); - gtk_menu_set_accel_path(GTK_MENU(submenu), path); - g_free(path); - gtk_menu_set_accel_group(GTK_MENU(submenu), group); - } - - for (l = act->children; l; l = l->next) { - PurpleMenuAction *act = (PurpleMenuAction *)l->data; - - pidgin_append_menu_action(submenu, act, object); - } - g_list_free(act->children); - act->children = NULL; + gtk_widget_set_sensitive(menuitem, FALSE); } - purple_menu_action_free(act); + + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + } else { + GList *l = NULL; + GtkWidget *submenu = NULL; + GtkAccelGroup *group; + + menuitem = gtk_menu_item_new_with_mnemonic(act->label); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem); + + submenu = gtk_menu_new(); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), submenu); + + group = gtk_menu_get_accel_group(GTK_MENU(menu)); + if (group) { + char *path = g_strdup_printf("%s/%s", GTK_MENU_ITEM(menuitem)->accel_path, act->label); + gtk_menu_set_accel_path(GTK_MENU(submenu), path); + g_free(path); + gtk_menu_set_accel_group(GTK_MENU(submenu), group); + } + + for (l = act->children; l; l = l->next) { + PurpleMenuAction *act = (PurpleMenuAction *)l->data; + + pidgin_append_menu_action(submenu, act, object); + } + g_list_free(act->children); + act->children = NULL; } + purple_menu_action_free(act); + return menuitem; } #if GTK_CHECK_VERSION(2,3,0) @@ -2035,6 +2081,7 @@ static void screenname_autocomplete_destroyed_cb(GtkWidget *widget, gpointer data) { + g_free(data); purple_signals_disconnect_by_handle(widget); } @@ -2116,7 +2163,7 @@ purple_signal_connect(purple_accounts_get_handle(), "account-removed", entry, PURPLE_CALLBACK(repopulate_autocomplete), cb_data); - g_signal_connect(G_OBJECT(entry), "destroy", G_CALLBACK(screenname_autocomplete_destroyed_cb), NULL); + g_signal_connect(G_OBJECT(entry), "destroy", G_CALLBACK(screenname_autocomplete_destroyed_cb), data); } void pidgin_set_cursor(GtkWidget *widget, GdkCursorType cursor_type) @@ -3031,26 +3078,85 @@ row = pixels; for (i = 3; i < rowstride; i+=4) { - if (row[i] != 0xff) + if (row[i] < 0xfe) return FALSE; } for (i = 1; i < height - 1; i++) { row = pixels + (i*rowstride); - if (row[3] != 0xff || row[rowstride-1] != 0xff) { + if (row[3] < 0xfe || row[rowstride-1] < 0xfe) { return FALSE; - } + } } row = pixels + ((height-1) * rowstride); for (i = 3; i < rowstride; i+=4) { - if (row[i] != 0xff) + if (row[i] < 0xfe) return FALSE; } return TRUE; } +void pidgin_gdk_pixbuf_make_round(GdkPixbuf *pixbuf) { + int width, height, rowstride; + guchar *pixels; + if (!gdk_pixbuf_get_has_alpha(pixbuf)) + return; + width = gdk_pixbuf_get_width(pixbuf); + height = gdk_pixbuf_get_height(pixbuf); + rowstride = gdk_pixbuf_get_rowstride(pixbuf); + pixels = gdk_pixbuf_get_pixels(pixbuf); + + if (width < 6 || height < 6) + return; + /* Top left */ + pixels[3] = 0; + pixels[7] = 0x80; + pixels[11] = 0xC0; + pixels[rowstride + 3] = 0x80; + pixels[rowstride * 2 + 3] = 0xC0; + + /* Top right */ + pixels[width * 4 - 1] = 0; + pixels[width * 4 - 5] = 0x80; + pixels[width * 4 - 9] = 0xC0; + pixels[rowstride + (width * 4) - 1] = 0x80; + pixels[(2 * rowstride) + (width * 4) - 1] = 0xC0; + + /* Bottom left */ + pixels[(height - 1) * rowstride + 3] = 0; + pixels[(height - 1) * rowstride + 7] = 0x80; + pixels[(height - 1) * rowstride + 11] = 0xC0; + pixels[(height - 2) * rowstride + 3] = 0x80; + pixels[(height - 3) * rowstride + 3] = 0xC0; + + /* Bottom right */ + pixels[height * rowstride - 1] = 0; + pixels[(height - 1) * rowstride - 1] = 0x80; + pixels[(height - 2) * rowstride - 1] = 0xC0; + pixels[height * rowstride - 5] = 0x80; + pixels[height * rowstride - 9] = 0xC0; +} + +const char *pidgin_get_dim_grey_string(GtkWidget *widget) { + static char dim_grey_string[8] = ""; + GtkStyle *style; + + if (!widget) + return "dim grey"; + + style = gtk_widget_get_style(widget); + if (!style) + return "dim grey"; + + snprintf(dim_grey_string, sizeof(dim_grey_string), "#%02x%02x%02x", + style->text_aa[GTK_STATE_NORMAL].red >> 8, + style->text_aa[GTK_STATE_NORMAL].green >> 8, + style->text_aa[GTK_STATE_NORMAL].blue >> 8); + return dim_grey_string; +} + #if !GTK_CHECK_VERSION(2,2,0) GtkTreePath * gtk_tree_path_new_from_indices (gint first_index, ...) @@ -3075,3 +3181,4 @@ return path; } #endif +