123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868 |
- // Copyright 2018 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/display/persistent_window_controller.h"
- #include "ash/display/display_move_window_util.h"
- #include "ash/display/screen_orientation_controller_test_api.h"
- #include "ash/display/window_tree_host_manager.h"
- #include "ash/screen_util.h"
- #include "ash/session/test_session_controller_client.h"
- #include "ash/shell.h"
- #include "ash/test/ash_test_base.h"
- #include "ash/wm/mru_window_tracker.h"
- #include "ash/wm/splitview/split_view_controller.h"
- #include "ash/wm/window_state.h"
- #include "ash/wm/window_util.h"
- #include "base/test/metrics/histogram_tester.h"
- #include "chromeos/ui/base/display_util.h"
- #include "chromeos/ui/base/window_state_type.h"
- #include "ui/display/test/display_manager_test_api.h"
- using session_manager::SessionState;
- namespace ash {
- using PersistentWindowControllerTest = AshTestBase;
- TEST_F(PersistentWindowControllerTest, DisconnectDisplay) {
- UpdateDisplay("500x600,500x600");
- aura::Window* w1 =
- CreateTestWindowInShellWithBounds(gfx::Rect(200, 0, 100, 200));
- aura::Window* w2 =
- CreateTestWindowInShellWithBounds(gfx::Rect(501, 0, 200, 100));
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- const int64_t primary_id = WindowTreeHostManager::GetPrimaryDisplayId();
- const int64_t secondary_id =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id();
- display::ManagedDisplayInfo primary_info =
- display_manager()->GetDisplayInfo(primary_id);
- display::ManagedDisplayInfo secondary_info =
- display_manager()->GetDisplayInfo(secondary_id);
- // Disconnects secondary display.
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- // Reconnects secondary display.
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- // Disconnects primary display.
- display_info_list.clear();
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- // Reconnects primary display.
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- // Disconnects secondary display.
- display_info_list.clear();
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- // A third id which is different from primary and secondary.
- const int64_t third_id = secondary_id + 1;
- display::ManagedDisplayInfo third_info =
- display::CreateDisplayInfo(third_id, gfx::Rect(0, 501, 600, 500));
- // Connects another secondary display with |third_id|.
- display_info_list.push_back(third_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- // Connects secondary display with |secondary_id|.
- display_info_list.clear();
- display_info_list.push_back(primary_info);
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- // Disconnects secondary display.
- display_info_list.clear();
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- // Sets |w2|'s bounds changed by user and then reconnects secondary display.
- WindowState* w2_state = WindowState::Get(w2);
- w2_state->set_bounds_changed_by_user(true);
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- }
- TEST_F(PersistentWindowControllerTest, ThreeDisplays) {
- UpdateDisplay("500x600,500x600,500x600");
- aura::Window* w1 =
- CreateTestWindowInShellWithBounds(gfx::Rect(200, 0, 100, 200));
- aura::Window* w2 =
- CreateTestWindowInShellWithBounds(gfx::Rect(501, 0, 200, 100));
- aura::Window* w3 =
- CreateTestWindowInShellWithBounds(gfx::Rect(1002, 0, 400, 200));
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1002, 0, 400, 200), w3->GetBoundsInScreen());
- const int64_t primary_id = display_manager()->GetDisplayAt(0).id();
- const int64_t second_id = display_manager()->GetDisplayAt(1).id();
- const int64_t third_id = display_manager()->GetDisplayAt(2).id();
- display::ManagedDisplayInfo primary_info =
- display_manager()->GetDisplayInfo(primary_id);
- display::ManagedDisplayInfo second_info =
- display_manager()->GetDisplayInfo(second_id);
- display::ManagedDisplayInfo third_info =
- display_manager()->GetDisplayInfo(third_id);
- // Disconnects third display.
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(primary_info);
- display_info_list.push_back(second_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(2, 0, 400, 200), w3->GetBoundsInScreen());
- // Disconnects second display.
- display_info_list.clear();
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(2, 0, 400, 200), w3->GetBoundsInScreen());
- // Reconnects third display.
- display_info_list.push_back(third_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(502, 0, 400, 200), w3->GetBoundsInScreen());
- // Reconnects second display.
- display_info_list.push_back(second_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1002, 0, 400, 200), w3->GetBoundsInScreen());
- // Disconnects both external displays.
- display_info_list.clear();
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(2, 0, 400, 200), w3->GetBoundsInScreen());
- // Reconnects second display.
- display_info_list.push_back(second_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(2, 0, 400, 200), w3->GetBoundsInScreen());
- // Reconnects third display.
- display_info_list.push_back(third_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1002, 0, 400, 200), w3->GetBoundsInScreen());
- }
- TEST_F(PersistentWindowControllerTest, NormalMirrorMode) {
- UpdateDisplay("500x600,500x600");
- aura::Window* w1 =
- CreateTestWindowInShellWithBounds(gfx::Rect(200, 0, 100, 200));
- aura::Window* w2 =
- CreateTestWindowInShellWithBounds(gfx::Rect(501, 0, 200, 100));
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- // Enables mirror mode.
- display_manager()->SetMirrorMode(display::MirrorMode::kNormal, absl::nullopt);
- EXPECT_TRUE(display_manager()->IsInMirrorMode());
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- // Disables mirror mode.
- display_manager()->SetMirrorMode(display::MirrorMode::kOff, absl::nullopt);
- EXPECT_FALSE(display_manager()->IsInMirrorMode());
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- }
- TEST_F(PersistentWindowControllerTest, MixedMirrorMode) {
- UpdateDisplay("500x600,500x600,500x600");
- aura::Window* w1 =
- CreateTestWindowInShellWithBounds(gfx::Rect(200, 0, 100, 200));
- aura::Window* w2 =
- CreateTestWindowInShellWithBounds(gfx::Rect(501, 0, 200, 100));
- aura::Window* w3 =
- CreateTestWindowInShellWithBounds(gfx::Rect(1002, 0, 400, 200));
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1002, 0, 400, 200), w3->GetBoundsInScreen());
- const int64_t primary_id = display_manager()->GetDisplayAt(0).id();
- const int64_t second_id = display_manager()->GetDisplayAt(1).id();
- const int64_t third_id = display_manager()->GetDisplayAt(2).id();
- display::ManagedDisplayInfo primary_info =
- display_manager()->GetDisplayInfo(primary_id);
- display::ManagedDisplayInfo second_info =
- display_manager()->GetDisplayInfo(second_id);
- display::ManagedDisplayInfo third_info =
- display_manager()->GetDisplayInfo(third_id);
- // Turn on mixed mirror mode. (Mirror from the primary display to the second
- // display).
- display::DisplayIdList dst_ids;
- dst_ids.emplace_back(second_id);
- display_manager()->SetMirrorMode(
- display::MirrorMode::kMixed,
- absl::make_optional<display::MixedMirrorModeParams>(primary_id, dst_ids));
- EXPECT_TRUE(display_manager()->IsInMirrorMode());
- EXPECT_TRUE(display_manager()->mixed_mirror_mode_params());
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(502, 0, 400, 200), w3->GetBoundsInScreen());
- // Turn off mixed mirror mode.
- display_manager()->SetMirrorMode(display::MirrorMode::kOff, absl::nullopt);
- EXPECT_FALSE(display_manager()->IsInMirrorMode());
- EXPECT_FALSE(display_manager()->mixed_mirror_mode_params());
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1002, 0, 400, 200), w3->GetBoundsInScreen());
- }
- TEST_F(PersistentWindowControllerTest, WindowMovedByAccel) {
- UpdateDisplay("500x600,500x600");
- aura::Window* w1 =
- CreateTestWindowInShellWithBounds(gfx::Rect(200, 0, 100, 200));
- aura::Window* w2 =
- CreateTestWindowInShellWithBounds(gfx::Rect(501, 0, 200, 100));
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- const int64_t primary_id = WindowTreeHostManager::GetPrimaryDisplayId();
- const int64_t secondary_id =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id();
- display::ManagedDisplayInfo primary_info =
- display_manager()->GetDisplayInfo(primary_id);
- display::ManagedDisplayInfo secondary_info =
- display_manager()->GetDisplayInfo(secondary_id);
- // Disconnects secondary display.
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- // Reconnects secondary display.
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- // Moves |w2| to primary display by accelerators after we reset the persistent
- // window info. It should be able to save persistent window info again on next
- // display change.
- wm::ActivateWindow(w2);
- display_move_window_util::HandleMoveActiveWindowBetweenDisplays();
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- // Disconnects secondary display.
- display_info_list.clear();
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- // Reconnects secondary display.
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- }
- TEST_F(PersistentWindowControllerTest, ReconnectOnLockScreen) {
- UpdateDisplay("500x600,500x600");
- aura::Window* w1 =
- CreateTestWindowInShellWithBounds(gfx::Rect(200, 0, 100, 200));
- aura::Window* w2 =
- CreateTestWindowInShellWithBounds(gfx::Rect(501, 0, 200, 100));
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- const int64_t primary_id = WindowTreeHostManager::GetPrimaryDisplayId();
- const int64_t secondary_id =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id();
- display::ManagedDisplayInfo primary_info =
- display_manager()->GetDisplayInfo(primary_id);
- display::ManagedDisplayInfo secondary_info =
- display_manager()->GetDisplayInfo(secondary_id);
- // Disconnects secondary display.
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- // Spin a run loop to ensure shelf is deleted. https://crbug.com/810807.
- base::RunLoop().RunUntilIdle();
- // Enters locked session state and reconnects secondary display.
- GetSessionControllerClient()->SetSessionState(SessionState::LOCKED);
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- // Unlocks and checks that |w2| is restored.
- GetSessionControllerClient()->SetSessionState(SessionState::ACTIVE);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- }
- TEST_F(PersistentWindowControllerTest, RecordNumOfWindowsRestored) {
- UpdateDisplay("500x600,500x600");
- aura::Window* w1 =
- CreateTestWindowInShellWithBounds(gfx::Rect(200, 0, 100, 200));
- aura::Window* w2 =
- CreateTestWindowInShellWithBounds(gfx::Rect(501, 0, 200, 100));
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- const int64_t primary_id = WindowTreeHostManager::GetPrimaryDisplayId();
- const int64_t secondary_id =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id();
- display::ManagedDisplayInfo primary_info =
- display_manager()->GetDisplayInfo(primary_id);
- display::ManagedDisplayInfo secondary_info =
- display_manager()->GetDisplayInfo(secondary_id);
- // Disconnects secondary display.
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- base::HistogramTester histogram_tester;
- histogram_tester.ExpectTotalCount(
- PersistentWindowController::kNumOfWindowsRestoredOnDisplayAdded, 0);
- // Reconnects secondary display.
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- histogram_tester.ExpectTotalCount(
- PersistentWindowController::kNumOfWindowsRestoredOnDisplayAdded, 1);
- }
- // Tests that swapping primary display shall not do persistent window restore.
- TEST_F(PersistentWindowControllerTest, SwapPrimaryDisplay) {
- const int64_t internal_display_id =
- display::test::DisplayManagerTestApi(display_manager())
- .SetFirstDisplayAsInternalDisplay();
- const display::ManagedDisplayInfo native_display_info =
- display::CreateDisplayInfo(internal_display_id,
- gfx::Rect(0, 0, 500, 600));
- const display::ManagedDisplayInfo secondary_display_info =
- display::CreateDisplayInfo(10, gfx::Rect(1, 1, 400, 500));
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(native_display_info);
- display_info_list.push_back(secondary_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- aura::Window* w1 =
- CreateTestWindowInShellWithBounds(gfx::Rect(200, 0, 100, 200));
- aura::Window* w2 =
- CreateTestWindowInShellWithBounds(gfx::Rect(501, 0, 200, 100));
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(501, 0, 200, 100), w2->GetBoundsInScreen());
- // Swaps primary display and check window bounds.
- SwapPrimaryDisplay();
- ASSERT_EQ(gfx::Rect(-500, 0, 500, 600),
- display_manager()->GetDisplayForId(internal_display_id).bounds());
- ASSERT_EQ(gfx::Rect(0, 0, 400, 500),
- display_manager()->GetDisplayForId(10).bounds());
- EXPECT_EQ(gfx::Rect(200, 0, 100, 200), w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(-499, 0, 200, 100), w2->GetBoundsInScreen());
- }
- // Tests that restore bounds persist after adding and removing a display.
- TEST_F(PersistentWindowControllerTest, RestoreBounds) {
- UpdateDisplay("500x600,500x600");
- std::unique_ptr<aura::Window> window = CreateTestWindow(gfx::Rect(200, 200));
- const int64_t primary_id = WindowTreeHostManager::GetPrimaryDisplayId();
- const int64_t secondary_id =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id();
- display::Screen* screen = display::Screen::GetScreen();
- ASSERT_EQ(primary_id, screen->GetDisplayNearestWindow(window.get()).id());
- // Move the window to the secondary display and maximize it.
- display_move_window_util::HandleMoveActiveWindowBetweenDisplays();
- ASSERT_EQ(secondary_id, screen->GetDisplayNearestWindow(window.get()).id());
- WindowState* window_state = WindowState::Get(window.get());
- window_state->Maximize();
- EXPECT_TRUE(window_state->HasRestoreBounds());
- const gfx::Rect restore_bounds_in_screen =
- window_state->GetRestoreBoundsInScreen();
- display::ManagedDisplayInfo primary_info =
- display_manager()->GetDisplayInfo(primary_id);
- display::ManagedDisplayInfo secondary_info =
- display_manager()->GetDisplayInfo(secondary_id);
- // Disconnect secondary display.
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(primary_id, screen->GetDisplayNearestWindow(window.get()).id());
- // Reconnect secondary display. On restoring the maximized window, the bounds
- // should be the same as they were before maximizing and disconnecting the
- // display.
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(secondary_id, screen->GetDisplayNearestWindow(window.get()).id());
- EXPECT_TRUE(window_state->IsMaximized());
- // Restore the window (i.e. press restore button on header).
- window_state->Restore();
- EXPECT_TRUE(window_state->IsNormalStateType());
- EXPECT_EQ(restore_bounds_in_screen, window->GetBoundsInScreen());
- }
- // Tests that the MRU order is maintained visually after adding and removing a
- // display.
- TEST_F(PersistentWindowControllerTest, MRUOrderMatchesStacking) {
- UpdateDisplay("500x600,500x600");
- // Add three windows, all on the secondary display.
- const gfx::Rect bounds(500, 0, 200, 200);
- std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds);
- std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds);
- std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds);
- // MRU order should be opposite of the order the windows were created. Verify
- // that all three windows are indeed on the secondary display.
- const int64_t primary_id = WindowTreeHostManager::GetPrimaryDisplayId();
- const int64_t secondary_id =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id();
- display::Screen* screen = display::Screen::GetScreen();
- const std::vector<aura::Window*> expected_mru_order = {
- window3.get(), window2.get(), window1.get()};
- ASSERT_EQ(
- expected_mru_order,
- Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kAllDesks));
- for (auto* window : expected_mru_order)
- ASSERT_EQ(secondary_id, screen->GetDisplayNearestWindow(window).id());
- // Disconnect secondary display. The windows should move to the primary
- // display and retain MRU ordering.
- display::ManagedDisplayInfo primary_info =
- display_manager()->GetDisplayInfo(primary_id);
- display::ManagedDisplayInfo secondary_info =
- display_manager()->GetDisplayInfo(secondary_id);
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- // The order which the children are stacked in is the reverse of the order
- // they are in the children() field.
- aura::Window* parent = window1->parent();
- ASSERT_TRUE(parent);
- std::vector<aura::Window*> children_ordered_by_stacking = parent->children();
- std::reverse(children_ordered_by_stacking.begin(),
- children_ordered_by_stacking.end());
- EXPECT_EQ(
- expected_mru_order,
- Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kAllDesks));
- EXPECT_EQ(expected_mru_order, children_ordered_by_stacking);
- EXPECT_EQ(primary_id, screen->GetDisplayNearestWindow(parent).id());
- // Reconnect secondary display. The windows should move to the secondary
- // display and retain MRU ordering.
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- parent = window1->parent();
- children_ordered_by_stacking = parent->children();
- std::reverse(children_ordered_by_stacking.begin(),
- children_ordered_by_stacking.end());
- ASSERT_TRUE(parent);
- EXPECT_EQ(
- expected_mru_order,
- Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kAllDesks));
- EXPECT_EQ(expected_mru_order, children_ordered_by_stacking);
- EXPECT_EQ(secondary_id, screen->GetDisplayNearestWindow(parent).id());
- }
- // Similar to the above test but with windows created on both displays.
- TEST_F(PersistentWindowControllerTest, MRUOrderMatchesStackingInterleaved) {
- UpdateDisplay("500x600,500x600");
- // Add four windows, two on each display.
- const gfx::Rect primary_bounds(200, 200);
- const gfx::Rect secondary_bounds(500, 0, 200, 200);
- std::unique_ptr<aura::Window> window1 = CreateTestWindow(primary_bounds);
- std::unique_ptr<aura::Window> window2 = CreateTestWindow(secondary_bounds);
- std::unique_ptr<aura::Window> window3 = CreateTestWindow(primary_bounds);
- std::unique_ptr<aura::Window> window4 = CreateTestWindow(secondary_bounds);
- // MRU order should be opposite of the order the windows were created.
- const int64_t primary_id = WindowTreeHostManager::GetPrimaryDisplayId();
- const int64_t secondary_id =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id();
- display::Screen* screen = display::Screen::GetScreen();
- const std::vector<aura::Window*> expected_mru_order = {
- window4.get(), window3.get(), window2.get(), window1.get()};
- ASSERT_EQ(
- expected_mru_order,
- Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kAllDesks));
- // Disconnect secondary display. The windows should move to the primary
- // display and retain MRU ordering. Note that this logic is part of
- // RootWindowController and not PersistentWindowController.
- display::ManagedDisplayInfo primary_info =
- display_manager()->GetDisplayInfo(primary_id);
- display::ManagedDisplayInfo secondary_info =
- display_manager()->GetDisplayInfo(secondary_id);
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- // The order which the children are stacked in is the reverse of the order
- // they are in the children() field.
- aura::Window* parent = window1->parent();
- ASSERT_TRUE(parent);
- ASSERT_EQ(parent, window2->parent());
- std::vector<aura::Window*> children_ordered_by_stacking = parent->children();
- std::reverse(children_ordered_by_stacking.begin(),
- children_ordered_by_stacking.end());
- EXPECT_EQ(
- expected_mru_order,
- Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kAllDesks));
- EXPECT_EQ(expected_mru_order, children_ordered_by_stacking);
- EXPECT_EQ(primary_id, screen->GetDisplayNearestWindow(parent).id());
- // Reconnect secondary display. |window2| and |window4| should move back to
- // the secondary display.
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(
- expected_mru_order,
- Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kAllDesks));
- parent = window1->parent();
- EXPECT_EQ(primary_id, screen->GetDisplayNearestWindow(parent).id());
- ASSERT_EQ(2u, parent->children().size());
- EXPECT_EQ(window1.get(), parent->children()[0]);
- EXPECT_EQ(window3.get(), parent->children()[1]);
- parent = window2->parent();
- EXPECT_EQ(secondary_id, screen->GetDisplayNearestWindow(parent).id());
- ASSERT_EQ(2u, parent->children().size());
- EXPECT_EQ(window2.get(), parent->children()[0]);
- EXPECT_EQ(window4.get(), parent->children()[1]);
- }
- // Tests that if a window is on a primary display which gets disconnected, on
- // reconnect the windows bounds will be persisted.
- TEST_F(PersistentWindowControllerTest, DisconnectingPrimaryDisplay) {
- // Create two displays with the one higher resolution.
- UpdateDisplay("500x600,1500x500");
- const int64_t small_id = WindowTreeHostManager::GetPrimaryDisplayId();
- const int64_t large_id =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id();
- // Set the larger display to be the primary display.
- Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId(large_id);
- ASSERT_EQ(large_id, WindowTreeHostManager::GetPrimaryDisplayId());
- // Add a window on the larger display.
- const gfx::Rect bounds(0, 200, 1500, 200);
- std::unique_ptr<aura::Window> window = CreateTestWindow(bounds);
- // Disconnect the large display. The windows should move to the new primary
- // display (small display) and shrink to fit.
- display::ManagedDisplayInfo small_info =
- display_manager()->GetDisplayInfo(small_id);
- display::ManagedDisplayInfo large_info =
- display_manager()->GetDisplayInfo(large_id);
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(small_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(small_id, WindowTreeHostManager::GetPrimaryDisplayId());
- EXPECT_EQ(gfx::Size(500, 200), window->bounds().size());
- // Reconnect the large display. The window should move back and have the old
- // size.
- display_info_list.push_back(large_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(large_id, WindowTreeHostManager::GetPrimaryDisplayId());
- EXPECT_EQ(gfx::Size(1500, 200), window->bounds().size());
- }
- TEST_F(PersistentWindowControllerTest, RestoreBoundsOnScreenRotation) {
- UpdateDisplay("800x600");
- display::test::DisplayManagerTestApi(display_manager())
- .SetFirstDisplayAsInternalDisplay();
- gfx::Rect bounds_in_landscape = gfx::Rect(420, 200, 200, 100);
- aura::Window* w1 = CreateTestWindowInShellWithBounds(bounds_in_landscape);
- ScreenOrientationControllerTestApi test_api(
- Shell::Get()->screen_orientation_controller());
- test_api.SetDisplayRotation(display::Display::ROTATE_0,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapePrimary);
- EXPECT_EQ(bounds_in_landscape, w1->GetBoundsInScreen());
- // The window should be fully visible after rotation.
- base::HistogramTester histogram_tester;
- test_api.SetDisplayRotation(display::Display::ROTATE_270,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kPortraitPrimary);
- gfx::Rect bounds_in_portrait = w1->GetBoundsInScreen();
- EXPECT_NE(bounds_in_landscape, bounds_in_portrait);
- EXPECT_TRUE(GetPrimaryDisplay().bounds().Contains(bounds_in_portrait));
- histogram_tester.ExpectTotalCount(
- PersistentWindowController::kNumOfWindowsRestoredOnScreenRotation, 0);
- // The window's bounds should be restored after rotated back to landscape
- // primary.
- test_api.SetDisplayRotation(display::Display::ROTATE_0,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapePrimary);
- EXPECT_EQ(bounds_in_landscape, w1->GetBoundsInScreen());
- histogram_tester.ExpectTotalCount(
- PersistentWindowController::kNumOfWindowsRestoredOnScreenRotation, 1);
- // Update window's bounds in portrait primary.
- auto* window_state = WindowState::Get(w1);
- test_api.SetDisplayRotation(display::Display::ROTATE_270,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kPortraitPrimary);
- EXPECT_EQ(bounds_in_portrait, w1->GetBoundsInScreen());
- w1->SetBounds(gfx::Rect(
- gfx::Point(bounds_in_portrait.x() - 100, bounds_in_portrait.y() - 100),
- bounds_in_portrait.size()));
- window_state->set_bounds_changed_by_user(true);
- bounds_in_portrait = w1->GetBoundsInScreen();
- EXPECT_FALSE(window_state->persistent_window_info_of_screen_rotation());
- // The window's bounds should not be restored after rotated to landscape
- // secondary, since the window's bounds has been changed by user.
- test_api.SetDisplayRotation(display::Display::ROTATE_180,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapeSecondary);
- EXPECT_NE(bounds_in_landscape, w1->GetBoundsInScreen());
- bounds_in_landscape = w1->GetBoundsInScreen();
- // The window's bounds should be the same as its bounds in portrait primary
- // after rotated to portrait secondary.
- test_api.SetDisplayRotation(display::Display::ROTATE_90,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kPortraitSecondary);
- EXPECT_EQ(bounds_in_portrait, w1->GetBoundsInScreen());
- // The window's bounds should be the same as its bounds in landscape secondary
- // after rotated to landscape primary.
- test_api.SetDisplayRotation(display::Display::ROTATE_0,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapePrimary);
- EXPECT_EQ(bounds_in_landscape, w1->GetBoundsInScreen());
- }
- TEST_F(PersistentWindowControllerTest, RotationOnLockScreen) {
- UpdateDisplay("800x600");
- display::test::DisplayManagerTestApi(display_manager())
- .SetFirstDisplayAsInternalDisplay();
- const gfx::Rect bounds_in_landscape = gfx::Rect(420, 200, 200, 100);
- aura::Window* w1 = CreateTestWindowInShellWithBounds(bounds_in_landscape);
- ScreenOrientationControllerTestApi test_api(
- Shell::Get()->screen_orientation_controller());
- test_api.SetDisplayRotation(display::Display::ROTATE_0,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapePrimary);
- EXPECT_EQ(bounds_in_landscape, w1->GetBoundsInScreen());
- // Rotates to portrait primary.
- test_api.SetDisplayRotation(display::Display::ROTATE_270,
- display::Display::RotationSource::ACTIVE);
- // Enters locked session state and rotates the screen back to landscape
- // primary.
- GetSessionControllerClient()->SetSessionState(SessionState::LOCKED);
- test_api.SetDisplayRotation(display::Display::ROTATE_0,
- display::Display::RotationSource::ACTIVE);
- // Unlocks and checks that `w1` is restored.
- GetSessionControllerClient()->SetSessionState(SessionState::ACTIVE);
- EXPECT_EQ(bounds_in_landscape, w1->GetBoundsInScreen());
- }
- TEST_F(PersistentWindowControllerTest, RotationOnDisplayReconnecting) {
- UpdateDisplay("500x600,500x600");
- display::test::DisplayManagerTestApi(display_manager())
- .SetFirstDisplayAsInternalDisplay();
- ScreenOrientationControllerTestApi test_api(
- Shell::Get()->screen_orientation_controller());
- const gfx::Rect w1_bounds_in_landscape = gfx::Rect(200, 0, 100, 200);
- const gfx::Rect w2_bounds_in_second_display = gfx::Rect(501, 0, 200, 100);
- aura::Window* w1 = CreateTestWindowInShellWithBounds(w1_bounds_in_landscape);
- aura::Window* w2 =
- CreateTestWindowInShellWithBounds(w2_bounds_in_second_display);
- const int64_t primary_id = WindowTreeHostManager::GetPrimaryDisplayId();
- const int64_t secondary_id =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id();
- display::ManagedDisplayInfo primary_info =
- display_manager()->GetDisplayInfo(primary_id);
- display::ManagedDisplayInfo secondary_info =
- display_manager()->GetDisplayInfo(secondary_id);
- // Disconnects secondary display.
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(primary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(w1_bounds_in_landscape, w1->GetBoundsInScreen());
- EXPECT_EQ(gfx::Rect(1, 0, 200, 100), w2->GetBoundsInScreen());
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapePrimary);
- test_api.SetDisplayRotation(display::Display::ROTATE_270,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kPortraitPrimary);
- // Reconnects secondary display, `w2` should be restored.
- display_info_list.push_back(secondary_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(w2_bounds_in_second_display, w2->GetBoundsInScreen());
- // Rotates the internal display back to landscape primary.
- test_api.SetDisplayRotation(display::Display::ROTATE_0,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(w1_bounds_in_landscape, w1->GetBoundsInScreen());
- }
- TEST_F(PersistentWindowControllerTest, NoRestoreOnRotationForSnappedWindows) {
- UpdateDisplay("800x600");
- display::test::DisplayManagerTestApi(display_manager())
- .SetFirstDisplayAsInternalDisplay();
- ScreenOrientationControllerTestApi test_api(
- Shell::Get()->screen_orientation_controller());
- test_api.SetDisplayRotation(display::Display::ROTATE_0,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapePrimary);
- aura::Window* w1 =
- CreateTestWindowInShellWithBounds(gfx::Rect(0, 0, 200, 200));
- auto* split_view_controller =
- SplitViewController::Get(Shell::GetPrimaryRootWindow());
- // Snap the unique window in clamshell mode will not enter split view mode.
- WindowSnapWMEvent wm_left_snap_event(WM_EVENT_SNAP_PRIMARY);
- auto* window_state = WindowState::Get(w1);
- window_state->OnWMEvent(&wm_left_snap_event);
- EXPECT_FALSE(split_view_controller->InSplitViewMode());
- EXPECT_TRUE(window_state->IsSnapped());
- EXPECT_EQ(chromeos::WindowStateType::kPrimarySnapped,
- window_state->GetStateType());
- const gfx::Rect bounds_in_landscape_primary = w1->GetBoundsInScreen();
- EXPECT_EQ(0, bounds_in_landscape_primary.x());
- // Snapped window should not have persistent window info on screen rotation
- // so its bounds will not be restored.
- test_api.SetDisplayRotation(display::Display::ROTATE_90,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kPortraitSecondary);
- EXPECT_FALSE(window_state->persistent_window_info_of_screen_rotation());
- // Snapped window's bounds should not be restored on screen rotation. The
- // primary snapped window in landscape primary should still be primary snapped
- // after rotated to landscape secondary, and be kept at the right side of the
- // screen.
- test_api.SetDisplayRotation(display::Display::ROTATE_180,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(test_api.GetCurrentOrientation(),
- chromeos::OrientationType::kLandscapeSecondary);
- EXPECT_FALSE(window_state->persistent_window_info_of_screen_rotation());
- EXPECT_TRUE(window_state->IsSnapped());
- EXPECT_EQ(chromeos::WindowStateType::kPrimarySnapped,
- window_state->GetStateType());
- const gfx::Rect bounds_in_landscape_secondary = w1->GetBoundsInScreen();
- EXPECT_NE(bounds_in_landscape_primary, bounds_in_landscape_secondary);
- EXPECT_NE(0, bounds_in_landscape_secondary.x());
- EXPECT_EQ(
- bounds_in_landscape_secondary.right(),
- screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(w1)
- .right());
- }
- } // namespace ash
|