pidgin/gtkconv.c

changeset 33510
8019461267d9
parent 33501
c224f6403237
parent 33393
ab10a481e30f
child 33513
abde619c77bf
equal deleted inserted replaced
33509:60647bc63acc 33510:8019461267d9
148 148
149 /* From http://www.w3.org/TR/AERT#color-contrast */ 149 /* From http://www.w3.org/TR/AERT#color-contrast */
150 #define MIN_BRIGHTNESS_CONTRAST 75 150 #define MIN_BRIGHTNESS_CONTRAST 75
151 #define MIN_COLOR_CONTRAST 200 151 #define MIN_COLOR_CONTRAST 200
152 152
153 #define NUM_NICK_COLORS 220 153 #define NICK_COLOR_GENERATE_COUNT 220
154 static GdkColor *nick_colors = NULL; 154 static GArray *generated_nick_colors = NULL;
155 static guint nbr_nick_colors;
156 155
157 /* These probably won't conflict with any WebKit values. */ 156 /* These probably won't conflict with any WebKit values. */
158 #define PIDGIN_DRAG_BLIST_NODE (1337) 157 #define PIDGIN_DRAG_BLIST_NODE (1337)
159 #define PIDGIN_DRAG_IM_CONTACT (31337) 158 #define PIDGIN_DRAG_IM_CONTACT (31337)
160 159
206 static void conv_set_unseen(PurpleConversation *gtkconv, PidginUnseenState state); 205 static void conv_set_unseen(PurpleConversation *gtkconv, PidginUnseenState state);
207 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); 206 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state);
208 static void update_typing_icon(PidginConversation *gtkconv); 207 static void update_typing_icon(PidginConversation *gtkconv);
209 static void update_typing_message(PidginConversation *gtkconv, const char *message); 208 static void update_typing_message(PidginConversation *gtkconv, const char *message);
210 gboolean pidgin_conv_has_focus(PurpleConversation *conv); 209 gboolean pidgin_conv_has_focus(PurpleConversation *conv);
211 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background); 210 static GArray* generate_nick_colors(guint numcolors, GdkColor background);
212 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); 211 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast);
213 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, gboolean create); 212 static GtkTextTag *get_buddy_tag(PurpleConversation *conv, const char *who, PurpleMessageFlags flag, gboolean create);
214 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); 213 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields);
215 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); 214 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win);
216 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); 215 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv);
225 { 224 {
226 static GdkColor col; 225 static GdkColor col;
227 GtkStyle *style = gtk_widget_get_style(gtkconv->webview); 226 GtkStyle *style = gtk_widget_get_style(gtkconv->webview);
228 float scale; 227 float scale;
229 228
230 col = nick_colors[g_str_hash(name) % nbr_nick_colors]; 229 col = g_array_index(gtkconv->nick_colors, GdkColor, g_str_hash(name) % gtkconv->nick_colors->len);
231 scale = ((1-(LUMINANCE(style->base[GTK_STATE_NORMAL]) / LUMINANCE(style->white))) * 230 scale = ((1-(LUMINANCE(style->base[GTK_STATE_NORMAL]) / LUMINANCE(style->white))) *
232 (LUMINANCE(style->white)/MAX(MAX(col.red, col.blue), col.green))); 231 (LUMINANCE(style->white)/MAX(MAX(col.red, col.blue), col.green)));
233 232
234 /* The colors are chosen to look fine on white; we should never have to darken */ 233 /* The colors are chosen to look fine on white; we should never have to darken */
235 if (scale > 1) { 234 if (scale > 1) {
5788 if (!theme) 5787 if (!theme)
5789 theme = default_conv_theme; 5788 theme = default_conv_theme;
5790 gtkconv->theme = PIDGIN_CONV_THEME(g_object_ref(theme)); 5789 gtkconv->theme = PIDGIN_CONV_THEME(g_object_ref(theme));
5791 gtkconv->last_flags = 0; 5790 gtkconv->last_flags = 0;
5792 5791
5792
5793 if (conv_type == PURPLE_CONV_TYPE_IM) { 5793 if (conv_type == PURPLE_CONV_TYPE_IM) {
5794 gtkconv->u.im = g_malloc0(sizeof(PidginImPane)); 5794 gtkconv->u.im = g_malloc0(sizeof(PidginImPane));
5795 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) { 5795 } else if (conv_type == PURPLE_CONV_TYPE_CHAT) {
5796 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane)); 5796 gtkconv->u.chat = g_malloc0(sizeof(PidginChatPane));
5797 } 5797 }
5885 if (hidden) 5885 if (hidden)
5886 pidgin_conv_window_add_gtkconv(hidden_convwin, gtkconv); 5886 pidgin_conv_window_add_gtkconv(hidden_convwin, gtkconv);
5887 else 5887 else
5888 pidgin_conv_placement_place(gtkconv); 5888 pidgin_conv_placement_place(gtkconv);
5889 5889
5890 if (nick_colors == NULL) { 5890 if (generated_nick_colors == NULL) {
5891 nbr_nick_colors = NUM_NICK_COLORS; 5891 generated_nick_colors = generate_nick_colors(NICK_COLOR_GENERATE_COUNT, gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]);
5892 nick_colors = generate_nick_colors(&nbr_nick_colors, gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]); 5892 }
5893
5894 if(NULL == (gtkconv->nick_colors = pidgin_conversation_theme_get_nick_colors(gtkconv->theme)))
5895 {
5896 gtkconv->nick_colors = g_array_ref(generated_nick_colors);
5893 } 5897 }
5894 5898
5895 if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY) 5899 if (purple_conversation_get_features(conv) & PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY)
5896 pidgin_themes_smiley_themeize_custom(gtkconv->entry); 5900 pidgin_themes_smiley_themeize_custom(gtkconv->entry);
5897 } 5901 }
6002 g_list_free(gtkconv->send_history); 6006 g_list_free(gtkconv->send_history);
6003 6007
6004 if (gtkconv->attach.timer) { 6008 if (gtkconv->attach.timer) {
6005 g_source_remove(gtkconv->attach.timer); 6009 g_source_remove(gtkconv->attach.timer);
6006 } 6010 }
6011
6012 g_array_unref(gtkconv->nick_colors);
6007 6013
6008 g_object_disconnect(G_OBJECT(gtkconv->theme), "any_signal::notify", 6014 g_object_disconnect(G_OBJECT(gtkconv->theme), "any_signal::notify",
6009 conv_variant_changed_cb, gtkconv, NULL); 6015 conv_variant_changed_cb, gtkconv, NULL);
6010 g_object_unref(gtkconv->theme); 6016 g_object_unref(gtkconv->theme);
6011 6017
6312 } else if (g_str_has_prefix(cur, "%senderScreenName%")) { 6318 } else if (g_str_has_prefix(cur, "%senderScreenName%")) {
6313 replace = name; 6319 replace = name;
6314 6320
6315 } else if (g_str_has_prefix(cur, "%sender%")) { 6321 } else if (g_str_has_prefix(cur, "%sender%")) {
6316 replace = alias; 6322 replace = alias;
6323
6324 } else if (g_str_has_prefix(cur, "%senderColor%")) {
6325 const GdkColor *color = get_nick_color(PIDGIN_CONVERSATION(conv), name);
6326 replace = freeval = g_strdup_printf("#%02x%02x%02x", (color->red >> 8), (color->green >> 8), (color->blue >> 8));
6317 6327
6318 } else if (g_str_has_prefix(cur, "%service%")) { 6328 } else if (g_str_has_prefix(cur, "%service%")) {
6319 replace = purple_account_get_protocol_name(purple_conversation_get_account(conv)); 6329 replace = purple_account_get_protocol_name(purple_conversation_get_account(conv));
6320 6330
6321 } else if (g_str_has_prefix(cur, "%messageDirection%")) { 6331 } else if (g_str_has_prefix(cur, "%messageDirection%")) {
7402 } 7412 }
7403 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 7413 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
7404 const char *topic = gtkconv->u.chat->topic_text 7414 const char *topic = gtkconv->u.chat->topic_text
7405 ? gtk_entry_get_text(GTK_ENTRY(gtkconv->u.chat->topic_text)) 7415 ? gtk_entry_get_text(GTK_ENTRY(gtkconv->u.chat->topic_text))
7406 : NULL; 7416 : NULL;
7407 char *esc = NULL, *tmp; 7417 const char *title = purple_conversation_get_title(conv);
7408 esc = topic ? g_markup_escape_text(topic, -1) : NULL; 7418 const char *name = purple_conversation_get_name(conv);
7409 tmp = g_markup_escape_text(purple_conversation_get_title(conv), -1); 7419
7410 markup = g_strdup_printf("%s%s<span color='%s' size='smaller'>%s</span>", 7420 char *topic_esc, *unaliased, *unaliased_esc, *title_esc;
7411 tmp, esc && *esc ? "\n" : "", 7421
7422 topic_esc = topic ? g_markup_escape_text(topic, -1) : NULL;
7423 unaliased = g_utf8_collate(title, name) ? g_strdup_printf("(%s)", name) : NULL;
7424 unaliased_esc = unaliased ? g_markup_escape_text(unaliased, -1) : NULL;
7425 title_esc = g_markup_escape_text(title, -1);
7426
7427 markup = g_strdup_printf("%s%s<span size='smaller'>%s</span>%s<span color='%s' size='smaller'>%s</span>",
7428 title_esc,
7429 unaliased_esc ? " " : "",
7430 unaliased_esc ? unaliased_esc : "",
7431 topic_esc && *topic_esc ? "\n" : "",
7412 pidgin_get_dim_grey_string(gtkconv->infopane), 7432 pidgin_get_dim_grey_string(gtkconv->infopane),
7413 esc ? esc : ""); 7433 topic_esc ? topic_esc : "");
7414 g_free(tmp); 7434
7415 g_free(esc); 7435 g_free(title_esc);
7436 g_free(topic_esc);
7437 g_free(unaliased);
7438 g_free(unaliased_esc);
7416 } 7439 }
7417 gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter), 7440 gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter),
7418 CONV_TEXT_COLUMN, markup, -1); 7441 CONV_TEXT_COLUMN, markup, -1);
7419 /* XXX seanegan Why do I have to do this? */ 7442 /* XXX seanegan Why do I have to do this? */
7420 gtk_widget_queue_draw(gtkconv->infopane); 7443 gtk_widget_queue_draw(gtkconv->infopane);
10091 } 10114 }
10092 10115
10093 void 10116 void
10094 pidgin_conv_window_destroy(PidginWindow *win) 10117 pidgin_conv_window_destroy(PidginWindow *win)
10095 { 10118 {
10096 PidginConversation *gtkconv;
10097 GList *iter;
10098
10099 if (win->gtkconvs) { 10119 if (win->gtkconvs) {
10100 for (iter = win->gtkconvs; iter != NULL; iter = iter->next) { 10120 GList *iter = win->gtkconvs;
10101 gtkconv = iter->data; 10121 while (iter)
10122 {
10123 PidginConversation *gtkconv = iter->data;
10124 iter = iter->next;
10102 close_conv_cb(NULL, gtkconv); 10125 close_conv_cb(NULL, gtkconv);
10103 } 10126 }
10104 return; 10127 return;
10105 } 10128 }
10106 10129
10936 10959
10937 return ((col_diff > color_contrast) && (br_diff > brightness_contrast)); 10960 return ((col_diff > color_contrast) && (br_diff > brightness_contrast));
10938 } 10961 }
10939 10962
10940 10963
10941 static GdkColor* 10964 static GArray*
10942 generate_nick_colors(guint *color_count, GdkColor background) 10965 generate_nick_colors(guint numcolors, GdkColor background)
10943 { 10966 {
10944 guint numcolors = *color_count;
10945 guint i = 0, j = 0; 10967 guint i = 0, j = 0;
10946 GdkColor *colors = g_new(GdkColor, numcolors); 10968 GArray *colors = g_array_new(FALSE, FALSE, sizeof(GdkColor));
10947 GdkColor nick_highlight; 10969 GdkColor nick_highlight;
10948 GdkColor send_color; 10970 GdkColor send_color;
10949 time_t breakout_time; 10971 time_t breakout_time;
10950 10972
10951 gdk_color_parse(DEFAULT_HIGHLIGHT_COLOR, &nick_highlight); 10973 gdk_color_parse(DEFAULT_HIGHLIGHT_COLOR, &nick_highlight);
10965 10987
10966 if (color_is_visible(color, background, MIN_COLOR_CONTRAST, MIN_BRIGHTNESS_CONTRAST) && 10988 if (color_is_visible(color, background, MIN_COLOR_CONTRAST, MIN_BRIGHTNESS_CONTRAST) &&
10967 color_is_visible(color, nick_highlight, MIN_COLOR_CONTRAST / 2, 0) && 10989 color_is_visible(color, nick_highlight, MIN_COLOR_CONTRAST / 2, 0) &&
10968 color_is_visible(color, send_color, MIN_COLOR_CONTRAST / 4, 0)) 10990 color_is_visible(color, send_color, MIN_COLOR_CONTRAST / 4, 0))
10969 { 10991 {
10970 colors[i] = color; 10992 g_array_append_val(colors, color);
10971 i++; 10993 i++;
10972 } 10994 }
10973 j++; 10995 j++;
10974 } 10996 }
10975 10997
10984 11006
10985 if (color_is_visible(color, background, MIN_COLOR_CONTRAST, MIN_BRIGHTNESS_CONTRAST) && 11007 if (color_is_visible(color, background, MIN_COLOR_CONTRAST, MIN_BRIGHTNESS_CONTRAST) &&
10986 color_is_visible(color, nick_highlight, MIN_COLOR_CONTRAST / 2, 0) && 11008 color_is_visible(color, nick_highlight, MIN_COLOR_CONTRAST / 2, 0) &&
10987 color_is_visible(color, send_color, MIN_COLOR_CONTRAST / 4, 0)) 11009 color_is_visible(color, send_color, MIN_COLOR_CONTRAST / 4, 0))
10988 { 11010 {
10989 colors[i] = color; 11011 g_array_append_val(colors, color);
10990 i++; 11012 i++;
10991 } 11013 }
10992 } 11014 }
10993 11015
10994 if (i < numcolors) { 11016 if (i < numcolors) {
10995 GdkColor *c = colors;
10996 purple_debug_warning("gtkconv", "Unable to generate enough random colors before timeout. %u colors found.\n", i); 11017 purple_debug_warning("gtkconv", "Unable to generate enough random colors before timeout. %u colors found.\n", i);
10997 colors = g_memdup(c, i * sizeof(GdkColor));
10998 g_free(c);
10999 *color_count = i;
11000 } 11018 }
11001 11019
11002 return colors; 11020 return colors;
11003 } 11021 }

mercurial