Commit 2f6bc704 authored by mukai@chromium.org's avatar mukai@chromium.org

Remember the configured device scale factor for external displays.

Users can specify the device scale factor for some external
displays. Now, it remembers the configured device scale factor
to the local storage, and recovers to the specified value when
reconnected.

This also fixes the bug when the user specifies the resolution
and the device scale factor at the same time (DSF was ignored
beforehand).

BUG=396704
R=oshima@chromium.org
TEST=manually, unit_tests

Review URL: https://codereview.chromium.org/455443002

Cr-Commit-Position: refs/heads/master@{#288412}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288412 0039d316-1c4b-4281-b951-d872f2087c98
parent e8eea25c
...@@ -191,10 +191,16 @@ void DisplayChangeObserver::OnDisplayModeChanged( ...@@ -191,10 +191,16 @@ void DisplayChangeObserver::OnDisplayModeChanged(
continue; continue;
float device_scale_factor = 1.0f; float device_scale_factor = 1.0f;
if (!ui::IsDisplaySizeBlackListed(state.display->physical_size())) { if (state.display->type() == ui::DISPLAY_CONNECTION_TYPE_INTERNAL) {
device_scale_factor = device_scale_factor =
FindDeviceScaleFactor((kInchInMm * mode_info->size().width() / FindDeviceScaleFactor((kInchInMm * mode_info->size().width() /
state.display->physical_size().width())); state.display->physical_size().width()));
} else {
DisplayMode mode;
if (Shell::GetInstance()->display_manager()->GetSelectedModeForDisplayId(
state.display->display_id(), &mode)) {
device_scale_factor = mode.device_scale_factor;
}
} }
gfx::Rect display_bounds(state.display->origin(), mode_info->size()); gfx::Rect display_bounds(state.display->origin(), mode_info->size());
......
...@@ -26,6 +26,24 @@ namespace { ...@@ -26,6 +26,24 @@ namespace {
// TODO(oshima): This feature is obsolete. Remove this after m38. // TODO(oshima): This feature is obsolete. Remove this after m38.
bool allow_upgrade_to_high_dpi = false; bool allow_upgrade_to_high_dpi = false;
// Check the content of |spec| and fill |bounds| and |device_scale_factor|.
// Returns true when |bounds| is found.
bool GetDisplayBounds(
const std::string& spec, gfx::Rect* bounds, float* device_scale_factor) {
int width = 0;
int height = 0;
int x = 0;
int y = 0;
if (sscanf(spec.c_str(), "%dx%d*%f",
&width, &height, device_scale_factor) >= 2 ||
sscanf(spec.c_str(), "%d+%d-%dx%d*%f", &x, &y, &width, &height,
device_scale_factor) >= 4) {
bounds->SetRect(x, y, width, height);
return true;
}
return false;
}
} }
DisplayMode::DisplayMode() DisplayMode::DisplayMode()
...@@ -126,14 +144,8 @@ DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec, ...@@ -126,14 +144,8 @@ DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec,
} }
} }
int x = 0, y = 0, width, height;
float device_scale_factor = 1.0f; float device_scale_factor = 1.0f;
if (sscanf(main_spec.c_str(), "%dx%d*%f", if (!GetDisplayBounds(main_spec, &bounds_in_native, &device_scale_factor)) {
&width, &height, &device_scale_factor) >= 2 ||
sscanf(main_spec.c_str(), "%d+%d-%dx%d*%f", &x, &y, &width, &height,
&device_scale_factor) >= 4) {
bounds_in_native.SetRect(x, y, width, height);
} else {
#if defined(OS_WIN) #if defined(OS_WIN)
if (gfx::IsHighDPIEnabled()) { if (gfx::IsHighDPIEnabled()) {
device_scale_factor = gfx::GetDPIScale(); device_scale_factor = gfx::GetDPIScale();
...@@ -150,23 +162,23 @@ DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec, ...@@ -150,23 +162,23 @@ DisplayInfo DisplayInfo::CreateFromSpecWithID(const std::string& spec,
std::string resolution_list = parts[1]; std::string resolution_list = parts[1];
count = Tokenize(resolution_list, "|", &parts); count = Tokenize(resolution_list, "|", &parts);
for (size_t i = 0; i < count; ++i) { for (size_t i = 0; i < count; ++i) {
std::string resolution = parts[i]; DisplayMode mode;
int width, height; gfx::Rect mode_bounds;
float refresh_rate = 0.0f; std::vector<std::string> resolution;
if (sscanf(resolution.c_str(), Tokenize(parts[i], "%", &resolution);
"%dx%d%%%f", if (GetDisplayBounds(
&width, resolution[0], &mode_bounds, &mode.device_scale_factor)) {
&height, mode.size = mode_bounds.size();
&refresh_rate) >= 2) { if (resolution.size() > 1)
if (width * height >= largest_area && sscanf(resolution[1].c_str(), "%f", &mode.refresh_rate);
refresh_rate > highest_refresh_rate) { if (mode.size.GetArea() >= largest_area &&
mode.refresh_rate > highest_refresh_rate) {
// Use mode with largest area and highest refresh rate as native. // Use mode with largest area and highest refresh rate as native.
largest_area = width * height; largest_area = mode.size.GetArea();
highest_refresh_rate = refresh_rate; highest_refresh_rate = mode.refresh_rate;
native_mode = i; native_mode = i;
} }
display_modes.push_back( display_modes.push_back(mode);
DisplayMode(gfx::Size(width, height), refresh_rate, false, false));
} }
} }
display_modes[native_mode].native = true; display_modes[native_mode].native = true;
......
...@@ -44,17 +44,27 @@ TEST_F(DisplayInfoTest, CreateFromSpec) { ...@@ -44,17 +44,27 @@ TEST_F(DisplayInfoTest, CreateFromSpec) {
EXPECT_EQ(1.5f, info.configured_ui_scale()); EXPECT_EQ(1.5f, info.configured_ui_scale());
info = DisplayInfo::CreateFromSpecWithID( info = DisplayInfo::CreateFromSpecWithID(
"200x200#300x200|200x200%59.9|100x100%60", 10); "200x200#300x200|200x200%59.9|100x100%60|150x100*2|150x150*1.25%30", 10);
EXPECT_EQ("0,0 200x200", info.bounds_in_native().ToString()); EXPECT_EQ("0,0 200x200", info.bounds_in_native().ToString());
EXPECT_EQ(3u, info.display_modes().size()); EXPECT_EQ(5u, info.display_modes().size());
EXPECT_EQ("300x200", info.display_modes()[0].size.ToString()); EXPECT_EQ("300x200", info.display_modes()[0].size.ToString());
EXPECT_EQ("200x200", info.display_modes()[1].size.ToString()); EXPECT_EQ("200x200", info.display_modes()[1].size.ToString());
EXPECT_EQ("100x100", info.display_modes()[2].size.ToString()); EXPECT_EQ("100x100", info.display_modes()[2].size.ToString());
EXPECT_EQ("150x100", info.display_modes()[3].size.ToString());
EXPECT_EQ("150x150", info.display_modes()[4].size.ToString());
EXPECT_EQ(59.9f, info.display_modes()[1].refresh_rate); EXPECT_EQ(59.9f, info.display_modes()[1].refresh_rate);
EXPECT_EQ(60.0f, info.display_modes()[2].refresh_rate); EXPECT_EQ(60.0f, info.display_modes()[2].refresh_rate);
EXPECT_EQ(30.0f, info.display_modes()[4].refresh_rate);
EXPECT_EQ(1.0f, info.display_modes()[0].device_scale_factor);
EXPECT_EQ(1.0f, info.display_modes()[1].device_scale_factor);
EXPECT_EQ(1.0f, info.display_modes()[2].device_scale_factor);
EXPECT_EQ(2.0f, info.display_modes()[3].device_scale_factor);
EXPECT_EQ(1.25f, info.display_modes()[4].device_scale_factor);
EXPECT_TRUE(info.display_modes()[0].native); EXPECT_TRUE(info.display_modes()[0].native);
EXPECT_FALSE(info.display_modes()[1].native); EXPECT_FALSE(info.display_modes()[1].native);
EXPECT_FALSE(info.display_modes()[2].native); EXPECT_FALSE(info.display_modes()[2].native);
EXPECT_FALSE(info.display_modes()[3].native);
EXPECT_FALSE(info.display_modes()[4].native);
} }
} // namespace ash } // namespace ash
...@@ -530,6 +530,7 @@ void DisplayManager::RegisterDisplayProperty( ...@@ -530,6 +530,7 @@ void DisplayManager::RegisterDisplayProperty(
float ui_scale, float ui_scale,
const gfx::Insets* overscan_insets, const gfx::Insets* overscan_insets,
const gfx::Size& resolution_in_pixels, const gfx::Size& resolution_in_pixels,
float device_scale_factor,
ui::ColorCalibrationProfile color_profile) { ui::ColorCalibrationProfile color_profile) {
if (display_info_.find(display_id) == display_info_.end()) if (display_info_.find(display_id) == display_info_.end())
display_info_[display_id] = DisplayInfo(display_id, std::string(), false); display_info_[display_id] = DisplayInfo(display_id, std::string(), false);
...@@ -544,10 +545,12 @@ void DisplayManager::RegisterDisplayProperty( ...@@ -544,10 +545,12 @@ void DisplayManager::RegisterDisplayProperty(
if (overscan_insets) if (overscan_insets)
display_info_[display_id].SetOverscanInsets(*overscan_insets); display_info_[display_id].SetOverscanInsets(*overscan_insets);
if (!resolution_in_pixels.IsEmpty()) { if (!resolution_in_pixels.IsEmpty()) {
DCHECK(!IsInternalDisplayId(display_id));
// Default refresh rate, until OnNativeDisplaysChanged() updates us with the // Default refresh rate, until OnNativeDisplaysChanged() updates us with the
// actual display info, is 60 Hz. // actual display info, is 60 Hz.
display_modes_[display_id] = DisplayMode mode(resolution_in_pixels, 60.0f, false, false);
DisplayMode(resolution_in_pixels, 60.0f, false, false); mode.device_scale_factor = device_scale_factor;
display_modes_[display_id] = mode;
} }
} }
......
...@@ -182,6 +182,7 @@ class ASH_EXPORT DisplayManager ...@@ -182,6 +182,7 @@ class ASH_EXPORT DisplayManager
float ui_scale, float ui_scale,
const gfx::Insets* overscan_insets, const gfx::Insets* overscan_insets,
const gfx::Size& resolution_in_pixels, const gfx::Size& resolution_in_pixels,
float device_scale_factor,
ui::ColorCalibrationProfile color_profile); ui::ColorCalibrationProfile color_profile);
// Returns the display mode of |display_id| which is currently used. // Returns the display mode of |display_id| which is currently used.
......
...@@ -166,6 +166,11 @@ void LoadDisplayProperties() { ...@@ -166,6 +166,11 @@ void LoadDisplayProperties() {
dict_value->GetInteger("height", &height); dict_value->GetInteger("height", &height);
gfx::Size resolution_in_pixels(width, height); gfx::Size resolution_in_pixels(width, height);
float device_scale_factor = 1.0;
int dsf_value = 0;
if (dict_value->GetInteger("device-scale-factor", &dsf_value))
device_scale_factor = static_cast<float>(dsf_value) / 1000.0f;
gfx::Insets insets; gfx::Insets insets;
if (ValueToInsets(*dict_value, &insets)) if (ValueToInsets(*dict_value, &insets))
insets_to_set = &insets; insets_to_set = &insets;
...@@ -179,6 +184,7 @@ void LoadDisplayProperties() { ...@@ -179,6 +184,7 @@ void LoadDisplayProperties() {
ui_scale, ui_scale,
insets_to_set, insets_to_set,
resolution_in_pixels, resolution_in_pixels,
device_scale_factor,
color_profile); color_profile);
} }
} }
...@@ -238,6 +244,9 @@ void StoreCurrentDisplayProperties() { ...@@ -238,6 +244,9 @@ void StoreCurrentDisplayProperties() {
!mode.native) { !mode.native) {
property_value->SetInteger("width", mode.size.width()); property_value->SetInteger("width", mode.size.width());
property_value->SetInteger("height", mode.size.height()); property_value->SetInteger("height", mode.size.height());
property_value->SetInteger(
"device-scale-factor",
static_cast<int>(mode.device_scale_factor * 1000));
} }
if (!info.overscan_insets_in_dip().empty()) if (!info.overscan_insets_in_dip().empty())
InsetsToValue(info.overscan_insets_in_dip(), property_value.get()); InsetsToValue(info.overscan_insets_in_dip(), property_value.get());
......
...@@ -199,7 +199,7 @@ TEST_F(DisplayPreferencesTest, BasicStores) { ...@@ -199,7 +199,7 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
ash::DisplayManager* display_manager = ash::DisplayManager* display_manager =
ash::Shell::GetInstance()->display_manager(); ash::Shell::GetInstance()->display_manager();
UpdateDisplay("200x200*2, 400x300#400x400|300x200"); UpdateDisplay("200x200*2, 400x300#400x400|300x200*1.25");
int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id(); int64 id1 = gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().id();
gfx::Display::SetInternalDisplayId(id1); gfx::Display::SetInternalDisplayId(id1);
int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id(); int64 id2 = ash::ScreenUtil::GetSecondaryDisplay().id();
...@@ -292,13 +292,15 @@ TEST_F(DisplayPreferencesTest, BasicStores) { ...@@ -292,13 +292,15 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
EXPECT_FALSE(property->GetString("color_profile_name", &color_profile)); EXPECT_FALSE(property->GetString("color_profile_name", &color_profile));
// Resolution is saved only when the resolution is set // Resolution is saved only when the resolution is set
// by DisplayManager::SetDisplayResolution // by DisplayManager::SetDisplayMode
width = 0; width = 0;
height = 0; height = 0;
EXPECT_FALSE(property->GetInteger("width", &width)); EXPECT_FALSE(property->GetInteger("width", &width));
EXPECT_FALSE(property->GetInteger("height", &height)); EXPECT_FALSE(property->GetInteger("height", &height));
display_manager->SetDisplayResolution(id2, gfx::Size(300, 200)); ash::DisplayMode mode(gfx::Size(300, 200), 60.0f, false, true);
mode.device_scale_factor = 1.25f;
display_manager->SetDisplayMode(id2, mode);
display_controller->SetPrimaryDisplayId(id2); display_controller->SetPrimaryDisplayId(id2);
...@@ -311,11 +313,15 @@ TEST_F(DisplayPreferencesTest, BasicStores) { ...@@ -311,11 +313,15 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
// External display's resolution must be stored this time because // External display's resolution must be stored this time because
// it's not best. // it's not best.
int device_scale_factor = 0;
EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property)); EXPECT_TRUE(properties->GetDictionary(base::Int64ToString(id2), &property));
EXPECT_TRUE(property->GetInteger("width", &width)); EXPECT_TRUE(property->GetInteger("width", &width));
EXPECT_TRUE(property->GetInteger("height", &height)); EXPECT_TRUE(property->GetInteger("height", &height));
EXPECT_TRUE(property->GetInteger(
"device-scale-factor", &device_scale_factor));
EXPECT_EQ(300, width); EXPECT_EQ(300, width);
EXPECT_EQ(200, height); EXPECT_EQ(200, height);
EXPECT_EQ(1250, device_scale_factor);
// The layout remains the same. // The layout remains the same.
EXPECT_TRUE(displays->GetDictionary(key, &layout_value)); EXPECT_TRUE(displays->GetDictionary(key, &layout_value));
...@@ -364,7 +370,7 @@ TEST_F(DisplayPreferencesTest, BasicStores) { ...@@ -364,7 +370,7 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
// Set new display's selected resolution. // Set new display's selected resolution.
display_manager->RegisterDisplayProperty( display_manager->RegisterDisplayProperty(
id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400), id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400), 1.0f,
ui::COLOR_PROFILE_STANDARD); ui::COLOR_PROFILE_STANDARD);
UpdateDisplay("200x200*2, 600x500#600x500|500x400"); UpdateDisplay("200x200*2, 600x500#600x500|500x400");
...@@ -390,7 +396,7 @@ TEST_F(DisplayPreferencesTest, BasicStores) { ...@@ -390,7 +396,7 @@ TEST_F(DisplayPreferencesTest, BasicStores) {
// Set yet another new display's selected resolution. // Set yet another new display's selected resolution.
display_manager->RegisterDisplayProperty( display_manager->RegisterDisplayProperty(
id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400), id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400), 1.0f,
ui::COLOR_PROFILE_STANDARD); ui::COLOR_PROFILE_STANDARD);
// Disconnect 2nd display first to generate new id for external display. // Disconnect 2nd display first to generate new id for external display.
UpdateDisplay("200x200*2"); UpdateDisplay("200x200*2");
...@@ -452,9 +458,9 @@ TEST_F(DisplayPreferencesTest, PreventStore) { ...@@ -452,9 +458,9 @@ TEST_F(DisplayPreferencesTest, PreventStore) {
ResolutionNotificationController::kNotificationId)); ResolutionNotificationController::kNotificationId));
// Once the notification is removed, the specified resolution will be stored // Once the notification is removed, the specified resolution will be stored
// by SetDisplayResolution. // by SetDisplayMode.
ash::Shell::GetInstance()->display_manager()->SetDisplayResolution( ash::Shell::GetInstance()->display_manager()->SetDisplayMode(
id, gfx::Size(300, 200)); id, ash::DisplayMode(gfx::Size(300, 200), 60.0f, false, true));
UpdateDisplay("300x200#500x400|400x300|300x200"); UpdateDisplay("300x200#500x400|400x300|300x200");
property = NULL; property = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment