| Index: chrome/browser/ui/libgtk2ui/gtk2_border.cc
|
| diff --git a/chrome/browser/ui/libgtk2ui/gtk2_border.cc b/chrome/browser/ui/libgtk2ui/gtk2_border.cc
|
| index 93c46db35f230feb6d7001b2a2c5ee91fff70df2..4e8bfd158725cfa72af04558986e089263531cbd 100644
|
| --- a/chrome/browser/ui/libgtk2ui/gtk2_border.cc
|
| +++ b/chrome/browser/ui/libgtk2ui/gtk2_border.cc
|
| @@ -7,34 +7,44 @@
|
| #include <gtk/gtk.h>
|
|
|
| #include "chrome/browser/ui/libgtk2ui/gtk2_ui.h"
|
| +#include "third_party/skia/include/effects/SkLerpXfermode.h"
|
| +#include "ui/gfx/animation/animation.h"
|
| #include "ui/gfx/canvas.h"
|
| #include "ui/gfx/image/image_skia_source.h"
|
| -#include "ui/views/controls/button/custom_button.h"
|
| +#include "ui/gfx/rect.h"
|
| +#include "ui/gfx/skia_util.h"
|
| +#include "ui/views/controls/button/label_button.h"
|
| +#include "ui/views/native_theme_delegate.h"
|
| +
|
| +using views::Button;
|
| +using views::NativeThemeDelegate;
|
|
|
| namespace libgtk2ui {
|
|
|
| namespace {
|
|
|
| -GtkStateType ViewsToGtkState(views::Button::ButtonState state) {
|
| +const int kNumberOfFocusedStates = 2;
|
| +
|
| +GtkStateType GetGtkState(ui::NativeTheme::State state) {
|
| switch (state) {
|
| - case views::Button::STATE_HOVERED:
|
| - return GTK_STATE_PRELIGHT;
|
| - case views::Button::STATE_PRESSED:
|
| - return GTK_STATE_ACTIVE;
|
| - case views::Button::STATE_DISABLED:
|
| - return GTK_STATE_INSENSITIVE;
|
| - default:
|
| - return GTK_STATE_NORMAL;
|
| + case ui::NativeTheme::kDisabled: return GTK_STATE_INSENSITIVE;
|
| + case ui::NativeTheme::kHovered: return GTK_STATE_PRELIGHT;
|
| + case ui::NativeTheme::kNormal: return GTK_STATE_NORMAL;
|
| + case ui::NativeTheme::kPressed: return GTK_STATE_ACTIVE;
|
| + case ui::NativeTheme::kMaxState: NOTREACHED() << "Unknown state: " << state;
|
| }
|
| + return GTK_STATE_NORMAL;
|
| }
|
|
|
| class ButtonImageSkiaSource : public gfx::ImageSkiaSource {
|
| public:
|
| ButtonImageSkiaSource(const Gtk2UI* gtk2_ui,
|
| - GtkStateType state,
|
| + const GtkStateType state,
|
| + const bool focused,
|
| const gfx::Size& size)
|
| : gtk2_ui_(gtk2_ui),
|
| state_(state),
|
| + focused_(focused),
|
| size_(size) {
|
| }
|
|
|
| @@ -45,12 +55,13 @@ class ButtonImageSkiaSource : public gfx::ImageSkiaSource {
|
| int w = size_.width() * scale;
|
| int h = size_.height() * scale;
|
| return gfx::ImageSkiaRep(
|
| - gtk2_ui_->DrawGtkButtonBorder(state_, w, h), scale);
|
| + gtk2_ui_->DrawGtkButtonBorder(state_, focused_, w, h), scale);
|
| }
|
|
|
| private:
|
| const Gtk2UI* gtk2_ui_;
|
| const GtkStateType state_;
|
| + const bool focused_;
|
| const gfx::Size size_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(ButtonImageSkiaSource);
|
| @@ -59,7 +70,7 @@ class ButtonImageSkiaSource : public gfx::ImageSkiaSource {
|
| } // namespace
|
|
|
| Gtk2Border::Gtk2Border(Gtk2UI* gtk2_ui,
|
| - views::CustomButton* owning_button,
|
| + views::LabelButton* owning_button,
|
| scoped_ptr<views::Border> border)
|
| : gtk2_ui_(gtk2_ui),
|
| use_gtk_(gtk2_ui_->GetUseSystemTheme()),
|
| @@ -73,8 +84,11 @@ Gtk2Border::~Gtk2Border() {
|
| }
|
|
|
| void Gtk2Border::InvalidateAndSetUsesGtk(bool use_gtk) {
|
| - hovered_ = gfx::ImageSkia();
|
| - pressed_ = gfx::ImageSkia();
|
| + for (int i = 0; i < kNumberOfFocusedStates; ++i) {
|
| + for (int j = 0; j < views::Button::STATE_COUNT; ++j) {
|
| + button_images_[i][j] = gfx::ImageSkia();
|
| + }
|
| + }
|
|
|
| // Our owning view must have its layout invalidated because the insets could
|
| // have changed.
|
| @@ -90,22 +104,31 @@ void Gtk2Border::Paint(const views::View& view, gfx::Canvas* canvas) {
|
| }
|
|
|
| DCHECK_EQ(&view, owning_button_);
|
| - GtkStateType state = ViewsToGtkState(owning_button_->state());
|
| -
|
| - if (state == GTK_STATE_PRELIGHT) {
|
| - if (hovered_.isNull() || hovered_.size() != view.size()) {
|
| - hovered_ = gfx::ImageSkia(
|
| - new ButtonImageSkiaSource(gtk2_ui_, state, view.size()), view.size());
|
| - }
|
| -
|
| - canvas->DrawImageInt(hovered_, 0, 0);
|
| - } else if (state == GTK_STATE_ACTIVE) {
|
| - if (pressed_.isNull() || pressed_.size() != view.size()) {
|
| - pressed_ = gfx::ImageSkia(
|
| - new ButtonImageSkiaSource(gtk2_ui_, state, view.size()), view.size());
|
| - }
|
| -
|
| - canvas->DrawImageInt(pressed_, 0, 0);
|
| + const NativeThemeDelegate* native_theme_delegate = owning_button_;
|
| + gfx::Rect rect(native_theme_delegate->GetThemePaintRect());
|
| + ui::NativeTheme::ExtraParams extra;
|
| + ui::NativeTheme::State state = native_theme_delegate->GetThemeState(&extra);
|
| +
|
| + const gfx::Animation* animation = native_theme_delegate->GetThemeAnimation();
|
| + if (animation && animation->is_animating()) {
|
| + // Linearly interpolate background and foreground painters during animation.
|
| + const SkRect sk_rect = gfx::RectToSkRect(rect);
|
| + canvas->sk_canvas()->saveLayer(&sk_rect, NULL);
|
| + state = native_theme_delegate->GetBackgroundThemeState(&extra);
|
| + PaintState(state, extra, rect, canvas);
|
| +
|
| + SkPaint paint;
|
| + skia::RefPtr<SkXfermode> sk_lerp_xfer =
|
| + skia::AdoptRef(SkLerpXfermode::Create(animation->GetCurrentValue()));
|
| + paint.setXfermode(sk_lerp_xfer.get());
|
| + canvas->sk_canvas()->saveLayer(&sk_rect, &paint);
|
| + state = native_theme_delegate->GetForegroundThemeState(&extra);
|
| + PaintState(state, extra, rect, canvas);
|
| + canvas->sk_canvas()->restore();
|
| +
|
| + canvas->sk_canvas()->restore();
|
| + } else {
|
| + PaintState(state, extra, rect, canvas);
|
| }
|
| }
|
|
|
| @@ -124,4 +147,37 @@ gfx::Size Gtk2Border::GetMinimumSize() const {
|
| return gfx::Size(insets.width(), insets.height());
|
| }
|
|
|
| +void Gtk2Border::PaintState(const ui::NativeTheme::State state,
|
| + const ui::NativeTheme::ExtraParams& extra,
|
| + const gfx::Rect& rect,
|
| + gfx::Canvas* canvas) {
|
| + bool focused = extra.button.is_focused;
|
| + Button::ButtonState views_state = Button::GetButtonStateFrom(state);
|
| +
|
| + if (ShouldDrawBorder(focused, views_state)) {
|
| + gfx::ImageSkia* image = &button_images_[focused][views_state];
|
| +
|
| + if (image->isNull() || image->size() != rect.size()) {
|
| + GtkStateType gtk_state = GetGtkState(state);
|
| + *image = gfx::ImageSkia(
|
| + new ButtonImageSkiaSource(gtk2_ui_, gtk_state, focused, rect.size()),
|
| + rect.size());
|
| + }
|
| + canvas->DrawImageInt(*image, rect.x(), rect.y());
|
| + }
|
| +}
|
| +
|
| +bool Gtk2Border::ShouldDrawBorder(bool focused,
|
| + views::Button::ButtonState state) {
|
| + // This logic should be kept in sync with the LabelButtonBorder constructor.
|
| + if (owning_button_->style() == Button::STYLE_BUTTON) {
|
| + return true;
|
| + } else if (owning_button_->style() == Button::STYLE_TEXTBUTTON) {
|
| + return focused == false && (state == Button::STATE_HOVERED ||
|
| + state == Button::STATE_PRESSED);
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| } // namespace libgtk2ui
|
|
|