Commit aeb60604 authored by Andrew Xu's avatar Andrew Xu Committed by Commit Bot

Fix the issue that shelf icon becomes invisible after drag

When ScrollableShelf is enabled, the shelf icon under drag is actually
the proxy icon created by ScrollableShelfView while the original shelf
icon is transparent. However, when dragging an icon which is already
pinned on Shelf from AppsGridView, if the drag gets canceled, the
original shelf icon fails to show. This CL fixes such an issue. A
unit test is created for this scenario.

Bug: 1021768
Change-Id: Ibfce9ae3c59c21ac7d7e515b3a3a733e453fe5b2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1902511Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Andrew Xu <andrewxu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#713630}
parent b482fd76
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#include "ash/public/cpp/window_properties.h" #include "ash/public/cpp/window_properties.h"
#include "ash/shelf/shelf.h" #include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_view.h"
#include "ash/shelf/shelf_view_test_api.h"
#include "ash/shelf/shelf_widget.h" #include "ash/shelf/shelf_widget.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/system/unified/unified_system_tray_test_api.h" #include "ash/system/unified/unified_system_tray_test_api.h"
...@@ -473,6 +475,52 @@ class HotseatAppListControllerImplTest ...@@ -473,6 +475,52 @@ class HotseatAppListControllerImplTest
// Tests with both hotseat disabled and enabled. // Tests with both hotseat disabled and enabled.
INSTANTIATE_TEST_SUITE_P(, HotseatAppListControllerImplTest, testing::Bool()); INSTANTIATE_TEST_SUITE_P(, HotseatAppListControllerImplTest, testing::Bool());
// Verifies that the pinned app should still show after canceling the drag from
// AppsGridView to Shelf (https://crbug.com/1021768).
TEST_P(HotseatAppListControllerImplTest, DragItemFromAppsGridView) {
// Turn on the tablet mode.
Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
EXPECT_TRUE(IsTabletMode());
Shelf* const shelf = GetPrimaryShelf();
// Add icons with the same app id to Shelf and AppsGridView respectively.
ShelfViewTestAPI shelf_view_test_api(shelf->GetShelfViewForTesting());
std::string app_id = shelf_view_test_api.AddItem(TYPE_PINNED_APP).app_id;
Shell::Get()->app_list_controller()->GetModel()->AddItem(
std::make_unique<AppListItem>(app_id));
AppsGridView* apps_grid_view = GetAppListView()
->app_list_main_view()
->contents_view()
->GetAppsContainerView()
->apps_grid_view();
AppListItemView* app_list_item_view =
test::AppsGridViewTestApi(apps_grid_view).GetViewAtIndex(GridIndex(0, 0));
views::View* shelf_icon_view =
shelf->GetShelfViewForTesting()->view_model()->view_at(0);
// Drag the app icon from AppsGridView to Shelf. Then move the icon back to
// AppsGridView before drag ends.
GetEventGenerator()->MoveMouseTo(
app_list_item_view->GetBoundsInScreen().CenterPoint());
GetEventGenerator()->PressLeftButton();
app_list_item_view->FireMouseDragTimerForTest();
GetEventGenerator()->MoveMouseTo(
shelf_icon_view->GetBoundsInScreen().CenterPoint());
GetEventGenerator()->MoveMouseTo(
apps_grid_view->GetBoundsInScreen().CenterPoint());
GetEventGenerator()->ReleaseLeftButton();
// The icon's opacity updates at the end of animation.
shelf_view_test_api.RunMessageLoopUntilAnimationsDone();
// The icon is pinned before drag starts. So the shelf icon should show in
// spite that drag is canceled.
EXPECT_TRUE(shelf_icon_view->GetVisible());
EXPECT_EQ(1.0f, shelf_icon_view->layer()->opacity());
}
// Tests for HomeScreenDelegate::GetInitialAppListItemScreenBoundsForWindow // Tests for HomeScreenDelegate::GetInitialAppListItemScreenBoundsForWindow
// implemtenation. // implemtenation.
TEST_P(HotseatAppListControllerImplTest, GetItemBoundsForWindow) { TEST_P(HotseatAppListControllerImplTest, GetItemBoundsForWindow) {
......
...@@ -803,6 +803,10 @@ void AppListItemView::EnsureLayer() { ...@@ -803,6 +803,10 @@ void AppListItemView::EnsureLayer() {
layer()->SetFillsBoundsOpaquely(false); layer()->SetFillsBoundsOpaquely(false);
} }
void AppListItemView::FireMouseDragTimerForTest() {
mouse_drag_timer_.FireNow();
}
void AppListItemView::AnimationProgressed(const gfx::Animation* animation) { void AppListItemView::AnimationProgressed(const gfx::Animation* animation) {
DCHECK(!is_folder_); DCHECK(!is_folder_);
......
...@@ -136,6 +136,8 @@ class APP_LIST_EXPORT AppListItemView : public views::Button, ...@@ -136,6 +136,8 @@ class APP_LIST_EXPORT AppListItemView : public views::Button,
// Ensures this item view has its own layer. // Ensures this item view has its own layer.
void EnsureLayer(); void EnsureLayer();
void FireMouseDragTimerForTest();
bool is_folder() const { return is_folder_; } bool is_folder() const { return is_folder_; }
private: private:
......
...@@ -1351,11 +1351,23 @@ void ShelfView::EndDrag(bool cancel) { ...@@ -1351,11 +1351,23 @@ void ShelfView::EndDrag(bool cancel) {
if (drag_and_drop_item_pinned_ && cancel) { if (drag_and_drop_item_pinned_ && cancel) {
model_->UnpinAppWithID(drag_and_drop_shelf_id_.app_id); model_->UnpinAppWithID(drag_and_drop_shelf_id_.app_id);
} else if (drag_and_drop_view) { } else if (drag_and_drop_view) {
std::unique_ptr<gfx::AnimationDelegate> animation_delegate;
if (chromeos::switches::ShouldShowScrollableShelf()) {
// Resets the dragged view's opacity at the end of drag. Otherwise, if
// the app is already pinned on shelf before drag starts, the dragged view
// will be invisible when drag ends.
animation_delegate = std::make_unique<StartFadeAnimationDelegate>(
this, drag_and_drop_view);
}
if (cancel) { if (cancel) {
// When a hosted drag gets canceled, the item can remain in the same slot // When a hosted drag gets canceled, the item can remain in the same slot
// and it might have moved within the bounds. In that case the item need // and it might have moved within the bounds. In that case the item need
// to animate back to its correct location. // to animate back to its correct location.
AnimateToIdealBounds(); AnimateToIdealBounds();
bounds_animator_->SetAnimationDelegate(drag_and_drop_view,
std::move(animation_delegate));
} else { } else {
drag_and_drop_view->SetSize(pre_drag_and_drop_size_); drag_and_drop_view->SetSize(pre_drag_and_drop_size_);
} }
......
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