12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937 |
- // Copyright (c) 2012 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/window_tree_host_manager.h"
- #include <memory>
- #include "ash/display/display_util.h"
- #include "ash/public/cpp/shelf_config.h"
- #include "ash/screen_util.h"
- #include "ash/shelf/shelf.h"
- #include "ash/shelf/shelf_widget.h"
- #include "ash/shell.h"
- #include "ash/test/ash_test_base.h"
- #include "ash/test/ash_test_helper.h"
- #include "ash/test/test_widget_builder.h"
- #include "ash/test_shell_delegate.h"
- #include "ash/wm/cursor_manager_test_api.h"
- #include "ash/wm/window_state.h"
- #include "ash/wm/wm_event.h"
- #include "base/command_line.h"
- #include "base/run_loop.h"
- #include "base/test/scoped_feature_list.h"
- #include "ui/aura/client/focus_change_observer.h"
- #include "ui/aura/client/focus_client.h"
- #include "ui/aura/env.h"
- #include "ui/aura/window_observer.h"
- #include "ui/aura/window_tracker.h"
- #include "ui/aura/window_tree_host.h"
- #include "ui/base/cursor/cursor.h"
- #include "ui/compositor/layer.h"
- #include "ui/display/display.h"
- #include "ui/display/display_features.h"
- #include "ui/display/display_layout.h"
- #include "ui/display/display_layout_builder.h"
- #include "ui/display/display_observer.h"
- #include "ui/display/display_switches.h"
- #include "ui/display/manager/display_layout_store.h"
- #include "ui/display/manager/display_manager.h"
- #include "ui/display/manager/managed_display_info.h"
- #include "ui/display/screen.h"
- #include "ui/display/test/display_manager_test_api.h"
- #include "ui/events/event_handler.h"
- #include "ui/events/keycodes/keyboard_codes.h"
- #include "ui/events/test/event_generator.h"
- #include "ui/events/types/event_type.h"
- #include "ui/gfx/geometry/rounded_corners_f.h"
- #include "ui/views/event_monitor.h"
- #include "ui/views/mouse_watcher.h"
- #include "ui/views/mouse_watcher_view_host.h"
- #include "ui/views/view.h"
- #include "ui/views/widget/widget.h"
- #include "ui/wm/core/cursor_manager.h"
- #include "ui/wm/public/activation_change_observer.h"
- #include "ui/wm/public/activation_client.h"
- namespace ash {
- namespace {
- const char kWallpaperView[] = "WallpaperViewWidget";
- template <typename T>
- class Resetter {
- public:
- explicit Resetter(T* value) : value_(*value) { *value = 0; }
- Resetter(const Resetter&) = delete;
- Resetter& operator=(const Resetter&) = delete;
- ~Resetter() = default;
- T value() { return value_; }
- private:
- T value_;
- };
- class TestObserver : public WindowTreeHostManager::Observer,
- public display::DisplayObserver,
- public aura::client::FocusChangeObserver,
- public ::wm::ActivationChangeObserver {
- public:
- TestObserver() {
- Shell::Get()->window_tree_host_manager()->AddObserver(this);
- aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())
- ->AddObserver(this);
- ::wm::GetActivationClient(Shell::GetPrimaryRootWindow())->AddObserver(this);
- }
- TestObserver(const TestObserver&) = delete;
- TestObserver& operator=(const TestObserver&) = delete;
- ~TestObserver() override {
- Shell::Get()->window_tree_host_manager()->RemoveObserver(this);
- aura::client::GetFocusClient(Shell::GetPrimaryRootWindow())
- ->RemoveObserver(this);
- ::wm::GetActivationClient(Shell::GetPrimaryRootWindow())
- ->RemoveObserver(this);
- }
- // Overridden from WindowTreeHostManager::Observer
- void OnDisplayConfigurationChanging() override { ++changing_count_; }
- void OnDisplayConfigurationChanged() override { ++changed_count_; }
- // Overrideen from display::DisplayObserver
- void OnDisplayMetricsChanged(const display::Display& display,
- uint32_t metrics) override {
- changed_display_id_ = display.id();
- if (metrics & DISPLAY_METRIC_BOUNDS)
- ++bounds_changed_count_;
- if (metrics & DISPLAY_METRIC_ROTATION)
- ++rotation_changed_count_;
- if (metrics & DISPLAY_METRIC_WORK_AREA)
- ++workarea_changed_count_;
- if (metrics & DISPLAY_METRIC_PRIMARY)
- ++primary_changed_count_;
- }
- // Overridden from aura::client::FocusChangeObserver
- void OnWindowFocused(aura::Window* gained_focus,
- aura::Window* lost_focus) override {
- focus_changed_count_++;
- }
- // Overridden from wm::ActivationChangeObserver
- void OnWindowActivated(
- ::wm::ActivationChangeObserver::ActivationReason reason,
- aura::Window* gained_active,
- aura::Window* lost_active) override {
- activation_changed_count_++;
- }
- void OnAttemptToReactivateWindow(aura::Window* request_active,
- aura::Window* actual_active) override {}
- int CountAndReset() {
- EXPECT_EQ(changing_count_, changed_count_);
- changed_count_ = 0;
- return Resetter<int>(&changing_count_).value();
- }
- int64_t GetBoundsChangedCountAndReset() {
- return Resetter<int>(&bounds_changed_count_).value();
- }
- int64_t GetRotationChangedCountAndReset() {
- return Resetter<int>(&rotation_changed_count_).value();
- }
- int64_t GetWorkareaChangedCountAndReset() {
- return Resetter<int>(&workarea_changed_count_).value();
- }
- int64_t GetPrimaryChangedCountAndReset() {
- return Resetter<int>(&primary_changed_count_).value();
- }
- int64_t GetChangedDisplayIdAndReset() {
- return Resetter<int64_t>(&changed_display_id_).value();
- }
- int GetFocusChangedCountAndReset() {
- return Resetter<int>(&focus_changed_count_).value();
- }
- int GetActivationChangedCountAndReset() {
- return Resetter<int>(&activation_changed_count_).value();
- }
- private:
- int changing_count_ = 0;
- int changed_count_ = 0;
- int bounds_changed_count_ = 0;
- int rotation_changed_count_ = 0;
- int workarea_changed_count_ = 0;
- int primary_changed_count_ = 0;
- int64_t changed_display_id_ = 0;
- int focus_changed_count_ = 0;
- int activation_changed_count_ = 0;
- display::ScopedDisplayObserver display_observer_{this};
- };
- class TestHelper {
- public:
- explicit TestHelper(AshTestBase* delegate);
- TestHelper(const TestHelper&) = delete;
- TestHelper& operator=(const TestHelper&) = delete;
- ~TestHelper();
- void SetSecondaryDisplayLayoutAndOffset(
- display::DisplayPlacement::Position position,
- int offset);
- void SetSecondaryDisplayLayout(display::DisplayPlacement::Position position);
- void SetDefaultDisplayLayout(display::DisplayPlacement::Position position);
- float GetStoredZoomScale(int64_t id);
- private:
- AshTestBase* delegate_; // Not owned
- };
- TestHelper::TestHelper(AshTestBase* delegate) : delegate_(delegate) {}
- TestHelper::~TestHelper() = default;
- void TestHelper::SetSecondaryDisplayLayoutAndOffset(
- display::DisplayPlacement::Position position,
- int offset) {
- std::unique_ptr<display::DisplayLayout> layout(
- display::test::CreateDisplayLayout(delegate_->display_manager(), position,
- offset));
- ASSERT_GT(display::Screen::GetScreen()->GetNumDisplays(), 1);
- delegate_->display_manager()->SetLayoutForCurrentDisplays(std::move(layout));
- }
- void TestHelper::SetSecondaryDisplayLayout(
- display::DisplayPlacement::Position position) {
- SetSecondaryDisplayLayoutAndOffset(position, 0);
- }
- void TestHelper::SetDefaultDisplayLayout(
- display::DisplayPlacement::Position position) {
- display::DisplayPlacement default_placement(position, 0);
- delegate_->display_manager()->layout_store()->SetDefaultDisplayPlacement(
- default_placement);
- }
- float TestHelper::GetStoredZoomScale(int64_t id) {
- return delegate_->display_manager()->GetDisplayInfo(id).zoom_factor();
- }
- class WindowTreeHostManagerShutdownTest : public AshTestBase,
- public TestHelper {
- public:
- WindowTreeHostManagerShutdownTest() : TestHelper(this) {}
- WindowTreeHostManagerShutdownTest(const WindowTreeHostManagerShutdownTest&) =
- delete;
- WindowTreeHostManagerShutdownTest& operator=(
- const WindowTreeHostManagerShutdownTest&) = delete;
- ~WindowTreeHostManagerShutdownTest() override = default;
- void TearDown() override {
- AshTestBase::TearDown();
- // Make sure that primary display is accessible after shutdown.
- display::Display primary =
- display::Screen::GetScreen()->GetPrimaryDisplay();
- EXPECT_EQ(gfx::Rect(0, 0, 444, 333), primary.bounds());
- EXPECT_EQ(2, display::Screen::GetScreen()->GetNumDisplays());
- }
- };
- class WindowTreeHostManagerStartupTest : public AshTestBase, public TestHelper {
- public:
- WindowTreeHostManagerStartupTest() : TestHelper(this) {}
- WindowTreeHostManagerStartupTest(const WindowTreeHostManagerStartupTest&) =
- delete;
- WindowTreeHostManagerStartupTest& operator=(
- const WindowTreeHostManagerStartupTest&) = delete;
- ~WindowTreeHostManagerStartupTest() override = default;
- };
- class TestEventHandler : public ui::EventHandler {
- public:
- TestEventHandler()
- : target_root_(nullptr),
- touch_radius_x_(0.0),
- touch_radius_y_(0.0),
- scroll_x_offset_(0.0),
- scroll_y_offset_(0.0),
- scroll_x_offset_ordinal_(0.0),
- scroll_y_offset_ordinal_(0.0) {}
- TestEventHandler(const TestEventHandler&) = delete;
- TestEventHandler& operator=(const TestEventHandler&) = delete;
- ~TestEventHandler() override = default;
- void OnMouseEvent(ui::MouseEvent* event) override {
- if (event->flags() & ui::EF_IS_SYNTHESIZED &&
- event->type() != ui::ET_MOUSE_EXITED &&
- event->type() != ui::ET_MOUSE_ENTERED) {
- return;
- }
- aura::Window* target = static_cast<aura::Window*>(event->target());
- mouse_location_ = event->root_location();
- target_root_ = target->GetRootWindow();
- event->StopPropagation();
- }
- void OnTouchEvent(ui::TouchEvent* event) override {
- aura::Window* target = static_cast<aura::Window*>(event->target());
- // Only record when the target is the wallpaper, which covers the entire
- // root window.
- if (target->GetName() != kWallpaperView)
- return;
- touch_radius_x_ = event->pointer_details().radius_x;
- touch_radius_y_ = event->pointer_details().radius_y;
- event->StopPropagation();
- }
- void OnScrollEvent(ui::ScrollEvent* event) override {
- aura::Window* target = static_cast<aura::Window*>(event->target());
- // Only record when the target is the wallpaper, which covers the entire
- // root window.
- if (target->GetName() != kWallpaperView)
- return;
- if (event->type() == ui::ET_SCROLL) {
- scroll_x_offset_ = event->x_offset();
- scroll_y_offset_ = event->y_offset();
- scroll_x_offset_ordinal_ = event->x_offset_ordinal();
- scroll_y_offset_ordinal_ = event->y_offset_ordinal();
- }
- event->StopPropagation();
- }
- gfx::Point GetLocationAndReset() {
- gfx::Point result = mouse_location_;
- mouse_location_.SetPoint(0, 0);
- target_root_ = nullptr;
- return result;
- }
- float touch_radius_x() { return touch_radius_x_; }
- float touch_radius_y() { return touch_radius_y_; }
- float scroll_x_offset() { return scroll_x_offset_; }
- float scroll_y_offset() { return scroll_y_offset_; }
- float scroll_x_offset_ordinal() { return scroll_x_offset_ordinal_; }
- float scroll_y_offset_ordinal() { return scroll_y_offset_ordinal_; }
- private:
- gfx::Point mouse_location_;
- aura::Window* target_root_;
- float touch_radius_x_;
- float touch_radius_y_;
- float scroll_x_offset_;
- float scroll_y_offset_;
- float scroll_x_offset_ordinal_;
- float scroll_y_offset_ordinal_;
- };
- class TestMouseWatcherListener : public views::MouseWatcherListener {
- public:
- TestMouseWatcherListener() = default;
- TestMouseWatcherListener(const TestMouseWatcherListener&) = delete;
- TestMouseWatcherListener& operator=(const TestMouseWatcherListener&) = delete;
- private:
- // views::MouseWatcherListener:
- void MouseMovedOutOfHost() override {}
- };
- } // namespace
- class WindowTreeHostManagerTest : public AshTestBase, public TestHelper {
- public:
- WindowTreeHostManagerTest() : TestHelper(this) {}
- WindowTreeHostManagerTest(const WindowTreeHostManagerTest&) = delete;
- WindowTreeHostManagerTest& operator=(const WindowTreeHostManagerTest&) =
- delete;
- ~WindowTreeHostManagerTest() override = default;
- };
- TEST_F(WindowTreeHostManagerShutdownTest, Shutdown) {
- UpdateDisplay("444x333, 300x200");
- }
- TEST_F(WindowTreeHostManagerStartupTest, Startup) {
- // Ensure that WindowTreeHostManager was initialized and created at least one
- // root window.
- aura::Window::Windows root_windows = Shell::GetAllRootWindows();
- EXPECT_FALSE(root_windows.empty());
- }
- TEST_F(WindowTreeHostManagerTest, SecondaryDisplayLayout) {
- // Creates windows to catch activation change event.
- std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
- w1->Focus();
- TestObserver observer;
- UpdateDisplay("600x500,500x400");
- EXPECT_EQ(1, observer.CountAndReset()); // resize and add
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(2, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- gfx::Insets insets(5);
- int64_t secondary_display_id =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id();
- display_manager()->UpdateWorkAreaOfDisplay(secondary_display_id, insets);
- // Default layout is RIGHT.
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(600, 0, 500, 400), GetSecondaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(605, 5, 490, 390), GetSecondaryDisplay().work_area());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- // Layout the secondary display to the bottom of the primary.
- SetSecondaryDisplayLayout(display::DisplayPlacement::BOTTOM);
- EXPECT_EQ(1, observer.CountAndReset());
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- // TODO (oshima): work area changes twice because ShelfLayoutManager updates
- // to its own insets.
- EXPECT_EQ(2, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(0, 500, 500, 400), GetSecondaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(5, 505, 490, 390), GetSecondaryDisplay().work_area());
- // Layout the secondary display to the left of the primary.
- SetSecondaryDisplayLayout(display::DisplayPlacement::LEFT);
- EXPECT_EQ(1, observer.CountAndReset());
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(-500, 0, 500, 400), GetSecondaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(-495, 5, 490, 390), GetSecondaryDisplay().work_area());
- // Layout the secondary display to the top of the primary.
- SetSecondaryDisplayLayout(display::DisplayPlacement::TOP);
- EXPECT_EQ(1, observer.CountAndReset());
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(0, -400, 500, 400), GetSecondaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(5, -395, 490, 390), GetSecondaryDisplay().work_area());
- // Layout to the right with an offset.
- SetSecondaryDisplayLayoutAndOffset(display::DisplayPlacement::RIGHT, 300);
- EXPECT_EQ(1, observer.CountAndReset()); // resize and add
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(600, 300, 500, 400), GetSecondaryDisplay().bounds());
- // Keep the minimum 100.
- SetSecondaryDisplayLayoutAndOffset(display::DisplayPlacement::RIGHT, 490);
- EXPECT_EQ(1, observer.CountAndReset()); // resize and add
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(600, 400, 500, 400), GetSecondaryDisplay().bounds());
- SetSecondaryDisplayLayoutAndOffset(display::DisplayPlacement::RIGHT, -400);
- EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(1, observer.CountAndReset()); // resize and add
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(600, -300, 500, 400), GetSecondaryDisplay().bounds());
- // Layout to the bottom with an offset.
- SetSecondaryDisplayLayoutAndOffset(display::DisplayPlacement::BOTTOM, -200);
- EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(1, observer.CountAndReset()); // resize and add
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(-200, 500, 500, 400), GetSecondaryDisplay().bounds());
- // Keep the minimum 100.
- SetSecondaryDisplayLayoutAndOffset(display::DisplayPlacement::BOTTOM, 590);
- EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(1, observer.CountAndReset()); // resize and add
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(500, 500, 500, 400), GetSecondaryDisplay().bounds());
- SetSecondaryDisplayLayoutAndOffset(display::DisplayPlacement::BOTTOM, -500);
- EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(1, observer.CountAndReset()); // resize and add
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(-400, 500, 500, 400), GetSecondaryDisplay().bounds());
- // Setting the same layout shouldn't invoke observers.
- SetSecondaryDisplayLayoutAndOffset(display::DisplayPlacement::BOTTOM, -500);
- EXPECT_EQ(0, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(0, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(0, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(0, observer.CountAndReset()); // resize and add
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(-400, 500, 500, 400), GetSecondaryDisplay().bounds());
- UpdateDisplay("600x500");
- EXPECT_LE(1, observer.GetFocusChangedCountAndReset());
- EXPECT_LE(1, observer.GetActivationChangedCountAndReset());
- }
- namespace {
- display::ManagedDisplayInfo
- CreateDisplayInfo(int64_t id, int y, display::Display::Rotation rotation) {
- display::ManagedDisplayInfo info(id, "", false);
- info.SetBounds(gfx::Rect(0, y, 600, 500));
- info.SetRotation(rotation, display::Display::RotationSource::ACTIVE);
- return info;
- }
- display::ManagedDisplayInfo CreateMirroredDisplayInfo(
- int64_t id,
- float device_scale_factor) {
- display::ManagedDisplayInfo info =
- CreateDisplayInfo(id, 0, display::Display::ROTATE_0);
- info.set_device_scale_factor(device_scale_factor);
- return info;
- }
- } // namespace
- TEST_F(WindowTreeHostManagerTest, MirrorToDockedWithFullscreen) {
- // Creates windows to catch activation change event.
- std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
- w1->Focus();
- // Docked mode.
- const display::ManagedDisplayInfo internal_display_info =
- CreateMirroredDisplayInfo(1, 2.0f);
- const display::ManagedDisplayInfo external_display_info =
- CreateMirroredDisplayInfo(2, 1.0f);
- std::vector<display::ManagedDisplayInfo> display_info_list;
- // Mirror.
- display_info_list.push_back(internal_display_info);
- display_info_list.push_back(external_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- const int64_t internal_display_id =
- display::test::DisplayManagerTestApi(display_manager())
- .SetFirstDisplayAsInternalDisplay();
- EXPECT_EQ(1, internal_display_id);
- EXPECT_EQ(2U, display_manager()->num_connected_displays());
- EXPECT_EQ(1U, display_manager()->GetNumDisplays());
- WindowState* window_state = WindowState::Get(w1.get());
- const WMEvent toggle_fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
- window_state->OnWMEvent(&toggle_fullscreen_event);
- EXPECT_TRUE(window_state->IsFullscreen());
- EXPECT_EQ(gfx::Rect(0, 0, 300, 250), w1->bounds());
- // Dock mode.
- TestObserver observer;
- display_info_list.clear();
- display_info_list.push_back(external_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(1U, display_manager()->GetNumDisplays());
- EXPECT_EQ(1U, display_manager()->num_connected_displays());
- // Observers are called due to primary change.
- EXPECT_EQ(2, observer.GetChangedDisplayIdAndReset());
- EXPECT_EQ(1, observer.GetBoundsChangedCountAndReset());
- EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset());
- EXPECT_EQ(1, observer.GetPrimaryChangedCountAndReset());
- EXPECT_EQ(1, observer.CountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_TRUE(window_state->IsFullscreen());
- EXPECT_EQ(gfx::Rect(0, 0, 600, 500), w1->bounds());
- }
- TEST_F(WindowTreeHostManagerTest, BoundsUpdated) {
- // Creates windows to catch activation change event.
- std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1));
- w1->Focus();
- TestObserver observer;
- SetDefaultDisplayLayout(display::DisplayPlacement::BOTTOM);
- UpdateDisplay("300x200,400x300"); // layout, resize and add.
- EXPECT_EQ(1, observer.CountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- gfx::Insets insets(5);
- display_manager()->UpdateWorkAreaOfDisplay(GetSecondaryDisplay().id(),
- insets);
- EXPECT_EQ(gfx::Rect(0, 0, 300, 200), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(0, 200, 400, 300), GetSecondaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(5, 205, 390, 290), GetSecondaryDisplay().work_area());
- UpdateDisplay("500x400,300x200");
- EXPECT_EQ(1, observer.CountAndReset()); // two resizes
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 500, 400), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(0, 400, 300, 200), GetSecondaryDisplay().bounds());
- UpdateDisplay("500x400,400x300");
- EXPECT_EQ(1, observer.CountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 500, 400), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(0, 400, 400, 300), GetSecondaryDisplay().bounds());
- UpdateDisplay("500x400");
- EXPECT_EQ(1, observer.CountAndReset());
- EXPECT_LE(1, observer.GetFocusChangedCountAndReset());
- EXPECT_LE(1, observer.GetActivationChangedCountAndReset());
- EXPECT_EQ(gfx::Rect(0, 0, 500, 400), GetPrimaryDisplay().bounds());
- EXPECT_EQ(1, display::Screen::GetScreen()->GetNumDisplays());
- UpdateDisplay("400x500*2,400x300");
- EXPECT_EQ(1, observer.CountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- ASSERT_EQ(2, display::Screen::GetScreen()->GetNumDisplays());
- EXPECT_EQ(gfx::Rect(0, 0, 200, 250), GetPrimaryDisplay().bounds());
- EXPECT_EQ(gfx::Rect(0, 250, 400, 300), GetSecondaryDisplay().bounds());
- // No change
- UpdateDisplay("400x500*2,400x300");
- // We still call into Pre/PostDisplayConfigurationChange().
- EXPECT_EQ(1, observer.CountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- // Rotation
- observer.GetRotationChangedCountAndReset(); // we only want to reset.
- int64_t primary_id = GetPrimaryDisplay().id();
- display_manager()->SetDisplayRotation(
- primary_id, display::Display::ROTATE_90,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
- EXPECT_EQ(1, observer.CountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- display_manager()->SetDisplayRotation(
- primary_id, display::Display::ROTATE_90,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(0, observer.GetRotationChangedCountAndReset());
- EXPECT_EQ(0, observer.CountAndReset());
- EXPECT_EQ(0, observer.GetFocusChangedCountAndReset());
- EXPECT_EQ(0, observer.GetActivationChangedCountAndReset());
- }
- TEST_F(WindowTreeHostManagerTest, FindNearestDisplay) {
- WindowTreeHostManager* window_tree_host_manager =
- Shell::Get()->window_tree_host_manager();
- UpdateDisplay("200x201,300x301");
- display_manager()->SetLayoutForCurrentDisplays(
- display::test::CreateDisplayLayout(display_manager(),
- display::DisplayPlacement::RIGHT, 50));
- display::Display primary_display =
- display::Screen::GetScreen()->GetPrimaryDisplay();
- display::Display secondary_display =
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay();
- EXPECT_NE(primary_display.id(), secondary_display.id());
- aura::Window* primary_root =
- window_tree_host_manager->GetRootWindowForDisplayId(primary_display.id());
- aura::Window* secondary_root =
- window_tree_host_manager->GetRootWindowForDisplayId(
- secondary_display.id());
- EXPECT_NE(primary_root, secondary_root);
- // Test that points outside of any display return the nearest display.
- EXPECT_EQ(primary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(-100, 0))
- .id());
- EXPECT_EQ(primary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(0, -100))
- .id());
- EXPECT_EQ(primary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(100, 100))
- .id());
- EXPECT_EQ(primary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(224, 25))
- .id());
- EXPECT_EQ(secondary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(226, 25))
- .id());
- EXPECT_EQ(secondary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(600, 100))
- .id());
- EXPECT_EQ(primary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(176, 225))
- .id());
- EXPECT_EQ(secondary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(178, 225))
- .id());
- EXPECT_EQ(secondary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(300, 400))
- .id());
- }
- TEST_F(WindowTreeHostManagerTest,
- SettingAndUpdatingRoundedCornerPropertyOnDisplay) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(display::features::kRoundedDisplay);
- WindowTreeHostManager* window_tree_host_manager =
- Shell::Get()->window_tree_host_manager();
- // Adding rounded corners on the primary display.
- UpdateDisplay("300x200~15");
- display::test::DisplayManagerTestApi display_manager_test(display_manager());
- aura::Window* primary_root = Shell::GetPrimaryRootWindow();
- EXPECT_EQ(gfx::RoundedCornersF(15.0),
- primary_root->layer()->rounded_corner_radii());
- // Adding a secondary display should not propagate the rounded corner
- // property.
- UpdateDisplay("300x200~15,300x200");
- display::Display secondary_display =
- display_manager_test.GetSecondaryDisplay();
- aura::Window* secondary_root =
- window_tree_host_manager->GetRootWindowForDisplayId(
- secondary_display.id());
- EXPECT_EQ(gfx::RoundedCornersF(15.0),
- primary_root->layer()->rounded_corner_radii());
- EXPECT_EQ(primary_root->layer()->is_fast_rounded_corner(), true);
- EXPECT_EQ(gfx::RoundedCornersF(0.0),
- secondary_root->layer()->rounded_corner_radii());
- // Removing the secondary display should not effect the rounded corner
- // property.
- UpdateDisplay("300x200~15");
- EXPECT_EQ(gfx::RoundedCornersF(15.0),
- primary_root->layer()->rounded_corner_radii());
- EXPECT_EQ(primary_root->layer()->is_fast_rounded_corner(), true);
- // Changing the the metrics should not effect rounded corner property.
- UpdateDisplay("10+20-300x200/ol~15");
- EXPECT_EQ(gfx::RoundedCornersF(15.0),
- primary_root->layer()->rounded_corner_radii());
- EXPECT_EQ(primary_root->layer()->is_fast_rounded_corner(), true);
- // Updating rounded corners property on the display.
- UpdateDisplay("300x200~15|15|12|12");
- EXPECT_EQ(gfx::RoundedCornersF(15.0, 15.0, 12.0, 12.0),
- primary_root->layer()->rounded_corner_radii());
- EXPECT_EQ(primary_root->layer()->is_fast_rounded_corner(), true);
- }
- TEST_F(WindowTreeHostManagerTest,
- SwappingPrimaryDisplayShouldNotSwapRoundedCornersOnDisplays) {
- base::test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitAndEnableFeature(display::features::kRoundedDisplay);
- WindowTreeHostManager* window_tree_host_manager =
- Shell::Get()->window_tree_host_manager();
- // primary display has rounded corners.
- UpdateDisplay("300x200~15,400x300");
- display::test::DisplayManagerTestApi display_manager_test(display_manager());
- display::Display secondary_display =
- display_manager_test.GetSecondaryDisplay();
- aura::Window* primary_root = Shell::GetPrimaryRootWindow();
- aura::Window* secondary_root =
- window_tree_host_manager->GetRootWindowForDisplayId(
- secondary_display.id());
- EXPECT_EQ(gfx::RoundedCornersF(15.0),
- primary_root->layer()->rounded_corner_radii());
- EXPECT_EQ(primary_root->layer()->is_fast_rounded_corner(), true);
- EXPECT_EQ(gfx::RoundedCornersF(0.0),
- secondary_root->layer()->rounded_corner_radii());
- // Switch primary and secondary by display ID.
- window_tree_host_manager->SetPrimaryDisplayId(secondary_display.id());
- // Getting the new primary and secondary root windows after the swap.
- secondary_display = display_manager_test.GetSecondaryDisplay();
- primary_root = Shell::GetPrimaryRootWindow();
- secondary_root = window_tree_host_manager->GetRootWindowForDisplayId(
- secondary_display.id());
- // After swapping primary display, the root windows are swapped. Secondary
- // root now belongs to the display with rounded corners.
- EXPECT_EQ(gfx::RoundedCornersF(15.0),
- secondary_root->layer()->rounded_corner_radii());
- EXPECT_EQ(secondary_root->layer()->is_fast_rounded_corner(), true);
- EXPECT_EQ(gfx::RoundedCornersF(0.0),
- primary_root->layer()->rounded_corner_radii());
- }
- TEST_F(WindowTreeHostManagerTest, SwapPrimaryById) {
- WindowTreeHostManager* window_tree_host_manager =
- Shell::Get()->window_tree_host_manager();
- UpdateDisplay("300x200,400x300/h");
- const int shelf_inset_first = 200 - ShelfConfig::Get()->shelf_size();
- const int shelf_inset_second = 300 - ShelfConfig::Get()->shelf_size();
- display::test::DisplayManagerTestApi display_manager_test(display_manager());
- display::Display primary_display =
- display::Screen::GetScreen()->GetPrimaryDisplay();
- display::Display secondary_display =
- display_manager_test.GetSecondaryDisplay();
- display_manager()->SetLayoutForCurrentDisplays(
- display::test::CreateDisplayLayout(display_manager(),
- display::DisplayPlacement::RIGHT, 50));
- EXPECT_NE(primary_display.id(), secondary_display.id());
- aura::Window* primary_root =
- window_tree_host_manager->GetRootWindowForDisplayId(primary_display.id());
- aura::Window* secondary_root =
- window_tree_host_manager->GetRootWindowForDisplayId(
- secondary_display.id());
- aura::Window* shelf_window =
- GetPrimaryShelf()->shelf_widget()->GetNativeView();
- EXPECT_TRUE(primary_root->Contains(shelf_window));
- EXPECT_FALSE(secondary_root->Contains(shelf_window));
- EXPECT_NE(primary_root, secondary_root);
- EXPECT_EQ(primary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(-100, -100))
- .id());
- EXPECT_EQ(
- primary_display.id(),
- display::Screen::GetScreen()->GetDisplayNearestWindow(nullptr).id());
- EXPECT_EQ(gfx::Rect(0, 0, 300, 200), primary_display.bounds());
- EXPECT_EQ(gfx::Rect(0, 0, 300, shelf_inset_first),
- primary_display.work_area());
- EXPECT_EQ(gfx::Rect(300, 0, 400, 300), secondary_display.bounds());
- EXPECT_EQ(gfx::Rect(300, 0, 400, shelf_inset_second),
- secondary_display.work_area());
- EXPECT_EQ("id=2200000257, parent=2200000000, right, 50",
- display_manager()
- ->GetCurrentDisplayLayout()
- .placement_list[0]
- .ToString());
- // Switch primary and secondary by display ID.
- TestObserver observer;
- window_tree_host_manager->SetPrimaryDisplayId(secondary_display.id());
- EXPECT_EQ(secondary_display.id(),
- display::Screen::GetScreen()->GetPrimaryDisplay().id());
- EXPECT_EQ(primary_display.id(),
- display_manager_test.GetSecondaryDisplay().id());
- EXPECT_LT(0, observer.CountAndReset());
- EXPECT_EQ(primary_root, window_tree_host_manager->GetRootWindowForDisplayId(
- secondary_display.id()));
- EXPECT_EQ(secondary_root, window_tree_host_manager->GetRootWindowForDisplayId(
- primary_display.id()));
- EXPECT_TRUE(primary_root->Contains(shelf_window));
- EXPECT_FALSE(secondary_root->Contains(shelf_window));
- const display::DisplayLayout& inverted_layout =
- display_manager()->GetCurrentDisplayLayout();
- EXPECT_EQ("id=2200000000, parent=2200000257, left, -50",
- inverted_layout.placement_list[0].ToString());
- // Test if the bounds are correctly swapped.
- display::Display swapped_primary =
- display::Screen::GetScreen()->GetPrimaryDisplay();
- display::Display swapped_secondary =
- display_manager_test.GetSecondaryDisplay();
- EXPECT_EQ(gfx::Rect(0, 0, 400, 300), swapped_primary.bounds());
- EXPECT_EQ(gfx::Rect(0, 0, 400, shelf_inset_second),
- swapped_primary.work_area());
- EXPECT_EQ(gfx::Rect(-300, -50, 300, 200), swapped_secondary.bounds());
- EXPECT_EQ(gfx::Rect(-300, -50, 300, shelf_inset_first),
- swapped_secondary.work_area());
- // Test that the color spaces are correctly swapped.
- auto* swapped_primary_compositor =
- window_tree_host_manager->GetRootWindowForDisplayId(swapped_primary.id())
- ->GetHost()
- ->compositor();
- auto* swapped_secondary_compositor =
- window_tree_host_manager
- ->GetRootWindowForDisplayId(swapped_secondary.id())
- ->GetHost()
- ->compositor();
- EXPECT_EQ(swapped_primary.color_spaces(),
- swapped_primary_compositor->display_color_spaces());
- EXPECT_EQ(swapped_secondary.color_spaces(),
- swapped_secondary_compositor->display_color_spaces());
- // Calling the same ID don't do anything.
- window_tree_host_manager->SetPrimaryDisplayId(secondary_display.id());
- EXPECT_EQ(0, observer.CountAndReset());
- aura::WindowTracker tracker;
- tracker.Add(primary_root);
- tracker.Add(secondary_root);
- // Deleting 2nd display should move the primary to original primary display.
- UpdateDisplay("300x200");
- base::RunLoop().RunUntilIdle(); // RootWindow is deleted in a posted task.
- EXPECT_EQ(1, display::Screen::GetScreen()->GetNumDisplays());
- EXPECT_EQ(primary_display.id(),
- display::Screen::GetScreen()->GetPrimaryDisplay().id());
- EXPECT_EQ(primary_display.id(),
- display::Screen::GetScreen()
- ->GetDisplayNearestPoint(gfx::Point(-100, -100))
- .id());
- EXPECT_EQ(
- primary_display.id(),
- display::Screen::GetScreen()->GetDisplayNearestWindow(nullptr).id());
- EXPECT_TRUE(tracker.Contains(primary_root));
- EXPECT_FALSE(tracker.Contains(secondary_root));
- EXPECT_TRUE(primary_root->Contains(shelf_window));
- // Adding 2nd display with the same ID. The 2nd display should become primary
- // since secondary id is still stored as desirable_primary_id.
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(
- display_manager()->GetDisplayInfo(primary_display.id()));
- display_info_list.push_back(
- display_manager()->GetDisplayInfo(secondary_display.id()));
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(2, display::Screen::GetScreen()->GetNumDisplays());
- EXPECT_EQ(secondary_display.id(),
- display::Screen::GetScreen()->GetPrimaryDisplay().id());
- EXPECT_EQ(primary_display.id(),
- display_manager_test.GetSecondaryDisplay().id());
- EXPECT_EQ(primary_root, window_tree_host_manager->GetRootWindowForDisplayId(
- secondary_display.id()));
- EXPECT_NE(primary_root, window_tree_host_manager->GetRootWindowForDisplayId(
- primary_display.id()));
- EXPECT_TRUE(primary_root->Contains(shelf_window));
- // Deleting 2nd display and adding 2nd display with a different ID. The 2nd
- // display shouldn't become primary.
- UpdateDisplay("300x200");
- display::ManagedDisplayInfo third_display_info(secondary_display.id() + 1,
- std::string(), false);
- third_display_info.SetBounds(secondary_display.bounds());
- ASSERT_NE(primary_display.id(), third_display_info.id());
- const display::ManagedDisplayInfo& primary_display_info =
- display_manager()->GetDisplayInfo(primary_display.id());
- std::vector<display::ManagedDisplayInfo> display_info_list2;
- display_info_list2.push_back(primary_display_info);
- display_info_list2.push_back(third_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list2);
- EXPECT_EQ(2, display::Screen::GetScreen()->GetNumDisplays());
- EXPECT_EQ(primary_display.id(),
- display::Screen::GetScreen()->GetPrimaryDisplay().id());
- EXPECT_EQ(third_display_info.id(),
- display_manager_test.GetSecondaryDisplay().id());
- EXPECT_EQ(primary_root, window_tree_host_manager->GetRootWindowForDisplayId(
- primary_display.id()));
- EXPECT_NE(primary_root, window_tree_host_manager->GetRootWindowForDisplayId(
- third_display_info.id()));
- EXPECT_TRUE(primary_root->Contains(shelf_window));
- }
- TEST_F(WindowTreeHostManagerTest, SetPrimaryWithThreeDisplays) {
- UpdateDisplay("500x400,400x300,300x200");
- int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
- display::DisplayIdList non_primary_ids =
- display_manager()->GetConnectedDisplayIdList();
- auto itr =
- std::remove(non_primary_ids.begin(), non_primary_ids.end(), primary_id);
- ASSERT_TRUE(itr != non_primary_ids.end());
- non_primary_ids.erase(itr, non_primary_ids.end());
- ASSERT_EQ(2u, non_primary_ids.size());
- // Build the following layout:
- //
- // +----------------+ +--------------------+
- // | primary_id (P) | <---- | non_primary_ids[0] |
- // +----------------+ +--------------------+
- // ^
- // |
- // +--------------------+
- // | non_primary_ids[1] |
- // +--------------------+
- display::DisplayLayoutBuilder builder(primary_id);
- builder.AddDisplayPlacement(non_primary_ids[0], primary_id,
- display::DisplayPlacement::RIGHT, 0);
- builder.AddDisplayPlacement(non_primary_ids[1], primary_id,
- display::DisplayPlacement::BOTTOM, 0);
- display_manager()->SetLayoutForCurrentDisplays(builder.Build());
- EXPECT_EQ(primary_id, display::Screen::GetScreen()->GetPrimaryDisplay().id());
- WindowTreeHostManager* window_tree_host_manager =
- Shell::Get()->window_tree_host_manager();
- aura::Window* primary_root =
- window_tree_host_manager->GetRootWindowForDisplayId(primary_id);
- aura::Window* non_primary_root_0 =
- window_tree_host_manager->GetRootWindowForDisplayId(non_primary_ids[0]);
- aura::Window* non_primary_root_1 =
- window_tree_host_manager->GetRootWindowForDisplayId(non_primary_ids[1]);
- // Make non_primary_ids[0] primary.
- window_tree_host_manager->SetPrimaryDisplayId(non_primary_ids[0]);
- EXPECT_EQ(non_primary_ids[0],
- display::Screen::GetScreen()->GetPrimaryDisplay().id());
- // Expect the root windows to be swapped.
- EXPECT_EQ(primary_root, window_tree_host_manager->GetRootWindowForDisplayId(
- non_primary_ids[0]));
- EXPECT_EQ(non_primary_root_0,
- window_tree_host_manager->GetRootWindowForDisplayId(primary_id));
- EXPECT_EQ(
- non_primary_root_1,
- window_tree_host_manager->GetRootWindowForDisplayId(non_primary_ids[1]));
- // Expect that the layout will be changed to:
- //
- // +----------------+ +-----------------------+
- // | primary_id | ----> | non_primary_ids[0] (P)|
- // +----------------+ +-----------------------+
- // ^
- // |
- // +--------------------+
- // | non_primary_ids[1] |
- // +--------------------+
- {
- const display::DisplayLayout& current_layout =
- display_manager()->GetCurrentDisplayLayout();
- EXPECT_EQ(non_primary_ids[0], current_layout.primary_id);
- ASSERT_EQ(2u, current_layout.placement_list.size());
- EXPECT_EQ(primary_id, current_layout.placement_list[0].display_id);
- EXPECT_EQ(non_primary_ids[0],
- current_layout.placement_list[0].parent_display_id);
- EXPECT_EQ(display::DisplayPlacement::LEFT,
- current_layout.placement_list[0].position);
- EXPECT_EQ(non_primary_ids[1], current_layout.placement_list[1].display_id);
- EXPECT_EQ(primary_id, current_layout.placement_list[1].parent_display_id);
- EXPECT_EQ(display::DisplayPlacement::BOTTOM,
- current_layout.placement_list[1].position);
- }
- // Make non_primary_ids[1] primary.
- window_tree_host_manager->SetPrimaryDisplayId(non_primary_ids[1]);
- EXPECT_EQ(non_primary_ids[1],
- display::Screen::GetScreen()->GetPrimaryDisplay().id());
- // Expect the root windows to be swapped.
- EXPECT_EQ(primary_root, window_tree_host_manager->GetRootWindowForDisplayId(
- non_primary_ids[1]));
- EXPECT_EQ(
- non_primary_root_1,
- window_tree_host_manager->GetRootWindowForDisplayId(non_primary_ids[0]));
- EXPECT_EQ(non_primary_root_0,
- window_tree_host_manager->GetRootWindowForDisplayId(primary_id));
- // Expect that the layout will be changed to:
- //
- // +----------------+ +--------------------+
- // | primary_id | <---- | non_primary_ids[0] |
- // +----------------+ +--------------------+
- // |
- // V
- // +------------------------+
- // | non_primary_ids[1] (P) |
- // +------------------------+
- {
- const display::DisplayLayout& current_layout =
- display_manager()->GetCurrentDisplayLayout();
- EXPECT_EQ(non_primary_ids[1], current_layout.primary_id);
- ASSERT_EQ(2u, current_layout.placement_list.size());
- EXPECT_EQ(primary_id, current_layout.placement_list[0].display_id);
- EXPECT_EQ(non_primary_ids[1],
- current_layout.placement_list[0].parent_display_id);
- EXPECT_EQ(display::DisplayPlacement::TOP,
- current_layout.placement_list[0].position);
- EXPECT_EQ(non_primary_ids[0], current_layout.placement_list[1].display_id);
- EXPECT_EQ(primary_id, current_layout.placement_list[1].parent_display_id);
- EXPECT_EQ(display::DisplayPlacement::RIGHT,
- current_layout.placement_list[1].position);
- }
- }
- TEST_F(WindowTreeHostManagerTest, SetPrimaryWithFourDisplays) {
- UpdateDisplay("600x500,500x400,400x300,300x200");
- int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
- display::DisplayIdList non_primary_ids =
- display_manager()->GetConnectedDisplayIdList();
- auto itr =
- std::remove(non_primary_ids.begin(), non_primary_ids.end(), primary_id);
- ASSERT_TRUE(itr != non_primary_ids.end());
- non_primary_ids.erase(itr, non_primary_ids.end());
- ASSERT_EQ(3u, non_primary_ids.size());
- // Build the following layout:
- //
- // +--------------------+ +--------------------+ +--------------------+
- // | | | primary_id (P) | | |
- // | | +--------------------+ | |
- // | | ^ | |
- // | non_primary_ids[1] | | | non_primary_ids[2] |
- // | | +--------------------+ | |
- // | |-->| non_primary_ids[0] |<--| |
- // +--------------------+ +--------------------+ +--------------------+
- display::DisplayLayoutBuilder builder(primary_id);
- builder.AddDisplayPlacement(non_primary_ids[0], primary_id,
- display::DisplayPlacement::BOTTOM, 0);
- builder.AddDisplayPlacement(non_primary_ids[1], non_primary_ids[0],
- display::DisplayPlacement::LEFT, 0);
- builder.AddDisplayPlacement(non_primary_ids[2], non_primary_ids[0],
- display::DisplayPlacement::RIGHT, 0);
- display_manager()->SetLayoutForCurrentDisplays(builder.Build());
- EXPECT_EQ(primary_id, display::Screen::GetScreen()->GetPrimaryDisplay().id());
- WindowTreeHostManager* window_tree_host_manager =
- Shell::Get()->window_tree_host_manager();
- // Make non_primary_ids[2] primary.
- window_tree_host_manager->SetPrimaryDisplayId(non_primary_ids[2]);
- EXPECT_EQ(non_primary_ids[2],
- display::Screen::GetScreen()->GetPrimaryDisplay().id());
- // Expect that the layout will be changed to:
- //
- // +--------------------+ +--------------------+ +--------------------+
- // | | | primary_id | | |
- // | | +--------------------+ | |
- // | | | | |
- // | non_primary_ids[1] | V | non_primary_ids[2] |
- // | | +--------------------+ | (P) |
- // | |-->| non_primary_ids[0] |-->| |
- // +--------------------+ +--------------------+ +--------------------+
- {
- const display::DisplayLayout& current_layout =
- display_manager()->GetCurrentDisplayLayout();
- EXPECT_EQ(non_primary_ids[2], current_layout.primary_id);
- ASSERT_EQ(3u, current_layout.placement_list.size());
- EXPECT_EQ(primary_id, current_layout.placement_list[0].display_id);
- EXPECT_EQ(non_primary_ids[0],
- current_layout.placement_list[0].parent_display_id);
- EXPECT_EQ(display::DisplayPlacement::TOP,
- current_layout.placement_list[0].position);
- EXPECT_EQ(non_primary_ids[0], current_layout.placement_list[1].display_id);
- EXPECT_EQ(non_primary_ids[2],
- current_layout.placement_list[1].parent_display_id);
- EXPECT_EQ(display::DisplayPlacement::LEFT,
- current_layout.placement_list[1].position);
- EXPECT_EQ(non_primary_ids[1], current_layout.placement_list[2].display_id);
- EXPECT_EQ(non_primary_ids[0],
- current_layout.placement_list[2].parent_display_id);
- EXPECT_EQ(display::DisplayPlacement::LEFT,
- current_layout.placement_list[2].position);
- }
- // Make non_primary_ids[1] primary.
- window_tree_host_manager->SetPrimaryDisplayId(non_primary_ids[1]);
- EXPECT_EQ(non_primary_ids[1],
- display::Screen::GetScreen()->GetPrimaryDisplay().id());
- // Expect that the layout will be changed to:
- //
- // +--------------------+ +--------------------+ +--------------------+
- // | | | primary_id | | |
- // | | +--------------------+ | |
- // | | | | |
- // | non_primary_ids[1] | V | non_primary_ids[2] |
- // | (P) | +--------------------+ | |
- // | |<--| non_primary_ids[0] |<--| |
- // +--------------------+ +--------------------+ +--------------------+
- {
- const display::DisplayLayout& current_layout =
- display_manager()->GetCurrentDisplayLayout();
- EXPECT_EQ(non_primary_ids[1], current_layout.primary_id);
- ASSERT_EQ(3u, current_layout.placement_list.size());
- EXPECT_EQ(primary_id, current_layout.placement_list[0].display_id);
- EXPECT_EQ(non_primary_ids[0],
- current_layout.placement_list[0].parent_display_id);
- EXPECT_EQ(display::DisplayPlacement::TOP,
- current_layout.placement_list[0].position);
- EXPECT_EQ(non_primary_ids[0], current_layout.placement_list[1].display_id);
- EXPECT_EQ(non_primary_ids[1],
- current_layout.placement_list[1].parent_display_id);
- EXPECT_EQ(display::DisplayPlacement::RIGHT,
- current_layout.placement_list[1].position);
- EXPECT_EQ(non_primary_ids[2], current_layout.placement_list[2].display_id);
- EXPECT_EQ(non_primary_ids[0],
- current_layout.placement_list[2].parent_display_id);
- EXPECT_EQ(display::DisplayPlacement::RIGHT,
- current_layout.placement_list[2].position);
- }
- }
- TEST_F(WindowTreeHostManagerTest, OverscanInsets) {
- WindowTreeHostManager* window_tree_host_manager =
- Shell::Get()->window_tree_host_manager();
- TestEventHandler event_handler;
- Shell::Get()->AddPreTargetHandler(&event_handler);
- UpdateDisplay("120x200,300x400*2");
- display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay();
- aura::Window::Windows root_windows = Shell::GetAllRootWindows();
- window_tree_host_manager->SetOverscanInsets(
- display1.id(), gfx::Insets::TLBR(10, 15, 20, 25));
- display::test::DisplayManagerTestApi display_manager_test(display_manager());
- EXPECT_EQ(gfx::Rect(0, 0, 80, 170), root_windows[0]->bounds());
- EXPECT_EQ(gfx::Size(150, 200), root_windows[1]->bounds().size());
- EXPECT_EQ(gfx::Rect(80, 0, 150, 200),
- display_manager_test.GetSecondaryDisplay().bounds());
- ui::test::EventGenerator generator(root_windows[0]);
- generator.MoveMouseToInHost(20, 25);
- EXPECT_EQ(gfx::Point(5, 15), event_handler.GetLocationAndReset());
- window_tree_host_manager->SetOverscanInsets(display1.id(), gfx::Insets());
- EXPECT_EQ(gfx::Rect(0, 0, 120, 200), root_windows[0]->bounds());
- EXPECT_EQ(gfx::Rect(120, 0, 150, 200),
- display_manager_test.GetSecondaryDisplay().bounds());
- generator.MoveMouseToInHost(30, 20);
- EXPECT_EQ(gfx::Point(30, 20), event_handler.GetLocationAndReset());
- // Make sure the root window transformer uses correct scale
- // factor when swapping display. Test crbug.com/253690.
- UpdateDisplay("400x300*2,600x400/o");
- root_windows = Shell::GetAllRootWindows();
- gfx::Point point;
- Shell::GetAllRootWindows()[1]->GetHost()->GetRootTransform().TransformPoint(
- &point);
- EXPECT_EQ(gfx::Point(15, 10), point);
- SwapPrimaryDisplay();
- point.SetPoint(0, 0);
- Shell::GetAllRootWindows()[1]->GetHost()->GetRootTransform().TransformPoint(
- &point);
- EXPECT_EQ(gfx::Point(15, 10), point);
- Shell::Get()->RemovePreTargetHandler(&event_handler);
- }
- TEST_F(WindowTreeHostManagerTest, Rotate) {
- TestEventHandler event_handler;
- Shell::Get()->AddPreTargetHandler(&event_handler);
- UpdateDisplay("120x200,300x400*2");
- display::test::DisplayManagerTestApi display_manager_test(display_manager());
- display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay();
- int64_t display2_id = display_manager_test.GetSecondaryDisplay().id();
- aura::Window::Windows root_windows = Shell::GetAllRootWindows();
- ui::test::EventGenerator generator1(root_windows[0]);
- TestObserver observer;
- EXPECT_EQ(gfx::Size(120, 200), root_windows[0]->bounds().size());
- EXPECT_EQ(gfx::Size(150, 200), root_windows[1]->bounds().size());
- EXPECT_EQ(gfx::Rect(120, 0, 150, 200),
- display_manager_test.GetSecondaryDisplay().bounds());
- generator1.MoveMouseToInHost(50, 40);
- EXPECT_EQ(gfx::Point(50, 40), event_handler.GetLocationAndReset());
- EXPECT_EQ(display::Display::ROTATE_0,
- GetActiveDisplayRotation(display1.id()));
- EXPECT_EQ(display::Display::ROTATE_0, GetActiveDisplayRotation(display2_id));
- EXPECT_EQ(0, observer.GetRotationChangedCountAndReset());
- display_manager()->SetDisplayRotation(
- display1.id(), display::Display::ROTATE_90,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(gfx::Size(200, 120), root_windows[0]->bounds().size());
- EXPECT_EQ(gfx::Size(150, 200), root_windows[1]->bounds().size());
- EXPECT_EQ(gfx::Rect(200, 0, 150, 200),
- display_manager_test.GetSecondaryDisplay().bounds());
- generator1.MoveMouseToInHost(50, 40);
- EXPECT_EQ(gfx::Point(40, 70), event_handler.GetLocationAndReset());
- EXPECT_EQ(display::Display::ROTATE_90,
- GetActiveDisplayRotation(display1.id()));
- EXPECT_EQ(display::Display::ROTATE_0, GetActiveDisplayRotation(display2_id));
- EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
- display_manager()->SetLayoutForCurrentDisplays(
- display::test::CreateDisplayLayout(
- display_manager(), display::DisplayPlacement::BOTTOM, 50));
- EXPECT_EQ(gfx::Rect(50, 120, 150, 200),
- display_manager_test.GetSecondaryDisplay().bounds());
- display_manager()->SetDisplayRotation(
- display2_id, display::Display::ROTATE_270,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(gfx::Size(200, 120), root_windows[0]->bounds().size());
- EXPECT_EQ(gfx::Size(200, 150), root_windows[1]->bounds().size());
- EXPECT_EQ(gfx::Rect(50, 120, 200, 150),
- display_manager_test.GetSecondaryDisplay().bounds());
- EXPECT_EQ(display::Display::ROTATE_90,
- GetActiveDisplayRotation(display1.id()));
- EXPECT_EQ(display::Display::ROTATE_270,
- GetActiveDisplayRotation(display2_id));
- EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
- ui::test::EventGenerator generator2(root_windows[1]);
- generator2.MoveMouseToInHost(50, 40);
- EXPECT_EQ(gfx::Point(180, 25), event_handler.GetLocationAndReset());
- display_manager()->SetDisplayRotation(
- display1.id(), display::Display::ROTATE_180,
- display::Display::RotationSource::ACTIVE);
- EXPECT_EQ(gfx::Size(120, 200), root_windows[0]->bounds().size());
- EXPECT_EQ(gfx::Size(200, 150), root_windows[1]->bounds().size());
- // Display must share at least 100, so the x's offset becomes 20.
- EXPECT_EQ(gfx::Rect(20, 200, 200, 150),
- display_manager_test.GetSecondaryDisplay().bounds());
- EXPECT_EQ(display::Display::ROTATE_180,
- GetActiveDisplayRotation(display1.id()));
- EXPECT_EQ(display::Display::ROTATE_270,
- GetActiveDisplayRotation(display2_id));
- EXPECT_EQ(1, observer.GetRotationChangedCountAndReset());
- generator1.MoveMouseToInHost(50, 40);
- EXPECT_EQ(gfx::Point(70, 160), event_handler.GetLocationAndReset());
- Shell::Get()->RemovePreTargetHandler(&event_handler);
- }
- TEST_F(WindowTreeHostManagerTest, ScaleRootWindow) {
- TestEventHandler event_handler;
- Shell::Get()->AddPreTargetHandler(&event_handler);
- UpdateDisplay("600x400*1.6,500x300");
- display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay();
- display::test::ScopedSetInternalDisplayId set_internal(display_manager(),
- display1.id());
- display::test::DisplayManagerTestApi display_manager_test(display_manager());
- display::Display display2 = display_manager_test.GetSecondaryDisplay();
- aura::Window::Windows root_windows = Shell::GetAllRootWindows();
- EXPECT_EQ(gfx::Rect(0, 0, 375, 250), display1.bounds());
- EXPECT_EQ(gfx::Rect(0, 0, 375, 250), root_windows[0]->bounds());
- EXPECT_EQ(gfx::Rect(375, 0, 500, 300), display2.bounds());
- EXPECT_FLOAT_EQ(1.0f, GetStoredZoomScale(display1.id()));
- EXPECT_FLOAT_EQ(1.0f, GetStoredZoomScale(display2.id()));
- ui::test::EventGenerator generator(root_windows[0]);
- generator.MoveMouseToInHost(599, 200);
- EXPECT_EQ(gfx::Point(374, 125), event_handler.GetLocationAndReset());
- display_manager()->UpdateZoomFactor(display1.id(), 1.f / 1.2f);
- display1 = display::Screen::GetScreen()->GetPrimaryDisplay();
- display2 = display_manager_test.GetSecondaryDisplay();
- EXPECT_EQ(gfx::Rect(0, 0, 450, 300), display1.bounds());
- EXPECT_EQ(gfx::Rect(0, 0, 450, 300), root_windows[0]->bounds());
- EXPECT_EQ(gfx::Rect(450, 0, 500, 300), display2.bounds());
- EXPECT_FLOAT_EQ(1.f / 1.2f, GetStoredZoomScale(display1.id()));
- EXPECT_FLOAT_EQ(1.0f, GetStoredZoomScale(display2.id()));
- Shell::Get()->RemovePreTargetHandler(&event_handler);
- }
- TEST_F(WindowTreeHostManagerTest, TouchScale) {
- TestEventHandler event_handler;
- Shell::Get()->AddPreTargetHandler(&event_handler);
- UpdateDisplay("300x200*2");
- display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
- aura::Window::Windows root_windows = Shell::GetAllRootWindows();
- aura::Window* root_window = root_windows[0];
- ui::test::EventGenerator generator(root_window);
- generator.PressMoveAndReleaseTouchTo(50, 50);
- // Default test touches have radius_x/y = 1.0, with device scale
- // factor = 2, the scaled radius_x/y should be 0.5.
- EXPECT_EQ(0.5, event_handler.touch_radius_x());
- EXPECT_EQ(0.5, event_handler.touch_radius_y());
- generator.ScrollSequence(gfx::Point(0, 0), base::Milliseconds(100), 10.0, 1.0,
- 5, 1);
- // ordinal_offset is invariant to the device scale factor.
- EXPECT_EQ(event_handler.scroll_x_offset(),
- event_handler.scroll_x_offset_ordinal());
- EXPECT_EQ(event_handler.scroll_y_offset(),
- event_handler.scroll_y_offset_ordinal());
- Shell::Get()->RemovePreTargetHandler(&event_handler);
- }
- TEST_F(WindowTreeHostManagerTest, ConvertHostToRootCoords) {
- TestEventHandler event_handler;
- Shell::Get()->AddPreTargetHandler(&event_handler);
- UpdateDisplay("600x400*2/r@0.8");
- display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay();
- aura::Window::Windows root_windows = Shell::GetAllRootWindows();
- EXPECT_EQ(gfx::Rect(0, 0, 250, 375), display1.bounds());
- EXPECT_EQ(gfx::Rect(0, 0, 250, 375), root_windows[0]->bounds());
- EXPECT_EQ(0.8f, GetStoredZoomScale(display1.id()));
- ui::test::EventGenerator generator(root_windows[0]);
- generator.MoveMouseToInHost(0, 0);
- // The mouse location must be inside the root bounds in dp.
- EXPECT_EQ(gfx::Point(0, 374), event_handler.GetLocationAndReset());
- generator.MoveMouseToInHost(599, 0);
- EXPECT_EQ(gfx::Point(0, 0), event_handler.GetLocationAndReset());
- generator.MoveMouseToInHost(599, 399);
- EXPECT_EQ(gfx::Point(249, 0), event_handler.GetLocationAndReset());
- generator.MoveMouseToInHost(0, 399);
- EXPECT_EQ(gfx::Point(249, 374), event_handler.GetLocationAndReset());
- UpdateDisplay("600x400*2/u@0.8");
- display1 = display::Screen::GetScreen()->GetPrimaryDisplay();
- root_windows = Shell::GetAllRootWindows();
- EXPECT_EQ(gfx::Rect(0, 0, 375, 250), display1.bounds());
- EXPECT_EQ(gfx::Rect(0, 0, 375, 250), root_windows[0]->bounds());
- EXPECT_EQ(0.8f, GetStoredZoomScale(display1.id()));
- generator.MoveMouseToInHost(0, 0);
- EXPECT_EQ(gfx::Point(374, 249), event_handler.GetLocationAndReset());
- generator.MoveMouseToInHost(599, 0);
- EXPECT_EQ(gfx::Point(0, 249), event_handler.GetLocationAndReset());
- generator.MoveMouseToInHost(599, 399);
- EXPECT_EQ(gfx::Point(0, 0), event_handler.GetLocationAndReset());
- generator.MoveMouseToInHost(0, 399);
- EXPECT_EQ(gfx::Point(374, 0), event_handler.GetLocationAndReset());
- UpdateDisplay("600x400*2/l@0.8");
- display1 = display::Screen::GetScreen()->GetPrimaryDisplay();
- root_windows = Shell::GetAllRootWindows();
- EXPECT_EQ(gfx::Rect(0, 0, 250, 375), display1.bounds());
- EXPECT_EQ(gfx::Rect(0, 0, 250, 375), root_windows[0]->bounds());
- EXPECT_EQ(0.8f, GetStoredZoomScale(display1.id()));
- generator.MoveMouseToInHost(0, 0);
- EXPECT_EQ(gfx::Point(249, 0), event_handler.GetLocationAndReset());
- generator.MoveMouseToInHost(599, 0);
- EXPECT_EQ(gfx::Point(249, 374), event_handler.GetLocationAndReset());
- generator.MoveMouseToInHost(599, 399);
- EXPECT_EQ(gfx::Point(0, 374), event_handler.GetLocationAndReset());
- generator.MoveMouseToInHost(0, 399);
- EXPECT_EQ(gfx::Point(0, 0), event_handler.GetLocationAndReset());
- Shell::Get()->RemovePreTargetHandler(&event_handler);
- }
- // Make sure that the compositor based mirroring can switch
- // from/to dock mode.
- TEST_F(WindowTreeHostManagerTest, DockToSingle) {
- const int64_t internal_id = 1;
- const display::ManagedDisplayInfo internal_display_info =
- CreateDisplayInfo(internal_id, 0, display::Display::ROTATE_0);
- const display::ManagedDisplayInfo external_display_info =
- CreateDisplayInfo(2, 1, display::Display::ROTATE_90);
- std::vector<display::ManagedDisplayInfo> display_info_list;
- // Extended
- display_info_list.push_back(internal_display_info);
- display_info_list.push_back(external_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- const int64_t internal_display_id =
- display::test::DisplayManagerTestApi(display_manager())
- .SetFirstDisplayAsInternalDisplay();
- EXPECT_EQ(internal_id, internal_display_id);
- EXPECT_EQ(2U, display_manager()->GetNumDisplays());
- // Dock mode.
- display_info_list.clear();
- display_info_list.push_back(external_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(1U, display_manager()->GetNumDisplays());
- EXPECT_FALSE(Shell::GetPrimaryRootWindow()
- ->GetHost()
- ->GetRootTransform()
- .IsIdentityOrIntegerTranslation());
- // Switch to single mode and make sure the transform is the one
- // for the internal display.
- display_info_list.clear();
- display_info_list.push_back(internal_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_TRUE(Shell::GetPrimaryRootWindow()
- ->GetHost()
- ->GetRootTransform()
- .IsIdentityOrIntegerTranslation());
- }
- // Tests if switching two displays at the same time while the primary display
- // is swapped should not cause a crash. (crbug.com/426292)
- TEST_F(WindowTreeHostManagerTest, ReplaceSwappedPrimary) {
- const display::ManagedDisplayInfo first_display_info =
- CreateDisplayInfo(10, 0, display::Display::ROTATE_0);
- const display::ManagedDisplayInfo second_display_info =
- CreateDisplayInfo(11, 1, display::Display::ROTATE_0);
- std::vector<display::ManagedDisplayInfo> display_info_list;
- // Extended
- display_info_list.push_back(first_display_info);
- display_info_list.push_back(second_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- SwapPrimaryDisplay();
- EXPECT_EQ(11, display::Screen::GetScreen()->GetPrimaryDisplay().id());
- display_info_list.clear();
- const display::ManagedDisplayInfo new_first_display_info =
- CreateDisplayInfo(20, 0, display::Display::ROTATE_0);
- const display::ManagedDisplayInfo new_second_display_info =
- CreateDisplayInfo(21, 1, display::Display::ROTATE_0);
- display_info_list.push_back(new_first_display_info);
- display_info_list.push_back(new_second_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- EXPECT_EQ(20, display::Screen::GetScreen()->GetPrimaryDisplay().id());
- }
- namespace {
- class RootWindowTestObserver : public aura::WindowObserver {
- public:
- RootWindowTestObserver() = default;
- RootWindowTestObserver(const RootWindowTestObserver&) = delete;
- RootWindowTestObserver& operator=(const RootWindowTestObserver&) = delete;
- ~RootWindowTestObserver() override = default;
- void OnWindowBoundsChanged(aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds,
- ui::PropertyChangeReason reason) override {
- shelf_display_bounds_ = screen_util::GetDisplayBoundsWithShelf(window);
- }
- // Returns the shelf display bounds, in screen coordinates.
- const gfx::Rect& shelf_display_bounds() const {
- return shelf_display_bounds_;
- }
- private:
- gfx::Rect shelf_display_bounds_;
- };
- } // namespace
- // Make sure that GetDisplayBoundsWithShelf returns the correct bounds
- // when the primary display gets replaced in one of the following scenarios:
- // 1) Two displays connected: a) b)
- // 2) both are disconnected and new one with the same size as b) is connected
- // in one configuration event.
- // See crbug.com/547280.
- TEST_F(WindowTreeHostManagerTest, ReplacePrimary) {
- display::ManagedDisplayInfo first_display_info =
- CreateDisplayInfo(10, 0, display::Display::ROTATE_0);
- first_display_info.SetBounds(gfx::Rect(0, 0, 400, 300));
- const display::ManagedDisplayInfo second_display_info =
- CreateDisplayInfo(11, 500, display::Display::ROTATE_0);
- std::vector<display::ManagedDisplayInfo> display_info_list;
- // Extended
- display_info_list.push_back(first_display_info);
- display_info_list.push_back(second_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- aura::Window* primary_root = Shell::GetAllRootWindows()[0];
- int64_t new_display_id = 20;
- RootWindowTestObserver test_observer;
- primary_root->AddObserver(&test_observer);
- display_info_list.clear();
- const display::ManagedDisplayInfo new_first_display_info =
- CreateDisplayInfo(new_display_id, 0, display::Display::ROTATE_0);
- display_info_list.push_back(new_first_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- // The shelf is now on the second display.
- EXPECT_EQ(gfx::Rect(400, 0, 600, 500), test_observer.shelf_display_bounds());
- primary_root->RemoveObserver(&test_observer);
- }
- TEST_F(WindowTreeHostManagerTest, UpdateMouseLocationAfterDisplayChange) {
- UpdateDisplay("300x200,400x300");
- aura::Window::Windows root_windows = Shell::GetAllRootWindows();
- aura::Env* env = aura::Env::GetInstance();
- ui::test::EventGenerator generator_on_2nd(root_windows[1]);
- // Set the initial position.
- generator_on_2nd.MoveMouseToInHost(150, 150);
- EXPECT_EQ(gfx::Point(450, 150), env->last_mouse_location());
- // A mouse pointer will stay in the 2nd display.
- UpdateDisplay("400x300,300x200");
- EXPECT_EQ(gfx::Point(550, 50), env->last_mouse_location());
- // A mouse pointer will be outside of displays and move to the
- // center of 2nd display.
- UpdateDisplay("400x300,110x100");
- EXPECT_EQ(gfx::Point(455, 50), env->last_mouse_location());
- // 2nd display was disconnected, and the cursor is
- // now in the 1st display.
- UpdateDisplay("500x400");
- EXPECT_EQ(gfx::Point(55, 350), env->last_mouse_location());
- // 1st display's resolution has changed, and the mouse pointer is
- // now outside. Move the mouse pointer to the center of 1st display.
- UpdateDisplay("400x300");
- EXPECT_EQ(gfx::Point(200, 150), env->last_mouse_location());
- // Move the mouse pointer to the bottom of 1st display.
- ui::test::EventGenerator generator_on_1st(root_windows[0]);
- generator_on_1st.MoveMouseToInHost(150, 290);
- EXPECT_EQ(gfx::Point(150, 290), env->last_mouse_location());
- // The mouse pointer is now on 2nd display.
- UpdateDisplay("300x280,300x200");
- EXPECT_EQ(gfx::Point(450, 10), env->last_mouse_location());
- }
- TEST_F(WindowTreeHostManagerTest,
- DontUpdateInvisibleCursorLocationAfterDisplayChange) {
- UpdateDisplay("500x300");
- aura::Window::Windows root_windows = Shell::GetAllRootWindows();
- aura::Env* env = aura::Env::GetInstance();
- ui::test::EventGenerator generator(root_windows[0]);
- // Logical cursor location is updated to keep the same physical location.
- generator.MoveMouseToInHost(350, 150);
- EXPECT_EQ(gfx::Point(350, 150), env->last_mouse_location());
- UpdateDisplay("300x500/r");
- EXPECT_EQ(gfx::Point(250, 150), env->last_mouse_location());
- // Logical cursor location change shouldn't change when the cursor isn't
- // visible.
- UpdateDisplay("500x300");
- generator.MoveMouseToInHost(350, 150);
- EXPECT_EQ(gfx::Point(350, 150), env->last_mouse_location());
- Shell::Get()->cursor_manager()->HideCursor();
- UpdateDisplay("300x500/r");
- EXPECT_EQ(gfx::Point(350, 150), env->last_mouse_location());
- }
- TEST_F(WindowTreeHostManagerTest,
- UpdateMouseLocationAfterDisplayChange_2ndOnLeft) {
- // Set the 2nd display on the left.
- display::DisplayLayoutStore* layout_store = display_manager()->layout_store();
- display::DisplayPlacement new_default(display::DisplayPlacement::LEFT, 0);
- layout_store->SetDefaultDisplayPlacement(new_default);
- UpdateDisplay("300x200,400x300");
- aura::Window::Windows root_windows = Shell::GetAllRootWindows();
- EXPECT_EQ(gfx::Rect(-400, 0, 400, 300),
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .bounds());
- aura::Env* env = aura::Env::GetInstance();
- // Set the initial position.
- root_windows[0]->MoveCursorTo(gfx::Point(-150, 250));
- EXPECT_EQ(gfx::Point(-150, 250), env->last_mouse_location());
- // A mouse pointer will stay in 2nd display.
- UpdateDisplay("400x300,200x300");
- EXPECT_EQ(gfx::Point(-100, 150), env->last_mouse_location());
- // A mouse pointer will be outside of displays and move to the
- // center of 2nd display.
- UpdateDisplay("400x300,200x100");
- EXPECT_EQ(gfx::Point(-100, 50), env->last_mouse_location());
- // 2nd display was disconnected. Mouse pointer should move to
- // 1st display.
- UpdateDisplay("400x300");
- EXPECT_EQ(gfx::Point(200, 150), env->last_mouse_location());
- }
- // Test that the cursor swaps displays and that its scale factor and rotation
- // are updated when the primary display is swapped.
- TEST_F(WindowTreeHostManagerTest,
- UpdateMouseLocationAfterDisplayChange_SwapPrimary) {
- UpdateDisplay("300x200,300x200*2/r");
- aura::Env* env = aura::Env::GetInstance();
- Shell* shell = Shell::Get();
- WindowTreeHostManager* window_tree_host_manager =
- shell->window_tree_host_manager();
- auto* cursor_manager = shell->cursor_manager();
- CursorManagerTestApi test_api;
- window_tree_host_manager->GetPrimaryRootWindow()->MoveCursorTo(
- gfx::Point(20, 50));
- EXPECT_EQ(gfx::Point(20, 50), env->last_mouse_location());
- EXPECT_EQ(1.0f, cursor_manager->GetCursor().image_scale_factor());
- EXPECT_EQ(display::Display::ROTATE_0, test_api.GetCurrentCursorRotation());
- SwapPrimaryDisplay();
- EXPECT_EQ(gfx::Point(20, 50), env->last_mouse_location());
- EXPECT_EQ(2.0f, cursor_manager->GetCursor().image_scale_factor());
- EXPECT_EQ(display::Display::ROTATE_90, test_api.GetCurrentCursorRotation());
- }
- // Test that the cursor moves to the other display and that its scale factor
- // and rotation are updated when the primary display is disconnected.
- TEST_F(WindowTreeHostManagerTest,
- UpdateMouseLocationAfterDisplayChange_PrimaryDisconnected) {
- aura::Env* env = aura::Env::GetInstance();
- Shell* shell = Shell::Get();
- WindowTreeHostManager* window_tree_host_manager =
- shell->window_tree_host_manager();
- auto* cursor_manager = shell->cursor_manager();
- CursorManagerTestApi test_api;
- UpdateDisplay("400x300*2/r,300x200");
- // Swap the primary display to make it possible to remove the primary display
- // via UpdateDisplay().
- SwapPrimaryDisplay();
- int primary_display_id = window_tree_host_manager->GetPrimaryDisplayId();
- window_tree_host_manager->GetPrimaryRootWindow()->MoveCursorTo(
- gfx::Point(20, 50));
- EXPECT_EQ(gfx::Point(20, 50), env->last_mouse_location());
- EXPECT_EQ(1.0f, cursor_manager->GetCursor().image_scale_factor());
- EXPECT_EQ(display::Display::ROTATE_0, test_api.GetCurrentCursorRotation());
- UpdateDisplay("400x300*2/r");
- ASSERT_NE(primary_display_id,
- window_tree_host_manager->GetPrimaryDisplayId());
- // Cursor should be centered on the remaining display.
- EXPECT_EQ(gfx::Point(75, 100), env->last_mouse_location());
- EXPECT_EQ(2.0f, cursor_manager->GetCursor().image_scale_factor());
- EXPECT_EQ(display::Display::ROTATE_90, test_api.GetCurrentCursorRotation());
- }
- TEST_F(WindowTreeHostManagerTest,
- UpdateNonVisibleMouseLocationAfterDisplayChange_PrimaryDisconnected) {
- aura::Env* env = aura::Env::GetInstance();
- Shell* shell = Shell::Get();
- WindowTreeHostManager* window_tree_host_manager =
- shell->window_tree_host_manager();
- auto* cursor_manager = shell->cursor_manager();
- CursorManagerTestApi test_api;
- UpdateDisplay("400x300*2/r,300x200");
- // Swap the primary display to make it possible to remove the primary display
- // via UpdateDisplay().
- SwapPrimaryDisplay();
- int primary_display_id = window_tree_host_manager->GetPrimaryDisplayId();
- gfx::Point cursor_location(20, 50);
- window_tree_host_manager->GetPrimaryRootWindow()->MoveCursorTo(
- cursor_location);
- // Hide cursor before disconnecting the display.
- cursor_manager->HideCursor();
- EXPECT_EQ(cursor_location, env->last_mouse_location());
- EXPECT_EQ(1.0f, cursor_manager->GetCursor().image_scale_factor());
- EXPECT_EQ(display::Display::ROTATE_0, test_api.GetCurrentCursorRotation());
- UpdateDisplay("400x300*2/r");
- ASSERT_NE(primary_display_id,
- window_tree_host_manager->GetPrimaryDisplayId());
- // Show the mouse cursor before checking properties which should be as if the
- // mouse cursor was never hidden.
- cursor_manager->ShowCursor();
- // The cursor will not be centered since it was hidden when the display list
- // was updated.
- EXPECT_EQ(gfx::Point(20, 50), env->last_mouse_location());
- // The cursor scale and rotation should be updated.
- EXPECT_EQ(2.0f, cursor_manager->GetCursor().image_scale_factor());
- EXPECT_EQ(display::Display::ROTATE_90, test_api.GetCurrentCursorRotation());
- }
- // GetRootWindowForDisplayId() for removed display::Display during
- // OnDisplayRemoved() should not cause crash. See http://crbug.com/415222
- TEST_F(WindowTreeHostManagerTest,
- GetRootWindowForDisplayIdDuringDisplayDisconnection) {
- UpdateDisplay("400x300,300x200");
- aura::Window* root2 =
- Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId(
- display::test::DisplayManagerTestApi(display_manager())
- .GetSecondaryDisplay()
- .id());
- views::Widget* widget = views::Widget::CreateWindowWithContext(
- nullptr, root2, gfx::Rect(350, 0, 100, 100));
- views::View* view = new views::View();
- widget->GetContentsView()->AddChildView(view);
- view->SetBounds(0, 0, 100, 100);
- widget->Show();
- TestMouseWatcherListener listener;
- views::MouseWatcher watcher(
- std::make_unique<views::MouseWatcherViewHost>(view, gfx::Insets()),
- &listener);
- watcher.Start(root2);
- ui::test::EventGenerator event_generator(
- widget->GetNativeWindow()->GetRootWindow());
- event_generator.MoveMouseToCenterOf(widget->GetNativeWindow());
- UpdateDisplay("400x300");
- watcher.Stop();
- widget->CloseNow();
- }
- // Replicates the behavior of MouseWatcher MouseEvent handling that led to crash
- // in https://crbug.com/1278429.
- class RootWindowTestEventHandler : public ui::EventHandler {
- public:
- explicit RootWindowTestEventHandler() = default;
- RootWindowTestEventHandler(const RootWindowTestEventHandler&) = delete;
- RootWindowTestEventHandler& operator=(const RootWindowTestEventHandler&) =
- delete;
- ~RootWindowTestEventHandler() override = default;
- private:
- // ui::EventHandler overrides:
- void OnMouseEvent(ui::MouseEvent* event) override {
- // Crash happened when finding the display in
- // |screen::GetDisplayNearestPoint()|, we got the display that was being
- // removed and in turn got null root window from
- // |window_util::GetRootWindowAt| since the root window was moved to the new
- // primary display.
- display::Screen::GetScreen()->GetWindowAtScreenPoint(
- display::Screen::GetScreen()->GetCursorScreenPoint());
- }
- };
- // Tests for the crash during the replacement of the primary display.
- // See https://crbug.com/1278429.
- TEST_F(WindowTreeHostManagerTest, GetActiveDisplayWhenReplacingPrimaryDisplay) {
- // We observed a crash during handling of a MouseEvent.
- UpdateDisplay("800x600");
- aura::Window* root_window =
- Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId(
- GetPrimaryDisplay().id());
- RootWindowTestEventHandler handler;
- root_window->AddPreTargetHandler(&handler);
- ui::test::EventGenerator generator(root_window);
- // Move the cursor to a coordinate that is in the logical bounds of the older
- // display[0,0 800x600] but not in the logical bounds[0,0 350x250] of the new
- // display. The cursor coordinates also needs to be in the root window's
- // bounds[0,0 700x500] attached to the new primary display.
- generator.MoveMouseTo(400, 300);
- // Replace the primary display with a newer display with a different device
- // scale factor compared to original display.
- display::ManagedDisplayInfo first_display_info =
- CreateDisplayInfo(100, 0, display::Display::ROTATE_0);
- first_display_info.SetBounds(gfx::Rect(0, 0, 700, 500));
- first_display_info.set_device_scale_factor(2.0);
- std::vector<display::ManagedDisplayInfo> display_info_list;
- display_info_list.push_back(first_display_info);
- display_manager()->OnNativeDisplaysChanged(display_info_list);
- root_window->RemovePreTargetHandler(&handler);
- }
- TEST_F(WindowTreeHostManagerTest, KeyEventFromSecondaryDisplay) {
- UpdateDisplay("400x300,300x200");
- ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, 0);
- ui::Event::DispatcherApi dispatcher_api(&key_event);
- // Set the target to the second display. WindowTreeHostManager will end up
- // targeting the primary display.
- dispatcher_api.set_target(
- Shell::Get()->window_tree_host_manager()->GetRootWindowForDisplayId(
- GetSecondaryDisplay().id()));
- Shell::Get()->window_tree_host_manager()->DispatchKeyEventPostIME(&key_event);
- // As long as nothing crashes, we're good.
- }
- } // namespace ash
|