diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-26 22:00:37 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-26 22:00:37 +0000 |
commit | dcb3070302b8ee07a3d1dbfc290a84d325c7a6e3 (patch) | |
tree | c4f5942b02cb09f2a37dc96298bbb32d1858d421 | |
parent | a314ee5ab5322b95a861e38fdc377ec156b0add9 (diff) | |
download | chromium_src-dcb3070302b8ee07a3d1dbfc290a84d325c7a6e3.zip chromium_src-dcb3070302b8ee07a3d1dbfc290a84d325c7a6e3.tar.gz chromium_src-dcb3070302b8ee07a3d1dbfc290a84d325c7a6e3.tar.bz2 |
[gtk] spoof proof infobars, take 2
This looks like a big review, but a lot of it is just shuffling code around:
- rip out dropshadow code
- move arrow state and drawing to a model class, to allow sharing between BrowserWindow and Infobar
- get rid of InfoBar's border_bin_ and slightly simplify baseclasses by no longer requiring them to call show() on the toplevel widget
Added stuff:
- transition between arrow colors (previous_color_ vs. target_color_ business)
- arrows protruding on neighboring infobars
BUG=48996
TEST=manual, with animations slowed down 100x
Review URL: http://codereview.chromium.org/3919004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63956 0039d316-1c4b-4281-b951-d872f2087c98
25 files changed, 426 insertions, 317 deletions
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index 1dfc8f3..16c0f1a 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -81,8 +81,6 @@ #include "chrome/common/native_web_keyboard_event.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" -#include "gfx/canvas_skia_paint.h" -#include "gfx/color_utils.h" #include "gfx/gtk_util.h" #include "gfx/rect.h" #include "gfx/skia_utils_gtk.h" @@ -90,7 +88,6 @@ #include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" -#include "third_party/skia/include/effects/SkGradientShader.h" namespace { @@ -261,10 +258,6 @@ GdkCursorType GdkWindowEdgeToGdkCursorType(GdkWindowEdge edge) { return GDK_LAST_CURSOR; } -GdkColor SkColorToGdkColor(const SkColor& color) { - return gfx::SkColorToGdkColor(color); -} - // A helper method for setting the GtkWindow size that should be used in place // of calling gtk_window_resize directly. This is done to avoid a WM "feature" // where setting the window size to the monitor size causes the WM to set the @@ -345,7 +338,7 @@ BrowserWindowGtk::BrowserWindowGtk(Browser* browser) maximize_after_show_(false), suppress_window_raise_(false), accel_group_(NULL), - infobar_animation_(this) { + infobar_arrow_model_(this) { // We register first so that other views like the toolbar can use the // is_active() function in their ActiveWindowChanged() handlers. ActiveWindowWatcherX::AddObserver(this); @@ -389,8 +382,6 @@ BrowserWindowGtk::BrowserWindowGtk(Browser* browser) SetBackgroundColor(); HideUnsupportedWindowFeatures(); - infobar_animation_.SetTweenType(Tween::LINEAR); - registrar_.Add(this, NotificationType::BOOKMARK_BAR_VISIBILITY_PREF_CHANGED, NotificationService::AllSources()); } @@ -1680,7 +1671,7 @@ void BrowserWindowGtk::SetBackgroundColor() { SkColor frame_color = theme_provider->GetColor(frame_color_id); // Paint the frame color on the left, right and bottom. - GdkColor frame_color_gdk = SkColorToGdkColor(frame_color); + GdkColor frame_color_gdk = gfx::SkColorToGdkColor(frame_color); gtk_widget_modify_bg(GTK_WIDGET(window_), GTK_STATE_NORMAL, &frame_color_gdk); @@ -1692,7 +1683,8 @@ void BrowserWindowGtk::SetBackgroundColor() { // color, override the prelight also. color_utils::HSL hsl = { -1, 0.5, 0.65 }; SkColor frame_prelight_color = color_utils::HSLShift(frame_color, hsl); - GdkColor frame_prelight_color_gdk = SkColorToGdkColor(frame_prelight_color); + GdkColor frame_prelight_color_gdk = + gfx::SkColorToGdkColor(frame_prelight_color); gtk_widget_modify_bg(contents_split_, GTK_STATE_PRELIGHT, &frame_prelight_color_gdk); @@ -1798,179 +1790,74 @@ void BrowserWindowGtk::SaveWindowPosition() { window_preferences->SetInteger("work_area_bottom", work_area.bottom()); } -void BrowserWindowGtk::AnimationEnded(const Animation* animation) { - InvalidateInfoBarBits(); -} - -void BrowserWindowGtk::AnimationProgressed(const Animation* animation) { - InvalidateInfoBarBits(); -} - -void BrowserWindowGtk::AnimationCanceled(const Animation* animation) { - InvalidateInfoBarBits(); +void BrowserWindowGtk::SetInfoBarShowing(InfoBar* bar, bool animate) { + infobar_arrow_model_.ShowArrowFor(bar, animate); } -void BrowserWindowGtk::SetInfoBarShowing( - const std::pair<SkColor, SkColor>* colors, - bool animate) { - if (colors) { - infobar_colors_ = *colors; - - if (animate) - infobar_animation_.Show(); - else - infobar_animation_.Reset(1.0); - } else { - if (animate) - infobar_animation_.Hide(); - else - infobar_animation_.Reset(); - } - +void BrowserWindowGtk::PaintStateChanged() { InvalidateInfoBarBits(); } -bool BrowserWindowGtk::ShouldDrawInfobarDropShadowOnRenderView() { - return infobar_animation_.GetCurrentValue() != 0.0 && - !(bookmark_bar_.get() && bookmark_bar_is_floating_); -} - void BrowserWindowGtk::InvalidateInfoBarBits() { gtk_widget_queue_draw(toolbar_border_); gtk_widget_queue_draw(toolbar_->widget()); - if (bookmark_bar_.get()) + if (bookmark_bar_.get() && !bookmark_bar_is_floating_) gtk_widget_queue_draw(bookmark_bar_->widget()); +} - // Redraw the top bit of the render view area. - int width = contents_container_->widget()->allocation.width; - int height = gtk_util::kInfoBarDropShadowHeight; - gtk_widget_queue_draw_area(contents_container_->widget(), - 0, 0, width, height); +int BrowserWindowGtk::GetXPositionOfLocationIcon(GtkWidget* relative_to) { + GtkWidget* location_icon = toolbar_->GetLocationBarView()-> + location_icon_widget(); + int x = 0; + gtk_widget_translate_coordinates( + location_icon, relative_to, + (location_icon->allocation.width + 1) / 2, + 0, &x, NULL); + + if (GTK_WIDGET_NO_WINDOW(relative_to)) + x += relative_to->allocation.x; + + return x; } gboolean BrowserWindowGtk::OnExposeDrawInfobarBits(GtkWidget* sender, GdkEventExpose* expose) { - double alpha = infobar_animation_.GetCurrentValue(); - if (alpha == 0.0) + if (!infobar_arrow_model_.NeedToDrawInfoBarArrow()) return FALSE; - GtkWidget* location_icon = toolbar_->GetLocationBarView()-> - location_icon_widget(); - int x = 0; - int top_y = 0; - // The offset between the vertical center of the location icon and the top - // of the arrow. - const int kArrowVerticalOffset = 4; - gtk_widget_translate_coordinates( - location_icon, sender, - location_icon->allocation.width / 2, - location_icon->allocation.height / 2 + kArrowVerticalOffset, - &x, &top_y); + int x = GetXPositionOfLocationIcon(sender); gfx::Rect toolbar_border(toolbar_border_->allocation); int y = 0; gtk_widget_translate_coordinates(toolbar_border_, sender, 0, toolbar_border.bottom(), NULL, &y); - - int arrow_height = y - top_y; - // The width of half the arrow. - const int kArrowWidth = 15; - - if (GTK_WIDGET_NO_WINDOW(sender)) { - x += sender->allocation.x; + if (GTK_WIDGET_NO_WINDOW(sender)) y += sender->allocation.y; - } - - SkPath path; - path.moveTo(SkPoint::Make(x - kArrowWidth, y)); - path.lineTo(SkPoint::Make(x, y - arrow_height)); - path.lineTo(SkPoint::Make(x + kArrowWidth, y)); - path.close(); - - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - - SkPoint grad_points[2]; - grad_points[0].set(SkIntToScalar(0), SkIntToScalar(y)); - grad_points[1].set(SkIntToScalar(0), - SkIntToScalar(y + InfoBar::kInfoBarHeight)); - - SkColor grad_colors[2]; - grad_colors[0] = SkColorSetA(infobar_colors_.first, alpha * 0xff); - grad_colors[1] = SkColorSetA(infobar_colors_.second, alpha * 0xff); - - SkShader* gradient_shader = SkGradientShader::CreateLinear( - grad_points, grad_colors, NULL, 2, SkShader::kMirror_TileMode); - paint.setShader(gradient_shader); - gradient_shader->unref(); - - gfx::CanvasSkiaPaint canvas(expose, false); - canvas.drawPath(path, paint); - - paint.setShader(NULL); - paint.setStyle(SkPaint::kStroke_Style); - // Smooth out the shadow. - paint.setAntiAlias(true); - - const int kMaxShading = 100; - const int kShadingPixels = 5; - - // The goal of all this mathematical trickery is to create a shadow for the - // arrow that looks decent. We want a shadow of a set width, and the thickest - // direction of that shadow needs to be perpendicular to the sides of the - // arrow. - double scale_factor = sqrt(static_cast<double>( - (arrow_height * arrow_height + kArrowWidth * kArrowWidth))) / - kShadingPixels; - double x_scale = arrow_height / scale_factor / kShadingPixels; - double y_scale = kArrowWidth / scale_factor / kShadingPixels; - for (int i = 1; i <= kShadingPixels; ++i) { - double x_backoff = x_scale * i; - double y_backoff = y_scale * i; - SkPath shadow_path; - shadow_path.moveTo(0, y - i); - // The +1 below makes sure the shadow hugs the left side of the arrow. - shadow_path.rLineTo(x - kArrowWidth - x_backoff + 1, 0); - shadow_path.rMoveTo(0, i - y_backoff); - shadow_path.rLineTo(kArrowWidth, -arrow_height); - // The -1.5 below makes sure the shadow hugs the right side of the arrow. - shadow_path.rLineTo(2 * x_backoff - 1.5, 0); - shadow_path.rLineTo(kArrowWidth, arrow_height); - shadow_path.rMoveTo(0, y_backoff - i); - shadow_path.rLineTo(sender->allocation.width, 0); - - int shading = (kShadingPixels - i + 1) * kMaxShading / kShadingPixels; - paint.setColor(SkColorSetARGB(alpha * shading, 0, 0, 0)); - canvas.drawPath(shadow_path, paint); - } + Profile* profile = browser()->profile(); + infobar_arrow_model_.Paint( + sender, expose, gfx::Point(x, y), + GtkThemeProvider::GetFrom(profile)->GetBorderColor()); return FALSE; } gboolean BrowserWindowGtk::OnBookmarkBarExpose(GtkWidget* sender, GdkEventExpose* expose) { - if (infobar_animation_.GetCurrentValue() == 0.0) + if (!infobar_arrow_model_.NeedToDrawInfoBarArrow()) return FALSE; - // This shares the same draw path as the other widgets when it's not floating. - if (!bookmark_bar_is_floating_) - return OnExposeDrawInfobarBits(sender, expose); + if (bookmark_bar_is_floating_) + return FALSE; - gfx::Point origin; - if (GTK_WIDGET_NO_WINDOW(sender)) - origin = gfx::Point(sender->allocation.x, sender->allocation.y); - cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(expose->window)); - gtk_util::DrawTopDropShadowForRenderView(cr, origin, gfx::Rect(expose->area)); - cairo_destroy(cr); - return FALSE; + return OnExposeDrawInfobarBits(sender, expose); } void BrowserWindowGtk::OnBookmarkBarSizeAllocate(GtkWidget* sender, GtkAllocation* allocation) { // The size of the bookmark bar affects how the infobar arrow is drawn on // the toolbar. - if (infobar_animation_.GetCurrentValue() != 0.0) + if (infobar_arrow_model_.NeedToDrawInfoBarArrow()) gtk_widget_queue_draw(toolbar_->widget()); } diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index ce6fd20..ce8e582 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -12,12 +12,12 @@ #include "app/active_window_watcher_x.h" #include "app/gtk_signal.h" -#include "app/slide_animation.h" #include "app/x11_util.h" #include "base/scoped_ptr.h" #include "base/timer.h" #include "build/build_config.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/gtk/infobar_arrow_model.h" #include "chrome/browser/prefs/pref_member.h" #include "chrome/browser/tabs/tab_strip_model_observer.h" #include "chrome/common/notification_registrar.h" @@ -45,7 +45,7 @@ class BrowserWindowGtk : public BrowserWindow, public NotificationObserver, public TabStripModelObserver, public ActiveWindowWatcherX::Observer, - public AnimationDelegate { + public InfoBarArrowModel::Observer { public: explicit BrowserWindowGtk(Browser* browser); virtual ~BrowserWindowGtk(); @@ -145,10 +145,8 @@ class BrowserWindowGtk : public BrowserWindow, // Overridden from ActiveWindowWatcher::Observer. virtual void ActiveWindowChanged(GdkWindow* active_window); - // Overridden from AnimationDelegate. - virtual void AnimationEnded(const Animation* animation); - virtual void AnimationProgressed(const Animation* animation); - virtual void AnimationCanceled(const Animation* animation); + // Overridden from InfoBarArrowModel::Observer. + virtual void PaintStateChanged(); // Accessor for the tab strip. TabStripGtk* tabstrip() const { return tabstrip_.get(); } @@ -178,16 +176,9 @@ class BrowserWindowGtk : public BrowserWindow, // else for the custom frame. void ResetCustomFrameCursor(); - // Toggles whether an infobar is showing. If |colors| is NULL, then no infobar - // is showing. When non-NULL, |colors| describes the gradient stop colors for - // the showing infobar. - // |animate| controls whether we animate to the new state set by |colors|. - void SetInfoBarShowing(const std::pair<SkColor, SkColor>* colors, - bool animate); - - // Called by the RenderViewHostDelegate::View (TabContentsViewGtk in our case) - // to decide whether to draw a drop shadow on the render view. - bool ShouldDrawInfobarDropShadowOnRenderView(); + // Toggles whether an infobar is showing. + // |animate| controls whether we animate to the new state set by |bar|. + void SetInfoBarShowing(InfoBar* bar, bool animate); // Returns the BrowserWindowGtk registered with |window|. static BrowserWindowGtk* GetBrowserWindowForNativeWindow( @@ -221,6 +212,10 @@ class BrowserWindowGtk : public BrowserWindow, // redraw when it should. void QueueToolbarRedraw(); + // Get the position where the infobar arrow should be anchored in + // |relative_to| coordinates. This is the middle of the omnibox location icon. + int GetXPositionOfLocationIcon(GtkWidget* relative_to); + protected: virtual void DestroyBrowser(); // Top level window. @@ -480,11 +475,9 @@ class BrowserWindowGtk : public BrowserWindow, scoped_ptr<FullscreenExitBubbleGtk> fullscreen_exit_bubble_; - // The top and bottom colors for the infobar gradient, if there is an - // infobar showing. - std::pair<SkColor, SkColor> infobar_colors_; - - SlideAnimation infobar_animation_; + // The model that tracks the paint state of the arrow for the infobar + // directly below the toolbar. + InfoBarArrowModel infobar_arrow_model_; DISALLOW_COPY_AND_ASSIGN(BrowserWindowGtk); }; diff --git a/chrome/browser/gtk/extension_infobar_gtk.cc b/chrome/browser/gtk/extension_infobar_gtk.cc index 7140afc..b7355b1 100644 --- a/chrome/browser/gtk/extension_infobar_gtk.cc +++ b/chrome/browser/gtk/extension_infobar_gtk.cc @@ -66,7 +66,6 @@ void ExtensionInfoBarGtk::BuildWidgets() { g_signal_connect(view_->native_view(), "size_allocate", G_CALLBACK(&OnSizeAllocateThunk), this); - gtk_widget_show_all(border_bin_.get()); } void ExtensionInfoBarGtk::OnSizeAllocate(GtkWidget* widget, diff --git a/chrome/browser/gtk/gtk_util.cc b/chrome/browser/gtk/gtk_util.cc index babed07..005c3b9 100644 --- a/chrome/browser/gtk/gtk_util.cc +++ b/chrome/browser/gtk/gtk_util.cc @@ -1136,25 +1136,4 @@ WebDragOperationsMask GdkDragActionToWebDragOp(GdkDragAction action) { return op; } -void DrawTopDropShadowForRenderView(cairo_t* cr, const gfx::Point& origin, - const gfx::Rect& paint_rect) { - gfx::Rect shadow_rect(paint_rect.x(), origin.y(), - paint_rect.width(), kInfoBarDropShadowHeight); - - // Avoid this extra work if we can. - if (!shadow_rect.Intersects(paint_rect)) - return; - - cairo_pattern_t* shadow = - cairo_pattern_create_linear(0.0, shadow_rect.y(), - 0.0, shadow_rect.bottom()); - cairo_pattern_add_color_stop_rgba(shadow, 0, 0, 0, 0, 0.6); - cairo_pattern_add_color_stop_rgba(shadow, 1, 0, 0, 0, 0.1); - cairo_rectangle(cr, shadow_rect.x(), shadow_rect.y(), - shadow_rect.width(), shadow_rect.height()); - cairo_set_source(cr, shadow); - cairo_fill(cr); - cairo_pattern_destroy(shadow); -} - } // namespace gtk_util diff --git a/chrome/browser/gtk/gtk_util.h b/chrome/browser/gtk/gtk_util.h index 466ba7e..0ecafee 100644 --- a/chrome/browser/gtk/gtk_util.h +++ b/chrome/browser/gtk/gtk_util.h @@ -57,9 +57,6 @@ const int kContentAreaSpacing = 18; // Horizontal Spacing between controls in a form. const int kFormControlSpacing = 10; -// Height for the infobar drop shadow. -const int kInfoBarDropShadowHeight = 6; - // Create a table of labeled controls, using proper spacing and alignment. // Arguments should be pairs of const char*, GtkWidget*, concluding with a // NULL. The first argument is a vector in which to place all labels @@ -344,11 +341,6 @@ void InitLabelSizeRequestAndEllipsizeMode(GtkWidget* label); GdkDragAction WebDragOpToGdkDragAction(WebKit::WebDragOperationsMask op); WebKit::WebDragOperationsMask GdkDragActionToWebDragOp(GdkDragAction action); -// Code to draw the drop shadow below an infobar (at the top of the render -// view). -void DrawTopDropShadowForRenderView(cairo_t* cr, const gfx::Point& origin, - const gfx::Rect& paint_rect); - } // namespace gtk_util #endif // CHROME_BROWSER_GTK_GTK_UTIL_H_ diff --git a/chrome/browser/gtk/infobar_arrow_model.cc b/chrome/browser/gtk/infobar_arrow_model.cc new file mode 100644 index 0000000..e66bb02 --- /dev/null +++ b/chrome/browser/gtk/infobar_arrow_model.cc @@ -0,0 +1,124 @@ +// Copyright (c) 2010 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. + +#include "chrome/browser/gtk/infobar_arrow_model.h" + +#include "chrome/browser/gtk/infobar_gtk.h" +#include "gfx/canvas_skia_paint.h" +#include "gfx/color_utils.h" +#include "gfx/point.h" +#include "gfx/skia_utils_gtk.h" +#include "third_party/skia/include/effects/SkGradientShader.h" + +InfoBarArrowModel::InfoBarArrowModel(Observer* observer) + : observer_(observer), + animation_(this) { + animation_.SetTweenType(Tween::LINEAR); + animation_.Reset(1.0); + target_colors_.top = target_colors_.bottom = SkColorSetARGB(0, 0, 0, 0); + previous_colors_ = target_colors_; +} + +InfoBarArrowModel::~InfoBarArrowModel() { +} + +InfoBarArrowModel::InfoBarColors InfoBarArrowModel::CurrentInfoBarColors() { + double alpha = animation_.GetCurrentValue(); + InfoBarColors colors = { + color_utils::AlphaBlend(target_colors_.top, + previous_colors_.top, + alpha * 0xff), + color_utils::AlphaBlend(target_colors_.bottom, + previous_colors_.bottom, + alpha * 0xff)}; + return colors; +} + +bool InfoBarArrowModel::NeedToDrawInfoBarArrow() { + return SkColorGetA(CurrentInfoBarColors().top) != 0; +} + +void InfoBarArrowModel::ShowArrowFor(InfoBar* bar, bool animate) { + scoped_ptr<std::pair<SkColor, SkColor> > colors; + + previous_colors_ = CurrentInfoBarColors(); + + if (bar) { + double r, g, b; + bar->GetTopColor(bar->delegate()->GetInfoBarType(), &r, &g, &b); + target_colors_.top = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff); + bar->GetBottomColor(bar->delegate()->GetInfoBarType(), &r, &g, &b); + target_colors_.bottom = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff); + } else { + target_colors_.bottom = target_colors_.top = SkColorSetARGB(0, 0, 0, 0); + } + + if (animate) { + // Fade from the current color to the target color. + animation_.Reset(); + animation_.Show(); + } else { + // Skip straight to showing the target color. + animation_.Reset(1.0); + } + + observer_->PaintStateChanged(); +} + +void InfoBarArrowModel::Paint(GtkWidget* widget, + GdkEventExpose* expose, + const gfx::Point& origin, + const GdkColor& border_color) { + if (!NeedToDrawInfoBarArrow()) + return; + + // The size of the arrow (its height; also half its width). + const int kArrowSize = 10; + + SkPath path; + path.moveTo(SkPoint::Make(origin.x() - kArrowSize, origin.y())); + path.rLineTo(kArrowSize, -kArrowSize); + path.rLineTo(kArrowSize, kArrowSize); + path.close(); + + SkPaint paint; + paint.setStrokeWidth(1); + paint.setStyle(SkPaint::kFill_Style); + + SkPoint grad_points[2]; + grad_points[0].set(SkIntToScalar(0), SkIntToScalar(origin.y())); + grad_points[1].set(SkIntToScalar(0), + SkIntToScalar(origin.y() + InfoBar::kInfoBarHeight)); + + InfoBarColors colors = CurrentInfoBarColors(); + SkColor grad_colors[2]; + grad_colors[0] = colors.top; + grad_colors[1] = colors.bottom; + + SkShader* gradient_shader = SkGradientShader::CreateLinear( + grad_points, grad_colors, NULL, 2, SkShader::kMirror_TileMode); + paint.setShader(gradient_shader); + gradient_shader->unref(); + + gfx::CanvasSkiaPaint canvas(expose, false); + canvas.drawPath(path, paint); + + paint.setShader(NULL); + paint.setColor(SkColorSetA(gfx::GdkColorToSkColor(border_color), + SkColorGetA(colors.top))); + paint.setStyle(SkPaint::kStroke_Style); + canvas.drawPath(path, paint); +} + +void InfoBarArrowModel::AnimationEnded(const Animation* animation) { + observer_->PaintStateChanged(); +} + +void InfoBarArrowModel::AnimationProgressed(const Animation* animation) { + observer_->PaintStateChanged(); +} + +void InfoBarArrowModel::AnimationCanceled(const Animation* animation) { + observer_->PaintStateChanged(); +} diff --git a/chrome/browser/gtk/infobar_arrow_model.h b/chrome/browser/gtk/infobar_arrow_model.h new file mode 100644 index 0000000..369e586 --- /dev/null +++ b/chrome/browser/gtk/infobar_arrow_model.h @@ -0,0 +1,77 @@ +// Copyright (c) 2010 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. + +#ifndef CHROME_BROWSER_GTK_INFOBAR_ARROW_MODEL_H_ +#define CHROME_BROWSER_GTK_INFOBAR_ARROW_MODEL_H_ + +#include <gtk/gtk.h> + +#include "app/slide_animation.h" +#include "third_party/skia/include/core/SkPaint.h" + +namespace gfx { +class Point; +} + +class InfoBar; + +// A helper class that tracks the state of an infobar arrow and provides a +// utility to draw it. +class InfoBarArrowModel : public AnimationDelegate { + public: + class Observer { + public: + // The arrow has changed states; relevant widgets need to be repainted. + virtual void PaintStateChanged() = 0; + }; + + explicit InfoBarArrowModel(Observer* observer); + virtual ~InfoBarArrowModel(); + + // An infobar has been added or removed that will affect the state of this + // arrow. + void ShowArrowFor(InfoBar* bar, bool animate); + + // Returns true if the arrow is showing at all. + bool NeedToDrawInfoBarArrow(); + + // Paints the arrow on |widget|, in response to |expose|, with the bottom + // center of the arrow at |origin|, drawing a border with |border_color|. + void Paint(GtkWidget* widget, + GdkEventExpose* expose, + const gfx::Point& origin, + const GdkColor& border_color); + + // Overridden from AnimationDelegate. + virtual void AnimationEnded(const Animation* animation); + virtual void AnimationProgressed(const Animation* animation); + virtual void AnimationCanceled(const Animation* animation); + + private: + // A pair of colors used to draw a gradient for an arrow. + struct InfoBarColors { + SkColor top; + SkColor bottom; + }; + + // Calculates the currently showing arrow color, which is a blend of the new + // arrow color and the old arrow color. + InfoBarColors CurrentInfoBarColors(); + + // The view that owns us. + Observer* observer_; + + // An animation that tracks the progress of the transition from the last color + // to the new color. + SlideAnimation animation_; + + // The color we are animating towards. + InfoBarColors target_colors_; + // The last color we showed (the one we are animating away from). + InfoBarColors previous_colors_; + + DISALLOW_COPY_AND_ASSIGN(InfoBarArrowModel); +}; + +#endif // CHROME_BROWSER_GTK_INFOBAR_ARROW_MODEL_H_ diff --git a/chrome/browser/gtk/infobar_container_gtk.cc b/chrome/browser/gtk/infobar_container_gtk.cc index 01c6ccc..b53a995 100644 --- a/chrome/browser/gtk/infobar_container_gtk.cc +++ b/chrome/browser/gtk/infobar_container_gtk.cc @@ -143,6 +143,41 @@ void InfoBarContainerGtk::UpdateInfoBars() { } } +void InfoBarContainerGtk::ShowArrowForDelegate(InfoBarDelegate* delegate, + bool animate) { + if (!CommandLine::ForCurrentProcess()-> + HasSwitch(switches::kEnableSecureInfoBars)) { + return; + } + + GList* children = gtk_container_get_children(GTK_CONTAINER(widget())); + if (!children) + return; + + // Iterate through the infobars and find the last one that isn't closing. + InfoBar* last_bar = NULL; + InfoBar* this_bar = NULL; + for (GList* iter = children; iter != NULL; iter = iter->next) { + this_bar = reinterpret_cast<InfoBar*>( + g_object_get_data(G_OBJECT(iter->data), kInfoBar)); + + if (this_bar->delegate() == delegate) + break; + + if (!this_bar->IsClosing()) + last_bar = this_bar; + + this_bar = NULL; + } + + if (last_bar) + last_bar->ShowArrowFor(this_bar, animate); + else + UpdateToolbarInfoBarState(this_bar, animate); + + g_list_free(children); +} + void InfoBarContainerGtk::AddInfoBar(InfoBarDelegate* delegate, bool animate) { InfoBar* infobar = delegate->CreateInfoBar(); infobar->set_container(this); @@ -155,8 +190,7 @@ void InfoBarContainerGtk::AddInfoBar(InfoBarDelegate* delegate, bool animate) { else infobar->Open(); - if (tab_contents_->GetInfoBarDelegateAt(0) == delegate) - UpdateToolbarInfoBarState(infobar, animate); + ShowArrowForDelegate(delegate, animate); } void InfoBarContainerGtk::RemoveInfoBar(InfoBarDelegate* delegate, @@ -169,21 +203,15 @@ void InfoBarContainerGtk::RemoveInfoBar(InfoBarDelegate* delegate, delegate); } - if (tab_contents_->GetInfoBarDelegateAt(0) == delegate) { - InfoBar* bar = NULL; - // Get the next infobar, if it exists, so we can change the color of the - // arrow to it. - GList* children = gtk_container_get_children(GTK_CONTAINER(widget())); - if (children) { - if (children->next) { - bar = reinterpret_cast<InfoBar*>( - g_object_get_data(G_OBJECT(children->next->data), kInfoBar)); - } - g_list_free(children); + InfoBarDelegate* next_delegate = NULL; + for (int i = 1; i < tab_contents_->infobar_delegate_count(); ++i) { + if (tab_contents_->GetInfoBarDelegateAt(i - 1) == delegate) { + next_delegate = tab_contents_->GetInfoBarDelegateAt(i); + break; } - - UpdateToolbarInfoBarState(bar, animate); } + + ShowArrowForDelegate(next_delegate, animate); } void InfoBarContainerGtk::UpdateToolbarInfoBarState( @@ -193,21 +221,9 @@ void InfoBarContainerGtk::UpdateToolbarInfoBarState( return; } - scoped_ptr<std::pair<SkColor, SkColor> > colors; - - if (infobar) { - double r, g, b; - infobar->GetTopColor(infobar->delegate()->GetInfoBarType(), &r, &g, &b); - SkColor top = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff); - infobar->GetBottomColor(infobar->delegate()->GetInfoBarType(), &r, &g, &b); - SkColor bottom = SkColorSetRGB(r * 0xff, g * 0xff, b * 0xff); - - colors.reset(new std::pair<SkColor, SkColor>(top, bottom)); - } - GtkWindow* parent = platform_util::GetTopLevel(widget()); BrowserWindowGtk* browser_window = BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent); if (browser_window) - browser_window->SetInfoBarShowing(colors.get(), animate); + browser_window->SetInfoBarShowing(infobar, animate); } diff --git a/chrome/browser/gtk/infobar_container_gtk.h b/chrome/browser/gtk/infobar_container_gtk.h index cb81580..ba676a9 100644 --- a/chrome/browser/gtk/infobar_container_gtk.h +++ b/chrome/browser/gtk/infobar_container_gtk.h @@ -51,6 +51,10 @@ class InfoBarContainerGtk : public NotificationObserver { // this process. void UpdateInfoBars(); + // Makes the calls to show an arrow for |delegate| (either on the browser + // toolbar or on the next infobar up). + void ShowArrowForDelegate(InfoBarDelegate* delegate, bool animate); + // Adds an InfoBar for the specified delegate, in response to a notification // from the selected TabContents. void AddInfoBar(InfoBarDelegate* delegate, bool animate); diff --git a/chrome/browser/gtk/infobar_gtk.cc b/chrome/browser/gtk/infobar_gtk.cc index ce420ac..a512237 100644 --- a/chrome/browser/gtk/infobar_gtk.cc +++ b/chrome/browser/gtk/infobar_gtk.cc @@ -7,12 +7,14 @@ #include <gtk/gtk.h> #include "base/utf_string_conversions.h" +#include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/gtk_chrome_link_button.h" #include "chrome/browser/gtk/gtk_chrome_shrinkable_hbox.h" #include "chrome/browser/gtk/gtk_theme_provider.h" #include "chrome/browser/gtk/gtk_util.h" #include "chrome/browser/gtk/infobar_container_gtk.h" +#include "chrome/browser/platform_util.h" #include "chrome/common/notification_service.h" #include "gfx/gtk_util.h" @@ -37,7 +39,8 @@ const int kRightPadding = 5; InfoBar::InfoBar(InfoBarDelegate* delegate) : container_(NULL), delegate_(delegate), - theme_provider_(NULL) { + theme_provider_(NULL), + arrow_model_(this) { // Create |hbox_| and pad the sides. hbox_ = gtk_hbox_new(FALSE, kElementPadding); @@ -48,17 +51,13 @@ InfoBar::InfoBar(InfoBarDelegate* delegate) gtk_alignment_set_padding(GTK_ALIGNMENT(padding), 0, 0, kLeftPadding, kRightPadding); - GtkWidget* bg_box = gtk_event_box_new(); - gtk_widget_set_app_paintable(bg_box, TRUE); - g_signal_connect(bg_box, "expose-event", + bg_box_ = gtk_event_box_new(); + gtk_widget_set_app_paintable(bg_box_, TRUE); + g_signal_connect(bg_box_, "expose-event", G_CALLBACK(OnBackgroundExposeThunk), this); gtk_container_add(GTK_CONTAINER(padding), hbox_); - gtk_container_add(GTK_CONTAINER(bg_box), padding); - // The -1 on the kInfoBarHeight is to account for the border. - gtk_widget_set_size_request(bg_box, -1, kInfoBarHeight - 1); - - border_bin_.Own(gtk_util::CreateGtkBorderBin(bg_box, NULL, - 0, 1, 0, 0)); + gtk_container_add(GTK_CONTAINER(bg_box_), padding); + gtk_widget_set_size_request(bg_box_, -1, kInfoBarHeight); // Add the icon on the left, if any. SkBitmap* icon = delegate->GetIcon(); @@ -69,13 +68,12 @@ InfoBar::InfoBar(InfoBarDelegate* delegate) gtk_box_pack_start(GTK_BOX(hbox_), image, FALSE, FALSE, 0); } - // TODO(erg): GTK theme the info bar. close_button_.reset(CustomDrawButton::CloseButton(NULL)); gtk_util::CenterWidgetInHBox(hbox_, close_button_->widget(), true, 0); g_signal_connect(close_button_->widget(), "clicked", G_CALLBACK(OnCloseButtonThunk), this); - slide_widget_.reset(new SlideAnimatorGtk(border_bin_.get(), + slide_widget_.reset(new SlideAnimatorGtk(bg_box_, SlideAnimatorGtk::DOWN, 0, true, true, this)); // We store a pointer back to |this| so we can refer to it from the infobar @@ -84,7 +82,6 @@ InfoBar::InfoBar(InfoBarDelegate* delegate) } InfoBar::~InfoBar() { - border_bin_.Destroy(); } GtkWidget* InfoBar::widget() { @@ -93,14 +90,18 @@ GtkWidget* InfoBar::widget() { void InfoBar::AnimateOpen() { slide_widget_->Open(); - if (border_bin_->window) - gdk_window_lower(border_bin_->window); + + gtk_widget_show_all(bg_box_); + if (bg_box_->window) + gdk_window_lower(bg_box_->window); } void InfoBar::Open() { slide_widget_->OpenWithoutAnimation(); - if (border_bin_->window) - gdk_window_lower(border_bin_->window); + + gtk_widget_show_all(bg_box_); + if (bg_box_->window) + gdk_window_lower(bg_box_->window); } void InfoBar::AnimateClose() { @@ -119,6 +120,18 @@ bool InfoBar::IsAnimating() { return slide_widget_->IsAnimating(); } +bool InfoBar::IsClosing() { + return slide_widget_->IsClosing(); +} + +void InfoBar::ShowArrowFor(InfoBar* other, bool animate) { + arrow_model_.ShowArrowFor(other, animate); +} + +void InfoBar::PaintStateChanged() { + gtk_widget_queue_draw(widget()); +} + void InfoBar::RemoveInfoBar() const { container_->RemoveDelegate(delegate_); } @@ -253,8 +266,7 @@ void InfoBar::GetBottomColor(InfoBarDelegate::Type type, } void InfoBar::UpdateBorderColor() { - GdkColor border_color = theme_provider_->GetBorderColor(); - gtk_widget_modify_bg(border_bin_.get(), GTK_STATE_NORMAL, &border_color); + gtk_widget_queue_draw(widget()); } void InfoBar::OnCloseButton(GtkWidget* button) { @@ -263,11 +275,11 @@ void InfoBar::OnCloseButton(GtkWidget* button) { RemoveInfoBar(); } -gboolean InfoBar::OnBackgroundExpose(GtkWidget* widget, +gboolean InfoBar::OnBackgroundExpose(GtkWidget* sender, GdkEventExpose* event) { - const int height = widget->allocation.height; + const int height = sender->allocation.height; - cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(widget->window)); + cairo_t* cr = gdk_cairo_create(GDK_DRAWABLE(sender->window)); gdk_cairo_rectangle(cr, &event->area); cairo_clip(cr); @@ -285,8 +297,30 @@ gboolean InfoBar::OnBackgroundExpose(GtkWidget* widget, cairo_paint(cr); cairo_pattern_destroy(pattern); + // Draw the bottom border. + GdkColor border_color = theme_provider_->GetBorderColor(); + cairo_set_source_rgb(cr, border_color.red / 65535.0, + border_color.green / 65535.0, + border_color.blue / 65535.0); + cairo_set_line_width(cr, 1.0); + int y = sender->allocation.height; + cairo_move_to(cr, 0, y - 0.5); + cairo_rel_line_to(cr, sender->allocation.width, 0); + cairo_stroke(cr); + cairo_destroy(cr); + if (!arrow_model_.NeedToDrawInfoBarArrow()) + return FALSE; + + GtkWindow* parent = platform_util::GetTopLevel(widget()); + BrowserWindowGtk* browser_window = + BrowserWindowGtk::GetBrowserWindowForNativeWindow(parent); + int x = browser_window ? + browser_window->GetXPositionOfLocationIcon(sender) : 0; + + arrow_model_.Paint(sender, event, gfx::Point(x, y), border_color); + return FALSE; } @@ -297,7 +331,6 @@ class AlertInfoBar : public InfoBar { explicit AlertInfoBar(AlertInfoBarDelegate* delegate) : InfoBar(delegate) { AddLabelAndLink(delegate->GetMessageText(), string16(), NULL); - gtk_widget_show_all(border_bin_.get()); } }; @@ -312,7 +345,6 @@ class LinkInfoBar : public InfoBar { string16 link_text = delegate->GetLinkText(); AddLabelWithInlineLink(display_text, link_text, link_offset, G_CALLBACK(OnLinkClick)); - gtk_widget_show_all(border_bin_.get()); } private: @@ -371,8 +403,6 @@ ConfirmInfoBar::ConfirmInfoBar(ConfirmInfoBarDelegate* delegate) // 13.4px == 10pt @ 96dpi gtk_util::ForceFontSizePixels(GTK_CHROME_LINK_BUTTON(link)->label, 13.4); gtk_util::CenterWidgetInHBox(hbox_, link, true, kEndOfLabelSpacing); - - gtk_widget_show_all(border_bin_.get()); } void ConfirmInfoBar::AddButton(ConfirmInfoBarDelegate::InfoBarButton type) { diff --git a/chrome/browser/gtk/infobar_gtk.h b/chrome/browser/gtk/infobar_gtk.h index 5589f9e..4293ea8 100644 --- a/chrome/browser/gtk/infobar_gtk.h +++ b/chrome/browser/gtk/infobar_gtk.h @@ -7,13 +7,16 @@ #pragma once #include "app/gtk_signal.h" +#include "app/slide_animation.h" #include "base/basictypes.h" #include "base/scoped_ptr.h" +#include "chrome/browser/gtk/infobar_arrow_model.h" #include "chrome/browser/gtk/owned_widget_gtk.h" #include "chrome/browser/gtk/slide_animator_gtk.h" #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" +#include "third_party/skia/include/core/SkPaint.h" class CustomDrawButton; class GtkThemeProvider; @@ -21,7 +24,8 @@ class InfoBarContainerGtk; class InfoBarDelegate; class InfoBar : public SlideAnimatorGtk::Delegate, - public NotificationObserver { + public NotificationObserver, + public InfoBarArrowModel::Observer { public: explicit InfoBar(InfoBarDelegate* delegate); virtual ~InfoBar(); @@ -53,12 +57,22 @@ class InfoBar : public SlideAnimatorGtk::Delegate, // Returns true if the infobar is showing the its open or close animation. bool IsAnimating(); + // Returns true if the infobar is showing the close animation. + bool IsClosing(); + void SetThemeProvider(GtkThemeProvider* theme_provider); + // Show an arrow that originates from another infobar (i.e. a bar was added + // below this one). If |other| is NULL, stop showing the arrow. + void ShowArrowFor(InfoBar* other, bool animate); + + // InfoBarArrowModel::Observer implementation. + virtual void PaintStateChanged(); + // SlideAnimatorGtk::Delegate implementation. virtual void Closed(); - // NotificationOPbserver implementation. + // NotificationObserver implementation. virtual void Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details); @@ -95,8 +109,8 @@ class InfoBar : public SlideAnimatorGtk::Delegate, // The top level widget of the infobar. scoped_ptr<SlideAnimatorGtk> slide_widget_; - // The second highest level widget of the infobar. - OwnedWidgetGtk border_bin_; + // The second highest widget in the hierarchy (after the slide widget). + GtkWidget* bg_box_; // The hbox that holds infobar elements (button, text, icon, etc.). GtkWidget* hbox_; @@ -113,6 +127,10 @@ class InfoBar : public SlideAnimatorGtk::Delegate, // The theme provider, used for getting border colors. GtkThemeProvider* theme_provider_; + // The model that tracks the paint state of the arrow for the infobar + // below this one (if it exists). + InfoBarArrowModel arrow_model_; + NotificationRegistrar registrar_; private: diff --git a/chrome/browser/gtk/translate/after_translate_infobar_gtk.cc b/chrome/browser/gtk/translate/after_translate_infobar_gtk.cc index 6fefadd..914f2ca 100644 --- a/chrome/browser/gtk/translate/after_translate_infobar_gtk.cc +++ b/chrome/browser/gtk/translate/after_translate_infobar_gtk.cc @@ -62,8 +62,6 @@ void AfterTranslateInfoBar::Init() { l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_REVERT).c_str()); g_signal_connect(button, "clicked",G_CALLBACK(&OnRevertPressedThunk), this); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); - - gtk_widget_show_all(border_bin_.get()); } void AfterTranslateInfoBar::OnOriginalLanguageModified(GtkWidget* sender) { diff --git a/chrome/browser/gtk/translate/before_translate_infobar_gtk.cc b/chrome/browser/gtk/translate/before_translate_infobar_gtk.cc index c3a9b8a..75c668e 100644 --- a/chrome/browser/gtk/translate/before_translate_infobar_gtk.cc +++ b/chrome/browser/gtk/translate/before_translate_infobar_gtk.cc @@ -73,8 +73,6 @@ void BeforeTranslateInfoBar::Init() { G_CALLBACK(&OnAlwaysTranslatePressedThunk), this); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); } - - gtk_widget_show_all(border_bin_.get()); } void BeforeTranslateInfoBar::OnLanguageModified(GtkWidget* sender) { diff --git a/chrome/browser/gtk/translate/translate_message_infobar_gtk.cc b/chrome/browser/gtk/translate/translate_message_infobar_gtk.cc index 22e800d..0f61bca 100644 --- a/chrome/browser/gtk/translate/translate_message_infobar_gtk.cc +++ b/chrome/browser/gtk/translate/translate_message_infobar_gtk.cc @@ -31,8 +31,6 @@ void TranslateMessageInfoBar::Init() { g_signal_connect(button, "clicked",G_CALLBACK(&OnButtonPressedThunk), this); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); } - - gtk_widget_show_all(border_bin_.get()); } void TranslateMessageInfoBar::OnButtonPressed(GtkWidget* sender) { diff --git a/chrome/browser/renderer_host/render_view_host_delegate.cc b/chrome/browser/renderer_host/render_view_host_delegate.cc index 19722a1..523fd8f 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.cc +++ b/chrome/browser/renderer_host/render_view_host_delegate.cc @@ -112,7 +112,3 @@ gfx::Rect RenderViewHostDelegate::GetRootWindowResizerRect() const { bool RenderViewHostDelegate::IsExternalTabContainer() const { return false; } - -bool RenderViewHostDelegate::View::ShouldDrawDropShadow() { - return false; -} diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index 5332a83..93aabb0 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -209,10 +209,6 @@ class RenderViewHostDelegate { // The contents' preferred size changed. virtual void UpdatePreferredSize(const gfx::Size& pref_size) = 0; - // Called to determine whether the render view needs to draw a drop shadow - // at the top (currently used for infobars). - virtual bool ShouldDrawDropShadow(); - protected: virtual ~View() {} }; diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc index 2f5a7e9..cc8ef50 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc +++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc @@ -876,14 +876,7 @@ void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) { // period where this object isn't attached to a window but hasn't been // Destroy()ed yet and it receives paint messages... if (window) { - gfx::Rect drop_shadow_area(0, 0, kMaxWindowWidth, - gtk_util::kInfoBarDropShadowHeight); - bool drop_shadow = host_->IsRenderView() && - static_cast<RenderViewHost*>(host_)->delegate()->GetViewDelegate()-> - ShouldDrawDropShadow() && - drop_shadow_area.Intersects(paint_rect); - - if (!visually_deemphasized_ && !drop_shadow) { + if (!visually_deemphasized_) { // In the common case, use XCopyArea. We don't draw more than once, so // we don't need to double buffer. backing_store->XShowRect( @@ -915,15 +908,9 @@ void RenderWidgetHostViewGtk::Paint(const gfx::Rect& damage_rect) { backing_store->CairoShowRect(damage_rect, GDK_DRAWABLE(window)); cairo_t* cr = gdk_cairo_create(window); - if (visually_deemphasized_) { - gdk_cairo_rectangle(cr, &rect); - cairo_set_source_rgba(cr, 0, 0, 0, 0.7); - cairo_fill(cr); - } - if (drop_shadow) { - gtk_util::DrawTopDropShadowForRenderView( - cr, gfx::Point(), damage_rect); - } + gdk_cairo_rectangle(cr, &rect); + cairo_set_source_rgba(cr, 0, 0, 0, 0.7); + cairo_fill(cr); cairo_destroy(cr); gdk_window_end_paint(window); diff --git a/chrome/browser/tab_contents/tab_contents_view.cc b/chrome/browser/tab_contents/tab_contents_view.cc index 83eb7a4..47e71f2 100644 --- a/chrome/browser/tab_contents/tab_contents_view.cc +++ b/chrome/browser/tab_contents/tab_contents_view.cc @@ -113,10 +113,6 @@ bool TabContentsView::IsEventTracking() const { return false; } -bool TabContentsView::ShouldDrawDropShadow() { - return false; -} - TabContentsView::TabContentsView() : tab_contents_(NULL) {} void TabContentsView::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) { diff --git a/chrome/browser/tab_contents/tab_contents_view.h b/chrome/browser/tab_contents/tab_contents_view.h index 4550781..c6b9a61 100644 --- a/chrome/browser/tab_contents/tab_contents_view.h +++ b/chrome/browser/tab_contents/tab_contents_view.h @@ -153,8 +153,6 @@ class TabContentsView : public RenderViewHostDelegate::View { virtual bool IsEventTracking() const; virtual void CloseTabAfterEventTracking() {} - virtual bool ShouldDrawDropShadow(); - protected: TabContentsView(); // Abstract interface. diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/tab_contents/tab_contents_view_gtk.cc index 2c8a276..7ec34e4 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.cc +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.cc @@ -247,19 +247,6 @@ void TabContentsViewGtk::RestoreFocus() { SetInitialFocus(); } -bool TabContentsViewGtk::ShouldDrawDropShadow() { - GtkWindow* window = GetTopLevelNativeWindow(); - if (!window) - return false; - - BrowserWindowGtk* browser_window = - BrowserWindowGtk::GetBrowserWindowForNativeWindow(window); - if (!browser_window) - return false; - - return browser_window->ShouldDrawInfobarDropShadowOnRenderView(); -} - void TabContentsViewGtk::SetFocusedWidget(GtkWidget* widget) { focus_store_.SetWidget(widget); } diff --git a/chrome/browser/tab_contents/tab_contents_view_gtk.h b/chrome/browser/tab_contents/tab_contents_view_gtk.h index 2ea02ca..9a016a1 100644 --- a/chrome/browser/tab_contents/tab_contents_view_gtk.h +++ b/chrome/browser/tab_contents/tab_contents_view_gtk.h @@ -59,7 +59,6 @@ class TabContentsViewGtk : public TabContentsView, virtual void SetInitialFocus(); virtual void StoreFocus(); virtual void RestoreFocus(); - virtual bool ShouldDrawDropShadow(); // Backend implementation of RenderViewHostDelegate::View. virtual void ShowContextMenu(const ContextMenuParams& params); diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 6c92179..aa3c47c 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -1845,6 +1845,8 @@ 'browser/gtk/info_bubble_gtk.h', 'browser/gtk/info_bubble_accelerators_gtk.cc', 'browser/gtk/info_bubble_accelerators_gtk.h', + 'browser/gtk/infobar_arrow_model.cc', + 'browser/gtk/infobar_arrow_model.h', 'browser/gtk/infobar_container_gtk.cc', 'browser/gtk/infobar_container_gtk.h', 'browser/gtk/infobar_gtk.cc', diff --git a/gfx/color_utils.cc b/gfx/color_utils.cc index 268f556..73c585b 100644 --- a/gfx/color_utils.cc +++ b/gfx/color_utils.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -256,13 +256,28 @@ SkColor AlphaBlend(SkColor foreground, SkColor background, SkAlpha alpha) { return background; if (alpha == 255) return foreground; - return SkColorSetRGB( - ((SkColorGetR(foreground) * alpha) + - (SkColorGetR(background) * (255 - alpha))) / 255, - ((SkColorGetG(foreground) * alpha) + - (SkColorGetG(background) * (255 - alpha))) / 255, - ((SkColorGetB(foreground) * alpha) + - (SkColorGetB(background) * (255 - alpha))) / 255); + + int f_alpha = SkColorGetA(foreground); + int b_alpha = SkColorGetA(background); + + double normalizer = (f_alpha * alpha + b_alpha * (255 - alpha)) / 255.0; + if (normalizer == 0.0) + return SkColorSetARGB(0, 0, 0, 0); + + double f_weight = f_alpha * alpha / normalizer; + double b_weight = b_alpha * (255 - alpha) / normalizer; + + double r = (SkColorGetR(foreground) * f_weight + + SkColorGetR(background) * b_weight) / 255.0; + double g = (SkColorGetG(foreground) * f_weight + + SkColorGetG(background) * b_weight) / 255.0; + double b = (SkColorGetB(foreground) * f_weight + + SkColorGetB(background) * b_weight) / 255.0; + + return SkColorSetARGB(static_cast<int>(normalizer), + static_cast<int>(r), + static_cast<int>(g), + static_cast<int>(b)); } SkColor GetReadableColor(SkColor foreground, SkColor background) { diff --git a/gfx/color_utils.h b/gfx/color_utils.h index f511168..b6eb2da 100644 --- a/gfx/color_utils.h +++ b/gfx/color_utils.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. @@ -58,7 +58,9 @@ SkColor GetAverageColorOfFavicon(SkBitmap* bitmap, SkAlpha alpha); void BuildLumaHistogram(SkBitmap* bitmap, int histogram[256]); // Returns a blend of the supplied colors, ranging from |background| (for -// |alpha| == 0) to |foreground| (for |alpha| == 255). +// |alpha| == 0) to |foreground| (for |alpha| == 255). The alpha channels of +// the supplied colors are also taken into account, so the returned color may +// be partially transparent. SkColor AlphaBlend(SkColor foreground, SkColor background, SkAlpha alpha); // Given a foreground and background color, try to return a foreground color diff --git a/gfx/color_utils_unittest.cc b/gfx/color_utils_unittest.cc index 363d700..30cf514 100644 --- a/gfx/color_utils_unittest.cc +++ b/gfx/color_utils_unittest.cc @@ -47,3 +47,21 @@ TEST(ColorUtils, ColorToHSLRegisterSpill) { EXPECT_EQ(153U, SkColorGetG(result)); EXPECT_EQ(88U, SkColorGetB(result)); } + +TEST(ColorUtils, AlphaBlend) { + SkColor fore = SkColorSetARGB(255, 200, 200, 200); + SkColor back = SkColorSetARGB(255, 100, 100, 100); + + EXPECT_TRUE(color_utils::AlphaBlend(fore, back, 255) == + fore); + EXPECT_TRUE(color_utils::AlphaBlend(fore, back, 0) == + back); + + // One is fully transparent, result is partially transparent. + back = SkColorSetA(back, 0); + EXPECT_EQ(136U, SkColorGetA(color_utils::AlphaBlend(fore, back, 136))); + + // Both are fully transparent, result is fully transparent. + fore = SkColorSetA(fore, 0); + EXPECT_EQ(0U, SkColorGetA(color_utils::AlphaBlend(fore, back, 255))); +} |