summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-02 22:47:36 +0000
committerpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-02 22:47:36 +0000
commit1c89c290fcfb818a7ee3b544bb2d534e002df8a6 (patch)
tree3cecc42eabe4fdd0a1119b00e4400a649d37666c /chrome/browser
parentaa1026c6b91c006370b0c8dda03064c9b19f765e (diff)
downloadchromium_src-1c89c290fcfb818a7ee3b544bb2d534e002df8a6.zip
chromium_src-1c89c290fcfb818a7ee3b544bb2d534e002df8a6.tar.gz
chromium_src-1c89c290fcfb818a7ee3b544bb2d534e002df8a6.tar.bz2
Fix DCHECK() in infobar animation.
The core of the problem here is that painting does not always happen synchronously with layout, and the old code was not always forcing re-layout to occur if the animation progressed in the meantime. This change forces re-layout to occur any time the animation progresses or the target height is changed, and makes that the one time when the tab and bar heights are recalculated -- all other places then use the calculated values. This also tweaks which functions are in the cross-platform versus platform-specific code as well as making a few other small cleanups. Finally, this re-enables a test on Mac that seems to be passing now. BUG=60990, 75451 TEST=none Review URL: http://codereview.chromium.org/6788014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80272 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/extensions/extension_crash_recovery_browsertest.cc4
-rw-r--r--chrome/browser/extensions/extension_infobar_apitest.cc8
-rw-r--r--chrome/browser/external_tab_container_win.cc2
-rw-r--r--chrome/browser/external_tab_container_win.h2
-rw-r--r--chrome/browser/ui/views/frame/browser_view.cc2
-rw-r--r--chrome/browser/ui/views/frame/browser_view.h2
-rw-r--r--chrome/browser/ui/views/frame/browser_view_layout.cc4
-rw-r--r--chrome/browser/ui/views/infobars/extension_infobar.cc4
-rw-r--r--chrome/browser/ui/views/infobars/infobar.cc11
-rw-r--r--chrome/browser/ui/views/infobars/infobar.h10
-rw-r--r--chrome/browser/ui/views/infobars/infobar_container.cc13
-rw-r--r--chrome/browser/ui/views/infobars/infobar_container.h15
-rw-r--r--chrome/browser/ui/views/infobars/infobar_container_view.cc15
-rw-r--r--chrome/browser/ui/views/infobars/infobar_container_view.h11
-rw-r--r--chrome/browser/ui/views/infobars/infobar_view.cc146
-rw-r--r--chrome/browser/ui/views/infobars/infobar_view.h15
16 files changed, 140 insertions, 124 deletions
diff --git a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
index a71ec7f..3dd85a9 100644
--- a/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
+++ b/chrome/browser/extensions/extension_crash_recovery_browsertest.cc
@@ -367,9 +367,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest,
}
}
-// Occassional crashes. See http://crbug.com75450
-IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest,
- DISABLED_TwoExtensionsOneByOne) {
+IN_PROC_BROWSER_TEST_F(ExtensionCrashRecoveryTest, TwoExtensionsOneByOne) {
const size_t size_before = GetExtensionService()->extensions()->size();
LoadTestExtension();
CrashExtension(size_before);
diff --git a/chrome/browser/extensions/extension_infobar_apitest.cc b/chrome/browser/extensions/extension_infobar_apitest.cc
index 3803e2f..98299f9 100644
--- a/chrome/browser/extensions/extension_infobar_apitest.cc
+++ b/chrome/browser/extensions/extension_infobar_apitest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -6,12 +6,10 @@
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/common/chrome_switches.h"
-#if defined(OS_WIN)
-// Also marking this as disabled on Windows. See http://crbug.com/75451.
-#define MAYBE_Infobars DISABLED_Infobars
+#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
+#define MAYBE_Infobars Infobars
#else
// Need to finish port to Linux. See http://crbug.com/39916 for details.
-// Temporarily marked as DISABLED on OSX too. See http://crbug.com/60990 for details.
#define MAYBE_Infobars DISABLED_Infobars
#endif
diff --git a/chrome/browser/external_tab_container_win.cc b/chrome/browser/external_tab_container_win.cc
index 33d1fc1..b2f3ade 100644
--- a/chrome/browser/external_tab_container_win.cc
+++ b/chrome/browser/external_tab_container_win.cc
@@ -939,7 +939,7 @@ void ExternalTabContainer::SetEnableExtensionAutomation(
}
}
-void ExternalTabContainer::InfoBarContainerSizeChanged(bool is_animating) {
+void ExternalTabContainer::InfoBarContainerHeightChanged(bool is_animating) {
if (external_tab_view_)
external_tab_view_->Layout();
}
diff --git a/chrome/browser/external_tab_container_win.h b/chrome/browser/external_tab_container_win.h
index 39e4854..02f5884 100644
--- a/chrome/browser/external_tab_container_win.h
+++ b/chrome/browser/external_tab_container_win.h
@@ -212,7 +212,7 @@ class ExternalTabContainer : public TabContentsDelegate,
}
// InfoBarContainer::Delegate overrides
- virtual void InfoBarContainerSizeChanged(bool is_animating);
+ virtual void InfoBarContainerHeightChanged(bool is_animating) OVERRIDE;
virtual void TabContentsCreated(TabContents* new_contents);
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 6c8adbd..237b91a 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1672,7 +1672,7 @@ void BrowserView::GetAccessibleState(ui::AccessibleViewState* state) {
state->role = ui::AccessibilityTypes::ROLE_CLIENT;
}
-void BrowserView::InfoBarContainerSizeChanged(bool is_animating) {
+void BrowserView::InfoBarContainerHeightChanged(bool is_animating) {
SelectedTabToolbarSizeChanged(is_animating);
}
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index d0be79c..6de107b 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -375,7 +375,7 @@ class BrowserView : public BrowserBubbleHost,
virtual gfx::Size GetMinimumSize() OVERRIDE;
// InfoBarContainer::Delegate overrides
- virtual void InfoBarContainerSizeChanged(bool is_animating) OVERRIDE;
+ virtual void InfoBarContainerHeightChanged(bool is_animating) OVERRIDE;
// views::SingleSplitView::Observer overrides:
virtual bool SplitHandleMoved(views::SingleSplitView* view) OVERRIDE;
diff --git a/chrome/browser/ui/views/frame/browser_view_layout.cc b/chrome/browser/ui/views/frame/browser_view_layout.cc
index 2ae1780..2bacf2ba 100644
--- a/chrome/browser/ui/views/frame/browser_view_layout.cc
+++ b/chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -367,8 +367,8 @@ int BrowserViewLayout::LayoutInfoBar(int top) {
infobar_container_->SetVisible(visible);
int height = infobar_container_->GetPreferredSize().height();
DCHECK(visible || !height) << "Invisible InfoBarContainer has height.";
- int overlapped_top = top -
- static_cast<InfoBarContainerView*>(infobar_container_)->VerticalOverlap();
+ int overlapped_top = top - static_cast<InfoBarContainerView*>(
+ infobar_container_)->GetVerticalOverlap();
infobar_container_->SetBounds(vertical_layout_rect_.x(),
overlapped_top,
vertical_layout_rect_.width(),
diff --git a/chrome/browser/ui/views/infobars/extension_infobar.cc b/chrome/browser/ui/views/infobars/extension_infobar.cc
index 4b5a4ff..e123459 100644
--- a/chrome/browser/ui/views/infobars/extension_infobar.cc
+++ b/chrome/browser/ui/views/infobars/extension_infobar.cc
@@ -43,7 +43,7 @@ ExtensionInfoBar::ExtensionInfoBar(ExtensionInfoBarDelegate* delegate)
ExtensionView* extension_view = delegate->extension_host()->view();
int height = extension_view->GetPreferredSize().height();
- set_target_height((height > 0) ?
+ SetTargetHeight((height > 0) ?
(height + InfoBarBackground::kSeparatorLineHeight) : height);
// Get notified of resize events for the ExtensionView.
@@ -130,7 +130,7 @@ void ExtensionInfoBar::OnExtensionPreferredSizeChanged(ExtensionView* view) {
animation()->Reset(0.0);
// Clamp height to a min and a max size of between 1 and 2 InfoBars.
- set_target_height(std::min(2 * kDefaultTargetHeight,
+ SetTargetHeight(std::min(2 * kDefaultTargetHeight,
std::max(kDefaultTargetHeight, view->GetPreferredSize().height())));
animation()->Show();
diff --git a/chrome/browser/ui/views/infobars/infobar.cc b/chrome/browser/ui/views/infobars/infobar.cc
index 7f37126..8641094 100644
--- a/chrome/browser/ui/views/infobars/infobar.cc
+++ b/chrome/browser/ui/views/infobars/infobar.cc
@@ -39,8 +39,7 @@ void InfoBar::Hide(bool animate) {
}
void InfoBar::AnimationProgressed(const ui::Animation* animation) {
- if (container_)
- container_->OnInfoBarAnimated(false);
+ RecalculateHeight();
}
void InfoBar::RemoveInfoBar() {
@@ -48,12 +47,14 @@ void InfoBar::RemoveInfoBar() {
container_->RemoveDelegate(delegate_);
}
-void InfoBar::PlatformSpecificHide(bool animate) {
+void InfoBar::RecalculateHeight() {
+ PlatformSpecificRecalculateHeight();
+ if (container_)
+ container_->OnInfoBarHeightChanged(animation_->is_animating());
}
void InfoBar::AnimationEnded(const ui::Animation* animation) {
- if (container_)
- container_->OnInfoBarAnimated(true);
+ RecalculateHeight();
MaybeDelete();
}
diff --git a/chrome/browser/ui/views/infobars/infobar.h b/chrome/browser/ui/views/infobars/infobar.h
index 651c368..7a50f27 100644
--- a/chrome/browser/ui/views/infobars/infobar.h
+++ b/chrome/browser/ui/views/infobars/infobar.h
@@ -45,8 +45,14 @@ class InfoBar : public ui::AnimationDelegate {
ui::SlideAnimation* animation() { return animation_.get(); }
const ui::SlideAnimation* animation() const { return animation_.get(); }
- // Subclasses may optionally override this.
- virtual void PlatformSpecificHide(bool animate);
+ // Calls PlatformSpecificRecalculateHeight(), then informs our container our
+ // height has changed.
+ void RecalculateHeight();
+
+ // Platforms may optionally override these if they need to do work during
+ // processing of the given calls.
+ virtual void PlatformSpecificHide(bool animate) {}
+ virtual void PlatformSpecificRecalculateHeight() {}
private:
// ui::AnimationDelegate:
diff --git a/chrome/browser/ui/views/infobars/infobar_container.cc b/chrome/browser/ui/views/infobars/infobar_container.cc
index 70612d3..1ec0159 100644
--- a/chrome/browser/ui/views/infobars/infobar_container.cc
+++ b/chrome/browser/ui/views/infobars/infobar_container.cc
@@ -20,9 +20,10 @@ InfoBarContainer::InfoBarContainer(Delegate* delegate)
InfoBarContainer::~InfoBarContainer() {
// Before we remove any children, we reset |delegate_|, so that no removals
- // will result in us trying to call delegate_->InfoBarContainerSizeChanged().
- // This is important because at this point |delegate_| may be shutting down,
- // and it's at best unimportant and at worst disastrous to call that.
+ // will result in us trying to call
+ // delegate_->InfoBarContainerHeightChanged(). This is important because at
+ // this point |delegate_| may be shutting down, and it's at best unimportant
+ // and at worst disastrous to call that.
delegate_ = NULL;
ChangeTabContents(NULL);
}
@@ -60,12 +61,12 @@ void InfoBarContainer::ChangeTabContents(TabContents* contents) {
}
// Now that everything is up to date, signal the delegate to re-layout.
- OnInfoBarAnimated(true);
+ OnInfoBarHeightChanged(true);
}
-void InfoBarContainer::OnInfoBarAnimated(bool done) {
+void InfoBarContainer::OnInfoBarHeightChanged(bool is_animating) {
if (delegate_)
- delegate_->InfoBarContainerSizeChanged(!done);
+ delegate_->InfoBarContainerHeightChanged(is_animating);
}
void InfoBarContainer::RemoveDelegate(InfoBarDelegate* delegate) {
diff --git a/chrome/browser/ui/views/infobars/infobar_container.h b/chrome/browser/ui/views/infobars/infobar_container.h
index a48b27d..c1dc3f3 100644
--- a/chrome/browser/ui/views/infobars/infobar_container.h
+++ b/chrome/browser/ui/views/infobars/infobar_container.h
@@ -25,11 +25,10 @@ class TabContents;
// functions, which are pure virtual here.
class InfoBarContainer : public NotificationObserver {
public:
- // The delegate is notified each time InfoBarContainer::OnInfoBarAnimated() is
- // called.
+ // The delegate is notified each time the infobar container changes height.
class Delegate {
public:
- virtual void InfoBarContainerSizeChanged(bool is_animating) = 0;
+ virtual void InfoBarContainerHeightChanged(bool is_animating) = 0;
protected:
virtual ~Delegate();
@@ -43,10 +42,10 @@ class InfoBarContainer : public NotificationObserver {
// |contents|, and show them all. |contents| may be NULL.
void ChangeTabContents(TabContents* contents);
- // Called when a contained infobar has animated. The container is expected to
- // do anything necessary to respond to the infobar's possible size change,
+ // Called when a contained infobar has animated or by some other means changed
+ // its height. The container is expected to do anything necessary to respond,
// e.g. re-layout.
- void OnInfoBarAnimated(bool done);
+ void OnInfoBarHeightChanged(bool is_animating);
// Remove the specified InfoBarDelegate from the selected TabContents. This
// will notify us back and cause us to close the InfoBar. This is called from
@@ -58,6 +57,10 @@ class InfoBarContainer : public NotificationObserver {
// hidden.
void RemoveInfoBar(InfoBar* infobar);
+ // Return the amount by which to overlap the toolbar above, so that the
+ // InfoBars inside may draw anti-spoof arrows atop it.
+ virtual int GetVerticalOverlap() = 0;
+
protected:
// These must be implemented on each platform to e.g. adjust the visible
// object hierarchy.
diff --git a/chrome/browser/ui/views/infobars/infobar_container_view.cc b/chrome/browser/ui/views/infobars/infobar_container_view.cc
index 66be4eb..0a98454 100644
--- a/chrome/browser/ui/views/infobars/infobar_container_view.cc
+++ b/chrome/browser/ui/views/infobars/infobar_container_view.cc
@@ -18,7 +18,7 @@ InfoBarContainerView::InfoBarContainerView(Delegate* delegate)
InfoBarContainerView::~InfoBarContainerView() {
}
-int InfoBarContainerView::VerticalOverlap() {
+int InfoBarContainerView::GetVerticalOverlap() {
return GetVerticalOverlap(NULL);
}
@@ -31,14 +31,14 @@ gfx::Size InfoBarContainerView::GetPreferredSize() {
}
void InfoBarContainerView::Layout() {
- int top = GetVerticalOverlap(NULL);
+ int top = GetVerticalOverlap();
for (int i = 0; i < child_count(); ++i) {
View* child = GetChildViewAt(i);
- gfx::Size ps = child->GetPreferredSize();
- top -= static_cast<InfoBarView*>(child)->AnimatedTabHeight();
- child->SetBounds(0, top, width(), ps.height());
- top += ps.height();
+ top -= static_cast<InfoBarView*>(child)->tab_height();
+ int child_height = child->GetPreferredSize().height();
+ child->SetBounds(0, top, width(), child_height);
+ top += child_height;
}
}
@@ -63,8 +63,7 @@ int InfoBarContainerView::GetVerticalOverlap(int* total_height) {
for (int i = 0; i < child_count(); ++i) {
View* child = GetChildViewAt(i);
- gfx::Size ps = child->GetPreferredSize();
- next_child_y -= static_cast<InfoBarView*>(child)->AnimatedTabHeight();
+ next_child_y -= static_cast<InfoBarView*>(child)->tab_height();
vertical_overlap = std::max(vertical_overlap, -next_child_y);
next_child_y += child->GetPreferredSize().height();
}
diff --git a/chrome/browser/ui/views/infobars/infobar_container_view.h b/chrome/browser/ui/views/infobars/infobar_container_view.h
index 1348bf7..ffd695b 100644
--- a/chrome/browser/ui/views/infobars/infobar_container_view.h
+++ b/chrome/browser/ui/views/infobars/infobar_container_view.h
@@ -16,10 +16,7 @@ class InfoBarContainerView : public AccessiblePaneView,
explicit InfoBarContainerView(Delegate* delegate);
virtual ~InfoBarContainerView();
- // Overlap the previous view by this amount, vertically, so that the
- // first InfoBarView in this InfoBarContainer may draw its tab on
- // top.
- int VerticalOverlap();
+ virtual int GetVerticalOverlap() OVERRIDE;
private:
// AccessiblePaneView:
@@ -31,9 +28,9 @@ class InfoBarContainerView : public AccessiblePaneView,
virtual void PlatformSpecificAddInfoBar(InfoBar* infobar) OVERRIDE;
virtual void PlatformSpecificRemoveInfoBar(InfoBar* infobar) OVERRIDE;
- // Return the maximum vertical overlap of the InfoBarContainer's children,
- // and, when |total_height| is non-NULL, set the |*total_height| of the
- // InfoBarContainer.
+ // Return the amount by which to overlap the toolbar above, and, when
+ // |total_height| is non-NULL, set it to the height of the InfoBarContainer
+ // (including overlap).
int GetVerticalOverlap(int* total_height);
DISALLOW_COPY_AND_ASSIGN(InfoBarContainerView);
diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc
index 893dcc0..813d2ee 100644
--- a/chrome/browser/ui/views/infobars/infobar_view.cc
+++ b/chrome/browser/ui/views/infobars/infobar_view.cc
@@ -56,6 +56,8 @@ InfoBarView::InfoBarView(InfoBarDelegate* delegate)
close_button_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(delete_factory_(this)),
target_height_(kDefaultTargetHeight),
+ tab_height_(0),
+ bar_height_(0),
fill_path_(new SkPath),
stroke_path_(new SkPath) {
set_parent_owned(false); // InfoBar deletes itself at the appropriate time.
@@ -149,6 +151,53 @@ views::TextButton* InfoBarView::CreateTextButton(
}
void InfoBarView::Layout() {
+ // Calculate the fill and stroke paths. We do this here, rather than in
+ // PlatformSpecificRecalculateHeight(), because this is also reached when our
+ // width is changed, which affects both paths.
+ stroke_path_->rewind();
+ fill_path_->rewind();
+ if (tab_height_) {
+ int divider_y = tab_height_ - 1;
+ stroke_path_->moveTo(
+ SkIntToScalar(GetMirroredXWithWidthInView(0, kTabWidth)),
+ SkIntToScalar(divider_y));
+ stroke_path_->rCubicTo(
+ SkScalarDiv(kCurveWidth, 2), 0.0,
+ SkScalarDiv(kCurveWidth, 2),
+ SkIntToScalar(-divider_y),
+ SkIntToScalar(kCurveWidth),
+ SkIntToScalar(-divider_y));
+ stroke_path_->rLineTo(SkScalarMulAdd(kTabIconPadding, 2, kMaxIconWidth),
+ 0.0);
+ stroke_path_->rCubicTo(
+ SkScalarDiv(kCurveWidth, 2), 0.0,
+ SkScalarDiv(kCurveWidth, 2),
+ SkIntToScalar(divider_y),
+ SkIntToScalar(kCurveWidth),
+ SkIntToScalar(divider_y));
+
+ // Create the fill portion of the tab. Because the fill is inside the
+ // bounds and will not cover the separator, we need to extend downward by a
+ // pixel before closing.
+ *fill_path_ = *stroke_path_;
+ fill_path_->rLineTo(0.0, 1.0);
+ fill_path_->rLineTo(-SkIntToScalar(kTabWidth), 0.0);
+ fill_path_->close();
+
+ // Fill and stroke have different opinions about how to treat paths.
+ // Because in Skia integral coordinates represent pixel boundaries,
+ // offsetting the path makes it go exactly through pixel centers; this
+ // results in lines that are exactly where we expect, instead of having odd
+ // "off by one" issues. Were we to do this for |fill_path|, however, which
+ // tries to fill "inside" the path (using some questionable math), we'd get
+ // a fill at a very different place than we'd want.
+ stroke_path_->offset(SK_ScalarHalf, SK_ScalarHalf);
+ }
+ if (bar_height_) {
+ fill_path_->addRect(0.0, SkIntToScalar(tab_height_), SkIntToScalar(width()),
+ SkIntToScalar(height()));
+ }
+
int start_x = kHorizontalPadding;
if (icon_ != NULL) {
// Center the icon horizontally within the tab, and vertically between the
@@ -245,12 +294,9 @@ void InfoBarView::PaintChildren(gfx::Canvas* canvas) {
//
// gfx::CanvasSkia* canvas_skia = canvas->AsCanvasSkia();
// canvas_skia->clipPath(*fill_path_);
- int tab_height = AnimatedTabHeight();
- int bar_height = AnimatedBarHeight();
- DCHECK_EQ(tab_height + bar_height, height())
- << "Animation progressed between OnBoundsChanged & PaintChildren.";
- canvas->ClipRectInt(0, tab_height, width(), bar_height);
-
+ DCHECK_EQ(tab_height_ + bar_height_, height())
+ << "Infobar piecewise heights do not match overall height";
+ canvas->ClipRectInt(0, tab_height_, width(), bar_height_);
views::View::PaintChildren(canvas);
canvas->Restore();
}
@@ -268,6 +314,13 @@ int InfoBarView::ContentMinimumWidth() const {
return 0;
}
+void InfoBarView::SetTargetHeight(int height) {
+ if (target_height_ != height) {
+ target_height_ = height;
+ RecalculateHeight();
+ }
+}
+
int InfoBarView::StartX() const {
// Ensure we don't return a value greater than EndX(), so children can safely
// set something's width to "EndX() - StartX()" without risking that being
@@ -286,8 +339,7 @@ int InfoBarView::CenterY(const gfx::Size prefsize) const {
}
int InfoBarView::OffsetY(const gfx::Size prefsize) const {
- return CenterY(prefsize) + AnimatedTabHeight() -
- (target_height_ - AnimatedBarHeight());
+ return CenterY(prefsize) + tab_height_ - (target_height_ - bar_height_);
}
void InfoBarView::PlatformSpecificHide(bool animate) {
@@ -305,6 +357,22 @@ void InfoBarView::PlatformSpecificHide(bool animate) {
DestroyFocusTracker(restore_focus);
}
+void InfoBarView::PlatformSpecificRecalculateHeight() {
+ int old_tab_height = tab_height_;
+ int old_bar_height = bar_height_;
+ tab_height_ = static_cast<int>(kTabHeight * animation()->GetCurrentValue());
+ bar_height_ =
+ static_cast<int>(target_height_ * animation()->GetCurrentValue());
+
+ // Don't re-layout if nothing has changed, e.g. because the animation step was
+ // not large enough to actually change the heights by at least a pixel.
+ if ((old_tab_height != tab_height_) || (old_bar_height != bar_height_)) {
+ // Ensure that notifying our container of our size change will result in a
+ // re-layout.
+ InvalidateLayout();
+ }
+}
+
void InfoBarView::GetAccessibleState(ui::AccessibleViewState* state) {
if (delegate()) {
state->name = l10n_util::GetStringUTF16(
@@ -314,68 +382,8 @@ void InfoBarView::GetAccessibleState(ui::AccessibleViewState* state) {
state->role = ui::AccessibilityTypes::ROLE_ALERT;
}
-int InfoBarView::AnimatedTabHeight() const {
- return static_cast<int>(kTabHeight * animation()->GetCurrentValue());
-}
-
-int InfoBarView::AnimatedBarHeight() const {
- return static_cast<int>(target_height_ * animation()->GetCurrentValue());
-}
-
gfx::Size InfoBarView::GetPreferredSize() {
- return gfx::Size(0, AnimatedTabHeight() + AnimatedBarHeight());
-}
-
-void InfoBarView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
- int tab_height = AnimatedTabHeight();
- int bar_height = AnimatedBarHeight();
- int divider_y = tab_height - 1;
- DCHECK_EQ(tab_height + bar_height, height())
- << "Animation progressed between Layout & OnBoundsChanged.";
-
- int mirrored_x = GetMirroredXWithWidthInView(0, kTabWidth);
- stroke_path_->rewind();
- fill_path_->rewind();
-
- if (tab_height) {
- stroke_path_->moveTo(SkIntToScalar(mirrored_x),
- SkIntToScalar(divider_y));
- stroke_path_->rCubicTo(
- SkScalarDiv(kCurveWidth, 2), 0.0,
- SkScalarDiv(kCurveWidth, 2),
- SkIntToScalar(-divider_y),
- SkIntToScalar(kCurveWidth),
- SkIntToScalar(-divider_y));
- stroke_path_->rLineTo(SkScalarMulAdd(kTabIconPadding, 2, kMaxIconWidth),
- 0.0);
- stroke_path_->rCubicTo(
- SkScalarDiv(kCurveWidth, 2), 0.0,
- SkScalarDiv(kCurveWidth, 2),
- SkIntToScalar(divider_y),
- SkIntToScalar(kCurveWidth),
- SkIntToScalar(divider_y));
-
- // Create the fill portion of the tab. Because the fill is inside the
- // bounds and will not cover the separator, we need to extend downward by a
- // pixel before closing.
- *fill_path_ = *stroke_path_;
- fill_path_->rLineTo(0.0, 1.0);
- fill_path_->rLineTo(-SkIntToScalar(kTabWidth), 0.0);
- fill_path_->close();
-
- // Fill and stroke have different opinions about how to treat paths.
- // Because in Skia integral coordinates represent pixel boundaries,
- // offsetting the path makes it go exactly through pixel centers; this
- // results in lines that are exactly where we expect, instead of having odd
- // "off by one" issues. Were we to do this for |fill_path|, however, which
- // tries to fill "inside" the path (using some questionable math), we'd get
- // a fill at a very different place than we'd want.
- stroke_path_->offset(SK_ScalarHalf, SK_ScalarHalf);
- }
- if (bar_height) {
- fill_path_->addRect(0.0, SkIntToScalar(tab_height),
- SkIntToScalar(width()), SkIntToScalar(height()));
- }
+ return gfx::Size(0, tab_height_ + bar_height_);
}
void InfoBarView::FocusWillChange(View* focused_before, View* focused_now) {
diff --git a/chrome/browser/ui/views/infobars/infobar_view.h b/chrome/browser/ui/views/infobars/infobar_view.h
index 3b5f924..09835c2 100644
--- a/chrome/browser/ui/views/infobars/infobar_view.h
+++ b/chrome/browser/ui/views/infobars/infobar_view.h
@@ -35,7 +35,7 @@ class InfoBarView : public InfoBar,
SkPath* fill_path() const { return fill_path_.get(); }
SkPath* stroke_path() const { return stroke_path_.get(); }
- int AnimatedTabHeight() const;
+ int tab_height() const { return tab_height_; }
protected:
// The target height of the InfoBar, regardless of what its current height
@@ -80,7 +80,8 @@ class InfoBarView : public InfoBar,
// button from overlapping views that cannot be shrunk any further.
virtual int ContentMinimumWidth() const;
- void set_target_height(int height) { target_height_ = height; }
+ // Changes the target height of the main ("bar") portion of the infobar.
+ void SetTargetHeight(int height);
// These return x coordinates delimiting the usable area for subclasses to lay
// out their controls.
@@ -102,11 +103,11 @@ class InfoBarView : public InfoBar,
// InfoBar:
virtual void PlatformSpecificHide(bool animate) OVERRIDE;
+ virtual void PlatformSpecificRecalculateHeight() OVERRIDE;
// views::View:
virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
virtual gfx::Size GetPreferredSize() OVERRIDE;
- virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE;
// views::FocusChangeListener:
@@ -117,8 +118,6 @@ class InfoBarView : public InfoBar,
// |prefsize| within the standard InfoBar height. Stable during an animation.
int CenterY(const gfx::Size prefsize) const;
- int AnimatedBarHeight() const;
-
// Destroys the external focus tracker, if present. If |restore_focus| is
// true, restores focus to the view tracked by the focus tracker before doing
// so.
@@ -144,6 +143,12 @@ class InfoBarView : public InfoBar,
// The target height for the bar portion of the InfoBarView.
int target_height_;
+ // The current heights of the tab and bar portions.
+ int tab_height_;
+ int bar_height_;
+
+ // The paths for the InfoBarBackground to draw, sized according to the heights
+ // above.
scoped_ptr<SkPath> fill_path_;
scoped_ptr<SkPath> stroke_path_;