diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-13 20:47:12 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-13 20:47:12 +0000 |
commit | 72d1a935f1adb1023d32c7c1906dbf64fdb02705 (patch) | |
tree | 0b5c6e4746a5037c6ba0066d26f0e2898dfff0ae /chrome/browser/gtk/tabs/tab_strip_gtk.cc | |
parent | f30f5e4d4d551ff6f95335599acf2f089aafc816 (diff) | |
download | chromium_src-72d1a935f1adb1023d32c7c1906dbf64fdb02705.zip chromium_src-72d1a935f1adb1023d32c7c1906dbf64fdb02705.tar.gz chromium_src-72d1a935f1adb1023d32c7c1906dbf64fdb02705.tar.bz2 |
Adds rendering and dragging of pinned tabs to gtk.
BUG=16634
TEST=not yet
Review URL: http://codereview.chromium.org/149544
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@20523 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/gtk/tabs/tab_strip_gtk.cc')
-rw-r--r-- | chrome/browser/gtk/tabs/tab_strip_gtk.cc | 380 |
1 files changed, 332 insertions, 48 deletions
diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc index 2648964..b7e549d 100644 --- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc @@ -38,6 +38,7 @@ const int kDefaultAnimationDurationMs = 100; const int kResizeLayoutAnimationDurationMs = 166; const int kReorderAnimationDurationMs = 166; const int kAnimateToBoundsDurationMs = 150; +const int kPinnedTabAnimationDurationMs = 166; const int kNewTabButtonHOffset = -5; const int kNewTabButtonVOffset = 5; @@ -93,7 +94,8 @@ class TabStripGtk::TabAnimation : public AnimationDelegate { REMOVE, MOVE, RESIZE, - SNAP + PIN, + PIN_MOVE }; TabAnimation(TabStripGtk* tabstrip, Type type) @@ -132,10 +134,15 @@ class TabStripGtk::TabAnimation : public AnimationDelegate { static double GetCurrentTabWidth(TabStripGtk* tabstrip, TabStripGtk::TabAnimation* animation, int index) { - double unselected, selected; - tabstrip->GetCurrentTabWidths(&unselected, &selected); TabGtk* tab = tabstrip->GetTabAt(index); - double tab_width = tab->IsSelected() ? selected : unselected; + double tab_width; + if (tab->is_pinned()) { + tab_width = TabGtk::GetPinnedWidth(); + } else { + double unselected, selected; + tabstrip->GetCurrentTabWidths(&unselected, &selected); + tab_width = tab->IsSelected() ? selected : unselected; + } if (animation) { double specified_tab_width = animation->GetWidthForTab(index); @@ -160,6 +167,12 @@ class TabStripGtk::TabAnimation : public AnimationDelegate { AnimationEnded(animation); } + // Returns the gap before the tab at the specified index. Subclass if during + // an animation you need to insert a gap before a tab. + virtual double GetGapWidth(int index) { + return 0; + } + protected: // Returns the duration of the animation. virtual int GetDuration() const { @@ -175,8 +188,11 @@ class TabStripGtk::TabAnimation : public AnimationDelegate { // Figure out the desired start and end widths for the specified pre- and // post- animation tab counts. - void GenerateStartAndEndWidths(int start_tab_count, int end_tab_count) { - tabstrip_->GetDesiredTabWidths(start_tab_count, &start_unselected_width_, + void GenerateStartAndEndWidths(int start_tab_count, int end_tab_count, + int start_pinned_count, + int end_pinned_count) { + tabstrip_->GetDesiredTabWidths(start_tab_count, start_pinned_count, + &start_unselected_width_, &start_selected_width_); double standard_tab_width = static_cast<double>(TabRendererGtk::GetStandardSize().width()); @@ -189,11 +205,26 @@ class TabStripGtk::TabAnimation : public AnimationDelegate { } tabstrip_->GenerateIdealBounds(); - tabstrip_->GetDesiredTabWidths(end_tab_count, + tabstrip_->GetDesiredTabWidths(end_tab_count, end_pinned_count, &end_unselected_width_, &end_selected_width_); } + // Returns a value between |start| and |target| based on the current + // animation. + // TODO(sky): move this to animation. + int AnimationPosition(int start, int target) const { + return static_cast<int>(AnimationPosition(static_cast<double>(start), + static_cast<double>(target))); + } + + // Returns a value between |start| and |target| based on the current + // animation. + // TODO(sky): move this to animation. + double AnimationPosition(double start, double target) const { + return start + (target - start) * animation_.GetCurrentValue(); + } + TabStripGtk* tabstrip_; SlideAnimation animation_; @@ -223,7 +254,12 @@ class InsertTabAnimation : public TabStripGtk::TabAnimation { : TabAnimation(tabstrip, INSERT), index_(index) { int tab_count = tabstrip->GetTabCount(); - GenerateStartAndEndWidths(tab_count - 1, tab_count); + int end_pinned_count = tabstrip->GetPinnedTabCount(); + int start_pinned_count = end_pinned_count; + if (index < end_pinned_count) + start_pinned_count--; + GenerateStartAndEndWidths(tab_count - 1, tab_count, start_pinned_count, + end_pinned_count); } virtual ~InsertTabAnimation() {} @@ -232,11 +268,17 @@ class InsertTabAnimation : public TabStripGtk::TabAnimation { virtual double GetWidthForTab(int index) const { if (index == index_) { bool is_selected = tabstrip_->model()->selected_index() == index; - double target_width = - is_selected ? end_unselected_width_ : end_selected_width_; - double start_width = - is_selected ? TabGtk::GetMinimumSelectedSize().width() : - TabGtk::GetMinimumUnselectedSize().width(); + double start_width, target_width; + if (index < tabstrip_->GetPinnedTabCount()) { + start_width = TabGtk::GetMinimumSelectedSize().width(); + target_width = TabGtk::GetPinnedWidth(); + } else { + target_width = + is_selected ? end_unselected_width_ : end_selected_width_; + start_width = + is_selected ? TabGtk::GetMinimumSelectedSize().width() : + TabGtk::GetMinimumUnselectedSize().width(); + } double delta = target_width - start_width; if (delta > 0) @@ -245,6 +287,9 @@ class InsertTabAnimation : public TabStripGtk::TabAnimation { return start_width; } + if (tabstrip_->GetTabAt(index)->is_pinned()) + return TabGtk::GetPinnedWidth(); + if (tabstrip_->GetTabAt(index)->IsSelected()) { double delta = end_selected_width_ - start_selected_width_; return start_selected_width_ + (delta * animation_.GetCurrentValue()); @@ -269,7 +314,12 @@ class RemoveTabAnimation : public TabStripGtk::TabAnimation { : TabAnimation(tabstrip, REMOVE), index_(index) { int tab_count = tabstrip->GetTabCount(); - GenerateStartAndEndWidths(tab_count, tab_count - 1); + int start_pinned_count = tabstrip->GetPinnedTabCount(); + int end_pinned_count = start_pinned_count; + if (index < start_pinned_count) + end_pinned_count--; + GenerateStartAndEndWidths(tab_count, tab_count - 1, start_pinned_count, + end_pinned_count); } virtual ~RemoveTabAnimation() {} @@ -285,6 +335,9 @@ class RemoveTabAnimation : public TabStripGtk::TabAnimation { if (index == index_) { // The tab(s) being removed are gradually shrunken depending on the state // of the animation. + if (tab->is_pinned()) + return AnimationPosition(TabGtk::GetPinnedWidth(), -kTabHOffset); + // Removed animated Tabs are never selected. double start_width = start_unselected_width_; // Make sure target_width is at least abs(kTabHOffset), otherwise if @@ -292,10 +345,12 @@ class RemoveTabAnimation : public TabStripGtk::TabAnimation { double target_width = std::max(abs(kTabHOffset), TabGtk::GetMinimumUnselectedSize().width() + kTabHOffset); - double delta = start_width - target_width; - return start_width - (delta * animation_.GetCurrentValue()); + return AnimationPosition(start_width, target_width); } + if (tab->is_pinned()) + return TabGtk::GetPinnedWidth(); + if (tabstrip_->available_width_for_tabs_ != -1 && index_ != tabstrip_->GetTabCount() - 1) { return TabStripGtk::TabAnimation::GetWidthForTab(index); @@ -386,7 +441,9 @@ class ResizeLayoutAnimation : public TabStripGtk::TabAnimation { explicit ResizeLayoutAnimation(TabStripGtk* tabstrip) : TabAnimation(tabstrip, RESIZE) { int tab_count = tabstrip->GetTabCount(); - GenerateStartAndEndWidths(tab_count, tab_count); + int pinned_tab_count = tabstrip->GetPinnedTabCount(); + GenerateStartAndEndWidths(tab_count, tab_count, pinned_tab_count, + pinned_tab_count); InitStartState(); } virtual ~ResizeLayoutAnimation() {} @@ -404,13 +461,15 @@ class ResizeLayoutAnimation : public TabStripGtk::TabAnimation { } virtual double GetWidthForTab(int index) const { - if (tabstrip_->GetTabAt(index)->IsSelected()) { - double delta = end_selected_width_ - start_selected_width_; - return start_selected_width_ + (delta * animation_.GetCurrentValue()); - } + TabGtk* tab = tabstrip_->GetTabAt(index); - double delta = end_unselected_width_ - start_unselected_width_; - return start_unselected_width_ + (delta * animation_.GetCurrentValue()); + if (tab->is_pinned()) + return TabGtk::GetPinnedWidth(); + + if (tab->IsSelected()) + return AnimationPosition(start_selected_width_, end_selected_width_); + + return AnimationPosition(start_unselected_width_, end_unselected_width_); } private: @@ -421,10 +480,12 @@ class ResizeLayoutAnimation : public TabStripGtk::TabAnimation { void InitStartState() { for (int i = 0; i < tabstrip_->GetTabCount(); ++i) { TabGtk* current_tab = tabstrip_->GetTabAt(i); - if (current_tab->IsSelected()) { - start_selected_width_ = current_tab->width(); - } else { - start_unselected_width_ = current_tab->width(); + if (!current_tab->is_pinned()) { + if (current_tab->IsSelected()) { + start_selected_width_ = current_tab->width(); + } else { + start_unselected_width_ = current_tab->width(); + } } } } @@ -433,6 +494,162 @@ class ResizeLayoutAnimation : public TabStripGtk::TabAnimation { }; //////////////////////////////////////////////////////////////////////////////// + +// Handles a tabs pinned state changing while the tab does not change position +// in the model. +class PinnedTabAnimation : public TabStripGtk::TabAnimation { + public: + explicit PinnedTabAnimation(TabStripGtk* tabstrip, int index) + : TabAnimation(tabstrip, PIN), + index_(index) { + int tab_count = tabstrip->GetTabCount(); + int start_pinned_count = tabstrip->GetPinnedTabCount(); + int end_pinned_count = start_pinned_count; + if (tabstrip->GetTabAt(index)->is_pinned()) + start_pinned_count--; + else + start_pinned_count++; + GenerateStartAndEndWidths(tab_count, tab_count, start_pinned_count, + end_pinned_count); + } + + protected: + // Overridden from TabStripGtk::TabAnimation: + virtual int GetDuration() const { + return kPinnedTabAnimationDurationMs; + } + + virtual double GetWidthForTab(int index) const { + TabGtk* tab = tabstrip_->GetTabAt(index); + + if (index == index_) { + if (tab->is_pinned()) { + return AnimationPosition( + start_selected_width_, + static_cast<double>(TabGtk::GetPinnedWidth())); + } else { + return AnimationPosition(static_cast<double>(TabGtk::GetPinnedWidth()), + end_selected_width_); + } + } else if (tab->is_pinned()) { + return TabGtk::GetPinnedWidth(); + } + + if (tab->IsSelected()) + return AnimationPosition(start_selected_width_, end_selected_width_); + + return AnimationPosition(start_unselected_width_, end_unselected_width_); + } + + private: + // Index of the tab whose pinned state changed. + int index_; + + DISALLOW_COPY_AND_ASSIGN(PinnedTabAnimation); +}; + +//////////////////////////////////////////////////////////////////////////////// + +// Handles the animation when a tabs pinned state changes and the tab moves as a +// result. +class PinAndMoveAnimation : public TabStripGtk::TabAnimation { + public: + explicit PinAndMoveAnimation(TabStripGtk* tabstrip, + int from_index, + int to_index, + const gfx::Rect& start_bounds) + : TabAnimation(tabstrip, PIN_MOVE), + tab_(tabstrip->GetTabAt(to_index)), + start_bounds_(start_bounds), + from_index_(from_index), + to_index_(to_index) { + int tab_count = tabstrip->GetTabCount(); + int start_pinned_count = tabstrip->GetPinnedTabCount(); + int end_pinned_count = start_pinned_count; + if (tabstrip->GetTabAt(to_index)->is_pinned()) + start_pinned_count--; + else + start_pinned_count++; + GenerateStartAndEndWidths(tab_count, tab_count, start_pinned_count, + end_pinned_count); + target_bounds_ = tabstrip->GetIdealBounds(to_index); + } + + // Overridden from AnimationDelegate: + virtual void AnimationProgressed(const Animation* animation) { + // Do the normal layout. + TabAnimation::AnimationProgressed(animation); + + // Then special case the position of the tab being moved. + int x = AnimationPosition(start_bounds_.x(), target_bounds_.x()); + int width = AnimationPosition(start_bounds_.width(), + target_bounds_.width()); + gfx::Rect tab_bounds(x, start_bounds_.y(), width, + start_bounds_.height()); + tabstrip_->SetTabBounds(tab_, tab_bounds); + } + + virtual void AnimationEnded(const Animation* animation) { + tabstrip_->resize_layout_scheduled_ = false; + TabStripGtk::TabAnimation::AnimationEnded(animation); + } + + virtual double GetGapWidth(int index) { + if (to_index_ < from_index_) { + // The tab was pinned. + if (index == to_index_) { + double current_size = AnimationPosition(0, target_bounds_.width()); + if (current_size < -kTabHOffset) + return -(current_size + kTabHOffset); + } else if (index == from_index_ + 1) { + return AnimationPosition(start_bounds_.width(), 0); + } + } else { + // The tab was unpinned. + if (index == from_index_) { + return AnimationPosition(TabGtk::GetPinnedWidth() + kTabHOffset, 0); + } + } + return 0; + } + + protected: + // Overridden from TabStripGtk::TabAnimation: + virtual int GetDuration() const { return kReorderAnimationDurationMs; } + + virtual double GetWidthForTab(int index) const { + TabGtk* tab = tabstrip_->GetTabAt(index); + + if (index == to_index_) + return AnimationPosition(0, target_bounds_.width()); + + if (tab->is_pinned()) + return TabGtk::GetPinnedWidth(); + + if (tab->IsSelected()) + return AnimationPosition(start_selected_width_, end_selected_width_); + + return AnimationPosition(start_unselected_width_, end_unselected_width_); + } + + private: + // The tab being moved. + TabGtk* tab_; + + // Initial bounds of tab_. + gfx::Rect start_bounds_; + + // Target bounds. + gfx::Rect target_bounds_; + + // Start and end indices of the tab. + int from_index_; + int to_index_; + + DISALLOW_COPY_AND_ASSIGN(PinAndMoveAnimation); +}; + +//////////////////////////////////////////////////////////////////////////////// // TabStripGtk, public: TabStripGtk::TabStripGtk(TabStripModel* model) @@ -537,7 +754,8 @@ void TabStripGtk::Layout() { const gfx::Rect& bounds = tab_data_.at(i).ideal_bounds; TabGtk* tab = GetTabAt(i); SetTabBounds(tab, bounds); - tab_right = bounds.right() + kTabHOffset; + tab_right = bounds.right(); + tab_right += GetTabHOffset(i + 1); } LayoutNewTabButton(static_cast<double>(tab_right), current_unselected_width_); @@ -685,16 +903,11 @@ void TabStripGtk::TabInsertedAt(TabContents* contents, // Only insert if we're not already in the list. if (!contains_tab) { - if (index == TabStripModel::kNoTab) { - TabData d = { tab, gfx::Rect() }; - tab_data_.push_back(d); - tab->UpdateData(contents, false); - } else { - TabData d = { tab, gfx::Rect() }; - tab_data_.insert(tab_data_.begin() + index, d); - tab->UpdateData(contents, false); - } + TabData d = { tab, gfx::Rect() }; + tab_data_.insert(tab_data_.begin() + index, d); + tab->UpdateData(contents, false); } + tab->set_pinned(model_->IsTabPinned(index)); if (gtk_widget_get_parent(tab->widget()) != tabstrip_.get()) gtk_fixed_put(GTK_FIXED(tabstrip_.get()), tab->widget(), 0, 0); @@ -742,13 +955,20 @@ void TabStripGtk::TabSelectedAt(TabContents* old_contents, void TabStripGtk::TabMoved(TabContents* contents, int from_index, - int to_index) { + int to_index, + bool pinned_state_changed) { + gfx::Rect start_bounds = GetIdealBounds(from_index); TabGtk* tab = GetTabAt(from_index); tab_data_.erase(tab_data_.begin() + from_index); TabData data = {tab, gfx::Rect()}; + tab->set_pinned(model_->IsTabPinned(to_index)); tab_data_.insert(tab_data_.begin() + to_index, data); - GenerateIdealBounds(); - StartMoveTabAnimation(from_index, to_index); + if (pinned_state_changed) { + StartPinAndMoveTabAnimation(from_index, to_index, start_bounds); + } else { + GenerateIdealBounds(); + StartMoveTabAnimation(from_index, to_index); + } } void TabStripGtk::TabChangedAt(TabContents* contents, int index, @@ -761,6 +981,11 @@ void TabStripGtk::TabChangedAt(TabContents* contents, int index, gtk_widget_queue_draw(tabstrip_.get()); } +void TabStripGtk::TabPinnedStateChanged(TabContents* contents, int index) { + GetTabAt(index)->set_pinned(model_->IsTabPinned(index)); + StartPinnedTabAnimation(index); +} + //////////////////////////////////////////////////////////////////////////////// // TabStripGtk, TabGtk::TabDelegate implementation: @@ -895,6 +1120,17 @@ int TabStripGtk::GetTabCount() const { return static_cast<int>(tab_data_.size()); } +int TabStripGtk::GetPinnedTabCount() const { + int pinned_count = 0; + for (size_t i = 0; i < tab_data_.size(); ++i) { + if (tab_data_[i].tab->is_pinned()) + pinned_count++; + else + return pinned_count; + } + return pinned_count; +} + int TabStripGtk::GetAvailableWidthForTabs(TabGtk* last_tab) const { return last_tab->x() + last_tab->width(); } @@ -950,7 +1186,7 @@ void TabStripGtk::HandleGlobalMouseMoveEvent() { void TabStripGtk::GenerateIdealBounds() { int tab_count = GetTabCount(); double unselected, selected; - GetDesiredTabWidths(tab_count, &unselected, &selected); + GetDesiredTabWidths(tab_count, GetPinnedTabCount(), &unselected, &selected); current_unselected_width_ = unselected; current_selected_width_ = selected; @@ -962,14 +1198,16 @@ void TabStripGtk::GenerateIdealBounds() { for (int i = 0; i < tab_count; ++i) { TabGtk* tab = GetTabAt(i); double tab_width = unselected; - if (tab->IsSelected()) + if (tab->is_pinned()) + tab_width = TabGtk::GetPinnedWidth(); + else if (tab->IsSelected()) tab_width = selected; double end_of_tab = tab_x + tab_width; int rounded_tab_x = Round(tab_x); gfx::Rect state(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, tab_height); tab_data_.at(i).ideal_bounds = state; - tab_x = end_of_tab + kTabHOffset; + tab_x = end_of_tab + GetTabHOffset(i + 1); } } @@ -1005,17 +1243,21 @@ void TabStripGtk::LayoutTabOverviewButton() { #endif void TabStripGtk::GetDesiredTabWidths(int tab_count, + int pinned_tab_count, double* unselected_width, double* selected_width) const { + DCHECK(tab_count >= 0 && pinned_tab_count >= 0 && + pinned_tab_count <= tab_count); const double min_unselected_width = TabGtk::GetMinimumUnselectedSize().width(); const double min_selected_width = TabGtk::GetMinimumSelectedSize().width(); + *unselected_width = min_unselected_width; + *selected_width = min_selected_width; + if (tab_count == 0) { // Return immediately to avoid divide-by-zero below. - *unselected_width = min_unselected_width; - *selected_width = min_selected_width; return; } @@ -1041,6 +1283,18 @@ void TabStripGtk::GetDesiredTabWidths(int tab_count, available_width = available_width_for_tabs_; } + if (pinned_tab_count > 0) { + available_width -= (pinned_tab_count * TabGtk::GetPinnedWidth() - + std::max(0, pinned_tab_count - 1) * kTabHOffset); + tab_count -= pinned_tab_count; + if (tab_count == 0) { + *selected_width = *unselected_width = TabGtk::GetStandardSize().width(); + return; + } + // For spacing between last pinned tab and normal tab. + available_width -= kTabHOffset; + } + // Calculate the desired tab widths by dividing the available space into equal // portions. Don't let tabs get larger than the "standard width" or smaller // than the minimum width for each type, respectively. @@ -1078,6 +1332,10 @@ void TabStripGtk::GetDesiredTabWidths(int tab_count, } } +int TabStripGtk::GetTabHOffset(int tab_index) { + return kTabHOffset; +} + int TabStripGtk::tab_start_x() const { return 0; } @@ -1090,9 +1348,15 @@ void TabStripGtk::ResizeLayoutTabs() { RemoveMessageLoopObserver(); available_width_for_tabs_ = -1; + int pinned_tab_count = GetPinnedTabCount(); + if (pinned_tab_count == GetTabCount()) { + // Only pinned tabs, we know the tab widths won't have changed (all pinned + // tabs have the same width), so there is nothing to do. + return; + } + TabGtk* first_tab = GetTabAt(pinned_tab_count); double unselected, selected; - GetDesiredTabWidths(GetTabCount(), &unselected, &selected); - TabGtk* first_tab = GetTabAt(0); + GetDesiredTabWidths(GetTabCount(), pinned_tab_count, &unselected, &selected); int w = Round(first_tab->IsSelected() ? selected : unselected); // We only want to run the animation if we're not already at the desired @@ -1139,6 +1403,7 @@ gfx::Rect TabStripGtk::GetDropBounds(int drop_index, int center_x; if (drop_index < GetTabCount()) { TabGtk* tab = GetTabAt(drop_index); + // TODO(sky): update these for pinned tabs. if (drop_before) center_x = tab->x() - (kTabHOffset / 2); else @@ -1368,6 +1633,8 @@ void TabStripGtk::AnimationLayout(double unselected_width) { double tab_x = tab_start_x(); for (int i = 0; i < GetTabCount(); ++i) { TabAnimation* animation = active_animation_.get(); + if (animation) + tab_x += animation->GetGapWidth(i); double tab_width = TabAnimation::GetCurrentTabWidth(this, animation, i); double end_of_tab = tab_x + tab_width; int rounded_tab_x = Round(tab_x); @@ -1375,7 +1642,7 @@ void TabStripGtk::AnimationLayout(double unselected_width) { gfx::Rect bounds(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, tab_height); SetTabBounds(tab, bounds); - tab_x = end_of_tab + kTabHOffset; + tab_x = end_of_tab + GetTabHOffset(i + 1); } LayoutNewTabButton(tab_x, unselected_width); #if defined(OS_CHROMEOS) @@ -1422,6 +1689,23 @@ void TabStripGtk::StartResizeLayoutAnimation() { active_animation_->Start(); } +void TabStripGtk::StartPinnedTabAnimation(int index) { + if (active_animation_.get()) + active_animation_->Stop(); + active_animation_.reset(new PinnedTabAnimation(this, index)); + active_animation_->Start(); +} + +void TabStripGtk::StartPinAndMoveTabAnimation(int from_index, + int to_index, + const gfx::Rect& start_bounds) { + if (active_animation_.get()) + active_animation_->Stop(); + active_animation_.reset( + new PinAndMoveAnimation(this, from_index, to_index, start_bounds)); + active_animation_->Start(); +} + bool TabStripGtk::CanUpdateDisplay() { // Don't bother laying out/painting when we're closing all tabs. if (model_->closing_all()) { |