Commit 8323d619 authored by Avery Musbach's avatar Avery Musbach Committed by Commit Bot

split view: Enable to drag overview window to another display and snap

You shall be able to start dragging from overview, drag to another
display, and snap.

Test: ash_unittests All/SplitViewOverviewSessionInClamshellTestMultiDisplayOnly.DragFromOneDisplayToAnotherAndSnap/0
Bug: 961170
Change-Id: Ib237fa253603433d307f232d0fc8a04affebeb7d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1986956
Commit-Queue: Avery Musbach <amusbach@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#729792}
parent ac9f7c42
...@@ -848,6 +848,9 @@ void OverviewSession::OnDisplayMetricsChanged(const display::Display& display, ...@@ -848,6 +848,9 @@ void OverviewSession::OnDisplayMetricsChanged(const display::Display& display,
void OverviewSession::OnWindowHierarchyChanged( void OverviewSession::OnWindowHierarchyChanged(
const HierarchyChangeParams& params) { const HierarchyChangeParams& params) {
if (ignore_window_hierarchy_changes_)
return;
// Only care about newly added children of |observed_windows_|. // Only care about newly added children of |observed_windows_|.
if (!observed_windows_.count(params.receiver) || if (!observed_windows_.count(params.receiver) ||
!observed_windows_.count(params.new_parent)) { !observed_windows_.count(params.new_parent)) {
......
...@@ -318,6 +318,11 @@ class ASH_EXPORT OverviewSession : public display::DisplayObserver, ...@@ -318,6 +318,11 @@ class ASH_EXPORT OverviewSession : public display::DisplayObserver,
OverviewDelegate* delegate() { return delegate_; } OverviewDelegate* delegate() { return delegate_; }
void set_ignore_window_hierarchy_changes(
bool ignore_window_hierarchy_changes) {
ignore_window_hierarchy_changes_ = ignore_window_hierarchy_changes;
}
bool is_shutting_down() const { return is_shutting_down_; } bool is_shutting_down() const { return is_shutting_down_; }
void set_is_shutting_down(bool is_shutting_down) { void set_is_shutting_down(bool is_shutting_down) {
is_shutting_down_ = is_shutting_down; is_shutting_down_ = is_shutting_down;
...@@ -400,6 +405,10 @@ class ASH_EXPORT OverviewSession : public display::DisplayObserver, ...@@ -400,6 +405,10 @@ class ASH_EXPORT OverviewSession : public display::DisplayObserver,
// initially true until this is initialized. // initially true until this is initialized.
bool ignore_activations_ = true; bool ignore_activations_ = true;
// True when performing operations that may cause window hierarchy changes.
// Used to prevent handling the resulting expected window hierarchy change.
bool ignore_window_hierarchy_changes_ = false;
// True when overview mode is exiting. // True when overview mode is exiting.
bool is_shutting_down_ = false; bool is_shutting_down_ = false;
......
...@@ -6382,6 +6382,37 @@ TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly, ...@@ -6382,6 +6382,37 @@ 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 display to another and then snapping.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
DragFromOneDisplayToAnotherAndSnap) {
UpdateDisplay("800x600,800x600");
aura::Window::Windows root_windows = Shell::GetAllRootWindows();
ASSERT_EQ(2u, root_windows.size());
SplitViewController* split_view_controller1 =
SplitViewController::Get(root_windows[0]);
SplitViewController* split_view_controller2 =
SplitViewController::Get(root_windows[1]);
const gfx::Rect bounds_within_root1(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root1);
std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root1);
ToggleOverview();
ui::test::EventGenerator* generator = GetEventGenerator();
generator->MoveMouseTo(gfx::ToRoundedPoint(
GetOverviewItemForWindow(window2.get())->target_bounds().CenterPoint()));
generator->PressLeftButton();
Shell::Get()->cursor_manager()->SetDisplay(
display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
generator->MoveMouseTo(800, 300);
generator->ReleaseLeftButton();
EXPECT_EQ(SplitViewController::State::kNoSnap,
split_view_controller1->state());
EXPECT_EQ(SplitViewController::State::kLeftSnapped,
split_view_controller2->state());
EXPECT_EQ(window2.get(), split_view_controller2->left_window());
EXPECT_EQ(root_windows[1], window2->GetRootWindow());
EXPECT_TRUE(InOverviewSession());
}
// Verify that |SplitViewController::CanSnapWindow| checks that the minimum size // Verify that |SplitViewController::CanSnapWindow| checks that the minimum size
// of the window fits into the left or top, with the default divider position. // of the window fits into the left or top, with the default divider position.
// (If the work area length is odd, then the right or bottom will be one pixel // (If the work area length is odd, then the right or bottom will be one pixel
......
...@@ -711,8 +711,6 @@ void OverviewWindowDragController::SnapWindow( ...@@ -711,8 +711,6 @@ void OverviewWindowDragController::SnapWindow(
DCHECK(!SplitViewController::Get(Shell::GetPrimaryRootWindow()) DCHECK(!SplitViewController::Get(Shell::GetPrimaryRootWindow())
->IsDividerAnimating()); ->IsDividerAnimating());
aura::Window* window = item_->GetWindow(); aura::Window* window = item_->GetWindow();
// TODO(crbug.com/970013): Properly implement the multi-display behavior which
// involves reparenting |window| to put it on the destination display.
SplitViewController::Get(GetRootWindowBeingDraggedIn()) SplitViewController::Get(GetRootWindowBeingDraggedIn())
->SnapWindow(window, snap_position, ->SnapWindow(window, snap_position,
/*use_divider_spawn_animation=*/true); /*use_divider_spawn_animation=*/true);
......
...@@ -139,6 +139,22 @@ OverviewSession* GetOverviewSession() { ...@@ -139,6 +139,22 @@ OverviewSession* GetOverviewSession() {
: nullptr; : nullptr;
} }
void RemoveSnappingWindowFromOverviewIfApplicable(
OverviewSession* overview_session,
aura::Window* window) {
if (!overview_session)
return;
OverviewItem* item = overview_session->GetOverviewItemForWindow(window);
if (!item)
return;
// Remove it from overview. The transform will be reset later after the window
// is snapped. Note the remaining windows in overview don't need to be
// repositioned in this case as they have been positioned to the right place
// during dragging.
item->RestoreWindow(/*reset_transform=*/false);
overview_session->RemoveItem(item);
}
} // namespace } // namespace
// The window observer that observes the current tab-dragged window. When it's // The window observer that observes the current tab-dragged window. When it's
...@@ -359,10 +375,28 @@ void SplitViewController::SnapWindow(aura::Window* window, ...@@ -359,10 +375,28 @@ void SplitViewController::SnapWindow(aura::Window* window,
DCHECK_NE(snap_position, NONE); DCHECK_NE(snap_position, NONE);
DCHECK(!is_resizing_); DCHECK(!is_resizing_);
DCHECK(!IsDividerAnimating()); DCHECK(!IsDividerAnimating());
DCHECK_EQ(root_window_, window->GetRootWindow());
// Save the transformed bounds in preparation for the snapping animation.
UpdateSnappingWindowTransformedBounds(window); UpdateSnappingWindowTransformedBounds(window);
RemoveWindowFromOverviewIfApplicable(window);
OverviewSession* overview_session = GetOverviewSession();
// We can straightforwardly remove |window| from overview and then move it to
// |root_window_|, whereas if we move |window| to |root_window_| first, we
// will run into problems because |window| will be on the wrong overview grid.
RemoveSnappingWindowFromOverviewIfApplicable(overview_session, window);
if (root_window_ != window->GetRootWindow()) {
// Use |OverviewSession::set_ignore_window_hierarchy_changes| to prevent
// |OverviewSession::OnWindowHierarchyChanged| from ending overview as we
// move |window| to |root_window_|.
if (overview_session)
overview_session->set_ignore_window_hierarchy_changes(true);
window_util::MoveWindowToDisplay(window,
display::Screen::GetScreen()
->GetDisplayNearestWindow(root_window_)
.id());
if (overview_session)
overview_session->set_ignore_window_hierarchy_changes(false);
}
bool do_divider_spawn_animation = false; bool do_divider_spawn_animation = false;
if (state_ == State::kNoSnap) { if (state_ == State::kNoSnap) {
...@@ -423,7 +457,8 @@ void SplitViewController::SnapWindow(aura::Window* window, ...@@ -423,7 +457,8 @@ void SplitViewController::SnapWindow(aura::Window* window,
StartObserving(window); StartObserving(window);
// Insert the previous snapped window to overview if overview is active. // Insert the previous snapped window to overview if overview is active.
if (previous_snapped_window && GetOverviewSession()) { DCHECK_EQ(overview_session, GetOverviewSession());
if (previous_snapped_window && overview_session) {
InsertWindowToOverview(previous_snapped_window); InsertWindowToOverview(previous_snapped_window);
// Ensure that the close icon will fade in. This part is redundant for // Ensure that the close icon will fade in. This part is redundant for
// dragging from overview, but necessary for dragging from the top. For // dragging from overview, but necessary for dragging from the top. For
...@@ -432,8 +467,7 @@ void SplitViewController::SnapWindow(aura::Window* window, ...@@ -432,8 +467,7 @@ void SplitViewController::SnapWindow(aura::Window* window,
// item anyway, whereas for dragging from the top, // item anyway, whereas for dragging from the top,
// |OverviewItem::OnSelectorItemDragEnded| already was called on all // |OverviewItem::OnSelectorItemDragEnded| already was called on all
// overview items and |previous_snapped_window| was not yet among them. // overview items and |previous_snapped_window| was not yet among them.
GetOverviewSession() overview_session->GetOverviewItemForWindow(previous_snapped_window)
->GetOverviewItemForWindow(previous_snapped_window)
->OnSelectorItemDragEnded(/*snap=*/true); ->OnSelectorItemDragEnded(/*snap=*/true);
} }
...@@ -1712,31 +1746,6 @@ void SplitViewController::SetTransformWithAnimation( ...@@ -1712,31 +1746,6 @@ void SplitViewController::SetTransformWithAnimation(
} }
} }
void SplitViewController::RemoveWindowFromOverviewIfApplicable(
aura::Window* window) {
DCHECK_EQ(root_window_, window->GetRootWindow());
if (!Shell::Get()->overview_controller()->InOverviewSession())
return;
OverviewSession* overview_session = GetOverviewSession();
OverviewGrid* current_grid =
overview_session->GetGridWithRootWindow(root_window_);
if (!current_grid)
return;
OverviewItem* item = current_grid->GetOverviewItemContaining(window);
if (!item)
return;
// Remove it from the grid. The transform will be reset later after the
// window is snapped. Note the remaining windows in overview don't need to be
// repositioned in this case as they have been positioned to the right place
// during dragging.
item->RestoreWindow(/*reset_transform=*/false);
overview_session->RemoveItem(item);
}
void SplitViewController::UpdateSnappingWindowTransformedBounds( void SplitViewController::UpdateSnappingWindowTransformedBounds(
aura::Window* window) { aura::Window* window) {
if (!window->layer()->GetTargetTransform().IsIdentity()) { if (!window->layer()->GetTargetTransform().IsIdentity()) {
......
...@@ -385,11 +385,6 @@ class ASH_EXPORT SplitViewController : public aura::WindowObserver, ...@@ -385,11 +385,6 @@ class ASH_EXPORT SplitViewController : public aura::WindowObserver,
const gfx::Transform& start_transform, const gfx::Transform& start_transform,
const gfx::Transform& target_transform); const gfx::Transform& target_transform);
// Removes the window item that contains |window| from the overview window
// grid if |window| is currently showing in overview window grid. It should be
// called before trying to snap the window.
void RemoveWindowFromOverviewIfApplicable(aura::Window* window);
// Updates the |snapping_window_transformed_bounds_map_| on |window|. It // Updates the |snapping_window_transformed_bounds_map_| on |window|. It
// should be called before trying to snap the window. // should be called before trying to snap the window.
void UpdateSnappingWindowTransformedBounds(aura::Window* window); void UpdateSnappingWindowTransformedBounds(aura::Window* window);
......
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