diff --git a/ChangeLog.API b/ChangeLog.API
--- a/ChangeLog.API
+++ b/ChangeLog.API
@@ -576,7 +576,6 @@ version 3.0.0 (??/??/????):
 		* purple_time_build. Use g_date_time_new* instead.
 		* purple_time_format. Use g_date_time_format instead.
 		* purple_timeout_*. Use g_timeout_* or g_idle_* instead.
-		* pidgin_tooltip_setup_for_widget
 		* purple_txt_cancel
 		* purple_txt_resolve_account
 		* PurpleType, use GType instead.
@@ -689,6 +688,7 @@ version 3.0.0 (??/??/????):
 		* gtk_imhtml_image_free
 		* gtk_imhtml_image_new
 		* gtk_imhtml_image_scale
+		* pidgin_blist_draw_tooltip
 		* pidgin_blist_get_theme
 		* pidgin_blist_layout_get_type
 		* pidgin_blist_set_theme
@@ -726,6 +726,7 @@ version 3.0.0 (??/??/????):
 		* pidgin_blist_theme_set_status_text_info
 		* pidgin_blist_theme_set_unread_message_nick_said_text_info
 		* pidgin_blist_theme_set_unread_message_text_info
+		* pidgin_blist_tooltip_destroy
 		* pidgin_blist_update_account_error_state
 		* PidginBlistLayout
 		* PidginBuddyList.connection_errors
@@ -785,6 +786,13 @@ version 3.0.0 (??/??/????):
 		* pidgin_theme_font_set_font_face
 		* pidgin_toggle_sensitive, pidgin_toggle_sensitive_array, and
 		  pidgin_toggle_showhide; use g_object_bind_property instead
+		* PidginTooltipCreate
+		* PidginTooltipCreateForTree
+		* PidginTooltipPaint
+		* pidgin_tooltip_destroy
+		* pidgin_tooltip_setup_for_treeview
+		* pidgin_tooltip_setup_for_widget
+		* pidgin_tooltip_show
 		* PidginThemeFont
 		* struct _GtkIMHtmlAnimation
 		* struct _GtkIMHtmlFontDetail
diff --git a/doc/reference/pidgin/pidgin-docs.xml b/doc/reference/pidgin/pidgin-docs.xml
--- a/doc/reference/pidgin/pidgin-docs.xml
+++ b/doc/reference/pidgin/pidgin-docs.xml
@@ -87,7 +87,6 @@
       <xi:include href="xml/pidginstock.xml" />
       <xi:include href="xml/pidginstylecontext.xml" />
       <xi:include href="xml/pidgintalkatu.xml" />
-      <xi:include href="xml/pidgintooltip.xml" />
       <xi:include href="xml/pidginwindow.xml" />
   </part>
 
diff --git a/pidgin/gtkblist.h b/pidgin/gtkblist.h
--- a/pidgin/gtkblist.h
+++ b/pidgin/gtkblist.h
@@ -64,8 +64,6 @@ typedef enum {
  * @contact_rect:      This is the bounding rectangle of the contact node and
  *                     its children.  This is used for auto-expand on mouseover.
  * @mouseover_contact: This is the contact currently mouse-over expanded
- * @tipwindow:         The window used by the tooltip
- * @tooltipdata:       The data for each "chunk" of the tooltip
  * @selected_node:     The currently selected node
  * @scrollbook:        Scrollbook for alerts
  * @headline:          Widget for headline notifications
@@ -103,9 +101,6 @@ struct _PidginBuddyList {
 	GdkRectangle contact_rect;
 	PurpleBlistNode *mouseover_contact;
 
-	GtkWidget *tipwindow;
-	GList *tooltipdata;
-
 	PurpleBlistNode *selected_node;
 
 	GtkWidget *scrollbook;
@@ -413,18 +408,6 @@ void pidgin_blist_set_headline(const cha
 gchar *pidgin_blist_get_name_markup(PurpleBuddy *buddy, gboolean selected, gboolean aliased);
 
 /**
- * pidgin_blist_draw_tooltip:
- * @node: The buddy list node to show a tooltip for
- * @widget: The widget to draw the tooltip on
- *
- * Creates the Buddy List tooltip at the current pointer location for the given buddy list node.
- *
- * This tooltip will be destroyed the next time this function is called, or when XXXX
- * is called
- */
-void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget);
-
-/**
  * pidgin_blist_query_tooltip_for_node:
  * @node: The buddy list to query a tooltip for.
  * @tooltip: The tooltip object to add a tooltip to.
@@ -437,13 +420,6 @@ void pidgin_blist_draw_tooltip(PurpleBli
  */
 gboolean pidgin_blist_query_tooltip_for_node(PurpleBlistNode *node, GtkTooltip *tooltip);
 
-/**
- * pidgin_blist_tooltip_destroy:
- *
- * Destroys the current (if any) Buddy List tooltip
- */
-void pidgin_blist_tooltip_destroy(void);
-
 G_END_DECLS
 
 #endif /* _PIDGINBLIST_H_ */
diff --git a/pidgin/gtkblist.c b/pidgin/gtkblist.c
--- a/pidgin/gtkblist.c
+++ b/pidgin/gtkblist.c
@@ -52,7 +52,6 @@
 #include "pidgin/pidginplugininfo.h"
 #include "pidginscrollbook.h"
 #include "pidgin/pidginstylecontext.h"
-#include "pidgin/pidgintooltip.h"
 #include "pidgin/pidginwindow.h"
 #include "pidginstock.h"
 
@@ -707,7 +706,7 @@ static void gtk_blist_menu_alias_cb(GtkW
 			return;
 	}
 
-	pidgin_blist_tooltip_destroy();
+	gtk_widget_trigger_tooltip_query(gtkblist->treeview);
 
 	path = gtk_tree_model_get_path(GTK_TREE_MODEL(gtkblist->treemodel), &iter);
 	g_object_set(G_OBJECT(gtkblist->text_rend), "editable", TRUE, NULL);
@@ -1192,7 +1191,7 @@ static void gtk_blist_row_expanded_cb(Gt
 		g_free(title);
 
 		purple_blist_node_set_bool(node, "collapsed", FALSE);
-		pidgin_blist_tooltip_destroy();
+		gtk_widget_trigger_tooltip_query(gtkblist->treeview);
 	}
 }
 
@@ -1227,7 +1226,7 @@ static void gtk_blist_row_collapsed_cb(G
 				pidgin_blist_update_contact(NULL, cnode);
 			}
 		}
-		pidgin_blist_tooltip_destroy();
+		gtk_widget_trigger_tooltip_query(gtkblist->treeview);
 	} else if(PURPLE_IS_CONTACT(node)) {
 		pidgin_blist_collapse_contact_cb(NULL, node);
 	}
@@ -1922,10 +1921,6 @@ pidgin_blist_show_context_menu(GtkWidget
 		menu = create_buddy_menu(node, b);
 	}
 
-#ifdef _WIN32
-	pidgin_blist_tooltip_destroy();
-#endif
-
 	/* Now display the menu */
 	if (menu != NULL) {
 		gtk_widget_show_all(menu);
@@ -2141,14 +2136,6 @@ parse_vcard(const char *vcard, PurpleGro
 	return TRUE;
 }
 
-#ifdef _WIN32
-static void pidgin_blist_drag_begin(GtkWidget *widget,
-		GdkDragContext *drag_context, gpointer user_data)
-{
-	pidgin_blist_tooltip_destroy();
-}
-#endif
-
 static void pidgin_blist_drag_data_get_cb(GtkWidget *widget,
 											GdkDragContext *dc,
 											GtkSelectionData *data,
@@ -2711,369 +2698,6 @@ static GdkPixbuf *pidgin_blist_get_buddy
 	return ret;
 }
 
-/* # - Status Icon
- * P - Protocol Icon
- * A - Buddy Icon
- * [ - SMALL_SPACE
- * = - LARGE_SPACE
- *                   +--- STATUS_SIZE                +--- td->avatar_width
- *                   |         +-- td->name_width    |
- *                +----+   +-------+            +---------+
- *                |    |   |       |            |         |
- *                +-------------------------------------------+
- *                |       [          =        [               |--- TOOLTIP_BORDER
- *name_height --+-| ######[BuddyName = PP     [   AAAAAAAAAAA |--+
- *              | | ######[          = PP     [   AAAAAAAAAAA |  |
- * STATUS SIZE -| | ######[[[[[[[[[[[[[[[[[[[[[   AAAAAAAAAAA |  |
- *           +--+-| ######[Account: So-and-so [   AAAAAAAAAAA |  |-- td->avatar_height
- *           |    |       [Idle: 4h 15m       [   AAAAAAAAAAA |  |
- *  height --+    |       [Foo: Bar, Baz      [   AAAAAAAAAAA |  |
- *           |    |       [Status: Awesome    [   AAAAAAAAAAA |--+
- *           +----|       [Stop: Hammer Time  [               |
- *                |       [                   [               |--- TOOLTIP_BORDER
- *                +-------------------------------------------+
- *                 |       |                |                |
- *                 |       +----------------+                |
- *                 |               |                         |
- *                 |               +-- td->width             |
- *                 |                                         |
- *                 +---- TOOLTIP_BORDER                      +---- TOOLTIP_BORDER
- *
- *
- */
-#define STATUS_SIZE 16
-#define TOOLTIP_BORDER 12
-#define SMALL_SPACE 6
-#define LARGE_SPACE 12
-#define PROTOCOL_SIZE 16
-struct tooltip_data {
-	PangoLayout *layout;
-	PangoLayout *name_layout;
-	GdkPixbuf *protocol_icon;
-	GdkPixbuf *status_icon;
-	GdkPixbuf *avatar;
-	gboolean avatar_is_protocol_icon;
-	int avatar_width;
-	int avatar_height;
-	int name_height;
-	int name_width;
-	int width;
-	int height;
-	int padding;
-};
-
-static PangoLayout * create_pango_layout(const char *markup, int *width, int *height)
-{
-	PangoLayout *layout;
-	int w, h;
-
-	layout = gtk_widget_create_pango_layout(gtkblist->tipwindow, NULL);
-	pango_layout_set_markup(layout, markup, -1);
-	pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
-	pango_layout_set_width(layout, 300000);
-
-	pango_layout_get_size (layout, &w, &h);
-	if (width)
-		*width = PANGO_PIXELS(w);
-	if (height)
-		*height = PANGO_PIXELS(h);
-	return layout;
-}
-
-static struct tooltip_data * create_tip_for_account(PurpleAccount *account)
-{
-	struct tooltip_data *td = g_new0(struct tooltip_data, 1);
-	td->status_icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
-		/* Yes, status_icon, not protocol_icon */
-	if (purple_account_is_disconnected(account))
-		gdk_pixbuf_saturate_and_pixelate(td->status_icon, td->status_icon, 0.0, FALSE);
-	td->layout = create_pango_layout(purple_account_get_username(account), &td->width, &td->height);
-	td->padding = SMALL_SPACE;
-	return td;
-}
-
-static struct tooltip_data * create_tip_for_node(PurpleBlistNode *node, gboolean full)
-{
-	struct tooltip_data *td = g_new0(struct tooltip_data, 1);
-	PurpleAccount *account = NULL;
-	char *tmp = NULL, *node_name = NULL, *tooltip_text = NULL;
-
-	if (PURPLE_IS_BUDDY(node)) {
-		account = purple_buddy_get_account((PurpleBuddy*)(node));
-	} else if (PURPLE_IS_CHAT(node)) {
-		account = purple_chat_get_account((PurpleChat*)(node));
-	}
-
-	td->padding = TOOLTIP_BORDER;
-	td->status_icon = pidgin_blist_get_status_icon(node, PIDGIN_STATUS_ICON_LARGE);
-	td->avatar = pidgin_blist_get_buddy_icon(node, !full, FALSE);
-	if (account != NULL) {
-		td->protocol_icon = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_SMALL);
-	}
-	tooltip_text = pidgin_get_tooltip_text(node, full);
-	if (tooltip_text && *tooltip_text) {
-		td->layout = create_pango_layout(tooltip_text, &td->width, &td->height);
-	}
-
-	if (PURPLE_IS_BUDDY(node)) {
-		tmp = g_markup_escape_text(purple_buddy_get_name((PurpleBuddy*)node), -1);
-	} else if (PURPLE_IS_CHAT(node)) {
-		tmp = g_markup_escape_text(purple_chat_get_name((PurpleChat*)node), -1);
-	} else if (PURPLE_IS_GROUP(node)) {
-		tmp = g_markup_escape_text(purple_group_get_name((PurpleGroup*)node), -1);
-	} else {
-		/* I don't believe this can happen currently, I think
-		 * everything that calls this function checks for one of the
-		 * above node types first. */
-		tmp = g_strdup(_("Unknown node type"));
-	}
-	node_name = g_strdup_printf("<span size='x-large' weight='bold'>%s</span>",
-								tmp ? tmp : "");
-	g_free(tmp);
-
-	td->name_layout = create_pango_layout(node_name, &td->name_width, &td->name_height);
-	td->name_width += SMALL_SPACE + PROTOCOL_SIZE;
-	td->name_height = MAX(td->name_height, PROTOCOL_SIZE + SMALL_SPACE);
-#if 0  /* Protocol Icon as avatar */
-	if(!td->avatar && full) {
-		td->avatar = pidgin_create_protocol_icon(account, PIDGIN_PROTOCOL_ICON_LARGE);
-		td->avatar_is_protocol_icon = TRUE;
-	}
-#endif
-
-	if (td->avatar) {
-		td->avatar_width = gdk_pixbuf_get_width(td->avatar);
-		td->avatar_height = gdk_pixbuf_get_height(td->avatar);
-	}
-
-	g_free(node_name);
-	g_free(tooltip_text);
-	return td;
-}
-
-static gboolean
-pidgin_blist_paint_tip(GtkWidget *widget, cairo_t *cr, gpointer null)
-{
-	GtkStyleContext *context;
-	int current_height, max_width;
-	int max_text_width;
-	int max_avatar_width;
-	GList *l;
-	int protocol_col = 0;
-	GtkTextDirection dir = gtk_widget_get_direction(widget);
-	int status_size = 0;
-
-	if(gtkblist->tooltipdata == NULL)
-		return FALSE;
-
-	context = gtk_widget_get_style_context(gtkblist->tipwindow);
-	gtk_style_context_add_class(context, GTK_STYLE_CLASS_TOOLTIP);
-
-	max_text_width = 0;
-	max_avatar_width = 0;
-
-	for(l = gtkblist->tooltipdata; l; l = l->next)
-	{
-		struct tooltip_data *td = l->data;
-
-		max_text_width = MAX(max_text_width,
-				MAX(td->width, td->name_width));
-		max_avatar_width = MAX(max_avatar_width, td->avatar_width);
-		if (td->status_icon)
-			status_size = STATUS_SIZE;
-	}
-
-	max_width = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width + SMALL_SPACE + max_avatar_width + TOOLTIP_BORDER;
-	if (dir == GTK_TEXT_DIR_RTL)
-		protocol_col = TOOLTIP_BORDER + max_avatar_width + SMALL_SPACE;
-	else
-		protocol_col = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width - PROTOCOL_SIZE;
-
-	current_height = 12;
-	for(l = gtkblist->tooltipdata; l; l = l->next)
-	{
-		struct tooltip_data *td = l->data;
-
-		if (td->avatar && pidgin_gdk_pixbuf_is_opaque(td->avatar))
-		{
-			gtk_style_context_save(context);
-			gtk_style_context_add_class(context, GTK_STYLE_CLASS_FRAME);
-			if (dir == GTK_TEXT_DIR_RTL) {
-				gtk_render_frame(context, cr,
-				                 TOOLTIP_BORDER - 1, current_height - 1,
-				                 td->avatar_width + 2, td->avatar_height + 2);
-			} else {
-				gtk_render_frame(context, cr,
-				                 max_width - (td->avatar_width + TOOLTIP_BORDER) - 1,
-				                 current_height - 1,
-				                 td->avatar_width + 2, td->avatar_height + 2);
-			}
-			gtk_style_context_restore(context);
-		}
-
-		if (td->status_icon) {
-			if (dir == GTK_TEXT_DIR_RTL) {
-				gdk_cairo_set_source_pixbuf(cr, td->status_icon,
-				                            max_width - TOOLTIP_BORDER - status_size,
-				                            current_height);
-				cairo_paint(cr);
-			} else {
-				gdk_cairo_set_source_pixbuf(cr, td->status_icon,
-				                            TOOLTIP_BORDER, current_height);
-				cairo_paint(cr);
-			}
-		}
-
-		if (td->avatar) {
-			if (dir == GTK_TEXT_DIR_RTL) {
-				gdk_cairo_set_source_pixbuf(cr, td->avatar,
-				                            TOOLTIP_BORDER, current_height);
-				cairo_paint(cr);
-			} else {
-				gdk_cairo_set_source_pixbuf(cr, td->avatar,
-				                            max_width - (td->avatar_width + TOOLTIP_BORDER),
-				                            current_height);
-				cairo_paint(cr);
-			}
-		}
-
-		if (!td->avatar_is_protocol_icon && td->protocol_icon) {
-			gdk_cairo_set_source_pixbuf(cr, td->protocol_icon, protocol_col,
-			                            current_height +
-			                               (td->name_height - PROTOCOL_SIZE) / 2);
-			cairo_paint(cr);
-		}
-
-		if (td->name_layout) {
-			if (dir == GTK_TEXT_DIR_RTL) {
-				gtk_render_layout(context, cr,
-				                  max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
-				                  current_height, td->name_layout);
-			} else {
-				gtk_render_layout(context, cr,
-				                  TOOLTIP_BORDER + status_size + SMALL_SPACE,
-				                  current_height, td->name_layout);
-			}
-		}
-
-		if (td->layout) {
-			if (dir != GTK_TEXT_DIR_RTL) {
-				gtk_render_layout(context, cr,
-				                  TOOLTIP_BORDER + status_size + SMALL_SPACE,
-				                  current_height + td->name_height,
-				                  td->layout);
-			} else {
-				gtk_render_layout(context, cr,
-				                  max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
-				                  current_height + td->name_height,
-				                  td->layout);
-			}
-		}
-
-		current_height += MAX(td->name_height + td->height, td->avatar_height) + td->padding;
-	}
-
-	return FALSE;
-}
-
-static void
-tooltip_data_free(struct tooltip_data *td)
-{
-	g_return_if_fail(td != NULL);
-
-	g_clear_object(&td->avatar);
-	g_clear_object(&td->status_icon);
-	g_clear_object(&td->protocol_icon);
-	g_clear_object(&td->layout);
-	g_clear_object(&td->name_layout);
-	g_free(td);
-}
-
-static void
-pidgin_blist_destroy_tooltip_data(void)
-{
-	g_list_free_full(gtkblist->tooltipdata, (GDestroyNotify)tooltip_data_free);
-	gtkblist->tooltipdata = NULL;
-}
-
-void pidgin_blist_tooltip_destroy()
-{
-	pidgin_blist_destroy_tooltip_data();
-	pidgin_tooltip_destroy();
-}
-
-static gboolean
-pidgin_blist_create_tooltip_for_node(GtkWidget *widget, gpointer data, int *w, int *h)
-{
-	PurpleBlistNode *node = data;
-	int width = 0, height = 0;
-	GList *list;
-	int max_text_width = 0;
-	int max_avatar_width = 0;
-	int status_size = 0;
-
-	if (gtkblist->tooltipdata) {
-		gtkblist->tipwindow = NULL;
-		pidgin_blist_destroy_tooltip_data();
-	}
-
-	gtkblist->tipwindow = widget;
-	if (PURPLE_IS_CHAT(node) ||
-	   PURPLE_IS_BUDDY(node)) {
-		struct tooltip_data *td = create_tip_for_node(node, TRUE);
-		gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td);
-	} else if (PURPLE_IS_GROUP(node)) {
-		PurpleGroup *group = (PurpleGroup*)node;
-		GSList *accounts;
-		struct tooltip_data *td = create_tip_for_node(node, TRUE);
-		gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td);
-
-		/* Accounts with buddies in group */
-		accounts = purple_group_get_accounts(group);
-		for (; accounts != NULL;
-		     accounts = g_slist_delete_link(accounts, accounts)) {
-			PurpleAccount *account = accounts->data;
-			td = create_tip_for_account(account);
-			gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td);
-		}
-	} else if (PURPLE_IS_CONTACT(node)) {
-		PurpleBlistNode *child;
-		PurpleBuddy *b = purple_contact_get_priority_buddy((PurpleContact *)node);
-
-		for(child = node->child; child; child = child->next)
-		{
-			if(PURPLE_IS_BUDDY(child) && buddy_is_displayable((PurpleBuddy*)child)) {
-				struct tooltip_data *td = create_tip_for_node(child, (b == (PurpleBuddy*)child));
-				if (b == (PurpleBuddy *)child) {
-					gtkblist->tooltipdata = g_list_prepend(gtkblist->tooltipdata, td);
-				} else {
-					gtkblist->tooltipdata = g_list_append(gtkblist->tooltipdata, td);
-				}
-			}
-		}
-	} else {
-		return FALSE;
-	}
-
-	for (list = gtkblist->tooltipdata; list; list = list->next) {
-		struct tooltip_data *td = list->data;
-		max_text_width = MAX(max_text_width, MAX(td->width, td->name_width));
-		max_avatar_width = MAX(max_avatar_width, td->avatar_width);
-		height += MAX(MAX(STATUS_SIZE, td->avatar_height), td->height + td->name_height) + td->padding;
-		if (td->status_icon)
-			status_size = MAX(status_size, STATUS_SIZE);
-	}
-	height += TOOLTIP_BORDER;
-	width = TOOLTIP_BORDER + status_size + SMALL_SPACE + max_text_width + SMALL_SPACE + max_avatar_width + TOOLTIP_BORDER;
-
-	if (w)
-		*w = width;
-	if (h)
-		*h = height;
-
-	return TRUE;
-}
-
 static gboolean pidgin_blist_expand_timeout(GtkWidget *tv)
 {
 	GtkTreePath *path;
@@ -3136,11 +2760,6 @@ static gboolean buddy_is_displayable(Pur
 			 purple_blist_node_get_bool(PURPLE_BLIST_NODE(buddy), "show_offline")));
 }
 
-void pidgin_blist_draw_tooltip(PurpleBlistNode *node, GtkWidget *widget)
-{
-	pidgin_tooltip_show(widget, node, pidgin_blist_create_tooltip_for_node, pidgin_blist_paint_tip);
-}
-
 static gboolean pidgin_blist_drag_motion_cb(GtkWidget *tv, GdkDragContext *drag_context,
 					      gint x, gint y, guint time, gpointer user_data)
 {
@@ -3221,6 +2840,11 @@ static gboolean pidgin_blist_drag_motion
  *
  *
  */
+#define STATUS_SIZE 16
+#define TOOLTIP_BORDER 12
+#define SMALL_SPACE 6
+#define LARGE_SPACE 12
+
 static void
 add_tip_for_account(GtkWidget *grid, gint row, PurpleAccount *account)
 {
@@ -4503,15 +4127,6 @@ account_status_changed(PurpleAccount *ac
 	account_modified(account, gtkblist);
 }
 
-static gboolean
-gtk_blist_window_key_press_cb(GtkWidget *w, GdkEventKey *event, PidginBuddyList *gtkblist)
-{
-	/* clear any tooltips */
-	pidgin_blist_tooltip_destroy();
-
-	return FALSE;
-}
-
 static void
 reset_headline(PidginBuddyList *gtkblist)
 {
@@ -5270,7 +4885,6 @@ static void pidgin_blist_show(PurpleBudd
 			G_CALLBACK(gtk_blist_size_allocate_cb), NULL);
 	g_signal_connect(G_OBJECT(gtkblist->window), "visibility_notify_event", G_CALLBACK(gtk_blist_visibility_cb), NULL);
 	g_signal_connect(G_OBJECT(gtkblist->window), "window_state_event", G_CALLBACK(gtk_blist_window_state_cb), NULL);
-	g_signal_connect(G_OBJECT(gtkblist->window), "key_press_event", G_CALLBACK(gtk_blist_window_key_press_cb), gtkblist);
 	gtk_widget_add_events(gtkblist->window, GDK_VISIBILITY_NOTIFY_MASK);
 
 	/****************************** Notebook *************************************/
@@ -5377,9 +4991,6 @@ static void pidgin_blist_show(PurpleBudd
 
 	g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-received", G_CALLBACK(pidgin_blist_drag_data_rcv_cb), NULL);
 	g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-data-get", G_CALLBACK(pidgin_blist_drag_data_get_cb), NULL);
-#ifdef _WIN32
-	g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-begin", G_CALLBACK(pidgin_blist_drag_begin), NULL);
-#endif
 	g_signal_connect(G_OBJECT(gtkblist->treeview), "drag-motion", G_CALLBACK(pidgin_blist_drag_motion_cb), NULL);
 	g_signal_connect(G_OBJECT(gtkblist->treeview), "motion-notify-event", G_CALLBACK(pidgin_blist_motion_cb), NULL);
 	g_signal_connect(G_OBJECT(gtkblist->treeview), "leave-notify-event", G_CALLBACK(pidgin_blist_leave_cb), NULL);
@@ -6801,8 +6412,6 @@ pidgin_buddy_list_finalize(GObject *obj)
 
 	gtk_widget_destroy(gtkblist->window);
 
-	pidgin_blist_tooltip_destroy();
-
 	if (gtkblist->refresh_timer) {
 		g_source_remove(gtkblist->refresh_timer);
 		gtkblist->refresh_timer = 0;
diff --git a/pidgin/gtkconv.c b/pidgin/gtkconv.c
--- a/pidgin/gtkconv.c
+++ b/pidgin/gtkconv.c
@@ -64,11 +64,8 @@
 #include "pidginpresenceicon.h"
 #include "pidginstock.h"
 #include "pidginstylecontext.h"
-#include "pidgintooltip.h"
 #include "pidginwindow.h"
 
-#define GTK_TOOLTIPS_VAR gtkconv->tooltips
-
 #define ADD_MESSAGE_HISTORY_AT_ONCE 100
 
 /*
diff --git a/pidgin/gtkroomlist.c b/pidgin/gtkroomlist.c
--- a/pidgin/gtkroomlist.c
+++ b/pidgin/gtkroomlist.c
@@ -30,7 +30,6 @@
 #include "gtkutils.h"
 #include "pidginaccountchooser.h"
 #include "pidginstock.h"
-#include "pidgintooltip.h"
 
 #define PIDGIN_TYPE_ROOMLIST_DIALOG (pidgin_roomlist_dialog_get_type())
 G_DECLARE_FINAL_TYPE(PidginRoomlistDialog, pidgin_roomlist_dialog, PIDGIN,
@@ -734,10 +733,7 @@ static void pidgin_roomlist_set_fields(P
 	g_signal_connect(G_OBJECT(tree), "button-press-event", G_CALLBACK(room_click_cb), list);
 	g_signal_connect(G_OBJECT(tree), "row-expanded", G_CALLBACK(row_expanded_cb), list);
 	g_signal_connect(G_OBJECT(tree), "row-activated", G_CALLBACK(row_activated_cb), list);
-#if 0 /* uncomment this when the tooltips are slightly less annoying and more well behaved */
-	g_signal_connect(G_OBJECT(tree), "motion-notify-event", G_CALLBACK(row_motion_cb), list);
-	g_signal_connect(G_OBJECT(tree), "leave-notify-event", G_CALLBACK(row_leave_cb), list);
-#endif
+
 	gtk_widget_set_has_tooltip(tree, TRUE);
 	g_signal_connect(G_OBJECT(tree), "query-tooltip",
 	                 G_CALLBACK(pidgin_roomlist_query_tooltip), list);
diff --git a/pidgin/meson.build b/pidgin/meson.build
--- a/pidgin/meson.build
+++ b/pidgin/meson.build
@@ -62,7 +62,6 @@ libpidgin_SOURCES = [
 	'pidginscrollbook.c',
 	'pidginstylecontext.c',
 	'pidgintalkatu.c',
-	'pidgintooltip.c',
 	'pidginwindow.c',
 	'prefs/pidginprefs.c',
 	'prefs/pidgincredentialproviderrow.c',
@@ -134,7 +133,6 @@ libpidgin_headers = [
 	'pidginscrollbook.h',
 	'pidginstylecontext.h',
 	'pidgintalkatu.h',
-	'pidgintooltip.h',
 	'pidginwindow.h',
 ]
 
diff --git a/pidgin/pidgintooltip.h b/pidgin/pidgintooltip.h
deleted file mode 100644
--- a/pidgin/pidgintooltip.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/* pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#if !defined(PIDGIN_GLOBAL_HEADER_INSIDE) && !defined(PIDGIN_COMPILATION)
-# error "only <pidgin.h> may be included directly"
-#endif
-
-#ifndef _PIDGIN_TOOLTIP_H_
-#define _PIDGIN_TOOLTIP_H_
-/**
- * SECTION:pidgintooltip
- * @section_id: pidgin-pidgintooltip
- * @short_description: <filename>pidgintooltip.h</filename>
- * @title: Pidgin Tooltip API
- */
-
-#include <gtk/gtk.h>
-
-/**
- * PidginTooltipCreateForTree:
- * @tipwindow:  The window for the tooltip.
- * @path:       The GtkTreePath representing the row under the cursor.
- * @userdata:   The userdata set during pidgin_tooltip_setup_for_treeview.
- * @w:          The value of this should be set to the desired width of the tooltip window.
- * @h:          The value of this should be set to the desired height of the tooltip window.
- *
- * Returns:  %TRUE if the tooltip was created correctly, %FALSE otherwise.
- */
-typedef gboolean (*PidginTooltipCreateForTree)(GtkWidget *tipwindow,
-			GtkTreePath *path, gpointer userdata, int *w, int *h);
-
-/**
- * PidginTooltipCreate:
- * @tipwindow:  The window for the tooltip.
- * @userdata:   The userdata set during pidgin_tooltip_show.
- * @w:          The value of this should be set to the desired width of the tooltip window.
- * @h:          The value of this should be set to the desired height of the tooltip window.
- *
- * Returns:  %TRUE if the tooltip was created correctly, %FALSE otherwise.
- */
-typedef gboolean (*PidginTooltipCreate)(GtkWidget *tipwindow,
-			gpointer userdata, int *w, int *h);
-
-/**
- * PidginTooltipPaint:
- * @tipwindow:   The window for the tooltip.
- * @cr:          The cairo context for drawing.
- * @userdata:    The userdata set during pidgin_tooltip_setup_for_treeview or pidgin_tooltip_show.
- *
- * Returns:  %TRUE if the tooltip was painted correctly, %FALSE otherwise.
- */
-typedef gboolean (*PidginTooltipPaint)(GtkWidget *tipwindow, cairo_t *cr,
-			gpointer userdata);
-
-G_BEGIN_DECLS
-
-/**
- * pidgin_tooltip_setup_for_treeview:
- * @tree: The treeview
- * @userdata: The userdata to send to the callback functions
- * @create_cb: (scope call): Callback function to create the tooltip for a GtkTreePath
- * @paint_cb: (scope call): Callback function to paint the tooltip
- *
- * Setup tooltip drawing functions for a treeview.
- *
- * Returns:   %TRUE if the tooltip callbacks were setup correctly.
- */
-gboolean pidgin_tooltip_setup_for_treeview(GtkWidget *tree, gpointer userdata,
-		PidginTooltipCreateForTree create_cb, PidginTooltipPaint paint_cb);
-
-/**
- * pidgin_tooltip_destroy:
- *
- * Destroy the tooltip.
- */
-void pidgin_tooltip_destroy(void);
-
-/**
- * pidgin_tooltip_show:
- * @widget:      The widget the tooltip is for
- * @userdata:    The userdata to send to the callback functions
- * @create_cb: (scope call): Callback function to create the tooltip from the GtkTreePath
- * @paint_cb: (scope call): Callback function to paint the tooltip
- *
- * Create and show a tooltip.
- */
-void pidgin_tooltip_show(GtkWidget *widget, gpointer userdata,
-		PidginTooltipCreate create_cb, PidginTooltipPaint paint_cb);
-
-G_END_DECLS
-
-#endif
diff --git a/pidgin/pidgintooltip.c b/pidgin/pidgintooltip.c
deleted file mode 100644
--- a/pidgin/pidgintooltip.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/* pidgin
- *
- * Pidgin is the legal property of its developers, whose names are too numerous
- * to list here.  Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
- */
-
-#include <glib/gi18n-lib.h>
-
-#include <purple.h>
-
-#include "pidgintooltip.h"
-
-static gboolean enable_tooltips;
-static int tooltip_delay = -1;
-
-struct
-{
-	GtkWidget *widget;
-	int timeout;
-	GdkRectangle tip_rect;
-	GtkWidget *tipwindow;
-	PidginTooltipPaint paint_tooltip;
-} pidgin_tooltip;
-
-typedef struct
-{
-	GtkWidget *widget;
-	gpointer userdata;
-	PidginTooltipPaint paint_tooltip;
-	PidginTooltipCreateForTree create_tooltip;
-	GtkTreePath *path;
-} PidginTooltipData;
-
-static void
-initialize_tooltip_delay()
-{
-	GtkSettings *settings;
-
-	if (tooltip_delay != -1)
-		return;
-
-	settings = gtk_settings_get_default();
-
-	g_object_get(settings, "gtk-enable-tooltips", &enable_tooltips, NULL);
-	g_object_get(settings, "gtk-tooltip-timeout", &tooltip_delay, NULL);
-}
-
-static void
-destroy_tooltip_data(PidginTooltipData *data)
-{
-	if (data->path) {
-		gtk_tree_path_free(data->path);
-	}
-	pidgin_tooltip_destroy();
-	g_free(data);
-}
-
-void pidgin_tooltip_destroy()
-{
-	if (pidgin_tooltip.timeout > 0) {
-		g_source_remove(pidgin_tooltip.timeout);
-		pidgin_tooltip.timeout = 0;
-	}
-	if (pidgin_tooltip.tipwindow) {
-		gtk_widget_destroy(pidgin_tooltip.tipwindow);
-		pidgin_tooltip.tipwindow = NULL;
-	}
-}
-
-static gboolean
-pidgin_tooltip_draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data)
-{
-	GtkAllocation allocation;
-
-	gtk_widget_get_allocation(widget, &allocation);
-
-	if (pidgin_tooltip.paint_tooltip) {
-		GtkStyleContext *context = gtk_widget_get_style_context(widget);
-		gtk_style_context_add_class(context, GTK_STYLE_CLASS_TOOLTIP);
-		gtk_render_background(context, cr,
-		                      0, 0, allocation.width, allocation.height);
-		pidgin_tooltip.paint_tooltip(widget, cr, data);
-	}
-	return FALSE;
-}
-
-static GtkWidget*
-setup_tooltip_window(void)
-{
-	const char *name;
-	GtkWidget *tipwindow;
-
-	tipwindow = gtk_window_new(GTK_WINDOW_POPUP);
-	gtk_window_set_transient_for(GTK_WINDOW(tipwindow),
-	                             GTK_WINDOW(pidgin_tooltip.widget));
-	name = gtk_window_get_title(GTK_WINDOW(pidgin_tooltip.widget));
-	gtk_window_set_type_hint(GTK_WINDOW(tipwindow), GDK_WINDOW_TYPE_HINT_TOOLTIP);
-	gtk_widget_set_app_paintable(tipwindow, TRUE);
-	gtk_window_set_title(GTK_WINDOW(tipwindow), name ? name : _("Pidgin Tooltip"));
-	gtk_window_set_resizable(GTK_WINDOW(tipwindow), FALSE);
-	gtk_widget_set_name(tipwindow, "gtk-tooltips");
-	gtk_widget_ensure_style(tipwindow);
-	gtk_widget_realize(tipwindow);
-	return tipwindow;
-}
-
-static void
-setup_tooltip_window_position(gpointer data, int w, int h)
-{
-	int scr_w, scr_h, x, y, dy;
-	int preserved_x, preserved_y;
-	GdkDisplay *display = NULL;
-	GdkSeat *seat = NULL;
-	GdkMonitor *monitor = NULL;
-	GdkDevice *dev = NULL;
-	GdkRectangle mon_size;
-	GtkWidget *tipwindow = pidgin_tooltip.tipwindow;
-
-	display = gdk_display_get_default();
-	seat = gdk_display_get_default_seat(display);
-	dev = gdk_seat_get_pointer(seat);
-	gdk_device_get_position(dev, NULL, &x, &y);
-
-	monitor = gdk_display_get_monitor_at_point(display, x, y);
-	gdk_monitor_get_geometry(monitor, &mon_size);
-
-	scr_w = mon_size.width + mon_size.x;
-	scr_h = mon_size.height + mon_size.y;
-
-	dy = gdk_display_get_default_cursor_size(gdk_display_get_default()) / 2;
-
-	if (w > mon_size.width)
-		w = mon_size.width - 10;
-
-	if (h > mon_size.height)
-		h = mon_size.height - 10;
-
-	preserved_x = x;
-	preserved_y = y;
-
-	x -= ((w >> 1) + 4);
-
-	if ((y + h + 4) > scr_h)
-		y = y - h - dy - 5;
-	else
-		y = y + dy + 6;
-
-	if (y < mon_size.y)
-		y = mon_size.y;
-
-	if (y != mon_size.y) {
-		if ((x + w) > scr_w)
-			x -= (x + w + 5) - scr_w;
-		else if (x < mon_size.x)
-			x = mon_size.x;
-	} else {
-		x -= (w / 2 + 10);
-		if (x < mon_size.x)
-			x = mon_size.x;
-	}
-
-	/* If the mouse covered by the tipwindow, move the tipwindow
-	 * to the righ side of the it */
-	if ((preserved_x >= x) && (preserved_x <= (x + w))
-			&& (preserved_y >= y) && (preserved_y <= (y + h)))
-		x = preserved_x + dy;
-
-	gtk_widget_set_size_request(tipwindow, w, h);
-	gtk_window_move(GTK_WINDOW(tipwindow), x, y);
-	gtk_widget_show(tipwindow);
-
-	g_signal_connect(G_OBJECT(tipwindow), "draw",
-			G_CALLBACK(pidgin_tooltip_draw_cb), data);
-
-	/* Hide the tooltip when the widget is destroyed */
-	g_signal_connect_object(G_OBJECT(pidgin_tooltip.widget),
-			"destroy", G_CALLBACK(pidgin_tooltip_destroy),
-			G_OBJECT(tipwindow), 0);
-}
-
-void pidgin_tooltip_show(GtkWidget *widget, gpointer userdata,
-		PidginTooltipCreate create_tooltip, PidginTooltipPaint paint_tooltip)
-{
-	GtkWidget *tipwindow;
-	int w, h;
-
-	pidgin_tooltip_destroy();
-
-	pidgin_tooltip.widget = gtk_widget_get_toplevel(widget);
-	pidgin_tooltip.tipwindow = tipwindow = setup_tooltip_window();
-	pidgin_tooltip.paint_tooltip = paint_tooltip;
-
-	if (!create_tooltip(tipwindow, userdata, &w, &h)) {
-		pidgin_tooltip_destroy();
-		return;
-	}
-	setup_tooltip_window_position(userdata, w, h);
-}
-
-static void
-reset_data_treepath(PidginTooltipData *data)
-{
-	gtk_tree_path_free(data->path);
-	data->path = NULL;
-}
-
-static gboolean
-pidgin_tooltip_timeout(gpointer userdata)
-{
-	PidginTooltipData *data = (PidginTooltipData *)userdata;
-	GtkWidget *tipwindow;
-	GtkTreePath *path = NULL;
-	int w, h;
-
-	pidgin_tooltip.timeout = 0;
-
-	if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(data->widget),
-				pidgin_tooltip.tip_rect.x,
-				pidgin_tooltip.tip_rect.y + (pidgin_tooltip.tip_rect.height/2),
-				&path, NULL, NULL, NULL)) {
-		pidgin_tooltip_destroy();
-		return FALSE;
-	}
-
-	if (data->path) {
-		if (gtk_tree_path_compare(data->path, path) == 0) {
-			gtk_tree_path_free(path);
-			return FALSE;
-		}
-		gtk_tree_path_free(data->path);
-		data->path = NULL;
-	}
-
-	pidgin_tooltip_destroy();
-
-	pidgin_tooltip.widget = gtk_widget_get_toplevel(data->widget);
-	pidgin_tooltip.tipwindow = tipwindow = setup_tooltip_window();
-	pidgin_tooltip.paint_tooltip = data->paint_tooltip;
-
-	if (!data->create_tooltip(tipwindow, path, data->userdata, &w, &h)) {
-		if (tipwindow == pidgin_tooltip.tipwindow)
-			pidgin_tooltip_destroy();
-		gtk_tree_path_free(path);
-		return FALSE;
-	}
-
-	setup_tooltip_window_position(data->userdata, w, h);
-
-	data->path = path;
-	g_signal_connect_swapped(G_OBJECT(pidgin_tooltip.tipwindow), "destroy",
-			G_CALLBACK(reset_data_treepath), data);
-
-	return FALSE;
-}
-
-static gboolean
-row_motion_cb(GtkWidget *tv, GdkEventMotion *event, gpointer userdata)
-{
-	GtkTreePath *path;
-
-	if (event->window != gtk_tree_view_get_bin_window(GTK_TREE_VIEW(tv)))
-		return FALSE;    /* The cursor is probably on the TreeView's header. */
-
-	initialize_tooltip_delay();
-	if (!enable_tooltips)
-		return FALSE;
-
-	if (pidgin_tooltip.timeout) {
-		if ((event->y >= pidgin_tooltip.tip_rect.y) && ((event->y - pidgin_tooltip.tip_rect.height) <= pidgin_tooltip.tip_rect.y))
-			return FALSE;
-		/* We've left the cell.  Remove the timeout and create a new one below */
-		pidgin_tooltip_destroy();
-	}
-
-	gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), event->x, event->y, &path, NULL, NULL, NULL);
-
-	if (path == NULL) {
-		pidgin_tooltip_destroy();
-		return FALSE;
-	}
-
-	gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, &pidgin_tooltip.tip_rect);
-	gtk_tree_path_free(path);
-
-	pidgin_tooltip.timeout = g_timeout_add(tooltip_delay, (GSourceFunc)pidgin_tooltip_timeout, userdata);
-
-	return FALSE;
-}
-
-static gboolean
-widget_leave_cb(GtkWidget *tv, GdkEvent *event, gpointer userdata)
-{
-	pidgin_tooltip_destroy();
-	return FALSE;
-}
-
-gboolean pidgin_tooltip_setup_for_treeview(GtkWidget *tree, gpointer userdata,
-		PidginTooltipCreateForTree create_tooltip, PidginTooltipPaint paint_tooltip)
-{
-	PidginTooltipData *tdata = g_new0(PidginTooltipData, 1);
-	tdata->widget = tree;
-	tdata->userdata = userdata;
-	tdata->create_tooltip = create_tooltip;
-	tdata->paint_tooltip = paint_tooltip;
-
-	g_signal_connect(G_OBJECT(tree), "motion-notify-event", G_CALLBACK(row_motion_cb), tdata);
-	g_signal_connect(G_OBJECT(tree), "leave-notify-event", G_CALLBACK(widget_leave_cb), NULL);
-	g_signal_connect(G_OBJECT(tree), "scroll-event", G_CALLBACK(widget_leave_cb), NULL);
-	g_signal_connect_swapped(G_OBJECT(tree), "destroy", G_CALLBACK(destroy_tooltip_data), tdata);
-	return TRUE;
-}
diff --git a/po/POTFILES.in b/po/POTFILES.in
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -374,7 +374,6 @@ pidgin/pidginscrollbook.c
 pidgin/pidginstock.c
 pidgin/pidginstylecontext.c
 pidgin/pidgintalkatu.c
-pidgin/pidgintooltip.c
 pidgin/pidginwindow.c
 pidgin/plugins/disco/gtkdisco.c
 pidgin/plugins/disco/resources/disco.ui
