summaryrefslogtreecommitdiffstats
path: root/views
diff options
context:
space:
mode:
authormsw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-01 21:06:00 +0000
committermsw@chromium.org <msw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-01 21:06:00 +0000
commit32eb60f4c7e4dfc0912a241d9b8705fb63255eea (patch)
tree6b4075d30e4666c698f4289eb118e46e9168492b /views
parentce6eccf380ffd58ff21c5e1a43a0472fd4b8893e (diff)
downloadchromium_src-32eb60f4c7e4dfc0912a241d9b8705fb63255eea.zip
chromium_src-32eb60f4c7e4dfc0912a241d9b8705fb63255eea.tar.gz
chromium_src-32eb60f4c7e4dfc0912a241d9b8705fb63255eea.tar.bz2
Support Windows native textfield, combobox, etc. in new bubbles.
Should allow us to fully convert all bubbles (bookmark, etc.) Use separate border and contents widgets (like old bubble). Supports transparency/opacity with fading, etc. Remove BubbleView remnants; update tests. BUG=98312 TEST=No views_examples bubble problems. Review URL: http://codereview.chromium.org/8368006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108167 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r--views/bubble/bubble_delegate.cc157
-rw-r--r--views/bubble/bubble_delegate.h27
-rw-r--r--views/bubble/bubble_delegate_unittest.cc13
-rw-r--r--views/bubble/bubble_frame_view_unittest.cc34
-rw-r--r--views/bubble/bubble_view_unittest.cc30
-rw-r--r--views/examples/bubble_example.cc6
-rw-r--r--views/views.gyp1
-rw-r--r--views/window/client_view.cc8
-rw-r--r--views/window/client_view.h3
9 files changed, 183 insertions, 96 deletions
diff --git a/views/bubble/bubble_delegate.cc b/views/bubble/bubble_delegate.cc
index 1fb7ebf..1b40c29 100644
--- a/views/bubble/bubble_delegate.cc
+++ b/views/bubble/bubble_delegate.cc
@@ -9,15 +9,76 @@
#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) {}
+ virtual ~BubbleBorderDelegateView() {}
+
+ // WidgetDelegateView overrides:
+ virtual bool CanActivate() const OVERRIDE;
+ virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE;
+
+ private:
+ BubbleDelegateView* bubble_;
+
+ DISALLOW_COPY_AND_ASSIGN(BubbleBorderDelegateView);
+};
+
+bool BubbleBorderDelegateView::CanActivate() const { return false; }
+
+NonClientFrameView* BubbleBorderDelegateView::CreateNonClientFrameView() {
+ return bubble_->CreateNonClientFrameView();
+}
+
+// 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,30 +86,35 @@ 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),
- original_opacity_(255) {
+ original_opacity_(255),
+ 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)
+ bubble_delegate->InitializeBorderWidget(parent_widget);
+ bubble_widget->SetContentsView(bubble_delegate->GetContentsView());
+ bubble_widget->SetBounds(bubble_delegate->GetBubbleClientBounds());
+#else
bubble_widget->SetBounds(bubble_delegate->GetBubbleBounds());
+#endif
+
return bubble_widget;
}
@@ -60,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(),
@@ -82,7 +144,12 @@ 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));
@@ -90,8 +157,10 @@ void BubbleDelegateView::StartFade(bool fade_in) {
fade_animation_->Reset(fade_in ? 0.0 : 1.0);
if (fade_in) {
original_opacity_ = 0;
+ if (border_widget_)
+ border_widget_->SetOpacity(original_opacity_);
GetWidget()->SetOpacity(original_opacity_);
- GetWidget()->Show();
+ Show();
fade_animation_->Show();
} else {
original_opacity_ = 255;
@@ -101,6 +170,8 @@ void BubbleDelegateView::StartFade(bool fade_in) {
void BubbleDelegateView::ResetFade() {
fade_animation_.reset();
+ if (border_widget_)
+ border_widget_->SetOpacity(original_opacity_);
GetWidget()->SetOpacity(original_opacity_);
}
@@ -113,6 +184,8 @@ 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;
@@ -124,17 +197,28 @@ 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)
+ // Explicitly set the content Widget's layered style and set transparency via
+ // SetLayeredWindowAttributes. This is done because initializing the Widget as
+ // transparent and setting opacity via UpdateLayeredWindow doesn't support
+ // hosting child native Windows controls.
+ const HWND hwnd = GetWidget()->GetNativeView();
+ const DWORD style = GetWindowLong(hwnd, GWL_EXSTYLE);
+ if ((opacity == 255) == !!(style & WS_EX_LAYERED))
+ SetWindowLong(hwnd, GWL_EXSTYLE, style ^ WS_EX_LAYERED);
+ SetLayeredWindowAttributes(hwnd, 0, opacity, LWA_ALPHA);
+ // Update the border widget's opacity.
+ border_widget_->SetOpacity(opacity);
+ border_widget_->non_client_view()->SchedulePaint();
+#endif
+ GetWidget()->SetOpacity(opacity);
SchedulePaint();
}
-const BubbleView* BubbleDelegateView::GetBubbleView() const {
- return GetWidget()->client_view()->AsBubbleView();
-}
-
-const BubbleFrameView* BubbleDelegateView::GetBubbleFrameView() const {
- return static_cast<BubbleFrameView*>(
- GetWidget()->non_client_view()->frame_view());
+BubbleFrameView* BubbleDelegateView::GetBubbleFrameView() const {
+ const Widget* widget = border_widget_ ? border_widget_ : GetWidget();
+ return static_cast<BubbleFrameView*>(widget->non_client_view()->frame_view());
}
gfx::Rect BubbleDelegateView::GetBubbleBounds() {
@@ -144,4 +228,17 @@ gfx::Rect BubbleDelegateView::GetBubbleBounds() {
gfx::Rect(GetAnchorPoint(), GetPreferredSize()));
}
+#if defined(OS_WIN) && !defined(USE_AURA)
+void BubbleDelegateView::InitializeBorderWidget(Widget* parent_widget) {
+ border_widget_ = CreateBorderWidget(this, parent_widget);
+ border_widget_->SetBounds(GetBubbleBounds());
+}
+
+gfx::Rect BubbleDelegateView::GetBubbleClientBounds() const {
+ gfx::Rect client_bounds(GetBubbleFrameView()->GetBoundsForClientView());
+ client_bounds.Offset(border_widget_->GetWindowScreenBounds().origin());
+ return client_bounds;
+}
+#endif
+
} // namespace views
diff --git a/views/bubble/bubble_delegate.h b/views/bubble/bubble_delegate.h
index 929f619..a5f6ab9 100644
--- a/views/bubble/bubble_delegate.h
+++ b/views/bubble/bubble_delegate.h
@@ -6,6 +6,7 @@
#define VIEWS_BUBBLE_BUBBLE_DELEGATE_H_
#pragma once
+#include "base/gtest_prod_util.h"
#include "ui/base/animation/animation_delegate.h"
#include "views/bubble/bubble_border.h"
#include "views/widget/widget_delegate.h"
@@ -17,7 +18,6 @@ class SlideAnimation;
namespace views {
class BubbleFrameView;
-class BubbleView;
// BubbleDelegateView creates frame and client views for bubble Widgets.
// BubbleDelegateView itself is the client's contents view.
@@ -32,14 +32,13 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
const SkColor& color);
virtual ~BubbleDelegateView();
- // Create a bubble Widget from the argument BubbleDelegateView.
+ // Create and initialize the bubble Widget(s) with proper bounds.
static Widget* CreateBubble(BubbleDelegateView* bubble_delegate,
Widget* parent_widget);
// WidgetDelegate overrides:
virtual View* GetInitiallyFocusedView() OVERRIDE;
virtual View* GetContentsView() OVERRIDE;
- virtual ClientView* CreateClientView(Widget* widget) OVERRIDE;
virtual NonClientFrameView* CreateNonClientFrameView() OVERRIDE;
bool close_on_esc() const { return close_on_esc_; }
@@ -54,6 +53,9 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
// Get the color used for the background and border.
virtual SkColor GetColor() const;
+ // Show the bubble's widget (and |border_widget_| on Windows).
+ void Show();
+
// Fade the bubble in or out via Widget transparency.
// Fade in calls Widget::Show; fade out calls Widget::Close upon completion.
void StartFade(bool fade_in);
@@ -70,16 +72,26 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
virtual void Init();
private:
+ FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewBasicTest, NonClientHitTest);
+ FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CreateDelegate);
+
// ui::AnimationDelegate overrides:
virtual void AnimationEnded(const ui::Animation* animation);
virtual void AnimationProgressed(const ui::Animation* animation);
- const BubbleView* GetBubbleView() const;
- const BubbleFrameView* GetBubbleFrameView() const;
+ BubbleFrameView* GetBubbleFrameView() const;
// Get bubble bounds from the anchor point and client view's preferred size.
gfx::Rect GetBubbleBounds();
+#if defined(OS_WIN) && !defined(USE_AURA)
+ // Initialize the border widget needed for Windows native control hosting.
+ void InitializeBorderWidget(Widget* parent_widget);
+
+ // Get bounds for the Windows-only widget that hosts the bubble's contents.
+ gfx::Rect GetBubbleClientBounds() const;
+#endif
+
// Fade animation for bubble.
scoped_ptr<ui::SlideAnimation> fade_animation_;
@@ -97,6 +109,11 @@ class VIEWS_EXPORT BubbleDelegateView : public WidgetDelegateView,
// Original opacity of the bubble.
int original_opacity_;
+
+ // The widget hosting the border for this bubble (non-Aura Windows only).
+ Widget* border_widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(BubbleDelegateView);
};
} // namespace views
diff --git a/views/bubble/bubble_delegate_unittest.cc b/views/bubble/bubble_delegate_unittest.cc
index ea3241c..ce561f5d 100644
--- a/views/bubble/bubble_delegate_unittest.cc
+++ b/views/bubble/bubble_delegate_unittest.cc
@@ -3,26 +3,29 @@
// found in the LICENSE file.
#include "views/bubble/bubble_delegate.h"
+#include "views/bubble/bubble_frame_view.h"
#include "views/test/views_test_base.h"
#include "views/widget/widget.h"
namespace views {
-namespace {
-
typedef ViewsTestBase BubbleDelegateTest;
TEST_F(BubbleDelegateTest, CreateDelegate) {
BubbleDelegateView* bubble_delegate = new BubbleDelegateView();
scoped_ptr<Widget> bubble_widget(
- views::BubbleDelegateView::CreateBubble(bubble_delegate, NULL));
+ BubbleDelegateView::CreateBubble(bubble_delegate, NULL));
EXPECT_EQ(bubble_delegate, bubble_widget->widget_delegate());
EXPECT_EQ(bubble_widget, bubble_delegate->GetWidget());
+
+ BubbleBorder* border = static_cast<BubbleBorder*>(
+ bubble_delegate->GetBubbleFrameView()->border());
+ EXPECT_EQ(bubble_delegate->GetArrowLocation(), border->arrow_location());
+ EXPECT_EQ(bubble_delegate->GetColor(), border->background_color());
+
bubble_widget->CloseNow();
bubble_widget.reset();
RunPendingMessages();
}
-} // namespace
-
} // namespace views
diff --git a/views/bubble/bubble_frame_view_unittest.cc b/views/bubble/bubble_frame_view_unittest.cc
index 766bcec..bbdd203 100644
--- a/views/bubble/bubble_frame_view_unittest.cc
+++ b/views/bubble/bubble_frame_view_unittest.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "views/bubble/bubble_frame_view.h"
#include "views/bubble/bubble_delegate.h"
+#include "views/bubble/bubble_frame_view.h"
#include "views/test/views_test_base.h"
#include "views/widget/widget.h"
#if !defined(OS_WIN)
@@ -32,22 +32,34 @@ TEST_F(BubbleFrameViewBasicTest, GetBoundsForClientView) {
EXPECT_EQ(expected_insets.top(), frame.GetBoundsForClientView().y());
}
+} // namespace
+
+class SizedBubbleDelegateView : public BubbleDelegateView {
+ public:
+ SizedBubbleDelegateView() {}
+ virtual ~SizedBubbleDelegateView() {}
+
+ // View overrides:
+ virtual gfx::Size GetPreferredSize() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SizedBubbleDelegateView);
+};
+
+gfx::Size SizedBubbleDelegateView::GetPreferredSize() { return kRect.size(); }
+
TEST_F(BubbleFrameViewBasicTest, NonClientHitTest) {
- BubbleDelegateView* delegate = new BubbleDelegateView();
- scoped_ptr<Widget> widget(
- views::BubbleDelegateView::CreateBubble(delegate, NULL));
- widget->SetBounds(kRect);
- widget->Show();
+ SizedBubbleDelegateView* delegate = new SizedBubbleDelegateView();
+ scoped_ptr<Widget> widget(BubbleDelegateView::CreateBubble(delegate, NULL));
+ delegate->Show();
gfx::Point kPtInBound(100, 100);
gfx::Point kPtOutsideBound(1000, 1000);
- EXPECT_EQ(HTCLIENT, widget->non_client_view()->NonClientHitTest(kPtInBound));
- EXPECT_EQ(HTNOWHERE,
- widget->non_client_view()->NonClientHitTest(kPtOutsideBound));
+ BubbleFrameView* bubble_frame_view = delegate->GetBubbleFrameView();
+ EXPECT_EQ(HTCLIENT, bubble_frame_view->NonClientHitTest(kPtInBound));
+ EXPECT_EQ(HTNOWHERE, bubble_frame_view->NonClientHitTest(kPtOutsideBound));
widget->CloseNow();
widget.reset();
RunPendingMessages();
}
-} // namespace
-
} // namespace views
diff --git a/views/bubble/bubble_view_unittest.cc b/views/bubble/bubble_view_unittest.cc
deleted file mode 100644
index c2a04fc..0000000
--- a/views/bubble/bubble_view_unittest.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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.
-
-#include "views/bubble/bubble_delegate.h"
-#include "views/test/views_test_base.h"
-#include "views/widget/widget.h"
-
-namespace views {
-
-namespace {
-
-typedef ViewsTestBase BubbleViewBasicTest;
-
-TEST_F(BubbleViewBasicTest, CreateArrowBubble) {
- BubbleDelegateView* bubble_delegate = new BubbleDelegateView();
- scoped_ptr<Widget> bubble_widget(
- views::BubbleDelegateView::CreateBubble(bubble_delegate, NULL));
-
- BubbleBorder* border = static_cast<BubbleBorder*>(
- bubble_widget->non_client_view()->frame_view()->border());
- EXPECT_EQ(bubble_delegate->GetArrowLocation(), border->arrow_location());
- bubble_widget->CloseNow();
- bubble_widget.reset();
- RunPendingMessages();
-}
-
-} // namespace
-
-} // namespace views
diff --git a/views/examples/bubble_example.cc b/views/examples/bubble_example.cc
index f99155b..b0d5ec4 100644
--- a/views/examples/bubble_example.cc
+++ b/views/examples/bubble_example.cc
@@ -88,13 +88,13 @@ void BubbleExample::ButtonPressed(views::Button* sender,
ExampleBubbleDelegateView* bubble_delegate =
new ExampleBubbleDelegateView(config);
- views::Widget* bubble = views::BubbleDelegateView::CreateBubble(
- bubble_delegate, example_view()->GetWidget());
+ views::BubbleDelegateView::CreateBubble(bubble_delegate,
+ example_view()->GetWidget());
if (config.fade_in)
bubble_delegate->StartFade(true);
else
- bubble->Show();
+ bubble_delegate->Show();
if (config.fade_out) {
bubble_delegate->set_close_on_esc(false);
diff --git a/views/views.gyp b/views/views.gyp
index 09cadf9..b8082a4 100644
--- a/views/views.gyp
+++ b/views/views.gyp
@@ -572,7 +572,6 @@
'animation/bounds_animator_unittest.cc',
'bubble/bubble_delegate_unittest.cc',
'bubble/bubble_frame_view_unittest.cc',
- 'bubble/bubble_view_unittest.cc',
'controls/label_unittest.cc',
'controls/progress_bar_unittest.cc',
'controls/single_split_view_unittest.cc',
diff --git a/views/window/client_view.cc b/views/window/client_view.cc
index 5b0d006..f0dc66a 100644
--- a/views/window/client_view.cc
+++ b/views/window/client_view.cc
@@ -37,14 +37,6 @@ const DialogClientView* ClientView::AsDialogClientView() const {
return NULL;
}
-BubbleView* ClientView::AsBubbleView() {
- return NULL;
-}
-
-const BubbleView* ClientView::AsBubbleView() const {
- return NULL;
-}
-
bool ClientView::CanClose() {
return true;
}
diff --git a/views/window/client_view.h b/views/window/client_view.h
index f45e508..4cd6f14 100644
--- a/views/window/client_view.h
+++ b/views/window/client_view.h
@@ -10,7 +10,6 @@
namespace views {
-class BubbleView;
class DialogClientView;
class Widget;
@@ -37,8 +36,6 @@ class VIEWS_EXPORT ClientView : public View {
// Manual RTTI ftw.
virtual DialogClientView* AsDialogClientView();
virtual const DialogClientView* AsDialogClientView() const;
- virtual BubbleView* AsBubbleView();
- virtual const BubbleView* AsBubbleView() const;
// Returns true to signal that the Widget can be closed. Specialized
// ClientView subclasses can override this default behavior to allow the