diff options
Diffstat (limited to 'chrome/browser/gtk/tabs/tab_strip_gtk.cc')
-rw-r--r-- | chrome/browser/gtk/tabs/tab_strip_gtk.cc | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc index 8db5a3f..590aa07 100644 --- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc @@ -71,6 +71,26 @@ gfx::Rect GetInitialWidgetBounds(GtkWidget* widget) { return gfx::Rect(0, 0, request.width, request.height); } +// Sort rectangles based on their x position. We don't care about y position +// so we don't bother breaking ties. +int CompareGdkRectangles(const void* p1, const void* p2) { + int p1_x = static_cast<const GdkRectangle*>(p1)->x; + int p2_x = static_cast<const GdkRectangle*>(p2)->x; + if (p1_x < p2_x) + return -1; + else if (p1_x == p2_x) + return 0; + return 1; +} + +bool GdkRectMatchesTabFavIconBounds(const GdkRectangle& gdk_rect, TabGtk* tab) { + gfx::Rect favicon_bounds = tab->favicon_bounds(); + return gdk_rect.x == favicon_bounds.x() + tab->x() && + gdk_rect.y == favicon_bounds.y() + tab->y() && + gdk_rect.width == favicon_bounds.width() && + gdk_rect.height == favicon_bounds.height(); +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -994,7 +1014,6 @@ void TabStripGtk::TabChangedAt(TabContents* contents, int index, TabGtk* tab = GetTabAt(index); tab->UpdateData(contents, loading_only); tab->UpdateFromModel(); - gtk_widget_queue_draw(tabstrip_.get()); } void TabStripGtk::TabPinnedStateChanged(TabContents* contents, int index) { @@ -1760,6 +1779,20 @@ gboolean TabStripGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event, if (gdk_region_empty(event->region)) return TRUE; + // If we're only repainting favicons, optimize the paint path and only draw + // the favicons. + GdkRectangle* rects; + gint num_rects; + gdk_region_get_rectangles(event->region, &rects, &num_rects); + qsort(rects, num_rects, sizeof(GdkRectangle), CompareGdkRectangles); + std::vector<int> tabs_to_repaint; + if (tabstrip->CanPaintOnlyFavIcons(rects, num_rects, &tabs_to_repaint)) { + tabstrip->PaintOnlyFavIcons(event, tabs_to_repaint); + g_free(rects); + return TRUE; + } + g_free(rects); + // TODO(jhawkins): Ideally we'd like to only draw what's needed in the damage // rect, but the tab widgets overlap each other, and painting on one widget // will cause an expose-event to be sent to the widgets underneath. The @@ -1947,6 +1980,31 @@ void TabStripGtk::SetTabBounds(TabGtk* tab, const gfx::Rect& bounds) { bds.x(), bds.y()); } +bool TabStripGtk::CanPaintOnlyFavIcons(const GdkRectangle* rects, + int num_rects, std::vector<int>* tabs_to_paint) { + // |rects| are sorted so we just need to scan from left to right and compare + // it to the tab favicon positions from left to right. + int t = 0; + for (int r = 0; r < num_rects; ++r) { + while (t < GetTabCount()) { + TabGtk* tab = GetTabAt(t); + if (GdkRectMatchesTabFavIconBounds(rects[r], tab)) { + tabs_to_paint->push_back(t); + ++t; + break; + } + ++t; + } + } + return static_cast<int>(tabs_to_paint->size()) == num_rects; +} + +void TabStripGtk::PaintOnlyFavIcons(GdkEventExpose* event, + const std::vector<int>& tabs_to_paint) { + for (size_t i = 0; i < tabs_to_paint.size(); ++i) + GetTabAt(tabs_to_paint[i])->PaintFavIconArea(event); +} + CustomDrawButton* TabStripGtk::MakeNewTabButton() { CustomDrawButton* button = new CustomDrawButton(IDR_NEWTAB_BUTTON, IDR_NEWTAB_BUTTON_P, IDR_NEWTAB_BUTTON_H, 0); |