Index: chrome/browser/ui/gtk/tabs/tab_gtk.cc |
diff --git a/chrome/browser/ui/gtk/tabs/tab_gtk.cc b/chrome/browser/ui/gtk/tabs/tab_gtk.cc |
index c8a03b083dce365de523d0c4e03e92a610006631..7de94cb5143b8c35c795e66e203502f7a10ff54c 100644 |
--- a/chrome/browser/ui/gtk/tabs/tab_gtk.cc |
+++ b/chrome/browser/ui/gtk/tabs/tab_gtk.cc |
@@ -298,12 +298,29 @@ void TabGtk::ContextMenuClosed() { |
} |
void TabGtk::UpdateTooltipState() { |
+ // Note: This method can be called several times per second for various |
+ // reasons (e.g., navigation/loading state changes, tab media indicator |
+ // updates, and so on). However, we must avoid calling the |
+ // gtk_widget_set_XXX() methods if there is no actual change in state. |
+ // Otherwise, GTK will continuously re-hide *all* tooltips throughout the |
+ // browser in response! http://crbug.com/333002 |
+ |
// Only show the tooltip if the title is truncated. |
if (title_width_ > title_bounds().width()) { |
- gtk_widget_set_tooltip_text(widget(), |
- base::UTF16ToUTF8(GetTitle()).c_str()); |
+ const std::string utf8_title = base::UTF16ToUTF8(GetTitle()); |
+ if (gtk_widget_get_has_tooltip(widget())) { |
+ gchar* const current_tooltip = gtk_widget_get_tooltip_text(widget()); |
+ if (current_tooltip) { |
+ const bool title_unchanged = (utf8_title == current_tooltip); |
+ g_free(current_tooltip); |
+ if (title_unchanged) |
+ return; |
+ } |
+ } |
+ gtk_widget_set_tooltip_text(widget(), utf8_title.c_str()); |
} else { |
- gtk_widget_set_has_tooltip(widget(), FALSE); |
+ if (gtk_widget_get_has_tooltip(widget())) |
+ gtk_widget_set_has_tooltip(widget(), FALSE); |
} |
} |