Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Side by Side Diff: chrome/browser/gtk/tabs/tab_strip_gtk.cc

Issue 179003: Add a fast path for tab strip expose. (Closed)
Patch Set: comment Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/gtk/tabs/tab_strip_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/gtk/tabs/tab_strip_gtk.h" 5 #include "chrome/browser/gtk/tabs/tab_strip_gtk.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "app/gtk_dnd_util.h" 9 #include "app/gtk_dnd_util.h"
10 #include "app/gfx/canvas_paint.h" 10 #include "app/gfx/canvas_paint.h"
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
64 } 64 }
65 65
66 // widget->allocation is not guaranteed to be set. After window creation, 66 // widget->allocation is not guaranteed to be set. After window creation,
67 // we pick up the normal bounds by connecting to the configure-event signal. 67 // we pick up the normal bounds by connecting to the configure-event signal.
68 gfx::Rect GetInitialWidgetBounds(GtkWidget* widget) { 68 gfx::Rect GetInitialWidgetBounds(GtkWidget* widget) {
69 GtkRequisition request; 69 GtkRequisition request;
70 gtk_widget_size_request(widget, &request); 70 gtk_widget_size_request(widget, &request);
71 return gfx::Rect(0, 0, request.width, request.height); 71 return gfx::Rect(0, 0, request.width, request.height);
72 } 72 }
73 73
74 // Sort rectangles based on their x position. We don't care about y position
75 // so we don't bother breaking ties.
76 int CompareGdkRectangles(const void* p1, const void* p2) {
77 int p1_x = static_cast<const GdkRectangle*>(p1)->x;
78 int p2_x = static_cast<const GdkRectangle*>(p2)->x;
79 if (p1_x < p2_x)
80 return -1;
81 else if (p1_x == p2_x)
82 return 0;
83 return 1;
84 }
85
86 bool GdkRectMatchesTabFavIconBounds(const GdkRectangle& gdk_rect, TabGtk* tab) {
87 gfx::Rect favicon_bounds = tab->favicon_bounds();
88 return gdk_rect.x == favicon_bounds.x() + tab->x() &&
89 gdk_rect.y == favicon_bounds.y() + tab->y() &&
90 gdk_rect.width == favicon_bounds.width() &&
91 gdk_rect.height == favicon_bounds.height();
92 }
93
74 } // namespace 94 } // namespace
75 95
76 //////////////////////////////////////////////////////////////////////////////// 96 ////////////////////////////////////////////////////////////////////////////////
77 // 97 //
78 // TabAnimation 98 // TabAnimation
79 // 99 //
80 // A base class for all TabStrip animations. 100 // A base class for all TabStrip animations.
81 // 101 //
82 class TabStripGtk::TabAnimation : public AnimationDelegate { 102 class TabStripGtk::TabAnimation : public AnimationDelegate {
83 public: 103 public:
(...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after
987 } 1007 }
988 } 1008 }
989 1009
990 void TabStripGtk::TabChangedAt(TabContents* contents, int index, 1010 void TabStripGtk::TabChangedAt(TabContents* contents, int index,
991 bool loading_only) { 1011 bool loading_only) {
992 // Index is in terms of the model. Need to make sure we adjust that index in 1012 // Index is in terms of the model. Need to make sure we adjust that index in
993 // case we have an animation going. 1013 // case we have an animation going.
994 TabGtk* tab = GetTabAt(index); 1014 TabGtk* tab = GetTabAt(index);
995 tab->UpdateData(contents, loading_only); 1015 tab->UpdateData(contents, loading_only);
996 tab->UpdateFromModel(); 1016 tab->UpdateFromModel();
997 gtk_widget_queue_draw(tabstrip_.get());
998 } 1017 }
999 1018
1000 void TabStripGtk::TabPinnedStateChanged(TabContents* contents, int index) { 1019 void TabStripGtk::TabPinnedStateChanged(TabContents* contents, int index) {
1001 GetTabAt(index)->set_pinned(model_->IsTabPinned(index)); 1020 GetTabAt(index)->set_pinned(model_->IsTabPinned(index));
1002 StartPinnedTabAnimation(index); 1021 StartPinnedTabAnimation(index);
1003 } 1022 }
1004 1023
1005 //////////////////////////////////////////////////////////////////////////////// 1024 ////////////////////////////////////////////////////////////////////////////////
1006 // TabStripGtk, TabGtk::TabDelegate implementation: 1025 // TabStripGtk, TabGtk::TabDelegate implementation:
1007 1026
(...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after
1753 if (layout) 1772 if (layout)
1754 Layout(); 1773 Layout();
1755 } 1774 }
1756 1775
1757 // static 1776 // static
1758 gboolean TabStripGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event, 1777 gboolean TabStripGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event,
1759 TabStripGtk* tabstrip) { 1778 TabStripGtk* tabstrip) {
1760 if (gdk_region_empty(event->region)) 1779 if (gdk_region_empty(event->region))
1761 return TRUE; 1780 return TRUE;
1762 1781
1782 // If we're only repainting favicons, optimize the paint path and only draw
1783 // the favicons.
1784 GdkRectangle* rects;
1785 gint num_rects;
1786 gdk_region_get_rectangles(event->region, &rects, &num_rects);
1787 qsort(rects, num_rects, sizeof(GdkRectangle), CompareGdkRectangles);
1788 std::vector<int> tabs_to_repaint;
1789 if (tabstrip->CanPaintOnlyFavIcons(rects, num_rects, &tabs_to_repaint)) {
1790 tabstrip->PaintOnlyFavIcons(event, tabs_to_repaint);
1791 g_free(rects);
1792 return TRUE;
1793 }
1794 g_free(rects);
1795
1763 // TODO(jhawkins): Ideally we'd like to only draw what's needed in the damage 1796 // TODO(jhawkins): Ideally we'd like to only draw what's needed in the damage
1764 // rect, but the tab widgets overlap each other, and painting on one widget 1797 // rect, but the tab widgets overlap each other, and painting on one widget
1765 // will cause an expose-event to be sent to the widgets underneath. The 1798 // will cause an expose-event to be sent to the widgets underneath. The
1766 // underlying widget does not need to be redrawn as we control the order of 1799 // underlying widget does not need to be redrawn as we control the order of
1767 // expose-events. Currently we hack it to redraw the entire tabstrip. We 1800 // expose-events. Currently we hack it to redraw the entire tabstrip. We
1768 // could change the damage rect to just contain the tabs + the new tab button. 1801 // could change the damage rect to just contain the tabs + the new tab button.
1769 event->area.x = 0; 1802 event->area.x = 0;
1770 event->area.y = 0; 1803 event->area.y = 0;
1771 event->area.width = tabstrip->bounds_.width(); 1804 event->area.width = tabstrip->bounds_.width();
1772 event->area.height = tabstrip->bounds_.height(); 1805 event->area.height = tabstrip->bounds_.height();
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
1940 } 1973 }
1941 1974
1942 void TabStripGtk::SetTabBounds(TabGtk* tab, const gfx::Rect& bounds) { 1975 void TabStripGtk::SetTabBounds(TabGtk* tab, const gfx::Rect& bounds) {
1943 gfx::Rect bds = bounds; 1976 gfx::Rect bds = bounds;
1944 bds.set_x(gtk_util::MirroredLeftPointForRect(tabstrip_.get(), bounds)); 1977 bds.set_x(gtk_util::MirroredLeftPointForRect(tabstrip_.get(), bounds));
1945 tab->SetBounds(bds); 1978 tab->SetBounds(bds);
1946 gtk_fixed_move(GTK_FIXED(tabstrip_.get()), tab->widget(), 1979 gtk_fixed_move(GTK_FIXED(tabstrip_.get()), tab->widget(),
1947 bds.x(), bds.y()); 1980 bds.x(), bds.y());
1948 } 1981 }
1949 1982
1983 bool TabStripGtk::CanPaintOnlyFavIcons(const GdkRectangle* rects,
1984 int num_rects, std::vector<int>* tabs_to_paint) {
1985 // |rects| are sorted so we just need to scan from left to right and compare
1986 // it to the tab favicon positions from left to right.
1987 int t = 0;
1988 for (int r = 0; r < num_rects; ++r) {
1989 while (t < GetTabCount()) {
1990 TabGtk* tab = GetTabAt(t);
1991 if (GdkRectMatchesTabFavIconBounds(rects[r], tab)) {
1992 tabs_to_paint->push_back(t);
1993 ++t;
1994 break;
1995 }
1996 ++t;
1997 }
1998 }
1999 return static_cast<int>(tabs_to_paint->size()) == num_rects;
2000 }
2001
2002 void TabStripGtk::PaintOnlyFavIcons(GdkEventExpose* event,
2003 const std::vector<int>& tabs_to_paint) {
2004 for (size_t i = 0; i < tabs_to_paint.size(); ++i)
2005 GetTabAt(tabs_to_paint[i])->PaintFavIconArea(event);
2006 }
2007
1950 CustomDrawButton* TabStripGtk::MakeNewTabButton() { 2008 CustomDrawButton* TabStripGtk::MakeNewTabButton() {
1951 CustomDrawButton* button = new CustomDrawButton(IDR_NEWTAB_BUTTON, 2009 CustomDrawButton* button = new CustomDrawButton(IDR_NEWTAB_BUTTON,
1952 IDR_NEWTAB_BUTTON_P, IDR_NEWTAB_BUTTON_H, 0); 2010 IDR_NEWTAB_BUTTON_P, IDR_NEWTAB_BUTTON_H, 0);
1953 2011
1954 // Let the middle mouse button initiate clicks as well. 2012 // Let the middle mouse button initiate clicks as well.
1955 gtk_util::SetButtonTriggersNavigation(button->widget()); 2013 gtk_util::SetButtonTriggersNavigation(button->widget());
1956 g_signal_connect(G_OBJECT(button->widget()), "clicked", 2014 g_signal_connect(G_OBJECT(button->widget()), "clicked",
1957 G_CALLBACK(OnNewTabClicked), this); 2015 G_CALLBACK(OnNewTabClicked), this);
1958 GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS); 2016 GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS);
1959 gtk_fixed_put(GTK_FIXED(tabstrip_.get()), button->widget(), 0, 0); 2017 gtk_fixed_put(GTK_FIXED(tabstrip_.get()), button->widget(), 0, 0);
1960 2018
1961 return button; 2019 return button;
1962 } 2020 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/tabs/tab_strip_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698