Index: chrome/browser/ui/webui/options/chromeos/display_options_handler.cc |
diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc |
index 52a5e238d54b84717626fbb058d3b0412eea3455..b0aad022b86cc09783d45c2543b05ed7cd631dfe 100644 |
--- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc |
+++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc |
@@ -54,10 +54,37 @@ int64 GetDisplayId(const base::ListValue* args) { |
return display_id; |
} |
-bool CompareDisplayMode(ash::DisplayMode d1, ash::DisplayMode d2) { |
- if (d1.size.GetArea() == d2.size.GetArea()) |
- return d1.refresh_rate < d2.refresh_rate; |
- return d1.size.GetArea() < d2.size.GetArea(); |
+bool CompareResolution(base::Value* v1, base::Value* v2) { |
+ base::DictionaryValue* r1 = NULL; |
+ base::DictionaryValue* r2 = NULL; |
+ if (!v1->GetAsDictionary(&r1)) |
+ return true; |
+ if (!v2->GetAsDictionary(&r2)) |
+ return false; |
+ int width1 = 0, height1 = 0, width2 = 0, height2 = 0; |
+ if (!r1->GetInteger("width", &width1) || !r1->GetInteger("height", &height1)) |
+ return true; |
+ if (!r2->GetInteger("width", &width2) || !r2->GetInteger("height", &height2)) |
+ return false; |
+ |
+ if (width1 * height1 != width2 * height2) |
+ return width1 * height1 < width2 * height2; |
+ |
+ double dsf1 = 0, dsf2 = 0; |
+ if (!r1->GetDouble("deviceScaleFactor", &dsf1)) |
+ return true; |
+ if (!r2->GetDouble("deviceScaleFactor", &dsf2)) |
+ return false; |
+ return dsf1 < dsf2; |
+ |
+ double refresh1 = 0, refresh2 = 0; |
+ if (!r1->GetDouble("refreshRate", &refresh1)) |
+ return true; |
+ if (!r2->GetDouble("refreshRate", &refresh2)) |
+ return false; |
+ // Higher refresh rate should appear first. |
+ if (refresh1 != refresh2) |
+ return refresh1 > refresh2; |
} |
base::string16 GetColorProfileName(ui::ColorCalibrationProfile profile) { |
@@ -82,6 +109,102 @@ base::string16 GetColorProfileName(ui::ColorCalibrationProfile profile) { |
return base::string16(); |
} |
+base::ListValue* CreateResolutionsForUIScale( |
+ const ash::DisplayInfo& display_info) { |
+ std::vector<float> ui_scales = |
+ DisplayManager::GetScalesForDisplay(display_info); |
+ gfx::SizeF base_size = display_info.bounds_in_native().size(); |
+ base::ListValue* result = new base::ListValue(); |
+ |
+ base_size.Scale(1.0f / display_info.device_scale_factor()); |
+ if (display_info.rotation() == gfx::Display::ROTATE_90 || |
+ display_info.rotation() == gfx::Display::ROTATE_270) { |
+ float tmp = base_size.width(); |
+ base_size.set_width(base_size.height()); |
+ base_size.set_height(tmp); |
+ } |
+ for (size_t i = 0; i < ui_scales.size(); ++i) { |
+ base::DictionaryValue* resolution_info = new base::DictionaryValue(); |
+ resolution_info->SetDouble("scale", ui_scales[i]); |
+ if (ui_scales[i] == 1.0f) |
+ resolution_info->SetBoolean("isBest", true); |
+ resolution_info->SetBoolean( |
+ "selected", display_info.configured_ui_scale() == ui_scales[i]); |
+ resolution_info->SetInteger("width", base_size.width() * ui_scales[i]); |
+ resolution_info->SetInteger("height", base_size.height() * ui_scales[i]); |
+ result->Append(resolution_info); |
+ } |
+ |
+ return result; |
+} |
+ |
+base::ListValue* CreateResolutionsForExternalDisplay( |
+ const ash::DisplayInfo& display_info) { |
+ base::ListValue* result = new base::ListValue(); |
+ gfx::Size current_size = display_info.bounds_in_native().size(); |
+ |
+ const std::vector<ash::DisplayMode>& display_modes = |
+ display_info.display_modes(); |
+ base::DictionaryValue* largest_resolution_info = NULL; |
+ gfx::Size largest_resolution; |
+ bool largest_is_selected = false; |
+ for (size_t i = 0; i < display_modes.size(); ++i) { |
+ base::DictionaryValue* resolution_info = new base::DictionaryValue(); |
+ gfx::Size resolution = display_modes[i].size; |
+ // Picks the largest one as the "best", which is the last element |
+ // because |display_modes| is sorted by its area. |
+ if (largest_resolution.GetArea() < resolution.GetArea()) { |
+ if (largest_resolution_info) |
+ largest_resolution_info->SetBoolean("isBest", false); |
+ resolution_info->SetBoolean("isBest", true); |
+ largest_resolution_info = resolution_info; |
+ largest_resolution = resolution; |
+ largest_is_selected = (resolution == current_size); |
+ } |
+ resolution_info->SetBoolean("selected", (resolution == current_size)); |
+ resolution_info->SetInteger("width", resolution.width()); |
+ resolution_info->SetInteger("height", resolution.height()); |
+ if (display_modes[i].refresh_rate > 0.0f) { |
+ resolution_info->SetDouble("refreshRate", |
+ display_modes[i].refresh_rate); |
+ } |
+ result->Append(resolution_info); |
+ } |
+ |
+ // Add other scale factors for larger external displays. |
+ std::vector<float> device_scale_factors = |
+ DisplayManager::GetDeviceScaleFactorsForDisplay(display_info); |
+ if (device_scale_factors.size() > 1) { |
+ for (size_t i = 0; i < device_scale_factors.size(); ++i) { |
+ if (device_scale_factors[i] == 1.0f) |
+ continue; |
+ base::DictionaryValue* resolution_info = |
+ largest_resolution_info->DeepCopy(); |
+ resolution_info->SetBoolean("isBest", false); |
+ if (largest_is_selected && |
+ display_info.device_scale_factor() == device_scale_factors[i]) { |
+ resolution_info->SetBoolean("selected", true); |
+ largest_resolution_info->SetBoolean("selected", false); |
+ } else { |
+ resolution_info->SetBoolean("selected", false); |
+ } |
+ resolution_info->SetDouble( |
+ "deviceScaleFactor", device_scale_factors[i]); |
+ resolution_info->SetInteger( |
+ "originalWidth", largest_resolution.width()); |
+ resolution_info->SetInteger( |
+ "originalHeight", largest_resolution.height()); |
+ resolution_info->SetInteger( |
+ "width", largest_resolution.width() / device_scale_factors[i]); |
+ resolution_info->SetInteger( |
+ "height", largest_resolution.height() / device_scale_factors[i]); |
+ result->Append(resolution_info); |
+ } |
+ largest_resolution_info->SetDouble("deviceScaleFactor", 1.0); |
+ } |
+ return result; |
+} |
+ |
} // namespace |
DisplayOptionsHandler::DisplayOptionsHandler() { |
@@ -167,6 +290,10 @@ void DisplayOptionsHandler::RegisterMessages() { |
base::Bind(&DisplayOptionsHandler::HandleSetResolution, |
base::Unretained(this))); |
web_ui()->RegisterMessageCallback( |
+ "setDeviceScaleFactor", |
+ base::Bind(&DisplayOptionsHandler::HandleSetDeviceScaleFactor, |
+ base::Unretained(this))); |
+ web_ui()->RegisterMessageCallback( |
"setOrientation", |
base::Bind(&DisplayOptionsHandler::HandleSetOrientation, |
base::Unretained(this))); |
@@ -219,54 +346,11 @@ void DisplayOptionsHandler::SendDisplayInfo( |
static_cast<int>(display_info.rotation())); |
std::vector<ash::DisplayMode> display_modes; |
std::vector<float> ui_scales; |
- if (display.IsInternal()) { |
- ui_scales = DisplayManager::GetScalesForDisplay(display_info); |
- gfx::SizeF base_size = display_info.bounds_in_native().size(); |
- base_size.Scale(1.0f / display_info.device_scale_factor()); |
- if (display_info.rotation() == gfx::Display::ROTATE_90 || |
- display_info.rotation() == gfx::Display::ROTATE_270) { |
- float tmp = base_size.width(); |
- base_size.set_width(base_size.height()); |
- base_size.set_height(tmp); |
- } |
- for (size_t i = 0; i < ui_scales.size(); ++i) { |
- gfx::SizeF new_size = base_size; |
- new_size.Scale(ui_scales[i]); |
- display_modes.push_back(ash::DisplayMode( |
- gfx::ToFlooredSize(new_size), -1.0f, false, false)); |
- } |
- } else { |
- for (size_t i = 0; i < display_info.display_modes().size(); ++i) |
- display_modes.push_back(display_info.display_modes()[i]); |
- } |
- std::sort(display_modes.begin(), display_modes.end(), CompareDisplayMode); |
- |
- base::ListValue* js_resolutions = new base::ListValue(); |
- gfx::Size current_size = display_info.bounds_in_native().size(); |
- for (size_t i = 0; i < display_modes.size(); ++i) { |
- base::DictionaryValue* resolution_info = new base::DictionaryValue(); |
- gfx::Size resolution = display_modes[i].size; |
- if (!ui_scales.empty()) { |
- resolution_info->SetDouble("scale", ui_scales[i]); |
- if (ui_scales[i] == 1.0f) |
- resolution_info->SetBoolean("isBest", true); |
- resolution_info->SetBoolean( |
- "selected", display_info.configured_ui_scale() == ui_scales[i]); |
- } else { |
- // Picks the largest one as the "best", which is the last element |
- // because |display_modes| is sorted by its area. |
- if (i == display_modes.size() - 1) |
- resolution_info->SetBoolean("isBest", true); |
- resolution_info->SetBoolean("selected", (resolution == current_size)); |
- } |
- resolution_info->SetInteger("width", resolution.width()); |
- resolution_info->SetInteger("height", resolution.height()); |
- if (display_modes[i].refresh_rate > 0.0f) { |
- resolution_info->SetDouble("refreshRate", |
- display_modes[i].refresh_rate); |
- } |
- js_resolutions->Append(resolution_info); |
- } |
+ base::ListValue* js_resolutions = display.IsInternal() ? |
+ CreateResolutionsForUIScale(display_info) : |
+ CreateResolutionsForExternalDisplay(display_info); |
+ std::sort(js_resolutions->begin(), js_resolutions->end(), |
+ CompareResolution); |
js_display->Set("resolutions", js_resolutions); |
js_display->SetInteger("colorProfile", display_info.color_profile()); |
@@ -381,8 +465,6 @@ void DisplayOptionsHandler::HandleSetResolution(const base::ListValue* args) { |
if (display_id == gfx::Display::kInvalidDisplayID) |
return; |
- content::RecordAction( |
- base::UserMetricsAction("Options_DisplaySetResolution")); |
double width = 0.0f; |
double height = 0.0f; |
if (!args->GetDouble(1, &width) || width == 0.0f) { |
@@ -398,6 +480,9 @@ void DisplayOptionsHandler::HandleSetResolution(const base::ListValue* args) { |
GetDisplayManager()->GetDisplayInfo(display_id); |
gfx::Size new_resolution = gfx::ToFlooredSize(gfx::SizeF(width, height)); |
gfx::Size old_resolution = display_info.bounds_in_native().size(); |
+ if (new_resolution == old_resolution) |
+ return; |
+ |
bool has_new_resolution = false; |
bool has_old_resolution = false; |
for (size_t i = 0; i < display_info.display_modes().size(); ++i) { |
@@ -418,12 +503,44 @@ void DisplayOptionsHandler::HandleSetResolution(const base::ListValue* args) { |
return; |
} |
+ content::RecordAction( |
+ base::UserMetricsAction("Options_DisplaySetResolution")); |
+ |
+ if (display_info.device_scale_factor() != 1.0f) |
+ GetDisplayManager()->SetDisplayDeviceScaleFactor(display_id, 1.0f); |
+ |
ash::Shell::GetInstance()->resolution_notification_controller()-> |
SetDisplayResolutionAndNotify( |
display_id, old_resolution, new_resolution, |
base::Bind(&StoreDisplayPrefs)); |
} |
+void DisplayOptionsHandler::HandleSetDeviceScaleFactor( |
+ const base::ListValue* args) { |
+ DCHECK(!args->empty()); |
+ int64 display_id = GetDisplayId(args); |
+ if (display_id == gfx::Display::kInvalidDisplayID) |
+ return; |
+ |
+ double device_scale_factor = 0.0f; |
+ if (!args->GetDouble(1, &device_scale_factor) || |
+ device_scale_factor == 0.0f) { |
+ LOG(ERROR) << "Can't find new device scale factor"; |
+ return; |
+ } |
+ |
+ const ash::DisplayInfo& display_info = |
+ GetDisplayManager()->GetDisplayInfo(display_id); |
+ if (display_info.device_scale_factor() == device_scale_factor) |
+ return; |
+ |
+ content::RecordAction( |
+ base::UserMetricsAction("Options_DisplaySetExternalDeviceScaleFactor")); |
+ |
+ GetDisplayManager()->SetDisplayDeviceScaleFactor( |
+ display_id, device_scale_factor); |
+} |
+ |
void DisplayOptionsHandler::HandleSetOrientation(const base::ListValue* args) { |
DCHECK(!args->empty()); |