Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ash/system/chromeos/screen_layout_observer.h" | 5 #include "ash/system/chromeos/screen_layout_observer.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 // Callback to handle a user selecting the notification view. | 95 // Callback to handle a user selecting the notification view. |
| 96 void OpenSettingsFromNotification() { | 96 void OpenSettingsFromNotification() { |
| 97 WmShell::Get()->RecordUserMetricsAction( | 97 WmShell::Get()->RecordUserMetricsAction( |
| 98 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED); | 98 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED); |
| 99 if (OpenSettings()) { | 99 if (OpenSettings()) { |
| 100 WmShell::Get()->RecordUserMetricsAction( | 100 WmShell::Get()->RecordUserMetricsAction( |
| 101 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS); | 101 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS); |
| 102 } | 102 } |
| 103 } | 103 } |
| 104 | 104 |
| 105 // Returns the name of the currently connected external display. This should not | 105 // Returns the name of the currently connected external display whose ID is |
| 106 // be used when the external display is used for mirroring. | 106 // |external_display_id|. This should not be used when the external display is |
| 107 base::string16 GetExternalDisplayName() { | 107 // used for mirroring. |
| 108 base::string16 GetExternalDisplayName(int64_t external_display_id) { | |
| 109 DCHECK(!display::Display::IsInternalDisplayId(external_display_id)); | |
| 110 | |
| 108 display::DisplayManager* display_manager = GetDisplayManager(); | 111 display::DisplayManager* display_manager = GetDisplayManager(); |
| 109 DCHECK(!display_manager->IsInMirrorMode()); | 112 DCHECK(!display_manager->IsInMirrorMode()); |
| 110 | 113 |
| 111 int64_t external_id = display::kInvalidDisplayId; | 114 if (external_display_id == display::kInvalidDisplayId) |
| 112 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { | |
| 113 int64_t id = display_manager->GetDisplayAt(i).id(); | |
| 114 if (!display::Display::IsInternalDisplayId(id)) { | |
| 115 external_id = id; | |
| 116 break; | |
| 117 } | |
| 118 } | |
| 119 | |
| 120 if (external_id == display::kInvalidDisplayId) | |
| 121 return l10n_util::GetStringUTF16(IDS_DISPLAY_NAME_UNKNOWN); | 115 return l10n_util::GetStringUTF16(IDS_DISPLAY_NAME_UNKNOWN); |
| 122 | 116 |
| 123 // The external display name may have an annotation of "(width x height)" in | 117 // The external display name may have an annotation of "(width x height)" in |
| 124 // case that the display is rotated or its resolution is changed. | 118 // case that the display is rotated or its resolution is changed. |
| 125 base::string16 name = GetDisplayName(external_id); | 119 base::string16 name = GetDisplayName(external_display_id); |
| 126 const display::ManagedDisplayInfo& display_info = | 120 const display::ManagedDisplayInfo& display_info = |
| 127 display_manager->GetDisplayInfo(external_id); | 121 display_manager->GetDisplayInfo(external_display_id); |
| 128 if (display_info.GetActiveRotation() != display::Display::ROTATE_0 || | 122 if (display_info.GetActiveRotation() != display::Display::ROTATE_0 || |
| 129 display_info.configured_ui_scale() != 1.0f || | 123 display_info.configured_ui_scale() != 1.0f || |
| 130 !display_info.overscan_insets_in_dip().IsEmpty()) { | 124 !display_info.overscan_insets_in_dip().IsEmpty()) { |
| 131 name = | 125 name = |
| 132 l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATED_NAME, | 126 l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATED_NAME, |
| 133 name, GetDisplaySize(external_id)); | 127 name, GetDisplaySize(external_display_id)); |
| 134 } else if (display_info.overscan_insets_in_dip().IsEmpty() && | 128 } else if (display_info.overscan_insets_in_dip().IsEmpty() && |
| 135 display_info.has_overscan()) { | 129 display_info.has_overscan()) { |
| 136 name = l10n_util::GetStringFUTF16( | 130 name = l10n_util::GetStringFUTF16( |
| 137 IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATED_NAME, name, | 131 IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATED_NAME, name, |
| 138 l10n_util::GetStringUTF16( | 132 l10n_util::GetStringUTF16( |
| 139 IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION_OVERSCAN)); | 133 IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION_OVERSCAN)); |
| 140 } | 134 } |
| 141 | 135 |
| 142 return name; | 136 return name; |
| 143 } | 137 } |
| 144 | 138 |
| 145 base::string16 GetDisplayMessage(base::string16* additional_message_out) { | 139 // Returns true if docked mode is currently enabled. |
| 140 bool IsDockedModeEnabled() { | |
| 146 display::DisplayManager* display_manager = GetDisplayManager(); | 141 display::DisplayManager* display_manager = GetDisplayManager(); |
| 147 if (display_manager->GetNumDisplays() > 1) { | 142 if (display::Display::HasInternalDisplay()) { |
| 143 // We have an internal display but it's not one of the active displays. | |
| 144 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { | |
| 145 if (display::Display::IsInternalDisplayId( | |
| 146 display_manager->GetDisplayAt(i).id())) { | |
| 147 return false; | |
| 148 } | |
| 149 | |
| 150 return true; | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 return false; | |
| 155 } | |
| 156 | |
| 157 // Returns the notification message that should be shown to the user when the | |
| 158 // docked mode is entered. | |
| 159 base::string16 GetDockedModeEnabledMessage( | |
| 160 base::string16* out_additional_message) { | |
| 161 DCHECK(IsDockedModeEnabled()); | |
| 162 | |
| 163 if (out_additional_message) { | |
|
oshima
2017/01/24 17:49:41
can this be null?
afakhry
2017/01/24 22:13:22
No. Replaced with a DCHECK
| |
| 164 *out_additional_message = ash::SubstituteChromeOSDeviceType( | |
| 165 IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED_DESCRIPTION); | |
| 166 } | |
| 167 | |
| 168 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED); | |
| 169 } | |
| 170 | |
| 171 // Fills |out_message| with the appropriate notification message the should be | |
| 172 // shown to the user when the status of the mirror mode is changed, and return | |
| 173 // true. Otherwise, returns false and |out_message| is not modified. | |
| 174 bool GetMirrorModeChangedMessage(bool current_mirror_mode, | |
| 175 base::string16* out_message, | |
| 176 base::string16* out_additional_message) { | |
|
oshima
2017/01/24 17:49:41
It's better to separate to
GetExit/EnterMirrorMod
afakhry
2017/01/24 22:13:22
Done.
| |
| 177 display::DisplayManager* display_manager = GetDisplayManager(); | |
| 178 if (current_mirror_mode) { | |
| 148 if (display::Display::HasInternalDisplay()) { | 179 if (display::Display::HasInternalDisplay()) { |
| 149 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, | 180 *out_message = l10n_util::GetStringFUTF16( |
| 150 GetExternalDisplayName()); | 181 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, |
| 182 GetDisplayName(display_manager->mirroring_display_id())); | |
| 183 } else { | |
| 184 *out_message = l10n_util::GetStringUTF16( | |
| 185 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL); | |
| 151 } | 186 } |
| 187 | |
| 188 return true; | |
| 189 } | |
| 190 | |
| 191 // Handle disabling mirror mode as a result of going to docked mode when we | |
| 192 // only have a single display (this means we actually have two physical | |
| 193 // displays, one of which is the internal display, but they were in mirror | |
| 194 // mode, and hence considered as one. Closing the internal display disables | |
| 195 // mirror mode and we still have a single active display). | |
| 196 // Also make sure we're not in unified mode as this is also considered as | |
| 197 // a single display. | |
| 198 if (IsDockedModeEnabled() && display_manager->GetNumDisplays() == 1 && | |
| 199 !display_manager->IsInUnifiedMode()) { | |
| 200 *out_message = GetDockedModeEnabledMessage(out_additional_message); | |
| 201 return true; | |
| 202 } | |
| 203 | |
| 204 if (display_manager->GetNumDisplays() > 2) { | |
| 205 // Mirror mode was turned off due to having more than two displays. Show | |
| 206 // a message that mirror mode for 3+ displays is not supported. | |
| 207 *out_message = | |
| 208 l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_MIRRORING_NOT_SUPPORTED); | |
| 209 return true; | |
| 210 } | |
| 211 | |
| 212 // Mirror mode was turned off; other messages should be shown e.g. extended | |
| 213 // mode is on, ... etc. | |
| 214 return false; | |
| 215 } | |
| 216 | |
| 217 // Returns the notification message that should be shown to the user when there | |
| 218 // is a change in the unified mode status. | |
| 219 base::string16 GetUnifiedModeChangedMessage(bool current_unified_mode) { | |
| 220 return l10n_util::GetStringUTF16( | |
| 221 current_unified_mode ? IDS_ASH_STATUS_TRAY_DISPLAY_UNIFIED | |
| 222 : IDS_ASH_STATUS_TRAY_DISPLAY_UNIFIED_EXITING); | |
| 223 } | |
| 224 | |
| 225 base::string16 GetDisplayRemovedMessage( | |
| 226 const display::ManagedDisplayInfo& removed_display_info, | |
| 227 base::string16* out_additional_message) { | |
| 228 // Removing the internal display means entering docked mode. | |
| 229 if (display::Display::IsInternalDisplayId(removed_display_info.id())) | |
| 230 return GetDockedModeEnabledMessage(out_additional_message); | |
| 231 | |
| 232 return l10n_util::GetStringFUTF16( | |
| 233 IDS_ASH_STATUS_TRAY_DISPLAY_REMOVED, | |
| 234 base::UTF8ToUTF16(removed_display_info.name())); | |
| 235 } | |
| 236 | |
| 237 base::string16 GetDisplayAddedMessage(int64_t added_display_id, | |
| 238 base::string16* additional_message_out) { | |
| 239 if (!display::Display::HasInternalDisplay()) { | |
| 152 return l10n_util::GetStringUTF16( | 240 return l10n_util::GetStringUTF16( |
| 153 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL); | 241 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL); |
| 154 } | 242 } |
| 155 | 243 |
| 156 if (display_manager->IsInMirrorMode()) { | 244 if (display::Display::IsInternalDisplayId(added_display_id)) { |
| 157 if (display::Display::HasInternalDisplay()) { | 245 // Adding the internal display means exiting docked mode (IFF we are not |
| 158 return l10n_util::GetStringFUTF16( | 246 // exiting unified mode. This case should have already been handled by the |
| 159 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, | 247 // time this function is called). |
| 160 GetDisplayName(display_manager->mirroring_display_id())); | |
| 161 } | |
| 162 return l10n_util::GetStringUTF16( | 248 return l10n_util::GetStringUTF16( |
| 163 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL); | 249 IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED_EXITING); |
| 164 } | 250 } |
| 165 | 251 |
| 166 if (display_manager->IsInUnifiedMode()) | 252 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, |
| 167 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_UNIFIED); | 253 GetExternalDisplayName(added_display_id)); |
| 168 | |
| 169 int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); | |
| 170 if (display::Display::HasInternalDisplay() && | |
| 171 !(display::Display::IsInternalDisplayId(primary_id))) { | |
| 172 if (additional_message_out) { | |
| 173 *additional_message_out = ash::SubstituteChromeOSDeviceType( | |
| 174 IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED_DESCRIPTION); | |
| 175 } | |
| 176 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED); | |
| 177 } | |
| 178 | |
| 179 return base::string16(); | |
| 180 } | 254 } |
| 181 | 255 |
| 182 } // namespace | 256 } // namespace |
| 183 | 257 |
| 184 const char ScreenLayoutObserver::kNotificationId[] = | 258 const char ScreenLayoutObserver::kNotificationId[] = |
| 185 "chrome://settings/display"; | 259 "chrome://settings/display"; |
| 186 | 260 |
| 187 ScreenLayoutObserver::ScreenLayoutObserver() { | 261 ScreenLayoutObserver::ScreenLayoutObserver() { |
| 188 WmShell::Get()->AddDisplayObserver(this); | 262 WmShell::Get()->AddDisplayObserver(this); |
| 189 UpdateDisplayInfo(NULL); | 263 UpdateDisplayInfo(NULL); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 203 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { | 277 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { |
| 204 int64_t id = display_manager->GetDisplayAt(i).id(); | 278 int64_t id = display_manager->GetDisplayAt(i).id(); |
| 205 display_info_[id] = display_manager->GetDisplayInfo(id); | 279 display_info_[id] = display_manager->GetDisplayInfo(id); |
| 206 } | 280 } |
| 207 } | 281 } |
| 208 | 282 |
| 209 bool ScreenLayoutObserver::GetDisplayMessageForNotification( | 283 bool ScreenLayoutObserver::GetDisplayMessageForNotification( |
| 210 const ScreenLayoutObserver::DisplayInfoMap& old_info, | 284 const ScreenLayoutObserver::DisplayInfoMap& old_info, |
| 211 base::string16* message_out, | 285 base::string16* message_out, |
| 212 base::string16* additional_message_out) { | 286 base::string16* additional_message_out) { |
| 213 // Display is added or removed. Use the same message as the one in | 287 // Detect changes in the mirror mode status. |
| 214 // the system tray. | 288 if (old_is_in_mirrored_mode_ != current_is_in_mirrored_mode_ && |
| 215 if (display_info_.size() != old_info.size()) { | 289 GetMirrorModeChangedMessage(current_is_in_mirrored_mode_, message_out, |
| 216 *message_out = GetDisplayMessage(additional_message_out); | 290 additional_message_out)) { |
| 217 return true; | 291 return true; |
| 218 } | 292 } |
| 219 | 293 |
| 220 for (DisplayInfoMap::const_iterator iter = display_info_.begin(); | 294 // Detect changes in the unified mode. |
| 221 iter != display_info_.end(); ++iter) { | 295 if (old_is_in_unified_mode_ != current_is_in_unified_mode_) { |
| 222 DisplayInfoMap::const_iterator old_iter = old_info.find(iter->first); | 296 *message_out = GetUnifiedModeChangedMessage(current_is_in_unified_mode_); |
| 223 // The display's number is same but different displays. This happens | 297 return true; |
| 224 // for the transition between docked mode and mirrored display. Falls back | 298 } |
| 225 // to GetDisplayMessage(). | 299 |
| 226 if (old_iter == old_info.end()) { | 300 // Displays are added or removed. |
| 227 *message_out = GetDisplayMessage(additional_message_out); | 301 if (display_info_.size() < old_info.size()) { |
| 302 // A display has been removed. | |
| 303 for (const auto& iter : old_info) { | |
| 304 if (display_info_.count(iter.first)) | |
| 305 continue; | |
| 306 | |
| 307 *message_out = | |
| 308 GetDisplayRemovedMessage(iter.second, additional_message_out); | |
| 228 return true; | 309 return true; |
| 229 } | 310 } |
| 311 } else if (display_info_.size() > old_info.size()) { | |
| 312 // A display has been added. | |
| 313 for (const auto& iter : display_info_) { | |
| 314 if (old_info.count(iter.first)) | |
| 315 continue; | |
| 230 | 316 |
| 231 if (iter->second.configured_ui_scale() != | 317 *message_out = GetDisplayAddedMessage(iter.first, additional_message_out); |
| 318 return true; | |
| 319 } | |
| 320 } | |
| 321 | |
| 322 for (const auto& iter : display_info_) { | |
| 323 DisplayInfoMap::const_iterator old_iter = old_info.find(iter.first); | |
| 324 if (old_iter == old_info.end()) { | |
| 325 // The display's number is same but different displays. This happens | |
| 326 // for the transition between docked mode and mirrored display. | |
| 327 // This condition can never be reached here, since it is handled above. | |
| 328 NOTREACHED(); | |
| 329 return false; | |
| 330 } | |
| 331 | |
| 332 if (iter.second.configured_ui_scale() != | |
| 232 old_iter->second.configured_ui_scale()) { | 333 old_iter->second.configured_ui_scale()) { |
| 233 *additional_message_out = l10n_util::GetStringFUTF16( | 334 *additional_message_out = l10n_util::GetStringFUTF16( |
| 234 IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, | 335 IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, |
| 235 GetDisplayName(iter->first), GetDisplaySize(iter->first)); | 336 GetDisplayName(iter.first), GetDisplaySize(iter.first)); |
| 236 return true; | 337 return true; |
| 237 } | 338 } |
| 238 if (iter->second.GetActiveRotation() != | 339 if (iter.second.GetActiveRotation() != |
| 239 old_iter->second.GetActiveRotation()) { | 340 old_iter->second.GetActiveRotation()) { |
| 240 int rotation_text_id = 0; | 341 int rotation_text_id = 0; |
| 241 switch (iter->second.GetActiveRotation()) { | 342 switch (iter.second.GetActiveRotation()) { |
| 242 case display::Display::ROTATE_0: | 343 case display::Display::ROTATE_0: |
| 243 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION; | 344 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION; |
| 244 break; | 345 break; |
| 245 case display::Display::ROTATE_90: | 346 case display::Display::ROTATE_90: |
| 246 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90; | 347 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90; |
| 247 break; | 348 break; |
| 248 case display::Display::ROTATE_180: | 349 case display::Display::ROTATE_180: |
| 249 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180; | 350 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180; |
| 250 break; | 351 break; |
| 251 case display::Display::ROTATE_270: | 352 case display::Display::ROTATE_270: |
| 252 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270; | 353 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270; |
| 253 break; | 354 break; |
| 254 } | 355 } |
| 255 *additional_message_out = l10n_util::GetStringFUTF16( | 356 *additional_message_out = l10n_util::GetStringFUTF16( |
| 256 IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetDisplayName(iter->first), | 357 IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetDisplayName(iter.first), |
| 257 l10n_util::GetStringUTF16(rotation_text_id)); | 358 l10n_util::GetStringUTF16(rotation_text_id)); |
| 258 return true; | 359 return true; |
| 259 } | 360 } |
| 260 } | 361 } |
| 261 | 362 |
| 262 // Found nothing special | 363 // Found nothing special |
| 263 return false; | 364 return false; |
| 264 } | 365 } |
| 265 | 366 |
| 266 void ScreenLayoutObserver::CreateOrUpdateNotification( | 367 void ScreenLayoutObserver::CreateOrUpdateNotification( |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 297 WmShell::Get()->RecordUserMetricsAction( | 398 WmShell::Get()->RecordUserMetricsAction( |
| 298 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED); | 399 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED); |
| 299 message_center::MessageCenter::Get()->AddNotification( | 400 message_center::MessageCenter::Get()->AddNotification( |
| 300 std::move(notification)); | 401 std::move(notification)); |
| 301 } | 402 } |
| 302 | 403 |
| 303 void ScreenLayoutObserver::OnDisplayConfigurationChanged() { | 404 void ScreenLayoutObserver::OnDisplayConfigurationChanged() { |
| 304 DisplayInfoMap old_info; | 405 DisplayInfoMap old_info; |
| 305 UpdateDisplayInfo(&old_info); | 406 UpdateDisplayInfo(&old_info); |
| 306 | 407 |
| 408 old_is_in_mirrored_mode_ = current_is_in_mirrored_mode_; | |
| 409 current_is_in_mirrored_mode_ = GetDisplayManager()->IsInMirrorMode(); | |
| 410 | |
| 411 old_is_in_unified_mode_ = current_is_in_unified_mode_; | |
| 412 current_is_in_unified_mode_ = GetDisplayManager()->IsInUnifiedMode(); | |
| 413 | |
| 307 if (!show_notifications_for_testing) | 414 if (!show_notifications_for_testing) |
| 308 return; | 415 return; |
| 309 | 416 |
| 310 base::string16 message; | 417 base::string16 message; |
| 311 base::string16 additional_message; | 418 base::string16 additional_message; |
| 312 if (GetDisplayMessageForNotification(old_info, &message, &additional_message)) | 419 if (GetDisplayMessageForNotification(old_info, &message, &additional_message)) |
| 313 CreateOrUpdateNotification(message, additional_message); | 420 CreateOrUpdateNotification(message, additional_message); |
| 314 } | 421 } |
| 315 | 422 |
| 316 } // namespace ash | 423 } // namespace ash |
| OLD | NEW |