Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(270)

Side by Side Diff: ash/system/chromeos/screen_layout_observer.cc

Issue 2644593003: Fix bugs in the display notification (Closed)
Patch Set: Adding 2 more test stories Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698