Merge fix for lost focus bug soc.2012.gg
authorTomasz Wasilczyk <tomkiewicz@cpw.pidgin.im>
Fri, 17 Aug 2012 17:22:23 +0200
branchsoc.2012.gg
changeset481258ec30de pushlog
parent 5f00ed891179
parent e3155594ea98
child 26ba5e4e8c24
Merge fix for lost focus bug
libpurple/protocols/gg/gg.c
     1.1 --- a/COPYRIGHT
     1.2 +++ b/COPYRIGHT
     1.3 @@ -342,6 +342,7 @@
     1.4  Robert McQueen
     1.5  Mihály Mészáros
     1.6  Robert Mibus
     1.7 +David Michael
     1.8  Lars T. Mikkelsen
     1.9  Benjamin Miller
    1.10  Kevin Miller
     2.1 --- a/ChangeLog
     2.2 +++ b/ChangeLog
     2.3 @@ -49,8 +49,6 @@
     2.4  	* Invalid user moods can no longer be sent to the server.
     2.5  
     2.6  	Plugins:
     2.7 -	* The Voice/Video Settings plugin supports using the sndio GStreamer
     2.8 -	  backends. (Brad Smith) (#14414)
     2.9  	* The Offline Message Emulation plugin now adds a note that the message
    2.10  	  was an offline message. (Flavius Anton) (#2497)
    2.11  
    2.12 @@ -59,6 +57,10 @@
    2.13  	* Fix a crash at startup with large contact list. Avatar support for
    2.14  	  buddies will be disabled till 3.0.0. (#15226, #14305)
    2.15  
    2.16 +	Gadu-Gadu:
    2.17 +	* Fix a crash at startup with large contact list. Avatar support for
    2.18 +	  buddies will be disabled till 3.0.0. (#15226, #14305)
    2.19 +
    2.20  	MSN:
    2.21  	* Fix a crash when removing a user before its icon is loaded. (Mark
    2.22  	  Barfield) (#15217)
    2.23 @@ -67,6 +69,10 @@
    2.24  	* Fix a double-free in profile/picture loading code. (Mihai Serban)
    2.25  	  (#15053)
    2.26  
    2.27 +	Plugins:
    2.28 +	* The Voice/Video Settings plugin supports using the sndio GStreamer
    2.29 +	 backends. (Brad Smith) (#14414)
    2.30 +
    2.31  version 2.10.6 (07/06/2012):
    2.32  	Pidgin:
    2.33  	* Fix a bug that requires a triple-click to open a conversation
     3.1 --- a/libpurple/media/enum-types.h
     3.2 +++ b/libpurple/media/enum-types.h
     3.3 @@ -44,7 +44,7 @@
     3.4  	PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX,
     3.5  	PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX,
     3.6  	PURPLE_MEDIA_CANDIDATE_TYPE_RELAY,
     3.7 -	PURPLE_MEDIA_CANDIDATE_TYPE_MULTICAST,
     3.8 +	PURPLE_MEDIA_CANDIDATE_TYPE_MULTICAST
     3.9  } PurpleMediaCandidateType;
    3.10  
    3.11  /** Media caps */
    3.12 @@ -56,14 +56,14 @@
    3.13  	PURPLE_MEDIA_CAPS_VIDEO_SINGLE_DIRECTION = 1 << 3,
    3.14  	PURPLE_MEDIA_CAPS_AUDIO_VIDEO = 1 << 4,
    3.15  	PURPLE_MEDIA_CAPS_MODIFY_SESSION = 1 << 5,
    3.16 -	PURPLE_MEDIA_CAPS_CHANGE_DIRECTION = 1 << 6,
    3.17 +	PURPLE_MEDIA_CAPS_CHANGE_DIRECTION = 1 << 6
    3.18  } PurpleMediaCaps;
    3.19  
    3.20  /** Media component types */
    3.21  typedef enum {
    3.22  	PURPLE_MEDIA_COMPONENT_NONE = 0,
    3.23  	PURPLE_MEDIA_COMPONENT_RTP = 1,
    3.24 -	PURPLE_MEDIA_COMPONENT_RTCP = 2,
    3.25 +	PURPLE_MEDIA_COMPONENT_RTCP = 2
    3.26  } PurpleMediaComponentType;
    3.27  
    3.28  /** Media info types */
    3.29 @@ -76,13 +76,13 @@
    3.30  	PURPLE_MEDIA_INFO_PAUSE,
    3.31  	PURPLE_MEDIA_INFO_UNPAUSE,
    3.32  	PURPLE_MEDIA_INFO_HOLD,
    3.33 -	PURPLE_MEDIA_INFO_UNHOLD,
    3.34 +	PURPLE_MEDIA_INFO_UNHOLD
    3.35  } PurpleMediaInfoType;
    3.36  
    3.37  /** Media network protocols */
    3.38  typedef enum {
    3.39  	PURPLE_MEDIA_NETWORK_PROTOCOL_UDP,
    3.40 -	PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
    3.41 +	PURPLE_MEDIA_NETWORK_PROTOCOL_TCP
    3.42  } PurpleMediaNetworkProtocol;
    3.43  
    3.44  /** Media session types */
    3.45 @@ -100,7 +100,7 @@
    3.46  typedef enum {
    3.47  	PURPLE_MEDIA_STATE_NEW = 0,
    3.48  	PURPLE_MEDIA_STATE_CONNECTED,
    3.49 -	PURPLE_MEDIA_STATE_END,
    3.50 +	PURPLE_MEDIA_STATE_END
    3.51  } PurpleMediaState;
    3.52  
    3.53  /**
     4.1 --- a/pidgin/gtk3compat.h
     4.2 +++ b/pidgin/gtk3compat.h
     4.3 @@ -25,9 +25,17 @@
     4.4   * Also, any public API should not depend on this file.
     4.5   */
     4.6  
     4.7 +#if !GTK_CHECK_VERSION(3,2,0)
     4.8 +
     4.9 +#define GTK_FONT_CHOOSER GTK_FONT_SELECTION_DIALOG
    4.10 +#define gtk_font_chooser_dialog_new(x,y) gtk_font_selection_dialog_new(x)
    4.11 +#define gtk_font_chooser_get_font gtk_font_selection_dialog_get_font_name
    4.12 +#define gtk_font_chooser_set_font gtk_font_selection_dialog_set_font_name
    4.13 +
    4.14  #if !GTK_CHECK_VERSION(3,0,0)
    4.15  
    4.16  #define gdk_x11_window_get_xid GDK_WINDOW_XWINDOW
    4.17 +#define gtk_widget_get_preferred_size(x,y,z) gtk_widget_size_request(x,z)
    4.18  
    4.19  #if !GTK_CHECK_VERSION(2,24,0)
    4.20  
    4.21 @@ -36,6 +44,7 @@
    4.22  #define GtkComboBoxText GtkComboBox
    4.23  #define GTK_COMBO_BOX_TEXT GTK_COMBO_BOX
    4.24  #define gtk_combo_box_text_new gtk_combo_box_new_text
    4.25 +#define gtk_combo_box_text_new_with_entry gtk_combo_box_entry_new_text
    4.26  #define gtk_combo_box_text_append_text gtk_combo_box_append_text
    4.27  #define gtk_combo_box_text_get_active_text gtk_combo_box_get_active_text
    4.28  #define gtk_combo_box_text_remove gtk_combo_box_remove_text
    4.29 @@ -168,5 +177,7 @@
    4.30  
    4.31  #endif /* 3.0.0 */
    4.32  
    4.33 +#endif /* 3.2.0 */
    4.34 +
    4.35  #endif /* _PIDGINGTK3COMPAT_H_ */
    4.36  
     5.1 --- a/pidgin/gtkaccount.c
     5.2 +++ b/pidgin/gtkaccount.c
     5.3 @@ -917,12 +917,13 @@
     5.4  				if (str_hints)
     5.5  				{
     5.6  					const GSList *hint_it = str_hints;
     5.7 -					entry = gtk_combo_box_entry_new_text();
     5.8 +					entry = gtk_combo_box_text_new_with_entry();
     5.9  					while (hint_it)
    5.10  					{
    5.11  						const gchar *hint = hint_it->data;
    5.12 -						hint_it = g_list_next(hint_it);
    5.13 -						gtk_combo_box_append_text(GTK_COMBO_BOX(entry), hint);
    5.14 +						hint_it = g_slist_next(hint_it);
    5.15 +						gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(entry),
    5.16 +						                               hint);
    5.17  					}
    5.18  				}
    5.19  				else
    5.20 @@ -941,7 +942,8 @@
    5.21  				}
    5.22  
    5.23  				if (str_value != NULL && str_hints)
    5.24 -					gtk_entry_set_text(GTK_ENTRY(GTK_BIN(entry)->child), str_value);
    5.25 +					gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(entry))),
    5.26 +					                   str_value);
    5.27  				else
    5.28  					gtk_entry_set_text(GTK_ENTRY(entry), str_value);
    5.29  
    5.30 @@ -1474,7 +1476,7 @@
    5.31  			switch (opt_entry->type) {
    5.32  				case PURPLE_PREF_STRING:
    5.33  					if (GTK_IS_COMBO_BOX(opt_entry->widget))
    5.34 -						value = gtk_combo_box_get_active_text(GTK_COMBO_BOX(opt_entry->widget));
    5.35 +						value = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(opt_entry->widget));
    5.36  					else
    5.37  						value = gtk_entry_get_text(GTK_ENTRY(opt_entry->widget));
    5.38  					purple_account_set_string(account, opt_entry->setting, value);
     6.1 --- a/pidgin/gtkblist.c
     6.2 +++ b/pidgin/gtkblist.c
     6.3 @@ -2965,7 +2965,11 @@
     6.4  static gboolean
     6.5  pidgin_blist_paint_tip(GtkWidget *widget, cairo_t *cr, gpointer null)
     6.6  {
     6.7 +#if GTK_CHECK_VERSION(3,0,0)
     6.8 +	GtkStyleContext *context;
     6.9 +#else
    6.10  	GtkStyle *style;
    6.11 +#endif
    6.12  	int current_height, max_width;
    6.13  	int max_text_width;
    6.14  	int max_avatar_width;
    6.15 @@ -2977,7 +2981,12 @@
    6.16  	if(gtkblist->tooltipdata == NULL)
    6.17  		return FALSE;
    6.18  
    6.19 +#if GTK_CHECK_VERSION(3,0,0)
    6.20 +	context = gtk_widget_get_style_context(gtkblist->tipwindow);
    6.21 +	gtk_style_context_add_class(context, GTK_STYLE_CLASS_TOOLTIP);
    6.22 +#else
    6.23  	style = gtk_widget_get_style(gtkblist->tipwindow);
    6.24 +#endif
    6.25  
    6.26  	max_text_width = 0;
    6.27  	max_avatar_width = 0;
    6.28 @@ -3007,27 +3016,34 @@
    6.29  		if (td->avatar && pidgin_gdk_pixbuf_is_opaque(td->avatar))
    6.30  		{
    6.31  #if GTK_CHECK_VERSION(3,0,0)
    6.32 -			if (dir == GTK_TEXT_DIR_RTL)
    6.33 -				gtk_paint_flat_box(style, cr, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
    6.34 -				                   gtkblist->tipwindow, "tooltip",
    6.35 +			gtk_style_context_save(context);
    6.36 +			gtk_style_context_add_class(context, GTK_STYLE_CLASS_FRAME);
    6.37 +			if (dir == GTK_TEXT_DIR_RTL) {
    6.38 +				gtk_render_frame(context, cr,
    6.39 +				                 TOOLTIP_BORDER - 1, current_height - 1,
    6.40 +				                 td->avatar_width + 2, td->avatar_height + 2);
    6.41 +			} else {
    6.42 +				gtk_render_frame(context, cr,
    6.43 +				                 max_width - (td->avatar_width + TOOLTIP_BORDER) - 1,
    6.44 +				                 current_height - 1,
    6.45 +				                 td->avatar_width + 2, td->avatar_height + 2);
    6.46 +			}
    6.47 +			gtk_style_context_restore(context);
    6.48 +#else
    6.49 +			if (dir == GTK_TEXT_DIR_RTL) {
    6.50 +				gtk_paint_flat_box(style, gtkblist->tipwindow->window,
    6.51 +				                   GTK_STATE_NORMAL, GTK_SHADOW_OUT,
    6.52 +				                   NULL, gtkblist->tipwindow, "tooltip",
    6.53  				                   TOOLTIP_BORDER - 1, current_height - 1,
    6.54  				                   td->avatar_width + 2, td->avatar_height + 2);
    6.55 -			else
    6.56 -				gtk_paint_flat_box(style, cr, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
    6.57 -				                   gtkblist->tipwindow, "tooltip",
    6.58 +			} else {
    6.59 +				gtk_paint_flat_box(style, gtkblist->tipwindow->window,
    6.60 +				                   GTK_STATE_NORMAL, GTK_SHADOW_OUT,
    6.61 +				                   NULL, gtkblist->tipwindow, "tooltip",
    6.62  				                   max_width - (td->avatar_width + TOOLTIP_BORDER) - 1,
    6.63 -				                   current_height - 1,
    6.64 -				                   td->avatar_width + 2, td->avatar_height + 2);
    6.65 -#else
    6.66 -			if (dir == GTK_TEXT_DIR_RTL)
    6.67 -				gtk_paint_flat_box(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
    6.68 -				                   NULL, gtkblist->tipwindow, "tooltip",
    6.69 -				                   TOOLTIP_BORDER -1, current_height -1, td->avatar_width +2, td->avatar_height + 2);
    6.70 -			else
    6.71 -				gtk_paint_flat_box(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
    6.72 -				                   NULL, gtkblist->tipwindow, "tooltip",
    6.73 -				                   max_width - (td->avatar_width+ TOOLTIP_BORDER)-1,
    6.74 -				                   current_height-1,td->avatar_width+2, td->avatar_height+2);
    6.75 +				                   current_height - 1, td->avatar_width + 2,
    6.76 +				                   td->avatar_height + 2);
    6.77 +			}
    6.78  #endif
    6.79  		}
    6.80  
    6.81 @@ -3067,14 +3083,13 @@
    6.82  		if (td->name_layout) {
    6.83  #if GTK_CHECK_VERSION(3,0,0)
    6.84  			if (dir == GTK_TEXT_DIR_RTL) {
    6.85 -				gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
    6.86 -				                 gtkblist->tipwindow, "tooltip",
    6.87 -				                 max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
    6.88 -				                 current_height, td->name_layout);
    6.89 +				gtk_render_layout(context, cr,
    6.90 +				                  max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
    6.91 +				                  current_height, td->name_layout);
    6.92  			} else {
    6.93 -				gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
    6.94 -				                 gtkblist->tipwindow, "tooltip",
    6.95 -				                 TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height, td->name_layout);
    6.96 +				gtk_render_layout(context, cr,
    6.97 +				                  TOOLTIP_BORDER + status_size + SMALL_SPACE,
    6.98 +				                  current_height, td->name_layout);
    6.99  			}
   6.100  #else
   6.101  			if (dir == GTK_TEXT_DIR_RTL) {
   6.102 @@ -3093,21 +3108,22 @@
   6.103  		if (td->layout) {
   6.104  #if GTK_CHECK_VERSION(3,0,0)
   6.105  			if (dir != GTK_TEXT_DIR_RTL) {
   6.106 -				gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
   6.107 -				                 gtkblist->tipwindow, "tooltip",
   6.108 -				                 TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height + td->name_height, td->layout);
   6.109 +				gtk_render_layout(context, cr,
   6.110 +				                  TOOLTIP_BORDER + status_size + SMALL_SPACE,
   6.111 +				                  current_height + td->name_height,
   6.112 +				                  td->layout);
   6.113  			} else {
   6.114 -				gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
   6.115 -				                 gtkblist->tipwindow, "tooltip",
   6.116 -				                 max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
   6.117 -				                 current_height + td->name_height,
   6.118 -				                 td->layout);
   6.119 +				gtk_render_layout(context, cr,
   6.120 +				                  max_width - (TOOLTIP_BORDER + status_size + SMALL_SPACE) - PANGO_PIXELS(300000),
   6.121 +				                  current_height + td->name_height,
   6.122 +				                  td->layout);
   6.123  			}
   6.124  #else
   6.125  			if (dir != GTK_TEXT_DIR_RTL) {
   6.126  				gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
   6.127  				                 NULL, gtkblist->tipwindow, "tooltip",
   6.128 -				                 TOOLTIP_BORDER + status_size + SMALL_SPACE, current_height + td->name_height, td->layout);
   6.129 +				                 TOOLTIP_BORDER + status_size + SMALL_SPACE,
   6.130 +				                 current_height + td->name_height, td->layout);
   6.131  			} else {
   6.132  				gtk_paint_layout(style, gtkblist->tipwindow->window, GTK_STATE_NORMAL, FALSE,
   6.133  				                 NULL, gtkblist->tipwindow, "tooltip",
     7.1 --- a/pidgin/gtkcellrendererexpander.c
     7.2 +++ b/pidgin/gtkcellrendererexpander.c
     7.3 @@ -271,6 +271,9 @@
     7.4  	gint ypad;
     7.5  	gboolean is_expanded;
     7.6  	GtkAllocation allocation;
     7.7 +#if GTK_CHECK_VERSION(3,0,0)
     7.8 +	GtkStyleContext *context;
     7.9 +#endif
    7.10  
    7.11  	if (!cellexpander->is_expander)
    7.12  		return;
    7.13 @@ -294,12 +297,18 @@
    7.14  	height -= ypad*2;
    7.15  
    7.16  #if GTK_CHECK_VERSION(3,0,0)
    7.17 -	gtk_paint_expander(gtk_widget_get_style(widget),
    7.18 -	                   cr, state,
    7.19 -	                   widget, "treeview",
    7.20 -	                   cell_area->x + xpad + (width / 2),
    7.21 -	                   cell_area->y + ypad + (height / 2),
    7.22 -	                   is_expanded ? GTK_EXPANDER_EXPANDED : GTK_EXPANDER_COLLAPSED);
    7.23 +	if (is_expanded)
    7.24 +		state |= GTK_STATE_ACTIVE;
    7.25 +	else
    7.26 +		state &= ~GTK_STATE_ACTIVE;
    7.27 +
    7.28 +	context = gtk_widget_get_style_context(widget);
    7.29 +	gtk_style_context_add_class(context, GTK_STYLE_CLASS_VIEW);
    7.30 +	gtk_style_context_add_class(context, GTK_STYLE_CLASS_EXPANDER);
    7.31 +	gtk_style_context_set_state(context, state);
    7.32 +	gtk_render_expander(context, cr,
    7.33 +	                    cell_area->x + xpad, cell_area->y + ypad,
    7.34 +	                    width, height);
    7.35  #else
    7.36  	gtk_paint_expander(gtk_widget_get_style(widget),
    7.37  	                   window, state,
    7.38 @@ -315,7 +324,7 @@
    7.39  
    7.40  #if GTK_CHECK_VERSION(3,0,0)
    7.41  	if (is_expanded && !set)
    7.42 -		gtk_paint_hline(gtk_widget_get_style(widget), cr, state, widget, NULL, 0,
    7.43 +		gtk_render_line(context, cr, 0, cell_area->y + cell_area->height,
    7.44  		                allocation.width, cell_area->y + cell_area->height);
    7.45  #else
    7.46  	if (is_expanded && !set)
     8.1 --- a/pidgin/gtkconv.c
     8.2 +++ b/pidgin/gtkconv.c
     8.3 @@ -171,6 +171,8 @@
     8.4  	{"application/x-im-contact", 0, PIDGIN_DRAG_IM_CONTACT}
     8.5  };
     8.6  
     8.7 +static GtkTargetList *webkit_dnd_targets = NULL;
     8.8 +
     8.9  typedef struct {
    8.10  	GtkWidget *window;
    8.11  
    8.12 @@ -337,7 +339,11 @@
    8.13  conversation_entry_clear(PidginConversation *gtkconv)
    8.14  {
    8.15  	GtkWebView *webview = GTK_WEBVIEW(gtkconv->entry);
    8.16 -	gtk_webview_load_html_string(webview, "");
    8.17 +
    8.18 +	//XXX: hotfix for not focused entry after sending a message
    8.19 +	//gtk_webview_load_html_string(webview, "");
    8.20 +	gtk_webview_load_html_string_with_selection(webview, "<div id='caret'></div>");
    8.21 +
    8.22  #if 0
    8.23  	/* TODO WebKit */
    8.24  	gtk_source_undo_manager_begin_not_undoable_action(webview->undo_manager);
    8.25 @@ -704,6 +710,7 @@
    8.26  
    8.27  	conversation_entry_clear(gtkconv);
    8.28  	gtkconv_set_unseen(gtkconv, PIDGIN_UNSEEN_NONE);
    8.29 +	gtk_widget_grab_focus(gtkconv->entry); // XXX: doesn't work
    8.30  }
    8.31  
    8.32  static void
    8.33 @@ -1618,38 +1625,49 @@
    8.34  	gtk_widget_grab_focus(PIDGIN_CONVERSATION(conv)->entry);
    8.35  }
    8.36  
    8.37 -static GtkTextMark *
    8.38 +static char *
    8.39 +get_class_for_user(const char *who)
    8.40 +{
    8.41 +	return g_strconcat("-pidgin-user:", who, NULL);
    8.42 +}
    8.43 +
    8.44 +static WebKitDOMNode *
    8.45  get_mark_for_user(PidginConversation *gtkconv, const char *who)
    8.46  {
    8.47 -#if 0
    8.48 -	/* TODO WebKit */
    8.49 -	GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtkconv->webview));
    8.50 -	char *tmp = g_strconcat("user:", who, NULL);
    8.51 -	GtkTextMark *mark = gtk_text_buffer_get_mark(buf, tmp);
    8.52 -
    8.53 +	WebKitDOMDocument *doc;
    8.54 +	WebKitDOMNodeList *nodes;
    8.55 +	WebKitDOMNode *node = NULL;
    8.56 +	gulong len;
    8.57 +	char *tmp;
    8.58 +
    8.59 +	doc = webkit_web_view_get_dom_document(WEBKIT_WEB_VIEW(gtkconv->webview));
    8.60 +
    8.61 +	tmp = get_class_for_user(who);
    8.62 +	nodes = webkit_dom_document_get_elements_by_class_name(doc, tmp);
    8.63  	g_free(tmp);
    8.64 -	return mark;
    8.65 -#else
    8.66 -	return NULL;
    8.67 -#endif
    8.68 +
    8.69 +	if (nodes != NULL) {
    8.70 +		len = webkit_dom_node_list_get_length(nodes);
    8.71 +		if (len > 0)
    8.72 +			node = webkit_dom_node_list_item(nodes, len - 1);
    8.73 +	}
    8.74 +
    8.75 +	return node;
    8.76  }
    8.77  
    8.78  static void
    8.79  menu_last_said_cb(GtkWidget *w, PidginConversation *gtkconv)
    8.80  {
    8.81 -/* TODO WEBKIT: This doesn't work yet, of course... */
    8.82 -#if 0
    8.83 -	GtkTextMark *mark;
    8.84 +	WebKitDOMNode *node;
    8.85  	const char *who;
    8.86  
    8.87  	who = g_object_get_data(G_OBJECT(w), "user_data");
    8.88 -	mark = get_mark_for_user(gtkconv, who);
    8.89 -
    8.90 -	if (mark != NULL)
    8.91 -		gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0);
    8.92 +	node = get_mark_for_user(gtkconv, who);
    8.93 +
    8.94 +	if (node != NULL)
    8.95 +		webkit_dom_element_scroll_into_view(WEBKIT_DOM_ELEMENT(node), TRUE);
    8.96  	else
    8.97  		g_return_if_reached();
    8.98 -#endif /* if 0 */
    8.99  }
   8.100  
   8.101  static GtkWidget *
   8.102 @@ -1855,13 +1873,11 @@
   8.103  		chat_do_im(gtkconv, who);
   8.104  	} else if (event->button == 2 && event->type == GDK_BUTTON_PRESS) {
   8.105  		/* Move to user's anchor */
   8.106 -/* TODO WEBKIT: This isn't implemented yet. */
   8.107 -#if 0
   8.108 -		GtkTextMark *mark = get_mark_for_user(gtkconv, who);
   8.109 -
   8.110 -		if(mark != NULL)
   8.111 -			gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(gtkconv->imhtml), mark, 0.1, FALSE, 0, 0);
   8.112 -#endif /* if 0 */
   8.113 +		WebKitDOMNode *node = get_mark_for_user(gtkconv, who);
   8.114 +
   8.115 +		if (node != NULL)
   8.116 +			webkit_dom_element_scroll_into_view(WEBKIT_DOM_ELEMENT(node), TRUE);
   8.117 +
   8.118  	} else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
   8.119  		GtkWidget *menu = create_chat_menu (conv, who, gc);
   8.120  		gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
   8.121 @@ -5527,7 +5543,6 @@
   8.122  	PurpleAccount *convaccount = purple_conversation_get_account(conv);
   8.123  	PurpleConnection *gc = purple_account_get_connection(convaccount);
   8.124  	PurplePluginProtocolInfo *prpl_info = gc ? PURPLE_PLUGIN_PROTOCOL_INFO(purple_connection_get_prpl(gc)) : NULL;
   8.125 -	GdkAtom target = gtk_selection_data_get_target(sd);
   8.126  	const guchar *data = gtk_selection_data_get_data(sd);
   8.127  
   8.128  	if (info == PIDGIN_DRAG_BLIST_NODE)
   8.129 @@ -5630,7 +5645,7 @@
   8.130  		gtk_drag_finish(dc, TRUE,
   8.131  		                gdk_drag_context_get_actions(dc) == GDK_ACTION_MOVE, t);
   8.132  	}
   8.133 -	else if (target == gdk_atom_intern("text/uri-list", FALSE)) {
   8.134 +	else if (info == WEBKIT_WEB_VIEW_TARGET_INFO_URI_LIST) {
   8.135  		if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM)
   8.136  			pidgin_dnd_file_manage(sd, convaccount, purple_conversation_get_name(conv));
   8.137  		gtk_drag_finish(dc, TRUE,
   8.138 @@ -5641,12 +5656,6 @@
   8.139  }
   8.140  
   8.141  
   8.142 -static const GtkTargetEntry te[] =
   8.143 -{
   8.144 -	{"PURPLE_BLIST_NODE", GTK_TARGET_SAME_APP, PIDGIN_DRAG_BLIST_NODE},
   8.145 -	{"application/x-im-contact", 0, PIDGIN_DRAG_IM_CONTACT}
   8.146 -};
   8.147 -
   8.148  static PidginConversation *
   8.149  pidgin_conv_find_gtkconv(PurpleConversation * conv)
   8.150  {
   8.151 @@ -5756,6 +5765,7 @@
   8.152  	GtkWidget *pane = NULL;
   8.153  	GtkWidget *tab_cont;
   8.154  	PurpleBlistNode *convnode;
   8.155 +	GtkTargetList *targets;
   8.156  
   8.157  	if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) {
   8.158  		purple_conversation_set_ui_data(conv, gtkconv);
   8.159 @@ -5804,33 +5814,45 @@
   8.160  	}
   8.161  
   8.162  	/* Setup drag-and-drop */
   8.163 -	gtk_drag_dest_set(pane,
   8.164 -	                  GTK_DEST_DEFAULT_MOTION |
   8.165 -	                  GTK_DEST_DEFAULT_DROP,
   8.166 -	                  te, sizeof(te) / sizeof(GtkTargetEntry),
   8.167 -	                  GDK_ACTION_COPY);
   8.168 -	gtk_drag_dest_set(pane,
   8.169 -	                  GTK_DEST_DEFAULT_MOTION |
   8.170 -	                  GTK_DEST_DEFAULT_DROP,
   8.171 -	                  te, sizeof(te) / sizeof(GtkTargetEntry),
   8.172 -	                  GDK_ACTION_COPY);
   8.173 -	gtk_drag_dest_set(gtkconv->webview, 0,
   8.174 -	                  te, sizeof(te) / sizeof(GtkTargetEntry),
   8.175 -	                  GDK_ACTION_COPY);
   8.176 -
   8.177 -	gtk_drag_dest_set(gtkconv->entry, 0,
   8.178 -	                  te, sizeof(te) / sizeof(GtkTargetEntry),
   8.179 -	                  GDK_ACTION_COPY);
   8.180 +	gtk_drag_dest_set(pane, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
   8.181 +	                  NULL, 0, GDK_ACTION_COPY);
   8.182 +	targets = gtk_target_list_new(dnd_targets, G_N_ELEMENTS(dnd_targets));
   8.183 +	gtk_target_list_add(targets, gdk_atom_intern("text/uri-list", FALSE), 0,
   8.184 +	                    WEBKIT_WEB_VIEW_TARGET_INFO_URI_LIST);
   8.185 +	gtk_drag_dest_set_target_list(pane, targets);
   8.186 +
   8.187 +	if (webkit_dnd_targets) {
   8.188 +		targets = webkit_dnd_targets;
   8.189 +	} else {
   8.190 +		GtkTargetEntry *entries;
   8.191 +		gint count;
   8.192 +
   8.193 +		targets = webkit_web_view_get_paste_target_list(WEBKIT_WEB_VIEW(gtkconv->webview));
   8.194 +		entries = gtk_target_table_new_from_list(targets, &count);
   8.195 +		targets = gtk_target_list_new(entries, count);
   8.196 +		gtk_target_table_free(entries, count);
   8.197 +
   8.198 +		gtk_target_list_add_table(targets, dnd_targets, G_N_ELEMENTS(dnd_targets));
   8.199 +		webkit_dnd_targets = targets;
   8.200 +	}
   8.201 +
   8.202 +	gtk_drag_dest_set(gtkconv->webview, 0, NULL, 0, GDK_ACTION_COPY);
   8.203 +	gtk_drag_dest_set_target_list(gtkconv->webview, targets);
   8.204 +
   8.205 +	gtk_drag_dest_set(gtkconv->entry, 0, NULL, 0, GDK_ACTION_COPY);
   8.206 +	gtk_drag_dest_set_target_list(gtkconv->entry, targets);
   8.207  
   8.208  	g_signal_connect(G_OBJECT(pane), "button_press_event",
   8.209  	                 G_CALLBACK(ignore_middle_click), NULL);
   8.210 -// TODO: this crashes with webkit, fix it
   8.211 -//	g_signal_connect(G_OBJECT(pane), "drag_data_received",
   8.212 -//	                 G_CALLBACK(conv_dnd_recv), gtkconv);
   8.213 -//	g_signal_connect(G_OBJECT(gtkconv->webview), "drag_data_received",
   8.214 -//	                 G_CALLBACK(conv_dnd_recv), gtkconv);
   8.215 -//	g_signal_connect(G_OBJECT(gtkconv->entry), "drag_data_received",
   8.216 -//	                 G_CALLBACK(conv_dnd_recv), gtkconv);
   8.217 +	g_signal_connect(G_OBJECT(pane), "drag-data-received",
   8.218 +	                 G_CALLBACK(conv_dnd_recv), gtkconv);
   8.219 +#if 0
   8.220 +	/* FIXME: WebKit confuses the dnd source when this is enabled */
   8.221 +	g_signal_connect(G_OBJECT(gtkconv->webview), "drag-data-received",
   8.222 +	                 G_CALLBACK(conv_dnd_recv), gtkconv);
   8.223 +	g_signal_connect(G_OBJECT(gtkconv->entry), "drag-data-received",
   8.224 +	                 G_CALLBACK(conv_dnd_recv), gtkconv);
   8.225 +#endif
   8.226  
   8.227  	g_signal_connect(gtkconv->webview, "style-set", G_CALLBACK(set_typing_font), gtkconv);
   8.228  
   8.229 @@ -6228,6 +6250,7 @@
   8.230  			replace = message;
   8.231  
   8.232  		} else if (g_str_has_prefix(cur, "%messageClasses%")) {
   8.233 +			char *user;
   8.234  			GString *classes = g_string_new(NULL);
   8.235  #define ADD_CLASS(f, class) \
   8.236  			if (flags & f) \
   8.237 @@ -6239,6 +6262,9 @@
   8.238  			ADD_CLASS(PURPLE_MESSAGE_DELAYED, "history ");
   8.239  			ADD_CLASS(PURPLE_MESSAGE_NICK, "mention ");
   8.240  #undef ADD_CLASS
   8.241 +			user = get_class_for_user(name);
   8.242 +			g_string_append(classes, user);
   8.243 +			g_free(user);
   8.244  
   8.245  			replace = freeval = g_string_free(classes, FALSE);
   8.246  
   8.247 @@ -6308,6 +6334,11 @@
   8.248  
   8.249  			replace = freeval = g_string_free(classes, FALSE);
   8.250  
   8.251 +		} else if (g_str_has_prefix(cur, "%variant%")) {
   8.252 +			replace = pidgin_conversation_theme_get_variant(PIDGIN_CONVERSATION(conv)->theme);
   8.253 +			replace = freeval = g_strdup(replace);
   8.254 +			purple_util_chrreplace(freeval, ' ', '_');
   8.255 +
   8.256  		} else {
   8.257  			cur++;
   8.258  			continue;
   8.259 @@ -9021,9 +9052,12 @@
   8.260  }
   8.261  
   8.262  static void
   8.263 -notebook_init_grab(PidginWindow *gtkwin, GtkWidget *widget)
   8.264 +notebook_init_grab(PidginWindow *gtkwin, GtkWidget *widget, GdkEvent *event)
   8.265  {
   8.266  	static GdkCursor *cursor = NULL;
   8.267 +#if GTK_CHECK_VERSION(3,0,0)
   8.268 +	GdkDevice *device;
   8.269 +#endif
   8.270  
   8.271  	gtkwin->in_drag = TRUE;
   8.272  
   8.273 @@ -9038,6 +9072,14 @@
   8.274  
   8.275  	/* Grab the pointer */
   8.276  	gtk_grab_add(gtkwin->notebook);
   8.277 +#if GTK_CHECK_VERSION(3,0,0)
   8.278 +	device = gdk_event_get_device(event);
   8.279 +	if (!gdk_display_device_is_grabbed(gdk_device_get_display(device), device))
   8.280 +		gdk_device_grab(device, gtk_widget_get_window(gtkwin->notebook),
   8.281 +		                GDK_OWNERSHIP_WINDOW, FALSE,
   8.282 +		                GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
   8.283 +		                cursor, gdk_event_get_time(event));
   8.284 +#else
   8.285  #ifndef _WIN32
   8.286  	/* Currently for win32 GTK+ (as of 2.2.1), gdk_pointer_is_grabbed will
   8.287  	   always be true after a button press. */
   8.288 @@ -9045,7 +9087,8 @@
   8.289  #endif
   8.290  		gdk_pointer_grab(gtk_widget_get_window(gtkwin->notebook), FALSE,
   8.291  		                 GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
   8.292 -		                 NULL, cursor, GDK_CURRENT_TIME);
   8.293 +		                 NULL, cursor, gdk_event_get_time(event));
   8.294 +#endif
   8.295  }
   8.296  
   8.297  static gboolean
   8.298 @@ -9063,7 +9106,7 @@
   8.299  		    e->y_root >= win->drag_max_y) {
   8.300  
   8.301  			    win->in_predrag = FALSE;
   8.302 -			    notebook_init_grab(win, widget);
   8.303 +			    notebook_init_grab(win, widget, (GdkEvent *)e);
   8.304  		    }
   8.305  	}
   8.306  	else { /* Otherwise, draw the arrows. */
   8.307 @@ -9075,7 +9118,7 @@
   8.308  		gboolean to_right = FALSE;
   8.309  
   8.310  		/* Get the window that the cursor is over. */
   8.311 -		dest_win = pidgin_conv_window_get_at_xy(e->x_root, e->y_root);
   8.312 +		dest_win = pidgin_conv_window_get_at_event((GdkEvent *)e);
   8.313  
   8.314  		if (dest_win == NULL) {
   8.315  			dnd_hints_hide_all();
   8.316 @@ -9139,9 +9182,9 @@
   8.317  	    e->y_root <  win->drag_min_y ||
   8.318  	    e->y_root >= win->drag_max_y) {
   8.319  
   8.320 -		    win->in_predrag = FALSE;
   8.321 -		    notebook_init_grab(win, widget);
   8.322 -	    }
   8.323 +		win->in_predrag = FALSE;
   8.324 +		notebook_init_grab(win, widget, (GdkEvent *)e);
   8.325 +	}
   8.326  
   8.327  	return TRUE;
   8.328  }
   8.329 @@ -9306,11 +9349,14 @@
   8.330  {
   8.331  	PidginWindow *dest_win;
   8.332  	GtkNotebook *dest_notebook;
   8.333 -	PurpleConversation *conv;
   8.334 +	PidginConversation *active_gtkconv;
   8.335  	PidginConversation *gtkconv;
   8.336  	gint dest_page_num = 0;
   8.337  	gboolean new_window = FALSE;
   8.338  	gboolean to_right = FALSE;
   8.339 +#if GTK_CHECK_VERSION(3,0,0)
   8.340 +	GdkDevice *device;
   8.341 +#endif
   8.342  
   8.343  	/*
   8.344  	* Don't check to make sure that the event's window matches the
   8.345 @@ -9320,10 +9366,18 @@
   8.346  	if (e->button != 1 && e->type != GDK_BUTTON_RELEASE)
   8.347  		return FALSE;
   8.348  
   8.349 +#if GTK_CHECK_VERSION(3,0,0)
   8.350 +	device = gdk_event_get_device((GdkEvent *)e);
   8.351 +	if (gdk_display_device_is_grabbed(gdk_device_get_display(device), device)) {
   8.352 +		gdk_device_ungrab(device, gdk_event_get_time((GdkEvent *)e));
   8.353 +		gtk_grab_remove(widget);
   8.354 +	}
   8.355 +#else
   8.356  	if (gdk_pointer_is_grabbed()) {
   8.357 -		gdk_pointer_ungrab(GDK_CURRENT_TIME);
   8.358 +		gdk_pointer_ungrab(gdk_event_get_time((GdkEvent *)e));
   8.359  		gtk_grab_remove(widget);
   8.360  	}
   8.361 +#endif
   8.362  
   8.363  	if (!win->in_predrag && !win->in_drag)
   8.364  		return FALSE;
   8.365 @@ -9360,9 +9414,9 @@
   8.366  
   8.367  	dnd_hints_hide_all();
   8.368  
   8.369 -	dest_win = pidgin_conv_window_get_at_xy(e->x_root, e->y_root);
   8.370 -
   8.371 -	conv = pidgin_conv_window_get_active_conversation(win);
   8.372 +	dest_win = pidgin_conv_window_get_at_event((GdkEvent *)e);
   8.373 +
   8.374 +	active_gtkconv = pidgin_conv_window_get_active_gtkconv(win);
   8.375  
   8.376  	if (dest_win == NULL) {
   8.377  		/* If the current window doesn't have any other conversations,
   8.378 @@ -9416,7 +9470,7 @@
   8.379  		}
   8.380  	}
   8.381  
   8.382 -	gtk_widget_grab_focus(PIDGIN_CONVERSATION(conv)->entry);
   8.383 +	gtk_widget_grab_focus(active_gtkconv->entry);
   8.384  
   8.385  	return TRUE;
   8.386  }
   8.387 @@ -10045,18 +10099,20 @@
   8.388  void
   8.389  pidgin_conv_window_destroy(PidginWindow *win)
   8.390  {
   8.391 +	PidginConversation *gtkconv;
   8.392 +	GList *iter;
   8.393 +
   8.394 +	if (win->gtkconvs) {
   8.395 +		for (iter = win->gtkconvs; iter != NULL; iter = iter->next) {
   8.396 +			gtkconv = iter->data;
   8.397 +			close_conv_cb(NULL, gtkconv);
   8.398 +		}
   8.399 +		return;
   8.400 +	}
   8.401 +
   8.402  	purple_prefs_disconnect_by_handle(win);
   8.403  	window_list = g_list_remove(window_list, win);
   8.404  
   8.405 -	if (win->gtkconvs) {
   8.406 -		while (win->gtkconvs) {
   8.407 -			gboolean last = (win->gtkconvs->next == NULL);
   8.408 -			close_conv_cb(NULL, win->gtkconvs->data);
   8.409 -			if (last)
   8.410 -				break;
   8.411 -		}
   8.412 -		return;
   8.413 -	}
   8.414  	gtk_widget_destroy(win->notebook_menu);
   8.415  	gtk_widget_destroy(win->window);
   8.416  
   8.417 @@ -10365,13 +10421,19 @@
   8.418  }
   8.419  
   8.420  PidginWindow *
   8.421 -pidgin_conv_window_get_at_xy(int x, int y)
   8.422 +pidgin_conv_window_get_at_event(GdkEvent *event)
   8.423  {
   8.424  	PidginWindow *win;
   8.425  	GdkWindow *gdkwin;
   8.426  	GList *l;
   8.427 -
   8.428 +	int x, y;
   8.429 +
   8.430 +#if GTK_CHECK_VERSION(3,0,0)
   8.431 +	gdkwin = gdk_device_get_window_at_position(gdk_event_get_device(event),
   8.432 +	                                           &x, &y);
   8.433 +#else
   8.434  	gdkwin = gdk_window_at_pointer(&x, &y);
   8.435 +#endif
   8.436  
   8.437  	if (gdkwin)
   8.438  		gdkwin = gdk_window_get_toplevel(gdkwin);
     9.1 --- a/pidgin/gtkconvwin.h
     9.2 +++ b/pidgin/gtkconvwin.h
     9.3 @@ -119,7 +119,7 @@
     9.4  PurpleConversation *pidgin_conv_window_get_active_conversation(const PidginWindow *win);
     9.5  gboolean pidgin_conv_window_is_active_conversation(const PurpleConversation *conv);
     9.6  gboolean pidgin_conv_window_has_focus(PidginWindow *win);
     9.7 -PidginWindow *pidgin_conv_window_get_at_xy(int x, int y);
     9.8 +PidginWindow *pidgin_conv_window_get_at_event(GdkEvent *event);
     9.9  GList *pidgin_conv_window_get_gtkconvs(PidginWindow *win);
    9.10  guint pidgin_conv_window_get_gtkconv_count(PidginWindow *win);
    9.11  
    10.1 --- a/pidgin/gtkimhtml.h
    10.2 +++ b/pidgin/gtkimhtml.h
    10.3 @@ -171,7 +171,7 @@
    10.4  	GTK_IMHTML_USE_POINTSIZE       = 1 << 8,
    10.5  	GTK_IMHTML_NO_FORMATTING       = 1 << 9,
    10.6  	GTK_IMHTML_USE_SMOOTHSCROLLING = 1 << 10,
    10.7 -	GTK_IMHTML_NO_SMILEY           = 1 << 11,
    10.8 +	GTK_IMHTML_NO_SMILEY           = 1 << 11
    10.9  } GtkIMHtmlOptions;
   10.10  
   10.11  enum {
    11.1 --- a/pidgin/gtkmedia.c
    11.2 +++ b/pidgin/gtkmedia.c
    11.3 @@ -443,7 +443,7 @@
    11.4  
    11.5  		gtk_widget_destroy(widget);
    11.6  
    11.7 -		gtk_widget_size_request(GTK_WIDGET(gtkmedia), &req);
    11.8 +		gtk_widget_get_preferred_size(GTK_WIDGET(gtkmedia), NULL, &req);
    11.9  		gtk_window_resize(GTK_WINDOW(gtkmedia), req.width, req.height);
   11.10  	}
   11.11  }
    12.1 --- a/pidgin/gtkplugin.c
    12.2 +++ b/pidgin/gtkplugin.c
    12.3 @@ -565,9 +565,9 @@
    12.4  {
    12.5  	PangoLayout *layout = g_object_get_data(G_OBJECT(tipwindow), "tooltip-plugin");
    12.6  #if GTK_CHECK_VERSION(3,0,0)
    12.7 -	gtk_paint_layout(gtk_widget_get_style(tipwindow), cr, GTK_STATE_NORMAL, FALSE,
    12.8 -	                 tipwindow, "tooltip",
    12.9 -	                 6, 6, layout);
   12.10 +	GtkStyleContext *context = gtk_widget_get_style_context(tipwindow);
   12.11 +	gtk_style_context_add_class(context, GTK_STYLE_CLASS_TOOLTIP);
   12.12 +	gtk_render_layout(context, cr, 6, 6, layout);
   12.13  #else
   12.14  	gtk_paint_layout(tipwindow->style, tipwindow->window, GTK_STATE_NORMAL, FALSE,
   12.15  	                 NULL, tipwindow, "tooltip",
    13.1 --- a/pidgin/gtkroomlist.c
    13.2 +++ b/pidgin/gtkroomlist.c
    13.3 @@ -356,12 +356,19 @@
    13.4  {
    13.5  	PurpleRoomlist *list = user_data;
    13.6  	PidginRoomlist *grl = purple_roomlist_get_ui_data(list);
    13.7 -	GtkStyle *style;
    13.8  	int current_height, max_width;
    13.9  	int max_text_width;
   13.10  	GtkTextDirection dir = gtk_widget_get_direction(GTK_WIDGET(grl->tree));
   13.11 +#if GTK_CHECK_VERSION(3,0,0)
   13.12 +	GtkStyleContext *context;
   13.13 +
   13.14 +	context = gtk_widget_get_style_context(grl->tipwindow);
   13.15 +	gtk_style_context_add_class(context, GTK_STYLE_CLASS_TOOLTIP);
   13.16 +#else
   13.17 +	GtkStyle *style;
   13.18  
   13.19  	style = gtk_widget_get_style(grl->tipwindow);
   13.20 +#endif
   13.21  
   13.22  	max_text_width = MAX(grl->tip_width, grl->tip_name_width);
   13.23  	max_width = TOOLTIP_BORDER + SMALL_SPACE + max_text_width + TOOLTIP_BORDER;
   13.24 @@ -370,30 +377,26 @@
   13.25  
   13.26  #if GTK_CHECK_VERSION(3,0,0)
   13.27  	if (dir == GTK_TEXT_DIR_RTL) {
   13.28 -		gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
   13.29 -		                 grl->tipwindow, "tooltip",
   13.30 -		                 max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000),
   13.31 -		                 current_height,
   13.32 -		                 grl->tip_name_layout);
   13.33 +		gtk_render_layout(context, cr,
   13.34 +		                  max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000),
   13.35 +		                  current_height,
   13.36 +		                  grl->tip_name_layout);
   13.37  	} else {
   13.38 -		gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
   13.39 -		                 grl->tipwindow, "tooltip",
   13.40 -		                 TOOLTIP_BORDER + SMALL_SPACE,
   13.41 -		                 current_height,
   13.42 -		                 grl->tip_name_layout);
   13.43 +		gtk_render_layout(context, cr,
   13.44 +		                  TOOLTIP_BORDER + SMALL_SPACE,
   13.45 +		                  current_height,
   13.46 +		                  grl->tip_name_layout);
   13.47  	}
   13.48  	if (dir != GTK_TEXT_DIR_RTL) {
   13.49 -		gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
   13.50 -		                 grl->tipwindow, "tooltip",
   13.51 -		                 TOOLTIP_BORDER + SMALL_SPACE,
   13.52 -		                 current_height + grl->tip_name_height,
   13.53 -		                 grl->tip_layout);
   13.54 +		gtk_render_layout(context, cr,
   13.55 +		                  TOOLTIP_BORDER + SMALL_SPACE,
   13.56 +		                  current_height + grl->tip_name_height,
   13.57 +		                  grl->tip_layout);
   13.58  	} else {
   13.59 -		gtk_paint_layout(style, cr, GTK_STATE_NORMAL, FALSE,
   13.60 -		                 grl->tipwindow, "tooltip",
   13.61 -		                 max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000),
   13.62 -		                 current_height + grl->tip_name_height,
   13.63 -		                 grl->tip_layout);
   13.64 +		gtk_render_layout(context, cr,
   13.65 +		                  max_width - (TOOLTIP_BORDER + SMALL_SPACE) - PANGO_PIXELS(600000),
   13.66 +		                  current_height + grl->tip_name_height,
   13.67 +		                  grl->tip_layout);
   13.68  	}
   13.69  #else
   13.70  	if (dir == GTK_TEXT_DIR_RTL) {
    14.1 --- a/pidgin/gtkstatusbox.c
    14.2 +++ b/pidgin/gtkstatusbox.c
    14.3 @@ -95,8 +95,8 @@
    14.4  static void pidgin_status_box_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
    14.5  static void pidgin_status_box_redisplay_buddy_icon(PidginStatusBox *status_box);
    14.6  static void pidgin_status_box_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data);
    14.7 -static void pidgin_status_box_popup(PidginStatusBox *box);
    14.8 -static void pidgin_status_box_popdown(PidginStatusBox *box);
    14.9 +static void pidgin_status_box_popup(PidginStatusBox *box, GdkEvent *event);
   14.10 +static void pidgin_status_box_popdown(PidginStatusBox *box, GdkEvent *event);
   14.11  
   14.12  static void do_colorshift (GdkPixbuf *dest, GdkPixbuf *src, int shift);
   14.13  static void icon_choose_cb(const char *filename, gpointer data);
   14.14 @@ -1136,7 +1136,7 @@
   14.15  static gboolean
   14.16  combo_box_scroll_event_cb(GtkWidget *w, GdkEventScroll *event, GtkWebView *webview)
   14.17  {
   14.18 -	pidgin_status_box_popup(PIDGIN_STATUS_BOX(w));
   14.19 +	pidgin_status_box_popup(PIDGIN_STATUS_BOX(w), (GdkEvent *)event);
   14.20  	return TRUE;
   14.21  }
   14.22  
   14.23 @@ -1331,7 +1331,7 @@
   14.24  	             "hscrollbar-policy", hpolicy,
   14.25  	             "vscrollbar-policy", vpolicy,
   14.26  	             NULL);
   14.27 -	gtk_widget_size_request(status_box->popup_frame, &popup_req);
   14.28 +	gtk_widget_get_preferred_size(status_box->popup_frame, NULL, &popup_req);
   14.29  
   14.30  	if (popup_req.width > *width) {
   14.31  		hpolicy = GTK_POLICY_ALWAYS;
   14.32 @@ -1339,7 +1339,7 @@
   14.33  		             "hscrollbar-policy", hpolicy,
   14.34  		             "vscrollbar-policy", vpolicy,
   14.35  		             NULL);
   14.36 -		gtk_widget_size_request(status_box->popup_frame, &popup_req);
   14.37 +		gtk_widget_get_preferred_size(status_box->popup_frame, NULL, &popup_req);
   14.38  	}
   14.39  
   14.40  	*height = popup_req.height;
   14.41 @@ -1381,28 +1381,52 @@
   14.42  }
   14.43  
   14.44  static gboolean
   14.45 -popup_grab_on_window (GdkWindow *window,
   14.46 -		      guint32    activate_time)
   14.47 +popup_grab_on_window(GdkWindow *window, GdkEvent *event)
   14.48  {
   14.49 -	if ((gdk_pointer_grab (window, TRUE,
   14.50 -			 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
   14.51 -			 GDK_POINTER_MOTION_MASK,
   14.52 -			 NULL, NULL, activate_time) == 0))
   14.53 +	guint32 activate_time = gdk_event_get_time(event);
   14.54 +#if GTK_CHECK_VERSION(3,0,0)
   14.55 +	GdkDevice *device = gdk_event_get_device(event);
   14.56 +	GdkGrabStatus status;
   14.57 +
   14.58 +	status = gdk_device_grab(device, window, GDK_OWNERSHIP_WINDOW, TRUE,
   14.59 +	                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
   14.60 +	                         GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK |
   14.61 +	                         GDK_KEY_RELEASE_MASK, NULL, activate_time);
   14.62 +	if (status == GDK_GRAB_SUCCESS) {
   14.63 +		status = gdk_device_grab(gdk_device_get_associated_device(device),
   14.64 +		                         window, GDK_OWNERSHIP_WINDOW, TRUE,
   14.65 +		                         GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
   14.66 +		                         GDK_POINTER_MOTION_MASK | GDK_KEY_PRESS_MASK |
   14.67 +		                         GDK_KEY_RELEASE_MASK, NULL, activate_time);
   14.68 +		if (status == GDK_GRAB_SUCCESS)
   14.69 +			return TRUE;
   14.70 +		else
   14.71 +			gdk_device_ungrab(device, activate_time);
   14.72 +	}
   14.73 +
   14.74 +	return FALSE;
   14.75 +#else
   14.76 +	if ((gdk_pointer_grab(window, TRUE,
   14.77 +	                      GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
   14.78 +	                      GDK_POINTER_MOTION_MASK,
   14.79 +	                      NULL, NULL, activate_time) == 0))
   14.80  	{
   14.81 -		if (gdk_keyboard_grab (window, TRUE, activate_time) == 0)
   14.82 +		if (gdk_keyboard_grab(window, TRUE, activate_time) == 0)
   14.83  			return TRUE;
   14.84  		else {
   14.85 -			gdk_display_pointer_ungrab (gdk_window_get_display (window), activate_time);
   14.86 +			gdk_display_pointer_ungrab(gdk_window_get_display(window),
   14.87 +			                           activate_time);
   14.88  			return FALSE;
   14.89  		}
   14.90  	}
   14.91  
   14.92  	return FALSE;
   14.93 +#endif
   14.94  }
   14.95  
   14.96  
   14.97  static void
   14.98 -pidgin_status_box_popup(PidginStatusBox *box)
   14.99 +pidgin_status_box_popup(PidginStatusBox *box, GdkEvent *event)
  14.100  {
  14.101  	int width, height, x, y;
  14.102  	pidgin_status_box_list_position (box, &x, &y, &width, &height);
  14.103 @@ -1411,8 +1435,7 @@
  14.104  	gtk_window_move (GTK_WINDOW (box->popup_window), x, y);
  14.105  	gtk_widget_show(box->popup_window);
  14.106  	gtk_widget_grab_focus (box->tree_view);
  14.107 -	if (!popup_grab_on_window (gtk_widget_get_window(box->popup_window),
  14.108 -				   GDK_CURRENT_TIME)) {
  14.109 +	if (!popup_grab_on_window(gtk_widget_get_window(box->popup_window), event)) {
  14.110  		gtk_widget_hide (box->popup_window);
  14.111  		return;
  14.112  	}
  14.113 @@ -1429,15 +1452,25 @@
  14.114  }
  14.115  
  14.116  static void
  14.117 -pidgin_status_box_popdown(PidginStatusBox *box)
  14.118 +pidgin_status_box_popdown(PidginStatusBox *box, GdkEvent *event)
  14.119  {
  14.120 +	guint32 time;
  14.121 +#if GTK_CHECK_VERSION(3,0,0)
  14.122 +	GdkDevice *device;
  14.123 +#endif
  14.124  	gtk_widget_hide(box->popup_window);
  14.125  	box->popup_in_progress = FALSE;
  14.126 -	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (box->toggle_button),
  14.127 -				      FALSE);
  14.128 -	gtk_grab_remove (box->popup_window);
  14.129 -	gdk_pointer_ungrab(GDK_CURRENT_TIME);
  14.130 -	gdk_keyboard_ungrab(GDK_CURRENT_TIME);
  14.131 +	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(box->toggle_button), FALSE);
  14.132 +	gtk_grab_remove(box->popup_window);
  14.133 +	time = gdk_event_get_time(event);
  14.134 +#if GTK_CHECK_VERSION(3,0,0)
  14.135 +	device = gdk_event_get_device(event);
  14.136 +	gdk_device_ungrab(device, time);
  14.137 +	gdk_device_ungrab(gdk_device_get_associated_device(device), time);
  14.138 +#else
  14.139 +	gdk_pointer_ungrab(time);
  14.140 +	gdk_keyboard_ungrab(time);
  14.141 +#endif
  14.142  }
  14.143  
  14.144  static gboolean
  14.145 @@ -1449,10 +1482,10 @@
  14.146  		case GDK_KEY_KP_Space:
  14.147  		case GDK_KEY_space:
  14.148  			if (!box->popup_in_progress) {
  14.149 -				pidgin_status_box_popup (box);
  14.150 +				pidgin_status_box_popup(box, (GdkEvent *)event);
  14.151  				box->popup_in_progress = TRUE;
  14.152  			} else {
  14.153 -				pidgin_status_box_popdown(box);
  14.154 +				pidgin_status_box_popdown(box, (GdkEvent *)event);
  14.155  			}
  14.156  			return TRUE;
  14.157  		default:
  14.158 @@ -1464,9 +1497,9 @@
  14.159  toggled_cb(GtkWidget *widget, GdkEventButton *event, PidginStatusBox *box)
  14.160  {
  14.161  	if (!box->popup_in_progress)
  14.162 -		pidgin_status_box_popup (box);
  14.163 +		pidgin_status_box_popup(box, (GdkEvent *)event);
  14.164  	else
  14.165 -		pidgin_status_box_popdown(box);
  14.166 +		pidgin_status_box_popdown(box, (GdkEvent *)event);
  14.167  	return TRUE;
  14.168  }
  14.169  
  14.170 @@ -1574,13 +1607,13 @@
  14.171  }
  14.172  
  14.173  static void
  14.174 -treeview_activate_current_selection(PidginStatusBox *status_box, GtkTreePath *path)
  14.175 +treeview_activate_current_selection(PidginStatusBox *status_box, GtkTreePath *path, GdkEvent *event)
  14.176  {
  14.177  	if (status_box->active_row)
  14.178  		gtk_tree_row_reference_free(status_box->active_row);
  14.179  
  14.180  	status_box->active_row = gtk_tree_row_reference_new(GTK_TREE_MODEL(status_box->dropdown_store), path);
  14.181 -	pidgin_status_box_popdown (status_box);
  14.182 +	pidgin_status_box_popdown(status_box, event);
  14.183  	pidgin_status_box_changed(status_box);
  14.184  }
  14.185  
  14.186 @@ -1596,7 +1629,7 @@
  14.187  }
  14.188  
  14.189  static void
  14.190 -tree_view_delete_current_selection(PidginStatusBox *status_box, GtkTreePath *path)
  14.191 +tree_view_delete_current_selection(PidginStatusBox *status_box, GtkTreePath *path, GdkEvent *event)
  14.192  {
  14.193  	GtkTreeIter iter;
  14.194  	gpointer data;
  14.195 @@ -1631,7 +1664,7 @@
  14.196  
  14.197  	g_free(msg);
  14.198  
  14.199 -	pidgin_status_box_popdown(status_box);
  14.200 +	pidgin_status_box_popdown(status_box, event);
  14.201  }
  14.202  
  14.203  static gboolean
  14.204 @@ -1645,7 +1678,7 @@
  14.205  		if (ewidget == status_box->toggle_button &&
  14.206  		    status_box->popup_in_progress &&
  14.207  		    gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (status_box->toggle_button))) {
  14.208 -			pidgin_status_box_popdown (status_box);
  14.209 +			pidgin_status_box_popdown(status_box, (GdkEvent *)event);
  14.210  			return TRUE;
  14.211  		} else if (ewidget == status_box->toggle_button) {
  14.212  			status_box->popup_in_progress = TRUE;
  14.213 @@ -1653,7 +1686,7 @@
  14.214  
  14.215  		/* released outside treeview */
  14.216  		if (ewidget != status_box->toggle_button) {
  14.217 -				pidgin_status_box_popdown (status_box);
  14.218 +				pidgin_status_box_popdown(status_box, (GdkEvent *)event);
  14.219  				return TRUE;
  14.220  		}
  14.221  
  14.222 @@ -1668,7 +1701,7 @@
  14.223  	if (!ret)
  14.224  		return TRUE; /* clicked outside window? */
  14.225  
  14.226 -	treeview_activate_current_selection(status_box, path);
  14.227 +	treeview_activate_current_selection(status_box, path, (GdkEvent *)event);
  14.228  	gtk_tree_path_free (path);
  14.229  
  14.230  	return TRUE;
  14.231 @@ -1680,7 +1713,7 @@
  14.232  {
  14.233  	if (box->popup_in_progress) {
  14.234  		if (event->keyval == GDK_KEY_Escape) {
  14.235 -			pidgin_status_box_popdown(box);
  14.236 +			pidgin_status_box_popdown(box, (GdkEvent *)event);
  14.237  			return TRUE;
  14.238  		} else {
  14.239  			GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(box->tree_view));
  14.240 @@ -1691,9 +1724,9 @@
  14.241  				gboolean ret = TRUE;
  14.242  				path = gtk_tree_model_get_path(GTK_TREE_MODEL(box->dropdown_store), &iter);
  14.243  				if (event->keyval == GDK_KEY_Return) {
  14.244 -					treeview_activate_current_selection(box, path);
  14.245 +					treeview_activate_current_selection(box, path, (GdkEvent *)event);
  14.246  				} else if (event->keyval == GDK_KEY_Delete) {
  14.247 -					tree_view_delete_current_selection(box, path);
  14.248 +					tree_view_delete_current_selection(box, path, (GdkEvent *)event);
  14.249  				} else
  14.250  					ret = FALSE;
  14.251  
  14.252 @@ -2038,7 +2071,7 @@
  14.253  	GtkAllocation parent_alc, box_alc, icon_alc;
  14.254  	gint border_width = gtk_container_get_border_width(GTK_CONTAINER (widget));
  14.255  
  14.256 -	gtk_widget_size_request(status_box->toggle_button, &req);
  14.257 +	gtk_widget_get_preferred_size(status_box->toggle_button, NULL, &req);
  14.258  	/* Make this icon the same size as other buddy icons in the list; unless it already wants to be bigger */
  14.259  
  14.260  	req.height = MAX(req.height, 34);
  14.261 @@ -2064,7 +2097,7 @@
  14.262  		icon_alc = parent_alc;
  14.263  		icon_alc.height = MAX(1, icon_alc.height) - 2;
  14.264  		icon_alc.width = icon_alc.height;
  14.265 -		icon_alc.x = allocation->width - (icon_alc.width + border_width + 1);
  14.266 +		icon_alc.x += allocation->width - (icon_alc.width + border_width + 1);
  14.267  		icon_alc.y += 1;
  14.268  
  14.269  		if (status_box->icon_size != icon_alc.height)
  14.270 @@ -2087,11 +2120,12 @@
  14.271  
  14.272  	if (status_box->icon_box && status_box->icon_opaque) {
  14.273  		GtkAllocation allocation;
  14.274 +		GtkStyleContext *context;
  14.275  
  14.276  		gtk_widget_get_allocation(status_box->icon_box, &allocation);
  14.277 -		gtk_paint_box(gtk_widget_get_style(widget), cr, GTK_STATE_NORMAL, GTK_SHADOW_OUT,
  14.278 -				status_box->icon_box, "button", allocation.x-1, allocation.y-1,
  14.279 -				34, 34);
  14.280 +		context = gtk_widget_get_style_context(widget);
  14.281 +		gtk_style_context_add_class(context, GTK_STYLE_CLASS_BUTTON);
  14.282 +		gtk_render_frame(context, cr, allocation.x-1, allocation.y-1, 34, 34);
  14.283  	}
  14.284  	return FALSE;
  14.285  }
    15.1 --- a/pidgin/gtkutils.c
    15.2 +++ b/pidgin/gtkutils.c
    15.3 @@ -62,8 +62,6 @@
    15.4  
    15.5  #include "gtkconv.h"
    15.6  #include "gtkdialogs.h"
    15.7 -#include "gtkimhtml.h"
    15.8 -#include "gtkimhtmltoolbar.h"
    15.9  #include "pidginstock.h"
   15.10  #include "gtkthemes.h"
   15.11  #include "gtkutils.h"
   15.12 @@ -103,49 +101,13 @@
   15.13  	return TRUE;
   15.14  }
   15.15  
   15.16 -static GtkIMHtmlFuncs gtkimhtml_cbs = {
   15.17 -	(GtkIMHtmlGetImageFunc)purple_imgstore_find_by_id,
   15.18 -	(GtkIMHtmlGetImageDataFunc)purple_imgstore_get_data,
   15.19 -	(GtkIMHtmlGetImageSizeFunc)purple_imgstore_get_size,
   15.20 -	(GtkIMHtmlGetImageFilenameFunc)purple_imgstore_get_filename,
   15.21 -	purple_imgstore_ref_by_id,
   15.22 -	purple_imgstore_unref_by_id,
   15.23 -};
   15.24 -
   15.25 -void
   15.26 -pidgin_setup_imhtml(GtkWidget *imhtml)
   15.27 -{
   15.28 -	g_return_if_fail(imhtml != NULL);
   15.29 -	g_return_if_fail(GTK_IS_IMHTML(imhtml));
   15.30 -
   15.31 -	pidgin_themes_smiley_themeize(imhtml);
   15.32 -
   15.33 -	gtk_imhtml_set_funcs(GTK_IMHTML(imhtml), &gtkimhtml_cbs);
   15.34 -
   15.35 -#ifdef _WIN32
   15.36 -	if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font")) {
   15.37 -		PangoFontDescription *desc;
   15.38 -		const char *font = purple_prefs_get_string(PIDGIN_PREFS_ROOT "/conversations/custom_font");
   15.39 -		desc = pango_font_description_from_string(font);
   15.40 -		if (desc) {
   15.41 -			gtk_widget_modify_font(imhtml, desc);
   15.42 -			pango_font_description_free(desc);
   15.43 -		}
   15.44 -	}
   15.45 -#endif
   15.46 -
   15.47 -}
   15.48 -
   15.49  void
   15.50  pidgin_setup_webview(GtkWidget *webview)
   15.51  {
   15.52  	g_return_if_fail(webview != NULL);
   15.53  	g_return_if_fail(GTK_IS_WEBVIEW(webview));
   15.54  
   15.55 -#if 0
   15.56 -/* TODO: WebKit this stuff... */
   15.57  	pidgin_themes_smiley_themeize(webview);
   15.58 -#endif
   15.59  
   15.60  #ifdef _WIN32
   15.61  	if (!purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/use_theme_font")) {
   15.62 @@ -252,66 +214,6 @@
   15.63  }
   15.64  
   15.65  GtkWidget *
   15.66 -pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret)
   15.67 -{
   15.68 -	GtkWidget *frame;
   15.69 -	GtkWidget *imhtml;
   15.70 -	GtkWidget *sep;
   15.71 -	GtkWidget *sw;
   15.72 -	GtkWidget *toolbar = NULL;
   15.73 -	GtkWidget *vbox;
   15.74 -
   15.75 -	frame = gtk_frame_new(NULL);
   15.76 -	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
   15.77 -
   15.78 -	vbox = gtk_vbox_new(FALSE, 0);
   15.79 -	gtk_container_add(GTK_CONTAINER(frame), vbox);
   15.80 -	gtk_widget_show(vbox);
   15.81 -
   15.82 -	if (editable) {
   15.83 -		toolbar = gtk_imhtmltoolbar_new();
   15.84 -		gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
   15.85 -		gtk_widget_show(toolbar);
   15.86 -
   15.87 -		sep = gtk_hseparator_new();
   15.88 -		gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
   15.89 -		g_signal_connect_swapped(G_OBJECT(toolbar), "show", G_CALLBACK(gtk_widget_show), sep);
   15.90 -		g_signal_connect_swapped(G_OBJECT(toolbar), "hide", G_CALLBACK(gtk_widget_hide), sep);
   15.91 -		gtk_widget_show(sep);
   15.92 -	}
   15.93 -
   15.94 -	imhtml = gtk_imhtml_new(NULL, NULL);
   15.95 -	gtk_imhtml_set_editable(GTK_IMHTML(imhtml), editable);
   15.96 -	gtk_imhtml_set_format_functions(GTK_IMHTML(imhtml), GTK_IMHTML_ALL ^ GTK_IMHTML_IMAGE);
   15.97 -	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(imhtml), GTK_WRAP_WORD_CHAR);
   15.98 -#ifdef USE_GTKSPELL
   15.99 -	if (editable && purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/spellcheck"))
  15.100 -		pidgin_setup_gtkspell(GTK_TEXT_VIEW(imhtml));
  15.101 -#endif
  15.102 -	gtk_widget_show(imhtml);
  15.103 -
  15.104 -	if (editable) {
  15.105 -		gtk_imhtmltoolbar_attach(GTK_IMHTMLTOOLBAR(toolbar), imhtml);
  15.106 -		gtk_imhtmltoolbar_associate_smileys(GTK_IMHTMLTOOLBAR(toolbar), "default");
  15.107 -	}
  15.108 -	pidgin_setup_imhtml(imhtml);
  15.109 -
  15.110 -	sw = pidgin_make_scrollable(imhtml, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC, GTK_SHADOW_NONE, -1, -1);
  15.111 -	gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0);
  15.112 -
  15.113 -	if (imhtml_ret != NULL)
  15.114 -		*imhtml_ret = imhtml;
  15.115 -
  15.116 -	if (editable && (toolbar_ret != NULL))
  15.117 -		*toolbar_ret = toolbar;
  15.118 -
  15.119 -	if (sw_ret != NULL)
  15.120 -		*sw_ret = sw;
  15.121 -
  15.122 -	return frame;
  15.123 -}
  15.124 -
  15.125 -GtkWidget *
  15.126  pidgin_create_webview(gboolean editable, GtkWidget **webview_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret)
  15.127  {
  15.128  	GtkWidget *frame;
  15.129 @@ -1299,7 +1201,7 @@
  15.130  	 * if a size_request was queued while we weren't popped up,
  15.131  	 * the requisition won't have been recomputed yet.
  15.132  	 */
  15.133 -	gtk_widget_size_request (widget, &requisition);
  15.134 +	gtk_widget_get_preferred_size(widget, NULL, &requisition);
  15.135  
  15.136  	monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y);
  15.137  
  15.138 @@ -1460,7 +1362,6 @@
  15.139  	GError *err = NULL;
  15.140  	PurpleConversation *conv;
  15.141  	PidginConversation *gtkconv;
  15.142 -	GtkTextIter iter;
  15.143  	int id;
  15.144  	PurpleBuddy *buddy;
  15.145  	PurpleContact *contact;
  15.146 @@ -1512,9 +1413,7 @@
  15.147  		shortname = shortname ? shortname + 1 : data->filename;
  15.148  		id = purple_imgstore_add_with_id(filedata, size, shortname);
  15.149  
  15.150 -		gtk_text_buffer_get_iter_at_mark(GTK_IMHTML(gtkconv->entry)->text_buffer, &iter,
  15.151 -						 gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer));
  15.152 -		gtk_imhtml_insert_image_at_iter(GTK_IMHTML(gtkconv->entry), id, &iter);
  15.153 +		gtk_webview_insert_image(GTK_WEBVIEW(gtkconv->entry), id);
  15.154  		purple_imgstore_unref_by_id(id);
  15.155  
  15.156  		break;
  15.157 @@ -1677,9 +1576,9 @@
  15.158  			case PURPLE_DESKTOP_ITEM_TYPE_LINK:
  15.159  				conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, who);
  15.160  				gtkconv =  PIDGIN_CONVERSATION(conv);
  15.161 -				gtk_imhtml_insert_link(GTK_IMHTML(gtkconv->entry),
  15.162 -						       gtk_text_buffer_get_insert(GTK_IMHTML(gtkconv->entry)->text_buffer),
  15.163 -						       purple_desktop_item_get_string(item, "URL"), itemname);
  15.164 +				gtk_webview_insert_link(GTK_WEBVIEW(gtkconv->entry),
  15.165 +				                        purple_desktop_item_get_string(item, "URL"),
  15.166 +				                        itemname);
  15.167  				break;
  15.168  			default:
  15.169  				/* I don't know if we really want to do anything here.  Most of
  15.170 @@ -3312,12 +3211,12 @@
  15.171  
  15.172  	if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC)
  15.173  	{
  15.174 -		purple_notify_error(imhtml, NULL,
  15.175 +		purple_notify_error(webview, NULL,
  15.176  				_("There is no application configured to open this type of file."), NULL);
  15.177  	}
  15.178  	else if (code < 32)
  15.179  	{
  15.180 -		purple_notify_error(imhtml, NULL,
  15.181 +		purple_notify_error(webview, NULL,
  15.182  				_("An error occurred while opening the file."), NULL);
  15.183  		purple_debug_warning("gtkutils", "filename: %s; code: %d\n", uri, code);
  15.184  	}
    16.1 --- a/pidgin/gtkutils.h
    16.2 +++ b/pidgin/gtkutils.h
    16.3 @@ -79,34 +79,6 @@
    16.4  G_BEGIN_DECLS
    16.5  
    16.6  /**
    16.7 - * Sets up a gtkimhtml widget, loads it with smileys, and sets the
    16.8 - * default signal handlers.
    16.9 - *
   16.10 - * @param imhtml The gtkimhtml widget to setup.
   16.11 - */
   16.12 -void pidgin_setup_imhtml(GtkWidget *imhtml);
   16.13 -
   16.14 -/**
   16.15 - * Create an GtkIMHtml widget and associated GtkIMHtmlToolbar widget.  This
   16.16 - * functions puts both widgets in a nice GtkFrame.  They're separate by an
   16.17 - * attractive GtkSeparator.
   16.18 - *
   16.19 - * @param editable @c TRUE if this imhtml should be editable.  If this is @c FALSE,
   16.20 - *        then the toolbar will NOT be created.  If this imthml should be
   16.21 - *        read-only at first, but may become editable later, then pass in
   16.22 - *        @c TRUE here and then manually call gtk_imhtml_set_editable() later.
   16.23 - * @param imhtml_ret A pointer to a pointer to a GtkWidget.  This pointer
   16.24 - *        will be set to the imhtml when this function exits.
   16.25 - * @param toolbar_ret A pointer to a pointer to a GtkWidget.  If editable is
   16.26 - *        TRUE then this will be set to the toolbar when this function exits.
   16.27 - *        Otherwise this will be set to @c NULL.
   16.28 - * @param sw_ret This will be filled with a pointer to the scrolled window
   16.29 - *        widget which contains the imhtml.
   16.30 - * @return The GtkFrame containing the toolbar and imhtml.
   16.31 - */
   16.32 -GtkWidget *pidgin_create_imhtml(gboolean editable, GtkWidget **imhtml_ret, GtkWidget **toolbar_ret, GtkWidget **sw_ret);
   16.33 -
   16.34 -/**
   16.35   * Sets up a gtkwebview widget, loads it with smileys, and sets the
   16.36   * default signal handlers.
   16.37   *
   16.38 @@ -115,7 +87,7 @@
   16.39  void pidgin_setup_webview(GtkWidget *webview);
   16.40  
   16.41  /**
   16.42 - * Create an GtkWebView widget and associated GtkIMHtmlToolbar widget.  This
   16.43 + * Create an GtkWebView widget and associated GtkWebViewToolbar widget.  This
   16.44   * function puts both widgets in a nice GtkFrame.  They're separated by an
   16.45   * attractive GtkSeparator.
   16.46   *
    17.1 --- a/pidgin/gtkwebviewtoolbar.c
    17.2 +++ b/pidgin/gtkwebviewtoolbar.c
    17.3 @@ -43,6 +43,8 @@
    17.4  
    17.5  #include <gdk/gdkkeysyms.h>
    17.6  
    17.7 +#include "gtk3compat.h"
    17.8 +
    17.9  #define GTK_WEBVIEWTOOLBAR_GET_PRIVATE(obj) \
   17.10  	(G_TYPE_INSTANCE_GET_PRIVATE((obj), GTK_TYPE_WEBVIEWTOOLBAR, GtkWebViewToolbarPriv))
   17.11  
   17.12 @@ -160,27 +162,22 @@
   17.13  	gtk_widget_grab_focus(toolbar->webview);
   17.14  }
   17.15  
   17.16 -static gboolean
   17.17 -destroy_toolbar_font(GtkWidget *widget, GdkEvent *event,
   17.18 -					 GtkWebViewToolbar *toolbar)
   17.19 +static void
   17.20 +destroy_toolbar_font(GtkWebViewToolbar *toolbar)
   17.21  {
   17.22  	GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar);
   17.23  
   17.24 -	if (widget != NULL)
   17.25 -		gtk_webview_toggle_fontface(GTK_WEBVIEW(toolbar->webview), "");
   17.26 -
   17.27  	if (priv->font_dialog != NULL)
   17.28  	{
   17.29  		gtk_widget_destroy(priv->font_dialog);
   17.30  		priv->font_dialog = NULL;
   17.31  	}
   17.32 -
   17.33 -	return FALSE;
   17.34  }
   17.35  
   17.36  static void
   17.37  realize_toolbar_font(GtkWidget *widget, GtkWebViewToolbar *toolbar)
   17.38  {
   17.39 +#if !GTK_CHECK_VERSION(3,2,0)
   17.40  	GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar);
   17.41  	GtkFontSelection *sel;
   17.42  
   17.43 @@ -193,40 +190,38 @@
   17.44  		gtk_font_selection_get_family_list(sel)));
   17.45  	gtk_widget_show(gtk_widget_get_parent(gtk_widget_get_parent(
   17.46  		gtk_font_selection_get_family_list(sel))));
   17.47 +#endif
   17.48  }
   17.49  
   17.50  static void
   17.51 -cancel_toolbar_font(GtkWidget *widget, GtkWebViewToolbar *toolbar)
   17.52 -{
   17.53 -	destroy_toolbar_font(widget, NULL, toolbar);
   17.54 -}
   17.55 -
   17.56 -static void
   17.57 -apply_font(GtkWidget *widget, GtkWebViewToolbar *toolbar)
   17.58 +apply_font(GtkDialog *dialog, gint response, GtkWebViewToolbar *toolbar)
   17.59  {
   17.60  	/* this could be expanded to include font size, weight, etc.
   17.61  	   but for now only works with font face */
   17.62 -	GtkWebViewToolbarPriv *priv = GTK_WEBVIEWTOOLBAR_GET_PRIVATE(toolbar);
   17.63 -	GtkFontSelectionDialog *fontsel = GTK_FONT_SELECTION_DIALOG(priv->font_dialog);
   17.64 -	gchar *fontname = gtk_font_selection_dialog_get_font_name(fontsel);
   17.65 +	gchar *fontname = NULL;
   17.66 +
   17.67 +	if (response == GTK_RESPONSE_OK)
   17.68 +		fontname = gtk_font_chooser_get_font(GTK_FONT_CHOOSER(dialog));
   17.69  
   17.70  	if (fontname) {
   17.71 -		const gchar *family_name = NULL;
   17.72 -		PangoFontDescription *desc = NULL;
   17.73 +		PangoFontDescription *desc;
   17.74 +		const gchar *family_name;
   17.75  
   17.76  		desc = pango_font_description_from_string(fontname);
   17.77  		family_name = pango_font_description_get_family(desc);
   17.78  
   17.79  		if (family_name) {
   17.80  			gtk_webview_toggle_fontface(GTK_WEBVIEW(toolbar->webview),
   17.81 -			                           family_name);
   17.82 +			                            family_name);
   17.83  		}
   17.84  
   17.85  		pango_font_description_free(desc);
   17.86  		g_free(fontname);
   17.87 +	} else {
   17.88 +		gtk_webview_toggle_fontface(GTK_WEBVIEW(toolbar->webview), "");
   17.89  	}
   17.90  
   17.91 -	cancel_toolbar_font(NULL, toolbar);
   17.92 +	destroy_toolbar_font(toolbar);
   17.93  }
   17.94  
   17.95  static void
   17.96 @@ -238,35 +233,31 @@
   17.97  		char *fontname = gtk_webview_get_current_fontface(GTK_WEBVIEW(toolbar->webview));
   17.98  
   17.99  		if (!priv->font_dialog) {
  17.100 -			priv->font_dialog = gtk_font_selection_dialog_new(_("Select Font"));
  17.101 +			GtkWindow *window;
  17.102 +			window = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar)));
  17.103 +			priv->font_dialog = gtk_font_chooser_dialog_new(_("Select Font"), window);
  17.104  
  17.105  			if (fontname) {
  17.106  				char *fonttif = g_strdup_printf("%s 12", fontname);
  17.107 -				gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(priv->font_dialog),
  17.108 -														fonttif);
  17.109 +				gtk_font_chooser_set_font(GTK_FONT_CHOOSER(priv->font_dialog),
  17.110 +				                          fonttif);
  17.111  				g_free(fonttif);
  17.112  			} else {
  17.113 -				gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(priv->font_dialog),
  17.114 -														DEFAULT_FONT_FACE);
  17.115 +				gtk_font_chooser_set_font(GTK_FONT_CHOOSER(priv->font_dialog),
  17.116 +				                          DEFAULT_FONT_FACE);
  17.117  			}
  17.118  
  17.119 -			g_signal_connect(G_OBJECT(priv->font_dialog), "delete_event",
  17.120 -							 G_CALLBACK(destroy_toolbar_font), toolbar);
  17.121 -			g_signal_connect(G_OBJECT(
  17.122 -				gtk_font_selection_dialog_get_ok_button(GTK_FONT_SELECTION_DIALOG(priv->font_dialog))),
  17.123 -				"clicked", G_CALLBACK(apply_font), toolbar);
  17.124 -			g_signal_connect(G_OBJECT(
  17.125 -				gtk_font_selection_dialog_get_cancel_button(GTK_FONT_SELECTION_DIALOG(priv->font_dialog))),
  17.126 -				"clicked", G_CALLBACK(cancel_toolbar_font), toolbar);
  17.127 +			g_signal_connect(G_OBJECT(priv->font_dialog), "response",
  17.128 +			                 G_CALLBACK(apply_font), toolbar);
  17.129  			g_signal_connect_after(G_OBJECT(priv->font_dialog), "realize",
  17.130 -							 G_CALLBACK(realize_toolbar_font), toolbar);
  17.131 +			                       G_CALLBACK(realize_toolbar_font), toolbar);
  17.132  		}
  17.133  
  17.134  		gtk_window_present(GTK_WINDOW(priv->font_dialog));
  17.135  
  17.136  		g_free(fontname);
  17.137  	} else {
  17.138 -		cancel_toolbar_font(GTK_WIDGET(toolbar), toolbar);
  17.139 +		destroy_toolbar_font(toolbar);
  17.140  	}
  17.141  
  17.142  	gtk_widget_grab_focus(toolbar->webview);
  17.143 @@ -695,7 +686,7 @@
  17.144  	it_last = ls; /* list iterators */
  17.145  	image = gtk_image_new_from_file(filename);
  17.146  
  17.147 -	gtk_widget_size_request(image, &size);
  17.148 +	gtk_widget_get_preferred_size(image, NULL, &size);
  17.149  
  17.150  	if ((size.width > 24)
  17.151  	 && (gtk_webview_smiley_get_flags(smiley) & GTK_WEBVIEW_SMILEY_CUSTOM)) {
  17.152 @@ -721,7 +712,7 @@
  17.153  					GDK_INTERP_HYPER);
  17.154  
  17.155  			gtk_image_set_from_pixbuf(GTK_IMAGE(image), resized); /* This unrefs pixbuf */
  17.156 -			gtk_widget_size_request(image, &size);
  17.157 +			gtk_widget_get_preferred_size(image, NULL, &size);
  17.158  			g_object_unref(G_OBJECT(resized));
  17.159  		}
  17.160  	}
  17.161 @@ -903,7 +894,7 @@
  17.162  			g_signal_connect_swapped(G_OBJECT(manage), "clicked",
  17.163  					G_CALLBACK(gtk_widget_destroy), dialog);
  17.164  			gtk_box_pack_end(GTK_BOX(vbox), manage, FALSE, TRUE, 0);
  17.165 -			gtk_widget_size_request(manage, &req);
  17.166 +			gtk_widget_get_preferred_size(manage, NULL, &req);
  17.167  			button_width = req.width;
  17.168  		}
  17.169  
  17.170 @@ -955,7 +946,7 @@
  17.171  	/* show everything */
  17.172  	gtk_widget_show_all(dialog);
  17.173  
  17.174 -	gtk_widget_size_request(viewport, &req);
  17.175 +	gtk_widget_get_preferred_size(viewport, NULL, &req);
  17.176  	gtk_widget_set_size_request(scrolled, MIN(300, req.width), MIN(290, req.height));
  17.177  
  17.178  	/* The window has to be made resizable, and the scrollbars in the scrolled window
  17.179 @@ -1164,7 +1155,7 @@
  17.180  	int savy;
  17.181  
  17.182  	gtk_widget_get_allocation(widget, &allocation);
  17.183 -	gtk_widget_size_request(GTK_WIDGET(menu), &menu_req);
  17.184 +	gtk_widget_get_preferred_size(GTK_WIDGET(menu), NULL, &menu_req);
  17.185  	gdk_window_get_origin(gtk_widget_get_window(widget), x, y);
  17.186  	*x += allocation.x;
  17.187  	*y += allocation.y + allocation.height;
  17.188 @@ -1263,12 +1254,10 @@
  17.189  		priv->image_dialog = NULL;
  17.190  	}
  17.191  
  17.192 -	destroy_toolbar_font(NULL, NULL, toolbar);
  17.193 +	destroy_toolbar_font(toolbar);
  17.194  	if (priv->smiley_dialog != NULL) {
  17.195 -#if 0
  17.196  		g_signal_handlers_disconnect_by_func(G_OBJECT(priv->smiley_dialog), close_smiley_dialog, toolbar);
  17.197  		destroy_smiley_dialog(toolbar);
  17.198 -#endif
  17.199  	}
  17.200  	destroy_toolbar_bgcolor(NULL, NULL, toolbar);
  17.201  	destroy_toolbar_fgcolor(NULL, NULL, toolbar);
    18.1 --- a/pidgin/gtkwhiteboard.c
    18.2 +++ b/pidgin/gtkwhiteboard.c
    18.3 @@ -491,7 +491,12 @@
    18.4  	GList *draw_list = purple_whiteboard_get_draw_list(wb);
    18.5  
    18.6  	if(event->is_hint)
    18.7 +#if GTK_CHECK_VERSION(3,0,0)
    18.8 +		gdk_window_get_device_position(event->window, event->device, &x, &y,
    18.9 +		                               &state);
   18.10 +#else
   18.11  		gdk_window_get_pointer(event->window, &x, &y, &state);
   18.12 +#endif
   18.13  	else
   18.14  	{
   18.15  		x = event->x;
    19.1 --- a/pidgin/pidginstock.c
    19.2 +++ b/pidgin/pidginstock.c
    19.3 @@ -520,8 +520,13 @@
    19.4  
    19.5  		if (stock_icons[i].dir == NULL) {
    19.6  			/* GTK+ Stock icon */
    19.7 +#if GTK_CHECK_VERSION(3,0,0)
    19.8 +			iconset = gtk_style_context_lookup_icon_set(gtk_widget_get_style_context(win),
    19.9 +			                                            stock_icons[i].filename);
   19.10 +#else
   19.11  			iconset = gtk_style_lookup_icon_set(gtk_widget_get_style(win),
   19.12 -					stock_icons[i].filename);
   19.13 +			                                    stock_icons[i].filename);
   19.14 +#endif
   19.15  		} else {
   19.16  			filename = find_file(stock_icons[i].dir, stock_icons[i].filename);
   19.17  
    20.1 --- a/pidgin/pidgintooltip.c
    20.2 +++ b/pidgin/pidgintooltip.c
    20.3 @@ -109,10 +109,10 @@
    20.4  	gtk_widget_get_allocation(widget, &allocation);
    20.5  
    20.6  	if (pidgin_tooltip.paint_tooltip) {
    20.7 -		gtk_paint_flat_box(gtk_widget_get_style(widget), cr,
    20.8 -		                   GTK_STATE_NORMAL, GTK_SHADOW_OUT,
    20.9 -		                   widget, "tooltip",
   20.10 -		                   0, 0, allocation.width, allocation.height);
   20.11 +		GtkStyleContext *context = gtk_widget_get_style_context(widget);
   20.12 +		gtk_style_context_add_class(context, GTK_STYLE_CLASS_TOOLTIP);
   20.13 +		gtk_render_background(context, cr,
   20.14 +		                      0, 0, allocation.width, allocation.height);
   20.15  		pidgin_tooltip.paint_tooltip(widget, cr, data);
   20.16  	}
   20.17  	return FALSE;
    21.1 --- a/pidgin/plugins/disco/gtkdisco.c
    21.2 +++ b/pidgin/plugins/disco/gtkdisco.c
    21.3 @@ -431,11 +431,9 @@
    21.4  {
    21.5  	PangoLayout *layout = g_object_get_data(G_OBJECT(tipwindow), "tooltip-plugin");
    21.6  #if GTK_CHECK_VERSION(3,0,0)
    21.7 -	gtk_paint_layout(gtk_widget_get_style(tipwindow),
    21.8 -	                 cr,
    21.9 -	                 GTK_STATE_NORMAL, FALSE,
   21.10 -	                 tipwindow, "tooltip",
   21.11 -	                 6, 6, layout);
   21.12 +	GtkStyleContext *context = gtk_widget_get_style_context(tipwindow);
   21.13 +	gtk_style_context_add_class(context, GTK_STYLE_CLASS_TOOLTIP);
   21.14 +	gtk_render_layout(context, cr, 6, 6, layout);
   21.15  #else
   21.16  	gtk_paint_layout(gtk_widget_get_style(tipwindow),
   21.17  	                 gtk_widget_get_window(tipwindow),
    22.1 --- a/pidgin/plugins/gestures/stroke-draw.c
    22.2 +++ b/pidgin/plugins/gestures/stroke-draw.c
    22.3 @@ -119,8 +119,11 @@
    22.4  	timer_id = 0;
    22.5  
    22.6  	if( event != NULL )
    22.7 +#if GTK_CHECK_VERSION(3,0,0)
    22.8 +		gdk_device_ungrab(gdk_event_get_device(event), event->button.time);
    22.9 +#else
   22.10  		gdk_pointer_ungrab (event->button.time);
   22.11 -
   22.12 +#endif
   22.13  
   22.14  	if (gstroke_draw_strokes() && gstroke_disp != NULL) {
   22.15  	    /* get rid of the invisible stroke window */
   22.16 @@ -158,9 +161,16 @@
   22.17  	  if (cursor == NULL)
   22.18  		  cursor = gdk_cursor_new(GDK_PENCIL);
   22.19  
   22.20 +#if GTK_CHECK_VERSION(3,0,0)
   22.21 +      gdk_device_grab(gdk_event_get_device(event),
   22.22 +                      gtk_widget_get_window(widget), GDK_OWNERSHIP_WINDOW,
   22.23 +                      FALSE, GDK_BUTTON_RELEASE_MASK, cursor,
   22.24 +                      event->button.time);
   22.25 +#else
   22.26        gdk_pointer_grab (gtk_widget_get_window(widget), FALSE,
   22.27  			GDK_BUTTON_RELEASE_MASK, NULL, cursor,
   22.28  			event->button.time);
   22.29 +#endif
   22.30        timer_id = g_timeout_add (GSTROKE_TIMEOUT_DURATION,
   22.31  				  gstroke_timeout, widget);
   22.32        return TRUE;
   22.33 @@ -179,7 +189,11 @@
   22.34        last_mouse_position.invalid = TRUE;
   22.35        original_widget = NULL;
   22.36        g_source_remove (timer_id);
   22.37 +#if GTK_CHECK_VERSION(3,0,0)
   22.38 +      gdk_device_ungrab(gdk_event_get_device(event), event->button.time);
   22.39 +#else
   22.40        gdk_pointer_ungrab (event->button.time);
   22.41 +#endif
   22.42        timer_id = 0;
   22.43  
   22.44        {
    23.1 --- a/pidgin/plugins/perl/common/GtkConvWin.xs
    23.2 +++ b/pidgin/plugins/perl/common/GtkConvWin.xs
    23.3 @@ -59,11 +59,6 @@
    23.4  pidgin_conv_window_has_focus(win)
    23.5  	Pidgin::Conversation::Window win
    23.6  
    23.7 -Pidgin::Conversation::Window
    23.8 -pidgin_conv_window_get_at_xy(x, y)
    23.9 -	int x
   23.10 -	int y
   23.11 -
   23.12  void
   23.13  pidgin_conv_window_get_gtkconvs(win)
   23.14  	Pidgin::Conversation::Window win
    24.1 --- a/pidgin/plugins/pidginrc.c
    24.2 +++ b/pidgin/plugins/pidginrc.c
    24.3 @@ -31,6 +31,8 @@
    24.4  #include "util.h"
    24.5  #include "version.h"
    24.6  
    24.7 +#include "gtk3compat.h"
    24.8 +
    24.9  static guint pref_callback;
   24.10  
   24.11  static const gchar *color_prefs[] = {
   24.12 @@ -306,7 +308,7 @@
   24.13  			prefpath = font_prefs[subscript];
   24.14  		}
   24.15  
   24.16 -		fontname = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(font_dialog));
   24.17 +		fontname = gtk_font_chooser_get_font(GTK_FONT_CHOOSER(font_dialog));
   24.18  
   24.19  		purple_prefs_set_string(prefpath, fontname);
   24.20  		g_free(fontname);
   24.21 @@ -318,6 +320,7 @@
   24.22  purplerc_set_font(GtkWidget *widget, gpointer data)
   24.23  {
   24.24  	gchar title[128];
   24.25 +	GtkWindow *window;
   24.26  	GtkWidget *font_dialog = NULL;
   24.27  	gint subscript = GPOINTER_TO_INT(data);
   24.28  	const gchar *pref = NULL, *prefpath = NULL;
   24.29 @@ -331,14 +334,15 @@
   24.30  		prefpath = font_prefs[subscript];
   24.31  	}
   24.32  
   24.33 -	font_dialog = gtk_font_selection_dialog_new(title);
   24.34 +	window = GTK_WINDOW(gtk_widget_get_toplevel(widget));
   24.35 +	font_dialog = gtk_font_chooser_dialog_new(title, window);
   24.36  	g_signal_connect(G_OBJECT(font_dialog), "response",
   24.37  	                 G_CALLBACK(purplerc_font_response), data);
   24.38  
   24.39  	pref = purple_prefs_get_string(prefpath);
   24.40  
   24.41  	if (pref != NULL && strcmp(pref, "")) {
   24.42 -		gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(font_dialog), pref);
   24.43 +		gtk_font_chooser_set_font(GTK_FONT_CHOOSER(font_dialog), pref);
   24.44  	}
   24.45  
   24.46  	gtk_window_present(GTK_WINDOW(font_dialog));
    25.1 --- a/pidgin/plugins/themeedit.c
    25.2 +++ b/pidgin/plugins/themeedit.c
    25.3 @@ -22,6 +22,8 @@
    25.4  #include "pidgin.h"
    25.5  #include "version.h"
    25.6  
    25.7 +#include "gtk3compat.h"
    25.8 +
    25.9  #include "theme-manager.h"
   25.10  
   25.11  #include "gtkblist.h"
   25.12 @@ -98,7 +100,7 @@
   25.13  theme_font_face_selected(GtkWidget *dialog, gint response, gpointer font)
   25.14  {
   25.15  	if (response == GTK_RESPONSE_OK || response == GTK_RESPONSE_APPLY) {
   25.16 -		const char *fontname = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dialog));
   25.17 +		const char *fontname = gtk_font_chooser_get_font(GTK_FONT_CHOOSER(dialog));
   25.18  		pidgin_theme_font_set_font_face(font, fontname);
   25.19  		pidgin_blist_refresh(purple_get_blist());
   25.20  	}
   25.21 @@ -108,6 +110,7 @@
   25.22  static void
   25.23  theme_font_select_face(GtkWidget *widget, gpointer prop)
   25.24  {
   25.25 +	GtkWindow *window;
   25.26  	GtkWidget *dialog;
   25.27  	PidginBlistTheme *theme;
   25.28  	PidginThemeFont *font = NULL;
   25.29 @@ -124,10 +127,10 @@
   25.30  	}
   25.31  
   25.32  	face = pidgin_theme_font_get_font_face(font);
   25.33 -	dialog = gtk_font_selection_dialog_new(_("Select Font"));
   25.34 +	window = GTK_WINDOW(gtk_widget_get_toplevel(widget));
   25.35 +	dialog = gtk_font_chooser_dialog_new(_("Select Font"), window);
   25.36  	if (face && *face)
   25.37 -		gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dialog),
   25.38 -				face);
   25.39 +		gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), face);
   25.40  	g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(theme_font_face_selected),
   25.41  			font);
   25.42  	gtk_widget_show_all(dialog);
    26.1 --- a/pidgin/plugins/ticker/gtkticker.c
    26.2 +++ b/pidgin/plugins/ticker/gtkticker.c
    26.3 @@ -294,7 +294,11 @@
    26.4  	GdkWindowAttr attributes;
    26.5  	gint attributes_mask;
    26.6  	GdkWindow *window;
    26.7 +#if GTK_CHECK_VERSION(3,0,0)
    26.8 +	GtkStyleContext *context;
    26.9 +#else
   26.10  	GtkStyle *style;
   26.11 +#endif
   26.12  	GtkAllocation allocation;
   26.13  
   26.14  	g_return_if_fail (widget != NULL);
   26.15 @@ -327,9 +331,16 @@
   26.16  	gtk_widget_set_window (widget, window);
   26.17  	gdk_window_set_user_data (window, widget);
   26.18  
   26.19 +#if GTK_CHECK_VERSION(3,0,0)
   26.20 +	context = gtk_widget_get_style_context(widget);
   26.21 +	gtk_style_context_add_class(context, GTK_STYLE_CLASS_BACKGROUND);
   26.22 +	gtk_style_context_set_state(context, GTK_STATE_NORMAL);
   26.23 +	gtk_style_context_set_background(context, window);
   26.24 +#else
   26.25  	style = gtk_style_attach (gtk_widget_get_style (widget), window);
   26.26  	gtk_widget_set_style (widget, style);
   26.27  	gtk_style_set_background (style, window, GTK_STATE_NORMAL);
   26.28 +#endif
   26.29  }
   26.30  
   26.31  #if GTK_CHECK_VERSION(3,0,0)
   26.32 @@ -469,7 +480,7 @@
   26.33  
   26.34  		child->x = 0;
   26.35  		if (gtk_widget_get_visible (child->widget)) {
   26.36 -			gtk_widget_get_child_requisition (child->widget, &child_requisition);
   26.37 +			gtk_widget_get_preferred_size (child->widget, NULL, &child_requisition);
   26.38  			child->offset = ticker->total;
   26.39  			ticker->total +=
   26.40  				child_requisition.width + border_width + ticker->spacing;
   26.41 @@ -521,7 +532,7 @@
   26.42  		child->x -= ticker->scootch;
   26.43  
   26.44  		if (gtk_widget_get_visible (child->widget)) {
   26.45 -			gtk_widget_get_child_requisition (child->widget, &child_requisition);
   26.46 +			gtk_widget_get_preferred_size (child->widget, NULL, &child_requisition);
   26.47  			child_allocation.width = child_requisition.width;
   26.48  			child_allocation.x = child->offset + border_width + child->x;
   26.49  			if ( ( child_allocation.x + child_allocation.width ) < allocation->x  ) {