Commit 623c7e4e authored by mohsen's avatar mohsen Committed by Commit bot

Add ink drop ripple to shelf overflow button

It uses a flood fill ripple that remains active while the overflow shelf
is active. InkDropHostView and CustomButton are updated to handle active
case:
 - CustomButton does not hide the ripple if it is not a pending ripple;
 - InkDropHostView does not show or hide a pending ripple if it is
   showing an active ripple.

BUG=612579
TEST=OverflowButtonInkDropTest.* in ash_unittests, manual

Review-Url: https://codereview.chromium.org/2178163002
Cr-Commit-Position: refs/heads/master@{#419232}
parent 2ad909df
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "ash/common/shelf/overflow_bubble.h" #include "ash/common/shelf/overflow_bubble.h"
#include "ash/common/shelf/overflow_bubble_view.h" #include "ash/common/shelf/overflow_bubble_view.h"
#include "ash/common/shelf/overflow_button.h"
#include "ash/common/shelf/shelf_view.h" #include "ash/common/shelf/shelf_view.h"
#include "ash/common/shelf/wm_shelf.h" #include "ash/common/shelf/wm_shelf.h"
#include "ash/common/system/tray/tray_background_view.h" #include "ash/common/system/tray/tray_background_view.h"
...@@ -17,7 +18,7 @@ namespace ash { ...@@ -17,7 +18,7 @@ namespace ash {
OverflowBubble::OverflowBubble(WmShelf* wm_shelf) OverflowBubble::OverflowBubble(WmShelf* wm_shelf)
: wm_shelf_(wm_shelf), : wm_shelf_(wm_shelf),
bubble_(nullptr), bubble_(nullptr),
anchor_(nullptr), overflow_button_(nullptr),
shelf_view_(nullptr) { shelf_view_(nullptr) {
WmShell::Get()->AddPointerWatcher(this, WmShell::Get()->AddPointerWatcher(this,
views::PointerWatcherEventTypes::BASIC); views::PointerWatcherEventTypes::BASIC);
...@@ -28,50 +29,47 @@ OverflowBubble::~OverflowBubble() { ...@@ -28,50 +29,47 @@ OverflowBubble::~OverflowBubble() {
WmShell::Get()->RemovePointerWatcher(this); WmShell::Get()->RemovePointerWatcher(this);
} }
void OverflowBubble::Show(views::View* anchor, ShelfView* shelf_view) { void OverflowBubble::Show(OverflowButton* overflow_button,
DCHECK(anchor); ShelfView* shelf_view) {
DCHECK(overflow_button);
DCHECK(shelf_view); DCHECK(shelf_view);
Hide(); Hide();
bubble_ = new OverflowBubbleView(wm_shelf_); bubble_ = new OverflowBubbleView(wm_shelf_);
bubble_->InitOverflowBubble(anchor, shelf_view); bubble_->InitOverflowBubble(overflow_button, shelf_view);
shelf_view_ = shelf_view; shelf_view_ = shelf_view;
anchor_ = anchor; overflow_button_ = overflow_button;
TrayBackgroundView::InitializeBubbleAnimations(bubble_->GetWidget()); TrayBackgroundView::InitializeBubbleAnimations(bubble_->GetWidget());
bubble_->GetWidget()->AddObserver(this); bubble_->GetWidget()->AddObserver(this);
bubble_->GetWidget()->Show(); bubble_->GetWidget()->Show();
overflow_button->OnOverflowBubbleShown();
} }
void OverflowBubble::Hide() { void OverflowBubble::Hide() {
if (!IsShowing()) if (!IsShowing())
return; return;
OverflowButton* overflow_button = overflow_button_;
bubble_->GetWidget()->RemoveObserver(this); bubble_->GetWidget()->RemoveObserver(this);
bubble_->GetWidget()->Close(); bubble_->GetWidget()->Close();
bubble_ = NULL; bubble_ = nullptr;
anchor_ = NULL; overflow_button_ = nullptr;
shelf_view_ = NULL; shelf_view_ = nullptr;
}
void OverflowBubble::HideBubbleAndRefreshButton() {
if (!IsShowing())
return;
views::View* anchor = anchor_; overflow_button->OnOverflowBubbleHidden();
Hide();
// Update overflow button (|anchor|) status when overflow bubble is hidden
// by outside event of overflow button.
anchor->SchedulePaint();
} }
void OverflowBubble::ProcessPressedEvent( void OverflowBubble::ProcessPressedEvent(
const gfx::Point& event_location_in_screen) { const gfx::Point& event_location_in_screen) {
if (IsShowing() && !shelf_view_->IsShowingMenu() && if (IsShowing() && !shelf_view_->IsShowingMenu() &&
!bubble_->GetBoundsInScreen().Contains(event_location_in_screen) && !bubble_->GetBoundsInScreen().Contains(event_location_in_screen) &&
!anchor_->GetBoundsInScreen().Contains(event_location_in_screen)) { !overflow_button_->GetBoundsInScreen().Contains(
HideBubbleAndRefreshButton(); event_location_in_screen)) {
Hide();
} }
} }
...@@ -86,9 +84,9 @@ void OverflowBubble::OnPointerEventObserved( ...@@ -86,9 +84,9 @@ void OverflowBubble::OnPointerEventObserved(
void OverflowBubble::OnWidgetDestroying(views::Widget* widget) { void OverflowBubble::OnWidgetDestroying(views::Widget* widget) {
DCHECK(widget == bubble_->GetWidget()); DCHECK(widget == bubble_->GetWidget());
// Update the overflow button in the parent ShelfView. // Update the overflow button in the parent ShelfView.
anchor_->SchedulePaint(); overflow_button_->SchedulePaint();
bubble_ = nullptr; bubble_ = nullptr;
anchor_ = nullptr; overflow_button_ = nullptr;
shelf_view_ = nullptr; shelf_view_ = nullptr;
} }
......
...@@ -19,6 +19,7 @@ class View; ...@@ -19,6 +19,7 @@ class View;
namespace ash { namespace ash {
class OverflowBubbleView; class OverflowBubbleView;
class OverflowButton;
class ShelfView; class ShelfView;
class WmShelf; class WmShelf;
...@@ -31,16 +32,13 @@ class OverflowBubble : public views::PointerWatcher, ...@@ -31,16 +32,13 @@ class OverflowBubble : public views::PointerWatcher,
explicit OverflowBubble(WmShelf* wm_shelf); explicit OverflowBubble(WmShelf* wm_shelf);
~OverflowBubble() override; ~OverflowBubble() override;
// Shows an bubble pointing to |anchor| with |shelf_view| as its content. // Shows an bubble pointing to |overflow_button| with |shelf_view| as its
// This |shelf_view| is different than the main shelf's view and only contains // content. This |shelf_view| is different than the main shelf's view and
// the overflow items. // only contains the overflow items.
void Show(views::View* anchor, ShelfView* shelf_view); void Show(OverflowButton* overflow_button, ShelfView* shelf_view);
void Hide(); void Hide();
// Hides the bubble and schedules paint for overflow button.
void HideBubbleAndRefreshButton();
bool IsShowing() const { return !!bubble_; } bool IsShowing() const { return !!bubble_; }
ShelfView* shelf_view() { return shelf_view_; } ShelfView* shelf_view() { return shelf_view_; }
OverflowBubbleView* bubble_view() { return bubble_; } OverflowBubbleView* bubble_view() { return bubble_; }
...@@ -58,7 +56,7 @@ class OverflowBubble : public views::PointerWatcher, ...@@ -58,7 +56,7 @@ class OverflowBubble : public views::PointerWatcher,
WmShelf* wm_shelf_; WmShelf* wm_shelf_;
OverflowBubbleView* bubble_; // Owned by views hierarchy. OverflowBubbleView* bubble_; // Owned by views hierarchy.
views::View* anchor_; // Owned by ShelfView. OverflowButton* overflow_button_; // Owned by ShelfView.
// ShelfView containing the overflow items. Owned by |bubble_|. // ShelfView containing the overflow items. Owned by |bubble_|.
ShelfView* shelf_view_; ShelfView* shelf_view_;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "ash/common/shelf/shelf_view.h" #include "ash/common/shelf/shelf_view.h"
#include "ash/common/shelf/wm_shelf.h" #include "ash/common/shelf/wm_shelf.h"
#include "ash/common/shelf/wm_shelf_util.h" #include "ash/common/shelf/wm_shelf_util.h"
#include "base/memory/ptr_util.h"
#include "grit/ash_resources.h" #include "grit/ash_resources.h"
#include "grit/ash_strings.h" #include "grit/ash_strings.h"
#include "third_party/skia/include/core/SkPaint.h" #include "third_party/skia/include/core/SkPaint.h"
...@@ -24,6 +25,7 @@ ...@@ -24,6 +25,7 @@
#include "ui/gfx/skia_util.h" #include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h" #include "ui/gfx/transform.h"
#include "ui/gfx/vector_icons_public.h" #include "ui/gfx/vector_icons_public.h"
#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
namespace ash { namespace ash {
...@@ -35,6 +37,10 @@ OverflowButton::OverflowButton(ShelfView* shelf_view, WmShelf* wm_shelf) ...@@ -35,6 +37,10 @@ OverflowButton::OverflowButton(ShelfView* shelf_view, WmShelf* wm_shelf)
background_alpha_(0) { background_alpha_(0) {
DCHECK(shelf_view_); DCHECK(shelf_view_);
if (MaterialDesignController::IsShelfMaterial()) { if (MaterialDesignController::IsShelfMaterial()) {
SetInkDropMode(InkDropMode::ON);
set_ink_drop_base_color(kShelfInkDropBaseColor);
set_ink_drop_visible_opacity(kShelfInkDropVisibleOpacity);
set_hide_ink_drop_when_showing_context_menu(false);
bottom_image_md_ = bottom_image_md_ =
CreateVectorIcon(gfx::VectorIconId::SHELF_OVERFLOW, kShelfIconColor); CreateVectorIcon(gfx::VectorIconId::SHELF_OVERFLOW, kShelfIconColor);
bottom_image_ = &bottom_image_md_; bottom_image_ = &bottom_image_md_;
...@@ -53,6 +59,18 @@ void OverflowButton::OnShelfAlignmentChanged() { ...@@ -53,6 +59,18 @@ void OverflowButton::OnShelfAlignmentChanged() {
SchedulePaint(); SchedulePaint();
} }
void OverflowButton::OnOverflowBubbleShown() {
AnimateInkDrop(views::InkDropState::ACTIVATED, nullptr);
if (!ash::MaterialDesignController::IsShelfMaterial())
SchedulePaint();
}
void OverflowButton::OnOverflowBubbleHidden() {
AnimateInkDrop(views::InkDropState::DEACTIVATED, nullptr);
if (!ash::MaterialDesignController::IsShelfMaterial())
SchedulePaint();
}
void OverflowButton::SetBackgroundAlpha(int alpha) { void OverflowButton::SetBackgroundAlpha(int alpha) {
background_alpha_ = alpha; background_alpha_ = alpha;
SchedulePaint(); SchedulePaint();
...@@ -64,6 +82,24 @@ void OverflowButton::OnPaint(gfx::Canvas* canvas) { ...@@ -64,6 +82,24 @@ void OverflowButton::OnPaint(gfx::Canvas* canvas) {
PaintForeground(canvas, bounds); PaintForeground(canvas, bounds);
} }
std::unique_ptr<views::InkDropRipple> OverflowButton::CreateInkDropRipple()
const {
return base::MakeUnique<views::FloodFillInkDropRipple>(
CalculateButtonBounds(), GetInkDropCenterBasedOnLastEvent(),
GetInkDropBaseColor(), ink_drop_visible_opacity());
}
bool OverflowButton::ShouldEnterPushedState(const ui::Event& event) {
if (shelf_view_->IsShowingOverflowBubble())
return false;
return CustomButton::ShouldEnterPushedState(event);
}
bool OverflowButton::ShouldShowInkDropHighlight() const {
return false;
}
void OverflowButton::NotifyClick(const ui::Event& event) { void OverflowButton::NotifyClick(const ui::Event& event) {
CustomButton::NotifyClick(event); CustomButton::NotifyClick(event);
shelf_view_->ButtonPressed(this, event, ink_drop()); shelf_view_->ButtonPressed(this, event, ink_drop());
...@@ -77,14 +113,6 @@ void OverflowButton::PaintBackground(gfx::Canvas* canvas, ...@@ -77,14 +113,6 @@ void OverflowButton::PaintBackground(gfx::Canvas* canvas,
background_paint.setColor(SkColorSetA(kShelfBaseColor, background_alpha_)); background_paint.setColor(SkColorSetA(kShelfBaseColor, background_alpha_));
canvas->DrawRoundRect(bounds, kOverflowButtonCornerRadius, canvas->DrawRoundRect(bounds, kOverflowButtonCornerRadius,
background_paint); background_paint);
if (shelf_view_->IsShowingOverflowBubble()) {
SkPaint highlight_paint;
highlight_paint.setFlags(SkPaint::kAntiAlias_Flag);
highlight_paint.setColor(kShelfButtonActivatedHighlightColor);
canvas->DrawRoundRect(bounds, kOverflowButtonCornerRadius,
highlight_paint);
}
} else { } else {
ResourceBundle& rb = ResourceBundle::GetSharedInstance(); ResourceBundle& rb = ResourceBundle::GetSharedInstance();
const gfx::ImageSkia* background = const gfx::ImageSkia* background =
...@@ -122,7 +150,7 @@ void OverflowButton::PaintForeground(gfx::Canvas* canvas, ...@@ -122,7 +150,7 @@ void OverflowButton::PaintForeground(gfx::Canvas* canvas,
bounds.y() + ((bounds.height() - image->height()) / 2)); bounds.y() + ((bounds.height() - image->height()) / 2));
} }
int OverflowButton::NonMaterialBackgroundImageId() { int OverflowButton::NonMaterialBackgroundImageId() const {
if (shelf_view_->IsShowingOverflowBubble()) if (shelf_view_->IsShowingOverflowBubble())
return IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED; return IDR_AURA_NOTIFICATION_BACKGROUND_PRESSED;
else if (wm_shelf_->IsDimmed()) else if (wm_shelf_->IsDimmed())
...@@ -130,7 +158,7 @@ int OverflowButton::NonMaterialBackgroundImageId() { ...@@ -130,7 +158,7 @@ int OverflowButton::NonMaterialBackgroundImageId() {
return IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL; return IDR_AURA_NOTIFICATION_BACKGROUND_NORMAL;
} }
gfx::Rect OverflowButton::CalculateButtonBounds() { gfx::Rect OverflowButton::CalculateButtonBounds() const {
ShelfAlignment alignment = wm_shelf_->GetAlignment(); ShelfAlignment alignment = wm_shelf_->GetAlignment();
gfx::Rect bounds(GetContentsBounds()); gfx::Rect bounds(GetContentsBounds());
ResourceBundle& rb = ResourceBundle::GetSharedInstance(); ResourceBundle& rb = ResourceBundle::GetSharedInstance();
......
...@@ -21,15 +21,18 @@ class OverflowButton : public views::CustomButton { ...@@ -21,15 +21,18 @@ class OverflowButton : public views::CustomButton {
~OverflowButton() override; ~OverflowButton() override;
void OnShelfAlignmentChanged(); void OnShelfAlignmentChanged();
void OnOverflowBubbleShown();
void OnOverflowBubbleHidden();
// Sets alpha value of the background and schedules a paint. // Sets alpha value of the background and schedules a paint.
void SetBackgroundAlpha(int alpha); void SetBackgroundAlpha(int alpha);
private: private:
// views::View:
void OnPaint(gfx::Canvas* canvas) override;
// views::CustomButton: // views::CustomButton:
void OnPaint(gfx::Canvas* canvas) override;
std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
bool ShouldEnterPushedState(const ui::Event& event) override;
bool ShouldShowInkDropHighlight() const override;
void NotifyClick(const ui::Event& event) override; void NotifyClick(const ui::Event& event) override;
// Helper functions to paint the background and foreground of the button // Helper functions to paint the background and foreground of the button
...@@ -41,10 +44,10 @@ class OverflowButton : public views::CustomButton { ...@@ -41,10 +44,10 @@ class OverflowButton : public views::CustomButton {
// current shelf state. // current shelf state.
// TODO(tdanderson): Remove this once the material design shelf is enabled // TODO(tdanderson): Remove this once the material design shelf is enabled
// by default. See crbug.com/614453. // by default. See crbug.com/614453.
int NonMaterialBackgroundImageId(); int NonMaterialBackgroundImageId() const;
// Calculates the bounds of the overflow button based on the shelf alignment. // Calculates the bounds of the overflow button based on the shelf alignment.
gfx::Rect CalculateButtonBounds(); gfx::Rect CalculateButtonBounds() const;
// Used for bottom shelf alignment. |bottom_image_| points to // Used for bottom shelf alignment. |bottom_image_| points to
// |bottom_image_md_| for material design, otherwise it is points to a // |bottom_image_md_| for material design, otherwise it is points to a
......
...@@ -1854,7 +1854,7 @@ void ShelfView::OnMenuClosed(views::InkDrop* ink_drop) { ...@@ -1854,7 +1854,7 @@ void ShelfView::OnMenuClosed(views::InkDrop* ink_drop) {
// Hide the hide overflow bubble after showing a context menu for its items. // Hide the hide overflow bubble after showing a context menu for its items.
if (owner_overflow_bubble_) if (owner_overflow_bubble_)
owner_overflow_bubble_->HideBubbleAndRefreshButton(); owner_overflow_bubble_->Hide();
closing_event_time_ = launcher_menu_runner_->closing_event_time(); closing_event_time_ = launcher_menu_runner_->closing_event_time();
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "ash/common/shelf/app_list_button.h" #include "ash/common/shelf/app_list_button.h"
#include "ash/common/shelf/overflow_bubble.h" #include "ash/common/shelf/overflow_bubble.h"
#include "ash/common/shelf/overflow_bubble_view.h" #include "ash/common/shelf/overflow_bubble_view.h"
#include "ash/common/shelf/overflow_button.h"
#include "ash/common/shelf/shelf_button.h" #include "ash/common/shelf/shelf_button.h"
#include "ash/common/shelf/shelf_constants.h" #include "ash/common/shelf/shelf_constants.h"
#include "ash/common/shelf/shelf_menu_model.h" #include "ash/common/shelf/shelf_menu_model.h"
...@@ -42,6 +43,7 @@ ...@@ -42,6 +43,7 @@
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/histogram_tester.h" #include "base/test/histogram_tester.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/test/user_action_tester.h" #include "base/test/user_action_tester.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -593,8 +595,7 @@ class ShelfViewTest : public AshTestBase { ...@@ -593,8 +595,7 @@ class ShelfViewTest : public AshTestBase {
void TestDraggingAnItemFromOverflowToShelf(bool cancel) { void TestDraggingAnItemFromOverflowToShelf(bool cancel) {
test_api_->ShowOverflowBubble(); test_api_->ShowOverflowBubble();
ASSERT_TRUE(test_api_->overflow_bubble() && ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
test_api_->overflow_bubble()->IsShowing());
ShelfViewTestAPI test_api_for_overflow( ShelfViewTestAPI test_api_for_overflow(
test_api_->overflow_bubble()->shelf_view()); test_api_->overflow_bubble()->shelf_view());
...@@ -674,6 +675,7 @@ class ShelfViewTest : public AshTestBase { ...@@ -674,6 +675,7 @@ class ShelfViewTest : public AshTestBase {
EXPECT_EQ(second_last_visible_item_id_in_overflow, EXPECT_EQ(second_last_visible_item_id_in_overflow,
GetItemId(test_api_for_overflow.GetLastVisibleIndex())); GetItemId(test_api_for_overflow.GetLastVisibleIndex()));
} }
test_api_->HideOverflowBubble();
} }
// Returns the item's ShelfID at |index|. // Returns the item's ShelfID at |index|.
...@@ -1012,8 +1014,7 @@ TEST_P(ShelfViewTextDirectionTest, OverflowArrowForShelfPosition) { ...@@ -1012,8 +1014,7 @@ TEST_P(ShelfViewTextDirectionTest, OverflowArrowForShelfPosition) {
// orientation. // orientation.
AddButtonsUntilOverflow(); AddButtonsUntilOverflow();
test_api_->ShowOverflowBubble(); test_api_->ShowOverflowBubble();
ASSERT_TRUE(test_api_->overflow_bubble() && ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
test_api_->overflow_bubble()->IsShowing());
EXPECT_EQ(kArrows[i], test_api_->overflow_bubble()->bubble_view()->arrow()); EXPECT_EQ(kArrows[i], test_api_->overflow_bubble()->bubble_view()->arrow());
OverflowBubbleViewTestAPI bubble_view_api( OverflowBubbleViewTestAPI bubble_view_api(
...@@ -1586,8 +1587,7 @@ TEST_F(ShelfViewTest, OverflowBubbleSize) { ...@@ -1586,8 +1587,7 @@ TEST_F(ShelfViewTest, OverflowBubbleSize) {
// Show overflow bubble. // Show overflow bubble.
test_api_->ShowOverflowBubble(); test_api_->ShowOverflowBubble();
ASSERT_TRUE(test_api_->overflow_bubble() && ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
test_api_->overflow_bubble()->IsShowing());
ShelfViewTestAPI test_for_overflow_view( ShelfViewTestAPI test_for_overflow_view(
test_api_->overflow_bubble()->shelf_view()); test_api_->overflow_bubble()->shelf_view());
...@@ -1613,8 +1613,7 @@ TEST_F(ShelfViewTest, OverflowBubbleSize) { ...@@ -1613,8 +1613,7 @@ TEST_F(ShelfViewTest, OverflowBubbleSize) {
// Check the overflow bubble size when an item is ripped off. // Check the overflow bubble size when an item is ripped off.
EXPECT_EQ(bubble_size.width() - item_width, EXPECT_EQ(bubble_size.width() - item_width,
test_for_overflow_view.GetPreferredSize().width()); test_for_overflow_view.GetPreferredSize().width());
ASSERT_TRUE(test_api_->overflow_bubble() && ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
test_api_->overflow_bubble()->IsShowing());
// Re-insert an item into the overflow bubble. // Re-insert an item into the overflow bubble.
int first_index = test_for_overflow_view.GetFirstVisibleIndex(); int first_index = test_for_overflow_view.GetFirstVisibleIndex();
...@@ -1642,8 +1641,7 @@ TEST_F(ShelfViewTest, CheckDragInsertBoundsOfScrolledOverflowBubble) { ...@@ -1642,8 +1641,7 @@ TEST_F(ShelfViewTest, CheckDragInsertBoundsOfScrolledOverflowBubble) {
// Show overflow bubble. // Show overflow bubble.
test_api_->ShowOverflowBubble(); test_api_->ShowOverflowBubble();
ASSERT_TRUE(test_api_->overflow_bubble() && ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
test_api_->overflow_bubble()->IsShowing());
int item_width = test_api_->GetButtonSize() + test_api_->GetButtonSpacing(); int item_width = test_api_->GetButtonSize() + test_api_->GetButtonSpacing();
OverflowBubbleView* bubble_view = test_api_->overflow_bubble()->bubble_view(); OverflowBubbleView* bubble_view = test_api_->overflow_bubble()->bubble_view();
...@@ -1655,8 +1653,7 @@ TEST_F(ShelfViewTest, CheckDragInsertBoundsOfScrolledOverflowBubble) { ...@@ -1655,8 +1653,7 @@ TEST_F(ShelfViewTest, CheckDragInsertBoundsOfScrolledOverflowBubble) {
(bubble_view->GetContentsBounds().width() + 3 * item_width)) (bubble_view->GetContentsBounds().width() + 3 * item_width))
AddAppShortcut(); AddAppShortcut();
ASSERT_TRUE(test_api_->overflow_bubble() && ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
test_api_->overflow_bubble()->IsShowing());
ShelfViewTestAPI test_for_overflow_view( ShelfViewTestAPI test_for_overflow_view(
test_api_->overflow_bubble()->shelf_view()); test_api_->overflow_bubble()->shelf_view());
...@@ -1706,8 +1703,7 @@ TEST_F(ShelfViewTest, CheckDragInsertBoundsWithMultiMonitor) { ...@@ -1706,8 +1703,7 @@ TEST_F(ShelfViewTest, CheckDragInsertBoundsWithMultiMonitor) {
// Test #1: Test drag insertion bounds of primary shelf. // Test #1: Test drag insertion bounds of primary shelf.
// Show overflow bubble. // Show overflow bubble.
test_api_->ShowOverflowBubble(); test_api_->ShowOverflowBubble();
ASSERT_TRUE(test_api_->overflow_bubble() && ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
test_api_->overflow_bubble()->IsShowing());
ShelfViewTestAPI test_api_for_overflow_view( ShelfViewTestAPI test_api_for_overflow_view(
test_api_->overflow_bubble()->shelf_view()); test_api_->overflow_bubble()->shelf_view());
...@@ -1727,8 +1723,7 @@ TEST_F(ShelfViewTest, CheckDragInsertBoundsWithMultiMonitor) { ...@@ -1727,8 +1723,7 @@ TEST_F(ShelfViewTest, CheckDragInsertBoundsWithMultiMonitor) {
// Test #2: Test drag insertion bounds of secondary shelf. // Test #2: Test drag insertion bounds of secondary shelf.
// Show overflow bubble. // Show overflow bubble.
test_api_for_secondary.ShowOverflowBubble(); test_api_for_secondary.ShowOverflowBubble();
ASSERT_TRUE(test_api_for_secondary.overflow_bubble() && ASSERT_TRUE(test_api_for_secondary.IsShowingOverflowBubble());
test_api_for_secondary.overflow_bubble()->IsShowing());
ShelfViewTestAPI test_api_for_overflow_view_of_secondary( ShelfViewTestAPI test_api_for_overflow_view_of_secondary(
test_api_for_secondary.overflow_bubble()->shelf_view()); test_api_for_secondary.overflow_bubble()->shelf_view());
...@@ -2132,8 +2127,7 @@ class ShelfViewInkDropTest : public ShelfViewTest { ...@@ -2132,8 +2127,7 @@ class ShelfViewInkDropTest : public ShelfViewTest {
~ShelfViewInkDropTest() override {} ~ShelfViewInkDropTest() override {}
void SetUp() override { void SetUp() override {
shell_delegate_ = new TestAppListShellDelegate; ash_test_helper()->set_test_shell_delegate(CreateTestShellDelegate());
ash_test_helper()->set_test_shell_delegate(shell_delegate_);
set_material_mode(ash::MaterialDesignController::MATERIAL_EXPERIMENTAL); set_material_mode(ash::MaterialDesignController::MATERIAL_EXPERIMENTAL);
...@@ -2141,26 +2135,36 @@ class ShelfViewInkDropTest : public ShelfViewTest { ...@@ -2141,26 +2135,36 @@ class ShelfViewInkDropTest : public ShelfViewTest {
} }
protected: protected:
// Gives subclasses a chance to return a custom test shell delegate to install
// before calling base class's SetUp(). Shell will take ownership of the
// returned object.
virtual TestShellDelegate* CreateTestShellDelegate() {
shell_delegate_ = new TestAppListShellDelegate;
return shell_delegate_;
}
void InitAppListButtonInkDrop() { void InitAppListButtonInkDrop() {
app_list_button_ = shelf_view_->GetAppListButton(); app_list_button_ = shelf_view_->GetAppListButton();
views::InkDropImpl* ink_drop_impl = auto app_list_button_ink_drop = base::MakeUnique<InkDropSpy>(
new views::InkDropImpl(app_list_button_); base::MakeUnique<views::InkDropImpl>(app_list_button_));
app_list_button_ink_drop_ = new InkDropSpy(base::WrapUnique(ink_drop_impl)); app_list_button_ink_drop_ = app_list_button_ink_drop.get();
views::test::InkDropHostViewTestApi(app_list_button_) views::test::InkDropHostViewTestApi(app_list_button_)
.SetInkDrop(base::WrapUnique(app_list_button_ink_drop_), false); .SetInkDrop(std::move(app_list_button_ink_drop), false);
} }
void InitBrowserButtonInkDrop() { void InitBrowserButtonInkDrop() {
browser_button_ = test_api_->GetButton(browser_index_); browser_button_ = test_api_->GetButton(browser_index_);
views::InkDropImpl* ink_drop_impl = new views::InkDropImpl(browser_button_); auto browser_button_ink_drop = base::MakeUnique<InkDropSpy>(
browser_button_ink_drop_ = new InkDropSpy(base::WrapUnique(ink_drop_impl)); base::MakeUnique<views::InkDropImpl>(browser_button_));
browser_button_ink_drop_ = browser_button_ink_drop.get();
views::test::InkDropHostViewTestApi(browser_button_) views::test::InkDropHostViewTestApi(browser_button_)
.SetInkDrop(base::WrapUnique(browser_button_ink_drop_)); .SetInkDrop(std::move(browser_button_ink_drop));
} }
void ShowAppList() { void ShowAppList() {
DCHECK(shelf_delegate_);
shell_delegate_->app_list_presenter()->Show(0); shell_delegate_->app_list_presenter()->Show(0);
// Similar to real AppListPresenter, notify button that the app list is // Similar to real AppListPresenter, notify button that the app list is
// shown. // shown.
...@@ -2168,6 +2172,7 @@ class ShelfViewInkDropTest : public ShelfViewTest { ...@@ -2168,6 +2172,7 @@ class ShelfViewInkDropTest : public ShelfViewTest {
} }
void DismissAppList() { void DismissAppList() {
DCHECK(shelf_delegate_);
shell_delegate_->app_list_presenter()->Dismiss(); shell_delegate_->app_list_presenter()->Dismiss();
// Similar to real AppListPresenter, notify button that the app list is // Similar to real AppListPresenter, notify button that the app list is
// dismissed. // dismissed.
...@@ -2175,6 +2180,7 @@ class ShelfViewInkDropTest : public ShelfViewTest { ...@@ -2175,6 +2180,7 @@ class ShelfViewInkDropTest : public ShelfViewTest {
} }
void FinishAppListVisibilityChange() { void FinishAppListVisibilityChange() {
DCHECK(shelf_delegate_);
shell_delegate_->app_list_presenter()->FinishVisibilityChange(); shell_delegate_->app_list_presenter()->FinishVisibilityChange();
} }
...@@ -2280,9 +2286,8 @@ TEST_F(ShelfViewInkDropTest, AppListButtonMouseEventsWhenVisible) { ...@@ -2280,9 +2286,8 @@ TEST_F(ShelfViewInkDropTest, AppListButtonMouseEventsWhenVisible) {
IsEmpty()); IsEmpty());
} }
#if !defined(OS_WIN)
// There is no ink drop effect for gesture events on Windows. // There is no ink drop effect for gesture events on Windows.
#if !defined(OS_WIN)
// Tests that when the app list is hidden, tapping on the app list button // Tests that when the app list is hidden, tapping on the app list button
// transitions ink drop states correctly. // transitions ink drop states correctly.
TEST_F(ShelfViewInkDropTest, AppListButtonGestureTapWhenHidden) { TEST_F(ShelfViewInkDropTest, AppListButtonGestureTapWhenHidden) {
...@@ -2576,5 +2581,600 @@ TEST_F(ShelfViewInkDropTest, ShelfButtonWithMenuPressRelease) { ...@@ -2576,5 +2581,600 @@ TEST_F(ShelfViewInkDropTest, ShelfButtonWithMenuPressRelease) {
views::InkDropState::DEACTIVATED)); views::InkDropState::DEACTIVATED));
} }
namespace {
// An empty menu model for shell context menu just to have a menu.
class TestShellMenuModel : public ui::SimpleMenuModel,
public ui::SimpleMenuModel::Delegate {
public:
TestShellMenuModel() : ui::SimpleMenuModel(this) {}
~TestShellMenuModel() override {}
private:
// ui::SimpleMenuModel::Delegate:
bool IsCommandIdChecked(int command_id) const override { return false; }
bool IsCommandIdEnabled(int command_id) const override { return true; }
void ExecuteCommand(int command_id, int event_flags) override {}
DISALLOW_COPY_AND_ASSIGN(TestShellMenuModel);
};
// A test ShellDelegate implementation for overflow button tests that returns a
// TestShelfMenuModel for the shell context menu.
class TestOverflowButtonShellDelegate : public TestShellDelegate {
public:
TestOverflowButtonShellDelegate() {}
~TestOverflowButtonShellDelegate() override {}
// TestShellDelegate:
ui::MenuModel* CreateContextMenu(WmShelf* wm_shelf,
const ShelfItem* item) override {
// Caller takes ownership of the returned object.
return new TestShellMenuModel;
}
private:
DISALLOW_COPY_AND_ASSIGN(TestOverflowButtonShellDelegate);
};
// A scoped wrapper around TestMockTimeTaskRunner that replaces message loop's
// task runner with a TestMockTimeTaskRunner and resets it back at the end of
// the scope.
class ScopedMockTaskRunnerWrapper {
public:
ScopedMockTaskRunnerWrapper() {
mock_task_runner_ = new base::TestMockTimeTaskRunner;
previous_task_runner_ = base::MessageLoop::current()->task_runner();
base::MessageLoop::current()->SetTaskRunner(mock_task_runner_);
}
~ScopedMockTaskRunnerWrapper() {
DCHECK_EQ(mock_task_runner_, base::MessageLoop::current()->task_runner());
mock_task_runner_->ClearPendingTasks();
base::MessageLoop::current()->SetTaskRunner(previous_task_runner_);
}
void FastForwardUntilNoTasksRemain() {
mock_task_runner_->FastForwardUntilNoTasksRemain();
}
private:
scoped_refptr<base::TestMockTimeTaskRunner> mock_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> previous_task_runner_;
DISALLOW_COPY_AND_ASSIGN(ScopedMockTaskRunnerWrapper);
};
} // namespace
// Test fixture for testing material design ink drop on overflow button.
class OverflowButtonInkDropTest : public ShelfViewInkDropTest {
public:
OverflowButtonInkDropTest() {}
~OverflowButtonInkDropTest() override {}
void SetUp() override {
ShelfViewInkDropTest::SetUp();
overflow_button_ = test_api_->overflow_button();
auto overflow_button_ink_drop = base::MakeUnique<InkDropSpy>(
base::MakeUnique<views::InkDropImpl>(overflow_button_));
overflow_button_ink_drop_ = overflow_button_ink_drop.get();
views::test::InkDropHostViewTestApi(overflow_button_)
.SetInkDrop(std::move(overflow_button_ink_drop));
AddButtonsUntilOverflow();
EXPECT_TRUE(test_api_->IsOverflowButtonVisible());
EXPECT_FALSE(test_api_->IsShowingOverflowBubble());
}
protected:
gfx::Point GetScreenPointInsideOverflowButton() const {
return overflow_button_->GetBoundsInScreen().CenterPoint();
}
gfx::Point GetScreenPointOutsideOverflowButton() const {
gfx::Point point = GetScreenPointInsideOverflowButton();
point.Offset(overflow_button_->width(), 0);
return point;
}
// Overridden from ShelfViewInkDropTest:
TestShellDelegate* CreateTestShellDelegate() override {
return new TestOverflowButtonShellDelegate;
}
OverflowButton* overflow_button_ = nullptr;
InkDropSpy* overflow_button_ink_drop_ = nullptr;
private:
DISALLOW_COPY_AND_ASSIGN(OverflowButtonInkDropTest);
};
// Tests ink drop state transitions for the overflow button when the overflow
// bubble is shown or hidden.
TEST_F(OverflowButtonInkDropTest, OnOverflowBubbleShowHide) {
test_api_->ShowOverflowBubble();
ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTIVATED));
test_api_->HideOverflowBubble();
EXPECT_FALSE(test_api_->IsShowingOverflowBubble());
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::DEACTIVATED));
}
// Tests ink drop state transitions for the overflow button when the user clicks
// on it.
TEST_F(OverflowButtonInkDropTest, MouseActivate) {
ui::test::EventGenerator& generator = GetEventGenerator();
gfx::Point mouse_location = GetScreenPointInsideOverflowButton();
generator.MoveMouseTo(mouse_location);
generator.PressLeftButton();
EXPECT_EQ(views::InkDropState::ACTION_PENDING,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTION_PENDING));
generator.ReleaseLeftButton();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTIVATED));
ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when the user
// presses left mouse button on it and drags it out of the button bounds.
TEST_F(OverflowButtonInkDropTest, MouseDragOut) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.MoveMouseTo(GetScreenPointInsideOverflowButton());
generator.PressLeftButton();
EXPECT_EQ(views::InkDropState::ACTION_PENDING,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTION_PENDING));
generator.MoveMouseTo(GetScreenPointOutsideOverflowButton());
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::HIDDEN));
generator.ReleaseLeftButton();
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
EXPECT_FALSE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when the user
// presses left mouse button on it and drags it out of the button bounds and
// back.
TEST_F(OverflowButtonInkDropTest, MouseDragOutAndBack) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.MoveMouseTo(GetScreenPointInsideOverflowButton());
generator.PressLeftButton();
EXPECT_EQ(views::InkDropState::ACTION_PENDING,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTION_PENDING));
generator.MoveMouseTo(GetScreenPointOutsideOverflowButton());
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::HIDDEN));
generator.MoveMouseTo(GetScreenPointInsideOverflowButton());
EXPECT_EQ(views::InkDropState::ACTION_PENDING,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTION_PENDING));
generator.ReleaseLeftButton();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTIVATED));
ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when the user right
// clicks on the button to show the context menu.
TEST_F(OverflowButtonInkDropTest, MouseContextMenu) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.MoveMouseTo(GetScreenPointInsideOverflowButton());
generator.PressRightButton();
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.ReleaseRightButton();
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
EXPECT_FALSE(test_api_->IsShowingOverflowBubble());
}
// There is no ink drop effect for gesture events on Windows.
#if !defined(OS_WIN)
// Tests ink drop state transitions for the overflow button when the user taps
// on it.
TEST_F(OverflowButtonInkDropTest, TouchActivate) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.set_current_location(GetScreenPointInsideOverflowButton());
generator.PressTouch();
EXPECT_EQ(views::InkDropState::ACTION_PENDING,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTION_PENDING));
generator.ReleaseTouch();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTIVATED));
ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when the user taps
// down on it and drags it out of the button bounds.
TEST_F(OverflowButtonInkDropTest, TouchDragOut) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.set_current_location(GetScreenPointInsideOverflowButton());
generator.PressTouch();
EXPECT_EQ(views::InkDropState::ACTION_PENDING,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTION_PENDING));
generator.MoveTouch(GetScreenPointOutsideOverflowButton());
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::HIDDEN));
generator.ReleaseTouch();
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
EXPECT_FALSE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when the user taps
// down on it and drags it out of the button bounds and back.
TEST_F(OverflowButtonInkDropTest, TouchDragOutAndBack) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.set_current_location(GetScreenPointInsideOverflowButton());
generator.PressTouch();
EXPECT_EQ(views::InkDropState::ACTION_PENDING,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTION_PENDING));
generator.MoveTouch(GetScreenPointOutsideOverflowButton());
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::HIDDEN));
generator.MoveTouch(GetScreenPointInsideOverflowButton());
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.ReleaseTouch();
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
EXPECT_FALSE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when the user long
// presses on the button to show the context menu.
TEST_F(OverflowButtonInkDropTest, TouchContextMenu) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.set_current_location(GetScreenPointInsideOverflowButton());
RunAllPendingInMessageLoop();
{
ScopedMockTaskRunnerWrapper mock_task_runner;
generator.PressTouch();
EXPECT_EQ(views::InkDropState::ACTION_PENDING,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTION_PENDING));
mock_task_runner.FastForwardUntilNoTasksRemain();
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ALTERNATE_ACTION_PENDING,
views::InkDropState::HIDDEN));
generator.ReleaseTouch();
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
EXPECT_FALSE(test_api_->IsShowingOverflowBubble());
}
}
#endif // !defined(OS_WIN)
// Test fixture for testing material design ink drop on overflow button when it
// is active.
class OverflowButtonActiveInkDropTest : public OverflowButtonInkDropTest {
public:
OverflowButtonActiveInkDropTest() {}
~OverflowButtonActiveInkDropTest() override {}
void SetUp() override {
OverflowButtonInkDropTest::SetUp();
test_api_->ShowOverflowBubble();
ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::ACTIVATED));
}
private:
DISALLOW_COPY_AND_ASSIGN(OverflowButtonActiveInkDropTest);
};
// Tests ink drop state transitions for the overflow button when it is active
// and the user clicks on it.
TEST_F(OverflowButtonActiveInkDropTest, MouseDeactivate) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.MoveMouseTo(GetScreenPointInsideOverflowButton());
generator.PressLeftButton();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.ReleaseLeftButton();
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::DEACTIVATED));
EXPECT_FALSE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when it is active
// and the user presses left mouse button on it and drags it out of the button
// bounds.
TEST_F(OverflowButtonActiveInkDropTest, MouseDragOut) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.MoveMouseTo(GetScreenPointInsideOverflowButton());
generator.PressLeftButton();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.MoveMouseTo(GetScreenPointOutsideOverflowButton());
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.ReleaseLeftButton();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when it is active
// and the user presses left mouse button on it and drags it out of the button
// bounds and back.
TEST_F(OverflowButtonActiveInkDropTest, MouseDragOutAndBack) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.MoveMouseTo(GetScreenPointInsideOverflowButton());
generator.PressLeftButton();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.MoveMouseTo(GetScreenPointOutsideOverflowButton());
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.MoveMouseTo(GetScreenPointInsideOverflowButton());
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.ReleaseLeftButton();
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::DEACTIVATED));
EXPECT_FALSE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when it is active
// and the user right clicks on the button to show the context menu.
TEST_F(OverflowButtonActiveInkDropTest, MouseContextMenu) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.MoveMouseTo(GetScreenPointInsideOverflowButton());
generator.PressRightButton();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.ReleaseRightButton();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
}
// There is no ink drop effect for gesture events on Windows.
#if !defined(OS_WIN)
// Tests ink drop state transitions for the overflow button when it is active
// and the user taps on it.
TEST_F(OverflowButtonActiveInkDropTest, TouchDeactivate) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.set_current_location(GetScreenPointInsideOverflowButton());
generator.PressTouch();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.ReleaseTouch();
EXPECT_EQ(views::InkDropState::HIDDEN,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
ElementsAre(views::InkDropState::DEACTIVATED,
views::InkDropState::HIDDEN));
EXPECT_FALSE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when it is active
// and the user taps down on it and drags it out of the button bounds.
TEST_F(OverflowButtonActiveInkDropTest, TouchDragOut) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.set_current_location(GetScreenPointInsideOverflowButton());
generator.PressTouch();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.MoveTouch(GetScreenPointOutsideOverflowButton());
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.ReleaseTouch();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when it is active
// and the user taps down on it and drags it out of the button bounds and back.
TEST_F(OverflowButtonActiveInkDropTest, TouchDragOutAndBack) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.set_current_location(GetScreenPointInsideOverflowButton());
generator.PressTouch();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.MoveTouch(GetScreenPointOutsideOverflowButton());
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.MoveTouch(GetScreenPointInsideOverflowButton());
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.ReleaseTouch();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
}
// Tests ink drop state transitions for the overflow button when it is active
// and the user long presses on the button to show the context menu.
TEST_F(OverflowButtonActiveInkDropTest, TouchContextMenu) {
ui::test::EventGenerator& generator = GetEventGenerator();
generator.set_current_location(GetScreenPointInsideOverflowButton());
RunAllPendingInMessageLoop();
{
ScopedMockTaskRunnerWrapper mock_task_runner;
generator.PressTouch();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
mock_task_runner.FastForwardUntilNoTasksRemain();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
generator.ReleaseTouch();
EXPECT_EQ(views::InkDropState::ACTIVATED,
overflow_button_ink_drop_->GetTargetInkDropState());
EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(),
IsEmpty());
ASSERT_TRUE(test_api_->IsShowingOverflowBubble());
}
}
#endif // !defined(OS_WIN)
} // namespace test } // namespace test
} // namespace ash } // namespace ash
...@@ -68,10 +68,19 @@ bool ShelfViewTestAPI::IsOverflowButtonVisible() { ...@@ -68,10 +68,19 @@ bool ShelfViewTestAPI::IsOverflowButtonVisible() {
} }
void ShelfViewTestAPI::ShowOverflowBubble() { void ShelfViewTestAPI::ShowOverflowBubble() {
if (!shelf_view_->IsShowingOverflowBubble()) DCHECK(!shelf_view_->IsShowingOverflowBubble());
shelf_view_->ToggleOverflowBubble(); shelf_view_->ToggleOverflowBubble();
} }
void ShelfViewTestAPI::HideOverflowBubble() {
DCHECK(shelf_view_->IsShowingOverflowBubble());
shelf_view_->ToggleOverflowBubble();
}
bool ShelfViewTestAPI::IsShowingOverflowBubble() const {
return shelf_view_->IsShowingOverflowBubble();
}
const gfx::Rect& ShelfViewTestAPI::GetBoundsByIndex(int index) { const gfx::Rect& ShelfViewTestAPI::GetBoundsByIndex(int index) {
return shelf_view_->view_model_->view_at(index)->bounds(); return shelf_view_->view_model_->view_at(index)->bounds();
} }
...@@ -110,6 +119,10 @@ OverflowBubble* ShelfViewTestAPI::overflow_bubble() { ...@@ -110,6 +119,10 @@ OverflowBubble* ShelfViewTestAPI::overflow_bubble() {
return shelf_view_->overflow_bubble_.get(); return shelf_view_->overflow_bubble_.get();
} }
OverflowButton* ShelfViewTestAPI::overflow_button() const {
return shelf_view_->overflow_button_;
}
ShelfTooltipManager* ShelfViewTestAPI::tooltip_manager() { ShelfTooltipManager* ShelfViewTestAPI::tooltip_manager() {
return &shelf_view_->tooltip_; return &shelf_view_->tooltip_;
} }
......
...@@ -25,6 +25,7 @@ class InkDrop; ...@@ -25,6 +25,7 @@ class InkDrop;
namespace ash { namespace ash {
class OverflowBubble; class OverflowBubble;
class OverflowButton;
class ShelfButton; class ShelfButton;
class ShelfButtonPressedMetricTracker; class ShelfButtonPressedMetricTracker;
class ShelfDelegate; class ShelfDelegate;
...@@ -61,6 +62,12 @@ class ShelfViewTestAPI { ...@@ -61,6 +62,12 @@ class ShelfViewTestAPI {
// Makes shelf view show its overflow bubble. // Makes shelf view show its overflow bubble.
void ShowOverflowBubble(); void ShowOverflowBubble();
// Makes shelf view hide its overflow bubble.
void HideOverflowBubble();
// Returns true if the overflow bubble is visible.
bool IsShowingOverflowBubble() const;
// Sets animation duration in milliseconds for test. // Sets animation duration in milliseconds for test.
void SetAnimationDuration(int duration_ms); void SetAnimationDuration(int duration_ms);
...@@ -79,6 +86,9 @@ class ShelfViewTestAPI { ...@@ -79,6 +86,9 @@ class ShelfViewTestAPI {
// An accessor for overflow bubble. // An accessor for overflow bubble.
OverflowBubble* overflow_bubble(); OverflowBubble* overflow_bubble();
// An accessor for overflow button.
OverflowButton* overflow_button() const;
// Returns the preferred size of |shelf_view_|. // Returns the preferred size of |shelf_view_|.
gfx::Size GetPreferredSize(); gfx::Size GetPreferredSize();
......
...@@ -58,6 +58,8 @@ class InkDropHostView::InkDropGestureHandler : public ui::EventHandler { ...@@ -58,6 +58,8 @@ class InkDropHostView::InkDropGestureHandler : public ui::EventHandler {
InkDropState ink_drop_state = InkDropState::HIDDEN; InkDropState ink_drop_state = InkDropState::HIDDEN;
switch (event->type()) { switch (event->type()) {
case ui::ET_GESTURE_TAP_DOWN: case ui::ET_GESTURE_TAP_DOWN:
if (current_ink_drop_state == InkDropState::ACTIVATED)
return;
ink_drop_state = InkDropState::ACTION_PENDING; ink_drop_state = InkDropState::ACTION_PENDING;
// The ui::ET_GESTURE_TAP_DOWN event needs to be marked as handled so // The ui::ET_GESTURE_TAP_DOWN event needs to be marked as handled so
// that // that
...@@ -65,16 +67,17 @@ class InkDropHostView::InkDropGestureHandler : public ui::EventHandler { ...@@ -65,16 +67,17 @@ class InkDropHostView::InkDropGestureHandler : public ui::EventHandler {
event->SetHandled(); event->SetHandled();
break; break;
case ui::ET_GESTURE_LONG_PRESS: case ui::ET_GESTURE_LONG_PRESS:
if (current_ink_drop_state == InkDropState::ACTIVATED)
return;
ink_drop_state = InkDropState::ALTERNATE_ACTION_PENDING; ink_drop_state = InkDropState::ALTERNATE_ACTION_PENDING;
break; break;
case ui::ET_GESTURE_LONG_TAP: case ui::ET_GESTURE_LONG_TAP:
ink_drop_state = InkDropState::ALTERNATE_ACTION_TRIGGERED; ink_drop_state = InkDropState::ALTERNATE_ACTION_TRIGGERED;
break; break;
case ui::ET_GESTURE_END: case ui::ET_GESTURE_END:
case ui::ET_GESTURE_SCROLL_BEGIN:
if (current_ink_drop_state == InkDropState::ACTIVATED) if (current_ink_drop_state == InkDropState::ACTIVATED)
return; return;
// Fall through to ui::ET_GESTURE_SCROLL_BEGIN case.
case ui::ET_GESTURE_SCROLL_BEGIN:
ink_drop_state = InkDropState::HIDDEN; ink_drop_state = InkDropState::HIDDEN;
break; break;
default: default:
......
...@@ -470,8 +470,13 @@ void CustomButton::NotifyClick(const ui::Event& event) { ...@@ -470,8 +470,13 @@ void CustomButton::NotifyClick(const ui::Event& event) {
} }
void CustomButton::OnClickCanceled(const ui::Event& event) { void CustomButton::OnClickCanceled(const ui::Event& event) {
if (ink_drop()->GetTargetInkDropState() ==
views::InkDropState::ACTION_PENDING ||
ink_drop()->GetTargetInkDropState() ==
views::InkDropState::ALTERNATE_ACTION_PENDING) {
AnimateInkDrop(views::InkDropState::HIDDEN, AnimateInkDrop(views::InkDropState::HIDDEN,
ui::LocatedEvent::FromIfValid(&event)); ui::LocatedEvent::FromIfValid(&event));
}
Button::OnClickCanceled(event); Button::OnClickCanceled(event);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment