From 8d41fc7ef16b8498a6adc809ca3deeeb855d34ac Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 20 Jun 2009 13:54:33 -0400 Subject: [PATCH] Reduce roundtrips Setting a tooltip on a widget unfortunately triggers several roundtrips to the X server. We reduce this overhead by only doing it if the widget is visible, and by deferring to an idle. See bug 585626. --- gtk/gtkwidget.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index c15da47d9f..8cf4f08b3d 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -274,6 +274,7 @@ static void gtk_widget_buildable_custom_finished (GtkBuildable static void gtk_widget_buildable_parser_finished (GtkBuildable *buildable, GtkBuilder *builder); +static void gtk_widget_queue_tooltip_query (GtkWidget *widget); static void gtk_widget_set_usize_internal (GtkWidget *widget, gint width, @@ -2488,17 +2489,18 @@ gtk_widget_set_property (GObject *object, * because an empty string would be useless for a tooltip: */ if (tooltip_markup && (strlen (tooltip_markup) == 0)) - { - g_free (tooltip_markup); - tooltip_markup = NULL; - } + { + g_free (tooltip_markup); + tooltip_markup = NULL; + } g_object_set_qdata_full (object, quark_tooltip_markup, tooltip_markup, g_free); tmp = (tooltip_window != NULL || tooltip_markup != NULL); gtk_widget_real_set_has_tooltip (widget, tmp, FALSE); - gtk_widget_trigger_tooltip_query (widget); + if (GTK_WIDGET_VISIBLE (widget)) + gtk_widget_queue_tooltip_query (widget); break; case PROP_TOOLTIP_TEXT: tooltip_window = g_object_get_qdata (object, quark_tooltip_window); @@ -2518,7 +2520,8 @@ gtk_widget_set_property (GObject *object, tmp = (tooltip_window != NULL || tooltip_markup != NULL); gtk_widget_real_set_has_tooltip (widget, tmp, FALSE); - gtk_widget_trigger_tooltip_query (widget); + if (GTK_WIDGET_VISIBLE (widget)) + gtk_widget_queue_tooltip_query (widget); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -10144,8 +10147,8 @@ gtk_widget_set_tooltip_window (GtkWidget *widget, has_tooltip = (custom_window != NULL || tooltip_markup != NULL); gtk_widget_real_set_has_tooltip (widget, has_tooltip, FALSE); - if (has_tooltip) - gtk_widget_trigger_tooltip_query (widget); + if (has_tooltip && GTK_WIDGET_VISIBLE (widget)) + gtk_widget_queue_tooltip_query (widget); } /** @@ -10184,6 +10187,36 @@ gtk_widget_trigger_tooltip_query (GtkWidget *widget) gtk_tooltip_trigger_tooltip_query (gtk_widget_get_display (widget)); } +static guint tooltip_query_id; +static GSList *tooltip_query_displays; + +static gboolean +tooltip_query_idle (gpointer data) +{ + g_slist_foreach (tooltip_query_displays, (GFunc)gtk_tooltip_trigger_tooltip_query, NULL); + g_slist_foreach (tooltip_query_displays, (GFunc)g_object_unref, NULL); + g_slist_free (tooltip_query_displays); + + tooltip_query_displays = NULL; + tooltip_query_id = 0; + + return FALSE; +} + +static void +gtk_widget_queue_tooltip_query (GtkWidget *widget) +{ + GdkDisplay *display; + + display = gtk_widget_get_display (widget); + + if (!g_slist_find (tooltip_query_displays, display)) + tooltip_query_displays = g_slist_prepend (tooltip_query_displays, g_object_ref (display)); + + if (tooltip_query_id == 0) + tooltip_query_id = gdk_threads_add_idle (tooltip_query_idle, NULL); +} + /** * gtk_widget_set_tooltip_text: * @widget: a #GtkWidget