// 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/display_manager.h" #include "ash/display/display_controller.h" #include "ash/screen_ash.h" #include "ash/shell.h" #include "ash/test/ash_test_base.h" #include "ash/test/display_manager_test_api.h" #include "base/format_macros.h" #include "base/stringprintf.h" #include "ui/aura/env.h" #include "ui/aura/root_window.h" #include "ui/aura/window_observer.h" #include "ui/gfx/display_observer.h" #include "ui/gfx/display.h" namespace ash { namespace internal { using std::vector; using std::string; using base::StringPrintf; class DisplayManagerTest : public test::AshTestBase, public gfx::DisplayObserver, public aura::WindowObserver { public: DisplayManagerTest() : removed_count_(0U), root_window_destroyed_(false) { } virtual ~DisplayManagerTest() {} virtual void SetUp() OVERRIDE { AshTestBase::SetUp(); Shell::GetScreen()->AddObserver(this); Shell::GetPrimaryRootWindow()->AddObserver(this); } virtual void TearDown() OVERRIDE { Shell::GetPrimaryRootWindow()->RemoveObserver(this); Shell::GetScreen()->RemoveObserver(this); AshTestBase::TearDown(); } DisplayManager* display_manager() { return Shell::GetInstance()->display_manager(); } const vector& changed() const { return changed_; } const vector& added() const { return added_; } string GetCountSummary() const { return StringPrintf("%"PRIuS" %"PRIuS" %"PRIuS, changed_.size(), added_.size(), removed_count_); } void reset() { changed_.clear(); added_.clear(); removed_count_ = 0U; root_window_destroyed_ = false; } bool root_window_destroyed() const { return root_window_destroyed_; } const DisplayInfo& GetDisplayInfo(const gfx::Display& display) { return display_manager()->GetDisplayInfo(display.id()); } const DisplayInfo& GetDisplayInfoAt(int index) { return GetDisplayInfo(*display_manager()->GetDisplayAt(index)); } const gfx::Display& FindDisplayForId(int64 id) { return display_manager()->FindDisplayForId(id); } const DisplayInfo& FindDisplayInfoForId(int64 id) { return GetDisplayInfo(display_manager()->FindDisplayForId(id)); } // aura::DisplayObserver overrides: virtual void OnDisplayBoundsChanged(const gfx::Display& display) OVERRIDE { changed_.push_back(display); } virtual void OnDisplayAdded(const gfx::Display& new_display) OVERRIDE { added_.push_back(new_display); } virtual void OnDisplayRemoved(const gfx::Display& old_display) OVERRIDE { ++removed_count_; } // aura::WindowObserver overrides: virtual void OnWindowDestroying(aura::Window* window) OVERRIDE { ASSERT_EQ(Shell::GetPrimaryRootWindow(), window); root_window_destroyed_ = true; } private: vector changed_; vector added_; size_t removed_count_; bool root_window_destroyed_; DISALLOW_COPY_AND_ASSIGN(DisplayManagerTest); }; TEST_F(DisplayManagerTest, NativeDisplayTest) { EXPECT_EQ(1U, display_manager()->GetNumDisplays()); // Update primary and add seconary. UpdateDisplay("100+0-500x500,0+501-400x400"); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", display_manager()->GetDisplayAt(0)->bounds().ToString()); EXPECT_EQ("1 1 0", GetCountSummary()); EXPECT_EQ(display_manager()->GetDisplayAt(0)->id(), changed()[0].id()); EXPECT_EQ(display_manager()->GetDisplayAt(1)->id(), added()[0].id()); EXPECT_EQ("0,0 500x500", changed()[0].bounds().ToString()); // Secondary display is on right. EXPECT_EQ("500,0 400x400", added()[0].bounds().ToString()); EXPECT_EQ("0,501 400x400", GetDisplayInfo(added()[0]).bounds_in_pixel().ToString()); reset(); // Delete secondary. UpdateDisplay("100+0-500x500"); EXPECT_EQ("0 0 1", GetCountSummary()); reset(); // Change primary. UpdateDisplay("1+1-1000x600"); EXPECT_EQ("1 0 0", GetCountSummary()); EXPECT_EQ(display_manager()->GetDisplayAt(0)->id(), changed()[0].id()); EXPECT_EQ("0,0 1000x600", changed()[0].bounds().ToString()); reset(); // Add secondary. UpdateDisplay("1+1-1000x600,1002+0-600x400"); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0 1 0", GetCountSummary()); EXPECT_EQ(display_manager()->GetDisplayAt(1)->id(), added()[0].id()); // Secondary display is on right. EXPECT_EQ("1000,0 600x400", added()[0].bounds().ToString()); EXPECT_EQ("1002,0 600x400", GetDisplayInfo(added()[0]).bounds_in_pixel().ToString()); reset(); // Secondary removed, primary changed. UpdateDisplay("1+1-800x300"); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ("1 0 1", GetCountSummary()); EXPECT_EQ(display_manager()->GetDisplayAt(0)->id(), changed()[0].id()); EXPECT_EQ("0,0 800x300", changed()[0].bounds().ToString()); reset(); // # of display can go to zero when screen is off. const vector empty; display_manager()->OnNativeDisplaysChanged(empty); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ("0 0 0", GetCountSummary()); EXPECT_FALSE(root_window_destroyed()); // Display configuration stays the same EXPECT_EQ("0,0 800x300", display_manager()->GetDisplayAt(0)->bounds().ToString()); reset(); // Connect to display again UpdateDisplay("100+100-500x400"); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ("1 0 0", GetCountSummary()); EXPECT_FALSE(root_window_destroyed()); EXPECT_EQ("0,0 500x400", changed()[0].bounds().ToString()); EXPECT_EQ("100,100 500x400", GetDisplayInfo(changed()[0]).bounds_in_pixel().ToString()); reset(); // Go back to zero and wake up with multiple displays. display_manager()->OnNativeDisplaysChanged(empty); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_FALSE(root_window_destroyed()); reset(); // Add secondary. UpdateDisplay("0+0-1000x600,1000+1000-600x400"); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 1000x600", display_manager()->GetDisplayAt(0)->bounds().ToString()); // Secondary display is on right. EXPECT_EQ("1000,0 600x400", display_manager()->GetDisplayAt(1)->bounds().ToString()); EXPECT_EQ("1000,1000 600x400", GetDisplayInfoAt(1).bounds_in_pixel().ToString()); reset(); } // Test in emulation mode (use_fullscreen_host_window=false) TEST_F(DisplayManagerTest, EmulatorTest) { EXPECT_EQ(1U, display_manager()->GetNumDisplays()); DisplayManager::CycleDisplay(); // Update primary and add seconary. EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0 1 0", GetCountSummary()); reset(); DisplayManager::CycleDisplay(); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ("0 0 1", GetCountSummary()); reset(); DisplayManager::CycleDisplay(); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0 1 0", GetCountSummary()); reset(); } TEST_F(DisplayManagerTest, OverscanInsetsTest) { UpdateDisplay("0+0-500x500,0+501-400x400"); reset(); ASSERT_EQ(2u, display_manager()->GetNumDisplays()); const DisplayInfo& display_info1 = GetDisplayInfoAt(0); const DisplayInfo& display_info2 = GetDisplayInfoAt(1); display_manager()->SetOverscanInsets( display_info2.id(), gfx::Insets(13, 12, 11, 10)); std::vector changed_displays = changed(); EXPECT_EQ(1u, changed_displays.size()); EXPECT_EQ(display_info2.id(), changed_displays[0].id()); EXPECT_EQ("0,0 500x500", GetDisplayInfoAt(0).bounds_in_pixel().ToString()); DisplayInfo updated_display_info2 = GetDisplayInfoAt(1); EXPECT_EQ("0,501 400x400", updated_display_info2.bounds_in_pixel().ToString()); EXPECT_EQ("378x376", updated_display_info2.size_in_pixel().ToString()); EXPECT_EQ("13,12,11,10", updated_display_info2.overscan_insets_in_dip().ToString()); EXPECT_EQ("500,0 378x376", ScreenAsh::GetSecondaryDisplay().bounds().ToString()); // Make sure that SetOverscanInsets() is idempotent. display_manager()->SetOverscanInsets(display_info1.id(), gfx::Insets()); display_manager()->SetOverscanInsets( display_info2.id(), gfx::Insets(13, 12, 11, 10)); EXPECT_EQ("0,0 500x500", GetDisplayInfoAt(0).bounds_in_pixel().ToString()); updated_display_info2 = GetDisplayInfoAt(1); EXPECT_EQ("0,501 400x400", updated_display_info2.bounds_in_pixel().ToString()); EXPECT_EQ("378x376", updated_display_info2.size_in_pixel().ToString()); EXPECT_EQ("13,12,11,10", updated_display_info2.overscan_insets_in_dip().ToString()); display_manager()->SetOverscanInsets( display_info2.id(), gfx::Insets(10, 11, 12, 13)); EXPECT_EQ("0,0 500x500", GetDisplayInfoAt(0).bounds_in_pixel().ToString()); EXPECT_EQ("376x378", GetDisplayInfoAt(1).size_in_pixel().ToString()); EXPECT_EQ("10,11,12,13", GetDisplayInfoAt(1).overscan_insets_in_dip().ToString()); // Recreate a new 2nd display. It won't apply the overscan inset because the // new display has a different ID. UpdateDisplay("0+0-500x500"); UpdateDisplay("0+0-500x500,0+501-400x400"); EXPECT_EQ("0,0 500x500", GetDisplayInfoAt(0).bounds_in_pixel().ToString()); EXPECT_EQ("0,501 400x400", GetDisplayInfoAt(1).bounds_in_pixel().ToString()); // Recreate the displays with the same ID. It should apply the overscan // inset. UpdateDisplay("0+0-500x500"); std::vector display_info_list; display_info_list.push_back(display_info1); display_info_list.push_back(display_info2); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ("1,1 500x500", GetDisplayInfoAt(0).bounds_in_pixel().ToString()); updated_display_info2 = GetDisplayInfoAt(1); EXPECT_EQ("376x378", updated_display_info2.size_in_pixel().ToString()); EXPECT_EQ("10,11,12,13", updated_display_info2.overscan_insets_in_dip().ToString()); // HiDPI but overscan display. The specified insets size should be doubled. UpdateDisplay("0+0-500x500,0+501-400x400*2"); display_manager()->SetOverscanInsets( display_manager()->GetDisplayAt(1)->id(), gfx::Insets(4, 5, 6, 7)); EXPECT_EQ("0,0 500x500", GetDisplayInfoAt(0).bounds_in_pixel().ToString()); updated_display_info2 = GetDisplayInfoAt(1); EXPECT_EQ("0,501 400x400", updated_display_info2.bounds_in_pixel().ToString()); EXPECT_EQ("376x380", updated_display_info2.size_in_pixel().ToString()); EXPECT_EQ("4,5,6,7", updated_display_info2.overscan_insets_in_dip().ToString()); EXPECT_EQ("8,10,12,14", updated_display_info2.GetOverscanInsetsInPixel().ToString()); // Make sure switching primary display applies the overscan offset only once. ash::Shell::GetInstance()->display_controller()->SetPrimaryDisplay( ScreenAsh::GetSecondaryDisplay()); EXPECT_EQ("-500,0 500x500", ScreenAsh::GetSecondaryDisplay().bounds().ToString()); EXPECT_EQ("0,0 500x500", GetDisplayInfo(ScreenAsh::GetSecondaryDisplay()). bounds_in_pixel().ToString()); EXPECT_EQ("0,501 400x400", GetDisplayInfo(Shell::GetScreen()->GetPrimaryDisplay()). bounds_in_pixel().ToString()); EXPECT_EQ("0,0 188x190", Shell::GetScreen()->GetPrimaryDisplay().bounds().ToString()); } TEST_F(DisplayManagerTest, ZeroOverscanInsets) { // Make sure the display change events is emitted for overscan inset changes. UpdateDisplay("0+0-500x500,0+501-400x400"); ASSERT_EQ(2u, display_manager()->GetNumDisplays()); int64 display2_id = display_manager()->GetDisplayAt(1)->id(); reset(); display_manager()->SetOverscanInsets(display2_id, gfx::Insets(0, 0, 0, 0)); EXPECT_EQ(0u, changed().size()); reset(); display_manager()->SetOverscanInsets(display2_id, gfx::Insets(1, 0, 0, 0)); EXPECT_EQ(1u, changed().size()); EXPECT_EQ(display2_id, changed()[0].id()); reset(); display_manager()->SetOverscanInsets(display2_id, gfx::Insets(0, 0, 0, 0)); EXPECT_EQ(1u, changed().size()); EXPECT_EQ(display2_id, changed()[0].id()); } TEST_F(DisplayManagerTest, TestDeviceScaleOnlyChange) { UpdateDisplay("1000x600"); EXPECT_EQ(1, Shell::GetPrimaryRootWindow()->compositor()->device_scale_factor()); EXPECT_EQ("1000x600", Shell::GetPrimaryRootWindow()->bounds().size().ToString()); UpdateDisplay("1000x600*2"); EXPECT_EQ(2, Shell::GetPrimaryRootWindow()->compositor()->device_scale_factor()); EXPECT_EQ("500x300", Shell::GetPrimaryRootWindow()->bounds().size().ToString()); } DisplayInfo CreateDisplayInfo(int64 id, const gfx::Rect& bounds) { DisplayInfo info(id, StringPrintf("x-%d", static_cast(id)), false); info.SetBounds(bounds); return info; } TEST_F(DisplayManagerTest, TestNativeDisplaysChanged) { const int internal_display_id = test::DisplayManagerTestApi(display_manager()). SetFirstDisplayAsInternalDisplay(); const int64 invalid_id = gfx::Display::kInvalidDisplayID; const DisplayInfo native_display_info = CreateDisplayInfo(internal_display_id, gfx::Rect(0, 0, 500, 500)); const DisplayInfo external_display_info = CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100)); const DisplayInfo mirrored_display_info = CreateDisplayInfo(11, gfx::Rect(0, 0, 500, 500)); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ(1U, display_manager()->num_connected_displays()); std::string default_bounds = display_manager()->GetDisplayAt(0)->bounds().ToString(); std::vector display_info_list; // Primary disconnected. display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ(default_bounds, display_manager()->GetDisplayAt(0)->bounds().ToString()); EXPECT_EQ(1U, display_manager()->num_connected_displays()); EXPECT_EQ(invalid_id, display_manager()->mirrored_display_id()); // External connected while primary was disconnected. display_info_list.push_back(external_display_info); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ(default_bounds, FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("1,1 100x100", FindDisplayInfoForId(10).bounds_in_pixel().ToString()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); EXPECT_EQ(invalid_id, display_manager()->mirrored_display_id()); // Primary connected, with different bounds. display_info_list.clear(); display_info_list.push_back(native_display_info); display_info_list.push_back(external_display_info); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("1,1 100x100", FindDisplayInfoForId(10).bounds_in_pixel().ToString()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); EXPECT_EQ(invalid_id, display_manager()->mirrored_display_id()); EXPECT_EQ(StringPrintf("x-%d", internal_display_id), display_manager()->GetDisplayNameForId(internal_display_id)); // Turn off primary. display_info_list.clear(); display_info_list.push_back(external_display_info); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("1,1 100x100", FindDisplayInfoForId(10).bounds_in_pixel().ToString()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); EXPECT_EQ(invalid_id, display_manager()->mirrored_display_id()); // Emulate suspend. display_info_list.clear(); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("1,1 100x100", FindDisplayInfoForId(10).bounds_in_pixel().ToString()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); EXPECT_EQ(invalid_id, display_manager()->mirrored_display_id()); EXPECT_EQ(StringPrintf("x-%d", internal_display_id), display_manager()->GetDisplayNameForId(internal_display_id)); // External display has disconnected then resumed. display_info_list.push_back(native_display_info); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ(1U, display_manager()->num_connected_displays()); EXPECT_EQ(invalid_id, display_manager()->mirrored_display_id()); // External display was changed during suspend. display_info_list.push_back(external_display_info); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); EXPECT_EQ(invalid_id, display_manager()->mirrored_display_id()); // suspend... display_info_list.clear(); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); EXPECT_EQ(invalid_id, display_manager()->mirrored_display_id()); // and resume with different external display. display_info_list.push_back(native_display_info); display_info_list.push_back(CreateDisplayInfo(12, gfx::Rect(1, 1, 100, 100))); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); EXPECT_EQ(invalid_id, display_manager()->mirrored_display_id()); // mirrored... display_info_list.clear(); display_info_list.push_back(native_display_info); display_info_list.push_back(mirrored_display_info); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ(2U, display_manager()->num_connected_displays()); EXPECT_EQ(11U, display_manager()->mirrored_display_id()); // Test display name. EXPECT_EQ(StringPrintf("x-%d", internal_display_id), display_manager()->GetDisplayNameForId(internal_display_id)); EXPECT_EQ("x-10", display_manager()->GetDisplayNameForId(10)); EXPECT_EQ("x-11", display_manager()->GetDisplayNameForId(11)); EXPECT_EQ("x-12", display_manager()->GetDisplayNameForId(12)); // Default name for the id that doesn't exist. EXPECT_EQ("Display 100", display_manager()->GetDisplayNameForId(100)); } #if defined(OS_WIN) // This test currently fails on Win8/Metro as it picks up the actual // display size. http://crbug.com/154081 #define MAYBE_TestNativeDisplaysChangedNoInternal \ DISABLED_TestNativeDisplaysChangedNoInternal #else #define MAYBE_TestNativeDisplaysChangedNoInternal \ TestNativeDisplaysChangedNoInternal #endif TEST_F(DisplayManagerTest, MAYBE_TestNativeDisplaysChangedNoInternal) { EXPECT_EQ(1U, display_manager()->GetNumDisplays()); // Don't change the display info if all displays are disconnected. std::vector display_info_list; display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); // Connect another display which will become primary. const DisplayInfo external_display_info = CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100)); display_info_list.push_back(external_display_info); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(1U, display_manager()->GetNumDisplays()); EXPECT_EQ("1,1 100x100", FindDisplayInfoForId(10).bounds_in_pixel().ToString()); EXPECT_EQ("100x100", ash::Shell::GetPrimaryRootWindow()->GetHostSize().ToString()); } TEST_F(DisplayManagerTest, EnsurePointerInDisplays) { UpdateDisplay("200x200,300x300"); Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); aura::Env* env = aura::Env::GetInstance(); // Set the initial position. root_windows[0]->MoveCursorTo(gfx::Point(350, 150)); EXPECT_EQ("350,150", env->last_mouse_location().ToString()); // A mouse pointer will be inside 2nd display. UpdateDisplay("300x300,200x200"); EXPECT_EQ("350,150", 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, but the mouse pointer says in the // 1st display. UpdateDisplay("400x400"); EXPECT_EQ("350,50", 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. root_windows[0]->MoveCursorTo(gfx::Point(150, 290)); EXPECT_EQ("150,290", env->last_mouse_location().ToString()); // The mouse pointer is outside and closest display is 1st one. UpdateDisplay("300x280,200x200"); EXPECT_EQ("150,140", env->last_mouse_location().ToString()); } TEST_F(DisplayManagerTest, EnsurePointerInDisplays_2ndOnLeft) { UpdateDisplay("200x200,300x300"); Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); // Set the 2nd display on the left. DisplayController* display_controller = Shell::GetInstance()->display_controller(); DisplayLayout layout = display_controller->default_display_layout(); layout.position = DisplayLayout::LEFT; display_controller->SetDefaultDisplayLayout(layout); EXPECT_EQ("-300,0 300x300", ScreenAsh::GetSecondaryDisplay().bounds().ToString()); aura::Env* env = aura::Env::GetInstance(); // Set the initial position. root_windows[0]->MoveCursorTo(gfx::Point(-150, 150)); EXPECT_EQ("-150,150", env->last_mouse_location().ToString()); // A mouse pointer will be in 2nd display. UpdateDisplay("300x300,200x200"); EXPECT_EQ("-150,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_F(DisplayManagerTest, NativeDisplaysChangedAfterPrimaryChange) { const int64 internal_display_id = test::DisplayManagerTestApi(display_manager()). SetFirstDisplayAsInternalDisplay(); const DisplayInfo native_display_info = CreateDisplayInfo(internal_display_id, gfx::Rect(0, 0, 500, 500)); const DisplayInfo secondary_display_info = CreateDisplayInfo(10, gfx::Rect(1, 1, 100, 100)); std::vector display_info_list; display_info_list.push_back(native_display_info); display_info_list.push_back(secondary_display_info); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ(2U, display_manager()->GetNumDisplays()); EXPECT_EQ("0,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("500,0 100x100", FindDisplayForId(10).bounds().ToString()); ash::Shell::GetInstance()->display_controller()->SetPrimaryDisplay( FindDisplayForId(secondary_display_info.id())); EXPECT_EQ("-500,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("0,0 100x100", FindDisplayForId(10).bounds().ToString()); // OnNativeDisplaysChanged may change the display bounds. Here makes sure // nothing changed if the exactly same displays are specified. display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ("-500,0 500x500", FindDisplayForId(internal_display_id).bounds().ToString()); EXPECT_EQ("0,0 100x100", FindDisplayForId(10).bounds().ToString()); } TEST_F(DisplayManagerTest, AutomaticOverscanInsets) { UpdateDisplay("200x200,400x400"); std::vector display_info_list; display_info_list.push_back(GetDisplayInfoAt(0)); display_info_list.push_back(GetDisplayInfoAt(1)); display_info_list[1].set_has_overscan_for_test(true); int64 id = display_info_list[1].id(); // SetDefaultOverscanInsets(&display_info_list[1]); display_manager()->OnNativeDisplaysChanged(display_info_list); // It has overscan insets, although SetOverscanInsets() isn't called. EXPECT_EQ("380x380", GetDisplayInfoAt(1).size_in_pixel().ToString()); // If custom overscan insets is specified, the specified value is used. display_manager()->SetOverscanInsets(id, gfx::Insets(5, 6, 7, 8)); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ("386x388", GetDisplayInfoAt(1).size_in_pixel().ToString()); // Do not overscan even though it has 'has_overscan' flag, if the custom // insets is empty. display_manager()->SetOverscanInsets(id, gfx::Insets()); display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_EQ("400x400", GetDisplayInfoAt(1).size_in_pixel().ToString()); // Clearing the custom overscan should set the bounds to // original. display_manager()->ClearCustomOverscanInsets(id); EXPECT_EQ("380x380", GetDisplayInfoAt(1).size_in_pixel().ToString()); } TEST_F(DisplayManagerTest, Rotate) { UpdateDisplay("100x200/r,300x400/l"); EXPECT_EQ("1,1 100x200", GetDisplayInfoAt(0).bounds_in_pixel().ToString()); EXPECT_EQ("200x100", GetDisplayInfoAt(0).size_in_pixel().ToString()); EXPECT_EQ("1,201 300x400", GetDisplayInfoAt(1).bounds_in_pixel().ToString()); EXPECT_EQ("400x300", GetDisplayInfoAt(1).size_in_pixel().ToString()); UpdateDisplay("100x200/b,300x400"); EXPECT_EQ("1,1 100x200", GetDisplayInfoAt(0).bounds_in_pixel().ToString()); EXPECT_EQ("100x200", GetDisplayInfoAt(0).size_in_pixel().ToString()); EXPECT_EQ("1,201 300x400", GetDisplayInfoAt(1).bounds_in_pixel().ToString()); EXPECT_EQ("300x400", GetDisplayInfoAt(1).size_in_pixel().ToString()); } } // namespace internal } // namespace ash