summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorvarkha <varkha@chromium.org>2015-11-27 08:54:00 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-27 16:54:43 +0000
commitbcd9c28cd2858c07ef2b0b5107e1c5523cf84645 (patch)
treedbb8620eb9f37f489a3881f004f943d65e89ed35
parente20defea3ea7b641bb91fce301cc000b44c0f92c (diff)
downloadchromium_src-bcd9c28cd2858c07ef2b0b5107e1c5523cf84645.zip
chromium_src-bcd9c28cd2858c07ef2b0b5107e1c5523cf84645.tar.gz
chromium_src-bcd9c28cd2858c07ef2b0b5107e1c5523cf84645.tar.bz2
Refactor ink drop animations to allow adding them to any View
and not just Button descendants. This CL is upstreamed to https://codereview.chromium.org/1409183003/ Looking for a way to allow organizing event handling necessary for ink drop animations. See goals description here: https://docs.google.com/document/d/1U4AdR4wZVsZ8g0y95EblY5YiYVbVXcBTJ59XJBF147M/edit#heading=h.ai99f1d1eumr BUG=537202 Review URL: https://codereview.chromium.org/1411833006 Cr-Commit-Position: refs/heads/master@{#362013}
-rw-r--r--chrome/browser/ui/views/bar_control_button.cc7
-rw-r--r--chrome/browser/ui/views/bar_control_button.h1
-rw-r--r--chrome/browser/ui/views/toolbar/app_menu_button.cc21
-rw-r--r--chrome/browser/ui/views/toolbar/app_menu_button.h1
-rw-r--r--chrome/browser/ui/views/toolbar/toolbar_action_view.cc142
-rw-r--r--chrome/browser/ui/views/toolbar/toolbar_action_view.h31
-rw-r--r--chrome/browser/ui/views/toolbar/toolbar_button.cc8
-rw-r--r--chrome/browser/ui/views/toolbar/toolbar_button.h6
-rw-r--r--ui/aura/window.cc4
-rw-r--r--ui/events/event_processor_unittest.cc3
-rw-r--r--ui/events/event_target.cc6
-rw-r--r--ui/events/event_target.h5
-rw-r--r--ui/views/animation/button_ink_drop_delegate.cc87
-rw-r--r--ui/views/animation/button_ink_drop_delegate.h54
-rw-r--r--ui/views/animation/ink_drop_delegate.h48
-rw-r--r--ui/views/animation/ink_drop_host.h5
-rw-r--r--ui/views/animation/test/test_ink_drop_host.cc4
-rw-r--r--ui/views/animation/test/test_ink_drop_host.h1
-rw-r--r--ui/views/controls/button/custom_button.cc18
-rw-r--r--ui/views/controls/button/custom_button.h12
-rw-r--r--ui/views/controls/button/label_button.cc1
-rw-r--r--ui/views/controls/button/menu_button.cc5
-rw-r--r--ui/views/controls/button/menu_button.h2
-rw-r--r--ui/views/scoped_target_handler.cc67
-rw-r--r--ui/views/scoped_target_handler.h55
-rw-r--r--ui/views/view_unittest.cc58
-rw-r--r--ui/views/views.gyp5
27 files changed, 577 insertions, 80 deletions
diff --git a/chrome/browser/ui/views/bar_control_button.cc b/chrome/browser/ui/views/bar_control_button.cc
index e8c727c..6eb966b 100644
--- a/chrome/browser/ui/views/bar_control_button.cc
+++ b/chrome/browser/ui/views/bar_control_button.cc
@@ -66,8 +66,7 @@ void BarControlButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
void BarControlButton::Layout() {
ImageButton::Layout();
- ink_drop_animation_controller_->SetInkDropCenter(
- GetLocalBounds().CenterPoint());
+ ink_drop_animation_controller_->SetInkDropCenter(CalculateInkDropCenter());
}
void BarControlButton::AddInkDropLayer(ui::Layer* ink_drop_layer) {
@@ -85,6 +84,10 @@ void BarControlButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
SetPaintToLayer(false);
}
+gfx::Point BarControlButton::CalculateInkDropCenter() const {
+ return GetLocalBounds().CenterPoint();
+}
+
bool BarControlButton::OnMousePressed(const ui::MouseEvent& event) {
if (IsTriggerableEvent(event)) {
ink_drop_animation_controller_->AnimateToState(
diff --git a/chrome/browser/ui/views/bar_control_button.h b/chrome/browser/ui/views/bar_control_button.h
index 7a997cc..8bc3917 100644
--- a/chrome/browser/ui/views/bar_control_button.h
+++ b/chrome/browser/ui/views/bar_control_button.h
@@ -43,6 +43,7 @@ class BarControlButton : public views::ImageButton, public views::InkDropHost {
// views::InkDropHost:
void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override;
+ gfx::Point CalculateInkDropCenter() const override;
gfx::VectorIconId id_;
base::Callback<SkColor(void)> get_text_color_callback_;
diff --git a/chrome/browser/ui/views/toolbar/app_menu_button.cc b/chrome/browser/ui/views/toolbar/app_menu_button.cc
index bca918d..6a1e488 100644
--- a/chrome/browser/ui/views/toolbar/app_menu_button.cc
+++ b/chrome/browser/ui/views/toolbar/app_menu_button.cc
@@ -211,6 +211,17 @@ void AppMenuButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
SetPaintToLayer(false);
}
+gfx::Point AppMenuButton::CalculateInkDropCenter() const {
+ // ToolbarView extends the bounds of the app button to the right in maximized
+ // mode. So instead of using the center point of local bounds, we use the
+ // center point (adjusted for RTL layouts) of the preferred size, which
+ // doesn't change in maximized mode.
+ const int visible_width = GetPreferredSize().width();
+ return gfx::Point(
+ (GetMirroredXWithWidthInView(0, visible_width) + visible_width) / 2,
+ height() / 2);
+}
+
const char* AppMenuButton::GetClassName() const {
return "AppMenuButton";
}
@@ -259,15 +270,7 @@ bool AppMenuButton::CanDrop(const ui::OSExchangeData& data) {
void AppMenuButton::Layout() {
MenuButton::Layout();
-
- // ToolbarView extends the bounds of the app button to the right in maximized
- // mode. So instead of using the center point of local bounds, we use the
- // center point (adjusted for RTL layouts) of preferred size which doesn't
- // change in maximized mode.
- const int visible_width = GetPreferredSize().width();
- ink_drop_animation_controller_->SetInkDropCenter(gfx::Point(
- (GetMirroredXWithWidthInView(0, visible_width) + visible_width) / 2,
- height() / 2));
+ ink_drop_animation_controller_->SetInkDropCenter(CalculateInkDropCenter());
}
void AppMenuButton::OnDragEntered(const ui::DropTargetEvent& event) {
diff --git a/chrome/browser/ui/views/toolbar/app_menu_button.h b/chrome/browser/ui/views/toolbar/app_menu_button.h
index bb677f7..2536f543 100644
--- a/chrome/browser/ui/views/toolbar/app_menu_button.h
+++ b/chrome/browser/ui/views/toolbar/app_menu_button.h
@@ -74,6 +74,7 @@ class AppMenuButton : public views::InkDropHost,
// views::InkDropHost:
void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override;
+ gfx::Point CalculateInkDropCenter() const override;
// views::MenuButton:
const char* GetClassName() const override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
index 2843f70..524fb95 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.cc
@@ -26,6 +26,7 @@
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/image/image_skia_source.h"
#include "ui/resources/grit/ui_resources.h"
+#include "ui/views/animation/button_ink_drop_delegate.h"
#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/controls/menu/menu_model_adapter.h"
@@ -67,6 +68,9 @@ ToolbarActionView::ToolbarActionView(
wants_to_run_(false),
menu_(nullptr),
weak_factory_(this) {
+ scoped_ptr<views::InkDropDelegate> new_ink_drop_delegate(
+ new views::ButtonInkDropDelegate(this, this));
+ SetInkDropDelegate(new_ink_drop_delegate.Pass());
set_id(VIEW_ID_BROWSER_ACTION);
view_controller_->SetDelegate(this);
SetHorizontalAlignment(gfx::ALIGN_CENTER);
@@ -74,6 +78,14 @@ ToolbarActionView::ToolbarActionView(
set_context_menu_controller(this);
+ const int kInkDropLargeSize = 32;
+ const int kInkDropLargeCornerRadius = 5;
+ const int kInkDropSmallSize = 24;
+ const int kInkDropSmallCornerRadius = 2;
+ ink_drop_delegate()->SetInkDropSize(
+ kInkDropLargeSize, kInkDropLargeCornerRadius, kInkDropSmallSize,
+ kInkDropSmallCornerRadius);
+
// We also listen for browser theme changes on linux because a switch from or
// to GTK requires that we regrab our browser action images.
registrar_.Add(
@@ -99,42 +111,31 @@ ToolbarActionView::~ToolbarActionView() {
view_controller_->SetDelegate(nullptr);
}
-gfx::Size ToolbarActionView::GetPreferredSize() const {
- return gfx::Size(ToolbarActionsBar::IconWidth(false),
- ToolbarActionsBar::IconHeight());
+void ToolbarActionView::GetAccessibleState(ui::AXViewState* state) {
+ views::MenuButton::GetAccessibleState(state);
+ state->role = ui::AX_ROLE_BUTTON;
}
-void ToolbarActionView::OnDragDone() {
- views::MenuButton::OnDragDone();
- delegate_->OnToolbarActionViewDragDone();
+scoped_ptr<LabelButtonBorder> ToolbarActionView::CreateDefaultBorder() const {
+ scoped_ptr<LabelButtonBorder> border = LabelButton::CreateDefaultBorder();
+ border->set_insets(gfx::Insets(kBorderInset, kBorderInset,
+ kBorderInset, kBorderInset));
+ return border.Pass();
}
-void ToolbarActionView::ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) {
- if (details.is_add && !called_register_command_ && GetFocusManager()) {
- view_controller_->RegisterCommand();
- called_register_command_ = true;
- }
-
- MenuButton::ViewHierarchyChanged(details);
+void ToolbarActionView::OnMouseEntered(const ui::MouseEvent& event) {
+ delegate_->OnMouseEnteredToolbarActionView();
+ views::MenuButton::OnMouseEntered(event);
}
-void ToolbarActionView::GetAccessibleState(ui::AXViewState* state) {
- views::MenuButton::GetAccessibleState(state);
- state->role = ui::AX_ROLE_BUTTON;
+bool ToolbarActionView::ShouldEnterPushedState(const ui::Event& event) {
+ return views::MenuButton::ShouldEnterPushedState(event) &&
+ (base::TimeTicks::Now() - popup_closed_time_).InMilliseconds() >
+ views::kMinimumMsBetweenButtonClicks;
}
-void ToolbarActionView::OnMenuButtonClicked(views::View* sender,
- const gfx::Point& point) {
- if (!view_controller_->IsEnabled(GetCurrentWebContents())) {
- // We should only get a button pressed event with a non-enabled action if
- // the left-click behavior should open the menu.
- DCHECK(view_controller_->DisabledClickOpensMenu());
- context_menu_controller()->ShowContextMenuForView(this, point,
- ui::MENU_SOURCE_NONE);
- } else {
- view_controller_->ExecuteAction(true);
- }
+content::WebContents* ToolbarActionView::GetCurrentWebContents() const {
+ return delegate_->GetCurrentWebContents();
}
void ToolbarActionView::UpdateState() {
@@ -170,6 +171,19 @@ void ToolbarActionView::UpdateState() {
SchedulePaint();
}
+void ToolbarActionView::OnMenuButtonClicked(views::View* sender,
+ const gfx::Point& point) {
+ if (!view_controller_->IsEnabled(GetCurrentWebContents())) {
+ // We should only get a button pressed event with a non-enabled action if
+ // the left-click behavior should open the menu.
+ DCHECK(view_controller_->DisabledClickOpensMenu());
+ context_menu_controller()->ShowContextMenuForView(this, point,
+ ui::MENU_SOURCE_NONE);
+ } else {
+ view_controller_->ExecuteAction(true);
+ }
+}
+
void ToolbarActionView::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
@@ -177,22 +191,22 @@ void ToolbarActionView::Observe(int type,
UpdateState();
}
-void ToolbarActionView::OnMouseEntered(const ui::MouseEvent& event) {
- delegate_->OnMouseEnteredToolbarActionView();
- views::MenuButton::OnMouseEntered(event);
-}
+void ToolbarActionView::AddInkDropLayer(ui::Layer* ink_drop_layer) {
+ SetPaintToLayer(true);
+ SetFillsBoundsOpaquely(false);
+ image()->SetPaintToLayer(true);
+ image()->SetFillsBoundsOpaquely(false);
-bool ToolbarActionView::ShouldEnterPushedState(const ui::Event& event) {
- return views::MenuButton::ShouldEnterPushedState(event) &&
- (base::TimeTicks::Now() - popup_closed_time_).InMilliseconds() >
- views::kMinimumMsBetweenButtonClicks;
+ layer()->Add(ink_drop_layer);
+ layer()->StackAtBottom(ink_drop_layer);
}
-scoped_ptr<LabelButtonBorder> ToolbarActionView::CreateDefaultBorder() const {
- scoped_ptr<LabelButtonBorder> border = LabelButton::CreateDefaultBorder();
- border->set_insets(gfx::Insets(kBorderInset, kBorderInset,
- kBorderInset, kBorderInset));
- return border.Pass();
+void ToolbarActionView::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
+ layer()->Remove(ink_drop_layer);
+
+ image()->SetFillsBoundsOpaquely(true);
+ image()->SetPaintToLayer(false);
+ SetPaintToLayer(false);
}
gfx::ImageSkia ToolbarActionView::GetIconForTest() {
@@ -204,6 +218,41 @@ void ToolbarActionView::set_context_menu_callback_for_testing(
context_menu_callback = callback;
}
+gfx::Size ToolbarActionView::GetPreferredSize() const {
+ return gfx::Size(ToolbarActionsBar::IconWidth(false),
+ ToolbarActionsBar::IconHeight());
+}
+
+bool ToolbarActionView::OnMousePressed(const ui::MouseEvent& event) {
+ // views::MenuButton actions are only triggered by left mouse clicks.
+ if (event.IsOnlyLeftMouseButton())
+ ink_drop_delegate()->OnAction(views::InkDropState::ACTION_PENDING);
+ return MenuButton::OnMousePressed(event);
+}
+
+void ToolbarActionView::OnGestureEvent(ui::GestureEvent* event) {
+ // While the dropdown menu is showing, the button should not handle gestures.
+ if (menu_)
+ event->StopPropagation();
+ else
+ MenuButton::OnGestureEvent(event);
+}
+
+void ToolbarActionView::OnDragDone() {
+ views::MenuButton::OnDragDone();
+ delegate_->OnToolbarActionViewDragDone();
+}
+
+void ToolbarActionView::ViewHierarchyChanged(
+ const ViewHierarchyChangedDetails& details) {
+ if (details.is_add && !called_register_command_ && GetFocusManager()) {
+ view_controller_->RegisterCommand();
+ called_register_command_ = true;
+ }
+
+ MenuButton::ViewHierarchyChanged(details);
+}
+
views::View* ToolbarActionView::GetAsView() {
return this;
}
@@ -223,10 +272,6 @@ bool ToolbarActionView::IsMenuRunning() const {
return menu_ != nullptr;
}
-content::WebContents* ToolbarActionView::GetCurrentWebContents() const {
- return delegate_->GetCurrentWebContents();
-}
-
void ToolbarActionView::OnPopupShown(bool by_user) {
// If this was through direct user action, we press the menu button.
if (by_user) {
@@ -271,6 +316,10 @@ void ToolbarActionView::ShowContextMenuForView(
DoShowContextMenu(source_type);
}
+gfx::Point ToolbarActionView::CalculateInkDropCenter() const {
+ return GetLocalBounds().CenterPoint();
+}
+
void ToolbarActionView::DoShowContextMenu(
ui::MenuSourceType source_type) {
ui::MenuModel* context_menu_model = view_controller_->GetContextMenu();
@@ -295,6 +344,8 @@ void ToolbarActionView::DoShowContextMenu(
delegate_->GetOverflowReferenceView()->GetWidget() :
GetWidget();
+ ink_drop_delegate()->OnAction(views::InkDropState::ACTIVATED);
+
views::MenuModelAdapter adapter(context_menu_model);
menu_ = adapter.CreateMenu();
menu_runner_.reset(new views::MenuRunner(menu_, run_types));
@@ -306,6 +357,7 @@ void ToolbarActionView::DoShowContextMenu(
source_type) == views::MenuRunner::MENU_DELETED) {
return;
}
+ ink_drop_delegate()->OnAction(views::InkDropState::DEACTIVATED);
menu_runner_.reset();
menu_ = nullptr;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view.h b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
index 73e607e..7df2efe 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view.h
@@ -9,6 +9,7 @@
#include "chrome/browser/ui/views/toolbar/toolbar_action_view_delegate_views.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#include "ui/views/animation/ink_drop_host.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/controls/button/menu_button_listener.h"
@@ -39,7 +40,8 @@ class ToolbarActionView : public views::MenuButton,
public ToolbarActionViewDelegateViews,
public views::MenuButtonListener,
public views::ContextMenuController,
- public content::NotificationObserver {
+ public content::NotificationObserver,
+ public views::InkDropHost {
public:
// Need DragController here because ToolbarActionView could be
// dragged/dropped.
@@ -65,6 +67,9 @@ class ToolbarActionView : public views::MenuButton,
~Delegate() override {}
};
+ // Callback type used for testing.
+ using ContextMenuCallback = base::Callback<void(ToolbarActionView*)>;
+
ToolbarActionView(ToolbarActionViewController* view_controller,
Profile* profile,
Delegate* delegate);
@@ -72,6 +77,13 @@ class ToolbarActionView : public views::MenuButton,
// views::MenuButton:
void GetAccessibleState(ui::AXViewState* state) override;
+ scoped_ptr<views::LabelButtonBorder> CreateDefaultBorder() const override;
+ void OnMouseEntered(const ui::MouseEvent& event) override;
+ bool ShouldEnterPushedState(const ui::Event& event) override;
+
+ // ToolbarActionViewDelegateViews:
+ content::WebContents* GetCurrentWebContents() const override;
+ void UpdateState() override;
// views::MenuButtonListener:
void OnMenuButtonClicked(views::View* sender,
@@ -82,14 +94,9 @@ class ToolbarActionView : public views::MenuButton,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
- // views::MenuButton:
- scoped_ptr<views::LabelButtonBorder> CreateDefaultBorder() const override;
- void OnMouseEntered(const ui::MouseEvent& event) override;
- bool ShouldEnterPushedState(const ui::Event& event) override;
-
- // ToolbarActionViewDelegate: (public because called by others).
- void UpdateState() override;
- content::WebContents* GetCurrentWebContents() const override;
+ // views::InkDropHost:
+ void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
+ void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override;
ToolbarActionViewController* view_controller() {
return view_controller_;
@@ -100,7 +107,6 @@ class ToolbarActionView : public views::MenuButton,
bool wants_to_run_for_testing() const { return wants_to_run_; }
- using ContextMenuCallback = base::Callback<void(ToolbarActionView*)>;
// Set a callback to be called directly before the context menu is shown.
// The toolbar action opening the menu will be passed in.
static void set_context_menu_callback_for_testing(
@@ -111,6 +117,8 @@ class ToolbarActionView : public views::MenuButton,
private:
// views::MenuButton:
gfx::Size GetPreferredSize() const override;
+ bool OnMousePressed(const ui::MouseEvent& event) override;
+ void OnGestureEvent(ui::GestureEvent* event) override;
void OnDragDone() override;
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override;
@@ -128,6 +136,9 @@ class ToolbarActionView : public views::MenuButton,
const gfx::Point& point,
ui::MenuSourceType source_type) override;
+ // views::InkDropHost:
+ gfx::Point CalculateInkDropCenter() const override;
+
// Shows the context menu (if one exists) for the toolbar action.
void DoShowContextMenu(ui::MenuSourceType source_type);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc
index f4c889b..f73fa3c 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -347,10 +347,10 @@ void ToolbarButton::ShowDropDownMenu(ui::MenuSourceType source_type) {
SetState(STATE_NORMAL);
}
-gfx::Point ToolbarButton::CalculateInkDropCenter() const {
- return GetLocalBounds().CenterPoint();
-}
-
const char* ToolbarButton::GetClassName() const {
return "ToolbarButton";
}
+
+gfx::Point ToolbarButton::CalculateInkDropCenter() const {
+ return GetLocalBounds().CenterPoint();
+}
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.h b/chrome/browser/ui/views/toolbar/toolbar_button.h
index f607a44..a9d7b84 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.h
@@ -73,9 +73,6 @@ class ToolbarButton : public views::LabelButton,
// Function to show the dropdown menu.
virtual void ShowDropDownMenu(ui::MenuSourceType source_type);
- // Returns the Point where the ink drop should be centered.
- virtual gfx::Point CalculateInkDropCenter() const;
-
views::InkDropAnimationController* ink_drop_animation_controller() {
return ink_drop_animation_controller_.get();
}
@@ -84,6 +81,9 @@ class ToolbarButton : public views::LabelButton,
// views::LabelButton:
const char* GetClassName() const override;
+ // views::InkDropHost:
+ gfx::Point CalculateInkDropCenter() const override;
+
// The model that populates the attached menu.
scoped_ptr<ui::MenuModel> model_;
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index c97941d..2634eba 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -93,7 +93,7 @@ Window::Window(WindowDelegate* delegate)
// problems for code that adds an observer as part of an observer
// notification (such as the workspace code).
observers_(base::ObserverList<WindowObserver>::NOTIFY_EXISTING_ONLY) {
- set_target_handler(delegate_);
+ SetTargetHandler(delegate_);
}
Window::~Window() {
@@ -109,7 +109,7 @@ Window::~Window() {
// While we are being destroyed, our target handler may also be in the
// process of destruction or already destroyed, so do not forward any
// input events at the ui::EP_TARGET phase.
- set_target_handler(nullptr);
+ SetTargetHandler(nullptr);
// TODO(beng): See comment in window_event_dispatcher.h. This shouldn't be
// necessary but unfortunately is right now due to ordering
diff --git a/ui/events/event_processor_unittest.cc b/ui/events/event_processor_unittest.cc
index a0ab5b6..c563c17 100644
--- a/ui/events/event_processor_unittest.cc
+++ b/ui/events/event_processor_unittest.cc
@@ -4,6 +4,7 @@
#include <vector>
+#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event.h"
#include "ui/events/event_target_iterator.h"
@@ -139,7 +140,7 @@ TEST_F(EventProcessorTest, NestedEventProcessing) {
// first event processor should be handled by |target_handler| instead.
scoped_ptr<TestEventHandler> target_handler(
new ReDispatchEventHandler(second_processor.get(), root()->child_at(0)));
- root()->child_at(0)->set_target_handler(target_handler.get());
+ ignore_result(root()->child_at(0)->SetTargetHandler(target_handler.get()));
// Dispatch a mouse event to the tree of event targets owned by the first
// event processor, checking in ReDispatchEventHandler that the phase and
diff --git a/ui/events/event_target.cc b/ui/events/event_target.cc
index 9b44f9a..2e07219 100644
--- a/ui/events/event_target.cc
+++ b/ui/events/event_target.cc
@@ -56,6 +56,12 @@ bool EventTarget::IsPreTargetListEmpty() const {
return pre_target_list_.empty();
}
+EventHandler* EventTarget::SetTargetHandler(EventHandler* target_handler) {
+ EventHandler* original_target_handler = target_handler_;
+ target_handler_ = target_handler;
+ return original_target_handler;
+}
+
void EventTarget::OnEvent(Event* event) {
CHECK_EQ(this, event->target());
if (target_handler_)
diff --git a/ui/events/event_target.h b/ui/events/event_target.h
index e8b14a6..21a84a4 100644
--- a/ui/events/event_target.h
+++ b/ui/events/event_target.h
@@ -77,9 +77,8 @@ class EVENTS_EXPORT EventTarget : public EventHandler {
// Returns true if the event pre target list is empty.
bool IsPreTargetListEmpty() const;
- void set_target_handler(EventHandler* handler) {
- target_handler_ = handler;
- }
+ // Sets |target_handler| as |target_handler_| and returns the old handler.
+ EventHandler* SetTargetHandler(EventHandler* target_handler);
protected:
EventHandler* target_handler() { return target_handler_; }
diff --git a/ui/views/animation/button_ink_drop_delegate.cc b/ui/views/animation/button_ink_drop_delegate.cc
new file mode 100644
index 0000000..5d3b9eb
--- /dev/null
+++ b/ui/views/animation/button_ink_drop_delegate.cc
@@ -0,0 +1,87 @@
+// Copyright 2015 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 "ui/views/animation/button_ink_drop_delegate.h"
+
+#include "ui/events/event.h"
+#include "ui/views/animation/ink_drop_animation_controller.h"
+#include "ui/views/animation/ink_drop_animation_controller_factory.h"
+#include "ui/views/animation/ink_drop_host.h"
+#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/scoped_target_handler.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+ButtonInkDropDelegate::ButtonInkDropDelegate(InkDropHost* ink_drop_host,
+ View* view)
+ : target_handler_(new views::ScopedTargetHandler(view, this)),
+ ink_drop_host_(ink_drop_host),
+ ink_drop_animation_controller_(
+ InkDropAnimationControllerFactory::CreateInkDropAnimationController(
+ ink_drop_host_)) {}
+
+ButtonInkDropDelegate::~ButtonInkDropDelegate() {
+}
+
+void ButtonInkDropDelegate::SetInkDropSize(int large_size,
+ int large_corner_radius,
+ int small_size,
+ int small_corner_radius) {
+ ink_drop_animation_controller_->SetInkDropSize(
+ gfx::Size(large_size, large_size), large_corner_radius,
+ gfx::Size(small_size, small_size), small_corner_radius);
+}
+
+void ButtonInkDropDelegate::OnLayout() {
+ ink_drop_animation_controller_->SetInkDropCenter(
+ ink_drop_host_->CalculateInkDropCenter());
+}
+
+void ButtonInkDropDelegate::OnAction(InkDropState state) {
+ ink_drop_animation_controller_->AnimateToState(state);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ui::EventHandler:
+
+void ButtonInkDropDelegate::OnGestureEvent(ui::GestureEvent* event) {
+ InkDropState ink_drop_state = InkDropState::HIDDEN;
+ switch (event->type()) {
+ case ui::ET_GESTURE_TAP_DOWN:
+ ink_drop_state = InkDropState::ACTION_PENDING;
+ // The ui::ET_GESTURE_TAP_DOWN event needs to be marked as handled so that
+ // subsequent events for the gesture are sent to |this|.
+ event->SetHandled();
+ break;
+ case ui::ET_GESTURE_LONG_PRESS:
+ ink_drop_state = InkDropState::SLOW_ACTION_PENDING;
+ break;
+ case ui::ET_GESTURE_LONG_TAP:
+ ink_drop_state = InkDropState::SLOW_ACTION;
+ break;
+ case ui::ET_GESTURE_SCROLL_BEGIN:
+ case ui::ET_GESTURE_END:
+ ink_drop_state = InkDropState::HIDDEN;
+ break;
+ default:
+ return;
+ }
+
+ InkDropState current_ink_drop_state =
+ ink_drop_animation_controller_->GetInkDropState();
+
+ if (ink_drop_state == InkDropState::HIDDEN &&
+ (current_ink_drop_state == InkDropState::QUICK_ACTION ||
+ current_ink_drop_state == InkDropState::SLOW_ACTION ||
+ current_ink_drop_state == InkDropState::DEACTIVATED)) {
+ // These InkDropStates automatically transition to the HIDDEN state so we
+ // don't make an explicit call. Explicitly animating to HIDDEN in this case
+ // would prematurely pre-empt these animations.
+ return;
+ }
+ ink_drop_animation_controller_->AnimateToState(ink_drop_state);
+}
+
+} // namespace views
diff --git a/ui/views/animation/button_ink_drop_delegate.h b/ui/views/animation/button_ink_drop_delegate.h
new file mode 100644
index 0000000..1deb51c
--- /dev/null
+++ b/ui/views/animation/button_ink_drop_delegate.h
@@ -0,0 +1,54 @@
+// Copyright 2015 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 UI_VIEWS_ANIMATION_BUTTON_INK_DROP_DELEGATE_H_
+#define UI_VIEWS_ANIMATION_BUTTON_INK_DROP_DELEGATE_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/events/event_handler.h"
+#include "ui/views/animation/ink_drop_delegate.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class InkDropAnimationController;
+class InkDropHost;
+class ScopedTargetHandler;
+class View;
+
+// An InkDropDelegate that handles animations for toolbar buttons.
+class VIEWS_EXPORT ButtonInkDropDelegate : public InkDropDelegate,
+ public ui::EventHandler {
+ public:
+ ButtonInkDropDelegate(InkDropHost* ink_drop_host, View* view);
+ ~ButtonInkDropDelegate() override;
+
+ // InkDropDelegate:
+ void SetInkDropSize(int large_size,
+ int large_corner_radius,
+ int small_size,
+ int small_corner_radius) override;
+ void OnLayout() override;
+ void OnAction(InkDropState state) override;
+
+ // ui::EventHandler:
+ void OnGestureEvent(ui::GestureEvent* event) override;
+
+ private:
+ // An instance of ScopedTargetHandler allowing |this| to handling events.
+ scoped_ptr<views::ScopedTargetHandler> target_handler_;
+
+ // Parent InkDropHost (typically a View) that hosts the ink ripple animations.
+ InkDropHost* ink_drop_host_;
+
+ // Animation controller for the ink drop ripple effect.
+ scoped_ptr<InkDropAnimationController> ink_drop_animation_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(ButtonInkDropDelegate);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_BUTTON_INK_DROP_DELEGATE_H_
diff --git a/ui/views/animation/ink_drop_delegate.h b/ui/views/animation/ink_drop_delegate.h
new file mode 100644
index 0000000..f8f7861
--- /dev/null
+++ b/ui/views/animation/ink_drop_delegate.h
@@ -0,0 +1,48 @@
+// Copyright 2015 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 UI_VIEWS_ANIMATION_INK_DROP_DELEGATE_H_
+#define UI_VIEWS_ANIMATION_INK_DROP_DELEGATE_H_
+
+#include "base/macros.h"
+#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/views_export.h"
+
+namespace ui {
+class GestureEvent;
+class Event;
+} // namespace ui
+
+namespace views {
+
+// Ink ripple animation delegate that starts and stops animations based on
+// View states and events.
+class VIEWS_EXPORT InkDropDelegate {
+ public:
+ InkDropDelegate() {}
+ virtual ~InkDropDelegate() {}
+
+ // Sets sizes for the animation layers that are squares with |large_size| and
+ // |small_size| being the length of each side. When painting rounded squares
+ // |large_corner_radius| and |small_corner_radius| are specifying the
+ // corner radius.
+ virtual void SetInkDropSize(int large_size,
+ int large_corner_radius,
+ int small_size,
+ int small_corner_radius) = 0;
+
+ // Called when the bounds or layout of the View changes necessitating change
+ // in positioning of ink ripple layers.
+ virtual void OnLayout() = 0;
+
+ // Called when ink ripple state changes.
+ virtual void OnAction(InkDropState state) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InkDropDelegate);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_INK_DROP_DELEGATE_H_
diff --git a/ui/views/animation/ink_drop_host.h b/ui/views/animation/ink_drop_host.h
index 4045e09..0830a41 100644
--- a/ui/views/animation/ink_drop_host.h
+++ b/ui/views/animation/ink_drop_host.h
@@ -6,6 +6,7 @@
#define UI_VIEWS_ANIMATION_INK_DROP_HOST_H_
#include "base/macros.h"
+#include "ui/gfx/geometry/point.h"
#include "ui/views/views_export.h"
namespace ui {
@@ -32,6 +33,10 @@ class VIEWS_EXPORT InkDropHost {
// Removes |ink_drop_layer| from the layer tree.
virtual void RemoveInkDropLayer(ui::Layer* ink_drop_layer) = 0;
+ // Returns the Point where the ink drop should be centered.
+ // TODO(varkha): This should be moved to InkDropConsumer.
+ virtual gfx::Point CalculateInkDropCenter() const = 0;
+
private:
DISALLOW_COPY_AND_ASSIGN(InkDropHost);
};
diff --git a/ui/views/animation/test/test_ink_drop_host.cc b/ui/views/animation/test/test_ink_drop_host.cc
index 4a30ff6..b853820 100644
--- a/ui/views/animation/test/test_ink_drop_host.cc
+++ b/ui/views/animation/test/test_ink_drop_host.cc
@@ -14,4 +14,8 @@ void TestInkDropHost::AddInkDropLayer(ui::Layer* ink_drop_layer) {}
void TestInkDropHost::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {}
+gfx::Point TestInkDropHost::CalculateInkDropCenter() const {
+ return gfx::Point();
+}
+
} // namespace views
diff --git a/ui/views/animation/test/test_ink_drop_host.h b/ui/views/animation/test/test_ink_drop_host.h
index e94839d..b952b77 100644
--- a/ui/views/animation/test/test_ink_drop_host.h
+++ b/ui/views/animation/test/test_ink_drop_host.h
@@ -20,6 +20,7 @@ class TestInkDropHost : public InkDropHost {
// TestInkDropHost:
void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override;
+ gfx::Point CalculateInkDropCenter() const override;
private:
DISALLOW_COPY_AND_ASSIGN(TestInkDropHost);
diff --git a/ui/views/controls/button/custom_button.cc b/ui/views/controls/button/custom_button.cc
index aafbf2d..66d9b2c 100644
--- a/ui/views/controls/button/custom_button.cc
+++ b/ui/views/controls/button/custom_button.cc
@@ -10,6 +10,7 @@
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/animation/throb_animation.h"
#include "ui/gfx/screen.h"
+#include "ui/views/animation/ink_drop_delegate.h"
#include "ui/views/controls/button/blue_button.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/image_button.h"
@@ -116,6 +117,11 @@ bool CustomButton::IsHotTracked() const {
////////////////////////////////////////////////////////////////////////////////
// CustomButton, View overrides:
+void CustomButton::Layout() {
+ if (ink_drop_delegate_)
+ ink_drop_delegate_->OnLayout();
+}
+
void CustomButton::OnEnabledChanged() {
if (enabled() ? (state_ != STATE_DISABLED) : (state_ == STATE_DISABLED))
return;
@@ -284,6 +290,8 @@ void CustomButton::OnDragDone() {
// (since disabled buttons may still be able to be dragged).
if (state_ != STATE_DISABLED)
SetState(STATE_NORMAL);
+ if (ink_drop_delegate_)
+ ink_drop_delegate_->OnAction(InkDropState::HIDDEN);
}
void CustomButton::GetAccessibleState(ui::AXViewState* state) {
@@ -371,9 +379,19 @@ bool CustomButton::ShouldEnterHoveredState() {
return check_mouse_position && IsMouseHovered();
}
+void CustomButton::SetInkDropDelegate(
+ scoped_ptr<InkDropDelegate> ink_drop_delegate) {
+ ink_drop_delegate_ = ink_drop_delegate.Pass();
+}
+
////////////////////////////////////////////////////////////////////////////////
// CustomButton, View overrides (protected):
+void CustomButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+ if (ink_drop_delegate_)
+ ink_drop_delegate_->OnLayout();
+}
+
void CustomButton::ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) {
if (!details.is_add && state_ != STATE_DISABLED)
diff --git a/ui/views/controls/button/custom_button.h b/ui/views/controls/button/custom_button.h
index 869bcd7..ef250c0 100644
--- a/ui/views/controls/button/custom_button.h
+++ b/ui/views/controls/button/custom_button.h
@@ -16,6 +16,8 @@ class ThrobAnimation;
namespace views {
+class InkDropDelegate;
+
// A button with custom rendering. The base of ImageButton and LabelButton.
// Note that this type of button is not focusable by default and will not be
// part of the focus chain. Call SetFocusable(true) to make it part of the
@@ -76,6 +78,7 @@ class VIEWS_EXPORT CustomButton : public Button,
bool IsHotTracked() const;
// Overridden from View:
+ void Layout() override;
void OnEnabledChanged() override;
const char* GetClassName() const override;
bool OnMousePressed(const ui::MouseEvent& event) override;
@@ -123,7 +126,13 @@ class VIEWS_EXPORT CustomButton : public Button,
// state). This does not take into account enabled state.
bool ShouldEnterHoveredState();
+ void SetInkDropDelegate(scoped_ptr<InkDropDelegate> ink_drop_delegate);
+ InkDropDelegate* ink_drop_delegate() const {
+ return ink_drop_delegate_.get();
+ }
+
// Overridden from View:
+ void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override;
void OnBlur() override;
@@ -152,6 +161,9 @@ class VIEWS_EXPORT CustomButton : public Button,
// See description above setter.
bool request_focus_on_press_;
+ // Animation delegate for the ink drop ripple effect.
+ scoped_ptr<InkDropDelegate> ink_drop_delegate_;
+
// The event on which the button should notify its listener.
NotifyAction notify_action_;
diff --git a/ui/views/controls/button/label_button.cc b/ui/views/controls/button/label_button.cc
index abd2c3f..2bb88c3 100644
--- a/ui/views/controls/button/label_button.cc
+++ b/ui/views/controls/button/label_button.cc
@@ -335,6 +335,7 @@ void LabelButton::Layout() {
image_->SetBoundsRect(gfx::Rect(image_origin, image_size));
label_->SetBoundsRect(gfx::Rect(label_origin, label_size));
+ CustomButton::Layout();
}
const char* LabelButton::GetClassName() const {
diff --git a/ui/views/controls/button/menu_button.cc b/ui/views/controls/button/menu_button.cc
index 5603548..22a79ae 100644
--- a/ui/views/controls/button/menu_button.cc
+++ b/ui/views/controls/button/menu_button.cc
@@ -18,6 +18,7 @@
#include "ui/gfx/text_constants.h"
#include "ui/resources/grit/ui_resources.h"
#include "ui/strings/grit/ui_strings.h"
+#include "ui/views/animation/ink_drop_delegate.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/menu_button_listener.h"
#include "ui/views/mouse_constants.h"
@@ -126,6 +127,8 @@ bool MenuButton::Activate() {
// We don't set our state here. It's handled in the MenuController code or
// by our click listener.
+ if (ink_drop_delegate())
+ ink_drop_delegate()->OnAction(InkDropState::QUICK_ACTION);
listener_->OnMenuButtonClicked(this, menu_position);
if (destroyed) {
@@ -189,6 +192,8 @@ void MenuButton::OnMouseReleased(const ui::MouseEvent& event) {
HitTestPoint(event.location()) && !InDrag()) {
Activate();
} else {
+ if (ink_drop_delegate())
+ ink_drop_delegate()->OnAction(InkDropState::HIDDEN);
LabelButton::OnMouseReleased(event);
}
}
diff --git a/ui/views/controls/button/menu_button.h b/ui/views/controls/button/menu_button.h
index 1881fd2..b7a1a8b 100644
--- a/ui/views/controls/button/menu_button.h
+++ b/ui/views/controls/button/menu_button.h
@@ -121,7 +121,7 @@ class VIEWS_EXPORT MenuButton : public LabelButton {
// The down arrow used to differentiate the menu button from normal buttons.
const gfx::ImageSkia* menu_marker_;
- // If non-null the destuctor sets this to true. This is set while the menu is
+ // If non-null the destructor sets this to true. This is set while the menu is
// showing and used to detect if the menu was deleted while running.
bool* destroyed_flag_;
diff --git a/ui/views/scoped_target_handler.cc b/ui/views/scoped_target_handler.cc
new file mode 100644
index 0000000..180a8a8
--- /dev/null
+++ b/ui/views/scoped_target_handler.cc
@@ -0,0 +1,67 @@
+// Copyright 2015 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 "ui/views/scoped_target_handler.h"
+
+#include "ui/events/event.h"
+#include "ui/events/event_handler.h"
+#include "ui/events/event_target.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+ScopedTargetHandler::ScopedTargetHandler(View* view,
+ ui::EventHandler* handler)
+ : destroyed_flag_(NULL), view_(view), new_handler_(handler){
+ original_handler_ = view_->SetTargetHandler(this);
+}
+
+ScopedTargetHandler::~ScopedTargetHandler() {
+ EventHandler* handler = view_->SetTargetHandler(original_handler_);
+ DCHECK_EQ(this, handler);
+ if (destroyed_flag_)
+ *destroyed_flag_ = true;
+}
+
+void ScopedTargetHandler::OnEvent(ui::Event* event) {
+ bool destroyed = false;
+ destroyed_flag_ = &destroyed;
+
+ if (original_handler_)
+ original_handler_->OnEvent(event);
+ else
+ EventHandler::OnEvent(event);
+
+ if (destroyed)
+ return;
+ destroyed_flag_ = NULL;
+
+ new_handler_->OnEvent(event);
+}
+
+void ScopedTargetHandler::OnKeyEvent(ui::KeyEvent* event) {
+ static_cast<EventHandler*>(view_)->OnKeyEvent(event);
+}
+
+void ScopedTargetHandler::OnMouseEvent(ui::MouseEvent* event) {
+ static_cast<EventHandler*>(view_)->OnMouseEvent(event);
+}
+
+void ScopedTargetHandler::OnScrollEvent(ui::ScrollEvent* event) {
+ static_cast<EventHandler*>(view_)->OnScrollEvent(event);
+}
+
+void ScopedTargetHandler::OnTouchEvent(ui::TouchEvent* event) {
+ static_cast<EventHandler*>(view_)->OnTouchEvent(event);
+}
+
+void ScopedTargetHandler::OnGestureEvent(ui::GestureEvent* event) {
+ static_cast<EventHandler*>(view_)->OnGestureEvent(event);
+}
+
+void ScopedTargetHandler::OnCancelMode(ui::CancelModeEvent* event) {
+ static_cast<EventHandler*>(view_)->OnCancelMode(event);
+}
+
+} // namespace views
diff --git a/ui/views/scoped_target_handler.h b/ui/views/scoped_target_handler.h
new file mode 100644
index 0000000..75b4f90
--- /dev/null
+++ b/ui/views/scoped_target_handler.h
@@ -0,0 +1,55 @@
+// Copyright 2015 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 UI_VIEWS_SCOPED_TARGET_HANDLER_H_
+#define UI_VIEWS_SCOPED_TARGET_HANDLER_H_
+
+#include "base/macros.h"
+#include "ui/events/event_handler.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class View;
+
+// An EventHandler that replaces an View's target handler with itself to pass
+// events first to the original handlers and second to an additional new
+// EventHandler. The new handler gets called after the original handlers even
+// if they call SetHandled() or StopPropagation() on the event.
+class VIEWS_EXPORT ScopedTargetHandler : public ui::EventHandler {
+ public:
+ ScopedTargetHandler(View* view, ui::EventHandler* new_handler);
+ ~ScopedTargetHandler() override;
+
+ // ui::EventHandler:
+ void OnEvent(ui::Event* event) override;
+ void OnKeyEvent(ui::KeyEvent* event) override;
+ void OnMouseEvent(ui::MouseEvent* event) override;
+ void OnScrollEvent(ui::ScrollEvent* event) override;
+ void OnTouchEvent(ui::TouchEvent* event) override;
+ void OnGestureEvent(ui::GestureEvent* event) override;
+ void OnCancelMode(ui::CancelModeEvent* event) override;
+
+ private:
+ // If non-null the destructor sets this to true. This is set while handling
+ // an event and used to detect if |this| has been deleted.
+ bool* destroyed_flag_;
+
+ // An View that has its target handler replaced with |this| for a life time of
+ // |this|.
+ View* view_;
+
+ // An EventHandler that gets restored on |view_| when |this| is destroyed.
+ ui::EventHandler* original_handler_;
+
+ // A new handler that gets events in addition to the |original_handler_| or
+ // |view_|.
+ ui::EventHandler* new_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedTargetHandler);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_SCOPED_TARGET_HANDLER_H_
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc
index cabf5d4..3e2180b 100644
--- a/ui/views/view_unittest.cc
+++ b/ui/views/view_unittest.cc
@@ -31,6 +31,7 @@
#include "ui/views/controls/scroll_view.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/focus/view_storage.h"
+#include "ui/views/scoped_target_handler.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/view.h"
#include "ui/views/widget/native_widget.h"
@@ -4296,4 +4297,61 @@ TEST_F(ViewTest, OnNativeThemeChanged) {
widget->CloseNow();
}
+class TestEventHandler : public ui::EventHandler {
+ public:
+ TestEventHandler(TestView* view) : view_(view), had_mouse_event_(false) {}
+ ~TestEventHandler() override {}
+
+ void OnMouseEvent(ui::MouseEvent* event) override {
+ // The |view_| should have received the event first.
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, view_->last_mouse_event_type_);
+ had_mouse_event_ = true;
+ }
+
+ TestView* view_;
+ bool had_mouse_event_;
+};
+
+TEST_F(ViewTest, ScopedTargetHandlerReceivesEvents) {
+ TestView* v = new TestView();
+ v->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
+
+ scoped_ptr<Widget> widget(new Widget);
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(50, 50, 350, 350);
+ widget->Init(params);
+ internal::RootView* root =
+ static_cast<internal::RootView*>(widget->GetRootView());
+ root->AddChildView(v);
+ v->Reset();
+ TestEventHandler handler(v);
+ {
+ ScopedTargetHandler scoped_target_handler(v, &handler);
+ // View's target EventHandler should be set to the |scoped_target_handler|.
+ EXPECT_EQ(&scoped_target_handler,
+ v->SetTargetHandler(&scoped_target_handler));
+
+ EXPECT_EQ(ui::ET_UNKNOWN, v->last_mouse_event_type_);
+ gfx::Point p(10, 120);
+ ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p, p, ui::EventTimeForNow(),
+ ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
+ root->OnMousePressed(pressed);
+
+ // Both the View |v| and the |handler| should have received the event.
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, v->last_mouse_event_type_);
+ EXPECT_TRUE(handler.had_mouse_event_);
+ }
+
+ // The View should no longer have a target EventHandler.
+ EXPECT_EQ(nullptr, v->SetTargetHandler(nullptr));
+
+ // The View should continue receiving events after the |handler| is deleted.
+ v->Reset();
+ ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), 0, 0);
+ root->OnMouseReleased(released);
+ EXPECT_EQ(ui::ET_MOUSE_RELEASED, v->last_mouse_event_type_);
+}
+
} // namespace views
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index 536b738..43423bf 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -14,6 +14,8 @@
'accessible_pane_view.h',
'animation/bounds_animator.cc',
'animation/bounds_animator.h',
+ 'animation/button_ink_drop_delegate.cc',
+ 'animation/button_ink_drop_delegate.h',
'animation/ink_drop_animation.cc',
'animation/ink_drop_animation.h',
'animation/ink_drop_animation_controller.h',
@@ -23,6 +25,7 @@
'animation/ink_drop_animation_controller_impl.h',
'animation/ink_drop_animation_observer.cc',
'animation/ink_drop_animation_observer.h',
+ 'animation/ink_drop_delegate.h',
'animation/ink_drop_host.h',
'animation/ink_drop_painted_layer_delegates.cc',
'animation/ink_drop_painted_layer_delegates.h',
@@ -269,6 +272,8 @@
'repeat_controller.h',
'round_rect_painter.cc',
'round_rect_painter.h',
+ 'scoped_target_handler.cc',
+ 'scoped_target_handler.h',
'shadow_border.cc',
'shadow_border.h',
'style/mac/dialog_button_border_mac.cc',