15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/options/chromeos/display_options_handler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/display/display_controller.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/display/display_manager.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/display/output_configurator_animation.h"
124311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "ash/display/resolution_notification_controller.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/screen_ash.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/display/display_preferences.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chromeos/display/output_configurator.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h"
234311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "grit/ash_strings.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/display.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ui/gfx/size_conversions.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using ash::internal::DisplayManager;
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace chromeos {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace options {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DisplayManager* GetDisplayManager() {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ash::Shell::GetInstance()->display_manager();
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)int64 GetDisplayId(const base::ListValue* args) {
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Assumes the display ID is specified as the first argument.
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string id_value;
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!args->GetString(0, &id_value)) {
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "Can't find ID";
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return gfx::Display::kInvalidDisplayID;
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int64 display_id = gfx::Display::kInvalidDisplayID;
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!base::StringToInt64(id_value, &display_id)) {
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "Invalid display id: " << id_value;
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return gfx::Display::kInvalidDisplayID;
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return display_id;
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool CompareResolution(ash::internal::Resolution r1,
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                       ash::internal::Resolution r2) {
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return r1.size.GetArea() < r2.size.GetArea();
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DisplayOptionsHandler::DisplayOptionsHandler() {
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ash::Shell::GetInstance()->display_controller()->AddObserver(this);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DisplayOptionsHandler::~DisplayOptionsHandler() {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ash::Shell::GetInstance()->display_controller()->RemoveObserver(this);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayOptionsHandler::GetLocalizedValues(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DictionaryValue* localized_strings) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(localized_strings);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RegisterTitle(localized_strings, "displayOptionsPage",
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_TAB_TITLE);
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString(
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "selectedDisplayTitleOptions", l10n_util::GetStringUTF16(
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_OPTIONS));
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString(
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "selectedDisplayTitleResolution", l10n_util::GetStringUTF16(
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION));
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString(
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "selectedDisplayTitleOrientation", l10n_util::GetStringUTF16(
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION));
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString(
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "selectedDisplayTitleOverscan", l10n_util::GetStringUTF16(
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_OVERSCAN));
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  localized_strings->SetString("startMirroring", l10n_util::GetStringUTF16(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_MIRRORING));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  localized_strings->SetString("stopMirroring", l10n_util::GetStringUTF16(
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STOP_MIRRORING));
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString("mirroringDisplay", l10n_util::GetStringUTF16(
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_MIRRORING_DISPLAY_NAME));
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  localized_strings->SetString("setPrimary", l10n_util::GetStringUTF16(
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_SET_PRIMARY));
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString("annotateBest", l10n_util::GetStringUTF16(
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION_ANNOTATION_BEST));
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString("orientation0", l10n_util::GetStringUTF16(
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STANDARD_ORIENTATION));
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString("orientation90", l10n_util::GetStringUTF16(
1054311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90));
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString("orientation180", l10n_util::GetStringUTF16(
1074311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180));
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString("orientation270", l10n_util::GetStringUTF16(
1094311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270));
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  localized_strings->SetString(
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "startCalibratingOverscan", l10n_util::GetStringUTF16(
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayOptionsHandler::InitializePage() {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(web_ui());
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayOptionsHandler::RegisterMessages() {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "getDisplayInfo",
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&DisplayOptionsHandler::HandleDisplayInfo,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback(
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "setMirroring",
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&DisplayOptionsHandler::HandleMirroring,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback(
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "setPrimary",
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&DisplayOptionsHandler::HandleSetPrimary,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->RegisterMessageCallback(
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "setDisplayLayout",
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&DisplayOptionsHandler::HandleDisplayLayout,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 base::Unretained(this)));
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  web_ui()->RegisterMessageCallback(
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "setUIScale",
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&DisplayOptionsHandler::HandleSetUIScale,
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 base::Unretained(this)));
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  web_ui()->RegisterMessageCallback(
141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "setResolution",
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&DisplayOptionsHandler::HandleSetResolution,
143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 base::Unretained(this)));
144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  web_ui()->RegisterMessageCallback(
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      "setOrientation",
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&DisplayOptionsHandler::HandleSetOrientation,
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 base::Unretained(this)));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayOptionsHandler::OnDisplayConfigurationChanging() {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayOptionsHandler::OnDisplayConfigurationChanged() {
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendAllDisplayInfo();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayOptionsHandler::SendAllDisplayInfo() {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayManager* display_manager = GetDisplayManager();
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::vector<gfx::Display> displays;
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    displays.push_back(display_manager->GetDisplayAt(i));
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendDisplayInfo(displays);
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void DisplayOptionsHandler::SendDisplayInfo(
168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::vector<gfx::Display>& displays) {
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayManager* display_manager = GetDisplayManager();
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ash::DisplayController* display_controller =
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ash::Shell::GetInstance()->display_controller();
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FundamentalValue mirroring(display_manager->IsMirrored());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 primary_id = ash::Shell::GetScreen()->GetPrimaryDisplay().id();
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::ListValue js_displays;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < displays.size(); ++i) {
177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const gfx::Display& display = displays[i];
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ash::internal::DisplayInfo& display_info =
179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        display_manager->GetDisplayInfo(display.id());
180ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const gfx::Rect& bounds = display.bounds();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::DictionaryValue* js_display = new base::DictionaryValue();
182ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    js_display->SetString("id", base::Int64ToString(display.id()));
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    js_display->SetInteger("x", bounds.x());
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    js_display->SetInteger("y", bounds.y());
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    js_display->SetInteger("width", bounds.width());
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    js_display->SetInteger("height", bounds.height());
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    js_display->SetString("name",
188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                          display_manager->GetDisplayNameForId(display.id()));
189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    js_display->SetBoolean("isPrimary", display.id() == primary_id);
190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    js_display->SetBoolean("isInternal", display.IsInternal());
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    js_display->SetInteger("orientation",
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                           static_cast<int>(display_info.rotation()));
193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::vector<ash::internal::Resolution> resolutions;
194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::vector<float> ui_scales;
195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (display.IsInternal()) {
196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ui_scales = DisplayManager::GetScalesForDisplay(display_info);
197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      gfx::SizeF base_size = display_info.bounds_in_pixel().size();
198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base_size.Scale(1.0f / display.device_scale_factor());
199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (display_info.rotation() == gfx::Display::ROTATE_90 ||
200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          display_info.rotation() == gfx::Display::ROTATE_270) {
201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        float tmp = base_size.width();
202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        base_size.set_width(base_size.height());
203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        base_size.set_height(tmp);
204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      }
205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      for (size_t i = 0; i < ui_scales.size(); ++i) {
206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        gfx::SizeF new_size = base_size;
207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        new_size.Scale(ui_scales[i]);
208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        resolutions.push_back(ash::internal::Resolution(
209a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            gfx::ToFlooredSize(new_size), false /* interlaced */));
210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      }
211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    } else {
212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      for (size_t i = 0; i < display_info.resolutions().size(); ++i)
213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        resolutions.push_back(display_info.resolutions()[i]);
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::sort(resolutions.begin(), resolutions.end(), CompareResolution);
216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::ListValue* js_resolutions = new base::ListValue();
218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    gfx::Size current_size(bounds.width() * display.device_scale_factor(),
219a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                           bounds.height() * display.device_scale_factor());
220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    for (size_t i = 0; i < resolutions.size(); ++i) {
221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::DictionaryValue* resolution_info = new base::DictionaryValue();
222a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      if (!ui_scales.empty()) {
223a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        resolution_info->SetDouble("scale", ui_scales[i]);
224a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        if (ui_scales[i] == 1.0f)
225a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          resolution_info->SetBoolean("isBest", true);
226a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        resolution_info->SetBoolean(
227a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            "selected", display_info.ui_scale() == ui_scales[i]);
228a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      } else {
229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        // Picks the largest one as the "best", which is the last element
230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        // because |resolutions| is sorted by its area.
231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        if (i == resolutions.size() - 1)
232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          resolution_info->SetBoolean("isBest", true);
233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        resolution_info->SetBoolean(
234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)            "selected", (resolutions[i].size == current_size));
235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      }
236a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      resolution_info->SetInteger("width", resolutions[i].size.width());
237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      resolution_info->SetInteger("height",resolutions[i].size.height());
238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      js_resolutions->Append(resolution_info);
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    js_display->Set("resolutions", js_resolutions);
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    js_displays.Append(js_display);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Value> layout_value(base::Value::CreateNullValue());
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Value> offset_value(base::Value::CreateNullValue());
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (display_manager->GetNumDisplays() > 1) {
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ash::DisplayLayout layout =
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        display_controller->GetCurrentDisplayLayout();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    layout_value.reset(new base::FundamentalValue(layout.position));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    offset_value.reset(new base::FundamentalValue(layout.offset));
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "options.DisplayOptions.setDisplayInfo",
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      mirroring, js_displays, *layout_value.get(), *offset_value.get());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayOptionsHandler::OnFadeOutForMirroringFinished(bool is_mirroring) {
25990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ash::Shell::GetInstance()->display_manager()->SetMirrorMode(is_mirroring);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not necessary to start fade-in animation.  OutputConfigurator will do that.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished(
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int position, int offset) {
265eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SetCurrentDisplayLayout(
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ash::DisplayLayout::FromInts(position, offset));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ash::Shell::GetInstance()->output_configurator_animation()->
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StartFadeInAnimation();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayOptionsHandler::HandleDisplayInfo(
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::ListValue* unused_args) {
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendAllDisplayInfo();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayOptionsHandler::HandleMirroring(const base::ListValue* args) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!args->empty());
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_mirroring = false;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  args->GetBoolean(0, &is_mirroring);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ash::Shell::GetInstance()->output_configurator_animation()->
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StartFadeOutAnimation(base::Bind(
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &DisplayOptionsHandler::OnFadeOutForMirroringFinished,
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Unretained(this),
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          is_mirroring));
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayOptionsHandler::HandleSetPrimary(const base::ListValue* args) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!args->empty());
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int64 display_id = GetDisplayId(args);
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (display_id == gfx::Display::kInvalidDisplayID)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ash::Shell::GetInstance()->display_controller()->
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SetPrimaryDisplayId(display_id);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DisplayOptionsHandler::HandleDisplayLayout(const base::ListValue* args) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double layout = -1;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double offset = -1;
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!args->GetDouble(0, &layout) || !args->GetDouble(1, &offset)) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Invalid parameter";
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendAllDisplayInfo();
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(ash::DisplayLayout::TOP, layout);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(ash::DisplayLayout::LEFT, layout);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ash::Shell::GetInstance()->output_configurator_animation()->
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StartFadeOutAnimation(base::Bind(
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Unretained(this),
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<int>(layout),
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          static_cast<int>(offset)));
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisplayOptionsHandler::HandleSetUIScale(const base::ListValue* args) {
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!args->empty());
31790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int64 display_id = GetDisplayId(args);
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (display_id == gfx::Display::kInvalidDisplayID)
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  double ui_scale = 0.0f;
323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!args->GetDouble(1, &ui_scale) || ui_scale == 0.0f) {
324a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    LOG(ERROR) << "Can't find new ui_scale";
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
328a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  GetDisplayManager()->SetDisplayUIScale(display_id, ui_scale);
329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void DisplayOptionsHandler::HandleSetResolution(const base::ListValue* args) {
332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(!args->empty());
333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int64 display_id = GetDisplayId(args);
334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (display_id == gfx::Display::kInvalidDisplayID)
335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
337a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  double width = 0.0f;
338a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  double height = 0.0f;
339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!args->GetDouble(1, &width) || width == 0.0f) {
340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    LOG(ERROR) << "Can't find new width";
341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return;
342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!args->GetDouble(2, &height) || height == 0.0f) {
344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    LOG(ERROR) << "Can't find new height";
34590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
34690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
34790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3484311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  const ash::internal::DisplayInfo& display_info =
3494311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      GetDisplayManager()->GetDisplayInfo(display_id);
3504311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  gfx::Size new_resolution = gfx::ToFlooredSize(gfx::SizeF(width, height));
3514311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  gfx::Size old_resolution = display_info.size_in_pixel();
3524311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  bool has_new_resolution = false;
3534311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  bool has_old_resolution = false;
3544311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  for (size_t i = 0; i < display_info.resolutions().size(); ++i) {
3554311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    ash::internal::Resolution resolution = display_info.resolutions()[i];
3564311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    if (resolution.size == new_resolution)
3574311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      has_new_resolution = true;
3584311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    if (resolution.size == old_resolution)
3594311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      has_old_resolution = true;
3604311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  }
3614311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  if (!has_new_resolution) {
3624311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    LOG(ERROR) << "No new resolution " << new_resolution.ToString()
3634311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch               << " is found in the display info " << display_info.ToString();
3644311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    return;
3654311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  }
3664311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  if (!has_old_resolution) {
3674311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    LOG(ERROR) << "No old resolution " << old_resolution.ToString()
3684311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch               << " is found in the display info " << display_info.ToString();
3694311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    return;
3704311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  }
3714311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
3724311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  ash::Shell::GetInstance()->resolution_notification_controller()->
3734311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch      SetDisplayResolutionAndNotify(
3744311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch          display_id, old_resolution, new_resolution,
3754311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch          base::Bind(&StoreDisplayPrefs));
37690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
37790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
37890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void DisplayOptionsHandler::HandleSetOrientation(const base::ListValue* args) {
37990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!args->empty());
38090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int64 display_id = GetDisplayId(args);
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (display_id == gfx::Display::kInvalidDisplayID)
38390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
38490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
38590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string rotation_value;
38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  gfx::Display::Rotation new_rotation = gfx::Display::ROTATE_0;
38790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!args->GetString(1, &rotation_value)) {
38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "Can't find new orientation";
38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
39090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
39190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (rotation_value == "90")
39290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    new_rotation = gfx::Display::ROTATE_90;
39390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else if (rotation_value == "180")
39490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    new_rotation = gfx::Display::ROTATE_180;
39590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else if (rotation_value == "270")
39690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    new_rotation = gfx::Display::ROTATE_270;
39790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  else if (rotation_value != "0")
39890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "Invalid rotation: " << rotation_value << " Falls back to 0";
39990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
40090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GetDisplayManager()->SetDisplayRotation(display_id, new_rotation);
40190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
40290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace options
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace chromeos
405