| // 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/common/ash_switches.h" |
| #include "ash/common/display/display_info.h" |
| #include "ash/common/material_design/material_design_controller.h" |
| #include "ash/common/wm/window_state.h" |
| #include "ash/common/wm/wm_event.h" |
| #include "ash/display/display_layout_store.h" |
| #include "ash/display/display_manager.h" |
| #include "ash/display/display_util.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_md_test_base.h" |
| #include "ash/test/ash_test_base.h" |
| #include "ash/test/ash_test_helper.h" |
| #include "ash/test/cursor_manager_test_api.h" |
| #include "ash/test/display_manager_test_api.h" |
| #include "ash/test/test_shell_delegate.h" |
| #include "ash/wm/window_state_aura.h" |
| #include "base/command_line.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/display/display.h" |
| #include "ui/display/display_observer.h" |
| #include "ui/display/manager/display_layout.h" |
| #include "ui/display/screen.h" |
| #include "ui/events/event_handler.h" |
| #include "ui/events/test/event_generator.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/public/activation_change_observer.h" |
| #include "ui/wm/public/activation_client.h" |
| |
| namespace ash { |
| namespace { |
| |
| const char kDesktopBackgroundView[] = "DesktopBackgroundView"; |
| |
| template <typename T> |
| class Resetter { |
| public: |
| explicit Resetter(T* value) : value_(*value) { *value = 0; } |
| ~Resetter() {} |
| T value() { return value_; } |
| |
| private: |
| T value_; |
| DISALLOW_COPY_AND_ASSIGN(Resetter); |
| }; |
| |
| class TestObserver : public WindowTreeHostManager::Observer, |
| public display::DisplayObserver, |
| public aura::client::FocusChangeObserver, |
| public aura::client::ActivationChangeObserver { |
| public: |
| TestObserver() |
| : changing_count_(0), |
| changed_count_(0), |
| bounds_changed_count_(0), |
| rotation_changed_count_(0), |
| workarea_changed_count_(0), |
| primary_changed_count_(0), |
| changed_display_id_(0), |
| focus_changed_count_(0), |
| activation_changed_count_(0) { |
| Shell::GetInstance()->window_tree_host_manager()->AddObserver(this); |
| display::Screen::GetScreen()->AddObserver(this); |
| aura::client::GetFocusClient(Shell::GetPrimaryRootWindow()) |
| ->AddObserver(this); |
| aura::client::GetActivationClient(Shell::GetPrimaryRootWindow()) |
| ->AddObserver(this); |
| } |
| |
| ~TestObserver() override { |
| Shell::GetInstance()->window_tree_host_manager()->RemoveObserver(this); |
| display::Screen::GetScreen()->RemoveObserver(this); |
| aura::client::GetFocusClient(Shell::GetPrimaryRootWindow()) |
| ->RemoveObserver(this); |
| aura::client::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_; |
| } |
| void OnDisplayAdded(const display::Display& new_display) override {} |
| void OnDisplayRemoved(const display::Display& old_display) override {} |
| |
| // Overridden from aura::client::FocusChangeObserver |
| void OnWindowFocused(aura::Window* gained_focus, |
| aura::Window* lost_focus) override { |
| focus_changed_count_++; |
| } |
| |
| // Overridden from aura::client::ActivationChangeObserver |
| void OnWindowActivated( |
| aura::client::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_; |
| int changed_count_; |
| |
| int bounds_changed_count_; |
| int rotation_changed_count_; |
| int workarea_changed_count_; |
| int primary_changed_count_; |
| int64_t changed_display_id_; |
| |
| int focus_changed_count_; |
| int activation_changed_count_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestObserver); |
| }; |
| |
| display::Display GetPrimaryDisplay() { |
| return display::Screen::GetScreen()->GetDisplayNearestWindow( |
| Shell::GetAllRootWindows()[0]); |
| } |
| |
| display::Display GetSecondaryDisplay() { |
| return display::Screen::GetScreen()->GetDisplayNearestWindow( |
| Shell::GetAllRootWindows()[1]); |
| } |
| |
| void SetSecondaryDisplayLayoutAndOffset( |
| display::DisplayPlacement::Position position, |
| int offset) { |
| std::unique_ptr<display::DisplayLayout> layout( |
| test::CreateDisplayLayout(position, offset)); |
| ASSERT_GT(display::Screen::GetScreen()->GetNumDisplays(), 1); |
| Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays( |
| std::move(layout)); |
| } |
| |
| void SetSecondaryDisplayLayout(display::DisplayPlacement::Position position) { |
| SetSecondaryDisplayLayoutAndOffset(position, 0); |
| } |
| |
| void SetDefaultDisplayLayout(display::DisplayPlacement::Position position) { |
| display::DisplayPlacement default_placement(position, 0); |
| |
| Shell::GetInstance() |
| ->display_manager() |
| ->layout_store() |
| ->SetDefaultDisplayPlacement(default_placement); |
| } |
| |
| class WindowTreeHostManagerShutdownTest : public test::AshTestBase { |
| public: |
| WindowTreeHostManagerShutdownTest() {} |
| ~WindowTreeHostManagerShutdownTest() override {} |
| |
| void TearDown() override { |
| test::AshTestBase::TearDown(); |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| // Make sure that primary display is accessible after shutdown. |
| display::Display primary = |
| display::Screen::GetScreen()->GetPrimaryDisplay(); |
| EXPECT_EQ("0,0 444x333", primary.bounds().ToString()); |
| EXPECT_EQ(2, display::Screen::GetScreen()->GetNumDisplays()); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(WindowTreeHostManagerShutdownTest); |
| }; |
| |
| class StartupHelper : public test::TestShellDelegate, |
| public WindowTreeHostManager::Observer { |
| public: |
| StartupHelper() : displays_initialized_(false) {} |
| ~StartupHelper() override {} |
| |
| // ash::ShellSelegate: |
| void PreInit() override { |
| Shell::GetInstance()->window_tree_host_manager()->AddObserver(this); |
| } |
| |
| // ash::WindowTreeHostManager::Observer: |
| void OnDisplaysInitialized() override { |
| DCHECK(!displays_initialized_); |
| displays_initialized_ = true; |
| } |
| |
| bool displays_initialized() const { return displays_initialized_; } |
| |
| private: |
| bool displays_initialized_; |
| |
| DISALLOW_COPY_AND_ASSIGN(StartupHelper); |
| }; |
| |
| class WindowTreeHostManagerStartupTest : public test::AshTestBase { |
| public: |
| WindowTreeHostManagerStartupTest() : startup_helper_(new StartupHelper) {} |
| ~WindowTreeHostManagerStartupTest() override {} |
| |
| // ash::test::AshTestBase: |
| void SetUp() override { |
| ash_test_helper()->set_test_shell_delegate(startup_helper_); |
| test::AshTestBase::SetUp(); |
| } |
| void TearDown() override { |
| Shell::GetInstance()->window_tree_host_manager()->RemoveObserver( |
| startup_helper_); |
| test::AshTestBase::TearDown(); |
| } |
| |
| const StartupHelper* startup_helper() const { return startup_helper_; } |
| |
| private: |
| StartupHelper* startup_helper_; // Owned by ash::Shell. |
| |
| DISALLOW_COPY_AND_ASSIGN(WindowTreeHostManagerStartupTest); |
| }; |
| |
| 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() override {} |
| |
| 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 background which covers |
| // entire root window. |
| if (target->name() != kDesktopBackgroundView) |
| 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 background which covers |
| // entire root window. |
| if (target->name() != kDesktopBackgroundView) |
| 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(); |
| } |
| |
| std::string GetLocationAndReset() { |
| std::string result = mouse_location_.ToString(); |
| 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_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestEventHandler); |
| }; |
| |
| float GetStoredUIScale(int64_t id) { |
| return Shell::GetInstance() |
| ->display_manager() |
| ->GetDisplayInfo(id) |
| .GetEffectiveUIScale(); |
| } |
| |
| class TestMouseWatcherListener : public views::MouseWatcherListener { |
| public: |
| TestMouseWatcherListener() {} |
| |
| private: |
| // views::MouseWatcherListener: |
| void MouseMovedOutOfHost() override {} |
| |
| DISALLOW_COPY_AND_ASSIGN(TestMouseWatcherListener); |
| }; |
| |
| } // namespace |
| |
| using WindowTreeHostManagerTest = test::AshMDTestBase; |
| |
| INSTANTIATE_TEST_CASE_P( |
| /* prefix intentionally left blank due to only one parameterization */, |
| WindowTreeHostManagerTest, |
| testing::Values(MaterialDesignController::NON_MATERIAL, |
| MaterialDesignController::MATERIAL_NORMAL, |
| MaterialDesignController::MATERIAL_EXPERIMENTAL)); |
| |
| TEST_F(WindowTreeHostManagerShutdownTest, Shutdown) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| UpdateDisplay("444x333, 200x200"); |
| } |
| |
| TEST_F(WindowTreeHostManagerStartupTest, Startup) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| EXPECT_TRUE(startup_helper()->displays_initialized()); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, SecondaryDisplayLayout) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| // Creates windows to catch activation change event. |
| std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1)); |
| w1->Focus(); |
| |
| TestObserver observer; |
| UpdateDisplay("500x500,400x400"); |
| 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()); |
| gfx::Insets insets(5, 5, 5, 5); |
| int64_t secondary_display_id = ScreenUtil::GetSecondaryDisplay().id(); |
| Shell::GetInstance()->display_manager()->UpdateWorkAreaOfDisplay( |
| secondary_display_id, insets); |
| |
| // Default layout is RIGHT. |
| EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("500,0 400x400", GetSecondaryDisplay().bounds().ToString()); |
| EXPECT_EQ("505,5 390x390", GetSecondaryDisplay().work_area().ToString()); |
| 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()); |
| EXPECT_EQ(1, observer.GetWorkareaChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); |
| EXPECT_EQ(secondary_display_id, observer.GetChangedDisplayIdAndReset()); |
| EXPECT_EQ("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("0,500 400x400", GetSecondaryDisplay().bounds().ToString()); |
| EXPECT_EQ("5,505 390x390", GetSecondaryDisplay().work_area().ToString()); |
| |
| // 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("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("-400,0 400x400", GetSecondaryDisplay().bounds().ToString()); |
| EXPECT_EQ("-395,5 390x390", GetSecondaryDisplay().work_area().ToString()); |
| |
| // 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("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("0,-400 400x400", GetSecondaryDisplay().bounds().ToString()); |
| EXPECT_EQ("5,-395 390x390", GetSecondaryDisplay().work_area().ToString()); |
| |
| // 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("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("500,300 400x400", GetSecondaryDisplay().bounds().ToString()); |
| |
| // 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("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("500,400 400x400", GetSecondaryDisplay().bounds().ToString()); |
| |
| 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("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("500,-300 400x400", GetSecondaryDisplay().bounds().ToString()); |
| |
| // 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("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("-200,500 400x400", GetSecondaryDisplay().bounds().ToString()); |
| |
| // Keep the minimum 100. |
| SetSecondaryDisplayLayoutAndOffset(display::DisplayPlacement::BOTTOM, 490); |
| 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("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("400,500 400x400", GetSecondaryDisplay().bounds().ToString()); |
| |
| SetSecondaryDisplayLayoutAndOffset(display::DisplayPlacement::BOTTOM, -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("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString()); |
| |
| // Setting the same layout shouldn't invoke observers. |
| SetSecondaryDisplayLayoutAndOffset(display::DisplayPlacement::BOTTOM, -400); |
| 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("0,0 500x500", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("-300,500 400x400", GetSecondaryDisplay().bounds().ToString()); |
| |
| UpdateDisplay("500x500"); |
| EXPECT_LE(1, observer.GetFocusChangedCountAndReset()); |
| EXPECT_LE(1, observer.GetActivationChangedCountAndReset()); |
| } |
| |
| namespace { |
| |
| DisplayInfo CreateDisplayInfo(int64_t id, |
| int y, |
| display::Display::Rotation rotation) { |
| DisplayInfo info(id, "", false); |
| info.SetBounds(gfx::Rect(0, y, 500, 500)); |
| info.SetRotation(rotation, display::Display::ROTATION_SOURCE_ACTIVE); |
| return info; |
| } |
| |
| DisplayInfo CreateMirroredDisplayInfo(int64_t id, float device_scale_factor) { |
| DisplayInfo info = CreateDisplayInfo(id, 0, display::Display::ROTATE_0); |
| info.set_device_scale_factor(device_scale_factor); |
| return info; |
| } |
| |
| } // namespace |
| |
| TEST_P(WindowTreeHostManagerTest, MirrorToDockedWithFullscreen) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| // Creates windows to catch activation change event. |
| std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1)); |
| w1->Focus(); |
| |
| // Docked mode. |
| DisplayManager* display_manager = Shell::GetInstance()->display_manager(); |
| |
| const DisplayInfo internal_display_info = CreateMirroredDisplayInfo(1, 2.0f); |
| const DisplayInfo external_display_info = CreateMirroredDisplayInfo(2, 1.0f); |
| |
| std::vector<DisplayInfo> 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 = |
| test::DisplayManagerTestApi().SetFirstDisplayAsInternalDisplay(); |
| EXPECT_EQ(1, internal_display_id); |
| EXPECT_EQ(2U, display_manager->num_connected_displays()); |
| EXPECT_EQ(1U, display_manager->GetNumDisplays()); |
| |
| wm::WindowState* window_state = wm::GetWindowState(w1.get()); |
| const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN); |
| window_state->OnWMEvent(&toggle_fullscreen_event); |
| EXPECT_TRUE(window_state->IsFullscreen()); |
| EXPECT_EQ("0,0 250x250", w1->bounds().ToString()); |
| // 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("0,0 500x500", w1->bounds().ToString()); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, BoundsUpdated) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| // Creates windows to catch activation change event. |
| std::unique_ptr<aura::Window> w1(CreateTestWindowInShellWithId(1)); |
| w1->Focus(); |
| |
| TestObserver observer; |
| SetDefaultDisplayLayout(display::DisplayPlacement::BOTTOM); |
| UpdateDisplay("200x200,300x300"); // layout, resize and add. |
| EXPECT_EQ(1, observer.CountAndReset()); |
| EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); |
| |
| DisplayManager* display_manager = Shell::GetInstance()->display_manager(); |
| gfx::Insets insets(5, 5, 5, 5); |
| display_manager->UpdateWorkAreaOfDisplay( |
| ScreenUtil::GetSecondaryDisplay().id(), insets); |
| |
| EXPECT_EQ("0,0 200x200", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("0,200 300x300", GetSecondaryDisplay().bounds().ToString()); |
| EXPECT_EQ("5,205 290x290", GetSecondaryDisplay().work_area().ToString()); |
| |
| UpdateDisplay("400x400,200x200"); |
| EXPECT_EQ(1, observer.CountAndReset()); // two resizes |
| EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); |
| EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("0,400 200x200", GetSecondaryDisplay().bounds().ToString()); |
| |
| UpdateDisplay("400x400,300x300"); |
| EXPECT_EQ(1, observer.CountAndReset()); |
| EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); |
| EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("0,400 300x300", GetSecondaryDisplay().bounds().ToString()); |
| |
| UpdateDisplay("400x400"); |
| EXPECT_EQ(1, observer.CountAndReset()); |
| EXPECT_LE(1, observer.GetFocusChangedCountAndReset()); |
| EXPECT_LE(1, observer.GetActivationChangedCountAndReset()); |
| EXPECT_EQ("0,0 400x400", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ(1, display::Screen::GetScreen()->GetNumDisplays()); |
| |
| UpdateDisplay("400x500*2,300x300"); |
| EXPECT_EQ(1, observer.CountAndReset()); |
| EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); |
| ASSERT_EQ(2, display::Screen::GetScreen()->GetNumDisplays()); |
| EXPECT_EQ("0,0 200x250", GetPrimaryDisplay().bounds().ToString()); |
| EXPECT_EQ("0,250 300x300", GetSecondaryDisplay().bounds().ToString()); |
| |
| // No change |
| UpdateDisplay("400x500*2,300x300"); |
| // 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::ROTATION_SOURCE_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::ROTATION_SOURCE_ACTIVE); |
| EXPECT_EQ(0, observer.GetRotationChangedCountAndReset()); |
| EXPECT_EQ(0, observer.CountAndReset()); |
| EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); |
| |
| // UI scale is eanbled only on internal display. |
| int64_t secondary_id = GetSecondaryDisplay().id(); |
| test::ScopedSetInternalDisplayId set_internal(secondary_id); |
| // Changing internal ID display changes the DisplayIdPair (it comes |
| // first), which also changes the primary display candidate. Update |
| // the primary display manually to update the primary display to |
| // avoid getting the OnDisplayConfigurationChanged() call twice in |
| // SetDisplayUIScale. Note that this scenario will never happen on |
| // real devices. |
| Shell::GetInstance()->window_tree_host_manager()->SetPrimaryDisplayId( |
| secondary_id); |
| EXPECT_EQ(1, observer.CountAndReset()); |
| |
| SetDisplayUIScale(secondary_id, 1.125f); |
| EXPECT_EQ(1, observer.CountAndReset()); |
| EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); |
| SetDisplayUIScale(secondary_id, 1.125f); |
| EXPECT_EQ(0, observer.CountAndReset()); |
| EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); |
| SetDisplayUIScale(primary_id, 1.125f); |
| EXPECT_EQ(0, observer.CountAndReset()); |
| EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); |
| SetDisplayUIScale(primary_id, 1.125f); |
| EXPECT_EQ(0, observer.CountAndReset()); |
| EXPECT_EQ(0, observer.GetFocusChangedCountAndReset()); |
| EXPECT_EQ(0, observer.GetActivationChangedCountAndReset()); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, FindNearestDisplay) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| WindowTreeHostManager* window_tree_host_manager = |
| Shell::GetInstance()->window_tree_host_manager(); |
| DisplayManager* display_manager = Shell::GetInstance()->display_manager(); |
| |
| UpdateDisplay("200x200,300x300"); |
| display_manager->SetLayoutForCurrentDisplays( |
| test::CreateDisplayLayout(display::DisplayPlacement::RIGHT, 50)); |
| |
| display::Display primary_display = |
| display::Screen::GetScreen()->GetPrimaryDisplay(); |
| display::Display secondary_display = ScreenUtil::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(174, 225)) |
| .id()); |
| EXPECT_EQ(secondary_display.id(), |
| display::Screen::GetScreen() |
| ->GetDisplayNearestPoint(gfx::Point(176, 225)) |
| .id()); |
| EXPECT_EQ(secondary_display.id(), |
| display::Screen::GetScreen() |
| ->GetDisplayNearestPoint(gfx::Point(300, 400)) |
| .id()); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, SwapPrimaryById) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| const int height_offset = GetMdMaximizedWindowHeightOffset(); |
| |
| WindowTreeHostManager* window_tree_host_manager = |
| Shell::GetInstance()->window_tree_host_manager(); |
| DisplayManager* display_manager = Shell::GetInstance()->display_manager(); |
| |
| UpdateDisplay("200x200,300x300"); |
| display::Display primary_display = |
| display::Screen::GetScreen()->GetPrimaryDisplay(); |
| display::Display secondary_display = ScreenUtil::GetSecondaryDisplay(); |
| |
| display_manager->SetLayoutForCurrentDisplays( |
| test::CreateDisplayLayout(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 = |
| Shelf::ForPrimaryDisplay()->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("0,0 200x200", primary_display.bounds().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 200, 153 + height_offset).ToString(), |
| primary_display.work_area().ToString()); |
| EXPECT_EQ("200,0 300x300", secondary_display.bounds().ToString()); |
| EXPECT_EQ(gfx::Rect(200, 0, 300, 253 + height_offset).ToString(), |
| secondary_display.work_area().ToString()); |
| EXPECT_EQ( |
| "id=2200000001, 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(), ScreenUtil::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=2200000001, 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 = ScreenUtil::GetSecondaryDisplay(); |
| EXPECT_EQ("0,0 300x300", swapped_primary.bounds().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 300, 253 + height_offset).ToString(), |
| swapped_primary.work_area().ToString()); |
| EXPECT_EQ("-200,-50 200x200", swapped_secondary.bounds().ToString()); |
| EXPECT_EQ(gfx::Rect(-200, -50, 200, 153 + height_offset).ToString(), |
| swapped_secondary.work_area().ToString()); |
| |
| // 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("200x200"); |
| RunAllPendingInMessageLoop(); // 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<DisplayInfo> 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(), ScreenUtil::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("200x200"); |
| DisplayInfo 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 DisplayInfo& primary_display_info = |
| display_manager->GetDisplayInfo(primary_display.id()); |
| std::vector<DisplayInfo> 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(), ScreenUtil::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_P(WindowTreeHostManagerTest, NoSwapPrimaryWithThreeDisplays) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| int64_t primary = display::Screen::GetScreen()->GetPrimaryDisplay().id(); |
| UpdateDisplay("500x400,400x300,300x200"); |
| EXPECT_EQ(primary, display::Screen::GetScreen()->GetPrimaryDisplay().id()); |
| Shell::GetInstance()->window_tree_host_manager()->SetPrimaryDisplayId( |
| ScreenUtil::GetSecondaryDisplay().id()); |
| EXPECT_EQ(primary, display::Screen::GetScreen()->GetPrimaryDisplay().id()); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, OverscanInsets) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| WindowTreeHostManager* window_tree_host_manager = |
| Shell::GetInstance()->window_tree_host_manager(); |
| TestEventHandler event_handler; |
| Shell::GetInstance()->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(10, 15, 20, 25)); |
| EXPECT_EQ("0,0 80x170", root_windows[0]->bounds().ToString()); |
| EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); |
| EXPECT_EQ("80,0 150x200", |
| ScreenUtil::GetSecondaryDisplay().bounds().ToString()); |
| |
| ui::test::EventGenerator generator(root_windows[0]); |
| generator.MoveMouseToInHost(20, 25); |
| EXPECT_EQ("5,15", event_handler.GetLocationAndReset()); |
| |
| window_tree_host_manager->SetOverscanInsets(display1.id(), gfx::Insets()); |
| EXPECT_EQ("0,0 120x200", root_windows[0]->bounds().ToString()); |
| EXPECT_EQ("120,0 150x200", |
| ScreenUtil::GetSecondaryDisplay().bounds().ToString()); |
| |
| generator.MoveMouseToInHost(30, 20); |
| EXPECT_EQ("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("15,10", point.ToString()); |
| |
| test::SwapPrimaryDisplay(); |
| point.SetPoint(0, 0); |
| Shell::GetAllRootWindows()[1]->GetHost()->GetRootTransform().TransformPoint( |
| &point); |
| EXPECT_EQ("15,10", point.ToString()); |
| |
| Shell::GetInstance()->RemovePreTargetHandler(&event_handler); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, Rotate) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| DisplayManager* display_manager = Shell::GetInstance()->display_manager(); |
| TestEventHandler event_handler; |
| Shell::GetInstance()->AddPreTargetHandler(&event_handler); |
| |
| UpdateDisplay("120x200,300x400*2"); |
| display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); |
| int64_t display2_id = ScreenUtil::GetSecondaryDisplay().id(); |
| aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
| ui::test::EventGenerator generator1(root_windows[0]); |
| |
| TestObserver observer; |
| EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString()); |
| EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); |
| EXPECT_EQ("120,0 150x200", |
| ScreenUtil::GetSecondaryDisplay().bounds().ToString()); |
| generator1.MoveMouseToInHost(50, 40); |
| EXPECT_EQ("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::ROTATION_SOURCE_ACTIVE); |
| EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); |
| EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString()); |
| EXPECT_EQ("200,0 150x200", |
| ScreenUtil::GetSecondaryDisplay().bounds().ToString()); |
| generator1.MoveMouseToInHost(50, 40); |
| EXPECT_EQ("40,69", 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( |
| test::CreateDisplayLayout(display::DisplayPlacement::BOTTOM, 50)); |
| EXPECT_EQ("50,120 150x200", |
| ScreenUtil::GetSecondaryDisplay().bounds().ToString()); |
| |
| display_manager->SetDisplayRotation(display2_id, display::Display::ROTATE_270, |
| display::Display::ROTATION_SOURCE_ACTIVE); |
| EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString()); |
| EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); |
| EXPECT_EQ("50,120 200x150", |
| ScreenUtil::GetSecondaryDisplay().bounds().ToString()); |
| EXPECT_EQ(display::Display::ROTATE_90, |
| GetActiveDisplayRotation(display1.id())); |
| EXPECT_EQ(display::Display::ROTATE_270, |
| GetActiveDisplayRotation(display2_id)); |
| EXPECT_EQ(1, observer.GetRotationChangedCountAndReset()); |
| |
| #if !defined(OS_WIN) |
| ui::test::EventGenerator generator2(root_windows[1]); |
| generator2.MoveMouseToInHost(50, 40); |
| EXPECT_EQ("179,25", event_handler.GetLocationAndReset()); |
| display_manager->SetDisplayRotation(display1.id(), |
| display::Display::ROTATE_180, |
| display::Display::ROTATION_SOURCE_ACTIVE); |
| |
| EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString()); |
| EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString()); |
| // Dislay must share at least 100, so the x's offset becomes 20. |
| EXPECT_EQ("20,200 200x150", |
| ScreenUtil::GetSecondaryDisplay().bounds().ToString()); |
| 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("69,159", event_handler.GetLocationAndReset()); |
| #endif |
| |
| Shell::GetInstance()->RemovePreTargetHandler(&event_handler); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, ScaleRootWindow) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| TestEventHandler event_handler; |
| Shell::GetInstance()->AddPreTargetHandler(&event_handler); |
| |
| UpdateDisplay("600x400*2@1.5,500x300"); |
| |
| display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); |
| test::ScopedSetInternalDisplayId set_internal(display1.id()); |
| |
| display::Display display2 = ScreenUtil::GetSecondaryDisplay(); |
| aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
| EXPECT_EQ("0,0 450x300", display1.bounds().ToString()); |
| EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString()); |
| EXPECT_EQ("450,0 500x300", display2.bounds().ToString()); |
| EXPECT_EQ(1.5f, GetStoredUIScale(display1.id())); |
| EXPECT_EQ(1.0f, GetStoredUIScale(display2.id())); |
| |
| ui::test::EventGenerator generator(root_windows[0]); |
| generator.MoveMouseToInHost(599, 200); |
| EXPECT_EQ("449,150", event_handler.GetLocationAndReset()); |
| |
| SetDisplayUIScale(display1.id(), 1.25f); |
| display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); |
| display2 = ScreenUtil::GetSecondaryDisplay(); |
| EXPECT_EQ("0,0 375x250", display1.bounds().ToString()); |
| EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString()); |
| EXPECT_EQ("375,0 500x300", display2.bounds().ToString()); |
| EXPECT_EQ(1.25f, GetStoredUIScale(display1.id())); |
| EXPECT_EQ(1.0f, GetStoredUIScale(display2.id())); |
| |
| Shell::GetInstance()->RemovePreTargetHandler(&event_handler); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, TouchScale) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| TestEventHandler event_handler; |
| Shell::GetInstance()->AddPreTargetHandler(&event_handler); |
| |
| UpdateDisplay("200x200*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::TimeDelta::FromMilliseconds(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::GetInstance()->RemovePreTargetHandler(&event_handler); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, ConvertHostToRootCoords) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| TestEventHandler event_handler; |
| Shell::GetInstance()->AddPreTargetHandler(&event_handler); |
| |
| UpdateDisplay("600x400*2/r@1.5"); |
| |
| display::Display display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); |
| aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
| EXPECT_EQ("0,0 300x450", display1.bounds().ToString()); |
| EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString()); |
| EXPECT_EQ(1.5f, GetStoredUIScale(display1.id())); |
| |
| ui::test::EventGenerator generator(root_windows[0]); |
| generator.MoveMouseToInHost(0, 0); |
| EXPECT_EQ("0,449", event_handler.GetLocationAndReset()); |
| generator.MoveMouseToInHost(599, 0); |
| EXPECT_EQ("0,0", event_handler.GetLocationAndReset()); |
| generator.MoveMouseToInHost(599, 399); |
| EXPECT_EQ("299,0", event_handler.GetLocationAndReset()); |
| generator.MoveMouseToInHost(0, 399); |
| EXPECT_EQ("299,449", event_handler.GetLocationAndReset()); |
| |
| UpdateDisplay("600x400*2/u@1.5"); |
| display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); |
| root_windows = Shell::GetAllRootWindows(); |
| EXPECT_EQ("0,0 450x300", display1.bounds().ToString()); |
| EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString()); |
| EXPECT_EQ(1.5f, GetStoredUIScale(display1.id())); |
| |
| generator.MoveMouseToInHost(0, 0); |
| EXPECT_EQ("449,299", event_handler.GetLocationAndReset()); |
| generator.MoveMouseToInHost(599, 0); |
| EXPECT_EQ("0,299", event_handler.GetLocationAndReset()); |
| generator.MoveMouseToInHost(599, 399); |
| EXPECT_EQ("0,0", event_handler.GetLocationAndReset()); |
| generator.MoveMouseToInHost(0, 399); |
| EXPECT_EQ("449,0", event_handler.GetLocationAndReset()); |
| |
| UpdateDisplay("600x400*2/l@1.5"); |
| display1 = display::Screen::GetScreen()->GetPrimaryDisplay(); |
| root_windows = Shell::GetAllRootWindows(); |
| EXPECT_EQ("0,0 300x450", display1.bounds().ToString()); |
| EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString()); |
| EXPECT_EQ(1.5f, GetStoredUIScale(display1.id())); |
| |
| generator.MoveMouseToInHost(0, 0); |
| EXPECT_EQ("299,0", event_handler.GetLocationAndReset()); |
| generator.MoveMouseToInHost(599, 0); |
| EXPECT_EQ("299,449", event_handler.GetLocationAndReset()); |
| generator.MoveMouseToInHost(599, 399); |
| EXPECT_EQ("0,449", event_handler.GetLocationAndReset()); |
| generator.MoveMouseToInHost(0, 399); |
| EXPECT_EQ("0,0", event_handler.GetLocationAndReset()); |
| |
| Shell::GetInstance()->RemovePreTargetHandler(&event_handler); |
| } |
| |
| // Make sure that the compositor based mirroring can switch |
| // from/to dock mode. |
| TEST_P(WindowTreeHostManagerTest, DockToSingle) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| DisplayManager* display_manager = Shell::GetInstance()->display_manager(); |
| |
| const int64_t internal_id = 1; |
| |
| const DisplayInfo internal_display_info = |
| CreateDisplayInfo(internal_id, 0, display::Display::ROTATE_0); |
| const DisplayInfo external_display_info = |
| CreateDisplayInfo(2, 1, display::Display::ROTATE_90); |
| |
| std::vector<DisplayInfo> 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 = |
| test::DisplayManagerTestApi().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_P(WindowTreeHostManagerTest, ReplaceSwappedPrimary) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| DisplayManager* display_manager = Shell::GetInstance()->display_manager(); |
| |
| const DisplayInfo first_display_info = |
| CreateDisplayInfo(10, 0, display::Display::ROTATE_0); |
| const DisplayInfo second_display_info = |
| CreateDisplayInfo(11, 1, display::Display::ROTATE_0); |
| |
| std::vector<DisplayInfo> 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); |
| |
| test::SwapPrimaryDisplay(); |
| |
| EXPECT_EQ(11, display::Screen::GetScreen()->GetPrimaryDisplay().id()); |
| |
| display_info_list.clear(); |
| const DisplayInfo new_first_display_info = |
| CreateDisplayInfo(20, 0, display::Display::ROTATE_0); |
| const DisplayInfo 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() {} |
| ~RootWindowTestObserver() override {} |
| |
| void OnWindowBoundsChanged(aura::Window* window, |
| const gfx::Rect& old_bounds, |
| const gfx::Rect& new_bounds) override { |
| shelf_display_bounds_ = ScreenUtil::GetShelfDisplayBoundsInRoot(window); |
| } |
| |
| const gfx::Rect& shelf_display_bounds() const { |
| return shelf_display_bounds_; |
| } |
| |
| private: |
| gfx::Rect shelf_display_bounds_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RootWindowTestObserver); |
| }; |
| |
| } // names |
| |
| // Make sure that GetShelfDisplayBoundsInRoot returns the correct bounds |
| // when primary display gets replaced in a following scenario. |
| // 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_P(WindowTreeHostManagerTest, ReplacePrimary) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| DisplayManager* display_manager = Shell::GetInstance()->display_manager(); |
| |
| DisplayInfo first_display_info = |
| CreateDisplayInfo(10, 0, display::Display::ROTATE_0); |
| first_display_info.SetBounds(gfx::Rect(0, 0, 400, 400)); |
| const DisplayInfo second_display_info = |
| CreateDisplayInfo(11, 500, display::Display::ROTATE_0); |
| |
| std::vector<DisplayInfo> 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 DisplayInfo 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); |
| EXPECT_EQ("0,0 500x500", test_observer.shelf_display_bounds().ToString()); |
| primary_root->RemoveObserver(&test_observer); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, UpdateMouseLocationAfterDisplayChange) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| UpdateDisplay("200x200,300x300"); |
| aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
| |
| aura::Env* env = aura::Env::GetInstance(); |
| |
| ui::test::EventGenerator generator(root_windows[0]); |
| |
| // Set the initial position. |
| generator.MoveMouseToInHost(350, 150); |
| EXPECT_EQ("350,150", env->last_mouse_location().ToString()); |
| |
| // A mouse pointer will stay in the 2nd display. |
| UpdateDisplay("300x300,200x200"); |
| EXPECT_EQ("450,50", env->last_mouse_location().ToString()); |
| |
| // A mouse pointer will be outside of displays and move to the |
| // center of 2nd display. |
| UpdateDisplay("300x300,100x100"); |
| EXPECT_EQ("350,50", env->last_mouse_location().ToString()); |
| |
| // 2nd display was disconnected, and the cursor is |
| // now in the 1st display. |
| UpdateDisplay("400x400"); |
| EXPECT_EQ("50,350", env->last_mouse_location().ToString()); |
| |
| // 1st display's resolution has changed, and the mouse pointer is |
| // now outside. Move the mouse pointer to the center of 1st display. |
| UpdateDisplay("300x300"); |
| EXPECT_EQ("150,150", env->last_mouse_location().ToString()); |
| |
| // Move the mouse pointer to the bottom of 1st display. |
| generator.MoveMouseToInHost(150, 290); |
| EXPECT_EQ("150,290", env->last_mouse_location().ToString()); |
| |
| // The mouse pointer is now on 2nd display. |
| UpdateDisplay("300x280,200x200"); |
| EXPECT_EQ("450,10", env->last_mouse_location().ToString()); |
| } |
| |
| TEST_P(WindowTreeHostManagerTest, |
| UpdateMouseLocationAfterDisplayChange_2ndOnLeft) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| // Set the 2nd display on the left. |
| DisplayLayoutStore* layout_store = |
| Shell::GetInstance()->display_manager()->layout_store(); |
| display::DisplayPlacement new_default(display::DisplayPlacement::LEFT, 0); |
| layout_store->SetDefaultDisplayPlacement(new_default); |
| |
| UpdateDisplay("200x200,300x300"); |
| aura::Window::Windows root_windows = Shell::GetAllRootWindows(); |
| |
| EXPECT_EQ("-300,0 300x300", |
| ScreenUtil::GetSecondaryDisplay().bounds().ToString()); |
| |
| aura::Env* env = aura::Env::GetInstance(); |
| |
| // Set the initial position. |
| root_windows[0]->MoveCursorTo(gfx::Point(-150, 250)); |
| EXPECT_EQ("-150,250", env->last_mouse_location().ToString()); |
| |
| // A mouse pointer will stay in 2nd display. |
| UpdateDisplay("300x300,200x300"); |
| EXPECT_EQ("-50,150", env->last_mouse_location().ToString()); |
| |
| // A mouse pointer will be outside of displays and move to the |
| // center of 2nd display. |
| UpdateDisplay("300x300,200x100"); |
| EXPECT_EQ("-100,50", env->last_mouse_location().ToString()); |
| |
| // 2nd display was disconnected. Mouse pointer should move to |
| // 1st display. |
| UpdateDisplay("300x300"); |
| EXPECT_EQ("150,150", env->last_mouse_location().ToString()); |
| } |
| |
| // Test that the cursor swaps displays and that its scale factor and rotation |
| // are updated when the primary display is swapped. |
| TEST_P(WindowTreeHostManagerTest, |
| UpdateMouseLocationAfterDisplayChange_SwapPrimary) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| UpdateDisplay("200x200,200x200*2/r"); |
| |
| aura::Env* env = aura::Env::GetInstance(); |
| Shell* shell = Shell::GetInstance(); |
| WindowTreeHostManager* window_tree_host_manager = |
| shell->window_tree_host_manager(); |
| test::CursorManagerTestApi test_api(shell->cursor_manager()); |
| |
| window_tree_host_manager->GetPrimaryRootWindow()->MoveCursorTo( |
| gfx::Point(20, 50)); |
| |
| EXPECT_EQ("20,50", env->last_mouse_location().ToString()); |
| EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor()); |
| EXPECT_EQ(display::Display::ROTATE_0, test_api.GetCurrentCursorRotation()); |
| |
| test::SwapPrimaryDisplay(); |
| |
| EXPECT_EQ("20,50", env->last_mouse_location().ToString()); |
| EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_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_P(WindowTreeHostManagerTest, |
| UpdateMouseLocationAfterDisplayChange_PrimaryDisconnected) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| aura::Env* env = aura::Env::GetInstance(); |
| Shell* shell = Shell::GetInstance(); |
| WindowTreeHostManager* window_tree_host_manager = |
| shell->window_tree_host_manager(); |
| test::CursorManagerTestApi test_api(shell->cursor_manager()); |
| |
| UpdateDisplay("300x300*2/r,200x200"); |
| // Swap the primary display to make it possible to remove the primary display |
| // via UpdateDisplay(). |
| test::SwapPrimaryDisplay(); |
| int primary_display_id = window_tree_host_manager->GetPrimaryDisplayId(); |
| |
| window_tree_host_manager->GetPrimaryRootWindow()->MoveCursorTo( |
| gfx::Point(20, 50)); |
| |
| EXPECT_EQ("20,50", env->last_mouse_location().ToString()); |
| EXPECT_EQ(1.0f, test_api.GetCurrentCursor().device_scale_factor()); |
| EXPECT_EQ(display::Display::ROTATE_0, test_api.GetCurrentCursorRotation()); |
| |
| UpdateDisplay("300x300*2/r"); |
| ASSERT_NE(primary_display_id, |
| window_tree_host_manager->GetPrimaryDisplayId()); |
| |
| // Cursor should be centered on the remaining display. |
| EXPECT_EQ("75,75", env->last_mouse_location().ToString()); |
| EXPECT_EQ(2.0f, test_api.GetCurrentCursor().device_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_P(WindowTreeHostManagerTest, |
| GetRootWindowForDisplayIdDuringDisplayDisconnection) { |
| if (!SupportsMultipleDisplays()) |
| return; |
| |
| UpdateDisplay("300x300,200x200"); |
| aura::Window* root2 = |
| Shell::GetInstance() |
| ->window_tree_host_manager() |
| ->GetRootWindowForDisplayId(ScreenUtil::GetSecondaryDisplay().id()); |
| views::Widget* widget = views::Widget::CreateWindowWithContextAndBounds( |
| 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( |
| new views::MouseWatcherViewHost(view, gfx::Insets()), &listener); |
| watcher.Start(); |
| |
| ui::test::EventGenerator event_generator( |
| widget->GetNativeWindow()->GetRootWindow()); |
| event_generator.MoveMouseToCenterOf(widget->GetNativeWindow()); |
| |
| UpdateDisplay("300x300"); |
| watcher.Stop(); |
| |
| widget->CloseNow(); |
| } |
| |
| } // namespace ash |