display_options_handler.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/webui/options/chromeos/display_options_handler.h" 6 7#include <string> 8 9#include "ash/display/display_controller.h" 10#include "ash/display/display_manager.h" 11#include "ash/display/output_configurator_animation.h" 12#include "ash/screen_ash.h" 13#include "ash/shell.h" 14#include "base/bind.h" 15#include "base/logging.h" 16#include "base/stringprintf.h" 17#include "base/strings/string_number_conversions.h" 18#include "base/values.h" 19#include "chrome/browser/chromeos/display/display_preferences.h" 20#include "chromeos/display/output_configurator.h" 21#include "content/public/browser/web_ui.h" 22#include "grit/generated_resources.h" 23#include "ui/base/l10n/l10n_util.h" 24#include "ui/gfx/display.h" 25#include "ui/gfx/rect.h" 26#include "ui/gfx/safe_integer_conversions.h" 27#include "ui/gfx/screen.h" 28 29using ash::internal::DisplayManager; 30 31namespace chromeos { 32namespace options { 33namespace { 34 35DisplayManager* GetDisplayManager() { 36 return ash::Shell::GetInstance()->display_manager(); 37} 38 39int64 GetDisplayId(const base::ListValue* args) { 40 // Assumes the display ID is specified as the first argument. 41 std::string id_value; 42 if (!args->GetString(0, &id_value)) { 43 LOG(ERROR) << "Can't find ID"; 44 return gfx::Display::kInvalidDisplayID; 45 } 46 47 int64 display_id = gfx::Display::kInvalidDisplayID; 48 if (!base::StringToInt64(id_value, &display_id)) { 49 LOG(ERROR) << "Invalid display id: " << id_value; 50 return gfx::Display::kInvalidDisplayID; 51 } 52 53 return display_id; 54} 55 56} // namespace 57 58DisplayOptionsHandler::DisplayOptionsHandler() { 59 ash::Shell::GetInstance()->display_controller()->AddObserver(this); 60} 61 62DisplayOptionsHandler::~DisplayOptionsHandler() { 63 ash::Shell::GetInstance()->display_controller()->RemoveObserver(this); 64} 65 66void DisplayOptionsHandler::GetLocalizedValues( 67 DictionaryValue* localized_strings) { 68 DCHECK(localized_strings); 69 RegisterTitle(localized_strings, "displayOptionsPage", 70 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_TAB_TITLE); 71 72 localized_strings->SetString( 73 "selectedDisplayTitleOptions", l10n_util::GetStringUTF16( 74 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_OPTIONS)); 75 localized_strings->SetString( 76 "selectedDisplayTitleResolution", l10n_util::GetStringUTF16( 77 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION)); 78 localized_strings->SetString( 79 "selectedDisplayTitleOrientation", l10n_util::GetStringUTF16( 80 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION)); 81 localized_strings->SetString( 82 "selectedDisplayTitleOverscan", l10n_util::GetStringUTF16( 83 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_OVERSCAN)); 84 85 localized_strings->SetString("startMirroring", l10n_util::GetStringUTF16( 86 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_MIRRORING)); 87 localized_strings->SetString("stopMirroring", l10n_util::GetStringUTF16( 88 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STOP_MIRRORING)); 89 localized_strings->SetString("mirroringDisplay", l10n_util::GetStringUTF16( 90 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_MIRRORING_DISPLAY_NAME)); 91 localized_strings->SetString("setPrimary", l10n_util::GetStringUTF16( 92 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_SET_PRIMARY)); 93 localized_strings->SetString("annotateBest", l10n_util::GetStringUTF16( 94 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION_ANNOTATION_BEST)); 95 localized_strings->SetString("orientation0", l10n_util::GetStringUTF16( 96 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STANDARD_ORIENTATION)); 97 localized_strings->SetString("orientation90", l10n_util::GetStringUTF16( 98 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_90)); 99 localized_strings->SetString("orientation180", l10n_util::GetStringUTF16( 100 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_180)); 101 localized_strings->SetString("orientation270", l10n_util::GetStringUTF16( 102 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION_270)); 103 localized_strings->SetString( 104 "startCalibratingOverscan", l10n_util::GetStringUTF16( 105 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN)); 106} 107 108void DisplayOptionsHandler::InitializePage() { 109 DCHECK(web_ui()); 110} 111 112void DisplayOptionsHandler::RegisterMessages() { 113 web_ui()->RegisterMessageCallback( 114 "getDisplayInfo", 115 base::Bind(&DisplayOptionsHandler::HandleDisplayInfo, 116 base::Unretained(this))); 117 web_ui()->RegisterMessageCallback( 118 "setMirroring", 119 base::Bind(&DisplayOptionsHandler::HandleMirroring, 120 base::Unretained(this))); 121 web_ui()->RegisterMessageCallback( 122 "setPrimary", 123 base::Bind(&DisplayOptionsHandler::HandleSetPrimary, 124 base::Unretained(this))); 125 web_ui()->RegisterMessageCallback( 126 "setDisplayLayout", 127 base::Bind(&DisplayOptionsHandler::HandleDisplayLayout, 128 base::Unretained(this))); 129 web_ui()->RegisterMessageCallback( 130 "setUIScale", 131 base::Bind(&DisplayOptionsHandler::HandleSetUIScale, 132 base::Unretained(this))); 133 web_ui()->RegisterMessageCallback( 134 "setOrientation", 135 base::Bind(&DisplayOptionsHandler::HandleSetOrientation, 136 base::Unretained(this))); 137} 138 139void DisplayOptionsHandler::OnDisplayConfigurationChanging() { 140} 141 142void DisplayOptionsHandler::OnDisplayConfigurationChanged() { 143 SendAllDisplayInfo(); 144} 145 146void DisplayOptionsHandler::SendAllDisplayInfo() { 147 DisplayManager* display_manager = GetDisplayManager(); 148 149 std::vector<const gfx::Display*> displays; 150 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { 151 displays.push_back(display_manager->GetDisplayAt(i)); 152 } 153 SendDisplayInfo(displays); 154} 155 156void DisplayOptionsHandler::SendDisplayInfo( 157 const std::vector<const gfx::Display*> displays) { 158 DisplayManager* display_manager = GetDisplayManager(); 159 ash::DisplayController* display_controller = 160 ash::Shell::GetInstance()->display_controller(); 161 base::FundamentalValue mirroring(display_manager->IsMirrored()); 162 163 int64 primary_id = ash::Shell::GetScreen()->GetPrimaryDisplay().id(); 164 base::ListValue js_displays; 165 for (size_t i = 0; i < displays.size(); ++i) { 166 const gfx::Display* display = displays[i]; 167 const ash::internal::DisplayInfo& display_info = 168 display_manager->GetDisplayInfo(display->id()); 169 const gfx::Rect& bounds = display->bounds(); 170 base::DictionaryValue* js_display = new base::DictionaryValue(); 171 js_display->SetString("id", base::Int64ToString(display->id())); 172 js_display->SetInteger("x", bounds.x()); 173 js_display->SetInteger("y", bounds.y()); 174 js_display->SetInteger("width", bounds.width()); 175 js_display->SetInteger("height", bounds.height()); 176 js_display->SetString("name", 177 display_manager->GetDisplayNameForId(display->id())); 178 js_display->SetBoolean("isPrimary", display->id() == primary_id); 179 js_display->SetBoolean("isInternal", display->IsInternal()); 180 js_display->SetInteger("orientation", 181 static_cast<int>(display_info.rotation())); 182 std::vector<float> ui_scales = DisplayManager::GetScalesForDisplay( 183 display_info); 184 base::ListValue* js_scales = new base::ListValue(); 185 gfx::SizeF base_size = display_info.bounds_in_pixel().size(); 186 base_size.Scale(1.0f / display->device_scale_factor()); 187 if (display_info.rotation() == gfx::Display::ROTATE_90 || 188 display_info.rotation() == gfx::Display::ROTATE_270) { 189 float tmp = base_size.width(); 190 base_size.set_width(base_size.height()); 191 base_size.set_height(tmp); 192 } 193 194 for (size_t i = 0; i < ui_scales.size(); ++i) { 195 base::DictionaryValue* scale_info = new base::DictionaryValue(); 196 scale_info->SetDouble("scale", ui_scales[i]); 197 scale_info->SetInteger( 198 "width", gfx::ToFlooredInt(base_size.width() * ui_scales[i])); 199 scale_info->SetInteger( 200 "height", gfx::ToFlooredInt(base_size.height() * ui_scales[i])); 201 scale_info->SetBoolean("selected", 202 display_info.ui_scale() == ui_scales[i]); 203 js_scales->Append(scale_info); 204 } 205 js_display->Set("uiScales", js_scales); 206 js_displays.Append(js_display); 207 } 208 209 scoped_ptr<base::Value> layout_value(base::Value::CreateNullValue()); 210 scoped_ptr<base::Value> offset_value(base::Value::CreateNullValue()); 211 if (display_manager->GetNumDisplays() > 1) { 212 const ash::DisplayLayout layout = 213 display_controller->GetCurrentDisplayLayout(); 214 layout_value.reset(new base::FundamentalValue(layout.position)); 215 offset_value.reset(new base::FundamentalValue(layout.offset)); 216 } 217 218 web_ui()->CallJavascriptFunction( 219 "options.DisplayOptions.setDisplayInfo", 220 mirroring, js_displays, *layout_value.get(), *offset_value.get()); 221} 222 223void DisplayOptionsHandler::OnFadeOutForMirroringFinished(bool is_mirroring) { 224 ash::Shell::GetInstance()->display_manager()->SetMirrorMode(is_mirroring); 225 // Not necessary to start fade-in animation. OutputConfigurator will do that. 226} 227 228void DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished( 229 int position, int offset) { 230 SetCurrentAndDefaultDisplayLayout( 231 ash::DisplayLayout::FromInts(position, offset)); 232 ash::Shell::GetInstance()->output_configurator_animation()-> 233 StartFadeInAnimation(); 234} 235 236void DisplayOptionsHandler::HandleDisplayInfo( 237 const base::ListValue* unused_args) { 238 SendAllDisplayInfo(); 239} 240 241void DisplayOptionsHandler::HandleMirroring(const base::ListValue* args) { 242 DCHECK(!args->empty()); 243 bool is_mirroring = false; 244 args->GetBoolean(0, &is_mirroring); 245 ash::Shell::GetInstance()->output_configurator_animation()-> 246 StartFadeOutAnimation(base::Bind( 247 &DisplayOptionsHandler::OnFadeOutForMirroringFinished, 248 base::Unretained(this), 249 is_mirroring)); 250} 251 252void DisplayOptionsHandler::HandleSetPrimary(const base::ListValue* args) { 253 DCHECK(!args->empty()); 254 int display_id = GetDisplayId(args); 255 if (display_id == gfx::Display::kInvalidDisplayID) 256 return; 257 258 ash::Shell::GetInstance()->display_controller()-> 259 SetPrimaryDisplayId(display_id); 260} 261 262void DisplayOptionsHandler::HandleDisplayLayout(const base::ListValue* args) { 263 double layout = -1; 264 double offset = -1; 265 if (!args->GetDouble(0, &layout) || !args->GetDouble(1, &offset)) { 266 LOG(ERROR) << "Invalid parameter"; 267 SendAllDisplayInfo(); 268 return; 269 } 270 DCHECK_LE(ash::DisplayLayout::TOP, layout); 271 DCHECK_GE(ash::DisplayLayout::LEFT, layout); 272 ash::Shell::GetInstance()->output_configurator_animation()-> 273 StartFadeOutAnimation(base::Bind( 274 &DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished, 275 base::Unretained(this), 276 static_cast<int>(layout), 277 static_cast<int>(offset))); 278} 279 280void DisplayOptionsHandler::HandleSetUIScale(const base::ListValue* args) { 281 DCHECK(!args->empty()); 282 283 int64 display_id = GetDisplayId(args); 284 if (display_id == gfx::Display::kInvalidDisplayID) 285 return; 286 287 std::string ui_scale_value; 288 double ui_scale = 0.0f; 289 if (!args->GetString(1, &ui_scale_value)) { 290 LOG(ERROR) << "Ca't find new ui_scale"; 291 return; 292 } 293 if (!base::StringToDouble(ui_scale_value, &ui_scale)) { 294 LOG(ERROR) << "Invalid ui_scale: " << ui_scale_value; 295 return; 296 } 297 298 GetDisplayManager()->SetDisplayUIScale(display_id, ui_scale); 299} 300 301void DisplayOptionsHandler::HandleSetOrientation(const base::ListValue* args) { 302 DCHECK(!args->empty()); 303 304 int64 display_id = GetDisplayId(args); 305 if (display_id == gfx::Display::kInvalidDisplayID) 306 return; 307 308 std::string rotation_value; 309 gfx::Display::Rotation new_rotation = gfx::Display::ROTATE_0; 310 if (!args->GetString(1, &rotation_value)) { 311 LOG(ERROR) << "Can't find new orientation"; 312 return; 313 } 314 if (rotation_value == "90") 315 new_rotation = gfx::Display::ROTATE_90; 316 else if (rotation_value == "180") 317 new_rotation = gfx::Display::ROTATE_180; 318 else if (rotation_value == "270") 319 new_rotation = gfx::Display::ROTATE_270; 320 else if (rotation_value != "0") 321 LOG(ERROR) << "Invalid rotation: " << rotation_value << " Falls back to 0"; 322 323 GetDisplayManager()->SetDisplayRotation(display_id, new_rotation); 324} 325 326} // namespace options 327} // namespace chromeos 328