Chromium Code Reviews| Index: views/bubble/bubble_delegate.cc |
| diff --git a/views/bubble/bubble_delegate.cc b/views/bubble/bubble_delegate.cc |
| index b46e3536bf73feba52fed2035c22b8abb319c331..aac3e1fcdb65ab3627252af1e3be13a897577629 100644 |
| --- a/views/bubble/bubble_delegate.cc |
| +++ b/views/bubble/bubble_delegate.cc |
| @@ -9,15 +9,72 @@ |
| #include "views/widget/widget.h" |
| // The duration of the fade animation in milliseconds. |
| -static const int kHideFadeDurationMS = 1000; |
| +static const int kHideFadeDurationMS = 200; |
| namespace views { |
| +namespace { |
| + |
| +// Create a widget to host the bubble. |
| +Widget* CreateBubbleWidget(BubbleDelegateView* bubble, Widget* parent) { |
| + Widget* bubble_widget = new Widget(); |
| + Widget::InitParams bubble_params(Widget::InitParams::TYPE_BUBBLE); |
| + bubble_params.delegate = bubble; |
| + bubble_params.transparent = true; |
| + bubble_params.parent_widget = parent; |
| + if (!bubble_params.parent_widget) |
| + bubble_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| +#if defined(OS_WIN) && !defined(USE_AURA) |
| + bubble_params.type = Widget::InitParams::TYPE_WINDOW_FRAMELESS; |
| + bubble_params.transparent = false; |
| +#endif |
| + bubble_widget->Init(bubble_params); |
| + return bubble_widget; |
| +} |
| + |
| +#if defined(OS_WIN) && !defined(USE_AURA) |
| +// The border widget's delegate, needed for transparent Windows native controls. |
| +// TODO(msw): Remove this when Windows native controls are no longer needed. |
| +class VIEWS_EXPORT BubbleBorderDelegateView : public WidgetDelegateView { |
| + public: |
| + explicit BubbleBorderDelegateView(BubbleDelegateView* bubble) |
| + : bubble_(bubble) {} |
|
Ben Goodger (Google)
2011/10/27 15:37:00
nit: 4-space indent instead of 2.
msw
2011/10/28 17:10:18
Done.
|
| + virtual ~BubbleBorderDelegateView() {} |
| + |
| + // WidgetDelegateView overrides: |
| + virtual bool CanActivate() const OVERRIDE { return false; } |
| + virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE { |
| + return bubble_->CreateNonClientFrameView(); |
| + } |
| + |
| + private: |
| + BubbleDelegateView* bubble_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(BubbleBorderDelegateView); |
| +}; |
| + |
| +// Create a widget to host the bubble's border. |
| +Widget* CreateBorderWidget(BubbleDelegateView* bubble, Widget* parent) { |
| + Widget* border_widget = new Widget(); |
| + Widget::InitParams border_params(Widget::InitParams::TYPE_BUBBLE); |
| + border_params.delegate = new BubbleBorderDelegateView(bubble); |
| + border_params.transparent = true; |
| + border_params.parent_widget = parent; |
| + if (!border_params.parent_widget) |
| + border_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| + border_widget->Init(border_params); |
| + return border_widget; |
| +} |
| +#endif |
| + |
| +} // namespace |
| + |
| BubbleDelegateView::BubbleDelegateView() |
| - : WidgetDelegateView(), |
| - close_on_esc_(true), |
| + : close_on_esc_(true), |
| arrow_location_(BubbleBorder::TOP_LEFT), |
| - color_(SK_ColorWHITE) { |
| + color_(SK_ColorWHITE), |
| + border_widget_(NULL) { |
| + set_background(views::Background::CreateSolidBackground(color_)); |
| AddAccelerator(Accelerator(ui::VKEY_ESCAPE, 0)); |
| } |
| @@ -25,29 +82,39 @@ BubbleDelegateView::BubbleDelegateView( |
| const gfx::Point& anchor_point, |
| BubbleBorder::ArrowLocation arrow_location, |
| const SkColor& color) |
| - : WidgetDelegateView(), |
| - close_on_esc_(true), |
| + : close_on_esc_(true), |
| anchor_point_(anchor_point), |
| arrow_location_(arrow_location), |
| - color_(color) { |
| + color_(color), |
| + border_widget_(NULL) { |
| + set_background(views::Background::CreateSolidBackground(color_)); |
| AddAccelerator(Accelerator(ui::VKEY_ESCAPE, 0)); |
| } |
| -BubbleDelegateView::~BubbleDelegateView() {} |
| +BubbleDelegateView::~BubbleDelegateView() { |
| + if (border_widget_) |
| + border_widget_->Close(); |
| +} |
| // static |
| Widget* BubbleDelegateView::CreateBubble(BubbleDelegateView* bubble_delegate, |
| Widget* parent_widget) { |
| bubble_delegate->Init(); |
| - views::Widget* bubble_widget = new views::Widget(); |
| - views::Widget::InitParams params(views::Widget::InitParams::TYPE_BUBBLE); |
| - params.delegate = bubble_delegate; |
| - params.transparent = true; |
| - if (!parent_widget) |
| - params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| - params.parent_widget = parent_widget; |
| - bubble_widget->Init(params); |
| + Widget* bubble_widget = CreateBubbleWidget(bubble_delegate, parent_widget); |
| + |
| +#if defined(OS_WIN) && !defined(USE_AURA) |
| + Widget* border_widget = CreateBorderWidget(bubble_delegate, parent_widget); |
|
Ben Goodger (Google)
2011/10/27 15:37:00
Move the border initialization into a separate fun
msw
2011/10/28 17:10:18
Only 3 lines were initializing the border, but I s
|
| + bubble_delegate->border_widget_ = border_widget; |
| + bubble_widget->SetContentsView(bubble_delegate->GetContentsView()); |
| + border_widget->SetBounds(bubble_delegate->GetBubbleBounds()); |
| + gfx::Rect client_bounds( |
| + bubble_delegate->GetBubbleFrameView()->GetBoundsForClientView()); |
| + client_bounds.Offset(border_widget->GetWindowScreenBounds().origin()); |
| + bubble_widget->SetBounds(client_bounds); |
| +#else |
| bubble_widget->SetBounds(bubble_delegate->GetBubbleBounds()); |
| +#endif |
| + |
| return bubble_widget; |
| } |
| @@ -59,10 +126,6 @@ View* BubbleDelegateView::GetContentsView() { |
| return this; |
| } |
| -ClientView* BubbleDelegateView::CreateClientView(Widget* widget) { |
| - return new ClientView(widget, GetContentsView()); |
| -} |
| - |
| NonClientFrameView* BubbleDelegateView::CreateNonClientFrameView() { |
| return new BubbleFrameView(GetArrowLocation(), |
| GetPreferredSize(), |
| @@ -81,15 +144,29 @@ SkColor BubbleDelegateView::GetColor() const { |
| return color_; |
| } |
| -void BubbleDelegateView::Init() {} |
| +void BubbleDelegateView::Show() { |
| + if (border_widget_) |
| + border_widget_->Show(); |
| + GetWidget()->Show(); |
| + GetFocusManager()->SetFocusedView(GetInitiallyFocusedView()); |
| +} |
| void BubbleDelegateView::StartFade(bool fade_in) { |
| fade_animation_.reset(new ui::SlideAnimation(this)); |
| fade_animation_->SetSlideDuration(kHideFadeDurationMS); |
| fade_animation_->Reset(fade_in ? 0.0 : 1.0); |
| + |
| +#if defined(OS_WIN) && !defined(USE_AURA) |
| + HWND hwnd = GetWidget()->GetNativeView(); |
| + SetWindowLong(hwnd, GWL_EXSTYLE, |
| + GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED); |
|
Ben Goodger (Google)
2011/10/27 15:37:00
Question: Can we do this in NativeWidgetWin::SetOp
msw
2011/10/28 17:10:18
Moved into AnimationProgressed. We don't want to t
|
| +#endif |
| + |
| if (fade_in) { |
| + if (border_widget_) |
| + border_widget_->SetOpacity(0); |
| GetWidget()->SetOpacity(0); |
| - GetWidget()->Show(); |
| + Show(); |
| fade_animation_->Show(); |
| } else { |
| fade_animation_->Hide(); |
| @@ -105,10 +182,19 @@ bool BubbleDelegateView::AcceleratorPressed(const Accelerator& accelerator) { |
| return true; |
| } |
| +void BubbleDelegateView::Init() {} |
| + |
| void BubbleDelegateView::AnimationEnded(const ui::Animation* animation) { |
| DCHECK_EQ(animation, fade_animation_.get()); |
| bool closed = fade_animation_->GetCurrentValue() == 0; |
| fade_animation_->Reset(); |
| + |
| +#if defined(OS_WIN) && !defined(USE_AURA) |
| + HWND hwnd = GetWidget()->GetNativeView(); |
| + SetWindowLong(hwnd, GWL_EXSTYLE, |
| + GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED); |
|
Ben Goodger (Google)
2011/10/27 15:37:00
Again, in NativeWidgetWin::SetOpacity() when setti
msw
2011/10/28 17:10:18
Ditto to the StartFade comment.
|
| +#endif |
| + |
| if (closed) |
| GetWidget()->Close(); |
| } |
| @@ -116,7 +202,14 @@ void BubbleDelegateView::AnimationEnded(const ui::Animation* animation) { |
| void BubbleDelegateView::AnimationProgressed(const ui::Animation* animation) { |
| DCHECK_EQ(animation, fade_animation_.get()); |
| DCHECK(fade_animation_->is_animating()); |
| - GetWidget()->SetOpacity(fade_animation_->GetCurrentValue() * 255); |
| + unsigned char opacity = fade_animation_->GetCurrentValue() * 255; |
| +#if defined(OS_WIN) && !defined(USE_AURA) |
| + HWND hwnd = GetWidget()->GetNativeView(); |
| + SetLayeredWindowAttributes(hwnd, 0, opacity, LWA_ALPHA); |
|
Ben Goodger (Google)
2011/10/27 15:37:00
Here, can we call SetOpacity() on GetWidget()?
msw
2011/10/28 17:10:18
Nope, as you pointed out, we need to use SetLayere
|
| + border_widget_->SetOpacity(opacity); |
| + border_widget_->non_client_view()->SchedulePaint(); |
| +#endif |
| + GetWidget()->SetOpacity(opacity); |
| SchedulePaint(); |
| } |
| @@ -126,7 +219,11 @@ const BubbleView* BubbleDelegateView::GetBubbleView() const { |
| const BubbleFrameView* BubbleDelegateView::GetBubbleFrameView() const { |
| return static_cast<BubbleFrameView*>( |
| +#if defined(OS_WIN) && !defined(USE_AURA) |
| + border_widget_->non_client_view()->frame_view()); |
| +#else |
| GetWidget()->non_client_view()->frame_view()); |
| +#endif |
| } |
| gfx::Rect BubbleDelegateView::GetBubbleBounds() { |