blob: 27623b5420b46509d3373516b1f4b7b056ffc533 [file] [log] [blame]
// Copyright (c) 2012 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 "ash/launcher/launcher_view.h"
#include <algorithm>
#include <vector>
#include "ash/launcher/launcher.h"
#include "ash/launcher/launcher_button.h"
#include "ash/launcher/launcher_icon_observer.h"
#include "ash/launcher/launcher_model.h"
#include "ash/launcher/launcher_tooltip_manager.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/test/launcher_view_test_api.h"
#include "ash/test/test_launcher_delegate.h"
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "grit/ash_resources.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/window.h"
#include "ui/base/events/event.h"
#include "ui/base/events/event_constants.h"
#include "ui/compositor/layer.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
namespace {
const int kExpectedAppIndex = 1;
}
namespace ash {
namespace test {
////////////////////////////////////////////////////////////////////////////////
// LauncherIconObserver tests.
class TestLauncherIconObserver : public LauncherIconObserver {
public:
explicit TestLauncherIconObserver(Launcher* launcher)
: launcher_(launcher),
change_notified_(false) {
if (launcher_)
launcher_->AddIconObserver(this);
}
virtual ~TestLauncherIconObserver() {
if (launcher_)
launcher_->RemoveIconObserver(this);
}
// LauncherIconObserver implementation.
virtual void OnLauncherIconPositionsChanged() OVERRIDE {
change_notified_ = true;
}
int change_notified() const { return change_notified_; }
void Reset() { change_notified_ = false; }
private:
Launcher* launcher_;
bool change_notified_;
DISALLOW_COPY_AND_ASSIGN(TestLauncherIconObserver);
};
class LauncherViewIconObserverTest : public ash::test::AshTestBase {
public:
LauncherViewIconObserverTest() {}
virtual ~LauncherViewIconObserverTest() {}
virtual void SetUp() OVERRIDE {
AshTestBase::SetUp();
Launcher* launcher = Shell::GetInstance()->launcher();
observer_.reset(new TestLauncherIconObserver(launcher));
launcher_view_test_.reset(new LauncherViewTestAPI(
launcher->GetLauncherViewForTest()));
launcher_view_test_->SetAnimationDuration(1);
}
virtual void TearDown() OVERRIDE {
observer_.reset();
AshTestBase::TearDown();
}
TestLauncherIconObserver* observer() { return observer_.get(); }
LauncherViewTestAPI* launcher_vew_test() {
return launcher_view_test_.get();
}
private:
scoped_ptr<TestLauncherIconObserver> observer_;
scoped_ptr<LauncherViewTestAPI> launcher_view_test_;
DISALLOW_COPY_AND_ASSIGN(LauncherViewIconObserverTest);
};
TEST_F(LauncherViewIconObserverTest, AddRemove) {
ash::test::TestLauncherDelegate* launcher_delegate =
ash::test::TestLauncherDelegate::instance();
ASSERT_TRUE(launcher_delegate);
views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.bounds = gfx::Rect(0, 0, 200, 200);
scoped_ptr<views::Widget> widget(new views::Widget());
widget->Init(params);
launcher_delegate->AddLauncherItem(widget->GetNativeWindow());
launcher_vew_test()->RunMessageLoopUntilAnimationsDone();
EXPECT_TRUE(observer()->change_notified());
observer()->Reset();
widget->Show();
widget->GetNativeWindow()->parent()->RemoveChild(widget->GetNativeWindow());
launcher_vew_test()->RunMessageLoopUntilAnimationsDone();
EXPECT_TRUE(observer()->change_notified());
observer()->Reset();
}
TEST_F(LauncherViewIconObserverTest, BoundsChanged) {
Launcher* launcher = Shell::GetInstance()->launcher();
gfx::Size launcher_size =
launcher->widget()->GetWindowBoundsInScreen().size();
int total_width = launcher_size.width() / 2;
ASSERT_GT(total_width, 0);
launcher->SetStatusSize(gfx::Size(total_width, launcher_size.height()));
// No animation happens for LauncherView bounds change.
EXPECT_TRUE(observer()->change_notified());
observer()->Reset();
}
////////////////////////////////////////////////////////////////////////////////
// LauncherView tests.
class MockLauncherDelegate : public ash::LauncherDelegate {
public:
MockLauncherDelegate() {}
virtual ~MockLauncherDelegate() {}
// LauncherDelegate overrides:
virtual void CreateNewTab() OVERRIDE {}
virtual void CreateNewWindow() OVERRIDE {}
virtual void ItemClicked(const ash::LauncherItem& item,
int event_flags) OVERRIDE {}
virtual int GetBrowserShortcutResourceId() OVERRIDE {
return IDR_AURA_LAUNCHER_BROWSER_SHORTCUT;
}
virtual string16 GetTitle(const ash::LauncherItem& item) OVERRIDE {
return string16();
}
virtual ui::MenuModel* CreateContextMenu(
const ash::LauncherItem& item) OVERRIDE {
return NULL;
}
virtual ui::MenuModel* CreateContextMenuForLauncher() OVERRIDE {
return NULL;
}
virtual ash::LauncherID GetIDByWindow(aura::Window* window) OVERRIDE {
NOTREACHED();
return -1;
}
virtual bool IsDraggable(const ash::LauncherItem& item) OVERRIDE {
return true;
}
};
class LauncherViewTest : public AshTestBase {
public:
LauncherViewTest() {}
virtual ~LauncherViewTest() {}
virtual void SetUp() OVERRIDE {
AshTestBase::SetUp();
model_.reset(new LauncherModel);
launcher_view_.reset(new internal::LauncherView(
model_.get(), &delegate_, NULL));
launcher_view_->Init();
// The bounds should be big enough for 4 buttons + overflow chevron.
launcher_view_->SetBounds(0, 0, 500, 50);
test_api_.reset(new LauncherViewTestAPI(launcher_view_.get()));
test_api_->SetAnimationDuration(1); // Speeds up animation for test.
}
virtual void TearDown() OVERRIDE {
launcher_view_.reset();
AshTestBase::TearDown();
}
protected:
LauncherID AddAppShortcut() {
LauncherItem item;
item.type = TYPE_APP_SHORTCUT;
item.status = STATUS_CLOSED;
LauncherID id = model_->next_id();
model_->Add(item);
test_api_->RunMessageLoopUntilAnimationsDone();
return id;
}
LauncherID AddTabbedBrowserNoWait() {
LauncherItem item;
item.type = TYPE_TABBED;
item.status = STATUS_RUNNING;
LauncherID id = model_->next_id();
model_->Add(item);
return id;
}
LauncherID AddTabbedBrowser() {
LauncherID id = AddTabbedBrowserNoWait();
test_api_->RunMessageLoopUntilAnimationsDone();
return id;
}
LauncherID AddPlatformAppNoWait() {
LauncherItem item;
item.type = TYPE_PLATFORM_APP;
item.status = STATUS_RUNNING;
LauncherID id = model_->next_id();
model_->Add(item);
return id;
}
LauncherID AddPlatformApp() {
LauncherID id = AddPlatformAppNoWait();
test_api_->RunMessageLoopUntilAnimationsDone();
return id;
}
void RemoveByID(LauncherID id) {
model_->RemoveItemAt(model_->ItemIndexByID(id));
test_api_->RunMessageLoopUntilAnimationsDone();
}
internal::LauncherButton* GetButtonByID(LauncherID id) {
int index = model_->ItemIndexByID(id);
return test_api_->GetButton(index);
}
LauncherItem GetItemByID(LauncherID id) {
LauncherItems::const_iterator items = model_->ItemByID(id);
return *items;
}
void CheckModelIDs(
const std::vector<std::pair<LauncherID, views::View*> >& id_map) {
size_t map_index = 0;
for (size_t model_index = 0;
model_index < model_->items().size();
++model_index) {
ash::LauncherItem item = model_->items()[model_index];
ash::LauncherID id = item.id;
EXPECT_EQ(id_map[map_index].first, id);
EXPECT_EQ(id_map[map_index].second, GetButtonByID(id));
++map_index;
}
ASSERT_EQ(map_index, id_map.size());
}
views::View* SimulateDrag(internal::LauncherButtonHost::Pointer pointer,
int button_index,
int destination_index) {
// Add kExpectedAppIndex to each button index to allow default icons.
internal::LauncherButtonHost* button_host = launcher_view_.get();
// Mouse down.
views::View* button =
test_api_->GetButton(kExpectedAppIndex + button_index);
ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED,
button->bounds().origin(),
button->bounds().origin(), 0);
button_host->PointerPressedOnButton(button, pointer, click_event);
// Drag.
views::View* destination =
test_api_->GetButton(kExpectedAppIndex + destination_index);
ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED,
destination->bounds().origin(),
destination->bounds().origin(), 0);
button_host->PointerDraggedOnButton(button, pointer, drag_event);
return button;
}
void SetupForDragTest(
std::vector<std::pair<LauncherID, views::View*> >* id_map) {
// Initialize |id_map| with the automatically-created launcher buttons.
for (size_t i = 0; i < model_->items().size(); ++i) {
internal::LauncherButton* button = test_api_->GetButton(i);
id_map->push_back(std::make_pair(model_->items()[i].id, button));
}
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(*id_map));
// Add 5 app launcher buttons for testing.
for (int i = 0; i < 5; ++i) {
LauncherID id = AddAppShortcut();
id_map->insert(id_map->begin() + (kExpectedAppIndex + i),
std::make_pair(id, GetButtonByID(id)));
}
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(*id_map));
}
views::View* GetTooltipAnchorView() {
return launcher_view_->tooltip_manager()->anchor_;
}
void ShowTooltip() {
launcher_view_->tooltip_manager()->ShowInternal();
}
MockLauncherDelegate delegate_;
scoped_ptr<LauncherModel> model_;
scoped_ptr<internal::LauncherView> launcher_view_;
scoped_ptr<LauncherViewTestAPI> test_api_;
private:
DISALLOW_COPY_AND_ASSIGN(LauncherViewTest);
};
// Adds browser button until overflow and verifies that the last added browser
// button is hidden.
TEST_F(LauncherViewTest, AddBrowserUntilOverflow) {
// All buttons should be visible.
ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
test_api_->GetButtonCount());
// Add tabbed browser until overflow.
LauncherID last_added = AddTabbedBrowser();
while (!test_api_->IsOverflowButtonVisible()) {
// Added button is visible after animation while in this loop.
EXPECT_TRUE(GetButtonByID(last_added)->visible());
last_added = AddTabbedBrowser();
}
// The last added button should be invisible.
EXPECT_FALSE(GetButtonByID(last_added)->visible());
}
// Adds one browser button then adds app shortcut until overflow. Verifies that
// the browser button gets hidden on overflow and last added app shortcut is
// still visible.
TEST_F(LauncherViewTest, AddAppShortcutWithBrowserButtonUntilOverflow) {
// All buttons should be visible.
ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
test_api_->GetButtonCount());
LauncherID browser_button_id = AddTabbedBrowser();
// Add app shortcut until overflow.
LauncherID last_added = AddAppShortcut();
while (!test_api_->IsOverflowButtonVisible()) {
// Added button is visible after animation while in this loop.
EXPECT_TRUE(GetButtonByID(last_added)->visible());
last_added = AddAppShortcut();
}
// The last added app short button should be visible.
EXPECT_TRUE(GetButtonByID(last_added)->visible());
// And the browser button is invisible.
EXPECT_FALSE(GetButtonByID(browser_button_id)->visible());
}
// Adds button until overflow then removes first added one. Verifies that
// the last added one changes from invisible to visible and overflow
// chevron is gone.
TEST_F(LauncherViewTest, RemoveButtonRevealsOverflowed) {
// All buttons should be visible.
ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
test_api_->GetButtonCount());
// Add tabbed browser until overflow.
LauncherID first_added= AddTabbedBrowser();
LauncherID last_added = first_added;
while (!test_api_->IsOverflowButtonVisible())
last_added = AddTabbedBrowser();
// Expect add more than 1 button. First added is visible and last is not.
EXPECT_NE(first_added, last_added);
EXPECT_TRUE(GetButtonByID(first_added)->visible());
EXPECT_FALSE(GetButtonByID(last_added)->visible());
// Remove first added.
RemoveByID(first_added);
// Last added button becomes visible and overflow chevron is gone.
EXPECT_TRUE(GetButtonByID(last_added)->visible());
EXPECT_EQ(1.0f, GetButtonByID(last_added)->layer()->opacity());
EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
}
// Verifies that remove last overflowed button should hide overflow chevron.
TEST_F(LauncherViewTest, RemoveLastOverflowed) {
// All buttons should be visible.
ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
test_api_->GetButtonCount());
// Add tabbed browser until overflow.
LauncherID last_added= AddTabbedBrowser();
while (!test_api_->IsOverflowButtonVisible())
last_added = AddTabbedBrowser();
RemoveByID(last_added);
EXPECT_FALSE(test_api_->IsOverflowButtonVisible());
}
// Adds browser button without waiting for animation to finish and verifies
// that all added buttons are visible.
TEST_F(LauncherViewTest, AddButtonQuickly) {
// All buttons should be visible.
ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
test_api_->GetButtonCount());
// Add a few tabbed browser quickly without wait for animation.
int added_count = 0;
while (!test_api_->IsOverflowButtonVisible()) {
AddTabbedBrowserNoWait();
++added_count;
}
// LauncherView should be big enough to hold at least 3 new buttons.
ASSERT_GE(added_count, 3);
// Wait for the last animation to finish.
test_api_->RunMessageLoopUntilAnimationsDone();
// Verifies non-overflow buttons are visible.
for (int i = 0; i <= test_api_->GetLastVisibleIndex(); ++i) {
internal::LauncherButton* button = test_api_->GetButton(i);
if (button) {
EXPECT_TRUE(button->visible()) << "button index=" << i;
EXPECT_EQ(1.0f, button->layer()->opacity()) << "button index=" << i;
}
}
}
// Check that model changes are handled correctly while a launcher icon is being
// dragged.
TEST_F(LauncherViewTest, ModelChangesWhileDragging) {
internal::LauncherButtonHost* button_host = launcher_view_.get();
std::vector<std::pair<LauncherID, views::View*> > id_map;
SetupForDragTest(&id_map);
// Dragging changes model order.
views::View* dragged_button = SimulateDrag(
internal::LauncherButtonHost::MOUSE, 0, 2);
std::rotate(id_map.begin() + kExpectedAppIndex,
id_map.begin() + kExpectedAppIndex + 1,
id_map.begin() + kExpectedAppIndex + 3);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// Cancelling the drag operation restores previous order.
button_host->PointerReleasedOnButton(dragged_button,
internal::LauncherButtonHost::MOUSE,
true);
std::rotate(id_map.begin() + kExpectedAppIndex,
id_map.begin() + kExpectedAppIndex + 2,
id_map.begin() + kExpectedAppIndex + 3);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// Deleting an item keeps the remaining intact.
dragged_button = SimulateDrag(internal::LauncherButtonHost::MOUSE, 0, 2);
model_->RemoveItemAt(kExpectedAppIndex + 1);
id_map.erase(id_map.begin() + kExpectedAppIndex + 1);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
button_host->PointerReleasedOnButton(dragged_button,
internal::LauncherButtonHost::MOUSE,
false);
// Adding a launcher item cancels the drag and respects the order.
dragged_button = SimulateDrag(internal::LauncherButtonHost::MOUSE, 0, 2);
LauncherID new_id = AddAppShortcut();
id_map.insert(id_map.begin() + kExpectedAppIndex + 4,
std::make_pair(new_id, GetButtonByID(new_id)));
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
button_host->PointerReleasedOnButton(dragged_button,
internal::LauncherButtonHost::MOUSE,
false);
}
// Check that 2nd drag from the other pointer would be ignored.
TEST_F(LauncherViewTest, SimultaneousDrag) {
internal::LauncherButtonHost* button_host = launcher_view_.get();
std::vector<std::pair<LauncherID, views::View*> > id_map;
SetupForDragTest(&id_map);
// Start a mouse drag.
views::View* dragged_button_mouse = SimulateDrag(
internal::LauncherButtonHost::MOUSE, 0, 2);
std::rotate(id_map.begin() + kExpectedAppIndex,
id_map.begin() + kExpectedAppIndex + 1,
id_map.begin() + kExpectedAppIndex + 3);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// Attempt a touch drag before the mouse drag finishes.
views::View* dragged_button_touch = SimulateDrag(
internal::LauncherButtonHost::TOUCH, 3, 1);
// Nothing changes since 2nd drag is ignored.
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// Finish the mouse drag.
button_host->PointerReleasedOnButton(dragged_button_mouse,
internal::LauncherButtonHost::MOUSE,
false);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// Now start a touch drag.
dragged_button_touch = SimulateDrag(
internal::LauncherButtonHost::TOUCH, 3, 1);
std::rotate(id_map.begin() + kExpectedAppIndex + 2,
id_map.begin() + kExpectedAppIndex + 3,
id_map.begin() + kExpectedAppIndex + 4);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
// And attempt a mouse drag before the touch drag finishes.
dragged_button_mouse = SimulateDrag(
internal::LauncherButtonHost::MOUSE, 0, 1);
// Nothing changes since 2nd drag is ignored.
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
button_host->PointerReleasedOnButton(dragged_button_touch,
internal::LauncherButtonHost::TOUCH,
false);
ASSERT_NO_FATAL_FAILURE(CheckModelIDs(id_map));
}
// Confirm that item status changes are reflected in the buttons.
TEST_F(LauncherViewTest, LauncherItemStatus) {
ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
test_api_->GetButtonCount());
// Add tabbed browser.
LauncherID last_added = AddTabbedBrowser();
LauncherItem item = GetItemByID(last_added);
int index = model_->ItemIndexByID(last_added);
internal::LauncherButton* button = GetButtonByID(last_added);
ASSERT_EQ(internal::LauncherButton::STATE_RUNNING, button->state());
item.status = ash::STATUS_ACTIVE;
model_->Set(index, item);
ASSERT_EQ(internal::LauncherButton::STATE_ACTIVE, button->state());
item.status = ash::STATUS_ATTENTION;
model_->Set(index, item);
ASSERT_EQ(internal::LauncherButton::STATE_ATTENTION, button->state());
}
// Confirm that item status changes are reflected in the buttons
// for platform apps.
TEST_F(LauncherViewTest, LauncherItemStatusPlatformApp) {
ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
test_api_->GetButtonCount());
// Add tabbed browser.
LauncherID last_added = AddPlatformApp();
LauncherItem item = GetItemByID(last_added);
int index = model_->ItemIndexByID(last_added);
internal::LauncherButton* button = GetButtonByID(last_added);
ASSERT_EQ(internal::LauncherButton::STATE_RUNNING, button->state());
item.status = ash::STATUS_ACTIVE;
model_->Set(index, item);
ASSERT_EQ(internal::LauncherButton::STATE_ACTIVE, button->state());
item.status = ash::STATUS_ATTENTION;
model_->Set(index, item);
ASSERT_EQ(internal::LauncherButton::STATE_ATTENTION, button->state());
}
TEST_F(LauncherViewTest, LauncherTooltipTest) {
ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
test_api_->GetButtonCount());
// Prepare some items to the launcher.
LauncherID app_button_id = AddAppShortcut();
LauncherID tab_button_id = AddTabbedBrowser();
internal::LauncherButton* app_button = GetButtonByID(app_button_id);
internal::LauncherButton* tab_button = GetButtonByID(tab_button_id);
internal::LauncherButtonHost* button_host = launcher_view_.get();
internal::LauncherTooltipManager* tooltip_manager =
launcher_view_->tooltip_manager();
button_host->MouseEnteredButton(app_button);
// There's a delay to show the tooltip, so it's not visible yet.
EXPECT_FALSE(tooltip_manager->IsVisible());
EXPECT_EQ(app_button, GetTooltipAnchorView());
ShowTooltip();
EXPECT_TRUE(tooltip_manager->IsVisible());
// Once it's visible, it keeps visibility and is pointing to the same
// item.
button_host->MouseExitedButton(app_button);
EXPECT_TRUE(tooltip_manager->IsVisible());
EXPECT_EQ(app_button, GetTooltipAnchorView());
// When entered to another item, it switches to the new item. There is no
// delay for the visibility.
button_host->MouseEnteredButton(tab_button);
EXPECT_TRUE(tooltip_manager->IsVisible());
EXPECT_EQ(tab_button, GetTooltipAnchorView());
button_host->MouseExitedButton(tab_button);
tooltip_manager->Close();
// Next time: enter app_button -> move immediately to tab_button.
button_host->MouseEnteredButton(app_button);
button_host->MouseExitedButton(app_button);
button_host->MouseEnteredButton(tab_button);
EXPECT_FALSE(tooltip_manager->IsVisible());
EXPECT_EQ(tab_button, GetTooltipAnchorView());
}
TEST_F(LauncherViewTest, ShouldHideTooltipTest) {
LauncherID app_button_id = AddAppShortcut();
LauncherID tab_button_id = AddTabbedBrowser();
// The tooltip shouldn't hide if the mouse is on normal buttons.
for (int i = 0; i < test_api_->GetButtonCount(); i++) {
internal::LauncherButton* button = test_api_->GetButton(i);
if (!button)
continue;
EXPECT_FALSE(launcher_view_->ShouldHideTooltip(
button->GetMirroredBounds().CenterPoint()))
<< "LauncherView tries to hide on button " << i;
}
// The tooltip should not hide on the app-list button.
views::View* app_list_button = launcher_view_->GetAppListButtonView();
EXPECT_FALSE(launcher_view_->ShouldHideTooltip(
app_list_button->GetMirroredBounds().CenterPoint()));
// The tooltip shouldn't hide if the mouse is in the gap between two buttons.
gfx::Rect app_button_rect = GetButtonByID(app_button_id)->GetMirroredBounds();
gfx::Rect tab_button_rect = GetButtonByID(tab_button_id)->GetMirroredBounds();
ASSERT_FALSE(app_button_rect.Intersects(tab_button_rect));
EXPECT_FALSE(launcher_view_->ShouldHideTooltip(
app_button_rect.Union(tab_button_rect).CenterPoint()));
// The tooltip should hide if it's outside of all buttons.
gfx::Rect all_area;
for (int i = 0; i < test_api_->GetButtonCount(); i++) {
internal::LauncherButton* button = test_api_->GetButton(i);
if (!button)
continue;
all_area = all_area.Union(button->GetMirroredBounds());
}
all_area = all_area.Union(
launcher_view_->GetAppListButtonView()->GetMirroredBounds());
EXPECT_FALSE(launcher_view_->ShouldHideTooltip(all_area.origin()));
EXPECT_FALSE(launcher_view_->ShouldHideTooltip(
gfx::Point(all_area.right() - 1, all_area.bottom() - 1)));
EXPECT_TRUE(launcher_view_->ShouldHideTooltip(
gfx::Point(all_area.right(), all_area.y())));
EXPECT_TRUE(launcher_view_->ShouldHideTooltip(
gfx::Point(all_area.x() - 1, all_area.y())));
EXPECT_TRUE(launcher_view_->ShouldHideTooltip(
gfx::Point(all_area.x(), all_area.y() - 1)));
EXPECT_TRUE(launcher_view_->ShouldHideTooltip(
gfx::Point(all_area.x(), all_area.bottom())));
}
TEST_F(LauncherViewTest, ShouldHideTooltipWithAppListWindowTest) {
Shell::GetInstance()->ToggleAppList();
ASSERT_TRUE(Shell::GetInstance()->GetAppListWindow());
// The tooltip shouldn't hide if the mouse is on normal buttons.
for (int i = 1; i < test_api_->GetButtonCount(); i++) {
internal::LauncherButton* button = test_api_->GetButton(i);
if (!button)
continue;
EXPECT_FALSE(launcher_view_->ShouldHideTooltip(
button->GetMirroredBounds().CenterPoint()))
<< "LauncherView tries to hide on button " << i;
}
// The tooltip should hide on the app-list button.
views::View* app_list_button = launcher_view_->GetAppListButtonView();
EXPECT_TRUE(launcher_view_->ShouldHideTooltip(
app_list_button->GetMirroredBounds().CenterPoint()));
}
// Resizing launcher view while an add animation without fade-in is running,
// which happens when overflow happens. App list button should end up in its
// new ideal bounds.
TEST_F(LauncherViewTest, ResizeDuringOverflowAddAnimation) {
// All buttons should be visible.
ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1,
test_api_->GetButtonCount());
// Add buttons until overflow. Let the non-overflow add animations finish but
// leave the last running.
AddTabbedBrowserNoWait();
while (!test_api_->IsOverflowButtonVisible()) {
test_api_->RunMessageLoopUntilAnimationsDone();
AddTabbedBrowserNoWait();
}
// Resize launcher view with that animation running and stay overflown.
gfx::Rect bounds = launcher_view_->bounds();
bounds.set_width(bounds.width() - kLauncherPreferredSize);
launcher_view_->SetBoundsRect(bounds);
ASSERT_TRUE(test_api_->IsOverflowButtonVisible());
// Finish the animation.
test_api_->RunMessageLoopUntilAnimationsDone();
// App list button should ends up in its new ideal bounds.
const int app_list_button_index = test_api_->GetButtonCount() - 1;
const gfx::Rect& app_list_ideal_bounds =
test_api_->GetIdealBoundsByIndex(app_list_button_index);
const gfx::Rect& app_list_bounds =
test_api_->GetBoundsByIndex(app_list_button_index);
EXPECT_EQ(app_list_bounds, app_list_ideal_bounds);
}
} // namespace test
} // namespace ash