comparison pidgin/gtkconv.c @ 19874:0ed8a2a86a1b

explicit merge of 'fc49baf44017a8fd511c607b435668baf2a0f518' and 'b50640e3caa45410064cc403c759c1b427800a1e' to branch 'org.maemo.garage.pidgin.pidgin.dialog-transience'
author Gabriel Schulhof <nix@go-nix.ca>
date Fri, 17 Aug 2007 22:10:43 +0000
parents fb3958716599 6cec9e871ad2
children 9474223e534b
comparison
equal deleted inserted replaced
19872:dd5e6f06be8f 19874:0ed8a2a86a1b
184 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast); 184 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast);
185 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); 185 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields);
186 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win); 186 static void focus_out_from_menubar(GtkWidget *wid, PidginWindow *win);
187 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv); 187 static void pidgin_conv_tab_pack(PidginWindow *win, PidginConversation *gtkconv);
188 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); 188 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv);
189 static gboolean alias_double_click_cb(GtkWidget *widget, GdkEventButton *event, PidginConversation *gtkconv);
189 190
190 static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y, 191 static void pidgin_conv_set_position_size(PidginWindow *win, int x, int y,
191 int width, int height); 192 int width, int height);
192 193
193 static GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) { 194 static GdkColor *get_nick_color(PidginConversation *gtkconv, const char *name) {
2298 { 2299 {
2299 PurpleAccount *account = NULL; 2300 PurpleAccount *account = NULL;
2300 const char *name = NULL; 2301 const char *name = NULL;
2301 GdkPixbuf *status = NULL; 2302 GdkPixbuf *status = NULL;
2302 PurpleBlistUiOps *ops = purple_blist_get_ui_ops(); 2303 PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
2303 2304 const char *icon_size = small_icon ? "pidgin-icon-size-tango-microscopic" : PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL;
2304 g_return_val_if_fail(conv != NULL, NULL); 2305 g_return_val_if_fail(conv != NULL, NULL);
2305 2306
2306 account = purple_conversation_get_account(conv); 2307 account = purple_conversation_get_account(conv);
2307 name = purple_conversation_get_name(conv); 2308 name = purple_conversation_get_name(conv);
2308 2309
2311 2312
2312 /* Use the buddy icon, if possible */ 2313 /* Use the buddy icon, if possible */
2313 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 2314 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
2314 PurpleBuddy *b = purple_find_buddy(account, name); 2315 PurpleBuddy *b = purple_find_buddy(account, name);
2315 if (b != NULL) { 2316 if (b != NULL) {
2317 PurplePresence *p = purple_buddy_get_presence(b);
2316 /* I hate this hack. It fixes a bug where the pending message icon 2318 /* I hate this hack. It fixes a bug where the pending message icon
2317 * displays in the conv tab even though it shouldn't. 2319 * displays in the conv tab even though it shouldn't.
2318 * A better solution would be great. */ 2320 * A better solution would be great. */
2319 if (ops && ops->update) 2321 if (ops && ops->update)
2320 ops->update(NULL, (PurpleBlistNode*)b); 2322 ops->update(NULL, (PurpleBlistNode*)b);
2321 2323
2322 status = pidgin_blist_get_status_icon((PurpleBlistNode*)b, 2324 /* XXX Seanegan: We really need a util function to return a pixbuf for a Presence to avoid all this switching */
2323 (small_icon ? PIDGIN_STATUS_ICON_SMALL : PIDGIN_STATUS_ICON_LARGE)); 2325 if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AWAY))
2326 status = pidgin_create_status_icon(PURPLE_STATUS_AWAY, PIDGIN_CONVERSATION(conv)->icon, icon_size);
2327 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_EXTENDED_AWAY))
2328 status = pidgin_create_status_icon(PURPLE_STATUS_EXTENDED_AWAY, PIDGIN_CONVERSATION(conv)->icon, icon_size);
2329 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE))
2330 status = pidgin_create_status_icon(PURPLE_STATUS_OFFLINE, PIDGIN_CONVERSATION(conv)->icon, icon_size);
2331 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE))
2332 status = pidgin_create_status_icon(PURPLE_STATUS_AVAILABLE, PIDGIN_CONVERSATION(conv)->icon, icon_size);
2333 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE))
2334 status = pidgin_create_status_icon(PURPLE_STATUS_INVISIBLE, PIDGIN_CONVERSATION(conv)->icon, icon_size);
2335 else if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_UNAVAILABLE))
2336 status = pidgin_create_status_icon(PURPLE_STATUS_UNAVAILABLE, PIDGIN_CONVERSATION(conv)->icon, icon_size);
2324 } 2337 }
2325 } 2338 }
2326 2339
2327 /* If they don't have a buddy icon, then use the PRPL icon */ 2340 /* If they don't have a buddy icon, then use the PRPL icon */
2328 if (status == NULL) 2341 if (status == NULL) {
2329 status = pidgin_create_prpl_icon(account, small_icon ? PIDGIN_PRPL_ICON_SMALL : PIDGIN_PRPL_ICON_LARGE); 2342 GtkIconSize size = gtk_icon_size_from_name(icon_size);
2330 2343 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
2331 return status; 2344 status = gtk_widget_render_icon (PIDGIN_CONVERSATION(conv)->icon, PIDGIN_STOCK_STATUS_PERSON,
2345 size, "GtkWidget");
2346 } else {
2347 status = gtk_widget_render_icon (PIDGIN_CONVERSATION(conv)->icon, PIDGIN_STOCK_STATUS_CHAT,
2348 size, "GtkWidget");
2349 }
2350 }
2351 return status;
2332 } 2352 }
2333 2353
2334 2354
2335 static void 2355 static void
2336 update_tab_icon(PurpleConversation *conv) 2356 update_tab_icon(PurpleConversation *conv)
2338 PidginConversation *gtkconv; 2358 PidginConversation *gtkconv;
2339 PidginWindow *win; 2359 PidginWindow *win;
2340 PurpleBuddy *b; 2360 PurpleBuddy *b;
2341 GList *l; 2361 GList *l;
2342 GdkPixbuf *status = NULL; 2362 GdkPixbuf *status = NULL;
2363 GdkPixbuf *infopane_status = NULL;
2343 GdkPixbuf *emblem = NULL; 2364 GdkPixbuf *emblem = NULL;
2344 2365
2345 g_return_if_fail(conv != NULL); 2366 g_return_if_fail(conv != NULL);
2346 2367
2347 gtkconv = PIDGIN_CONVERSATION(conv); 2368 gtkconv = PIDGIN_CONVERSATION(conv);
2349 if (conv != gtkconv->active_conv) 2370 if (conv != gtkconv->active_conv)
2350 return; 2371 return;
2351 2372
2352 2373
2353 status = pidgin_conv_get_tab_icon(conv, TRUE); 2374 status = pidgin_conv_get_tab_icon(conv, TRUE);
2375 infopane_status = pidgin_conv_get_tab_icon(conv, FALSE);
2376
2354 b = purple_find_buddy(conv->account, conv->name); 2377 b = purple_find_buddy(conv->account, conv->name);
2355 if (b) 2378 if (b)
2356 emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b); 2379 emblem = pidgin_blist_get_emblem((PurpleBlistNode*)b);
2357 2380
2358 g_return_if_fail(status != NULL); 2381 g_return_if_fail(status != NULL);
2360 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->icon), status); 2383 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->icon), status);
2361 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->menu_icon), status); 2384 gtk_image_set_from_pixbuf(GTK_IMAGE(gtkconv->menu_icon), status);
2362 2385
2363 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model), 2386 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model),
2364 &(gtkconv->infopane_iter), 2387 &(gtkconv->infopane_iter),
2365 CONV_ICON_COLUMN, status, -1); 2388 CONV_ICON_COLUMN, infopane_status, -1);
2366 2389
2367 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model), 2390 gtk_list_store_set(GTK_LIST_STORE(gtkconv->infopane_model),
2368 &(gtkconv->infopane_iter), 2391 &(gtkconv->infopane_iter),
2369 CONV_EMBLEM_COLUMN, emblem, -1); 2392 CONV_EMBLEM_COLUMN, emblem, -1);
2370 2393
3338 stock_id = PIDGIN_STOCK_ANIMATION_TYPING1; 3361 stock_id = PIDGIN_STOCK_ANIMATION_TYPING1;
3339 tooltip = _("User is typing..."); 3362 tooltip = _("User is typing...");
3340 } else { 3363 } else {
3341 stock_id = PIDGIN_STOCK_ANIMATION_TYPING5; 3364 stock_id = PIDGIN_STOCK_ANIMATION_TYPING5;
3342 tooltip = _("User has typed something and stopped"); 3365 tooltip = _("User has typed something and stopped");
3343 g_source_remove(gtkconv->u.im->typing_timer); 3366 if (gtkconv->u.im->typing_timer != 0) {
3344 gtkconv->u.im->typing_timer = 0; 3367 g_source_remove(gtkconv->u.im->typing_timer);
3368 gtkconv->u.im->typing_timer = 0;
3369 }
3345 } 3370 }
3346 3371
3347 if (gtkwin->menu.typing_icon == NULL) 3372 if (gtkwin->menu.typing_icon == NULL)
3348 { 3373 {
3349 gtkwin->menu.typing_icon = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU); 3374 gtkwin->menu.typing_icon = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_MENU);
4013 g_free(new_topic); 4038 g_free(new_topic);
4014 return; 4039 return;
4015 } 4040 }
4016 4041
4017 gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), current_topic); 4042 gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), current_topic);
4018
4019 prpl_info->set_chat_topic(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)), 4043 prpl_info->set_chat_topic(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)),
4020 new_topic); 4044 new_topic);
4021 4045
4022 g_free(new_topic); 4046 g_free(new_topic);
4023 } 4047 }
4381 rend = gtk_cell_renderer_text_new(); 4405 rend = gtk_cell_renderer_text_new();
4382 g_object_set(rend, 4406 g_object_set(rend,
4383 "foreground-set", TRUE, 4407 "foreground-set", TRUE,
4384 "weight-set", TRUE, 4408 "weight-set", TRUE,
4385 NULL); 4409 NULL);
4410 g_object_set(G_OBJECT(rend), "editable", TRUE, NULL);
4411
4386 col = gtk_tree_view_column_new_with_attributes(NULL, rend, 4412 col = gtk_tree_view_column_new_with_attributes(NULL, rend,
4387 "text", CHAT_USERS_ALIAS_COLUMN, 4413 "text", CHAT_USERS_ALIAS_COLUMN,
4388 "foreground-gdk", CHAT_USERS_COLOR_COLUMN, 4414 "foreground-gdk", CHAT_USERS_COLOR_COLUMN,
4389 "weight", CHAT_USERS_WEIGHT_COLUMN, 4415 "weight", CHAT_USERS_WEIGHT_COLUMN,
4390 NULL); 4416 NULL);
4409 gtkchat->list = list; 4435 gtkchat->list = list;
4410 4436
4411 gtk_container_add(GTK_CONTAINER(sw), list); 4437 gtk_container_add(GTK_CONTAINER(sw), list);
4412 } 4438 }
4413 4439
4414 static int tooltip_timeout = 0; 4440 /* Stuff used to display tooltips on the infopane */
4441 static struct {
4442 int timeout;
4443 PidginConversation *gtkconv; /* This is the Pidgin conversation that
4444 triggered the tooltip */
4445 } tooltip;
4446
4447 static void
4448 reset_tooltip()
4449 {
4450 if (tooltip.timeout != 0) {
4451 g_source_remove(tooltip.timeout);
4452 tooltip.timeout = 0;
4453 }
4454 tooltip.gtkconv = NULL;
4455 }
4415 4456
4416 static gboolean 4457 static gboolean
4417 pidgin_conv_tooltip_timeout(PidginConversation *gtkconv) 4458 pidgin_conv_tooltip_timeout(PidginConversation *gtkconv)
4418 { 4459 {
4419 PurpleBlistNode *node = NULL; 4460 PurpleBlistNode *node = NULL;
4420 PurpleConversation *conv = gtkconv->active_conv; 4461 PurpleConversation *conv;
4421 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 4462
4422 node = (PurpleBlistNode*)(purple_blist_find_chat(conv->account, conv->name)); 4463 g_return_val_if_fail (tooltip.gtkconv == gtkconv, FALSE);
4464
4465 conv = gtkconv->active_conv;
4466 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
4467 node = (PurpleBlistNode*)(purple_blist_find_chat(conv->account, conv->name));
4423 } else { 4468 } else {
4424 node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name)); 4469 node = (PurpleBlistNode*)(purple_find_buddy(conv->account, conv->name));
4425 } 4470 }
4426 4471
4427 if (node) 4472 if (node)
4428 pidgin_blist_draw_tooltip(node, gtkconv->infopane); 4473 pidgin_blist_draw_tooltip(node, gtkconv->infopane);
4429 return FALSE; 4474 return FALSE;
4431 4476
4432 static void 4477 static void
4433 pidgin_conv_leave_cb (GtkWidget *w, GdkEventCrossing *e, PidginConversation *gtkconv) 4478 pidgin_conv_leave_cb (GtkWidget *w, GdkEventCrossing *e, PidginConversation *gtkconv)
4434 { 4479 {
4435 pidgin_blist_tooltip_destroy(); 4480 pidgin_blist_tooltip_destroy();
4436 if (tooltip_timeout) { 4481 reset_tooltip();
4437 g_source_remove(tooltip_timeout);
4438 tooltip_timeout = 0;
4439 }
4440 } 4482 }
4441 4483
4442 static gboolean 4484 static gboolean
4443 pidgin_conv_motion_cb (GtkWidget *infopane, GdkEventMotion *event, PidginConversation *gtkconv) 4485 pidgin_conv_motion_cb (GtkWidget *infopane, GdkEventMotion *event, PidginConversation *gtkconv)
4444 { 4486 {
4446 4488
4447 pidgin_blist_tooltip_destroy(); 4489 pidgin_blist_tooltip_destroy();
4448 if (delay == 0) 4490 if (delay == 0)
4449 return FALSE; 4491 return FALSE;
4450 4492
4451 if (tooltip_timeout != 0) 4493 if (tooltip.timeout != 0)
4452 g_source_remove(tooltip_timeout); 4494 g_source_remove(tooltip.timeout);
4453 4495
4454 tooltip_timeout = g_timeout_add(delay, (GSourceFunc)pidgin_conv_tooltip_timeout, gtkconv); 4496 tooltip.timeout = g_timeout_add(delay, (GSourceFunc)pidgin_conv_tooltip_timeout, gtkconv);
4497 tooltip.gtkconv = gtkconv;
4455 return FALSE; 4498 return FALSE;
4456 } 4499 }
4457 4500
4458 static GtkWidget * 4501 static GtkWidget *
4459 setup_common_pane(PidginConversation *gtkconv) 4502 setup_common_pane(PidginConversation *gtkconv)
4486 gtk_widget_add_events(event_box, 4529 gtk_widget_add_events(event_box,
4487 GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); 4530 GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
4488 g_signal_connect(G_OBJECT(event_box), "button_press_event", 4531 g_signal_connect(G_OBJECT(event_box), "button_press_event",
4489 G_CALLBACK(infopane_press_cb), gtkconv); 4532 G_CALLBACK(infopane_press_cb), gtkconv);
4490 4533
4491 g_signal_connect(G_OBJECT(event_box), "motion-notify-event", 4534 g_signal_connect(G_OBJECT(event_box), "motion-notify-event",
4492 G_CALLBACK(pidgin_conv_motion_cb), gtkconv); 4535 G_CALLBACK(pidgin_conv_motion_cb), gtkconv);
4493 g_signal_connect(G_OBJECT(event_box), "leave-notify-event", 4536 g_signal_connect(G_OBJECT(event_box), "leave-notify-event",
4494 G_CALLBACK(pidgin_conv_leave_cb), gtkconv); 4537 G_CALLBACK(pidgin_conv_leave_cb), gtkconv);
4495
4496 4538
4497 gtkconv->infopane = gtk_cell_view_new(); 4539 gtkconv->infopane = gtk_cell_view_new();
4498 gtkconv->infopane_model = gtk_list_store_new(CONV_NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDK_TYPE_PIXBUF); 4540 gtkconv->infopane_model = gtk_list_store_new(CONV_NUM_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, GDK_TYPE_PIXBUF);
4499 gtk_cell_view_set_model(GTK_CELL_VIEW(gtkconv->infopane), 4541 gtk_cell_view_set_model(GTK_CELL_VIEW(gtkconv->infopane),
4500 GTK_TREE_MODEL(gtkconv->infopane_model)); 4542 GTK_TREE_MODEL(gtkconv->infopane_model));
4501 gtk_list_store_append(gtkconv->infopane_model, &(gtkconv->infopane_iter)); 4543 gtk_list_store_append(gtkconv->infopane_model, &(gtkconv->infopane_iter));
4502 gtk_box_pack_start(GTK_BOX(gtkconv->infopane_hbox), gtkconv->infopane, TRUE, TRUE, 0); 4544 gtk_box_pack_start(GTK_BOX(gtkconv->infopane_hbox), gtkconv->infopane, TRUE, TRUE, 0);
4503 path = gtk_tree_path_new_from_string("0"); 4545 path = gtk_tree_path_new_from_string("0");
4504 gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(gtkconv->infopane), path); 4546 gtk_cell_view_set_displayed_row(GTK_CELL_VIEW(gtkconv->infopane), path);
4505 gtk_tree_path_free(path); 4547 gtk_tree_path_free(path);
4506 gtk_widget_set_size_request(gtkconv->infopane, -1, 32); 4548 gtk_widget_set_size_request(gtkconv->infopane_hbox, -1, 32);
4507 gtk_widget_show(gtkconv->infopane); 4549 gtk_widget_show(gtkconv->infopane);
4508 4550
4509 rend = gtk_cell_renderer_pixbuf_new(); 4551 rend = gtk_cell_renderer_pixbuf_new();
4510 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE); 4552 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkconv->infopane), rend, FALSE);
4511 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_ICON_COLUMN, NULL); 4553 gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkconv->infopane), rend, "pixbuf", CONV_ICON_COLUMN, NULL);
4983 gtk_object_sink(GTK_OBJECT(gtkconv->tooltips)); 5025 gtk_object_sink(GTK_OBJECT(gtkconv->tooltips));
4984 5026
4985 gtkconv->send_history = g_list_first(gtkconv->send_history); 5027 gtkconv->send_history = g_list_first(gtkconv->send_history);
4986 g_list_foreach(gtkconv->send_history, (GFunc)g_free, NULL); 5028 g_list_foreach(gtkconv->send_history, (GFunc)g_free, NULL);
4987 g_list_free(gtkconv->send_history); 5029 g_list_free(gtkconv->send_history);
5030
5031 if (tooltip.gtkconv == gtkconv)
5032 reset_tooltip();
4988 5033
4989 g_free(gtkconv); 5034 g_free(gtkconv);
4990 } 5035 }
4991 5036
4992 5037
6254 6299
6255 if ((fields & PIDGIN_CONV_COLORIZE_TITLE) || 6300 if ((fields & PIDGIN_CONV_COLORIZE_TITLE) ||
6256 (fields & PIDGIN_CONV_SET_TITLE) || 6301 (fields & PIDGIN_CONV_SET_TITLE) ||
6257 (fields & PIDGIN_CONV_TOPIC)) 6302 (fields & PIDGIN_CONV_TOPIC))
6258 { 6303 {
6259 char *title, *truncate = NULL, truncchar = '\0'; 6304 char *title;
6260 PurpleConvIm *im = NULL; 6305 PurpleConvIm *im = NULL;
6261 PurpleAccount *account = purple_conversation_get_account(conv); 6306 PurpleAccount *account = purple_conversation_get_account(conv);
6262 PurpleBuddy *buddy = NULL; 6307 PurpleBuddy *buddy = NULL;
6263 PurplePresence *p = NULL; 6308 PurplePresence *p = NULL;
6264 char *markup = NULL; 6309 char *markup = NULL;
6265 AtkObject *accessibility_obj; 6310 AtkObject *accessibility_obj;
6266 /* I think this is a little longer than it needs to be but I'm lazy. */ 6311 /* I think this is a little longer than it needs to be but I'm lazy. */
6267 char *style, *status_style; 6312 char *style;
6268 6313
6269 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) 6314 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
6270 im = PURPLE_CONV_IM(conv); 6315 im = PURPLE_CONV_IM(conv);
6271 6316
6272 if ((account == NULL) || 6317 if ((account == NULL) ||
6274 ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) 6319 ((purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT)
6275 && purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv)))) 6320 && purple_conv_chat_has_left(PURPLE_CONV_CHAT(conv))))
6276 title = g_strdup_printf("(%s)", purple_conversation_get_title(conv)); 6321 title = g_strdup_printf("(%s)", purple_conversation_get_title(conv));
6277 else 6322 else
6278 title = g_strdup(purple_conversation_get_title(conv)); 6323 title = g_strdup(purple_conversation_get_title(conv));
6279
6280 if ((truncate = strchr(title, ' ')) ||
6281 (truncate = strchr(title, '@'))) {
6282 truncchar = *truncate;
6283 *truncate = '\0';
6284 }
6285 6324
6286 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) { 6325 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
6287 buddy = purple_find_buddy(account, conv->name); 6326 buddy = purple_find_buddy(account, conv->name);
6288 if (buddy) { 6327 if (buddy) {
6289 p = purple_buddy_get_presence(buddy); 6328 p = purple_buddy_get_presence(buddy);
6290 markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE); 6329 markup = pidgin_blist_get_name_markup(buddy, FALSE, FALSE);
6291 } else { 6330 } else {
6292 markup = title; 6331 markup = title;
6293 } 6332 }
6294 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 6333 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
6295 PurpleConvChat *chat = PURPLE_CONV_CHAT(conv); 6334 const char *topic = gtk_entry_get_text(GTK_ENTRY(gtkconv->u.chat->topic_text));
6296 const char *topic = purple_conv_chat_get_topic(chat); 6335 char *esc = topic ? g_markup_escape_text(topic, -1) : NULL;
6297 markup = g_strdup_printf("%s%s<span color='%s' size='smaller'>%s</span>", 6336 markup = g_strdup_printf("%s%s<span color='%s' size='smaller'>%s</span>",
6298 purple_conversation_get_title(conv), 6337 purple_conversation_get_title(conv),
6299 topic ? "\n" : "", 6338 esc && *esc ? "\n" : "",
6300 pidgin_get_dim_grey_string(gtkconv->infopane), 6339 pidgin_get_dim_grey_string(gtkconv->infopane),
6301 topic ? topic : ""); 6340 esc ? esc : "");
6341 g_free(esc);
6302 } 6342 }
6303 gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter), 6343 gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter),
6304 CONV_TEXT_COLUMN, markup, -1); 6344 CONV_TEXT_COLUMN, markup, -1);
6345 /* XXX seanegan Why do I have to do this? */
6346 gtk_widget_queue_draw(gtkconv->infopane);
6305 6347
6306 if (title != markup) 6348 if (title != markup)
6307 g_free(markup); 6349 g_free(markup);
6308 6350
6309 if (!GTK_WIDGET_REALIZED(gtkconv->tab_label)) 6351 if (!GTK_WIDGET_REALIZED(gtkconv->tab_label))
6329 style = "color=\"#888a85\" weight=\"bold\""; 6371 style = "color=\"#888a85\" weight=\"bold\"";
6330 } else { 6372 } else {
6331 style = ""; 6373 style = "";
6332 } 6374 }
6333 6375
6334 if (p && purple_presence_is_status_primitive_active(p, PURPLE_STATUS_OFFLINE)) { 6376 if (*style != '\0')
6335 status_style = "strikethrough='true'";
6336 } else if (p && !purple_presence_is_status_primitive_active(p, PURPLE_STATUS_AVAILABLE) &&
6337 !purple_presence_is_status_primitive_active(p, PURPLE_STATUS_INVISIBLE)) {
6338 status_style = "style='italic'";
6339 } else {
6340 status_style = "";
6341 }
6342
6343 if (*style != '\0' || *status_style != '\0')
6344 { 6377 {
6345 char *html_title,*label; 6378 char *html_title,*label;
6346 6379
6347 html_title = g_markup_escape_text(title, -1); 6380 html_title = g_markup_escape_text(title, -1);
6348 label = g_strdup_printf("<span %s %s>%s</span>", 6381 label = g_strdup_printf("<span %s>%s</span>",
6349 style, status_style, html_title); 6382 style, html_title);
6350 g_free(html_title); 6383 g_free(html_title);
6351 gtk_label_set_markup(GTK_LABEL(gtkconv->tab_label), label); 6384 gtk_label_set_markup(GTK_LABEL(gtkconv->tab_label), label);
6352 g_free(label); 6385 g_free(label);
6353 } 6386 }
6354 else 6387 else
6355 gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), title); 6388 gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), title);
6356 6389
6357 if (truncate)
6358 *truncate = truncchar;
6359
6360 if (pidgin_conv_window_is_active_conversation(conv)) 6390 if (pidgin_conv_window_is_active_conversation(conv))
6361 update_typing_icon(gtkconv); 6391 update_typing_icon(gtkconv);
6362 6392
6363 gtk_label_set_text(GTK_LABEL(gtkconv->menu_label), title); 6393 gtk_label_set_text(GTK_LABEL(gtkconv->menu_label), title);
6364 if (pidgin_conv_window_is_active_conversation(conv)) 6394 if (pidgin_conv_window_is_active_conversation(conv))
6602 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event), FALSE); 6632 gtk_event_box_set_visible_window(GTK_EVENT_BOX(event), FALSE);
6603 gtk_widget_add_events(event, 6633 gtk_widget_add_events(event,
6604 GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK); 6634 GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK);
6605 g_signal_connect(G_OBJECT(event), "button-press-event", 6635 g_signal_connect(G_OBJECT(event), "button-press-event",
6606 G_CALLBACK(icon_menu), gtkconv); 6636 G_CALLBACK(icon_menu), gtkconv);
6607 g_signal_connect(G_OBJECT(event), "motion-notify-event", 6637 g_signal_connect(G_OBJECT(event), "motion-notify-event",
6608 G_CALLBACK(pidgin_conv_motion_cb), gtkconv); 6638 G_CALLBACK(pidgin_conv_motion_cb), gtkconv);
6609 g_signal_connect(G_OBJECT(event), "leave-notify-event", 6639 g_signal_connect(G_OBJECT(event), "leave-notify-event",
6610 G_CALLBACK(pidgin_conv_leave_cb), gtkconv); 6640 G_CALLBACK(pidgin_conv_leave_cb), gtkconv);
6611 gtk_widget_show(event); 6641 gtk_widget_show(event);
6612 6642
6613 gtkconv->u.im->icon = gtk_image_new_from_pixbuf(scale); 6643 gtkconv->u.im->icon = gtk_image_new_from_pixbuf(scale);
6614 gtk_container_add(GTK_CONTAINER(event), gtkconv->u.im->icon); 6644 gtk_container_add(GTK_CONTAINER(event), gtkconv->u.im->icon);
6615 gtk_widget_show(gtkconv->u.im->icon); 6645 gtk_widget_show(gtkconv->u.im->icon);
7177 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font", TRUE); 7207 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font", TRUE);
7178 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/custom_font", ""); 7208 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/custom_font", "");
7179 7209
7180 /* Conversations -> Chat */ 7210 /* Conversations -> Chat */
7181 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/chat"); 7211 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/chat");
7182 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height", 50); 7212 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/entry_height", 54);
7183 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/userlist_width", 80); 7213 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/userlist_width", 80);
7184 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/x", 0); 7214 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/x", 0);
7185 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/y", 0); 7215 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/y", 0);
7186 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/width", 0); 7216 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/width", 340);
7187 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/height", 0); 7217 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/chat/height", 390);
7188 7218
7189 /* Conversations -> IM */ 7219 /* Conversations -> IM */
7190 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/im"); 7220 purple_prefs_add_none(PIDGIN_PREFS_ROOT "/conversations/im");
7191 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/x", 0); 7221 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/x", 0);
7192 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/y", 0); 7222 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/y", 0);
7193 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/width", 0); 7223 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/width", 340);
7194 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/height", 0); 7224 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/height", 390);
7195 7225
7196 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons", TRUE); 7226 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/animate_buddy_icons", TRUE);
7197 7227
7198 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height", 50); 7228 purple_prefs_add_int(PIDGIN_PREFS_ROOT "/conversations/im/entry_height", 54);
7199 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons", TRUE); 7229 purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons", TRUE);
7200 7230
7201 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new", "never"); 7231 purple_prefs_add_string(PIDGIN_PREFS_ROOT "/conversations/im/hide_new", "never");
7202 7232
7203 #ifdef _WIN32 7233 #ifdef _WIN32
7590 /* 7620 /*
7591 * When a conversation window is focused, we know the user 7621 * When a conversation window is focused, we know the user
7592 * has looked at it so we know there are no longer unseen 7622 * has looked at it so we know there are no longer unseen
7593 * messages. 7623 * messages.
7594 */ 7624 */
7595 static gint 7625 static gboolean
7596 focus_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) 7626 focus_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d)
7597 { 7627 {
7598 PidginWindow *win = d; 7628 PidginWindow *win = d;
7599 PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win); 7629 PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win);
7600 7630
7601 gtkconv_set_unseen(gtkconv, PIDGIN_UNSEEN_NONE); 7631 if (gtkconv)
7632 gtkconv_set_unseen(gtkconv, PIDGIN_UNSEEN_NONE);
7602 7633
7603 return FALSE; 7634 return FALSE;
7604 } 7635 }
7605 7636
7606 #if !GTK_CHECK_VERSION(2,6,0) 7637 #if !GTK_CHECK_VERSION(2,6,0)
7688 horiz_tabs = TRUE; 7719 horiz_tabs = TRUE;
7689 } 7720 }
7690 7721
7691 gtkconv = pidgin_conv_window_get_gtkconv_at_index(dest_win, page_num); 7722 gtkconv = pidgin_conv_window_get_gtkconv_at_index(dest_win, page_num);
7692 tab = gtkconv->tabby; 7723 tab = gtkconv->tabby;
7693 7724 if (gtk_notebook_get_show_tabs(dest_notebook) == FALSE) {
7694 if (horiz_tabs) { 7725 dnd_hints_show_relative(HINT_ARROW_DOWN, gtkconv->infopane, HINT_POSITION_CENTER, HINT_POSITION_TOP);
7726 dnd_hints_show_relative(HINT_ARROW_UP, gtkconv->infopane, HINT_POSITION_CENTER, HINT_POSITION_BOTTOM);
7727 } else if (horiz_tabs) {
7695 if (((gpointer)win == (gpointer)dest_win && win->drag_tab < page_num) || to_right) { 7728 if (((gpointer)win == (gpointer)dest_win && win->drag_tab < page_num) || to_right) {
7696 dnd_hints_show_relative(HINT_ARROW_DOWN, tab, HINT_POSITION_RIGHT, HINT_POSITION_TOP); 7729 dnd_hints_show_relative(HINT_ARROW_DOWN, tab, HINT_POSITION_RIGHT, HINT_POSITION_TOP);
7697 dnd_hints_show_relative(HINT_ARROW_UP, tab, HINT_POSITION_RIGHT, HINT_POSITION_BOTTOM); 7730 dnd_hints_show_relative(HINT_ARROW_UP, tab, HINT_POSITION_RIGHT, HINT_POSITION_BOTTOM);
7698 } else { 7731 } else {
7699 dnd_hints_show_relative(HINT_ARROW_DOWN, tab, HINT_POSITION_LEFT, HINT_POSITION_TOP); 7732 dnd_hints_show_relative(HINT_ARROW_DOWN, tab, HINT_POSITION_LEFT, HINT_POSITION_TOP);
7736 */ 7769 */
7737 7770
7738 static gboolean 7771 static gboolean
7739 infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv) 7772 infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *gtkconv)
7740 { 7773 {
7774 if (e->type == GDK_2BUTTON_PRESS && e->button == 1) {
7775 if (alias_double_click_cb(widget, e, gtkconv))
7776 return TRUE;
7777 }
7778
7741 if (e->type != GDK_BUTTON_PRESS) 7779 if (e->type != GDK_BUTTON_PRESS)
7742 return FALSE; 7780 return FALSE;
7743 7781
7782 if (e->button == 1) {
7783 int nb_x, nb_y;
7784
7785 if (gtkconv->win->in_drag)
7786 return TRUE;
7787
7788 gtkconv->win->in_predrag = TRUE;
7789 gtkconv->win->drag_tab = gtk_notebook_page_num(GTK_NOTEBOOK(gtkconv->win->notebook), gtkconv->tab_cont);
7790
7791 gdk_window_get_origin(gtkconv->infopane_hbox->window, &nb_x, &nb_y);
7792
7793 gtkconv->win->drag_min_x = gtkconv->infopane_hbox->allocation.x + nb_x;
7794 gtkconv->win->drag_min_y = gtkconv->infopane_hbox->allocation.y + nb_y;
7795 gtkconv->win->drag_max_x = gtkconv->infopane_hbox->allocation.width + gtkconv->win->drag_min_x;
7796 gtkconv->win->drag_max_y = gtkconv->infopane_hbox->allocation.height + gtkconv->win->drag_min_y;
7797
7798 gtkconv->win->drag_motion_signal = g_signal_connect(G_OBJECT(gtkconv->win->notebook), "motion_notify_event",
7799 G_CALLBACK(notebook_motion_cb), gtkconv->win);
7800 gtkconv->win->drag_leave_signal = g_signal_connect(G_OBJECT(gtkconv->win->notebook), "leave_notify_event",
7801 G_CALLBACK(notebook_leave_cb), gtkconv->win);
7802 return FALSE;
7803 }
7804
7744 if (e->button == 3) { 7805 if (e->button == 3) {
7745 /* Right click was pressed. Popup the Send To menu. */ 7806 /* Right click was pressed. Popup the Send To menu. */
7746 GtkWidget *menu = gtk_menu_new(), *sub; 7807 GtkWidget *menu = gtk_menu_new(), *sub;
7747 sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to)); 7808 sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to));
7748 7809
8117 static void 8178 static void
8118 remove_edit_entry(PidginConversation *gtkconv, GtkWidget *entry) 8179 remove_edit_entry(PidginConversation *gtkconv, GtkWidget *entry)
8119 { 8180 {
8120 g_signal_handlers_disconnect_matched(G_OBJECT(entry), G_SIGNAL_MATCH_DATA, 8181 g_signal_handlers_disconnect_matched(G_OBJECT(entry), G_SIGNAL_MATCH_DATA,
8121 0, 0, NULL, NULL, gtkconv); 8182 0, 0, NULL, NULL, gtkconv);
8122 gtk_widget_show(gtkconv->tab_label); 8183 gtk_widget_show(gtkconv->infopane);
8123 gtk_widget_grab_focus(gtkconv->entry); 8184 gtk_widget_grab_focus(gtkconv->entry);
8124 gtk_widget_destroy(entry); 8185 gtk_widget_destroy(entry);
8125 } 8186 }
8126 8187
8127 static gboolean 8188 static gboolean
8164 purple_blist_alias_buddy(buddy, 8225 purple_blist_alias_buddy(buddy,
8165 gtk_entry_get_text(entry)); 8226 gtk_entry_get_text(entry));
8166 } 8227 }
8167 serv_alias_buddy(buddy); 8228 serv_alias_buddy(buddy);
8168 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) { 8229 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
8169 PurpleChat *chat; 8230 gtk_entry_set_text(GTK_ENTRY(gtkconv->u.chat->topic_text), gtk_entry_get_text(entry));
8170 8231 topic_callback(NULL, gtkconv);
8171 chat = purple_blist_find_chat(account, name);
8172 if (chat != NULL) {
8173 purple_blist_alias_chat(chat,
8174 gtk_entry_get_text(entry));
8175 }
8176 } 8232 }
8177 remove_edit_entry(user_data, GTK_WIDGET(entry)); 8233 remove_edit_entry(user_data, GTK_WIDGET(entry));
8178 } 8234 }
8179 8235
8180 static gboolean 8236 static gboolean
8181 alias_double_click_cb(GtkNotebook *notebook, GdkEventButton *event, PidginConversation *gtkconv) 8237 alias_double_click_cb(GtkWidget *widget, GdkEventButton *event, PidginConversation *gtkconv)
8182 { 8238 {
8183 GtkWidget *entry = NULL; 8239 GtkWidget *entry = NULL;
8240 PurpleConversation *conv = gtkconv->active_conv;
8241 const char *text = NULL;
8184 8242
8185 if (event->button != 1 || event->type != GDK_2BUTTON_PRESS) { 8243 if (event->button != 1 || event->type != GDK_2BUTTON_PRESS) {
8186 return FALSE; 8244 return FALSE;
8187 } 8245 }
8188 8246
8192 } 8250 }
8193 8251
8194 if (!purple_account_is_connected(gtkconv->active_conv->account)) { 8252 if (!purple_account_is_connected(gtkconv->active_conv->account)) {
8195 /* Do not allow aliasing someone on a disconnected account. */ 8253 /* Do not allow aliasing someone on a disconnected account. */
8196 return FALSE; 8254 return FALSE;
8255 }
8256
8257 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) {
8258 PurpleBuddy *buddy = purple_find_buddy(gtkconv->active_conv->account, gtkconv->active_conv->name);
8259 if (!buddy)
8260 return FALSE;
8261 text = purple_buddy_get_contact_alias(buddy);
8262 } else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
8263 text = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(conv));
8197 } 8264 }
8198 8265
8199 /* alias label */ 8266 /* alias label */
8200 entry = gtk_entry_new(); 8267 entry = gtk_entry_new();
8201 gtk_entry_set_has_frame(GTK_ENTRY(entry), FALSE); 8268 gtk_entry_set_has_frame(GTK_ENTRY(entry), FALSE);
8202 gtk_entry_set_width_chars(GTK_ENTRY(entry), 10); 8269 gtk_entry_set_width_chars(GTK_ENTRY(entry), 10);
8203 #if GTK_CHECK_VERSION(2,4,0) 8270 #if GTK_CHECK_VERSION(2,4,0)
8204 gtk_entry_set_alignment(GTK_ENTRY(entry), 0.5); 8271 gtk_entry_set_alignment(GTK_ENTRY(entry), 0.5);
8205 #endif 8272 #endif
8206 8273
8207 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), entry, TRUE, TRUE, 0); 8274 gtk_box_pack_start(GTK_BOX(gtkconv->infopane_hbox), entry, TRUE, TRUE, 0);
8208 /* after the tab label */ 8275 /* after the tab label */
8209 gtk_box_reorder_child(GTK_BOX(gtkconv->tabby), entry, 2); 8276 gtk_box_reorder_child(GTK_BOX(gtkconv->infopane_hbox), entry, 0);
8210 8277
8211 g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(alias_cb), gtkconv); 8278 g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(alias_cb), gtkconv);
8212 g_signal_connect(G_OBJECT(entry), "focus-out-event", G_CALLBACK(alias_focus_cb), gtkconv); 8279 g_signal_connect(G_OBJECT(entry), "focus-out-event", G_CALLBACK(alias_focus_cb), gtkconv);
8213 g_signal_connect(G_OBJECT(entry), "key-press-event", G_CALLBACK(alias_key_press_cb), gtkconv); 8280 g_signal_connect(G_OBJECT(entry), "key-press-event", G_CALLBACK(alias_key_press_cb), gtkconv);
8214 gtk_entry_set_text(GTK_ENTRY(entry), 8281
8215 gtk_label_get_text(GTK_LABEL(gtkconv->tab_label))); 8282
8283
8284 gtk_entry_set_text(GTK_ENTRY(entry), text);
8216 gtk_widget_show(entry); 8285 gtk_widget_show(entry);
8217 gtk_widget_hide(gtkconv->tab_label); 8286 gtk_widget_hide(gtkconv->infopane);
8218 gtk_widget_grab_focus(entry); 8287 gtk_widget_grab_focus(entry);
8219 8288
8220 return FALSE; 8289 return FALSE;
8221 } 8290 }
8222 8291
8426 #endif 8495 #endif
8427 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(win->notebook), pos); 8496 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(win->notebook), pos);
8428 gtk_notebook_set_scrollable(GTK_NOTEBOOK(win->notebook), TRUE); 8497 gtk_notebook_set_scrollable(GTK_NOTEBOOK(win->notebook), TRUE);
8429 gtk_notebook_popup_enable(GTK_NOTEBOOK(win->notebook)); 8498 gtk_notebook_popup_enable(GTK_NOTEBOOK(win->notebook));
8430 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE); 8499 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), FALSE);
8431 gtk_notebook_set_show_border(GTK_NOTEBOOK(win->notebook), FALSE); 8500 gtk_notebook_set_show_border(GTK_NOTEBOOK(win->notebook), TRUE);
8432 8501
8433 g_signal_connect(G_OBJECT(win->notebook), "button-press-event", 8502 g_signal_connect(G_OBJECT(win->notebook), "button-press-event",
8434 G_CALLBACK(right_click_menu_cb), win); 8503 G_CALLBACK(right_click_menu_cb), win);
8435 8504
8436 gtk_widget_show(win->notebook); 8505 gtk_widget_show(win->notebook);
8538 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 8607 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook),
8539 gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), 8608 gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook),
8540 gtkconv->tab_cont)); 8609 gtkconv->tab_cont));
8541 } 8610 }
8542 8611
8612 static gboolean
8613 close_button_left_cb(GtkWidget *widget, GdkEventCrossing *event, GtkLabel *label)
8614 {
8615 static GdkCursor *ptr = NULL;
8616 if (ptr == NULL) {
8617 ptr = gdk_cursor_new(GDK_LEFT_PTR);
8618 }
8619
8620 gtk_label_set_markup(label, "×");
8621 gdk_window_set_cursor(event->window, ptr);
8622 return FALSE;
8623 }
8624
8625 static gboolean
8626 close_button_entered_cb(GtkWidget *widget, GdkEventCrossing *event, GtkLabel *label)
8627 {
8628 static GdkCursor *hand = NULL;
8629 if (hand == NULL) {
8630 hand = gdk_cursor_new(GDK_HAND2);
8631 }
8632
8633 gtk_label_set_markup(label, "<u>×</u>");
8634 gdk_window_set_cursor(event->window, hand);
8635 return FALSE;
8636 }
8637
8543 void 8638 void
8544 pidgin_conv_window_add_gtkconv(PidginWindow *win, PidginConversation *gtkconv) 8639 pidgin_conv_window_add_gtkconv(PidginWindow *win, PidginConversation *gtkconv)
8545 { 8640 {
8546 PurpleConversation *conv = gtkconv->active_conv; 8641 PurpleConversation *conv = gtkconv->active_conv;
8547 PidginConversation *focus_gtkconv; 8642 PidginConversation *focus_gtkconv;
8560 8655
8561 8656
8562 /* Close button. */ 8657 /* Close button. */
8563 gtkconv->close = gtk_event_box_new(); 8658 gtkconv->close = gtk_event_box_new();
8564 gtk_event_box_set_visible_window(GTK_EVENT_BOX(gtkconv->close), FALSE); 8659 gtk_event_box_set_visible_window(GTK_EVENT_BOX(gtkconv->close), FALSE);
8565 close_image = gtk_label_new(NULL); 8660 gtk_widget_set_events(gtkconv->close, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
8566 gtk_label_set_markup(GTK_LABEL(close_image),"<b>×</b>"); 8661 close_image = gtk_label_new("×");
8662 g_signal_connect(G_OBJECT(gtkconv->close), "enter-notify-event", G_CALLBACK(close_button_entered_cb), close_image);
8663 g_signal_connect(G_OBJECT(gtkconv->close), "leave-notify-event", G_CALLBACK(close_button_left_cb), close_image);
8567 gtk_widget_show(close_image); 8664 gtk_widget_show(close_image);
8568 gtk_container_add(GTK_CONTAINER(gtkconv->close), close_image); 8665 gtk_container_add(GTK_CONTAINER(gtkconv->close), close_image);
8569 gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close, 8666 gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close,
8570 _("Close conversation"), NULL); 8667 _("Close conversation"), NULL);
8571 8668
8572 g_signal_connect(G_OBJECT(gtkconv->close), "button-press-event", 8669 g_signal_connect(G_OBJECT(gtkconv->close), "button-press-event",
8573 G_CALLBACK(close_conv_cb), gtkconv); 8670 G_CALLBACK(close_conv_cb), gtkconv);
8574 8671
8575 #if !GTK_CHECK_VERSION(2,6,0) 8672 #if !GTK_CHECK_VERSION(2,6,0)
8576 /* 8673 /*
8577 * I love Galeon. They have a fix for that stupid annoying visible 8674 * I love Galeon. They have a fix for that stupid annoying visible
8578 * border bug. I love you guys! -- ChipX86 8675 * border bug. I love you guys! -- ChipX86
8583 #endif 8680 #endif
8584 8681
8585 /* Status icon. */ 8682 /* Status icon. */
8586 gtkconv->icon = gtk_image_new(); 8683 gtkconv->icon = gtk_image_new();
8587 gtkconv->menu_icon = gtk_image_new(); 8684 gtkconv->menu_icon = gtk_image_new();
8685 gtk_widget_show(gtkconv->icon);
8588 update_tab_icon(conv); 8686 update_tab_icon(conv);
8589 8687
8590 /* Tab label. */ 8688 /* Tab label. */
8591 gtkconv->tab_label = gtk_label_new(tmp_lab = purple_conversation_get_title(conv)); 8689 gtkconv->tab_label = gtk_label_new(tmp_lab = purple_conversation_get_title(conv));
8592 8690
8593 gtkconv->menu_tabby = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); 8691 gtkconv->menu_tabby = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
8594 gtkconv->menu_label = gtk_label_new(purple_conversation_get_title(gtkconv->active_conv)); 8692 gtkconv->menu_label = gtk_label_new(tmp_lab);
8595 gtk_box_pack_start(GTK_BOX(gtkconv->menu_tabby), gtkconv->menu_icon, FALSE, FALSE, 0); 8693 gtk_box_pack_start(GTK_BOX(gtkconv->menu_tabby), gtkconv->menu_icon, FALSE, FALSE, 0);
8596 8694
8597 gtk_widget_show_all(gtkconv->menu_icon); 8695 gtk_widget_show_all(gtkconv->menu_icon);
8598 8696
8599 gtk_box_pack_start(GTK_BOX(gtkconv->menu_tabby), gtkconv->menu_label, TRUE, TRUE, 0); 8697 gtk_box_pack_start(GTK_BOX(gtkconv->menu_tabby), gtkconv->menu_label, TRUE, TRUE, 0);
8600 gtk_widget_show(gtkconv->menu_label); 8698 gtk_widget_show(gtkconv->menu_label);
8601 gtk_misc_set_alignment(GTK_MISC(gtkconv->menu_label), 0, 0); 8699 gtk_misc_set_alignment(GTK_MISC(gtkconv->menu_label), 0, 0);
8602 8700
8603 gtk_widget_show(gtkconv->menu_tabby); 8701 gtk_widget_show(gtkconv->menu_tabby);
8604 gtk_widget_set_size_request(gtkconv->menu_tabby, 0, -1);
8605 8702
8606 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) 8703 if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
8607 pidgin_conv_update_buddy_icon(conv); 8704 pidgin_conv_update_buddy_icon(conv);
8608 8705
8609 /* Build and set conversations tab */ 8706 /* Build and set conversations tab */
8614 gtk_widget_show(tab_cont); 8711 gtk_widget_show(tab_cont);
8615 8712
8616 if (pidgin_conv_window_get_gtkconv_count(win) == 1) { 8713 if (pidgin_conv_window_get_gtkconv_count(win) == 1) {
8617 /* Er, bug in notebooks? Switch to the page manually. */ 8714 /* Er, bug in notebooks? Switch to the page manually. */
8618 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0); 8715 gtk_notebook_set_current_page(GTK_NOTEBOOK(win->notebook), 0);
8619
8620 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook),
8621 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs"));
8622 } else { 8716 } else {
8623 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), TRUE); 8717 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook), TRUE);
8624 } 8718 }
8625 8719
8626 focus_gtkconv = g_list_nth_data(pidgin_conv_window_get_gtkconvs(win), 8720 focus_gtkconv = g_list_nth_data(pidgin_conv_window_get_gtkconvs(win),
8647 angle = 270; 8741 angle = 270;
8648 8742
8649 #if GTK_CHECK_VERSION(2,6,0) 8743 #if GTK_CHECK_VERSION(2,6,0)
8650 if (!angle && pidgin_conv_window_get_gtkconv_count(win) > 1) { 8744 if (!angle && pidgin_conv_window_get_gtkconv_count(win) > 1) {
8651 g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_END, NULL); 8745 g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
8652 gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), 6); 8746 gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), 4);
8653 } else { 8747 } else {
8654 g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_NONE, NULL); 8748 g_object_set(G_OBJECT(gtkconv->tab_label), "ellipsize", PANGO_ELLIPSIZE_NONE, NULL);
8655 gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), -1); 8749 gtk_label_set_width_chars(GTK_LABEL(gtkconv->tab_label), -1);
8656 } 8750 }
8657 8751
8687 ebox = gtk_event_box_new(); 8781 ebox = gtk_event_box_new();
8688 #if GTK_CHECK_VERSION(2,4,0) 8782 #if GTK_CHECK_VERSION(2,4,0)
8689 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE); 8783 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
8690 #endif 8784 #endif
8691 gtk_container_add(GTK_CONTAINER(ebox), gtkconv->tabby); 8785 gtk_container_add(GTK_CONTAINER(ebox), gtkconv->tabby);
8692 g_signal_connect(G_OBJECT(ebox), "button-press-event",
8693 G_CALLBACK(alias_double_click_cb), gtkconv);
8694 8786
8695 if (gtkconv->tab_label->parent == NULL) { 8787 if (gtkconv->tab_label->parent == NULL) {
8696 /* Pack if it's a new widget */ 8788 /* Pack if it's a new widget */
8697 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), first, FALSE, FALSE, 0); 8789 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), first, FALSE, FALSE, 0);
8698 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), gtkconv->tab_label, TRUE, TRUE, 0); 8790 gtk_box_pack_start(GTK_BOX(gtkconv->tabby), gtkconv->tab_label, TRUE, TRUE, 0);
8715 8807
8716 gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont, 8808 gtk_notebook_set_tab_label_packing(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont,
8717 !tabs_side && !angle && pidgin_conv_window_get_gtkconv_count(win) > 1, 8809 !tabs_side && !angle && pidgin_conv_window_get_gtkconv_count(win) > 1,
8718 TRUE, GTK_PACK_START); 8810 TRUE, GTK_PACK_START);
8719 8811
8812 if (pidgin_conv_window_get_gtkconv_count(win) == 1)
8813 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook),
8814 !purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/im/show_buddy_icons") ||
8815 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_LEFT ||
8816 purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_RIGHT);
8817
8720 /* show the widgets */ 8818 /* show the widgets */
8721 /* gtk_widget_show(gtkconv->icon); */ 8819 /* gtk_widget_show(gtkconv->icon); */
8722 gtk_widget_show(gtkconv->tab_label); 8820 gtk_widget_show(gtkconv->tab_label);
8723 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs")) 8821 if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/close_on_tabs"))
8724 gtk_widget_show(gtkconv->close); 8822 gtk_widget_show(gtkconv->close);
8737 8835
8738 g_object_ref(gtkconv->tab_cont); 8836 g_object_ref(gtkconv->tab_cont);
8739 gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont)); 8837 gtk_object_sink(GTK_OBJECT(gtkconv->tab_cont));
8740 8838
8741 gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index); 8839 gtk_notebook_remove_page(GTK_NOTEBOOK(win->notebook), index);
8742
8743 /* go back to tabless */
8744 if (pidgin_conv_window_get_gtkconv_count(win) <= 2) {
8745 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(win->notebook),
8746 purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/tabs"));
8747 }
8748 8840
8749 win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv); 8841 win->gtkconvs = g_list_remove(win->gtkconvs, gtkconv);
8750 8842
8751 if (win->gtkconvs && win->gtkconvs->next == NULL) 8843 if (win->gtkconvs && win->gtkconvs->next == NULL)
8752 pidgin_conv_tab_pack(win, win->gtkconvs->data); 8844 pidgin_conv_tab_pack(win, win->gtkconvs->data);