Commit 293d9bbf authored by Jun Mukai's avatar Jun Mukai Committed by Commit Bot

Keep item view's layer as long as app-list is dragged

The current code nicely creates and destroys the layer of
individual app-list item view when dragging the app-list to reveal.
This actually invalidates the parent layer and causes during
the drag.

Creating the layers of all items when the drag starts keeping them
as long as the drag continues actually reduce unnecessary repainting
because of this.

This CL does not change the LauncherDragTest numbers, but it
actually decreases the presentation time of dragging significantly
on nocturne with my test account -- mean ~110msec to ~65msec.

Bug: 987095
Test: manually / ash_unittests
Change-Id: Ib26fb9f192832b91237ed155d30f56bae80d76d1
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1717424
Commit-Queue: Jun Mukai <mukai@chromium.org>
Reviewed-by: default avatarAlex Newcomer <newcomer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#680623}
parent eb9334b0
......@@ -1454,11 +1454,17 @@ TEST_F(AppListPresenterDelegateHomeLauncherTest, MouseDragAppList) {
EXPECT_TRUE(apps_grid_view->GetVisible());
}
// Verifies that mouse dragging AppListView causes to change the opacity.
// Verifies that mouse dragging AppListView creates layers, causes to change the
// opacity, and destroys the layers when done.
TEST_F(AppListPresenterDelegateHomeLauncherTest, MouseDragAppListItemOpacity) {
std::unique_ptr<app_list::AppListItem> item(
new app_list::AppListItem("fake id"));
Shell::Get()->app_list_controller()->GetModel()->AddItem(std::move(item));
const int items_in_page =
app_list::AppListConfig::instance().preferred_cols() *
app_list::AppListConfig::instance().preferred_rows();
for (int i = 0; i < items_in_page; ++i) {
std::unique_ptr<app_list::AppListItem> item(
new app_list::AppListItem(base::StringPrintf("fake id %d", i)));
Shell::Get()->app_list_controller()->GetModel()->AddItem(std::move(item));
}
GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
......@@ -1474,23 +1480,41 @@ TEST_F(AppListPresenterDelegateHomeLauncherTest, MouseDragAppListItemOpacity) {
->contents_view()
->GetAppsContainerView()
->apps_grid_view();
views::View* item_view = apps_grid_view->view_model()->view_at(0);
EXPECT_FALSE(item_view->layer());
// No items have layer.
for (int i = 0; i < items_in_page; ++i) {
views::View* item_view = apps_grid_view->view_model()->view_at(i);
EXPECT_FALSE(item_view->layer()) << "at " << i;
}
// Drags the mouse a bit above (twice as shelf's height). This should show the
// item vaguely.
const int shelf_height =
GetPrimaryShelf()->GetShelfViewForTesting()->height();
generator->MoveMouseBy(0, -shelf_height * 2);
EXPECT_TRUE(item_view->layer());
EXPECT_LE(0.f, item_view->layer()->opacity());
EXPECT_GT(1.f, item_view->layer()->opacity());
// All of the item should have the layer at this point.
for (int i = 0; i < items_in_page; ++i) {
views::View* item_view = apps_grid_view->view_model()->view_at(i);
EXPECT_TRUE(item_view->layer()) << "at " << i;
EXPECT_LE(0.f, item_view->layer()->opacity()) << "at " << i;
EXPECT_GE(1.f, item_view->layer()->opacity()) << "at " << i;
}
// Finishes the drag to expand the app-list. Now the app-list item should be
// fully visible and does not need layer anymore.
// Moves the mouse to the top edge of the screen; now all app-list items are
// fully visible, but stays to keep layer. The opacity should be almost 1.0.
generator->MoveMouseTo(start_point.x(), 0);
for (int i = 0; i < items_in_page; ++i) {
views::View* item_view = apps_grid_view->view_model()->view_at(i);
EXPECT_TRUE(item_view->layer()) << "at " << i;
EXPECT_LE(0.f, item_view->layer()->opacity()) << "at " << i;
EXPECT_GE(1.f, item_view->layer()->opacity()) << "at " << i;
}
// Finishes the drag. It should destruct the layer.
generator->ReleaseLeftButton();
EXPECT_FALSE(item_view->layer());
for (int i = 0; i < items_in_page; ++i) {
views::View* item_view = apps_grid_view->view_model()->view_at(i);
EXPECT_FALSE(item_view->layer()) << "at " << i;
}
}
// Tests that the app list is shown automatically when the tablet mode is on.
......
......@@ -1974,6 +1974,24 @@ void AppsGridView::UpdateOpacity() {
(app_list_view->app_list_state() != ash::AppListViewState::kClosed);
const int selected_page = pagination_model_.selected_page();
auto current_page = view_structure_.pages()[selected_page];
// First it should prepare the layers for all of the app items in the current
// page when necessary, or destroy all of the layers when they become
// unnecessary. Do not dynamically ensure/destroy layers of individual items
// since the creation/destruction of the layer requires to repaint the parent
// view (i.e. this class).
if (should_restore_opacity) {
// Layers are not necessary. Destroy them, and return. No need to update
// opacity.
for (size_t i = 0; i < current_page.size(); ++i)
current_page[i]->DestroyLayer();
return;
}
// Ensure layers and update their opacity.
for (size_t i = 0; i < current_page.size(); ++i)
current_page[i]->EnsureLayer();
float centerline_above_work_area = 0.f;
float opacity = 0.f;
for (size_t i = 0; i < current_page.size(); i += cols_) {
......@@ -1984,31 +2002,18 @@ void AppsGridView::UpdateOpacity() {
app_list_view->GetScreenBottom() - view_bounds.CenterPoint().y(), 0.f);
const float start_px =
AppListConfig::instance().all_apps_opacity_start_px();
opacity = std::min(
std::max((centerline_above_work_area - start_px) /
(AppListConfig::instance().all_apps_opacity_end_px() -
start_px),
0.f),
1.0f);
opacity = should_restore_opacity ? 1.0f : opacity;
const bool has_change =
((opacity == 1.0f || opacity == 0.f) && item_view->layer()) ||
(!item_view->layer() || opacity != item_view->layer()->opacity());
if (!has_change)
opacity = base::ClampToRange(
(centerline_above_work_area - start_px) /
(AppListConfig::instance().all_apps_opacity_end_px() - start_px),
0.f, 1.0f);
if (opacity == item_view->layer()->opacity())
continue;
const size_t end_index = std::min(current_page.size() - 1, i + cols_ - 1);
for (size_t j = i; j <= end_index; ++j) {
if (current_page[j] != drag_view_) {
if (opacity == 1.0f) {
current_page[j]->DestroyLayer();
} else {
current_page[j]->EnsureLayer();
current_page[j]->layer()->SetOpacity(opacity);
}
}
if (current_page[j] != drag_view_)
current_page[j]->layer()->SetOpacity(opacity);
}
}
}
......
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