blob: db104c6c8bb22b0d14dffe9733261aebbd19ca44 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/display/screen_orientation_controller_chromeos.h"
#include "ash/display/screen_orientation_controller_test_api.h"
#include "ash/screen_util.h"
#include "ash/shell.h"
#include "ash/system/overview/overview_button_tray.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/status_area_widget_test_helper.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/splitview/split_view_divider.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ash/wm/wm_event.h"
#include "services/ui/public/interfaces/window_manager_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/test_windows.h"
#include "ui/display/test/display_manager_test_api.h"
#include "ui/events/test/event_generator.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/window_util.h"
namespace ash {
class SplitViewControllerTest : public AshTestBase {
public:
SplitViewControllerTest() = default;
~SplitViewControllerTest() override = default;
// test::AshTestBase:
void SetUp() override {
AshTestBase::SetUp();
Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
}
aura::Window* CreateWindow(const gfx::Rect& bounds) {
aura::Window* window = CreateTestWindowInShellWithDelegate(
new SplitViewTestWindowDelegate, -1, bounds);
return window;
}
aura::Window* CreateNonSnappableWindow(const gfx::Rect& bounds) {
aura::Window* window = CreateWindow(bounds);
window->SetProperty(aura::client::kResizeBehaviorKey,
ui::mojom::kResizeBehaviorNone);
return window;
}
void EndSplitView() { split_view_controller()->EndSplitView(); }
void ToggleOverview() {
Shell::Get()->window_selector_controller()->ToggleOverview();
}
void LongPressOnOverivewButtonTray() {
ui::GestureEvent event(0, 0, 0, base::TimeTicks(),
ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
StatusAreaWidgetTestHelper::GetStatusAreaWidget()
->overview_button_tray()
->OnGestureEvent(&event);
}
std::vector<aura::Window*> GetWindowsInOverviewGrids() {
return Shell::Get()
->window_selector_controller()
->GetWindowsListInOverviewGridsForTesting();
}
SplitViewController* split_view_controller() {
return Shell::Get()->split_view_controller();
}
SplitViewDivider* split_view_divider() {
return split_view_controller()->split_view_divider();
}
blink::WebScreenOrientationLockType screen_orientation() {
return split_view_controller()->screen_orientation();
}
int divider_position() { return split_view_controller()->divider_position(); }
private:
class SplitViewTestWindowDelegate : public aura::test::TestWindowDelegate {
public:
SplitViewTestWindowDelegate() = default;
~SplitViewTestWindowDelegate() override = default;
// aura::test::TestWindowDelegate:
void OnWindowDestroying(aura::Window* window) override { window->Hide(); }
void OnWindowDestroyed(aura::Window* window) override { delete this; }
};
DISALLOW_COPY_AND_ASSIGN(SplitViewControllerTest);
};
// Tests the basic functionalities.
TEST_F(SplitViewControllerTest, Basic) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
EXPECT_EQ(split_view_controller()->state(), SplitViewController::NO_SNAP);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::LEFT_SNAPPED);
EXPECT_EQ(split_view_controller()->left_window(), window1.get());
EXPECT_NE(split_view_controller()->left_window(), window2.get());
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
EXPECT_EQ(window1->GetBoundsInScreen(),
split_view_controller()->GetSnappedWindowBoundsInScreen(
window1.get(), SplitViewController::LEFT));
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::BOTH_SNAPPED);
EXPECT_EQ(split_view_controller()->right_window(), window2.get());
EXPECT_NE(split_view_controller()->right_window(), window1.get());
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
EXPECT_EQ(window2->GetBoundsInScreen(),
split_view_controller()->GetSnappedWindowBoundsInScreen(
window2.get(), SplitViewController::RIGHT));
EndSplitView();
EXPECT_EQ(split_view_controller()->state(), SplitViewController::NO_SNAP);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
}
// Tests that the default snapped window is the first window that gets snapped.
TEST_F(SplitViewControllerTest, DefaultSnappedWindow) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
EXPECT_EQ(window1.get(), split_view_controller()->GetDefaultSnappedWindow());
EndSplitView();
split_view_controller()->SnapWindow(window2.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window1.get(),
SplitViewController::RIGHT);
EXPECT_EQ(window2.get(), split_view_controller()->GetDefaultSnappedWindow());
}
// Tests that if there are two snapped windows, closing one of them will open
// overview window grid on the closed window side of the screen. If there is
// only one snapped windows, closing the sanpped window will end split view mode
// and adjust the overview window grid bounds if the overview mode is active at
// that moment.
TEST_F(SplitViewControllerTest, WindowCloseTest) {
// 1 - First test one snapped window scenario.
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window0(CreateWindow(bounds));
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
split_view_controller()->SnapWindow(window0.get(), SplitViewController::LEFT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
// Closing this snapped window should exit split view mode.
window0.reset();
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
// 2 - Then test two snapped windows scenario.
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::BOTH_SNAPPED);
EXPECT_EQ(split_view_controller()->default_snap_position(),
SplitViewController::LEFT);
// Closing one of the two snapped windows will not end split view mode.
window1.reset();
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::RIGHT_SNAPPED);
// Since left window was closed, its default snap position changed to RIGHT.
EXPECT_EQ(split_view_controller()->default_snap_position(),
SplitViewController::RIGHT);
// It can't open overview window grid since there is no window to be shown
// in the overview window grid.
EXPECT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting());
// Now close the other snapped window.
window2.reset();
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
EXPECT_EQ(split_view_controller()->state(), SplitViewController::NO_SNAP);
EXPECT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting());
// 3 - Then test the scenario with more than two windows.
std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
std::unique_ptr<aura::Window> window4(CreateWindow(bounds));
std::unique_ptr<aura::Window> window5(CreateWindow(bounds));
split_view_controller()->SnapWindow(window3.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window4.get(),
SplitViewController::RIGHT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::BOTH_SNAPPED);
EXPECT_EQ(split_view_controller()->default_snap_position(),
SplitViewController::LEFT);
// Close one of the snapped windows.
window4.reset();
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::LEFT_SNAPPED);
EXPECT_EQ(split_view_controller()->default_snap_position(),
SplitViewController::LEFT);
// Now overview window grid can be opened.
EXPECT_TRUE(Shell::Get()->window_selector_controller()->IsSelecting());
// Close the other snapped window.
window3.reset();
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
EXPECT_EQ(split_view_controller()->state(), SplitViewController::NO_SNAP);
// Test the overview winow grid should still open.
EXPECT_TRUE(Shell::Get()->window_selector_controller()->IsSelecting());
}
// Tests that if there are two snapped windows, minimizing one of them will open
// overview window grid on the minimized window side of the screen. If there is
// only one snapped windows, minimizing the sanpped window will end split view
// mode and adjust the overview window grid bounds if the overview mode is
// active at that moment.
TEST_F(SplitViewControllerTest, MinimizeWindowTest) {
const gfx::Rect bounds(0, 0, 400, 400);
// 1 - First test one snapped window scenario.
std::unique_ptr<aura::Window> window0(CreateWindow(bounds));
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
split_view_controller()->SnapWindow(window0.get(), SplitViewController::LEFT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
wm::WMEvent minimize_event(wm::WM_EVENT_MINIMIZE);
wm::GetWindowState(window0.get())->OnWMEvent(&minimize_event);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
// 2 - Then test the scenario that has 2 or more windows.
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::BOTH_SNAPPED);
EXPECT_EQ(split_view_controller()->default_snap_position(),
SplitViewController::LEFT);
// Minimizing one of the two snapped windows will not end split view mode.
wm::GetWindowState(window1.get())->OnWMEvent(&minimize_event);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::RIGHT_SNAPPED);
// Since left window was minimized, its default snap position changed to
// RIGHT.
EXPECT_EQ(split_view_controller()->default_snap_position(),
SplitViewController::RIGHT);
// The overview window grid will open.
EXPECT_TRUE(Shell::Get()->window_selector_controller()->IsSelecting());
// Now minimize the other snapped window.
wm::GetWindowState(window2.get())->OnWMEvent(&minimize_event);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
EXPECT_EQ(split_view_controller()->state(), SplitViewController::NO_SNAP);
// The overview window grid is still open.
EXPECT_TRUE(Shell::Get()->window_selector_controller()->IsSelecting());
}
// Tests that if one of the snapped window gets maximized / full-screened, the
// split view mode ends.
TEST_F(SplitViewControllerTest, WindowStateChangeTest) {
const gfx::Rect bounds(0, 0, 400, 400);
// 1 - First test one snapped window scenario.
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
wm::WMEvent maximize_event(wm::WM_EVENT_MAXIMIZE);
wm::GetWindowState(window1.get())->OnWMEvent(&maximize_event);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
wm::WMEvent fullscreen_event(wm::WM_EVENT_FULLSCREEN);
wm::GetWindowState(window1.get())->OnWMEvent(&fullscreen_event);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
// 2 - Then test two snapped window scenario.
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
// Maximize one of the snapped window will end the split view mode.
wm::GetWindowState(window1.get())->OnWMEvent(&maximize_event);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
// Full-screen one of the snapped window will also end the split view mode.
wm::GetWindowState(window1.get())->OnWMEvent(&fullscreen_event);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
// 3 - Test the scenario that part of the screen is a snapped window and part
// of the screen is the overview window grid.
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
ToggleOverview();
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
// Maximize the snapped window will end the split view mode and overview mode.
wm::GetWindowState(window1.get())->OnWMEvent(&maximize_event);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
EXPECT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting());
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
ToggleOverview();
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
// Fullscreen the snapped window will end the split view mode and overview
// mode.
wm::GetWindowState(window1.get())->OnWMEvent(&fullscreen_event);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
EXPECT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting());
}
// Tests that if split view mode is active, activate another window will snap
// the window to the non-default side of the screen.
TEST_F(SplitViewControllerTest, WindowActivationTest) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
EXPECT_EQ(split_view_controller()->left_window(), window1.get());
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::LEFT_SNAPPED);
wm::ActivateWindow(window2.get());
EXPECT_EQ(split_view_controller()->right_window(), window2.get());
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::BOTH_SNAPPED);
wm::ActivateWindow(window3.get());
EXPECT_EQ(split_view_controller()->right_window(), window3.get());
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::BOTH_SNAPPED);
}
// Tests that if split view mode and overview mode are active at the same time,
// i.e., half of the screen is occupied by a snapped window and half of the
// screen is occupied by the overview windows grid, the next activatable window
// will be picked to snap when exiting the overview mode.
TEST_F(SplitViewControllerTest, ExitOverviewTest) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), false);
ToggleOverview();
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
EXPECT_EQ(split_view_controller()->IsSplitViewModeActive(), true);
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::LEFT_SNAPPED);
EXPECT_EQ(split_view_controller()->left_window(), window1.get());
ToggleOverview();
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::BOTH_SNAPPED);
EXPECT_EQ(split_view_controller()->right_window(), window3.get());
}
// Tests that if split view mode is active when entering overview, the overview
// windows grid should show in the non-default side of the screen, and the
// default snapped window should not be shown in the overview window grid.
TEST_F(SplitViewControllerTest, EnterOverviewTest) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::BOTH_SNAPPED);
EXPECT_EQ(split_view_controller()->GetDefaultSnappedWindow(), window1.get());
ToggleOverview();
EXPECT_EQ(split_view_controller()->state(),
SplitViewController::LEFT_SNAPPED);
std::vector<aura::Window*> windows = GetWindowsInOverviewGrids();
auto iter = std::find(windows.begin(), windows.end(),
split_view_controller()->GetDefaultSnappedWindow());
EXPECT_TRUE(iter == windows.end());
}
// Tests that the split divider was created when the split view mode is active
// and destroyed when the split view mode is ended. The split divider should be
// always above the two snapped windows.
TEST_F(SplitViewControllerTest, SplitDividerBasicTest) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
EXPECT_TRUE(!split_view_divider());
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
EXPECT_TRUE(split_view_divider());
EXPECT_TRUE(split_view_divider()->divider_widget()->IsAlwaysOnTop());
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
EXPECT_TRUE(split_view_divider());
EXPECT_TRUE(split_view_divider()->divider_widget()->IsAlwaysOnTop());
std::unique_ptr<aura::Window> window3(CreateNonSnappableWindow(bounds));
wm::ActivateWindow(window3.get());
EXPECT_TRUE(split_view_divider());
EXPECT_FALSE(split_view_divider()->divider_widget()->IsAlwaysOnTop());
EndSplitView();
EXPECT_TRUE(!split_view_divider());
}
// Verifys that the bounds of the two windows in splitview are as expected.
TEST_F(SplitViewControllerTest, SplitDividerWindowBounds) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
ASSERT_TRUE(split_view_divider());
// Verify with two freshly snapped windows are roughly the same width (off by
// one pixel at most due to the display maybe being even and the divider being
// a fixed odd pixel width).
int window1_width = window1->GetBoundsInScreen().width();
int window2_width = window2->GetBoundsInScreen().width();
gfx::Rect divider_bounds =
split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */);
const int screen_width =
screen_util::GetDisplayWorkAreaBoundsInParent(window1.get()).width();
EXPECT_NEAR(window1_width, window2_width, 1);
EXPECT_EQ(screen_width,
window1_width + divider_bounds.width() + window2_width);
// Drag the divider to a position two thirds of the screen size. Verify window
// 1 is wider than window 2.
GetEventGenerator().set_current_location(divider_bounds.CenterPoint());
GetEventGenerator().DragMouseTo(screen_width * 0.67f, 0);
window1_width = window1->GetBoundsInScreen().width();
window2_width = window2->GetBoundsInScreen().width();
const int old_window1_width = window1_width;
const int old_window2_width = window2_width;
EXPECT_GT(window1_width, 2 * window2_width);
EXPECT_EQ(screen_width,
window1_width + divider_bounds.width() + window2_width);
// Drag the divider to a position close to two thirds of the screen size.
// Verify the divider snaps to two thirds of the screen size, and the windows
// remain the same size as previously.
divider_bounds =
split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */);
GetEventGenerator().set_current_location(divider_bounds.CenterPoint());
GetEventGenerator().DragMouseTo(screen_width * 0.7f, 0);
window1_width = window1->GetBoundsInScreen().width();
window2_width = window2->GetBoundsInScreen().width();
EXPECT_EQ(window1_width, old_window1_width);
EXPECT_EQ(window2_width, old_window2_width);
// Drag the divider to a position one third of the screen size. Verify window
// 1 is wider than window 2.
divider_bounds =
split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */);
GetEventGenerator().set_current_location(divider_bounds.CenterPoint());
GetEventGenerator().DragMouseTo(screen_width * 0.33f, 0);
window1_width = window1->GetBoundsInScreen().width();
window2_width = window2->GetBoundsInScreen().width();
EXPECT_GT(window2_width, 2 * window1_width);
EXPECT_EQ(screen_width,
window1_width + divider_bounds.width() + window2_width);
// Verify that the left window from dragging the divider to two thirds of the
// screen size is roughly the same size as the right window after dragging the
// divider to one third of the screen size, and vice versa.
EXPECT_NEAR(window1_width, old_window2_width, 1);
EXPECT_NEAR(window2_width, old_window1_width, 1);
}
// Tests that the bounds of the snapped windows and divider are adjusted when
// the screen display configuration changes.
TEST_F(SplitViewControllerTest, DisplayConfigurationChangeTest) {
UpdateDisplay("407x400");
const gfx::Rect bounds(0, 0, 200, 200);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
const gfx::Rect bounds_window1 = window1->GetBoundsInScreen();
const gfx::Rect bounds_window2 = window2->GetBoundsInScreen();
const gfx::Rect bounds_divider =
split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */);
// Test that |window1| and |window2| has the same width and height after snap.
EXPECT_EQ(bounds_window1.width(), bounds_window2.width());
EXPECT_EQ(bounds_window1.height(), bounds_window2.height());
EXPECT_EQ(bounds_divider.height(), bounds_window1.height());
// Test that |window1|, divider, |window2| are aligned properly.
EXPECT_EQ(bounds_divider.x(), bounds_window1.x() + bounds_window1.width());
EXPECT_EQ(bounds_window2.x(), bounds_divider.x() + bounds_divider.width());
// Now change the display configuration.
UpdateDisplay("507x500");
const gfx::Rect new_bounds_window1 = window1->GetBoundsInScreen();
const gfx::Rect new_bounds_window2 = window2->GetBoundsInScreen();
const gfx::Rect new_bounds_divider =
split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */);
// Test that the new bounds are different with the old ones.
EXPECT_NE(bounds_window1, new_bounds_window1);
EXPECT_NE(bounds_window2, new_bounds_window2);
EXPECT_NE(bounds_divider, new_bounds_divider);
// Test that |window1|, divider, |window2| are still aligned properly.
EXPECT_EQ(new_bounds_divider.x(),
new_bounds_window1.x() + new_bounds_window1.width());
EXPECT_EQ(new_bounds_window2.x(),
new_bounds_divider.x() + new_bounds_divider.width());
}
// Verify the left and right windows get swapped when SwapWindows is called or
// the divider is double tapped.
TEST_F(SplitViewControllerTest, SwapWindows) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
EXPECT_EQ(split_view_controller()->left_window(), window1.get());
EXPECT_EQ(split_view_controller()->right_window(), window2.get());
const gfx::Rect left_bounds = window1->GetBoundsInScreen();
const gfx::Rect right_bounds = window2->GetBoundsInScreen();
// Verify that after swapping windows, the windows and their bounds have been
// swapped.
split_view_controller()->SwapWindows();
EXPECT_EQ(split_view_controller()->left_window(), window2.get());
EXPECT_EQ(split_view_controller()->right_window(), window1.get());
EXPECT_EQ(left_bounds, window2->GetBoundsInScreen());
EXPECT_EQ(right_bounds, window1->GetBoundsInScreen());
// Perform a double tap on the divider center.
const gfx::Point divider_center =
split_view_divider()
->GetDividerBoundsInScreen(false /* is_dragging */)
.CenterPoint();
GetEventGenerator().set_current_location(divider_center);
GetEventGenerator().DoubleClickLeftButton();
EXPECT_EQ(split_view_controller()->left_window(), window1.get());
EXPECT_EQ(split_view_controller()->right_window(), window2.get());
}
// Verifies that by long pressing on the overview button tray, split view gets
// activated iff we have two or more windows in the mru list.
TEST_F(SplitViewControllerTest, LongPressEntersSplitView) {
// Verify that with no active windows, split view does not get activated.
LongPressOnOverivewButtonTray();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
wm::ActivateWindow(window1.get());
// Verify that with only one window, split view does not get activated.
LongPressOnOverivewButtonTray();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
// Verify that with two windows, split view gets activated.
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
wm::ActivateWindow(window2.get());
LongPressOnOverivewButtonTray();
EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive());
}
// Verify that when in split view mode with either one snapped or two snapped
// windows, split view mode gets exited when the overview button gets a long
// press event.
TEST_F(SplitViewControllerTest, LongPressExitsSplitView) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
wm::ActivateWindow(window2.get());
wm::ActivateWindow(window1.get());
// Snap |window1| to the left.
ToggleOverview();
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
ASSERT_TRUE(split_view_controller()->IsSplitViewModeActive());
// Verify that by long pressing on the overview button tray with left snapped
// window, split view mode gets exited and the left window (|window1|) is the
// current active window.
LongPressOnOverivewButtonTray();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
EXPECT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting());
EXPECT_EQ(window1.get(), wm::GetActiveWindow());
// Snap |window1| to the right.
ToggleOverview();
split_view_controller()->SnapWindow(window1.get(),
SplitViewController::RIGHT);
ASSERT_TRUE(split_view_controller()->IsSplitViewModeActive());
// Verify that by long pressing on the overview button tray with right snapped
// window, split view mode gets exited and the right window (|window1|) is the
// current active window.
LongPressOnOverivewButtonTray();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
EXPECT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting());
EXPECT_EQ(window1.get(), wm::GetActiveWindow());
// Snap two windows and activate the left window, |window1|.
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
wm::ActivateWindow(window1.get());
ASSERT_TRUE(split_view_controller()->IsSplitViewModeActive());
// Verify that by long pressing on the overview button tray with two snapped
// windows, split view mode gets exited.
LongPressOnOverivewButtonTray();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
EXPECT_EQ(window1.get(), wm::GetActiveWindow());
// Snap two windows and activate the right window, |window2|.
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
wm::ActivateWindow(window2.get());
ASSERT_TRUE(split_view_controller()->IsSplitViewModeActive());
// Verify that by long pressing on the overview button tray with two snapped
// windows, split view mode gets exited, and the activated window in splitview
// is the current active window.
LongPressOnOverivewButtonTray();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
EXPECT_EQ(window2.get(), wm::GetActiveWindow());
}
TEST_F(SplitViewControllerTest, LongPressExitsSplitViewWithTransientChild) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> left_window(CreateWindow(bounds));
std::unique_ptr<aura::Window> right_window(CreateWindow(bounds));
wm::ActivateWindow(left_window.get());
wm::ActivateWindow(right_window.get());
ToggleOverview();
split_view_controller()->SnapWindow(left_window.get(),
SplitViewController::LEFT);
split_view_controller()->SnapWindow(right_window.get(),
SplitViewController::RIGHT);
ASSERT_TRUE(split_view_controller()->IsSplitViewModeActive());
// Add a transient child to |right_window|, and activate it.
aura::Window* transient_child =
aura::test::CreateTestWindowWithId(0, right_window.get());
::wm::AddTransientChild(right_window.get(), transient_child);
wm::ActivateWindow(transient_child);
// Verify that by long pressing on the overview button tray, split view mode
// gets exited and the window which contained |transient_child| is the
// current active window.
LongPressOnOverivewButtonTray();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
EXPECT_FALSE(Shell::Get()->window_selector_controller()->IsSelecting());
EXPECT_EQ(right_window.get(), wm::GetActiveWindow());
}
// Verify that split view mode get activated when long pressing on the overview
// button while in overview mode iff we have more than two windows in the mru
// list.
TEST_F(SplitViewControllerTest, LongPressInOverviewMode) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
wm::ActivateWindow(window1.get());
ToggleOverview();
ASSERT_TRUE(Shell::Get()->window_selector_controller()->IsSelecting());
ASSERT_FALSE(split_view_controller()->IsSplitViewModeActive());
// Nothing happens if there is only one window.
LongPressOnOverivewButtonTray();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
// Verify that with two windows, a long press on the overview button tray will
// enter splitview.
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
wm::ActivateWindow(window2.get());
ToggleOverview();
ASSERT_TRUE(Shell::Get()->window_selector_controller()->IsSelecting());
ASSERT_FALSE(split_view_controller()->IsSplitViewModeActive());
LongPressOnOverivewButtonTray();
EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive());
EXPECT_EQ(window2.get(), split_view_controller()->left_window());
}
TEST_F(SplitViewControllerTest, LongPressWithUnsnappableWindow) {
// Add one unsnappable window and two regular windows.
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> unsnappable_window(
CreateNonSnappableWindow(bounds));
ASSERT_FALSE(split_view_controller()->IsSplitViewModeActive());
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
wm::ActivateWindow(window2.get());
wm::ActivateWindow(window3.get());
wm::ActivateWindow(unsnappable_window.get());
ASSERT_EQ(unsnappable_window.get(), wm::GetActiveWindow());
// Verify split view is not activated when long press occurs when active
// window is unsnappable.
LongPressOnOverivewButtonTray();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
// Verify split view is not activated when long press occurs in overview mode
// and the most recent window is unsnappable.
ToggleOverview();
ASSERT_TRUE(Shell::Get()->mru_window_tracker()->BuildMruWindowList().size() >
0);
ASSERT_EQ(unsnappable_window.get(),
Shell::Get()->mru_window_tracker()->BuildMruWindowList()[0]);
LongPressOnOverivewButtonTray();
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
}
// Test the rotation functionalities in split view mode.
TEST_F(SplitViewControllerTest, RotationTest) {
UpdateDisplay("807x407");
int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
display::DisplayManager* display_manager = Shell::Get()->display_manager();
display::test::ScopedSetInternalDisplayId set_internal(display_manager,
display_id);
ScreenOrientationControllerTestApi test_api(
Shell::Get()->screen_orientation_controller());
// Set the screen orientation to LANDSCAPE_PRIMARY.
test_api.SetDisplayRotation(display::Display::ROTATE_0,
display::Display::ROTATION_SOURCE_ACTIVE);
EXPECT_EQ(test_api.GetCurrentOrientation(),
blink::kWebScreenOrientationLockLandscapePrimary);
const gfx::Rect bounds(0, 0, 200, 200);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
gfx::Rect bounds_window1 = window1->GetBoundsInScreen();
gfx::Rect bounds_window2 = window2->GetBoundsInScreen();
gfx::Rect bounds_divider =
split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */);
// Test |window1|, divider and |window2| are aligned horizontally.
// |window1| is on the left, then the divider, and then |window2|.
EXPECT_EQ(bounds_divider.x(), bounds_window1.x() + bounds_window1.width());
EXPECT_EQ(bounds_window2.x(), bounds_divider.x() + bounds_divider.width());
EXPECT_EQ(bounds_window1.height(), bounds_divider.height());
EXPECT_EQ(bounds_window1.height(), bounds_window2.height());
// Rotate the screen by 90 degree.
test_api.SetDisplayRotation(display::Display::ROTATE_90,
display::Display::ROTATION_SOURCE_ACTIVE);
EXPECT_EQ(test_api.GetCurrentOrientation(),
blink::kWebScreenOrientationLockPortraitPrimary);
bounds_window1 = window1->GetBoundsInScreen();
bounds_window2 = window2->GetBoundsInScreen();
bounds_divider =
split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */);
// Test that |window1|, divider, |window2| are now aligned vertically.
// |window2| is on the top, then the divider, and then |window1|.
EXPECT_EQ(bounds_divider.y(), bounds_window2.y() + bounds_window2.height());
EXPECT_EQ(bounds_window1.y(), bounds_divider.y() + bounds_divider.height());
EXPECT_EQ(bounds_window1.width(), bounds_divider.width());
EXPECT_EQ(bounds_window1.width(), bounds_window2.width());
// Rotate the screen by 180 degree.
test_api.SetDisplayRotation(display::Display::ROTATE_180,
display::Display::ROTATION_SOURCE_ACTIVE);
EXPECT_EQ(test_api.GetCurrentOrientation(),
blink::kWebScreenOrientationLockLandscapeSecondary);
bounds_window1 = window1->GetBoundsInScreen();
bounds_window2 = window2->GetBoundsInScreen();
bounds_divider =
split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */);
// Test that |window1|, divider, |window2| are now aligned horizontally.
// |window2| is on the left, then the divider, and then |window1|.
EXPECT_EQ(bounds_divider.x(), bounds_window2.x() + bounds_window2.width());
EXPECT_EQ(bounds_window1.x(), bounds_divider.x() + bounds_divider.width());
EXPECT_EQ(bounds_window1.height(), bounds_divider.height());
EXPECT_EQ(bounds_window1.height(), bounds_window2.height());
// Rotate the screen by 270 degree.
test_api.SetDisplayRotation(display::Display::ROTATE_270,
display::Display::ROTATION_SOURCE_ACTIVE);
EXPECT_EQ(test_api.GetCurrentOrientation(),
blink::kWebScreenOrientationLockPortraitSecondary);
bounds_window1 = window1->GetBoundsInScreen();
bounds_window2 = window2->GetBoundsInScreen();
bounds_divider =
split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */);
// Test that |window1|, divider, |window2| are now aligned vertically.
// |window1| is on the top, then the divider, and then |window2|.
EXPECT_EQ(bounds_divider.y(), bounds_window1.y() + bounds_window1.height());
EXPECT_EQ(bounds_window2.y(), bounds_divider.y() + bounds_divider.height());
EXPECT_EQ(bounds_window1.width(), bounds_divider.width());
EXPECT_EQ(bounds_window1.width(), bounds_window2.width());
// Rotate the screen back to 0 degree.
test_api.SetDisplayRotation(display::Display::ROTATE_0,
display::Display::ROTATION_SOURCE_ACTIVE);
EXPECT_EQ(test_api.GetCurrentOrientation(),
blink::kWebScreenOrientationLockLandscapePrimary);
bounds_window1 = window1->GetBoundsInScreen();
bounds_window2 = window2->GetBoundsInScreen();
bounds_divider =
split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */);
// Test |window1|, divider and |window2| are aligned horizontally.
// |window1| is on the left, then the divider, and then |window2|.
EXPECT_EQ(bounds_divider.x(), bounds_window1.x() + bounds_window1.width());
EXPECT_EQ(bounds_window2.x(), bounds_divider.x() + bounds_divider.width());
EXPECT_EQ(bounds_window1.height(), bounds_divider.height());
EXPECT_EQ(bounds_window1.height(), bounds_window2.height());
}
// Test that if the split view mode is active when exiting tablet mode, we
// should also end split view mode.
TEST_F(SplitViewControllerTest, ExitTabletModeEndSplitView) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
EXPECT_TRUE(split_view_controller()->IsSplitViewModeActive());
Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false);
EXPECT_FALSE(split_view_controller()->IsSplitViewModeActive());
}
// Tests that if a window's minimum size is larger than half of the display work
// area's size, it can't be snapped.
TEST_F(SplitViewControllerTest, SnapWindowWithMinimumSizeTest) {
const gfx::Rect bounds(0, 0, 400, 400);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
EXPECT_TRUE(split_view_controller()->CanSnap(window1.get()));
const gfx::Rect display_bounds =
split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get());
aura::test::TestWindowDelegate* delegate =
static_cast<aura::test::TestWindowDelegate*>(window1->delegate());
delegate->set_minimum_size(
gfx::Size(display_bounds.width() * 0.5f, display_bounds.height()));
EXPECT_TRUE(split_view_controller()->CanSnap(window1.get()));
delegate->set_minimum_size(
gfx::Size(display_bounds.width() * 0.67f, display_bounds.height()));
EXPECT_FALSE(split_view_controller()->CanSnap(window1.get()));
}
// Tests that the left or top snapped window can be moved outside of work area
// when its minimum size is larger than its current bounds.
TEST_F(SplitViewControllerTest, SnapWindowBoundsWithMinimumSizeTest) {
int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
display::DisplayManager* display_manager = Shell::Get()->display_manager();
display::test::ScopedSetInternalDisplayId set_internal(display_manager,
display_id);
ScreenOrientationControllerTestApi test_api(
Shell::Get()->screen_orientation_controller());
const gfx::Rect bounds(0, 0, 300, 200);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
aura::test::TestWindowDelegate* delegate1 =
static_cast<aura::test::TestWindowDelegate*>(window1->delegate());
// Set the screen orientation to LANDSCAPE_PRIMARY
test_api.SetDisplayRotation(display::Display::ROTATE_0,
display::Display::ROTATION_SOURCE_ACTIVE);
EXPECT_EQ(test_api.GetCurrentOrientation(),
blink::kWebScreenOrientationLockLandscapePrimary);
gfx::Rect display_bounds =
split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get());
EXPECT_TRUE(split_view_controller()->CanSnap(window1.get()));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
delegate1->set_minimum_size(
gfx::Size(display_bounds.width() * 0.4f, display_bounds.height()));
gfx::Rect divider_bounds =
split_view_divider()->GetDividerBoundsInScreen(false);
split_view_controller()->StartResize(divider_bounds.CenterPoint());
gfx::Point resize_point(display_bounds.width() * 0.33f, 0);
split_view_controller()->Resize(resize_point);
gfx::Rect snapped_window_bounds =
split_view_controller()->GetSnappedWindowBoundsInScreen(
window1.get(), SplitViewController::LEFT);
EXPECT_LT(snapped_window_bounds.x(), display_bounds.x());
EXPECT_EQ(snapped_window_bounds.width(),
window1->delegate()->GetMinimumSize().width());
EndSplitView();
// Rotate the screen by 90 degree.
test_api.SetDisplayRotation(display::Display::ROTATE_90,
display::Display::ROTATION_SOURCE_ACTIVE);
EXPECT_EQ(test_api.GetCurrentOrientation(),
blink::kWebScreenOrientationLockPortraitPrimary);
display_bounds =
split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get());
delegate1->set_minimum_size(
gfx::Size(display_bounds.width(), display_bounds.height() * 0.4f));
EXPECT_TRUE(split_view_controller()->CanSnap(window1.get()));
split_view_controller()->SnapWindow(window1.get(),
SplitViewController::RIGHT);
divider_bounds = split_view_divider()->GetDividerBoundsInScreen(false);
split_view_controller()->StartResize(divider_bounds.CenterPoint());
resize_point.SetPoint(0, display_bounds.height() * 0.33f);
split_view_controller()->Resize(resize_point);
snapped_window_bounds =
split_view_controller()->GetSnappedWindowBoundsInScreen(
window1.get(), SplitViewController::RIGHT);
EXPECT_LT(snapped_window_bounds.y(), display_bounds.y());
EXPECT_EQ(snapped_window_bounds.height(),
window1->delegate()->GetMinimumSize().height());
EndSplitView();
// Rotate the screen by 180 degree.
test_api.SetDisplayRotation(display::Display::ROTATE_180,
display::Display::ROTATION_SOURCE_ACTIVE);
EXPECT_EQ(test_api.GetCurrentOrientation(),
blink::kWebScreenOrientationLockLandscapeSecondary);
display_bounds =
split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get());
delegate1->set_minimum_size(
gfx::Size(display_bounds.width() * 0.4f, display_bounds.height()));
EXPECT_TRUE(split_view_controller()->CanSnap(window1.get()));
split_view_controller()->SnapWindow(window1.get(),
SplitViewController::RIGHT);
divider_bounds = split_view_divider()->GetDividerBoundsInScreen(false);
split_view_controller()->StartResize(divider_bounds.CenterPoint());
resize_point.SetPoint(display_bounds.width() * 0.33f, 0);
split_view_controller()->Resize(resize_point);
snapped_window_bounds =
split_view_controller()->GetSnappedWindowBoundsInScreen(
window1.get(), SplitViewController::RIGHT);
EXPECT_LT(snapped_window_bounds.x(), display_bounds.x());
EXPECT_EQ(snapped_window_bounds.width(),
window1->delegate()->GetMinimumSize().width());
EndSplitView();
// Rotate the screen by 270 degree.
test_api.SetDisplayRotation(display::Display::ROTATE_270,
display::Display::ROTATION_SOURCE_ACTIVE);
EXPECT_EQ(test_api.GetCurrentOrientation(),
blink::kWebScreenOrientationLockPortraitSecondary);
display_bounds =
split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get());
delegate1->set_minimum_size(
gfx::Size(display_bounds.width(), display_bounds.height() * 0.4f));
EXPECT_TRUE(split_view_controller()->CanSnap(window1.get()));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
divider_bounds = split_view_divider()->GetDividerBoundsInScreen(false);
split_view_controller()->StartResize(divider_bounds.CenterPoint());
resize_point.SetPoint(0, display_bounds.height() * 0.33f);
split_view_controller()->Resize(resize_point);
snapped_window_bounds =
split_view_controller()->GetSnappedWindowBoundsInScreen(
window1.get(), SplitViewController::LEFT);
EXPECT_LT(snapped_window_bounds.y(), display_bounds.y());
EXPECT_EQ(snapped_window_bounds.height(),
window1->delegate()->GetMinimumSize().height());
EndSplitView();
}
// Tests that if a snapped window's minumum size is larger than one third but
// smaller than half of the work area's longer side. The divider should be
// snapped to a position that is larger than the window's minimum size.
TEST_F(SplitViewControllerTest, DividerPositionWithWindowMinimumSizeTest) {
const gfx::Rect bounds(0, 0, 200, 200);
std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
aura::test::TestWindowDelegate* delegate1 =
static_cast<aura::test::TestWindowDelegate*>(window1->delegate());
ui::test::EventGenerator& generator(GetEventGenerator());
EXPECT_EQ(blink::kWebScreenOrientationLockLandscapePrimary,
screen_orientation());
gfx::Rect workarea_bounds =
split_view_controller()->GetDisplayWorkAreaBoundsInScreen(window1.get());
// Snap the divider to one third position when there is only left window with
// minimum size larger than one third of the display's width. The divider
// should be snapped to the middle position after dragging.
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
delegate1->set_minimum_size(
gfx::Size(workarea_bounds.width() * 0.4f, workarea_bounds.height()));
gfx::Rect divider_bounds =
split_view_divider()->GetDividerBoundsInScreen(false);
generator.set_current_location(divider_bounds.CenterPoint());
generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.33f, 0));
EXPECT_GT(divider_position(), 0.33f * workarea_bounds.width());
EXPECT_LE(divider_position(), 0.5f * workarea_bounds.width());
// Snap the divider to two third position, it should be kept at there after
// dragging.
generator.set_current_location(divider_bounds.CenterPoint());
generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.67f, 0));
EXPECT_GT(divider_position(), 0.5f * workarea_bounds.width());
EXPECT_LE(divider_position(), 0.67f * workarea_bounds.width());
EndSplitView();
// Snap the divider to two third position when there is only right window with
// minium size larger than one third of the display's width. The divider
// should be snapped to the middle position after dragging.
delegate1->set_minimum_size(
gfx::Size(workarea_bounds.width() * 0.4f, workarea_bounds.height()));
split_view_controller()->SnapWindow(window1.get(),
SplitViewController::RIGHT);
divider_bounds = split_view_divider()->GetDividerBoundsInScreen(false);
generator.set_current_location(divider_bounds.CenterPoint());
generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.67f, 0));
EXPECT_GT(divider_position(), 0.33f * workarea_bounds.width());
EXPECT_LE(divider_position(), 0.5f * workarea_bounds.width());
// Snap the divider to one third position, it should be kept at there after
// dragging.
generator.set_current_location(divider_bounds.CenterPoint());
generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.33f, 0));
EXPECT_GT(divider_position(), 0);
EXPECT_LE(divider_position(), 0.33f * workarea_bounds.width());
EndSplitView();
// Snap the divider to one third position when there are both left and right
// snapped windows with the same minimum size larger than one third of the
// display's width. The divider should be snapped to the middle position after
// dragging.
std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
aura::test::TestWindowDelegate* delegate2 =
static_cast<aura::test::TestWindowDelegate*>(window2->delegate());
delegate2->set_minimum_size(
gfx::Size(workarea_bounds.width() * 0.4f, workarea_bounds.height()));
split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller()->SnapWindow(window2.get(),
SplitViewController::RIGHT);
divider_bounds = split_view_divider()->GetDividerBoundsInScreen(false);
generator.set_current_location(divider_bounds.CenterPoint());
generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.33f, 0));
EXPECT_GT(divider_position(), 0.33f * workarea_bounds.width());
EXPECT_LE(divider_position(), 0.5f * workarea_bounds.width());
// Snap the divider to two third position, it should be snapped to the middle
// position after dragging.
generator.set_current_location(divider_bounds.CenterPoint());
generator.DragMouseTo(gfx::Point(workarea_bounds.width() * 0.67f, 0));
EXPECT_GT(divider_position(), 0.33f * workarea_bounds.width());
EXPECT_LE(divider_position(), 0.5f * workarea_bounds.width());
EndSplitView();
}
} // namespace ash