#include <string>
+#include "ash/display/display_configurator_animation.h"
#include "ash/display/display_controller.h"
#include "ash/display/display_manager.h"
-#include "ash/display/output_configurator_animation.h"
#include "ash/display/resolution_notification_controller.h"
#include "ash/shell.h"
#include "base/bind.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/chromeos/display/display_preferences.h"
-#include "chromeos/display/output_configurator.h"
+#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_ui.h"
#include "grit/ash_strings.h"
#include "grit/generated_resources.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/size_conversions.h"
-using ash::internal::DisplayManager;
+using ash::DisplayManager;
namespace chromeos {
namespace options {
return display_id;
}
-bool CompareDisplayMode(ash::internal::DisplayMode d1,
- ash::internal::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* display1, base::Value* display2) {
+ base::DictionaryValue* d1 = NULL;
+ base::DictionaryValue* d2 = NULL;
+ CHECK(display1->GetAsDictionary(&d1) && display2->GetAsDictionary(&d2));
+ int width1 = 0, height1 = 0, width2 = 0, height2 = 0;
+ CHECK(d1->GetInteger("width", &width1) && d1->GetInteger("height", &height1));
+ CHECK(d2->GetInteger("width", &width2) && d2->GetInteger("height", &height2));
+ double scale_factor1 = 0, scale_factor2 = 0;
+ if (d1->GetDouble("scaleFactor", &scale_factor1)) {
+ width1 /= scale_factor1;
+ height1 /= scale_factor1;
+ }
+ if (d2->GetDouble("scaleFactor", &scale_factor2)) {
+ width2 /= scale_factor2;
+ height2 /= scale_factor2;
+ }
+
+ if (width1 * height1 == width2 * height2) {
+ if (scale_factor1 != scale_factor2)
+ return scale_factor1 < scale_factor2;
+
+ int refresh_rate1 = 0, refresh_rate2 = 0;
+ CHECK(d1->GetInteger("refreshRate", &refresh_rate1) ==
+ d2->GetInteger("refreshRate", &refresh_rate2));
+ return refresh_rate1 < refresh_rate2;
+ }
+ return width1 * height1 < width2 * height2;
+}
+
+base::string16 GetColorProfileName(ui::ColorCalibrationProfile profile) {
+ switch (profile) {
+ case ui::COLOR_PROFILE_STANDARD:
+ return l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_STANDARD);
+ case ui::COLOR_PROFILE_DYNAMIC:
+ return l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_DYNAMIC);
+ case ui::COLOR_PROFILE_MOVIE:
+ return l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_MOVIE);
+ case ui::COLOR_PROFILE_READING:
+ return l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_READING);
+ case ui::NUM_COLOR_PROFILES:
+ break;
+ }
+
+ NOTREACHED();
+ return base::string16();
+}
+
+scoped_ptr<base::ListValue> GetResolutionsForInternalDisplay(
+ const ash::DisplayInfo& display_info) {
+ scoped_ptr<base::ListValue> js_resolutions(new base::ListValue);
+ const std::vector<float> 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) {
+ base::DictionaryValue* resolution_info = new base::DictionaryValue();
+ gfx::SizeF new_size = base_size;
+ new_size.Scale(ui_scales[i]);
+ gfx::Size resolution = gfx::ToFlooredSize(new_size);
+ 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", resolution.width());
+ resolution_info->SetInteger("height", resolution.height());
+ js_resolutions->Append(resolution_info);
+ }
+
+ return js_resolutions.Pass();
+}
+
+scoped_ptr<base::ListValue> GetResolutionsForExternalDisplay(
+ const ash::DisplayInfo& display_info) {
+ scoped_ptr<base::ListValue> js_resolutions(new base::ListValue);
+
+ gfx::Size current_size = display_info.bounds_in_native().size();
+ int largest_index = -1;
+ int largest_area = -1;
+
+ for (size_t i = 0; i < display_info.display_modes().size(); ++i) {
+ base::DictionaryValue* resolution_info = new base::DictionaryValue();
+ const ash::DisplayMode& display_mode = display_info.display_modes()[i];
+ gfx::Size resolution = display_mode.size;
+
+ if (resolution.GetArea() > largest_area) {
+ resolution_info->SetBoolean("isBest", true);
+ largest_area = resolution.GetArea();
+ if (largest_index >= 0) {
+ base::DictionaryValue* prev_largest = NULL;
+ CHECK(js_resolutions->GetDictionary(largest_index, &prev_largest));
+ prev_largest->SetBoolean("isBest", false);
+ }
+ largest_index = i;
+ }
+
+ if (resolution == current_size) {
+ // Right now, the scale factor for unselected resolutions is unknown.
+ // TODO(mukai): Set the scale factor for unselected ones.
+ resolution_info->SetDouble(
+ "scaleFactor", display_info.device_scale_factor());
+ resolution_info->SetBoolean("selected", true);
+ }
+
+ resolution_info->SetInteger("width", resolution.width());
+ resolution_info->SetInteger("height", resolution.height());
+ resolution_info->SetDouble("refreshRate", display_mode.refresh_rate);
+ js_resolutions->Append(resolution_info);
+ }
+
+ return js_resolutions.Pass();
}
} // namespace
localized_strings->SetString(
"startCalibratingOverscan", l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN));
+ localized_strings->SetString(
+ "selectedDisplayColorProfile", l10n_util::GetStringUTF16(
+ IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE));
}
void DisplayOptionsHandler::InitializePage() {
"setOrientation",
base::Bind(&DisplayOptionsHandler::HandleSetOrientation,
base::Unretained(this)));
+ web_ui()->RegisterMessageCallback(
+ "setColorProfile",
+ base::Bind(&DisplayOptionsHandler::HandleSetColorProfile,
+ base::Unretained(this)));
}
void DisplayOptionsHandler::OnDisplayConfigurationChanging() {
base::ListValue js_displays;
for (size_t i = 0; i < displays.size(); ++i) {
const gfx::Display& display = displays[i];
- const ash::internal::DisplayInfo& display_info =
+ const ash::DisplayInfo& display_info =
display_manager->GetDisplayInfo(display.id());
const gfx::Rect& bounds = display.bounds();
base::DictionaryValue* js_display = new base::DictionaryValue();
js_display->SetBoolean("isInternal", display.IsInternal());
js_display->SetInteger("orientation",
static_cast<int>(display_info.rotation()));
- std::vector<ash::internal::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::internal::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();
- gfx::Insets current_overscan = display_info.GetOverscanInsetsInPixel();
- 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.Enlarge(
- -current_overscan.width(), -current_overscan.height());
- }
- 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);
+
+ scoped_ptr<base::ListValue> js_resolutions = display.IsInternal() ?
+ GetResolutionsForInternalDisplay(display_info) :
+ GetResolutionsForExternalDisplay(display_info);
+ std::sort(
+ js_resolutions->begin(), js_resolutions->end(), CompareResolution);
+ js_display->Set("resolutions", js_resolutions.release());
+
+ js_display->SetInteger("colorProfile", display_info.color_profile());
+ base::ListValue* available_color_profiles = new base::ListValue();
+ for (size_t i = 0;
+ i < display_info.available_color_profiles().size(); ++i) {
+ base::DictionaryValue* color_profile_dict = new base::DictionaryValue();
+ ui::ColorCalibrationProfile color_profile =
+ display_info.available_color_profiles()[i];
+ color_profile_dict->SetInteger("profileId", color_profile);
+ color_profile_dict->SetString("name", GetColorProfileName(color_profile));
+ available_color_profiles->Append(color_profile_dict);
}
- js_display->Set("resolutions", js_resolutions);
+ js_display->Set("availableColorProfiles", available_color_profiles);
js_displays.Append(js_display);
}
void DisplayOptionsHandler::OnFadeOutForMirroringFinished(bool is_mirroring) {
ash::Shell::GetInstance()->display_manager()->SetMirrorMode(is_mirroring);
- // Not necessary to start fade-in animation. OutputConfigurator will do that.
+ // Not necessary to start fade-in animation. DisplayConfigurator will do that.
}
void DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished(
int position, int offset) {
SetCurrentDisplayLayout(
ash::DisplayLayout::FromInts(position, offset));
- ash::Shell::GetInstance()->output_configurator_animation()->
+ ash::Shell::GetInstance()->display_configurator_animation()->
StartFadeInAnimation();
}
void DisplayOptionsHandler::HandleMirroring(const base::ListValue* args) {
DCHECK(!args->empty());
+ content::RecordAction(
+ base::UserMetricsAction("Options_DisplayToggleMirroring"));
bool is_mirroring = false;
args->GetBoolean(0, &is_mirroring);
- ash::Shell::GetInstance()->output_configurator_animation()->
+ ash::Shell::GetInstance()->display_configurator_animation()->
StartFadeOutAnimation(base::Bind(
&DisplayOptionsHandler::OnFadeOutForMirroringFinished,
base::Unretained(this),
if (display_id == gfx::Display::kInvalidDisplayID)
return;
+ content::RecordAction(base::UserMetricsAction("Options_DisplaySetPrimary"));
ash::Shell::GetInstance()->display_controller()->
SetPrimaryDisplayId(display_id);
}
}
DCHECK_LE(ash::DisplayLayout::TOP, layout);
DCHECK_GE(ash::DisplayLayout::LEFT, layout);
- ash::Shell::GetInstance()->output_configurator_animation()->
+ content::RecordAction(base::UserMetricsAction("Options_DisplayRearrange"));
+ ash::Shell::GetInstance()->display_configurator_animation()->
StartFadeOutAnimation(base::Bind(
&DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished,
base::Unretained(this),
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) {
return;
}
- const ash::internal::DisplayInfo& display_info =
+ const ash::DisplayInfo& display_info =
GetDisplayManager()->GetDisplayInfo(display_id);
- gfx::Insets current_overscan = display_info.GetOverscanInsetsInPixel();
gfx::Size new_resolution = gfx::ToFlooredSize(gfx::SizeF(width, height));
- new_resolution.Enlarge(current_overscan.width(), current_overscan.height());
gfx::Size old_resolution = display_info.bounds_in_native().size();
bool has_new_resolution = false;
bool has_old_resolution = false;
for (size_t i = 0; i < display_info.display_modes().size(); ++i) {
- ash::internal::DisplayMode display_mode = display_info.display_modes()[i];
+ ash::DisplayMode display_mode = display_info.display_modes()[i];
if (display_mode.size == new_resolution)
has_new_resolution = true;
if (display_mode.size == old_resolution)
else if (rotation_value != "0")
LOG(ERROR) << "Invalid rotation: " << rotation_value << " Falls back to 0";
+ content::RecordAction(
+ base::UserMetricsAction("Options_DisplaySetOrientation"));
GetDisplayManager()->SetDisplayRotation(display_id, new_rotation);
}
+void DisplayOptionsHandler::HandleSetColorProfile(const base::ListValue* args) {
+ DCHECK(!args->empty());
+ int64 display_id = GetDisplayId(args);
+ if (display_id == gfx::Display::kInvalidDisplayID)
+ return;
+
+ std::string profile_value;
+ if (!args->GetString(1, &profile_value)) {
+ LOG(ERROR) << "Invalid profile_value";
+ return;
+ }
+
+ int profile_id;
+ if (!base::StringToInt(profile_value, &profile_id)) {
+ LOG(ERROR) << "Invalid profile: " << profile_value;
+ return;
+ }
+
+ if (profile_id < ui::COLOR_PROFILE_STANDARD ||
+ profile_id > ui::COLOR_PROFILE_READING) {
+ LOG(ERROR) << "Invalid profile_id: " << profile_id;
+ return;
+ }
+
+ GetDisplayManager()->SetColorCalibrationProfile(
+ display_id, static_cast<ui::ColorCalibrationProfile>(profile_id));
+ SendAllDisplayInfo();
+}
+
} // namespace options
} // namespace chromeos