changeset 32597:b960be0f3423

propagate from branch 'im.pidgin.pidgin' (head 31e040ab1b9ac3ec6250c3e89b47f8df06c03879) to branch 'im.pidgin.cpw.qulogic.gtk3' (head 1153f36f9a7f396da1c60c96af0b347a9739a948)
author Elliott Sales de Andrade <qulogic@pidgin.im>
date Tue, 28 Jul 2009 05:49:14 +0000
parents 1b6ac48c5ffa (diff) 2e49cbdd5040 (current diff)
children fb50e2499748
files
diffstat 16 files changed, 1569 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/pidgin/gtkblist.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkblist.c	Tue Jul 28 05:49:14 2009 +0000
@@ -126,7 +126,12 @@
 #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \
 	((PidginBuddyListPrivate *)((list)->priv))
 
+#if GTK_CHECK_VERSION(2,4,0)
+static guint accounts_merge_id;
+static GtkActionGroup *accounts_action_group = NULL;
+#else
 static GtkWidget *accountmenu = NULL;
+#endif
 
 static guint visibility_manager_count = 0;
 static GdkVisibilityState gtk_blist_visibility = GDK_VISIBILITY_UNOBSCURED;
@@ -136,7 +141,6 @@
 static GList *pidgin_blist_sort_methods = NULL;
 static struct pidgin_blist_sort_method *current_sort_method = NULL;
 static void sort_method_none(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
-
 /* The functions we use for sorting aren't available in gtk 2.0.x, and
  * segfault in 2.2.0.  2.2.1 is known to work, so I'll require that */
 #if GTK_CHECK_VERSION(2,2,1)
@@ -144,6 +148,11 @@
 static void sort_method_status(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
 static void sort_method_log_activity(PurpleBlistNode *node, PurpleBuddyList *blist, GtkTreeIter groupiter, GtkTreeIter *cur, GtkTreeIter *iter);
 #endif
+#if GTK_CHECK_VERSION(2,4,0)
+static guint sort_merge_id;
+static GtkActionGroup *sort_action_group = NULL;
+#endif
+
 static PidginBuddyList *gtkblist = NULL;
 
 static GList *groups_tree(void);
@@ -154,7 +163,9 @@
 static void pidgin_blist_update_group(PurpleBuddyList *list, PurpleBlistNode *node);
 static void pidgin_blist_update_contact(PurpleBuddyList *list, PurpleBlistNode *node);
 static char *pidgin_get_tooltip_text(PurpleBlistNode *node, gboolean full);
+#if !GTK_CHECK_VERSION(2,4,0)
 static const char *item_factory_translate_func (const char *path, gpointer func_data);
+#endif
 static gboolean get_iter_from_node(PurpleBlistNode *node, GtkTreeIter *iter);
 static gboolean buddy_is_displayable(PurpleBuddy *buddy);
 static void redo_buddy_list(PurpleBuddyList *list, gboolean remove, gboolean rerender);
@@ -2057,6 +2068,67 @@
 	return handled;
 }
 
+#if GTK_CHECK_VERSION(2,4,0)
+
+static void gtk_blist_show_xfer_dialog_cb(GtkAction *item, gpointer data)
+{
+	pidgin_xfer_dialog_show(NULL);
+}
+
+static void pidgin_blist_buddy_details_cb(GtkToggleAction *item, gpointer data)
+{
+	pidgin_set_cursor(gtkblist->window, GDK_WATCH);
+
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons",
+			gtk_toggle_action_get_active(item));
+
+	pidgin_clear_cursor(gtkblist->window);
+}
+
+static void pidgin_blist_show_idle_time_cb(GtkToggleAction *item, gpointer data)
+{
+	pidgin_set_cursor(gtkblist->window, GDK_WATCH);
+
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time",
+			gtk_toggle_action_get_active(item));
+
+	pidgin_clear_cursor(gtkblist->window);
+}
+
+static void pidgin_blist_show_protocol_icons_cb(GtkToggleAction *item, gpointer data)
+{
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons",
+			gtk_toggle_action_get_active(item));
+}
+
+static void pidgin_blist_show_empty_groups_cb(GtkToggleAction *item, gpointer data)
+{
+	pidgin_set_cursor(gtkblist->window, GDK_WATCH);
+
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_empty_groups",
+			gtk_toggle_action_get_active(item));
+
+	pidgin_clear_cursor(gtkblist->window);
+}
+
+static void pidgin_blist_edit_mode_cb(GtkToggleAction *checkitem, gpointer data)
+{
+	pidgin_set_cursor(gtkblist->window, GDK_WATCH);
+
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies",
+			gtk_toggle_action_get_active(checkitem));
+
+	pidgin_clear_cursor(gtkblist->window);
+}
+
+static void pidgin_blist_mute_sounds_cb(GtkToggleAction *item, gpointer data)
+{
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute",
+			gtk_toggle_action_get_active(item));
+}
+
+#else /* GTK_CHECK_VERSION(2,4,0) */
+
 static void pidgin_blist_buddy_details_cb(gpointer data, guint action, GtkWidget *item)
 {
 	pidgin_set_cursor(gtkblist->window, GDK_WATCH);
@@ -2106,15 +2178,23 @@
 
 static void pidgin_blist_mute_sounds_cb(gpointer data, guint action, GtkWidget *item)
 {
-	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute", GTK_CHECK_MENU_ITEM(item)->active);
-}
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/sound/mute",
+			gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item)));
+}
+
+#endif /* GTK_CHECK_VERSION(2,4,0) */
 
 static void
 pidgin_blist_mute_pref_cb(const char *name, PurplePrefType type,
 							gconstpointer value, gpointer data)
 {
+#if GTK_CHECK_VERSION(2,4,0)
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui,
+						"/BList/ToolsMenu/MuteSounds")), (gboolean)GPOINTER_TO_INT(value));
+#else
 	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(gtkblist->ift,
 						N_("/Tools/Mute Sounds"))),	(gboolean)GPOINTER_TO_INT(value));
+#endif
 }
 
 static void
@@ -2126,7 +2206,11 @@
 	if(!strcmp(value, "none"))
 		sensitive = FALSE;
 
+#if GTK_CHECK_VERSION(2,4,0)
+	gtk_action_set_sensitive(gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/MuteSounds"), sensitive);
+#else
 	gtk_widget_set_sensitive(gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Mute Sounds")), sensitive);
+#endif
 }
 
 static void
@@ -3424,6 +3508,113 @@
 /***************************************************
  *            Crap                                 *
  ***************************************************/
+#if GTK_CHECK_VERSION(2,4,0)
+/* TODO: fill out tooltips... */
+static const GtkActionEntry blist_menu_entries[] = {
+	/* Buddies menu */
+	{ "BuddiesMenu", NULL, N_("_Buddies"), NULL, NULL, NULL },
+	{ "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "<control>M", NULL, pidgin_dialogs_im },
+	{ "JoinAChat", PIDGIN_STOCK_CHAT, N_("Join a _Chat..."), "<control>C", NULL, pidgin_blist_joinchat_show },
+	{ "GetUserInfo", PIDGIN_STOCK_TOOLBAR_USER_INFO, N_("Get User _Info..."), "<control>I", NULL, pidgin_dialogs_info },
+	{ "ViewUserLog", NULL, N_("View User _Log..."), "<control>L", NULL, pidgin_dialogs_log },
+	{ "ShowMenu", NULL, N_("Sh_ow"), NULL, NULL, NULL },
+	{ "SortMenu", NULL, N_("_Sort Buddies"), NULL, NULL, NULL },
+	{ "AddBuddy", GTK_STOCK_ADD, N_("_Add Buddy..."), "<control>B", NULL, pidgin_blist_add_buddy_cb },
+	{ "AddChat", GTK_STOCK_ADD, N_("Add C_hat..."), NULL, NULL, pidgin_blist_add_chat_cb },
+	{ "AddGroup", GTK_STOCK_ADD, N_("Add _Group..."), NULL, NULL, purple_blist_request_add_group },
+	{ "Quit", GTK_STOCK_QUIT, N_("_Quit"), "<control>Q", NULL, purple_core_quit },
+
+	/* Accounts menu */
+	{ "AccountsMenu", NULL, N_("_Accounts"), NULL, NULL, NULL },
+	{ "ManageAccounts", NULL, N_("Manage Accounts"), "<control>A", NULL, pidgin_accounts_window_show },
+	{ "EnableAccountMenu", NULL, N_("Enable Account"), NULL, NULL, NULL },
+
+	/* Tools */
+	{ "ToolsMenu", NULL, N_("_Tools"), NULL, NULL, NULL },
+	{ "BuddyPounces", NULL, N_("Buddy _Pounces"), NULL, NULL, pidgin_pounces_manager_show },
+	{ "Certificates", NULL, N_("_Certificates"), NULL, NULL, pidgin_certmgr_show },
+	{ "CustomSmileys", PIDGIN_STOCK_TOOLBAR_SMILEY, N_("Custom Smile_ys"), "<control>Y", NULL, pidgin_smiley_manager_show },
+	{ "Plugins", PIDGIN_STOCK_TOOLBAR_PLUGINS, N_("Plu_gins"), "<control>U", NULL, pidgin_plugin_dialog_show },
+	{ "Preferences", GTK_STOCK_PREFERENCES, N_("Pr_eferences"), "<control>P", NULL, pidgin_prefs_show },
+	{ "Privacy", NULL, N_("Pr_ivacy"), NULL, NULL, pidgin_privacy_dialog_show },
+	{ "FileTransfers", PIDGIN_STOCK_TOOLBAR_TRANSFER, N_("_File Transfers"), "<control>T", NULL, G_CALLBACK(gtk_blist_show_xfer_dialog_cb) },
+	{ "RoomList", NULL, N_("R_oom List"), NULL, NULL, pidgin_roomlist_dialog_show },
+	{ "SystemLog", NULL, N_("System _Log"), NULL, NULL, gtk_blist_show_systemlog_cb },
+
+	/* Help */
+	{ "HelpMenu", NULL, N_("_Help"), NULL, NULL, NULL },
+	{ "OnlineHelp", GTK_STOCK_HELP, N_("Online _Help"), "F1", NULL, gtk_blist_show_onlinehelp_cb },
+	{ "DebugWindow", NULL, N_("_Debug Window"), NULL, NULL, toggle_debug },
+	{ "About", GTK_STOCK_ABOUT, N_("_About"), NULL, NULL, pidgin_dialogs_about },
+};
+
+/* Toggle items */
+static const GtkToggleActionEntry blist_menu_toggle_entries[] = {
+	/* Buddies->Show menu */
+	{ "ShowOffline", NULL, N_("_Offline Buddies"), NULL, NULL, G_CALLBACK(pidgin_blist_edit_mode_cb), FALSE },
+	{ "ShowEmptyGroups", NULL, N_("_Empty Groups"), NULL, NULL, G_CALLBACK(pidgin_blist_show_empty_groups_cb), FALSE },
+	{ "ShowBuddyDetails", NULL, N_("Buddy _Details"), NULL, NULL, G_CALLBACK(pidgin_blist_buddy_details_cb), FALSE },
+	{ "ShowIdleTimes", NULL, N_("Idle _Times"), NULL, NULL, G_CALLBACK(pidgin_blist_show_idle_time_cb), FALSE },
+	{ "ShowProtocolIcons", NULL, N_("_Protocol Icons"), NULL, NULL, G_CALLBACK(pidgin_blist_show_protocol_icons_cb), FALSE },
+
+	/* Tools menu */
+	{ "MuteSounds", NULL, N_("Mute _Sounds"), NULL, NULL, G_CALLBACK(pidgin_blist_mute_sounds_cb), FALSE },
+};
+
+static const char *blist_menu =
+"<ui>"
+	"<menubar name='BList'>"
+		"<menu action='BuddiesMenu'>"
+			"<menuitem action='NewInstantMessage'/>"
+			"<menuitem action='JoinAChat'/>"
+			"<menuitem action='GetUserInfo'/>"
+			"<menuitem action='ViewUserLog'/>"
+			"<separator/>"
+			"<menu action='ShowMenu'>"
+				"<menuitem action='ShowOffline'/>"
+				"<menuitem action='ShowEmptyGroups'/>"
+				"<menuitem action='ShowBuddyDetails'/>"
+				"<menuitem action='ShowIdleTimes'/>"
+				"<menuitem action='ShowProtocolIcons'/>"
+			"</menu>"
+			"<menu action='SortMenu'/>"
+			"<separator/>"
+			"<menuitem action='AddBuddy'/>"
+			"<menuitem action='AddChat'/>"
+			"<menuitem action='AddGroup'/>"
+			"<separator/>"
+			"<menuitem action='Quit'/>"
+		"</menu>"
+		"<menu action='AccountsMenu'>"
+			"<menuitem action='ManageAccounts'/>"
+			"<menu action='EnableAccountMenu'/>"
+			"<separator/>"
+			"<placeholder name='Accounts'/>"
+		"</menu>"
+		"<menu action='ToolsMenu'>"
+			"<menuitem action='BuddyPounces'/>"
+			"<menuitem action='Certificates'/>"
+			"<menuitem action='Plugins'/>"
+			"<menuitem action='Preferences'/>"
+			"<menuitem action='Privacy'/>"
+			"<menuitem action='CustomSmileys'/>"
+			"<separator/>"
+			"<menuitem action='FileTransfers'/>"
+			"<menuitem action='RoomList'/>"
+			"<menuitem action='SystemLog'/>"
+			"<separator/>"
+			"<menuitem action='MuteSounds'/>"
+			"<placeholder name='PluginActions'/>"
+		"</menu>"
+		"<menu action='HelpMenu'>"
+			"<menuitem action='OnlineHelp'/>"
+			"<menuitem action='DebugWindow'/>"
+			"<menuitem action='About'/>"
+		"</menu>"
+	"</menubar>"
+"</ui>";
+
+#else
 static GtkItemFactoryEntry blist_menu[] =
 {
 	/* Buddies menu */
@@ -3469,12 +3660,9 @@
 	{ N_("/_Help"), NULL, NULL, 0, "<Branch>", NULL },
 	{ N_("/Help/Online _Help"), "F1", gtk_blist_show_onlinehelp_cb, 0, "<StockItem>", GTK_STOCK_HELP },
 	{ N_("/Help/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL },
-#if GTK_CHECK_VERSION(2,6,0)
-	{ N_("/Help/_About"), NULL, pidgin_dialogs_about, 4,  "<StockItem>", GTK_STOCK_ABOUT },
-#else
 	{ N_("/Help/_About"), NULL, pidgin_dialogs_about, 4,  "<Item>", NULL },
+};
 #endif
-};
 
 /*********************************************************
  * Private Utility functions                             *
@@ -4299,12 +4487,21 @@
 
 static const char *require_connection[] =
 {
+#if GTK_CHECK_VERSION(2,4,0)
+	"/BList/BuddiesMenu/NewInstantMessage",
+	"/BList/BuddiesMenu/JoinAChat",
+	"/BList/BuddiesMenu/GetUserInfo",
+	"/BList/BuddiesMenu/AddBuddy",
+	"/BList/BuddiesMenu/AddChat",
+	"/BList/BuddiesMenu/AddGroup",
+#else
 	N_("/Buddies/New Instant Message..."),
 	N_("/Buddies/Join a Chat..."),
 	N_("/Buddies/Get User Info..."),
 	N_("/Buddies/Add Buddy..."),
 	N_("/Buddies/Add Chat..."),
 	N_("/Buddies/Add Group..."),
+#endif
 };
 
 static const int require_connection_size = sizeof(require_connection)
@@ -4317,7 +4514,11 @@
 static void
 update_menu_bar(PidginBuddyList *gtkblist)
 {
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkAction *action;
+#else
 	GtkWidget *widget;
+#endif
 	gboolean sensitive;
 	int i;
 
@@ -4327,6 +4528,25 @@
 
 	sensitive = (purple_connections_get_all() != NULL);
 
+#if GTK_CHECK_VERSION(2,4,0)
+	for (i = 0; i < require_connection_size; i++)
+	{
+		action = gtk_ui_manager_get_action(gtkblist->ui, require_connection[i]);
+		gtk_action_set_sensitive(action, sensitive);
+	}
+
+	action = gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/JoinAChat");
+	gtk_action_set_sensitive(action, pidgin_blist_joinchat_is_showable());
+
+	action = gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/AddChat");
+	gtk_action_set_sensitive(action, pidgin_blist_joinchat_is_showable());
+
+	action = gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/Privacy");
+	gtk_action_set_sensitive(action, sensitive);
+
+	action = gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/RoomList");
+	gtk_action_set_sensitive(action, pidgin_roomlist_is_showable());
+#else
 	for (i = 0; i < require_connection_size; i++)
 	{
 		widget = gtk_item_factory_get_widget(gtkblist->ift, require_connection[i]);
@@ -4344,6 +4564,7 @@
 
 	widget = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Room List"));
 	gtk_widget_set_sensitive(widget, pidgin_roomlist_is_showable());
+#endif
 }
 
 static void
@@ -4634,11 +4855,13 @@
 	NUM_TARGETS
 };
 
+#if !GTK_CHECK_VERSION(2,4,0)
 static const char *
 item_factory_translate_func (const char *path, gpointer func_data)
 {
 	return _((char *)path);
 }
+#endif
 
 void pidgin_blist_setup_sort_methods()
 {
@@ -5365,8 +5588,28 @@
 headline_style_set (GtkWidget *widget,
 		    GtkStyle  *prev_style)
 {
+	GtkStyle *style;
+#if GTK_CHECK_VERSION(2,12,0)
+	GtkWidget *window;
+
+	if (gtkblist->changing_style)
+		return;
+
+	/* This is a hack needed to use the tooltip background colour */
+	window = gtk_window_new(GTK_WINDOW_POPUP);
+	gtk_widget_set_name(window, "gtk-tooltip");
+	gtk_widget_ensure_style(window);
+	style = gtk_widget_get_style(window);
+
+	gtkblist->changing_style = TRUE;
+	gtk_widget_set_style(gtkblist->headline_hbox, style);
+	gtkblist->changing_style = FALSE;
+
+	gtk_widget_destroy(window);
+
+	gtk_widget_queue_draw(gtkblist->headline_hbox);
+#else
 	GtkTooltips *tooltips;
-	GtkStyle *style;
 
 	if (gtkblist->changing_style)
 		return;
@@ -5391,6 +5634,7 @@
 	gtkblist->changing_style = FALSE;
 
 	g_object_unref (tooltips);
+#endif
 }
 
 /******************************************/
@@ -5602,6 +5846,10 @@
 	GtkWidget *label;
 	char *pretty, *tmp;
 	const char *theme_name;
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkActionGroup *action_group;
+	GError *error;
+#endif
 	GtkAccelGroup *accel_group;
 	GtkTreeSelection *selection;
 	GtkTargetEntry dte[] = {{"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, DRAG_ROW},
@@ -5651,6 +5899,42 @@
 	gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK);
 
 	/******************************* Menu bar *************************************/
+#if GTK_CHECK_VERSION(2,4,0)
+	action_group = gtk_action_group_new("BListActions");
+	gtk_action_group_add_actions(action_group,
+	                             blist_menu_entries,
+	                             G_N_ELEMENTS(blist_menu_entries),
+	                             GTK_WINDOW(gtkblist->window));
+	gtk_action_group_add_toggle_actions(action_group,
+	                                    blist_menu_toggle_entries,
+	                                    G_N_ELEMENTS(blist_menu_toggle_entries),
+	                                    GTK_WINDOW(gtkblist->window));
+#ifdef ENABLE_NLS
+	gtk_action_group_set_translation_domain(action_group,
+	                                        PACKAGE);
+#endif
+
+	gtkblist->ui = gtk_ui_manager_new();
+	gtk_ui_manager_insert_action_group(gtkblist->ui, action_group, 0);
+
+	accel_group = gtk_ui_manager_get_accel_group(gtkblist->ui);
+	gtk_window_add_accel_group(GTK_WINDOW(gtkblist->window), accel_group);
+
+	error = NULL;
+	if (!gtk_ui_manager_add_ui_from_string(gtkblist->ui, blist_menu, -1, &error))
+	{
+		g_message("building menus failed: %s", error->message);
+		g_error_free(error);
+		exit(EXIT_FAILURE);
+	}
+
+	menu = gtk_ui_manager_get_widget(gtkblist->ui, "/BList");
+	gtkblist->menutray = pidgin_menu_tray_new();
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtkblist->menutray);
+	gtk_widget_show(gtkblist->menutray);
+	gtk_widget_show(menu);
+	gtk_box_pack_start(GTK_BOX(gtkblist->main_vbox), menu, FALSE, FALSE, 0);
+#else
 	accel_group = gtk_accel_group_new();
 	gtk_window_add_accel_group(GTK_WINDOW (gtkblist->window), accel_group);
 	g_object_unref(accel_group);
@@ -5658,7 +5942,7 @@
 	gtk_item_factory_set_translate_func(gtkblist->ift,
 										(GtkTranslateFunc)item_factory_translate_func,
 										NULL, NULL);
-	gtk_item_factory_create_items(gtkblist->ift, sizeof(blist_menu) / sizeof(*blist_menu),
+	gtk_item_factory_create_items(gtkblist->ift, G_N_ENTRIES(blist_menu),
 								  blist_menu, NULL);
 	pidgin_load_accels();
 	g_signal_connect(G_OBJECT(accel_group), "accel-changed", G_CALLBACK(pidgin_save_accels_cb), NULL);
@@ -5671,7 +5955,7 @@
 	gtk_box_pack_start(GTK_BOX(gtkblist->main_vbox), menu, FALSE, FALSE, 0);
 
 	accountmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Accounts"));
-
+#endif
 
 	/****************************** Notebook *************************************/
 	gtkblist->notebook = gtk_notebook_new();
@@ -5860,6 +6144,30 @@
 	/* set the Show Offline Buddies option. must be done
 	 * after the treeview or faceprint gets mad. -Robot101
 	 */
+#if GTK_CHECK_VERSION(2,4,0)
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowOffline")),
+			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies"));
+
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowEmptyGroups")),
+			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_empty_groups"));
+
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/MuteSounds")),
+			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/sound/mute"));
+
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowBuddyDetails")),
+			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_buddy_icons"));
+
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowIdleTimes")),
+			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_idle_time"));
+
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtk_ui_manager_get_action(gtkblist->ui, "/BList/BuddiesMenu/ShowMenu/ShowProtocolIcons")),
+			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_protocol_icons"));
+
+	if(!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"), "none"))
+		gtk_action_set_sensitive(gtk_ui_manager_get_action(gtkblist->ui, "/BList/ToolsMenu/MuteSounds"), FALSE);
+
+#else
+
 	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item (gtkblist->ift, N_("/Buddies/Show/Offline Buddies"))),
 			purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/show_offline_buddies"));
 
@@ -5880,6 +6188,7 @@
 
 	if(!strcmp(purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method"), "none"))
 		gtk_widget_set_sensitive(gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools/Mute Sounds")), FALSE);
+#endif
 
 	/* Update some dynamic things */
 	update_menu_bar(gtkblist);
@@ -6756,7 +7065,11 @@
 	gtkblist->window = gtkblist->vbox = gtkblist->treeview = NULL;
 	g_object_unref(G_OBJECT(gtkblist->treemodel));
 	gtkblist->treemodel = NULL;
+#if GTK_CHECK_VERSION(2,4,0)
+	g_object_unref(G_OBJECT(gtkblist->ui));
+#else
 	g_object_unref(G_OBJECT(gtkblist->ift));
+#endif
 	g_object_unref(G_OBJECT(gtkblist->empty_avatar));
 
 	gdk_cursor_unref(gtkblist->hand_cursor);
@@ -6770,7 +7083,9 @@
 	g_free(priv);
 
 	g_free(gtkblist);
+#if !GTK_CHECK_VERSION(2,4,0)
 	accountmenu = NULL;
+#endif
 	gtkblist = NULL;
 	purple_prefs_disconnect_by_handle(pidgin_blist_get_handle());
 }
@@ -7774,6 +8089,45 @@
 		pam->callback(pam);
 }
 
+#if GTK_CHECK_VERSION(2,4,0)
+static void
+build_plugin_actions(GtkActionGroup *action_group, GString *ui, char *parent,
+		PurplePlugin *plugin, gpointer context)
+{
+	GtkAction *menuaction;
+	PurplePluginAction *action = NULL;
+	GList *actions, *l;
+	char *name;
+	int count = 0;
+
+	actions = PURPLE_PLUGIN_ACTIONS(plugin, context);
+
+	for (l = actions; l != NULL; l = l->next) {
+		if (l->data) {
+			action = (PurplePluginAction *)l->data;
+			action->plugin = plugin;
+			action->context = context;
+
+			name = g_strdup_printf("%s-action-%d", parent, count++);
+			menuaction = gtk_action_new(name, action->label, NULL, NULL);
+			gtk_action_group_add_action(action_group, menuaction);
+			g_string_append_printf(ui, "<menuitem action='%s'/>", name);
+
+			g_signal_connect(G_OBJECT(menuaction), "activate",
+					G_CALLBACK(plugin_act), action);
+			g_object_set_data_full(G_OBJECT(menuaction), "plugin_action",
+								   action,
+								   (GDestroyNotify)purple_plugin_action_free);
+			g_free(name);
+		}
+		else
+			g_string_append(ui, "<separator/>");
+	}
+
+	g_list_free(actions);
+}
+
+#else
 static void
 build_plugin_actions(GtkWidget *menu, PurplePlugin *plugin,
 		gpointer context)
@@ -7808,6 +8162,7 @@
 
 	g_list_free(actions);
 }
+#endif
 
 static void
 modify_account_cb(GtkWidget *widget, gpointer data)
@@ -7838,9 +8193,114 @@
 void
 pidgin_blist_update_accounts_menu(void)
 {
+	GList *accounts = NULL;
+
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkAction *action;
+	GString *accounts_ui;
+	GString *enable_ui;
+	gchar *ui_string;
+	int count = 0;
+
+	if ((gtkblist == NULL) || (gtkblist->ui == NULL))
+		return;
+
+	/* Clear the old menu */
+	if (accounts_action_group) {
+		gtk_ui_manager_remove_ui(gtkblist->ui, accounts_merge_id);
+		gtk_ui_manager_remove_action_group(gtkblist->ui, accounts_action_group);
+		g_object_unref(G_OBJECT(accounts_action_group));
+	}
+
+	accounts_action_group = gtk_action_group_new("Accounts");
+#ifdef ENABLE_NLS
+	gtk_action_group_set_translation_domain(accounts_action_group, PACKAGE);
+#endif
+	accounts_ui = g_string_new(NULL);
+	enable_ui = g_string_new(NULL);
+
+	action = gtk_action_new("none-available", N_("No actions available"), NULL, NULL);
+	gtk_action_group_add_action(accounts_action_group, action);
+	gtk_action_set_sensitive(action, FALSE);
+
+	for (accounts = purple_accounts_get_all(); accounts; accounts = accounts->next) {
+		char *label;
+		char *base;
+		char *name;
+		PurpleAccount *account = NULL;
+
+		account = accounts->data;
+
+		base = name = g_strdup_printf("account%d", count);
+		label = g_strconcat(purple_account_get_username(account), " (",
+				purple_account_get_protocol_name(account), ")", NULL);
+		action = gtk_action_new(name, label, NULL, NULL);
+		g_free(label);
+		gtk_action_group_add_action(accounts_action_group, action);
+
+		if (!purple_account_get_enabled(account, PIDGIN_UI)) {
+			g_string_append_printf(enable_ui, "<menuitem action='%s'/>", name);
+			g_signal_connect(G_OBJECT(action), "activate",
+			                 G_CALLBACK(enable_account_cb), account);
+
+		} else {
+			PurpleConnection *gc = NULL;
+			PurplePlugin *plugin = NULL;
+
+			g_string_append_printf(accounts_ui, "<menu action='%s'>", name);
+
+			name = g_strconcat(base, "-edit", NULL);
+			action = gtk_action_new(name, N_("_Edit Account"), NULL, NULL);
+			gtk_action_group_add_action(accounts_action_group, action);
+			g_signal_connect(G_OBJECT(action), "activate",
+			                 G_CALLBACK(modify_account_cb), account);
+			g_string_append_printf(accounts_ui, "<menuitem action='%s'/>", name);
+			g_free(name);
+
+			g_string_append(accounts_ui, "<separator/>");
+
+			gc = purple_account_get_connection(account);
+			plugin = gc && PURPLE_CONNECTION_IS_CONNECTED(gc) ? gc->prpl : NULL;
+			if (plugin && PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
+				build_plugin_actions(accounts_action_group, accounts_ui, base, plugin, gc);
+			} else {
+				g_string_append(accounts_ui, "<menuitem action='none-available'/>");
+			}
+
+			g_string_append(accounts_ui, "<separator/>");
+
+			name = g_strconcat(base, "-disable", NULL);
+			action = gtk_action_new(name, N_("_Disable"), NULL, NULL);
+			gtk_action_group_add_action(accounts_action_group, action);
+			g_signal_connect(G_OBJECT(action), "activate",
+			                 G_CALLBACK(disable_account_cb), account);
+			g_string_append_printf(accounts_ui, "<menuitem action='%s'/>", name);
+			g_free(name);
+
+			g_string_append(accounts_ui, "</menu>");
+		}
+
+		g_free(base);
+		count++;
+	}
+
+	ui_string = g_strconcat("<ui><menubar action='BList'><menu action='AccountsMenu'><menu action='EnableAccountMenu'>",
+	                        enable_ui->str,
+	                        "</menu><placeholder name='Accounts'>",
+	                        accounts_ui->str,
+	                        "</placeholder></menu></menubar></ui>",
+	                        NULL);
+	gtk_ui_manager_insert_action_group(gtkblist->ui, accounts_action_group, 1);
+	accounts_merge_id = gtk_ui_manager_add_ui_from_string(gtkblist->ui, ui_string, -1, NULL);
+purple_debug_info("blist", "The account menu is {%s}\n", ui_string);
+
+	g_string_free(enable_ui, TRUE);
+	g_string_free(accounts_ui, TRUE);
+	g_free(ui_string);
+#else
 	GtkWidget *menuitem = NULL, *submenu = NULL;
+	GList *l = NULL;
 	GtkAccelGroup *accel_group = NULL;
-	GList *l = NULL, *accounts = NULL;
 	gboolean disabled_accounts = FALSE;
 	gboolean enabled_accounts = FALSE;
 
@@ -7969,18 +8429,82 @@
 		gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
 	}
 	gtk_widget_show_all(accountmenu);
-}
-
+#endif
+}
+
+#if GTK_CHECK_VERSION(2,4,0)
+static guint plugins_merge_id;
+static GtkActionGroup *plugins_action_group = NULL;
+#else
 static GList *plugin_submenus = NULL;
+#endif
 
 void
 pidgin_blist_update_plugin_actions(void)
 {
-	GtkWidget *menuitem, *submenu;
 	PurplePlugin *plugin = NULL;
 	GList *l;
+
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkAction *action;
+	GString *plugins_ui;
+	gchar *ui_string;
+	int count = 0;
+
+	if ((gtkblist == NULL) || (gtkblist->ui == NULL))
+		return;
+
+	/* Clear the old menu */
+	if (plugins_action_group) {
+		gtk_ui_manager_remove_ui(gtkblist->ui, plugins_merge_id);
+		gtk_ui_manager_remove_action_group(gtkblist->ui, plugins_action_group);
+		g_object_unref(G_OBJECT(plugins_action_group));
+	}
+
+	plugins_action_group = gtk_action_group_new("Accounts");
+#ifdef ENABLE_NLS
+	gtk_action_group_set_translation_domain(plugins_action_group, PACKAGE);
+#endif
+	plugins_ui = g_string_new(NULL);
+
+	/* Add a submenu for each plugin with custom actions */
+	for (l = purple_plugins_get_loaded(); l; l = l->next) {
+		char *name;
+
+		plugin = (PurplePlugin *)l->data;
+
+		if (PURPLE_IS_PROTOCOL_PLUGIN(plugin))
+			continue;
+
+		if (!PURPLE_PLUGIN_HAS_ACTIONS(plugin))
+			continue;
+
+		name = g_strdup_printf("plugin%d", count);
+		action = gtk_action_new(name, plugin->info->name, NULL, NULL);
+		gtk_action_group_add_action(plugins_action_group, action);
+		g_string_append_printf(plugins_ui, "<menu action='%s'>", name);
+
+		build_plugin_actions(plugins_action_group, plugins_ui, name, plugin, NULL);
+
+		g_string_append(plugins_ui, "</menu>");
+		count++;
+
+		g_free(name);
+	}
+
+	ui_string = g_strconcat("<ui><menubar action='BList'><menu action='ToolsMenu'><placeholder name='PluginActions'>",
+	                        plugins_ui->str,
+	                        "</placeholder></menu></menubar></ui>",
+	                        NULL);
+	gtk_ui_manager_insert_action_group(gtkblist->ui, plugins_action_group, 1);
+	plugins_merge_id = gtk_ui_manager_add_ui_from_string(gtkblist->ui, ui_string, -1, NULL);
+purple_debug_info("blist", "The plugins menu is {%s}\n", ui_string);
+
+	g_string_free(plugins_ui, TRUE);
+	g_free(ui_string);
+#else
+	GtkWidget *menuitem, *submenu;
 	GtkAccelGroup *accel_group;
-
 	GtkWidget *pluginmenu = gtk_item_factory_get_widget(gtkblist->ift, N_("/Tools"));
 
 	g_return_if_fail(pluginmenu != NULL);
@@ -8021,8 +8545,24 @@
 		build_plugin_actions(submenu, plugin, NULL);
 	}
 	gtk_widget_show_all(pluginmenu);
-}
-
+#endif
+}
+
+#if GTK_CHECK_VERSION(2,4,0)
+static void
+sortmethod_act(GtkRadioAction *action, GtkRadioAction *current, char *id)
+{
+	if (action == current)
+	{
+		pidgin_set_cursor(gtkblist->window, GDK_WATCH);
+		/* This is redundant. I think. */
+		/* pidgin_blist_sort_method_set(id); */
+		purple_prefs_set_string(PIDGIN_PREFS_ROOT "/blist/sort_type", id);
+
+		pidgin_clear_cursor(gtkblist->window);
+	}
+}
+#else
 static void
 sortmethod_act(GtkCheckMenuItem *checkmenuitem, char *id)
 {
@@ -8036,16 +8576,68 @@
 		pidgin_clear_cursor(gtkblist->window);
 	}
 }
+#endif
 
 void
 pidgin_blist_update_sort_methods(void)
 {
-	GtkWidget *menuitem = NULL, *activeitem = NULL;
 	PidginBlistSortMethod *method = NULL;
 	GList *l;
 	GSList *sl = NULL;
+	const char *m = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/sort_type");
+
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkRadioAction *action;
+	GString *ui_string;
+
+	if ((gtkblist == NULL) || (gtkblist->ui == NULL))
+		return;
+
+	/* Clear the old menu */
+	if (sort_action_group) {
+		gtk_ui_manager_remove_ui(gtkblist->ui, sort_merge_id);
+		gtk_ui_manager_remove_action_group(gtkblist->ui, sort_action_group);
+		g_object_unref(G_OBJECT(sort_action_group));
+	}
+
+	sort_action_group = gtk_action_group_new("SortMethods");
+#ifdef ENABLE_NLS
+	gtk_action_group_set_translation_domain(sort_action_group, PACKAGE);
+#endif
+	ui_string = g_string_new("<ui><menubar name='BList'>"
+	                         "<menu action='BuddiesMenu'><menu action='SortMenu'>");
+
+	for (l = pidgin_blist_sort_methods; l; l = l->next) {
+		method = (PidginBlistSortMethod *)l->data;
+
+		g_string_append_printf(ui_string, "<menuitem action='%s'/>", method->id);
+		action = gtk_radio_action_new(method->id,
+		                              method->name,
+		                              NULL,
+		                              NULL,
+		                              0);
+		gtk_action_group_add_action_with_accel(sort_action_group, GTK_ACTION(action), NULL);
+
+		gtk_radio_action_set_group(action, sl);
+		sl = gtk_radio_action_get_group(action);
+
+		if (!strcmp(m, method->id))
+			gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), TRUE);
+		else
+			gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), FALSE);
+
+		g_signal_connect(G_OBJECT(action), "changed",
+		                 G_CALLBACK(sortmethod_act), method->id);
+	}
+
+	g_string_append(ui_string, "</menu></menu></menubar></ui>");
+	gtk_ui_manager_insert_action_group(gtkblist->ui, sort_action_group, 1);
+	sort_merge_id = gtk_ui_manager_add_ui_from_string(gtkblist->ui, ui_string->str, -1, NULL);
+
+	g_string_free(ui_string, TRUE);
+#else
+	GtkWidget *menuitem = NULL, *activeitem = NULL;
 	GtkWidget *sortmenu;
-	const char *m = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/blist/sort_type");
 
 	if ((gtkblist == NULL) || (gtkblist->ift == NULL))
 		return;
@@ -8076,4 +8668,5 @@
 	}
 	if (activeitem)
 		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(activeitem), TRUE);
-}
+#endif
+}
--- a/pidgin/gtkblist.h	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkblist.h	Tue Jul 28 05:49:14 2009 +0000
@@ -82,7 +82,11 @@
 
 	GtkCellRenderer *text_rend;
 
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkUIManager *ui;
+#else
 	GtkItemFactory *ift;
+#endif
 	GtkWidget *menutray;            /**< The menu tray widget. */
 	GtkWidget *menutrayicon;        /**< The menu tray icon. */
 
--- a/pidgin/gtkconv.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkconv.c	Tue Jul 28 05:49:14 2009 +0000
@@ -160,7 +160,9 @@
 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state);
 static void update_typing_icon(PidginConversation *gtkconv);
 static void update_typing_message(PidginConversation *gtkconv, const char *message);
+#if !GTK_CHECK_VERSION(2,6,0)
 static const char *item_factory_translate_func (const char *path, gpointer func_data);
+#endif
 gboolean pidgin_conv_has_focus(PurpleConversation *conv);
 static GdkColor* generate_nick_colors(guint *numcolors, GdkColor background);
 static gboolean color_is_visible(GdkColor foreground, GdkColor background, int color_contrast, int brightness_contrast);
@@ -953,7 +955,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_new_conv_cb(GtkAction *action, gpointer data)
+#else
 menu_new_conv_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	pidgin_dialogs_im();
 }
@@ -994,7 +1000,11 @@
  * plaintext v. HTML file.
  */
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_save_as_cb(GtkAction *action, gpointer data)
+#else
 menu_save_as_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
@@ -1024,7 +1034,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_view_log_cb(GtkAction *action, gpointer data)
+#else
 menu_view_log_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1051,7 +1065,7 @@
 	gdk_window_set_cursor(gtkblist->window->window, cursor);
 	gdk_window_set_cursor(win->window->window, cursor);
 	gdk_cursor_unref(cursor);
-#if GTK_CHECK_VERSION(2,4,0)
+#if GTK_CHECK_VERSION(2,4,0) && !GTK_CHECK_VERSION(2,6,0) //FIXME: What?
 	gdk_display_flush(gdk_drawable_get_display(GDK_DRAWABLE(widget->window)));
 #else
 	gdk_flush();
@@ -1082,7 +1096,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_clear_cb(GtkAction *action, gpointer data)
+#else
 menu_clear_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1143,7 +1161,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_find_cb(GtkAction *action, gpointer data)
+#else
 menu_find_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *gtkwin = data;
 	GtkWidget *hbox;
@@ -1203,6 +1225,21 @@
 
 #ifdef USE_VV
 static void 
+#if GTK_CHECK_VERSION(2,6,0)
+menu_initiate_media_call_cb(GtkAction *action, gpointer data)
+{
+	PidginWindow *win = (PidginWindow *)data;
+	PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
+	PurpleAccount *account = purple_conversation_get_account(conv);
+
+	purple_prpl_initiate_media(account,
+			purple_conversation_get_name(conv),
+			action == win->audio_call ? PURPLE_MEDIA_AUDIO :
+			action == win->video_call ? PURPLE_MEDIA_VIDEO :
+			action == win->audio_video_call ? PURPLE_MEDIA_AUDIO |
+			PURPLE_MEDIA_VIDEO : PURPLE_MEDIA_NONE);
+}
+#else
 menu_initiate_media_call_cb(gpointer data, guint action, GtkWidget *widget)
 {
 	PidginWindow *win = (PidginWindow *)data;
@@ -1217,9 +1254,14 @@
 			PURPLE_MEDIA_VIDEO : PURPLE_MEDIA_NONE);
 }
 #endif
-
-static void
+#endif
+
+static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_send_file_cb(GtkAction *action, gpointer data)
+#else
 menu_send_file_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv = pidgin_conv_window_get_active_conversation(win);
@@ -1231,7 +1273,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_add_pounce_cb(GtkAction *action, gpointer data)
+#else
 menu_add_pounce_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1243,7 +1289,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_insert_link_cb(GtkAction *action, gpointer data)
+#else
 menu_insert_link_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PidginConversation *gtkconv;
@@ -1257,7 +1307,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_insert_image_cb(GtkAction *action, gpointer data)
+#else
 menu_insert_image_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1274,7 +1328,11 @@
 
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_alias_cb(GtkAction *action, gpointer data)
+#else
 menu_alias_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1301,7 +1359,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_get_info_cb(GtkAction *action, gpointer data)
+#else
 menu_get_info_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1312,7 +1374,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_invite_cb(GtkAction *action, gpointer data)
+#else
 menu_invite_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1323,7 +1389,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_block_cb(GtkAction *action, gpointer data)
+#else
 menu_block_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1334,7 +1404,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_unblock_cb(GtkAction *action, gpointer data)
+#else
 menu_unblock_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1345,7 +1419,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_add_remove_cb(GtkAction *action, gpointer data)
+#else
 menu_add_remove_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1390,7 +1468,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_close_conv_cb(GtkAction *action, gpointer data)
+#else
 menu_close_conv_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 
@@ -1398,7 +1480,11 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_logging_cb(GtkAction *action, gpointer data)
+#else
 menu_logging_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1410,7 +1496,11 @@
 	if (conv == NULL)
 		return;
 
+#if GTK_CHECK_VERSION(2,6,0)
+	logging = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
+#else
 	logging = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
+#endif
 
 	if (logging == purple_conversation_is_logging(conv))
 		return;
@@ -1463,14 +1553,26 @@
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_toolbar_cb(GtkAction *action, gpointer data)
+{
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar",
+	                    gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)));
+}
+#else
 menu_toolbar_cb(gpointer data, guint action, GtkWidget *widget)
 {
 	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar",
 	                    gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)));
 }
-
-static void
+#endif
+
+static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_sounds_cb(GtkAction *action, gpointer data)
+#else
 menu_sounds_cb(gpointer data, guint action, GtkWidget *widget)
+#endif
 {
 	PidginWindow *win = data;
 	PurpleConversation *conv;
@@ -1485,18 +1587,30 @@
 	gtkconv = PIDGIN_CONVERSATION(conv);
 
 	gtkconv->make_sound =
+#if GTK_CHECK_VERSION(2,6,0)
+		gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
+#else
 		gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
+#endif
 	node = get_conversation_blist_node(conv);
 	if (node)
 		purple_blist_node_set_bool(node, "gtk-mute-sound", !gtkconv->make_sound);
 }
 
 static void
+#if GTK_CHECK_VERSION(2,6,0)
+menu_timestamps_cb(GtkAction *action, gpointer data)
+{
+	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps",
+		gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)));
+}
+#else
 menu_timestamps_cb(gpointer data, guint action, GtkWidget *widget)
 {
 	purple_prefs_set_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps",
 		gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)));
 }
+#endif
 
 static void
 chat_do_im(PidginConversation *gtkconv, const char *who)
@@ -2302,8 +2416,13 @@
 	purple_conversation_close_logs(old_conv);
 	gtkconv->active_conv = conv;
 
+#if GTK_CHECK_VERSION(2,6,0)
+	purple_conversation_set_logging(conv,
+		gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(gtkconv->win->menu.logging)));
+#else
 	purple_conversation_set_logging(conv,
 		gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging)));
+#endif
 
 	entry = GTK_IMHTML(gtkconv->entry);
 	protocol_name = purple_account_get_protocol_name(conv->account);
@@ -3126,6 +3245,99 @@
 	return gtkconv->win;
 }
 
+#if GTK_CHECK_VERSION(2,6,0)
+
+static GtkActionEntry menu_entries[] =
+/* TODO: fill out tooltips... */
+{
+	/* Conversation menu */
+	{ "ConversationMenu", NULL, N_("_Conversation"), NULL, NULL, NULL },
+	{ "NewInstantMessage", PIDGIN_STOCK_TOOLBAR_MESSAGE_NEW, N_("New Instant _Message..."), "<control>M", NULL, G_CALLBACK(menu_new_conv_cb) },
+	{ "Find", GTK_STOCK_FIND, N_("_Find..."), NULL, NULL, G_CALLBACK(menu_find_cb) },
+	{ "ViewLog", NULL, N_("View _Log"), NULL, NULL, G_CALLBACK(menu_view_log_cb) },
+	{ "SaveAs", GTK_STOCK_SAVE_AS, N_("_Save As..."), NULL, NULL, G_CALLBACK(menu_save_as_cb) },
+	{ "ClearScrollback", GTK_STOCK_CLEAR, N_("Clea_r Scrollback"), "<control>L", NULL, G_CALLBACK(menu_clear_cb) },
+
+#ifdef USE_VV
+	{ "MediaMenu", NULL, N_("M_edia"), NULL, NULL, NULL },
+	{ "AudioCall", PIDGIN_STOCK_TOOLBAR_AUDIO_CALL, N_("_Audio Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) },
+	{ "VideoCall", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, N_("_Video Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) },
+	{ "AudioVideoCall", PIDGIN_STOCK_TOOLBAR_VIDEO_CALL, N_("Audio\\/Video _Call"), NULL, NULL, G_CALLBACK(menu_initiate_media_call_cb) },
+#endif
+
+	{ "SendFile", PIDGIN_STOCK_TOOLBAR_SEND_FILE, N_("Se_nd File..."), NULL, NULL, G_CALLBACK(menu_send_file_cb) },
+	{ "AddBuddyPounce", NULL, N_("Add Buddy _Pounce..."), NULL, NULL, G_CALLBACK(menu_add_pounce_cb) },
+	{ "GetInfo", PIDGIN_STOCK_TOOLBAR_USER_INFO, N_("_Get Info"), "<control>O", NULL, G_CALLBACK(menu_get_info_cb) },
+	{ "Invite", NULL, N_("In_vite..."), NULL, NULL, G_CALLBACK(menu_invite_cb) },
+	{ "MoreMenu", NULL, N_("M_ore"), NULL, NULL, NULL },
+	{ "Alias", NULL, N_("Al_ias..."), NULL, NULL, G_CALLBACK(menu_alias_cb) },
+	{ "Block", PIDGIN_STOCK_TOOLBAR_BLOCK, N_("_Block..."), NULL, NULL, G_CALLBACK(menu_block_cb) },
+	{ "Unblock", PIDGIN_STOCK_TOOLBAR_UNBLOCK, N_("_Unblock..."), NULL, NULL, G_CALLBACK(menu_unblock_cb) },
+	{ "Add", GTK_STOCK_ADD, N_("_Add..."), NULL, NULL, G_CALLBACK(menu_add_remove_cb) },
+	{ "Remove", GTK_STOCK_REMOVE, N_("_Remove..."), NULL, NULL, G_CALLBACK(menu_add_remove_cb) },
+	{ "InsertLink", PIDGIN_STOCK_TOOLBAR_INSERT_LINK, N_("Insert Lin_k..."), NULL, NULL, G_CALLBACK(menu_insert_link_cb) },
+	{ "InsertImage", PIDGIN_STOCK_TOOLBAR_INSERT_IMAGE, N_("Insert Imag_e..."), NULL, NULL, G_CALLBACK(menu_insert_image_cb) },
+	{ "Close", GTK_STOCK_CLOSE, N_("_Close"), NULL, NULL, G_CALLBACK(menu_close_conv_cb) },
+
+	/* Options */
+	{ "OptionsMenu", NULL, N_("_Options"), NULL, NULL, NULL },
+};
+
+/* Toggle items */
+static const GtkToggleActionEntry menu_toggle_entries[] = {
+	{ "EnableLogging", NULL, N_("Enable _Logging"), NULL, NULL, G_CALLBACK(menu_logging_cb), FALSE },
+	{ "EnableSounds", NULL, N_("Enable _Sounds"), NULL, NULL, G_CALLBACK(menu_sounds_cb), FALSE },
+	{ "ShowFormattingToolbars", NULL, N_("Show Formatting _Toolbars"), NULL, NULL, G_CALLBACK(menu_toolbar_cb), FALSE },
+	{ "ShowTimestamps", NULL, N_("Show Ti_mestamps"), NULL, NULL, G_CALLBACK(menu_timestamps_cb), FALSE },
+};
+
+static const char *conversation_menu =
+"<ui>"
+	"<menubar name='Conversation'>"
+		"<menu action='ConversationMenu'>"
+			"<menuitem action='NewInstantMessage'/>"
+			"<separator/>"
+			"<menuitem action='Find'/>"
+			"<menuitem action='ViewLog'/>"
+			"<menuitem action='SaveAs'/>"
+			"<menuitem action='ClearScrollback'/>"
+			"<separator/>"
+#ifdef USE_VV
+			"<menu action='MediaMenu'>"
+				"<menuitem action='AudioCall'/>"
+				"<menuitem action='VideoCall'/>"
+				"<menuitem action='AudioVideoCall'/>"
+			"</menu>"
+#endif
+			"<menuitem action='SendFile'/>"
+			"<menuitem action='AddBuddyPounce'/>"
+			"<menuitem action='GetInfo'/>"
+			"<menuitem action='Invite'/>"
+			"<menu action='MoreMenu'/>"
+			"<separator/>"
+			"<menuitem action='Alias'/>"
+			"<menuitem action='Block'/>"
+			"<menuitem action='Unblock'/>"
+			"<menuitem action='Add'/>"
+			"<menuitem action='Remove'/>"
+			"<separator/>"
+			"<menuitem action='InsertLink'/>"
+			"<menuitem action='InsertImage'/>"
+			"<separator/>"
+			"<menuitem action='Close'/>"
+		"</menu>"
+		"<menu action='OptionsMenu'>"
+			"<menuitem action='EnableLogging'/>"
+			"<menuitem action='EnableSounds'/>"
+			"<separator/>"
+			"<menuitem action='ShowFormattingToolbars'/>"
+			"<menuitem action='ShowTimestamps'/>"
+		"</menu>"
+	"</menubar>"
+"</ui>";
+
+#else
+
 static GtkItemFactoryEntry menu_items[] =
 {
 	/* Conversation menu */
@@ -3209,6 +3421,8 @@
 	return _(path);
 }
 
+#endif
+
 static void
 sound_method_pref_changed_cb(const char *name, PurplePrefType type,
 							 gconstpointer value, gpointer data)
@@ -3218,19 +3432,31 @@
 
 	if (!strcmp(method, "none"))
 	{
+#if GTK_CHECK_VERSION(2,6,0)
+		gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds),
+		                             FALSE);
+		gtk_action_set_sensitive(win->menu.sounds, FALSE);
+#else
 		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds),
 		                               FALSE);
 		gtk_widget_set_sensitive(win->menu.sounds, FALSE);
+#endif
 	}
 	else
 	{
 		PidginConversation *gtkconv = pidgin_conv_window_get_active_gtkconv(win);
 
+#if GTK_CHECK_VERSION(2,6,0)
+		if (gtkconv != NULL)
+			gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds),
+			                             gtkconv->make_sound);
+		gtk_action_set_sensitive(win->menu.sounds, TRUE);
+#else
 		if (gtkconv != NULL)
 			gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds),
 			                               gtkconv->make_sound);
 		gtk_widget_set_sensitive(win->menu.sounds, TRUE);
-
+#endif
 	}
 }
 
@@ -3328,6 +3554,8 @@
 static void
 regenerate_options_items(PidginWindow *win)
 {
+#if GTK_CHECK_VERSION(2,6,0)
+#else
 	GtkWidget *menu;
 	PidginConversation *gtkconv;
 	GList *list;
@@ -3351,6 +3579,7 @@
 	}
 
 	gtk_widget_show_all(menu);
+#endif
 }
 
 static void
@@ -3364,6 +3593,8 @@
 static void
 regenerate_plugins_items(PidginWindow *win)
 {
+#if GTK_CHECK_VERSION(2,6,0)
+#else
 	GList *action_items;
 	GtkWidget *menu;
 	GList *list;
@@ -3405,8 +3636,10 @@
 		g_signal_connect(G_OBJECT(item), "destroy", G_CALLBACK(remove_from_list), win);
 	}
 	g_object_set_data(G_OBJECT(win->window), "plugin-actions", action_items);
-}
-
+#endif
+}
+
+#if !GTK_CHECK_VERSION(2,6,0)
 static void menubar_activated(GtkWidget *item, gpointer data)
 {
 	PidginWindow *win = data;
@@ -3429,12 +3662,146 @@
 	g_signal_handlers_disconnect_by_func(G_OBJECT(win->menu.menubar),
 				G_CALLBACK(focus_out_from_menubar), win);
 }
+#endif
 
 static GtkWidget *
 setup_menubar(PidginWindow *win)
 {
 	GtkAccelGroup *accel_group;
 	const char *method;
+
+#if GTK_CHECK_VERSION(2,6,0)
+	GtkActionGroup *action_group;
+	GError *error;
+
+	action_group = gtk_action_group_new("ConversationActions");
+	gtk_action_group_add_actions(action_group,
+	                             menu_entries,
+	                             G_N_ELEMENTS(menu_entries),
+	                             win);
+	gtk_action_group_add_toggle_actions(action_group,
+	                                    menu_toggle_entries,
+	                                    G_N_ELEMENTS(menu_toggle_entries),
+	                                    win);
+#ifdef ENABLE_NLS
+	gtk_action_group_set_translation_domain(action_group,
+	                                        PACKAGE);
+#endif
+
+	win->menu.ui = gtk_ui_manager_new();
+	gtk_ui_manager_insert_action_group(win->menu.ui, action_group, 0);
+
+	accel_group = gtk_ui_manager_get_accel_group(win->menu.ui);
+	gtk_window_add_accel_group(GTK_WINDOW(win->window), accel_group);
+	g_signal_connect(G_OBJECT(accel_group), "accel-changed",
+	                 G_CALLBACK(pidgin_save_accels_cb), NULL);
+
+	error = NULL;
+	if (!gtk_ui_manager_add_ui_from_string(win->menu.ui, conversation_menu, -1, &error))
+	{
+		g_message("building menus failed: %s", error->message);
+		g_error_free(error);
+		exit(EXIT_FAILURE);
+	}
+
+	win->menu.menubar =
+		gtk_ui_manager_get_widget(win->menu.ui, "/Conversation");
+
+	win->menu.view_log =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/ConversationMenu/ViewLog");
+
+#ifdef USE_VV
+	win->audio_call =
+		gtk_ui_manager_get_action(win->menu.ui,
+					    "/Conversation/ConversationMenu/MediaMenu/AudioCall");
+	win->video_call =
+		gtk_ui_manager_get_action(win->menu.ui,
+					    "/Conversation/ConversationMenu/MediaMenu/VideoCall");
+	win->audio_video_call =
+		gtk_ui_manager_get_action(win->menu.ui,
+					    "/Conversation/ConversationMenu/MediaMenu/AudioVideoCall");
+#endif
+	
+	/* --- */
+
+	win->menu.send_file =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/ConversationMenu/SendFile");
+
+	win->menu.add_pounce =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/ConversationMenu/AddBuddyPounce");
+
+	/* --- */
+
+	win->menu.get_info =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/ConversationMenu/GetInfo");
+
+	win->menu.invite =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/ConversationMenu/Invite");
+
+	/* --- */
+
+	win->menu.alias =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/ConversationMenu/Alias");
+
+	win->menu.block =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/ConversationMenu/Block");
+
+	win->menu.unblock =
+		gtk_ui_manager_get_action(win->menu.ui,
+					    "/Conversation/ConversationMenu/Unblock");
+
+	win->menu.add =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/ConversationMenu/Add");
+
+	win->menu.remove =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/ConversationMenu/Remove");
+
+	/* --- */
+
+	win->menu.insert_link =
+		gtk_ui_manager_get_action(win->menu.ui,
+				"/Conversation/ConversationMenu/InsertLink");
+
+	win->menu.insert_image =
+		gtk_ui_manager_get_action(win->menu.ui,
+				"/Conversation/ConversationMenu/InsertImage");
+
+	/* --- */
+
+	win->menu.logging =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/OptionsMenu/EnableLogging");
+	win->menu.sounds =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/OptionsMenu/EnableSounds");
+	method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method");
+	if (method != NULL && !strcmp(method, "none"))
+	{
+		gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds),
+		                               FALSE);
+		gtk_action_set_sensitive(win->menu.sounds, FALSE);
+	}
+	purple_prefs_connect_callback(win, PIDGIN_PREFS_ROOT "/sound/method",
+				    sound_method_pref_changed_cb, win);
+
+	win->menu.show_formatting_toolbar =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/OptionsMenu/ShowFormattingToolbars");
+	win->menu.show_timestamps =
+		gtk_ui_manager_get_action(win->menu.ui,
+		                          "/Conversation/OptionsMenu/ShowTimestamps");
+	win->menu.show_icon = NULL;
+
+#else
 	GtkWidget *menuitem;
 
 	accel_group = gtk_accel_group_new ();
@@ -3556,6 +3923,8 @@
 		                            N_("/Options/Show Timestamps"));
 	win->menu.show_icon = NULL;
 
+#endif
+
 	win->menu.tray = pidgin_menu_tray_new();
 	gtk_menu_shell_append(GTK_MENU_SHELL(win->menu.menubar),
 	                      win->menu.tray);
@@ -3737,7 +4106,8 @@
 	if (!(b = purple_find_buddy(account, conv->name)))
 		return FALSE;
 
-
+#if GTK_CHECK_VERSION(2,6,0)
+#else
 	gtk_widget_show(win->menu.send_to);
 
 	menu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(win->menu.send_to));
@@ -3759,6 +4129,7 @@
 			break;
 		}
 	}
+#endif
 
 	return FALSE;
 }
@@ -3869,6 +4240,8 @@
 static void
 generate_send_to_items(PidginWindow *win)
 {
+#if GTK_CHECK_VERSION(2,6,0)
+#else
 	GtkWidget *menu;
 	GSList *group = NULL;
 	GtkSizeGroup *sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
@@ -3953,6 +4326,7 @@
 	if (!group)
 		gtk_widget_set_sensitive(win->menu.send_to, FALSE);
 	update_send_to_selection(win);
+#endif
 }
 
 static const char *
@@ -5249,7 +5623,9 @@
 	gtkconv->send_history = g_list_append(NULL, NULL);
 
 	/* Setup some initial variables. */
+#if !GTK_CHECK_VERSION(2,12,0)
 	gtkconv->tooltips = gtk_tooltips_new();
+#endif
 	gtkconv->unseen_state = PIDGIN_UNSEEN_NONE;
 	gtkconv->unseen_count = 0;
 
@@ -5442,7 +5818,9 @@
 		g_free(gtkconv->u.chat);
 	}
 
+#if !GTK_CHECK_VERSION(2,12,0)
 	gtk_object_sink(GTK_OBJECT(gtkconv->tooltips));
+#endif
 
 	gtkconv->send_history = g_list_first(gtkconv->send_history);
 	g_list_foreach(gtkconv->send_history, (GFunc)g_free, NULL);
@@ -6359,6 +6737,16 @@
 	gtk_imhtml_append_text(GTK_IMHTML(gtkconv->entry), message, 0);
 }
 
+/* Mask functions with ones from newer GTK+ */
+#if GTK_CHECK_VERSION(2,6,0)
+#define gtk_widget_set_sensitive_ gtk_widget_set_sensitive
+#define gtk_widget_show_ gtk_widget_show
+#define gtk_widget_hide_ gtk_widget_hide
+#define gtk_widget_set_sensitive gtk_action_set_sensitive
+#define gtk_widget_show(x) gtk_action_set_visible((x), TRUE)
+#define gtk_widget_hide(x) gtk_action_set_visible((x), FALSE)
+#endif
+
 /*
  * Makes sure all the menu items and all the buttons are hidden/shown and
  * sensitive/insensitive.  This is called after changing tabs and when an
@@ -6593,6 +6981,17 @@
 	}
 }
 
+/* Restore the functions */
+#if GTK_CHECK_VERSION(2,6,0)
+#undef gtk_widget_set_sensitive
+#undef gtk_widget_show
+#undef gtk_widget_hide
+
+#define gtk_widget_set_sensitive gtk_widget_set_sensitive_
+#define gtk_widget_show gtk_widget_show_
+#define gtk_widget_hide gtk_widget_hide_
+#endif
+
 static void
 pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields)
 {
@@ -6641,8 +7040,13 @@
 			topic = purple_conv_chat_get_topic(chat);
 
 			gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), topic ? topic : "");
+#if GTK_CHECK_VERSION(2,12,0)
+			gtk_widget_set_tooltip_text(gtkchat->topic_text,
+			                            topic ? topic : "");
+#else
 			gtk_tooltips_set_tip(gtkconv->tooltips, gtkchat->topic_text,
 			                     topic ? topic : "", NULL);
+#endif
 		}
 	}
 
@@ -7274,9 +7678,15 @@
 		gtkconv = PIDGIN_CONVERSATION(conv);
 		win     = gtkconv->win;
 
+#if GTK_CHECK_VERSION(2,6,0)
+		gtk_toggle_action_set_active(
+		        GTK_TOGGLE_ACTION(win->menu.show_timestamps),
+		        (gboolean)GPOINTER_TO_INT(value));
+#else
 		gtk_check_menu_item_set_active(
 		        GTK_CHECK_MENU_ITEM(win->menu.show_timestamps),
 		        (gboolean)GPOINTER_TO_INT(value));
+#endif
 
 		gtk_imhtml_show_comments(GTK_IMHTML(gtkconv->imhtml),
 			(gboolean)GPOINTER_TO_INT(value));
@@ -7302,9 +7712,15 @@
 		gtkconv = PIDGIN_CONVERSATION(conv);
 		win     = gtkconv->win;
 
+#if GTK_CHECK_VERSION(2,6,0)
+		gtk_toggle_action_set_active(
+		        GTK_TOGGLE_ACTION(win->menu.show_formatting_toolbar),
+		        (gboolean)GPOINTER_TO_INT(value));
+#else
 		gtk_check_menu_item_set_active(
 		        GTK_CHECK_MENU_ITEM(win->menu.show_formatting_toolbar),
 		        (gboolean)GPOINTER_TO_INT(value));
+#endif
 
 		if ((gboolean)GPOINTER_TO_INT(value))
 			gtk_widget_show(gtkconv->toolbar);
@@ -8533,6 +8949,8 @@
 		/* Right click was pressed. Popup the context menu. */
 		GtkWidget *menu = gtk_menu_new(), *sub;
 		gboolean populated = populate_menu_with_options(menu, gtkconv, TRUE);
+#if GTK_CHECK_VERSION(2,6,0)
+#else
 		sub = gtk_menu_item_get_submenu(GTK_MENU_ITEM(gtkconv->win->menu.send_to));
 
 		if (sub && GTK_WIDGET_IS_SENSITIVE(gtkconv->win->menu.send_to)) {
@@ -8547,7 +8965,7 @@
 			gtk_widget_destroy(menu);
 			return FALSE;
 		}
-
+#endif
 		gtk_widget_show_all(menu);
 		gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, e->button, e->time);
 		return TRUE;
@@ -9057,8 +9475,13 @@
 
 	/* Update the menubar */
 
+#if GTK_CHECK_VERSION(2,6,0)
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(gtkconv->win->menu.logging),
+	                             purple_conversation_is_logging(conv));
+#else
 	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtkconv->win->menu.logging),
 	                               purple_conversation_is_logging(conv));
+#endif
 
 	generate_send_to_items(win);
 	regenerate_options_items(win);
@@ -9067,6 +9490,17 @@
 	pidgin_conv_switch_active_conversation(conv);
 
 	sound_method = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/sound/method");
+#if GTK_CHECK_VERSION(2,6,0)
+	if (strcmp(sound_method, "none") != 0)
+		gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.sounds),
+		                             gtkconv->make_sound);
+
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.show_formatting_toolbar),
+	                             purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar"));
+
+	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(win->menu.show_timestamps),
+	                             purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps"));
+#else
 	if (strcmp(sound_method, "none") != 0)
 		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds),
 		                               gtkconv->make_sound);
@@ -9076,6 +9510,7 @@
 
 	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.show_timestamps),
 	                               purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_timestamps"));
+#endif
 
 	/*
 	 * We pause icons when they are not visible.  If this icon should
@@ -9328,7 +9763,11 @@
 	}
 	gtk_widget_destroy(win->window);
 
+#if GTK_CHECK_VERSION(2,6,0)
+	g_object_unref(G_OBJECT(win->menu.ui));
+#else
 	g_object_unref(G_OBJECT(win->menu.item_factory));
+#endif
 
 	purple_notify_close_with_handle(win);
 	purple_signals_disconnect_by_handle(win);
@@ -9418,8 +9857,12 @@
 	g_signal_connect(G_OBJECT(gtkconv->close), "leave-notify-event", G_CALLBACK(close_button_left_cb), close_image);
 	gtk_widget_show(close_image);
 	gtk_container_add(GTK_CONTAINER(gtkconv->close), close_image);
+#if GTK_CHECK_VERSION(2,12,0)
+	gtk_widget_set_tooltip_text(gtkconv->close, _("Close conversation"));
+#else
 	gtk_tooltips_set_tip(gtkconv->tooltips, gtkconv->close,
 	                     _("Close conversation"), NULL);
+#endif
 
 	g_signal_connect(G_OBJECT(gtkconv->close), "button-press-event",
 			 G_CALLBACK(close_conv_cb), gtkconv);
--- a/pidgin/gtkconv.h	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkconv.h	Tue Jul 28 05:49:14 2009 +0000
@@ -122,7 +122,11 @@
 
 	gboolean make_sound;
 
+#if GTK_CHECK_VERSION(2,12,0)
+	gpointer depr2;
+#else
 	GtkTooltips *tooltips;
+#endif
 
 	GtkWidget *tab_cont;
 	GtkWidget *tabby;
--- a/pidgin/gtkconvwin.h	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkconvwin.h	Tue Jul 28 05:49:14 2009 +0000
@@ -46,8 +46,31 @@
 
 	struct
 	{
+/* Some necessary functions were only added in 2.6.0 */
 		GtkWidget *menubar;
 
+#if GTK_CHECK_VERSION(2,6,0)
+		GtkAction *view_log;
+
+		GtkAction *send_file;
+		GtkAction *add_pounce;
+		GtkAction *get_info;
+		GtkAction *invite;
+
+		GtkAction *alias;
+		GtkAction *block;
+		GtkAction *unblock;
+		GtkAction *add;
+		GtkAction *remove;
+
+		GtkAction *insert_link;
+		GtkAction *insert_image;
+
+		GtkAction *logging;
+		GtkAction *sounds;
+		GtkAction *show_formatting_toolbar;
+		GtkAction *show_timestamps;
+#else
 		GtkWidget *view_log;
 
 		GtkWidget *send_file;
@@ -68,6 +91,7 @@
 		GtkWidget *sounds;
 		GtkWidget *show_formatting_toolbar;
 		GtkWidget *show_timestamps;
+#endif
 		GtkWidget *show_icon;
 
 		GtkWidget *send_to;
@@ -76,7 +100,11 @@
 
 		GtkWidget *typing_icon;
 
+#if GTK_CHECK_VERSION(2,6,0)
+		GtkUIManager *ui;
+#else
 		GtkItemFactory *item_factory;
+#endif
 
 	} menu;
 
@@ -98,9 +126,15 @@
 	gint drag_leave_signal;
 
 	/* Media menu options. */
+#if GTK_CHECK_VERSION(2,6,0)
+	GtkAction *audio_call;
+	GtkAction *video_call;
+	GtkAction *audio_video_call;
+#else
 	GtkWidget *audio_call;
 	GtkWidget *video_call;
 	GtkWidget *audio_video_call;
+#endif
 };
 
 /*@}*/
--- a/pidgin/gtkdebug.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkdebug.c	Tue Jul 28 05:49:14 2009 +0000
@@ -43,6 +43,19 @@
 
 #include <gdk/gdkkeysyms.h>
 
+/* TODO: I'm too lazy to change all these until we bump required GTK+ version */
+#if GTK_CHECK_VERSION(2,4,0)
+#undef GTK_TOGGLE_BUTTON
+#undef gtk_toggle_button_get_active
+#undef gtk_toggle_button_set_active
+#undef GtkToggleButton
+
+#define GTK_TOGGLE_BUTTON GTK_TOGGLE_TOOL_BUTTON
+#define gtk_toggle_button_get_active gtk_toggle_tool_button_get_active
+#define gtk_toggle_button_set_active gtk_toggle_tool_button_set_active
+#define GtkToggleButton GtkToggleToolButton
+#endif
+
 typedef struct
 {
 	GtkWidget *window;
@@ -677,9 +690,16 @@
 	GtkWidget *vbox;
 	GtkWidget *toolbar;
 	GtkWidget *frame;
-	GtkWidget *image;
 	gint width, height;
 	void *handle;
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkToolItem *item;
+#if !GTK_CHECK_VERSION(2,12,0)
+	GtkTooltips *tooltips;
+#endif
+#else
+	GtkWidget *image;
+#endif
 
 	win = g_new0(DebugWindow, 1);
 
@@ -719,7 +739,12 @@
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/toolbar")) {
 		/* Setup our top button bar thingie. */
 		toolbar = gtk_toolbar_new();
+#if GTK_CHECK_VERSION(2,4,0) && !GTK_CHECK_VERSION(2,12,0)
+		tooltips = gtk_tooltips_new();
+#endif
+#if !GTK_CHECK_VERSION(2,14,0)
 		gtk_toolbar_set_tooltips(GTK_TOOLBAR(toolbar), TRUE);
+#endif
 #if GTK_CHECK_VERSION(2,4,0)
 		gtk_toolbar_set_show_arrow(GTK_TOOLBAR(toolbar), TRUE);
 #endif
@@ -736,36 +761,101 @@
 
 #ifndef HAVE_REGEX_H
 		/* Find button */
+#if GTK_CHECK_VERSION(2,4,0)
+		item = gtk_tool_button_new_from_stock(GTK_STOCK_FIND);
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_tool_item_set_tooltip_text(item, _("Find"));
+#else
+		gtk_tool_item_set_tooltip(item, tooltips, _("Find"), NULL);
+#endif
+		g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(find_cb), win);
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+#else
 		gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_FIND,
 		                         _("Find"), NULL, G_CALLBACK(find_cb),
 		                         win, -1);
+#endif
 #endif /* HAVE_REGEX_H */
 
 		/* Save */
+#if GTK_CHECK_VERSION(2,4,0)
+		item = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_tool_item_set_tooltip_text(item, _("Save"));
+#else
+		gtk_tool_item_set_tooltip(item, tooltips, _("Save"), NULL);
+#endif
+		g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(save_cb), win);
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+#else
 		gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_SAVE,
 		                         _("Save"), NULL, G_CALLBACK(save_cb),
 		                         win, -1);
+#endif
 
 		/* Clear button */
+#if GTK_CHECK_VERSION(2,4,0)
+		item = gtk_tool_button_new_from_stock(GTK_STOCK_CLEAR);
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_tool_item_set_tooltip_text(item, _("Clear"));
+#else
+		gtk_tool_item_set_tooltip(item, tooltips, _("Clear"), NULL);
+#endif
+		g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(clear_cb), win);
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+#else
 		gtk_toolbar_insert_stock(GTK_TOOLBAR(toolbar), GTK_STOCK_CLEAR,
 		                         _("Clear"), NULL, G_CALLBACK(clear_cb),
 		                         win, -1);
+#endif
 
+#if GTK_CHECK_VERSION(2,4,0)
+		item = gtk_separator_tool_item_new();
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+#else
 		gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1);
+#endif
 
 		/* Pause */
+#if GTK_CHECK_VERSION(2,4,0)
+		item = gtk_toggle_tool_button_new_from_stock(PIDGIN_STOCK_PAUSE);
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_tool_item_set_tooltip_text(item, _("Pause"));
+#else
+		gtk_tool_item_set_tooltip(item, tooltips, _("Pause"), NULL);
+#endif
+		g_signal_connect(G_OBJECT(item), "clicked", G_CALLBACK(pause_cb), win);
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+#else
 		image = gtk_image_new_from_stock(PIDGIN_STOCK_PAUSE, GTK_ICON_SIZE_MENU);
 		gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
 		                                    GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
 		                                    NULL, _("Pause"), _("Pause"),
 		                                    NULL, image,
 		                                    G_CALLBACK(pause_cb), win);
+#endif
 
 #ifdef HAVE_REGEX_H
 		/* regex stuff */
+#if GTK_CHECK_VERSION(2,4,0)
+		item = gtk_separator_tool_item_new();
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+#else
 		gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1);
+#endif
 
 		/* regex toggle button */
+#if GTK_CHECK_VERSION(2,4,0)
+		win->filter = GTK_WIDGET(gtk_toggle_tool_button_new());
+		gtk_tool_button_set_label(GTK_TOOL_BUTTON(win->filter), _("Filter"));
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(win->filter), _("Filter"));
+#else
+		gtk_tooltips_set_tip(tooltips, win->filter, _("Filter"), NULL);
+#endif
+		g_signal_connect(G_OBJECT(win->filter), "clicked", G_CALLBACK(regex_filter_toggled_cb), win);
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(win->filter));
+#else
 		win->filter =
 			gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
 									   GTK_TOOLBAR_CHILD_TOGGLEBUTTON,
@@ -773,6 +863,8 @@
 									   NULL, NULL,
 									   G_CALLBACK(regex_filter_toggled_cb),
 									   win);
+#endif
+
 		/* we purposely disable the toggle button here in case
 		 * /purple/gtk/debug/expression has an empty string.  If it does not have
 		 * an empty string, the change signal will get called and make the
@@ -786,10 +878,21 @@
 
 		/* regex entry */
 		win->expression = gtk_entry_new();
+#if GTK_CHECK_VERSION(2,4,0)
+		item = gtk_tool_item_new();
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_widget_set_tooltip_text(win->expression, _("Right click for more options."));
+#else
+		gtk_tooltips_set_tip(tooltips, win->expression, _("Right click for more options."), NULL);
+#endif
+		gtk_container_add(GTK_CONTAINER(item), GTK_WIDGET(win->expression));
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+#else
 		gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
 								   GTK_TOOLBAR_CHILD_WIDGET, win->expression,
 								   NULL, _("Right click for more options."),
 								   NULL, NULL, NULL, NULL);
+#endif
 		/* this needs to be before the text is set from the pref if we want it
 		 * to colorize a stored expression.
 		 */
@@ -815,18 +918,39 @@
 
 #endif /* HAVE_REGEX_H */
 
+#if GTK_CHECK_VERSION(2,4,0)
+		item = gtk_separator_tool_item_new();
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+#else
 		gtk_toolbar_insert_space(GTK_TOOLBAR(toolbar), -1);
+#endif
 
+#if GTK_CHECK_VERSION(2,4,0)
+		item = gtk_tool_item_new();
+		gtk_container_add(GTK_CONTAINER(item), gtk_label_new(_("Level ")));
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+#else
 		gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
 		                           GTK_TOOLBAR_CHILD_WIDGET, gtk_label_new(_("Level ")),
 		                           NULL, _("Select the debug filter level."),
 		                           NULL, NULL, NULL, NULL);
-
+#endif
 		win->filterlevel = gtk_combo_box_new_text();
+#if GTK_CHECK_VERSION(2,4,0)
+		item = gtk_tool_item_new();
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_widget_set_tooltip_text(win->filterlevel, _("Select the debug filter level."));
+#else
+		gtk_tooltips_set_tip(tooltips, win->filterlevel, _("Select the debug filter level."), NULL);
+#endif
+		gtk_container_add(GTK_CONTAINER(item), win->filterlevel);
+		gtk_container_add(GTK_CONTAINER(toolbar), GTK_WIDGET(item));
+#else
 		gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
 		                           GTK_TOOLBAR_CHILD_WIDGET, win->filterlevel,
 		                           NULL, _("Select the debug filter level."),
 		                           NULL, NULL, NULL, NULL);
+#endif
 		gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("All"));
 		gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Misc"));
 		gtk_combo_box_append_text(GTK_COMBO_BOX(win->filterlevel), _("Info"));
--- a/pidgin/gtkdocklet-x11.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkdocklet-x11.c	Tue Jul 28 05:49:14 2009 +0000
@@ -40,7 +40,9 @@
 /* globals */
 static EggTrayIcon *docklet = NULL;
 static GtkWidget *image = NULL;
+#if !GTK_CHECK_VERSION(2,12,0)
 static GtkTooltips *tooltips = NULL;
+#endif
 static GdkPixbuf *blank_icon = NULL;
 static int embed_timeout = 0;
 static int docklet_height = 0;
@@ -192,6 +194,13 @@
 static void
 docklet_x11_set_tooltip(gchar *tooltip)
 {
+#if GTK_CHECK_VERSION(2,12,0)
+	if (tooltip) {
+		gtk_widget_set_tooltip_text(image->parent, tooltip);
+	} else {
+		gtk_widget_set_tooltip_text(image->parent, ""); /* NULL? */
+	}
+#else
 	if (!tooltips)
 		tooltips = gtk_tooltips_new();
 
@@ -203,6 +212,7 @@
 		gtk_tooltips_set_tip(tooltips, image->parent, "", NULL);
 		gtk_tooltips_disable(tooltips);
 	}
+#endif
 }
 
 #if GTK_CHECK_VERSION(2,2,0)
--- a/pidgin/gtkimhtmltoolbar.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Tue Jul 28 05:49:14 2009 +0000
@@ -669,7 +669,11 @@
 	g_object_set_data(G_OBJECT(button), "smiley_text", face);
 	g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(insert_smiley_text), toolbar);
 
+#if GTK_CHECK_VERSION(2,12,0)
+	gtk_widget_set_tooltip_text(button, face);
+#else
 	gtk_tooltips_set_tip(toolbar->tooltips, button, face, NULL);
+#endif
 
 	/* these look really weird with borders */
 	gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
@@ -683,7 +687,11 @@
 		g_snprintf(tip, sizeof(tip),
 			_("This smiley is disabled because a custom smiley exists for this shortcut:\n %s"),
 			face);
+#if GTK_CHECK_VERSION(2,12,0)
+		gtk_widget_set_tooltip_text(button, tip);
+#else
 		gtk_tooltips_set_tip(toolbar->tooltips, button, tip, NULL);
+#endif
 		gtk_widget_set_sensitive(button, FALSE);
 	} else if (psmiley) {
 		/* Remove the button if the smiley is destroyed */
@@ -1147,7 +1155,9 @@
 	}
 
 	g_free(toolbar->sml);
+#if !GTK_CHECK_VERSION(2,12,0)
 	gtk_object_sink(GTK_OBJECT(toolbar->tooltips));
+#endif
 
 	menu = g_object_get_data(object, "font_menu");
 	if (menu)
@@ -1244,7 +1254,11 @@
 			g_signal_connect(G_OBJECT(button), "clicked",
 					 G_CALLBACK(buttons[iter].callback), toolbar);
 			*(buttons[iter].button) = button;
+#if GTK_CHECK_VERSION(2,12,0)
+			gtk_widget_set_tooltip_text(button, buttons[iter].tooltip);
+#else
 			gtk_tooltips_set_tip(toolbar->tooltips, button, buttons[iter].tooltip, NULL);
+#endif
 		} else
 			button = gtk_vseparator_new();
 		gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
@@ -1334,7 +1348,9 @@
 	toolbar->smiley_dialog = NULL;
 	toolbar->image_dialog = NULL;
 
+#if !GTK_CHECK_VERSION(2,12,0)
 	toolbar->tooltips = gtk_tooltips_new();
+#endif
 
 	gtk_box_set_spacing(GTK_BOX(toolbar), 3);
 
--- a/pidgin/gtkimhtmltoolbar.h	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkimhtmltoolbar.h	Tue Jul 28 05:49:14 2009 +0000
@@ -46,7 +46,11 @@
 
 	GtkWidget *imhtml;
 
+#if GTK_CHECK_VERSION(2,12,0)
+	gpointer depr1;
+#else
 	GtkTooltips *tooltips;
+#endif
 
 	GtkWidget *bold;
 	GtkWidget *italic;
--- a/pidgin/gtkmenutray.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkmenutray.c	Tue Jul 28 05:49:14 2009 +0000
@@ -104,9 +104,11 @@
 		gtk_widget_destroy(GTK_WIDGET(tray->tray));
 #endif
 
+#if !GTK_CHECK_VERSION(2,12,0)
 	if (tray->tooltips) {
 		gtk_object_sink(GTK_OBJECT(tray->tooltips));
 	}
+#endif
 
 	G_OBJECT_CLASS(parent_class)->finalize(obj);
 }
@@ -244,13 +246,15 @@
 void
 pidgin_menu_tray_set_tooltip(PidginMenuTray *menu_tray, GtkWidget *widget, const char *tooltip)
 {
+#if !GTK_CHECK_VERSION(2,12,0)
 	if (!menu_tray->tooltips)
 		menu_tray->tooltips = gtk_tooltips_new();
+#endif
 
 	/* Should we check whether widget is a child of menu_tray? */
 
 	/*
-	 * If the widget does not have it's own window, then it
+	 * If the widget does not have its own window, then it
 	 * must have automatically been added to an event box
 	 * when it was added to the menu tray.  If this is the
 	 * case, we want to set the tooltip on the widget's parent,
@@ -259,6 +263,10 @@
 	if (GTK_WIDGET_NO_WINDOW(widget))
 		widget = widget->parent;
 
+#if GTK_CHECK_VERSION(2,12,0)
+	gtk_widget_set_tooltip_text(widget, tooltip);
+#else
 	gtk_tooltips_set_tip(menu_tray->tooltips, widget, tooltip, NULL);
+#endif
 }
 
--- a/pidgin/gtkmenutray.h	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkmenutray.h	Tue Jul 28 05:49:14 2009 +0000
@@ -40,7 +40,11 @@
 struct _PidginMenuTray {
 	GtkMenuItem gparent;					/**< The parent instance */
 	GtkWidget *tray;						/**< The tray */
+#if GTK_CHECK_VERSION(2,12,0)
+	gpointer depr1;
+#else
 	GtkTooltips *tooltips;					/**< Tooltips */
+#endif
 };
 
 /** A PidginMenuTrayClass */
--- a/pidgin/gtkprefs.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkprefs.c	Tue Jul 28 05:49:14 2009 +0000
@@ -176,14 +176,52 @@
 	return pidgin_add_widget_to_vbox(GTK_BOX(page), title, sg, entry, TRUE, NULL);
 }
 
+/* TODO: Maybe move this up somewheres... */
+enum {
+	PREF_DROPDOWN_TEXT,
+	PREF_DROPDOWN_VALUE,
+	PREF_DROPDOWN_COUNT
+};
 
 static void
 dropdown_set(GObject *w, const char *key)
 {
 	const char *str_value;
 	int int_value;
+	gboolean bool_value;
 	PurplePrefType type;
 
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkTreeIter iter;
+	GtkTreeModel *tree_model;
+
+	tree_model = gtk_combo_box_get_model(GTK_COMBO_BOX(w));
+	gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w), &iter);
+
+	type = GPOINTER_TO_INT(g_object_get_data(w, "type"));
+
+	if (type == PURPLE_PREF_INT) {
+		gtk_tree_model_get(tree_model, &iter,
+		                   PREF_DROPDOWN_VALUE, &int_value,
+		                   -1);
+
+		purple_prefs_set_int(key, int_value);
+	}
+	else if (type == PURPLE_PREF_STRING) {
+		gtk_tree_model_get(tree_model, &iter,
+		                   PREF_DROPDOWN_VALUE, &str_value,
+		                   -1);
+
+		purple_prefs_set_string(key, str_value);
+	}
+	else if (type == PURPLE_PREF_BOOLEAN) {
+		gtk_tree_model_get(tree_model, &iter,
+		                   PREF_DROPDOWN_VALUE, &bool_value,
+		                   -1);
+
+		purple_prefs_set_bool(key, bool_value);
+	}
+#else
 	type = GPOINTER_TO_INT(g_object_get_data(w, "type"));
 
 	if (type == PURPLE_PREF_INT) {
@@ -197,64 +235,129 @@
 		purple_prefs_set_string(key, str_value);
 	}
 	else if (type == PURPLE_PREF_BOOLEAN) {
-		purple_prefs_set_bool(key,
-				GPOINTER_TO_INT(g_object_get_data(w, "value")));
+		bool_value = (gboolean)GPOINTER_TO_INT(g_object_get_data(w, "value"));
+		purple_prefs_set_bool(key, bool_value);
 	}
+#endif
 }
 
 GtkWidget *
 pidgin_prefs_dropdown_from_list(GtkWidget *box, const gchar *title,
 		PurplePrefType type, const char *key, GList *menuitems)
 {
-	GtkWidget  *dropdown, *opt, *menu;
+	GtkWidget  *dropdown;
 	GtkWidget  *label = NULL;
 	gchar      *text;
 	const char *stored_str = NULL;
 	int         stored_int = 0;
+	gboolean    stored_bool = FALSE;
 	int         int_value  = 0;
 	const char *str_value  = NULL;
+	gboolean    bool_value = FALSE;
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkListStore *store;
+	GtkTreeIter iter;
+	GtkTreeIter active;
+	GtkCellRenderer *renderer;
+
+	g_return_val_if_fail(menuitems != NULL, NULL);
+
+	if (type == PURPLE_PREF_INT) {
+		store = gtk_list_store_new(PREF_DROPDOWN_COUNT, G_TYPE_STRING, G_TYPE_INT);
+		stored_int = purple_prefs_get_int(key);
+	} else if (type == PURPLE_PREF_STRING) {
+		store = gtk_list_store_new(PREF_DROPDOWN_COUNT, G_TYPE_STRING, G_TYPE_STRING);
+		stored_str = purple_prefs_get_string(key);
+	} else if (type == PURPLE_PREF_BOOLEAN) {
+		store = gtk_list_store_new(PREF_DROPDOWN_COUNT, G_TYPE_STRING, G_TYPE_BOOLEAN);
+		stored_bool = purple_prefs_get_bool(key);
+	}
+
+	dropdown = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
+	g_object_set_data(G_OBJECT(dropdown), "type", GINT_TO_POINTER(type));
+
+	while (menuitems != NULL && (text = (char *)menuitems->data) != NULL) {
+		menuitems = g_list_next(menuitems);
+		g_return_val_if_fail(menuitems != NULL, NULL);
+
+		gtk_list_store_append(store, &iter);
+		gtk_list_store_set(store, &iter,
+		                   PREF_DROPDOWN_TEXT, text,
+		                   -1);
+
+		if (type == PURPLE_PREF_INT) {
+			int_value = GPOINTER_TO_INT(menuitems->data);
+			gtk_list_store_set(store, &iter,
+			                   PREF_DROPDOWN_VALUE, int_value,
+			                   -1);
+		}
+		else if (type == PURPLE_PREF_STRING) {
+			str_value = (const char *)menuitems->data;
+			gtk_list_store_set(store, &iter,
+			                   PREF_DROPDOWN_VALUE, str_value,
+			                   -1);
+		}
+		else if (type == PURPLE_PREF_BOOLEAN) {
+			bool_value = (gboolean)GPOINTER_TO_INT(menuitems->data);
+			gtk_list_store_set(store, &iter,
+			                   PREF_DROPDOWN_VALUE, bool_value,
+			                   -1);
+		}
+
+		if ((type == PURPLE_PREF_INT && stored_int == int_value) ||
+			(type == PURPLE_PREF_STRING && stored_str != NULL &&
+			 !strcmp(stored_str, str_value)) ||
+			(type == PURPLE_PREF_BOOLEAN &&
+			 (stored_bool == bool_value))) {
+
+			active = iter;
+		}
+
+		menuitems = g_list_next(menuitems);
+	}
+
+	renderer = gtk_cell_renderer_text_new();
+	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropdown), renderer, TRUE);
+	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropdown), renderer,
+	                               "text", 0,
+	                               NULL);
+
+	gtk_combo_box_set_active_iter(GTK_COMBO_BOX(dropdown), &active);
+
+	g_signal_connect(G_OBJECT(dropdown), "changed",
+	                 G_CALLBACK(dropdown_set), (char *)key);
+
+#else
+	GtkWidget  *opt, *menu;
 	int         o = 0;
 
 	g_return_val_if_fail(menuitems != NULL, NULL);
 
-#if 0 /* GTK_CHECK_VERSION(2,4,0) */
-	if(type == PURPLE_PREF_INT)
-		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
-	else if(type == PURPLE_PREF_STRING)
-		model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
-	dropdown = gtk_combo_box_new_with_model(model);
-#else
 	dropdown = gtk_option_menu_new();
 	menu = gtk_menu_new();
-#endif
 
 	if (type == PURPLE_PREF_INT)
 		stored_int = purple_prefs_get_int(key);
 	else if (type == PURPLE_PREF_STRING)
 		stored_str = purple_prefs_get_string(key);
-
-	while (menuitems != NULL && (text = (char *) menuitems->data) != NULL) {
+	else if (type == PURPLE_PREF_BOOLEAN)
+		stored_bool = purple_prefs_get_bool(key);
+
+	while (menuitems != NULL && (text = (char *)menuitems->data) != NULL) {
 		menuitems = g_list_next(menuitems);
 		g_return_val_if_fail(menuitems != NULL, NULL);
 
 		opt = gtk_menu_item_new_with_label(text);
 
 		g_object_set_data(G_OBJECT(opt), "type", GINT_TO_POINTER(type));
-
-		if (type == PURPLE_PREF_INT) {
+		g_object_set_data(G_OBJECT(opt), "value", menuitems->data);
+
+		if (type == PURPLE_PREF_INT)
 			int_value = GPOINTER_TO_INT(menuitems->data);
-			g_object_set_data(G_OBJECT(opt), "value",
-							  GINT_TO_POINTER(int_value));
-		}
-		else if (type == PURPLE_PREF_STRING) {
+		else if (type == PURPLE_PREF_STRING)
 			str_value = (const char *)menuitems->data;
-
-			g_object_set_data(G_OBJECT(opt), "value", (char *)str_value);
-		}
-		else if (type == PURPLE_PREF_BOOLEAN) {
-			g_object_set_data(G_OBJECT(opt), "value",
-					menuitems->data);
-		}
+		else if (type == PURPLE_PREF_BOOLEAN)
+			bool_value = (gboolean)GPOINTER_TO_INT(menuitems->data);
 
 		g_signal_connect(G_OBJECT(opt), "activate",
 						 G_CALLBACK(dropdown_set), (char *)key);
@@ -266,7 +369,7 @@
 			(type == PURPLE_PREF_STRING && stored_str != NULL &&
 			 !strcmp(stored_str, str_value)) ||
 			(type == PURPLE_PREF_BOOLEAN &&
-			 (purple_prefs_get_bool(key) == GPOINTER_TO_INT(menuitems->data)))) {
+			 (stored_bool == bool_value))) {
 
 			gtk_menu_set_active(GTK_MENU(menu), o);
 		}
@@ -278,6 +381,8 @@
 
 	gtk_option_menu_set_menu(GTK_OPTION_MENU(dropdown), menu);
 
+#endif
+
 	pidgin_add_widget_to_vbox(GTK_BOX(box), title, NULL, dropdown, FALSE, &label);
 
 	return label;
--- a/pidgin/gtkprivacy.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkprivacy.c	Tue Jul 28 05:49:14 2009 +0000
@@ -220,7 +220,11 @@
 
 	for (i = 0; i < menu_entry_count; i++) {
 		if (menu_entries[i].num == account->perm_deny) {
+#if GTK_CHECK_VERSION(2,4,0)
+			gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->type_menu), i);
+#else
 			gtk_option_menu_set_history(GTK_OPTION_MENU(dialog->type_menu), i);
+#endif
 			break;
 		}
 	}
@@ -233,10 +237,17 @@
  * TODO: Setting the permit/deny setting needs to go through privacy.c
  *       Even better: the privacy API needs to not suck.
  */
+#if GTK_CHECK_VERSION(2,4,0)
+static void
+type_changed_cb(GtkComboBox *combo, PidginPrivacyDialog *dialog)
+{
+	int new_type = menu_entries[gtk_combo_box_get_active(combo)].num;
+#else
 static void
 type_changed_cb(GtkOptionMenu *optmenu, PidginPrivacyDialog *dialog)
 {
 	int new_type = menu_entries[gtk_option_menu_get_history(optmenu)].num;
+#endif
 
 	dialog->account->perm_deny = new_type;
 	serv_set_permit_deny(purple_account_get_connection(dialog->account));
@@ -343,7 +354,9 @@
 	GtkWidget *button;
 	GtkWidget *dropdown;
 	GtkWidget *label;
+#if !GTK_CHECK_VERSION(2,4,0)
 	GtkWidget *menu;
+#endif
 	int selected = 0;
 	int i;
 
@@ -372,6 +385,24 @@
 	dialog->account = pidgin_account_option_menu_get_selected(dropdown);
 
 	/* Add the drop-down list with the allow/block types. */
+#if GTK_CHECK_VERSION(2,4,0)
+	dialog->type_menu = gtk_combo_box_new_text();
+	gtk_box_pack_start(GTK_BOX(vbox), dialog->type_menu, FALSE, FALSE, 0);
+	gtk_widget_show(dialog->type_menu);
+
+	for (i = 0; i < menu_entry_count; i++) {
+		gtk_combo_box_append_text(GTK_COMBO_BOX(dialog->type_menu),
+		                          _(menu_entries[i].text));
+
+		if (menu_entries[i].num == dialog->account->perm_deny)
+			selected = i;
+	}
+
+	gtk_combo_box_set_active(GTK_COMBO_BOX(dialog->type_menu), selected);
+
+	g_signal_connect(G_OBJECT(dialog->type_menu), "changed",
+					 G_CALLBACK(type_changed_cb), dialog);
+#else
 	dialog->type_menu = gtk_option_menu_new();
 	gtk_box_pack_start(GTK_BOX(vbox), dialog->type_menu, FALSE, FALSE, 0);
 	gtk_widget_show(dialog->type_menu);
@@ -391,6 +422,7 @@
 
 	g_signal_connect(G_OBJECT(dialog->type_menu), "changed",
 					 G_CALLBACK(type_changed_cb), dialog);
+#endif
 
 	/* Build the treeview for the allow list. */
 	dialog->allow_widget = build_allow_list(dialog);
@@ -421,7 +453,11 @@
 	button = pidgin_dialog_add_button(GTK_DIALOG(dialog->win), GTK_STOCK_CLOSE, G_CALLBACK(close_cb), dialog);
 	dialog->close_button = button;
 
+#if GTK_CHECK_VERSION(2,4,0)
+	type_changed_cb(GTK_COMBO_BOX(dialog->type_menu), dialog);
+#else
 	type_changed_cb(GTK_OPTION_MENU(dialog->type_menu), dialog);
+#endif
 #if 0
 	if (dialog->account->perm_deny == PURPLE_PRIVACY_ALLOW_USERS) {
 		gtk_widget_show(dialog->allow_widget);
--- a/pidgin/gtkrequest.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtkrequest.c	Tue Jul 28 05:49:14 2009 +0000
@@ -202,12 +202,21 @@
 			gtk_toggle_button_get_active(button));
 }
 
+#if GTK_CHECK_VERSION(2,4,0)
+static void
+field_choice_menu_cb(GtkComboBox *menu, PurpleRequestField *field)
+{
+	purple_request_field_choice_set_value(field,
+			gtk_combo_box_get_active(menu));
+}
+#else
 static void
 field_choice_menu_cb(GtkOptionMenu *menu, PurpleRequestField *field)
 {
 	purple_request_field_choice_set_value(field,
 			gtk_option_menu_get_history(menu));
 }
+#endif
 
 static void
 field_choice_option_cb(GtkRadioButton *button, PurpleRequestField *field)
@@ -874,6 +883,21 @@
 
 	if (num_labels > 5)
 	{
+#if GTK_CHECK_VERSION(2,4,0)
+		widget = gtk_combo_box_new_text();
+
+		for (l = labels; l != NULL; l = l->next)
+		{
+			const char *text = l->data;
+			gtk_combo_box_append_text(GTK_COMBO_BOX(widget), text);
+		}
+
+		gtk_combo_box_set_active(GTK_COMBO_BOX(widget),
+						purple_request_field_choice_get_default_value(field));
+
+		g_signal_connect(G_OBJECT(widget), "changed",
+						 G_CALLBACK(field_choice_menu_cb), field);
+#else
 		GtkWidget *menu;
 		GtkWidget *item;
 
@@ -898,6 +922,7 @@
 
 		g_signal_connect(G_OBJECT(widget), "changed",
 						 G_CALLBACK(field_choice_menu_cb), field);
+#endif
 	}
 	else
 	{
--- a/pidgin/gtksavedstatuses.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/gtksavedstatuses.c	Tue Jul 28 05:49:14 2009 +0000
@@ -119,7 +119,11 @@
 
 	gchar *original_title;
 	GtkEntry *title;
+#if GTK_CHECK_VERSION(2,4,0)
+	GtkComboBox *type;
+#else
 	GtkOptionMenu *type;
+#endif
 	GtkIMHtml *message;
 } StatusEditor;
 
@@ -780,7 +784,11 @@
 		return;
 	}
 
+#if GTK_CHECK_VERSION(2,4,0)
+	type = gtk_combo_box_get_active(dialog->type) + (PURPLE_STATUS_UNSET + 1);
+#else
 	type = gtk_option_menu_get_history(dialog->type) + (PURPLE_STATUS_UNSET + 1);
+#endif
 	message = gtk_imhtml_get_markup(dialog->message);
 	unformatted = purple_markup_strip_html(message);
 
@@ -874,6 +882,64 @@
 	gtk_widget_set_sensitive(GTK_WIDGET(dialog->save_button), (*text != '\0'));
 }
 
+#if GTK_CHECK_VERSION(2,4,0)
+
+enum {
+	STATUS_MENU_STOCK_ICON,
+	STATUS_MENU_NAME,
+	STATUS_MENU_COUNT
+};
+
+static GtkWidget *
+create_status_type_menu(PurpleStatusPrimitive type)
+{
+	int i;
+	GtkWidget *dropdown;
+	GtkListStore *store;
+	GtkTreeIter iter;
+	GtkCellRenderer *renderer;
+
+	store = gtk_list_store_new(STATUS_MENU_COUNT, G_TYPE_STRING, G_TYPE_STRING);
+
+	for (i = PURPLE_STATUS_UNSET + 1; i < PURPLE_STATUS_NUM_PRIMITIVES; i++)
+	{
+		if (i == PURPLE_STATUS_MOBILE || i == PURPLE_STATUS_TUNE)
+			/*
+			 * Special-case these.  They're intended to be independent
+			 * status types, so don't show them in the list.
+			 */
+			continue;
+
+		gtk_list_store_append(store, &iter);
+		/* TODO: how's this get the right size (since it seems to work fine)? */
+		gtk_list_store_set(store, &iter,
+		                   STATUS_MENU_STOCK_ICON, get_stock_icon_from_primitive(i),
+		                   STATUS_MENU_NAME, purple_primitive_get_name_from_type(i),
+		                   -1);
+	}
+
+	dropdown = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
+
+	renderer = gtk_cell_renderer_pixbuf_new();
+	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropdown), renderer, FALSE);
+	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropdown), renderer,
+	                               "stock-id", STATUS_MENU_STOCK_ICON,
+	                               NULL);
+
+	renderer = gtk_cell_renderer_text_new();
+	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(dropdown), renderer, TRUE);
+	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(dropdown), renderer,
+	                               "text", STATUS_MENU_NAME,
+	                               NULL);
+
+	gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown),
+	                         type - (PURPLE_STATUS_UNSET + 1));
+
+	return dropdown;
+}
+
+#else
+
 static GtkWidget *
 create_stock_item(const gchar *str, const gchar *icon)
 {
@@ -881,7 +947,7 @@
 	GtkWidget *label = gtk_label_new_with_mnemonic(str);
 	GtkWidget *hbox = gtk_hbox_new(FALSE, 4);
 	GtkIconSize icon_size = gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL);
-	GtkWidget *image = gtk_image_new_from_stock(icon, icon_size);;
+	GtkWidget *image = gtk_image_new_from_stock(icon, icon_size);
 
 	gtk_widget_show(label);
 	gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
@@ -926,6 +992,8 @@
 	return dropdown;
 }
 
+#endif
+
 static void edit_substatus(StatusEditor *status_editor, PurpleAccount *account);
 
 static void
@@ -1191,7 +1259,11 @@
 		dropdown = create_status_type_menu(purple_savedstatus_get_type(saved_status));
 	else
 		dropdown = create_status_type_menu(PURPLE_STATUS_AWAY);
+#if GTK_CHECK_VERSION(2,4,0)
+	dialog->type = GTK_COMBO_BOX(dropdown);
+#else
 	dialog->type = GTK_OPTION_MENU(dropdown);
+#endif
 	pidgin_add_widget_to_vbox(GTK_BOX(vbox), _("_Status:"), sg, dropdown, TRUE, NULL);
 
 	/* Status message */
--- a/pidgin/plugins/gestures/gestures.c	Tue Jul 28 04:43:53 2009 +0000
+++ b/pidgin/plugins/gestures/gestures.c	Tue Jul 28 05:49:14 2009 +0000
@@ -149,6 +149,15 @@
 }
 
 #if 0
+#if GTK_CHECK_VERSION(2,4,0)
+static void
+mouse_button_menu_cb(GtkComboBox *opt, gpointer data)
+{
+	int button = gtk_combo_box_get_active(opt);
+
+	gstroke_set_mouse_button(button + 2);
+}
+#else
 static void
 mouse_button_menu_cb(GtkMenuItem *item, gpointer data)
 {
@@ -157,6 +166,7 @@
 	gstroke_set_mouse_button(button + 2);
 }
 #endif
+#endif
 
 static void
 toggle_draw_cb(GtkToggleButton *toggle, gpointer data)
@@ -224,8 +234,10 @@
 	GtkWidget *toggle;
 #if 0
 	GtkWidget *opt;
+#if GTK_CHECK_VERSION(2,4,0)
 	GtkWidget *menu, *item;
 #endif
+#endif
 
 	/* Outside container */
 	ret = gtk_vbox_new(FALSE, 18);
@@ -235,6 +247,19 @@
 	vbox = pidgin_make_frame(ret, _("Mouse Gestures Configuration"));
 
 #if 0
+#if GTK_CHECK_VERSION(2,4,0)
+	/* Mouse button drop-down menu */
+	opt = gtk_combo_box_new_text();
+
+	gtk_combo_box_append_text(_("Middle mouse button"));
+	gtk_combo_box_append_text(_("Right mouse button"));
+	g_signal_connect(G_OBJECT(opt), "changed",
+	                 G_CALLBACK(mouse_button_menu_cb), NULL);
+
+	gtk_box_pack_start(GTK_BOX(vbox), opt, FALSE, FALSE, 0);
+	gtk_combo_box_set_active(GTK_COMBO_BOX(opt),
+							gstroke_get_mouse_button() - 2);
+#else
 	/* Mouse button drop-down menu */
 	menu = gtk_menu_new();
 	opt = gtk_option_menu_new();
@@ -254,6 +279,7 @@
 	gtk_option_menu_set_history(GTK_OPTION_MENU(opt),
 								gstroke_get_mouse_button() - 2);
 #endif
+#endif
 
 	/* "Visual gesture display" checkbox */
 	toggle = gtk_check_button_new_with_mnemonic(_("_Visual gesture display"));