Commit fe5e63af authored by Avery Musbach's avatar Avery Musbach Committed by Commit Bot

overview: Support dragging an overview window from one grid to another

Test: ash_unittests All/SplitViewOverviewSessionInClamshellTestMultiDisplayOnly.DragAndDropIntoAnotherOverviewGrid/0
Test: ash_unittests All/SplitViewOverviewSessionInClamshellTestMultiDisplayOnly.OverviewWidgetStackingOrderWithMultiDisplayDragging/0
Bug: 961170
Change-Id: I56862dfd8094b72ce0abf07a855d058be3d3c3da
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2008237
Commit-Queue: Avery Musbach <amusbach@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Reviewed-by: default avatarSammie Quon <sammiequon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734610}
parent 2f2c200f
...@@ -549,8 +549,10 @@ void OverviewGrid::AppendItem(aura::Window* window, ...@@ -549,8 +549,10 @@ void OverviewGrid::AppendItem(aura::Window* window,
window_list_.size(), use_spawn_animation); window_list_.size(), use_spawn_animation);
} }
void OverviewGrid::AddItemInMruOrder(aura::Window* window, bool animate) { void OverviewGrid::AddItemInMruOrder(aura::Window* window,
AddItem(window, /*reposition=*/true, animate, /*ignored_items=*/{}, bool reposition,
bool animate) {
AddItem(window, reposition, animate, /*ignored_items=*/{},
FindInsertionIndex(window)); FindInsertionIndex(window));
} }
......
...@@ -106,10 +106,9 @@ class ASH_EXPORT OverviewGrid : public SplitViewObserver, ...@@ -106,10 +106,9 @@ class ASH_EXPORT OverviewGrid : public SplitViewObserver,
bool animate, bool animate,
bool use_spawn_animation = false); bool use_spawn_animation = false);
// Adds |window| at the correct position according to MRU order. |window| // Like |AddItem|, but adds |window| at the correct position according to MRU
// cannot already be on the grid. Repositions all items. If |animate| is true, // order.
// animates the repositioning. void AddItemInMruOrder(aura::Window* window, bool reposition, bool animate);
void AddItemInMruOrder(aura::Window* window, bool animate);
// Removes |overview_item| from the grid. |overview_item| cannot already be // Removes |overview_item| from the grid. |overview_item| cannot already be
// absent from the grid. If |item_destroying| is true, we may want to notify // absent from the grid. If |item_destroying| is true, we may want to notify
......
...@@ -427,7 +427,7 @@ void OverviewSession::AddItemInMruOrder(aura::Window* window, bool animate) { ...@@ -427,7 +427,7 @@ void OverviewSession::AddItemInMruOrder(aura::Window* window, bool animate) {
if (!grid || grid->GetOverviewItemContaining(window)) if (!grid || grid->GetOverviewItemContaining(window))
return; return;
grid->AddItemInMruOrder(window, animate); grid->AddItemInMruOrder(window, /*reposition=*/true, animate);
OnItemAdded(window); OnItemAdded(window);
} }
......
...@@ -6388,6 +6388,101 @@ TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly, ...@@ -6388,6 +6388,101 @@ TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
EXPECT_EQ(root1_drop_target_bounds(item3), root1_drop_target_bounds(item4)); EXPECT_EQ(root1_drop_target_bounds(item3), root1_drop_target_bounds(item4));
} }
// Test dragging from one overview grid and dropping into another overview grid.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
DragAndDropIntoAnotherOverviewGrid) {
UpdateDisplay("800x600,800x600");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
ASSERT_EQ(2u, root_windows.size());
std::unique_ptr<aura::Window> window = CreateTestWindow();
ASSERT_EQ(root_windows[0], window->GetRootWindow());
ToggleOverview();
OverviewGrid* grid1 =
overview_session()->GetGridWithRootWindow(root_windows[0]);
OverviewGrid* grid2 =
overview_session()->GetGridWithRootWindow(root_windows[1]);
// Drag |window| from |grid1| and drop into |grid2|.
ui::test::EventGenerator* generator = GetEventGenerator();
generator->MoveMouseTo(
gfx::ToRoundedPoint(grid1->GetOverviewItemContaining(window.get())
->target_bounds()
.CenterPoint()));
generator->PressLeftButton();
Shell::Get()->cursor_manager()->SetDisplay(
display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
generator->MoveMouseTo(1200, 300);
generator->ReleaseLeftButton();
EXPECT_EQ(root_windows[1], window->GetRootWindow());
EXPECT_TRUE(grid1->empty());
OverviewItem* item = grid2->GetOverviewItemContaining(window.get());
ASSERT_TRUE(item);
EXPECT_EQ(root_windows[1], item->root_window());
}
// Test that overview widgets are stacked in the correct order after an overview
// window is dragged from one overview grid and dropped into another.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
OverviewWidgetStackingOrderWithMultiDisplayDragging) {
UpdateDisplay("800x600,800x600");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
ASSERT_EQ(2u, root_windows.size());
const gfx::Rect bounds_within_root1(0, 0, 400, 400);
const gfx::Rect bounds_within_root2(800, 0, 400, 400);
std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds_within_root2);
std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root1);
std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root2);
aura::Window* parent_on_root1 = window2->parent();
aura::Window* parent_on_root2 = window1->parent();
ASSERT_NE(parent_on_root1, parent_on_root2);
ASSERT_EQ(window3->parent(), parent_on_root2);
ToggleOverview();
OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
OverviewItem* item3 = GetOverviewItemForWindow(window3.get());
ASSERT_EQ(root_windows[0], item2->root_window());
// Verify that |item1| is stacked above |item3| (because we created |window1|
// after |window3|).
EXPECT_GT(IndexOf(item1->item_widget()->GetNativeWindow(), parent_on_root2),
IndexOf(item3->item_widget()->GetNativeWindow(), parent_on_root2));
// Verify that the item widget for each window is stacked below that window.
EXPECT_LT(IndexOf(item1->item_widget()->GetNativeWindow(), parent_on_root2),
IndexOf(window1.get(), parent_on_root2));
EXPECT_LT(IndexOf(item2->item_widget()->GetNativeWindow(), parent_on_root1),
IndexOf(window2.get(), parent_on_root1));
EXPECT_LT(IndexOf(item3->item_widget()->GetNativeWindow(), parent_on_root2),
IndexOf(window3.get(), parent_on_root2));
// Drag |item2| from the left display and drop into the right display.
ui::test::EventGenerator* generator = GetEventGenerator();
generator->MoveMouseTo(
gfx::ToRoundedPoint(item2->target_bounds().CenterPoint()));
generator->PressLeftButton();
Shell::Get()->cursor_manager()->SetDisplay(
display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
generator->MoveMouseTo(1200, 300);
generator->ReleaseLeftButton();
// |item2| is now a dangling pointer and we have to refresh it, because when
// an overview window is dragged from one grid and dropped into another, the
// original item is destroyed and a new one is created.
item2 = GetOverviewItemForWindow(window2.get());
ASSERT_EQ(window2->parent(), parent_on_root2);
ASSERT_EQ(root_windows[1], item2->root_window());
// With all three items on one grid, verify that their stacking order
// corresponds to the MRU order of the windows. The new |item2| is sandwiched
// between |item1| and |item3|.
EXPECT_GT(IndexOf(item1->item_widget()->GetNativeWindow(), parent_on_root2),
IndexOf(item2->item_widget()->GetNativeWindow(), parent_on_root2));
EXPECT_GT(IndexOf(item2->item_widget()->GetNativeWindow(), parent_on_root2),
IndexOf(item3->item_widget()->GetNativeWindow(), parent_on_root2));
// Verify that the item widget for the new |item2| is stacked below |window2|.
EXPECT_LT(IndexOf(item2->item_widget()->GetNativeWindow(), parent_on_root2),
IndexOf(window2.get(), parent_on_root2));
}
// Test dragging from one display to another and then snapping. // Test dragging from one display to another and then snapping.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly, TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
DragFromOneDisplayToAnotherAndSnap) { DragFromOneDisplayToAnotherAndSnap) {
......
...@@ -582,6 +582,36 @@ OverviewWindowDragController::CompleteNormalDrag( ...@@ -582,6 +582,36 @@ OverviewWindowDragController::CompleteNormalDrag(
// Drop a window into overview because we have not done anything else with it. // Drop a window into overview because we have not done anything else with it.
DCHECK(item_); DCHECK(item_);
aura::Window* target_root = GetRootWindowBeingDraggedIn();
if (AreMultiDisplayOverviewAndSplitViewEnabled() &&
target_root != item_->root_window()) {
// Get the window and bounds from |item_| before removing it from its grid.
aura::Window* window = item_->GetWindow();
const gfx::RectF bounds = item_->target_bounds();
item_->overview_grid()->RemoveItem(item_);
item_ = nullptr;
// Use |OverviewSession::set_ignore_window_hierarchy_changes| to prevent
// |OverviewSession::OnWindowHierarchyChanged| from ending overview as we
// move |window| to |target_root|.
overview_session_->set_ignore_window_hierarchy_changes(true);
window_util::MoveWindowToDisplay(window,
display::Screen::GetScreen()
->GetDisplayNearestWindow(target_root)
.id());
overview_session_->set_ignore_window_hierarchy_changes(false);
OverviewGrid* target_grid =
overview_session_->GetGridWithRootWindow(target_root);
// Add |window| to |target_grid| with reposition=false because soon we will
// call |OverviewSession::PositionWindows| anyway.
target_grid->AddItemInMruOrder(window, /*reposition=*/false,
/*animate=*/false);
item_ = target_grid->GetOverviewItemContaining(window);
// Put the new item where the old item ended, so it looks like it is the
// same item. The following call to |OverviewSession::PositionWindows| will
// animate it from there.
item_->SetBounds(bounds, OVERVIEW_ANIMATION_NONE);
}
item_->set_should_restack_on_animation_end(true); item_->set_should_restack_on_animation_end(true);
overview_session_->PositionWindows(/*animate=*/true); overview_session_->PositionWindows(/*animate=*/true);
return DragResult::kDropIntoOverview; return DragResult::kDropIntoOverview;
......
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