Commit 1751c4de authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

splitview: Add minimum bounds for overview grid when dragging divider.

When we reach one third of work area, stop shrinking the overview bounds
and instead start sliding it out off screen.

Test: added test
Bug: 872141
Change-Id: I4d42e5943485c9a4d96205d1a1870823305b49e9
Reviewed-on: https://chromium-review.googlesource.com/1169974
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#581995}
parent acf579da
......@@ -112,25 +112,71 @@ void UpdateShelfVisibility() {
// Returns the bounds for the overview window grid according to the split view
// state. If split view mode is active, the overview window should open on the
// opposite side of the default snap window.
gfx::Rect GetGridBoundsInScreen(aura::Window* root_window) {
// opposite side of the default snap window. If |divider_changed| is true, maybe
// clamp the bounds to a minimum size and shift the bounds offscreen.
gfx::Rect GetGridBoundsInScreen(aura::Window* root_window,
bool divider_changed) {
SplitViewController* split_view_controller =
Shell::Get()->split_view_controller();
if (split_view_controller->IsSplitViewModeActive()) {
SplitViewController::SnapPosition oppsite_position =
(split_view_controller->default_snap_position() ==
SplitViewController::LEFT)
? SplitViewController::RIGHT
: SplitViewController::LEFT;
return split_view_controller->GetSnappedWindowBoundsInScreen(
root_window, oppsite_position);
} else {
return split_view_controller->GetDisplayWorkAreaBoundsInScreen(root_window);
}
const gfx::Rect work_area =
split_view_controller->GetDisplayWorkAreaBoundsInScreen(root_window);
if (!split_view_controller->IsSplitViewModeActive())
return work_area;
SplitViewController::SnapPosition opposite_position =
(split_view_controller->default_snap_position() ==
SplitViewController::LEFT)
? SplitViewController::RIGHT
: SplitViewController::LEFT;
gfx::Rect bounds = split_view_controller->GetSnappedWindowBoundsInScreen(
root_window, opposite_position);
if (!divider_changed)
return bounds;
const bool landscape =
split_view_controller->IsCurrentScreenOrientationLandscape();
const int min_length =
(landscape ? work_area.width() : work_area.height()) / 3;
if ((landscape ? bounds.width() : bounds.height()) > min_length)
return bounds;
// Helper function which shifts and clamps |out_bounds|. Handles the
// orientation and whether |opposite_position| is physically on the left
// or top of the screen.
auto shift_bounds = [&min_length, &landscape](bool left_or_top,
gfx::Rect* out_bounds) {
// If we are shifting to the left or top we need to update the origin as
// well.
if (left_or_top) {
if (landscape) {
out_bounds->set_x(out_bounds->x() - (min_length - out_bounds->width()));
} else {
out_bounds->set_y(out_bounds->y() -
(min_length - out_bounds->height()));
}
}
if (landscape)
out_bounds->set_width(min_length);
else
out_bounds->set_height(min_length);
};
// Shift the opposite direction when |primary| is false because the physical
// location will not be aligned with |opposite_position|.
const bool primary =
split_view_controller->IsCurrentScreenOrientationPrimary();
if (opposite_position == SplitViewController::LEFT)
shift_bounds(primary, &bounds);
else
shift_bounds(!primary, &bounds);
return bounds;
}
gfx::Rect GetTextFilterPosition(aura::Window* root_window) {
const gfx::Rect total_bounds = GetGridBoundsInScreen(root_window);
const gfx::Rect total_bounds =
GetGridBoundsInScreen(root_window, /*divider_changed=*/false);
return gfx::Rect(
total_bounds.x() +
0.5 * (total_bounds.width() -
......@@ -279,7 +325,8 @@ void WindowSelector::Init(const WindowList& windows,
}
std::unique_ptr<WindowGrid> grid(
new WindowGrid(root, windows, this, GetGridBoundsInScreen(root)));
new WindowGrid(root, windows, this,
GetGridBoundsInScreen(root, /*divider_changed=*/false)));
num_items_ += grid->size();
grid_list_.push_back(std::move(grid));
}
......@@ -893,7 +940,14 @@ void WindowSelector::OnSplitViewStateChanged(
void WindowSelector::OnSplitViewDividerPositionChanged() {
DCHECK(Shell::Get()->IsSplitViewModeActive());
OnDisplayBoundsChanged();
// Re-calculate the bounds for the window grids and position all the windows.
for (std::unique_ptr<WindowGrid>& grid : grid_list_) {
grid->SetBoundsAndUpdatePositions(
GetGridBoundsInScreen(const_cast<aura::Window*>(grid->root_window()),
/*divider_changed=*/true));
}
PositionWindows(/*animate=*/false);
RepositionTextFilterOnDisplayMetricsChange();
}
aura::Window* WindowSelector::GetTextFilterWidgetWindow() {
......@@ -967,7 +1021,8 @@ void WindowSelector::OnDisplayBoundsChanged() {
// Re-calculate the bounds for the window grids and position all the windows.
for (std::unique_ptr<WindowGrid>& grid : grid_list_) {
grid->SetBoundsAndUpdatePositions(
GetGridBoundsInScreen(const_cast<aura::Window*>(grid->root_window())));
GetGridBoundsInScreen(const_cast<aura::Window*>(grid->root_window()),
/*divider_changed=*/false));
}
PositionWindows(/*animate=*/false);
RepositionTextFilterOnDisplayMetricsChange();
......
......@@ -4493,6 +4493,62 @@ TEST_F(SplitViewWindowSelectorTest,
EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
}
// Verify that if the split view divider is dragged close to the edge, the grid
// bounds will be fixed to a third of the work area width and start sliding off
// the screen instead of continuing to shrink.
TEST_F(SplitViewWindowSelectorTest,
OverviewHasMinimumBoundsWhenDividerDragged) {
UpdateDisplay("600x400");
const gfx::Rect bounds(400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
ToggleOverview();
// Snap a window to the left and test dragging the divider towards the right
// edge of the screen.
Shell::Get()->split_view_controller()->SnapWindow(window1.get(),
SplitViewController::LEFT);
WindowGrid* grid = window_selector()->grid_list_for_testing()[0].get();
ASSERT_TRUE(grid);
// Drag the divider to the right edge.
gfx::Rect divider_bounds = GetSplitViewDividerBounds(/*is_dragging=*/false);
ui::test::EventGenerator* generator = GetEventGenerator();
generator->set_current_location(divider_bounds.CenterPoint());
generator->PressLeftButton();
// Tests that near the right edge, the grid bounds are fixed at 200 and are
// partially off screen to the right.
generator->MoveMouseTo(580, 0);
EXPECT_EQ(200, grid->bounds().width());
EXPECT_GT(grid->bounds().right(), 600);
generator->ReleaseLeftButton();
// Releasing close to the edge will activate the left window and exit
// overview.
ASSERT_FALSE(IsSelecting());
ToggleOverview();
// Snap a window to the right and test dragging the divider towards the left
// edge of the screen.
Shell::Get()->split_view_controller()->SnapWindow(window1.get(),
SplitViewController::RIGHT);
grid = window_selector()->grid_list_for_testing()[0].get();
ASSERT_TRUE(grid);
// Drag the divider to the left edge.
divider_bounds = GetSplitViewDividerBounds(/*is_dragging=*/false);
generator->set_current_location(divider_bounds.CenterPoint());
generator->PressLeftButton();
generator->MoveMouseTo(20, 0);
// Tests that near the left edge, the grid bounds are fixed at 200 and are
// partially off screen to the left.
EXPECT_EQ(200, grid->bounds().width());
EXPECT_LT(grid->bounds().x(), 0);
generator->ReleaseLeftButton();
}
// Test that when splitview mode is active, minimizing one of the snapped window
// will insert the minimized window back to overview mode if overview mode is
// active at the moment.
......
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