| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/display/cros_display_config.h" |
| |
| #include "ash/display/cros_display_config.h" |
| #include "ash/display/touch_calibrator_controller.h" |
| #include "ash/public/interfaces/cros_display_config.mojom.h" |
| #include "ash/shell.h" |
| #include "ash/test/ash_test_base.h" |
| #include "ash/touch/ash_touch_transform_controller.h" |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "mojo/public/cpp/bindings/associated_binding.h" |
| #include "services/ws/public/cpp/input_devices/input_device_client_test_api.h" |
| #include "ui/display/display_switches.h" |
| #include "ui/display/manager/display_manager.h" |
| #include "ui/display/manager/test/touch_transform_controller_test_api.h" |
| #include "ui/display/manager/touch_transform_setter.h" |
| #include "ui/display/test/display_manager_test_api.h" |
| #include "ui/events/devices/touch_device_transform.h" |
| #include "ui/events/devices/touchscreen_device.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| void SetResult(mojom::DisplayConfigResult* result_ptr, |
| base::OnceClosure callback, |
| mojom::DisplayConfigResult result) { |
| *result_ptr = result; |
| std::move(callback).Run(); |
| } |
| |
| void InitExternalTouchDevices(int64_t display_id) { |
| ui::TouchscreenDevice touchdevice(123, ui::InputDeviceType::INPUT_DEVICE_USB, |
| std::string("test external touch device"), |
| gfx::Size(1000, 1000), 1); |
| ws::InputDeviceClientTestApi().SetTouchscreenDevices({touchdevice}); |
| |
| std::vector<ui::TouchDeviceTransform> transforms; |
| ui::TouchDeviceTransform touch_device_transform; |
| touch_device_transform.display_id = display_id; |
| touch_device_transform.device_id = touchdevice.id; |
| transforms.push_back(touch_device_transform); |
| display::test::TouchTransformControllerTestApi( |
| ash::Shell::Get()->touch_transformer_controller()) |
| .touch_transform_setter() |
| ->ConfigureTouchDevices(transforms); |
| } |
| |
| class TestObserver : public mojom::CrosDisplayConfigObserver { |
| public: |
| TestObserver() = default; |
| |
| // mojom::CrosDisplayConfigObserver: |
| void OnDisplayConfigChanged() override { display_changes_++; } |
| |
| int display_changes() const { return display_changes_; } |
| void reset_display_changes() { display_changes_ = 0; } |
| |
| private: |
| int display_changes_ = 0; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestObserver); |
| }; |
| |
| class CrosDisplayConfigTest : public AshTestBase { |
| public: |
| CrosDisplayConfigTest() {} |
| ~CrosDisplayConfigTest() override {} |
| |
| void SetUp() override { |
| base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kUseFirstDisplayAsInternal); |
| AshTestBase::SetUp(); |
| CHECK(display::Screen::GetScreen()); |
| cros_display_config_ = Shell::Get()->cros_display_config(); |
| } |
| |
| mojom::DisplayLayoutInfoPtr GetDisplayLayoutInfo() { |
| mojom::DisplayLayoutInfoPtr display_layout_info; |
| base::RunLoop run_loop; |
| cros_display_config_->GetDisplayLayoutInfo(base::BindOnce( |
| [](mojom::DisplayLayoutInfoPtr* result_ptr, base::OnceClosure callback, |
| mojom::DisplayLayoutInfoPtr result) { |
| *result_ptr = std::move(result); |
| std::move(callback).Run(); |
| }, |
| &display_layout_info, run_loop.QuitClosure())); |
| run_loop.Run(); |
| return display_layout_info; |
| } |
| |
| mojom::DisplayConfigResult SetDisplayLayoutInfo( |
| mojom::DisplayLayoutInfoPtr display_layout_info) { |
| mojom::DisplayConfigResult result; |
| base::RunLoop run_loop; |
| cros_display_config_->SetDisplayLayoutInfo( |
| std::move(display_layout_info), |
| base::BindOnce(&SetResult, &result, run_loop.QuitClosure())); |
| run_loop.Run(); |
| return result; |
| } |
| |
| std::vector<mojom::DisplayUnitInfoPtr> GetDisplayUnitInfoList() { |
| std::vector<mojom::DisplayUnitInfoPtr> display_info_list; |
| base::RunLoop run_loop; |
| cros_display_config_->GetDisplayUnitInfoList( |
| /*single_unified=*/false, |
| base::BindOnce( |
| [](std::vector<mojom::DisplayUnitInfoPtr>* result_ptr, |
| base::OnceClosure callback, |
| std::vector<mojom::DisplayUnitInfoPtr> result) { |
| *result_ptr = std::move(result); |
| std::move(callback).Run(); |
| }, |
| &display_info_list, run_loop.QuitClosure())); |
| run_loop.Run(); |
| return display_info_list; |
| } |
| |
| mojom::DisplayConfigResult SetDisplayProperties( |
| const std::string& id, |
| mojom::DisplayConfigPropertiesPtr properties) { |
| mojom::DisplayConfigResult result; |
| base::RunLoop run_loop; |
| cros_display_config_->SetDisplayProperties( |
| id, std::move(properties), |
| base::BindOnce(&SetResult, &result, run_loop.QuitClosure())); |
| run_loop.Run(); |
| return result; |
| } |
| |
| bool OverscanCalibration(int64_t id, |
| mojom::DisplayConfigOperation op, |
| const base::Optional<gfx::Insets>& delta) { |
| mojom::DisplayConfigResult result; |
| base::RunLoop run_loop; |
| cros_display_config()->OverscanCalibration( |
| base::NumberToString(id), op, delta, |
| base::BindOnce(&SetResult, &result, run_loop.QuitClosure())); |
| run_loop.Run(); |
| return result == mojom::DisplayConfigResult::kSuccess; |
| } |
| |
| bool DisplayExists(int64_t display_id) { |
| const display::Display& display = |
| display_manager()->GetDisplayForId(display_id); |
| return display.id() != display::kInvalidDisplayId; |
| } |
| |
| mojom::TouchCalibrationPtr GetDefaultCalibration() { |
| auto calibration = mojom::TouchCalibration::New(); |
| for (int i = 0; i < 4; ++i) |
| calibration->pairs.emplace_back(mojom::TouchCalibrationPair::New()); |
| return calibration; |
| } |
| |
| bool StartTouchCalibration(const std::string& display_id) { |
| return CallTouchCalibration( |
| display_id, ash::mojom::DisplayConfigOperation::kStart, nullptr); |
| } |
| |
| bool CompleteCustomTouchCalibration(const std::string& display_id, |
| mojom::TouchCalibrationPtr calibration) { |
| return CallTouchCalibration(display_id, |
| ash::mojom::DisplayConfigOperation::kComplete, |
| std::move(calibration)); |
| } |
| |
| bool CallTouchCalibration(const std::string& id, |
| ash::mojom::DisplayConfigOperation op, |
| ash::mojom::TouchCalibrationPtr calibration) { |
| mojom::DisplayConfigResult result; |
| base::RunLoop run_loop; |
| cros_display_config_->TouchCalibration( |
| id, op, std::move(calibration), |
| base::BindOnce(&SetResult, &result, run_loop.QuitClosure())); |
| run_loop.Run(); |
| return result == mojom::DisplayConfigResult::kSuccess; |
| } |
| |
| bool IsTouchCalibrationActive() { |
| TouchCalibratorController* touch_calibrator = |
| cros_display_config_->touch_calibrator_for_test(); |
| return touch_calibrator && touch_calibrator->IsCalibrating(); |
| } |
| |
| CrosDisplayConfig* cros_display_config() { return cros_display_config_; } |
| |
| private: |
| CrosDisplayConfig* cros_display_config_ = nullptr; |
| |
| DISALLOW_COPY_AND_ASSIGN(CrosDisplayConfigTest); |
| }; |
| |
| } // namespace |
| |
| TEST_F(CrosDisplayConfigTest, OnDisplayConfigChanged) { |
| TestObserver observer; |
| mojom::CrosDisplayConfigObserverAssociatedPtr observer_ptr; |
| mojo::AssociatedBinding<mojom::CrosDisplayConfigObserver> binding( |
| &observer, mojo::MakeRequestAssociatedWithDedicatedPipe(&observer_ptr)); |
| cros_display_config()->AddObserver(observer_ptr.PassInterface()); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Adding one display should trigger one notification. |
| UpdateDisplay("500x400"); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(1, observer.display_changes()); |
| observer.reset_display_changes(); |
| |
| // Adding two displays should trigger two notification. |
| UpdateDisplay("500x400,500x400"); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_EQ(2, observer.display_changes()); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, GetDisplayLayoutInfo) { |
| UpdateDisplay("500x400,500x400,500x400"); |
| std::vector<display::Display> displays = |
| display::Screen::GetScreen()->GetAllDisplays(); |
| ASSERT_EQ(3u, displays.size()); |
| |
| mojom::DisplayLayoutInfoPtr display_layout_info = GetDisplayLayoutInfo(); |
| |
| ASSERT_TRUE(display_layout_info); |
| const std::vector<mojom::DisplayLayoutPtr>& layouts = |
| *display_layout_info->layouts; |
| ASSERT_EQ(2u, layouts.size()); |
| |
| EXPECT_EQ(base::NumberToString(displays[1].id()), layouts[0]->id); |
| EXPECT_EQ(base::NumberToString(displays[0].id()), layouts[0]->parent_id); |
| EXPECT_EQ(mojom::DisplayLayoutPosition::kRight, layouts[0]->position); |
| EXPECT_EQ(0, layouts[0]->offset); |
| |
| EXPECT_EQ(base::NumberToString(displays[2].id()), layouts[1]->id); |
| EXPECT_EQ(layouts[0]->id, layouts[1]->parent_id); |
| EXPECT_EQ(mojom::DisplayLayoutPosition::kRight, layouts[1]->position); |
| EXPECT_EQ(0, layouts[1]->offset); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, SetLayoutUnified) { |
| UpdateDisplay("500x400,500x400"); |
| EXPECT_FALSE(display_manager()->IsInUnifiedMode()); |
| |
| // Enable unified desktop. Enables unified mode. |
| cros_display_config()->SetUnifiedDesktopEnabled(true); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(display_manager()->IsInUnifiedMode()); |
| |
| // Disable unified mode. |
| auto properties = mojom::DisplayLayoutInfo::New(); |
| properties->layout_mode = mojom::DisplayLayoutMode::kNormal; |
| mojom::DisplayConfigResult result = |
| SetDisplayLayoutInfo(std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_FALSE(display_manager()->IsInUnifiedMode()); |
| |
| // Enable unified mode. |
| properties = mojom::DisplayLayoutInfo::New(); |
| properties->layout_mode = mojom::DisplayLayoutMode::kUnified; |
| result = SetDisplayLayoutInfo(std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_TRUE(display_manager()->IsInUnifiedMode()); |
| |
| // Restore extended mode. |
| cros_display_config()->SetUnifiedDesktopEnabled(false); |
| EXPECT_FALSE(display_manager()->IsInUnifiedMode()); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, SetLayoutMirroredDefault) { |
| UpdateDisplay("500x400,500x400,500x400"); |
| |
| auto properties = mojom::DisplayLayoutInfo::New(); |
| properties->layout_mode = mojom::DisplayLayoutMode::kMirrored; |
| mojom::DisplayConfigResult result = |
| SetDisplayLayoutInfo(std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_TRUE(display_manager()->IsInMirrorMode()); |
| display::DisplayIdList id_list = |
| display_manager()->GetMirroringDestinationDisplayIdList(); |
| ASSERT_EQ(2u, id_list.size()); |
| |
| properties = mojom::DisplayLayoutInfo::New(); |
| properties->layout_mode = mojom::DisplayLayoutMode::kNormal; |
| result = SetDisplayLayoutInfo(std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_FALSE(display_manager()->IsInMirrorMode()); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, SetLayoutMirroredMixed) { |
| UpdateDisplay("500x400,500x400,500x400,500x400"); |
| |
| std::vector<display::Display> displays = |
| display::Screen::GetScreen()->GetAllDisplays(); |
| ASSERT_EQ(4u, displays.size()); |
| |
| auto properties = mojom::DisplayLayoutInfo::New(); |
| properties->layout_mode = mojom::DisplayLayoutMode::kMirrored; |
| properties->mirror_source_id = base::NumberToString(displays[0].id()); |
| properties->mirror_destination_ids = |
| base::make_optional<std::vector<std::string>>( |
| {base::NumberToString(displays[1].id()), |
| base::NumberToString(displays[3].id())}); |
| mojom::DisplayConfigResult result = |
| SetDisplayLayoutInfo(std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_TRUE(display_manager()->IsInMirrorMode()); |
| display::DisplayIdList id_list = |
| display_manager()->GetMirroringDestinationDisplayIdList(); |
| ASSERT_EQ(2u, id_list.size()); |
| EXPECT_TRUE(base::ContainsValue(id_list, displays[1].id())); |
| EXPECT_TRUE(base::ContainsValue(id_list, displays[3].id())); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, GetDisplayUnitInfoListBasic) { |
| UpdateDisplay("500x600,400x520"); |
| std::vector<mojom::DisplayUnitInfoPtr> result = GetDisplayUnitInfoList(); |
| ASSERT_EQ(2u, result.size()); |
| |
| int64_t display_id; |
| ASSERT_TRUE(base::StringToInt64(result[0]->id, &display_id)); |
| ASSERT_TRUE(DisplayExists(display_id)); |
| const mojom::DisplayUnitInfo& info_0 = *result[0]; |
| EXPECT_TRUE(info_0.is_primary); |
| EXPECT_TRUE(info_0.is_internal); |
| EXPECT_TRUE(info_0.is_enabled); |
| EXPECT_FALSE(info_0.is_tablet_mode); |
| EXPECT_FALSE(info_0.has_touch_support); |
| EXPECT_FALSE(info_0.has_accelerometer_support); |
| EXPECT_EQ(96, info_0.dpi_x); |
| EXPECT_EQ(96, info_0.dpi_y); |
| EXPECT_EQ(display::Display::ROTATE_0, info_0.rotation); |
| EXPECT_EQ("0,0 500x600", info_0.bounds.ToString()); |
| EXPECT_EQ("0,0,0,0", info_0.overscan.ToString()); |
| |
| ASSERT_TRUE(base::StringToInt64(result[1]->id, &display_id)); |
| ASSERT_TRUE(DisplayExists(display_id)); |
| const mojom::DisplayUnitInfo& info_1 = *result[1]; |
| EXPECT_EQ(display_manager()->GetDisplayNameForId(display_id), info_1.name); |
| // Second display is left of the primary display whose width 500. |
| EXPECT_EQ("500,0 400x520", info_1.bounds.ToString()); |
| EXPECT_EQ("0,0,0,0", info_1.overscan.ToString()); |
| EXPECT_EQ(display::Display::ROTATE_0, info_1.rotation); |
| EXPECT_FALSE(info_1.is_primary); |
| EXPECT_FALSE(info_1.is_internal); |
| EXPECT_TRUE(info_1.is_enabled); |
| EXPECT_EQ(96, info_1.dpi_x); |
| EXPECT_EQ(96, info_1.dpi_y); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, GetDisplayUnitInfoListZoomFactor) { |
| UpdateDisplay("1024x512,1024x512"); |
| std::vector<mojom::DisplayUnitInfoPtr> result = GetDisplayUnitInfoList(); |
| ASSERT_EQ(2u, result.size()); |
| |
| const mojom::DisplayUnitInfo& info_0 = *result[0]; |
| EXPECT_EQ(1.0, info_0.display_zoom_factor); |
| const std::vector<double>& zoom_factors = |
| info_0.available_display_zoom_factors; |
| EXPECT_EQ(9u, zoom_factors.size()); |
| EXPECT_FLOAT_EQ(0.90f, zoom_factors[0]); |
| EXPECT_FLOAT_EQ(0.95f, zoom_factors[1]); |
| EXPECT_FLOAT_EQ(1.f, zoom_factors[2]); |
| EXPECT_FLOAT_EQ(1.05f, zoom_factors[3]); |
| EXPECT_FLOAT_EQ(1.10f, zoom_factors[4]); |
| EXPECT_FLOAT_EQ(1.15f, zoom_factors[5]); |
| EXPECT_FLOAT_EQ(1.20f, zoom_factors[6]); |
| EXPECT_FLOAT_EQ(1.25f, zoom_factors[7]); |
| EXPECT_FLOAT_EQ(1.30f, zoom_factors[8]); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, SetDisplayPropertiesPrimary) { |
| UpdateDisplay("1200x600,600x1000"); |
| int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); |
| int64_t secondary_id = display_manager()->GetSecondaryDisplay().id(); |
| ASSERT_NE(primary_id, secondary_id); |
| |
| auto properties = mojom::DisplayConfigProperties::New(); |
| properties->set_primary = true; |
| mojom::DisplayConfigResult result = SetDisplayProperties( |
| base::NumberToString(secondary_id), std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| |
| // secondary display should now be primary. |
| primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); |
| EXPECT_EQ(primary_id, secondary_id); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, SetDisplayPropertiesOverscan) { |
| UpdateDisplay("1200x600,600x1000*2"); |
| const display::Display& secondary = display_manager()->GetSecondaryDisplay(); |
| |
| auto properties = mojom::DisplayConfigProperties::New(); |
| properties->overscan = gfx::Insets({199, 20, 51, 130}); |
| mojom::DisplayConfigResult result = SetDisplayProperties( |
| base::NumberToString(secondary.id()), std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_EQ("1200,0 150x250", secondary.bounds().ToString()); |
| const gfx::Insets overscan = |
| display_manager()->GetOverscanInsets(secondary.id()); |
| EXPECT_EQ(199, overscan.top()); |
| EXPECT_EQ(20, overscan.left()); |
| EXPECT_EQ(51, overscan.bottom()); |
| EXPECT_EQ(130, overscan.right()); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, SetDisplayPropertiesRotation) { |
| UpdateDisplay("1200x600,600x1000*2"); |
| const display::Display& secondary = display_manager()->GetSecondaryDisplay(); |
| |
| mojom::DisplayConfigResult result; |
| |
| auto properties = mojom::DisplayConfigProperties::New(); |
| properties->rotation = |
| mojom::DisplayRotation::New(display::Display::ROTATE_90); |
| result = SetDisplayProperties(base::NumberToString(secondary.id()), |
| std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_EQ("1200,0 500x300", secondary.bounds().ToString()); |
| EXPECT_EQ(display::Display::ROTATE_90, secondary.rotation()); |
| |
| properties = mojom::DisplayConfigProperties::New(); |
| properties->rotation = |
| mojom::DisplayRotation::New(display::Display::ROTATE_270); |
| result = SetDisplayProperties(base::NumberToString(secondary.id()), |
| std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_EQ("1200,0 500x300", secondary.bounds().ToString()); |
| EXPECT_EQ(display::Display::ROTATE_270, secondary.rotation()); |
| |
| // Test setting primary and rotating. |
| properties = mojom::DisplayConfigProperties::New(); |
| properties->set_primary = true; |
| properties->rotation = |
| mojom::DisplayRotation::New(display::Display::ROTATE_180); |
| result = SetDisplayProperties(base::NumberToString(secondary.id()), |
| std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| const display::Display& primary = |
| display::Screen::GetScreen()->GetPrimaryDisplay(); |
| EXPECT_EQ(secondary.id(), primary.id()); |
| EXPECT_EQ("0,0 300x500", primary.bounds().ToString()); |
| EXPECT_EQ(display::Display::ROTATE_180, primary.rotation()); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, SetDisplayPropertiesBoundsOrigin) { |
| UpdateDisplay("1200x600,520x400"); |
| const display::Display& secondary = display_manager()->GetSecondaryDisplay(); |
| |
| mojom::DisplayConfigResult result; |
| |
| auto properties = mojom::DisplayConfigProperties::New(); |
| properties->bounds_origin = gfx::Point({-520, 50}); |
| result = SetDisplayProperties(base::NumberToString(secondary.id()), |
| std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_EQ("-520,50 520x400", secondary.bounds().ToString()); |
| |
| properties = mojom::DisplayConfigProperties::New(); |
| properties->bounds_origin = gfx::Point({1200, 100}); |
| result = SetDisplayProperties(base::NumberToString(secondary.id()), |
| std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_EQ("1200,100 520x400", secondary.bounds().ToString()); |
| |
| properties = mojom::DisplayConfigProperties::New(); |
| properties->bounds_origin = gfx::Point({1100, -400}); |
| result = SetDisplayProperties(base::NumberToString(secondary.id()), |
| std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_EQ("1100,-400 520x400", secondary.bounds().ToString()); |
| |
| properties = mojom::DisplayConfigProperties::New(); |
| properties->bounds_origin = gfx::Point({-350, 600}); |
| result = SetDisplayProperties(base::NumberToString(secondary.id()), |
| std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_EQ("-350,600 520x400", secondary.bounds().ToString()); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, SetDisplayPropertiesDisplayZoomFactor) { |
| UpdateDisplay("1200x600, 1600x1000#1600x1000"); |
| display::DisplayIdList display_id_list = |
| display_manager()->GetCurrentDisplayIdList(); |
| |
| const float zoom_factor_1 = 1.23f; |
| const float zoom_factor_2 = 2.34f; |
| |
| display_manager()->UpdateZoomFactor(display_id_list[0], zoom_factor_2); |
| display_manager()->UpdateZoomFactor(display_id_list[1], zoom_factor_1); |
| |
| EXPECT_EQ( |
| zoom_factor_2, |
| display_manager()->GetDisplayInfo(display_id_list[0]).zoom_factor()); |
| EXPECT_EQ( |
| zoom_factor_1, |
| display_manager()->GetDisplayInfo(display_id_list[1]).zoom_factor()); |
| |
| // Set zoom factor for display 0, should not affect display 1. |
| auto properties = mojom::DisplayConfigProperties::New(); |
| properties->display_zoom_factor = zoom_factor_1; |
| mojom::DisplayConfigResult result = SetDisplayProperties( |
| base::NumberToString(display_id_list[0]), std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_EQ( |
| zoom_factor_1, |
| display_manager()->GetDisplayInfo(display_id_list[0]).zoom_factor()); |
| EXPECT_EQ( |
| zoom_factor_1, |
| display_manager()->GetDisplayInfo(display_id_list[1]).zoom_factor()); |
| |
| // Set zoom factor for display 1. |
| properties = mojom::DisplayConfigProperties::New(); |
| properties->display_zoom_factor = zoom_factor_2; |
| result = SetDisplayProperties(base::NumberToString(display_id_list[1]), |
| std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kSuccess, result); |
| EXPECT_EQ( |
| zoom_factor_1, |
| display_manager()->GetDisplayInfo(display_id_list[0]).zoom_factor()); |
| EXPECT_EQ( |
| zoom_factor_2, |
| display_manager()->GetDisplayInfo(display_id_list[1]).zoom_factor()); |
| |
| // Invalid zoom factor should fail. |
| const float invalid_zoom_factor = 0.01f; |
| properties = mojom::DisplayConfigProperties::New(); |
| properties->display_zoom_factor = invalid_zoom_factor; |
| result = SetDisplayProperties(base::NumberToString(display_id_list[1]), |
| std::move(properties)); |
| EXPECT_EQ(mojom::DisplayConfigResult::kPropertyValueOutOfRangeError, result); |
| EXPECT_EQ( |
| zoom_factor_2, |
| display_manager()->GetDisplayInfo(display_id_list[1]).zoom_factor()); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, SetDisplayMode) { |
| UpdateDisplay("1024x512,1024x512"); |
| std::vector<mojom::DisplayUnitInfoPtr> result = GetDisplayUnitInfoList(); |
| ASSERT_EQ(2u, result.size()); |
| // Internal display has just one mode. |
| EXPECT_EQ(0, result[0]->selected_display_mode_index); |
| ASSERT_EQ(1u, result[0]->available_display_modes.size()); |
| |
| auto properties = mojom::DisplayConfigProperties::New(); |
| auto display_mode = result[0]->available_display_modes[0].Clone(); |
| properties->display_mode = std::move(display_mode); |
| ASSERT_EQ(mojom::DisplayConfigResult::kSuccess, |
| SetDisplayProperties(result[0]->id, std::move(properties))); |
| |
| result = GetDisplayUnitInfoList(); |
| ASSERT_EQ(2u, result.size()); |
| EXPECT_EQ(0, result[0]->selected_display_mode_index); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, OverscanCalibration) { |
| UpdateDisplay("1200x600"); |
| int64_t id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); |
| ASSERT_NE(display::kInvalidDisplayId, id); |
| |
| // Test that kAdjust succeeds after kComplete call. |
| EXPECT_TRUE(OverscanCalibration(id, mojom::DisplayConfigOperation::kStart, |
| base::nullopt)); |
| EXPECT_EQ(gfx::Insets(0, 0, 0, 0), display_manager()->GetOverscanInsets(id)); |
| |
| gfx::Insets insets(10, 10, 10, 10); |
| EXPECT_TRUE( |
| OverscanCalibration(id, mojom::DisplayConfigOperation::kAdjust, insets)); |
| // Adjust has no effect until Complete. |
| EXPECT_EQ(gfx::Insets(0, 0, 0, 0), display_manager()->GetOverscanInsets(id)); |
| |
| EXPECT_TRUE(OverscanCalibration(id, mojom::DisplayConfigOperation::kComplete, |
| base::nullopt)); |
| gfx::Insets overscan = display_manager()->GetOverscanInsets(id); |
| EXPECT_EQ(insets, overscan) |
| << "Overscan: " << overscan.ToString() << " != " << insets.ToString(); |
| |
| // Test that kReset clears restores previous insets. |
| |
| // Start clears any overscan values. |
| EXPECT_TRUE(OverscanCalibration(id, mojom::DisplayConfigOperation::kStart, |
| base::nullopt)); |
| EXPECT_EQ(gfx::Insets(0, 0, 0, 0), display_manager()->GetOverscanInsets(id)); |
| |
| // Reset + Complete restores previously set insets. |
| EXPECT_TRUE(OverscanCalibration(id, mojom::DisplayConfigOperation::kReset, |
| base::nullopt)); |
| EXPECT_EQ(gfx::Insets(0, 0, 0, 0), display_manager()->GetOverscanInsets(id)); |
| EXPECT_TRUE(OverscanCalibration(id, mojom::DisplayConfigOperation::kComplete, |
| base::nullopt)); |
| EXPECT_EQ(insets, display_manager()->GetOverscanInsets(id)); |
| |
| // Additional complete call should fail. |
| EXPECT_FALSE(OverscanCalibration(id, mojom::DisplayConfigOperation::kComplete, |
| base::nullopt)); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, CustomTouchCalibrationInternal) { |
| UpdateDisplay("1200x600,600x1000*2"); |
| const int64_t internal_display_id = |
| display::test::DisplayManagerTestApi(display_manager()) |
| .SetFirstDisplayAsInternalDisplay(); |
| |
| InitExternalTouchDevices(internal_display_id); |
| |
| EXPECT_FALSE( |
| StartTouchCalibration(base::NumberToString(internal_display_id))); |
| EXPECT_FALSE(IsTouchCalibrationActive()); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, CustomTouchCalibrationWithoutStart) { |
| UpdateDisplay("1200x600,600x1000*2"); |
| EXPECT_FALSE(IsTouchCalibrationActive()); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, CustomTouchCalibrationNonTouchDisplay) { |
| UpdateDisplay("1200x600,600x1000*2"); |
| |
| const int64_t internal_display_id = |
| display::test::DisplayManagerTestApi(display_manager()) |
| .SetFirstDisplayAsInternalDisplay(); |
| |
| display::DisplayIdList display_id_list = |
| display_manager()->GetCurrentDisplayIdList(); |
| |
| // Pick the non internal display Id. |
| const int64_t display_id = display_id_list[0] == internal_display_id |
| ? display_id_list[1] |
| : display_id_list[0]; |
| |
| ws::InputDeviceClientTestApi().SetTouchscreenDevices({}); |
| std::string id = base::NumberToString(display_id); |
| |
| // Since no external touch devices are present, the calibration should fail. |
| EXPECT_FALSE(StartTouchCalibration(id)); |
| |
| // If an external touch device is present, the calibration should proceed. |
| InitExternalTouchDevices(display_id); |
| EXPECT_TRUE(StartTouchCalibration(id)); |
| EXPECT_TRUE(IsTouchCalibrationActive()); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, CustomTouchCalibrationInvalidPoints) { |
| UpdateDisplay("1200x600,600x1000*2"); |
| |
| const int64_t internal_display_id = |
| display::test::DisplayManagerTestApi(display_manager()) |
| .SetFirstDisplayAsInternalDisplay(); |
| |
| display::DisplayIdList display_id_list = |
| display_manager()->GetCurrentDisplayIdList(); |
| |
| // Pick the non internal display Id. |
| const int64_t display_id = display_id_list[0] == internal_display_id |
| ? display_id_list[1] |
| : display_id_list[0]; |
| |
| InitExternalTouchDevices(display_id); |
| |
| std::string id = base::NumberToString(display_id); |
| |
| EXPECT_TRUE(StartTouchCalibration(id)); |
| mojom::TouchCalibrationPtr calibration = GetDefaultCalibration(); |
| calibration->pairs[0]->display_point.set_x(-1); |
| EXPECT_FALSE(CompleteCustomTouchCalibration(id, std::move(calibration))); |
| |
| EXPECT_TRUE(StartTouchCalibration(id)); |
| calibration = GetDefaultCalibration(); |
| calibration->bounds.set_width(1); |
| calibration->pairs[0]->display_point.set_x(2); |
| EXPECT_FALSE(CompleteCustomTouchCalibration(id, std::move(calibration))); |
| } |
| |
| TEST_F(CrosDisplayConfigTest, CustomTouchCalibrationSuccess) { |
| UpdateDisplay("1200x600,600x1000*2"); |
| |
| const int64_t internal_display_id = |
| display::test::DisplayManagerTestApi(display_manager()) |
| .SetFirstDisplayAsInternalDisplay(); |
| |
| display::DisplayIdList display_id_list = |
| display_manager()->GetCurrentDisplayIdList(); |
| |
| // Pick the non internal display Id. |
| const int64_t display_id = display_id_list[0] == internal_display_id |
| ? display_id_list[1] |
| : display_id_list[0]; |
| |
| InitExternalTouchDevices(display_id); |
| |
| std::string id = base::NumberToString(display_id); |
| |
| EXPECT_TRUE(StartTouchCalibration(id)); |
| EXPECT_TRUE(IsTouchCalibrationActive()); |
| mojom::TouchCalibrationPtr calibration = GetDefaultCalibration(); |
| EXPECT_TRUE(CompleteCustomTouchCalibration(id, std::move(calibration))); |
| } |
| |
| } // namespace ash |