Commit 566592e6 authored by Avery Musbach's avatar Avery Musbach Committed by Commit Bot

splitview: Animate the snapping after dragging the split view divider.

I am implementing the "Divider snapping" animation specified here:
https://mccanny.users.x20web.corp.google.com/www/splitscreen-motion/index.html#project-resizing
Notice that the window bounds update continuously with the snap
animation. That is what makes it so much more complicated to implement
than the "Divider selection" part and the "Divider deselection" part.

Test: ash_unittests SplitViewOverviewSessionTest.SplitViewOverviewBothActiveTest
Test: ash_unittests SplitViewOverviewSessionTest.DragDividerToExitTest
Test: ash_unittests SplitViewOverviewSessionTest.SnappedWindowBoundsTest
Test: ash_unittests SplitViewOverviewSessionTest.OverviewHasMinimumBoundsWhenDividerDragged
Test: ash_unittests SplitViewControllerTest.SplitDividerWindowBounds
Test: ash_unittests SplitViewControllerTest.InternalDisplayConfigurationChange*
Test: ash_unittests SplitViewControllerTest.SwapWindows
Test: ash_unittests SplitViewControllerTest.DoubleTapDivider
Test: ash_unittests SplitViewControllerTest.DragAndDouble*Divider
Test: ash_unittests SplitViewControllerTest.SnapWindowDuringDividerSnapAnimation
Test: ash_unittests SplitViewControllerTest.StartDraggingDividerDuringSnapAnimation
Test: ash_unittests SplitViewControllerTest.DividerPositionOnResizingSnappedWindowWithMinimumSizeTest
Test: ash_unittests SplitViewControllerTest.EndSplitViewDuringDividerSnapAnimation
Bug: 884930
Change-Id: I2494998606a340d75a87bf96fb5f83d38c751bb3
Reviewed-on: https://chromium-review.googlesource.com/c/1480869Reviewed-by: default avatarXiaoqian Dai <xdai@chromium.org>
Commit-Queue: Avery Musbach <amusbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#636145}
parent 59fd5a64
...@@ -2629,6 +2629,18 @@ class SplitViewOverviewSessionTest : public OverviewSessionTest { ...@@ -2629,6 +2629,18 @@ class SplitViewOverviewSessionTest : public OverviewSessionTest {
return Shell::Get()->split_view_controller(); return Shell::Get()->split_view_controller();
} }
bool IsDividerAnimating() {
return split_view_controller()->IsDividerAnimating();
}
void SkipDividerSnapAnimation() {
if (!IsDividerAnimating())
return;
split_view_controller()->StopAndShoveAnimatedDivider();
split_view_controller()->EndResizeImpl();
split_view_controller()->EndSplitViewAfterResizingIfAppropriate();
}
void EndSplitView() { split_view_controller()->EndSplitView(); } void EndSplitView() { split_view_controller()->EndSplitView(); }
protected: protected:
...@@ -3377,6 +3389,7 @@ TEST_F(SplitViewOverviewSessionTest, SplitViewOverviewBothActiveTest) { ...@@ -3377,6 +3389,7 @@ TEST_F(SplitViewOverviewSessionTest, SplitViewOverviewBothActiveTest) {
split_view_controller()->StartResize(resize_start_location); split_view_controller()->StartResize(resize_start_location);
const gfx::Point resize_end_location(300, 0); const gfx::Point resize_end_location(300, 0);
split_view_controller()->EndResize(resize_end_location); split_view_controller()->EndResize(resize_end_location);
SkipDividerSnapAnimation();
const gfx::Rect window1_bounds_after_resize = window1->GetBoundsInScreen(); const gfx::Rect window1_bounds_after_resize = window1->GetBoundsInScreen();
const gfx::Rect overview_grid_bounds_after_resize = GetGridBounds(); const gfx::Rect overview_grid_bounds_after_resize = GetGridBounds();
...@@ -3494,6 +3507,7 @@ TEST_F(SplitViewOverviewSessionTest, OverviewUnsnappableIndicatorVisibility) { ...@@ -3494,6 +3507,7 @@ TEST_F(SplitViewOverviewSessionTest, OverviewUnsnappableIndicatorVisibility) {
GetEventGenerator()->set_current_screen_location( GetEventGenerator()->set_current_screen_location(
divider_bounds.CenterPoint()); divider_bounds.CenterPoint());
GetEventGenerator()->DragMouseTo(0, 0); GetEventGenerator()->DragMouseTo(0, 0);
SkipDividerSnapAnimation();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
EXPECT_EQ(0.f, unsnappable_layer->opacity()); EXPECT_EQ(0.f, unsnappable_layer->opacity());
...@@ -3524,6 +3538,7 @@ TEST_F(SplitViewOverviewSessionTest, DragDividerToExitTest) { ...@@ -3524,6 +3538,7 @@ TEST_F(SplitViewOverviewSessionTest, DragDividerToExitTest) {
gfx::Rect divider_bounds = GetSplitViewDividerBounds(false /* is_dragging */); gfx::Rect divider_bounds = GetSplitViewDividerBounds(false /* is_dragging */);
split_view_controller()->StartResize(divider_bounds.CenterPoint()); split_view_controller()->StartResize(divider_bounds.CenterPoint());
split_view_controller()->EndResize(gfx::Point(0, 0)); split_view_controller()->EndResize(gfx::Point(0, 0));
SkipDividerSnapAnimation();
// Test that split view mode is ended. Overview mode is still active. // Test that split view mode is ended. Overview mode is still active.
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
...@@ -3542,6 +3557,7 @@ TEST_F(SplitViewOverviewSessionTest, DragDividerToExitTest) { ...@@ -3542,6 +3557,7 @@ TEST_F(SplitViewOverviewSessionTest, DragDividerToExitTest) {
const gfx::Rect display_bounds = GetWorkAreaInScreen(window2.get()); const gfx::Rect display_bounds = GetWorkAreaInScreen(window2.get());
split_view_controller()->StartResize(divider_bounds.CenterPoint()); split_view_controller()->StartResize(divider_bounds.CenterPoint());
split_view_controller()->EndResize(display_bounds.bottom_right()); split_view_controller()->EndResize(display_bounds.bottom_right());
SkipDividerSnapAnimation();
// Test that split view mode is ended. Overview mode is also ended. |window2| // Test that split view mode is ended. Overview mode is also ended. |window2|
// should be activated. // should be activated.
...@@ -3607,6 +3623,7 @@ TEST_F(SplitViewOverviewSessionTest, SnappedWindowBoundsTest) { ...@@ -3607,6 +3623,7 @@ TEST_F(SplitViewOverviewSessionTest, SnappedWindowBoundsTest) {
// Drag the divider to a point that is close enough but still have a short // Drag the divider to a point that is close enough but still have a short
// distance to the edge of the screen. // distance to the edge of the screen.
split_view_controller()->EndResize(gfx::Point(20, 20)); split_view_controller()->EndResize(gfx::Point(20, 20));
SkipDividerSnapAnimation();
// Test that split view mode is ended. Overview mode is still active. // Test that split view mode is ended. Overview mode is still active.
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
...@@ -3634,6 +3651,7 @@ TEST_F(SplitViewOverviewSessionTest, SnappedWindowBoundsTest) { ...@@ -3634,6 +3651,7 @@ TEST_F(SplitViewOverviewSessionTest, SnappedWindowBoundsTest) {
// distance to the edge of the screen. // distance to the edge of the screen.
end_location2.Offset(-20, -20); end_location2.Offset(-20, -20);
split_view_controller()->EndResize(end_location2); split_view_controller()->EndResize(end_location2);
SkipDividerSnapAnimation();
// Test that split view mode is ended. Overview mode is still active. // Test that split view mode is ended. Overview mode is still active.
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive()); EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
...@@ -3678,6 +3696,7 @@ TEST_F(SplitViewOverviewSessionTest, ...@@ -3678,6 +3696,7 @@ TEST_F(SplitViewOverviewSessionTest,
GetEventGenerator()->set_current_screen_location( GetEventGenerator()->set_current_screen_location(
divider_bounds.CenterPoint()); divider_bounds.CenterPoint());
GetEventGenerator()->DragMouseTo(0, 0); GetEventGenerator()->DragMouseTo(0, 0);
SkipDividerSnapAnimation();
// Verify that it is still in overview mode and that |window1| is returned to // Verify that it is still in overview mode and that |window1| is returned to
// the overview list. // the overview list.
...@@ -3720,6 +3739,7 @@ TEST_F(SplitViewOverviewSessionTest, ...@@ -3720,6 +3739,7 @@ TEST_F(SplitViewOverviewSessionTest,
EXPECT_EQ(200, grid->bounds().width()); EXPECT_EQ(200, grid->bounds().width());
EXPECT_GT(grid->bounds().right(), 600); EXPECT_GT(grid->bounds().right(), 600);
generator->ReleaseLeftButton(); generator->ReleaseLeftButton();
SkipDividerSnapAnimation();
// Releasing close to the edge will activate the left window and exit // Releasing close to the edge will activate the left window and exit
// overview. // overview.
...@@ -3743,6 +3763,7 @@ TEST_F(SplitViewOverviewSessionTest, ...@@ -3743,6 +3763,7 @@ TEST_F(SplitViewOverviewSessionTest,
EXPECT_EQ(200, grid->bounds().width()); EXPECT_EQ(200, grid->bounds().width());
EXPECT_LT(grid->bounds().x(), 0); EXPECT_LT(grid->bounds().x(), 0);
generator->ReleaseLeftButton(); generator->ReleaseLeftButton();
SkipDividerSnapAnimation();
} }
// Test that when splitview mode is active, minimizing one of the snapped window // Test that when splitview mode is active, minimizing one of the snapped window
......
This diff is collapsed.
...@@ -206,6 +206,7 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -206,6 +206,7 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
friend class SplitViewControllerTest; friend class SplitViewControllerTest;
friend class SplitViewOverviewSessionTest; friend class SplitViewOverviewSessionTest;
class TabDraggedWindowObserver; class TabDraggedWindowObserver;
class DividerSnapAnimation;
// Start observing |window|. // Start observing |window|.
void StartObserving(aura::Window* window); void StartObserving(aura::Window* window);
...@@ -251,14 +252,23 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -251,14 +252,23 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
gfx::Rect* left_or_top_rect, gfx::Rect* left_or_top_rect,
gfx::Rect* right_or_bottom_rect); gfx::Rect* right_or_bottom_rect);
// Finds the closest fix location for |divider_position_| and updates its // Returns the closest fix location for |divider_position_|.
// value. int GetClosestFixedDividerPosition();
void MoveDividerToClosestFixedPosition();
// Returns true during the divider snap animation.
bool IsDividerAnimating();
// While the divider is animating to somewhere, stop it and shove it there.
void StopAndShoveAnimatedDivider();
// Returns true if we should end split view mode after resizing, i.e., the // Returns true if we should end split view mode after resizing, i.e., the
// split view divider is near to the edge of the screen. // split view divider is near to the edge of the screen.
bool ShouldEndSplitViewAfterResizing(); bool ShouldEndSplitViewAfterResizing();
// Ends split view if ShouldEndSplitViewAfterResizing() returns true. Handles
// extra details associated with dragging the divider off the screen.
void EndSplitViewAfterResizingIfAppropriate();
// After resizing, if we should end split view mode, returns the window that // After resizing, if we should end split view mode, returns the window that
// needs to be activated. Returns nullptr if there is no such window. // needs to be activated. Returns nullptr if there is no such window.
aura::Window* GetActiveWindowAfterResizingUponExit(); aura::Window* GetActiveWindowAfterResizingUponExit();
...@@ -352,6 +362,10 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -352,6 +362,10 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// snapped windows. // snapped windows.
void FinishWindowResizing(aura::Window* window); void FinishWindowResizing(aura::Window* window);
// Finalizes and cleans up divider dragging/animating. Called when the divider
// snapping animation completes or is interrupted or totally skipped.
void EndResizeImpl();
// Called by OnWindowDragEnded to do the actual work of finishing the window // Called by OnWindowDragEnded to do the actual work of finishing the window
// dragging. If |is_being_destroyed| equals true, the dragged window is to be // dragging. If |is_being_destroyed| equals true, the dragged window is to be
// destroyed, and SplitViewController should not try to put it in splitview. // destroyed, and SplitViewController should not try to put it in splitview.
...@@ -407,6 +421,9 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -407,6 +421,9 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// The location of the previous mouse/gesture event in screen coordinates. // The location of the previous mouse/gesture event in screen coordinates.
gfx::Point previous_event_location_; gfx::Point previous_event_location_;
// The animation that animates the divider to a fixed position after resizing.
std::unique_ptr<DividerSnapAnimation> divider_snap_animation_;
// Current snap state. // Current snap state.
State state_ = NO_SNAP; State state_ = NO_SNAP;
...@@ -419,7 +436,7 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController, ...@@ -419,7 +436,7 @@ class ASH_EXPORT SplitViewController : public mojom::SplitViewController,
// The previous orientation of the screen. // The previous orientation of the screen.
OrientationLockType previous_screen_orientation_ = OrientationLockType::kAny; OrientationLockType previous_screen_orientation_ = OrientationLockType::kAny;
// If the divider is currently being dragging. // True when the divider is being dragged (not during its snap animation).
bool is_resizing_ = false; bool is_resizing_ = false;
// Stores the reason which cause splitview to end. // Stores the reason which cause splitview to end.
......
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