Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / options / chromeos / display_options_handler.cc
index 528dc20..679bffb 100644 (file)
@@ -6,9 +6,9 @@
 
 #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"
@@ -17,7 +17,7 @@
 #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"
@@ -27,7 +27,7 @@
 #include "ui/gfx/screen.h"
 #include "ui/gfx/size_conversions.h"
 
-using ash::internal::DisplayManager;
+using ash::DisplayManager;
 
 namespace chromeos {
 namespace options {
@@ -54,11 +54,128 @@ int64 GetDisplayId(const base::ListValue* args) {
   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
@@ -111,6 +228,9 @@ void DisplayOptionsHandler::GetLocalizedValues(
   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() {
@@ -146,6 +266,10 @@ void DisplayOptionsHandler::RegisterMessages() {
       "setOrientation",
       base::Bind(&DisplayOptionsHandler::HandleSetOrientation,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setColorProfile",
+      base::Bind(&DisplayOptionsHandler::HandleSetColorProfile,
+                 base::Unretained(this)));
 }
 
 void DisplayOptionsHandler::OnDisplayConfigurationChanging() {
@@ -174,7 +298,7 @@ void DisplayOptionsHandler::SendDisplayInfo(
   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();
@@ -189,60 +313,26 @@ void DisplayOptionsHandler::SendDisplayInfo(
     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);
   }
 
@@ -262,14 +352,14 @@ void DisplayOptionsHandler::SendDisplayInfo(
 
 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();
 }
 
@@ -280,9 +370,11 @@ void DisplayOptionsHandler::HandleDisplayInfo(
 
 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),
@@ -295,6 +387,7 @@ void DisplayOptionsHandler::HandleSetPrimary(const base::ListValue* args) {
   if (display_id == gfx::Display::kInvalidDisplayID)
     return;
 
+  content::RecordAction(base::UserMetricsAction("Options_DisplaySetPrimary"));
   ash::Shell::GetInstance()->display_controller()->
       SetPrimaryDisplayId(display_id);
 }
@@ -309,7 +402,8 @@ void DisplayOptionsHandler::HandleDisplayLayout(const base::ListValue* args) {
   }
   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),
@@ -339,6 +433,8 @@ 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) {
@@ -350,16 +446,14 @@ void DisplayOptionsHandler::HandleSetResolution(const base::ListValue* args) {
     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)
@@ -404,8 +498,39 @@ void DisplayOptionsHandler::HandleSetOrientation(const base::ListValue* args) {
   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