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

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

Issue 2644593003: Fix bugs in the display notification (Closed)
Patch Set: Nit Created 3 years, 10 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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 // Callback to handle a user selecting the notification view. 94 // Callback to handle a user selecting the notification view.
95 void OpenSettingsFromNotification() { 95 void OpenSettingsFromNotification() {
96 WmShell::Get()->RecordUserMetricsAction( 96 WmShell::Get()->RecordUserMetricsAction(
97 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED); 97 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SELECTED);
98 if (OpenSettings()) { 98 if (OpenSettings()) {
99 WmShell::Get()->RecordUserMetricsAction( 99 WmShell::Get()->RecordUserMetricsAction(
100 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS); 100 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_SHOW_SETTINGS);
101 } 101 }
102 } 102 }
103 103
104 // Returns the name of the currently connected external display. This should not 104 // Returns the name of the currently connected external display whose ID is
105 // be used when the external display is used for mirroring. 105 // |external_display_id|. This should not be used when the external display is
106 base::string16 GetExternalDisplayName() { 106 // used for mirroring.
107 base::string16 GetExternalDisplayName(int64_t external_display_id) {
108 DCHECK(!display::Display::IsInternalDisplayId(external_display_id));
109
107 display::DisplayManager* display_manager = GetDisplayManager(); 110 display::DisplayManager* display_manager = GetDisplayManager();
108 DCHECK(!display_manager->IsInMirrorMode()); 111 DCHECK(!display_manager->IsInMirrorMode());
109 112
110 int64_t external_id = display::kInvalidDisplayId; 113 if (external_display_id == display::kInvalidDisplayId)
111 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
112 int64_t id = display_manager->GetDisplayAt(i).id();
113 if (!display::Display::IsInternalDisplayId(id)) {
114 external_id = id;
115 break;
116 }
117 }
118
119 if (external_id == display::kInvalidDisplayId)
120 return l10n_util::GetStringUTF16(IDS_DISPLAY_NAME_UNKNOWN); 114 return l10n_util::GetStringUTF16(IDS_DISPLAY_NAME_UNKNOWN);
121 115
122 // The external display name may have an annotation of "(width x height)" in 116 // The external display name may have an annotation of "(width x height)" in
123 // case that the display is rotated or its resolution is changed. 117 // case that the display is rotated or its resolution is changed.
124 base::string16 name = GetDisplayName(external_id); 118 base::string16 name = GetDisplayName(external_display_id);
125 const display::ManagedDisplayInfo& display_info = 119 const display::ManagedDisplayInfo& display_info =
126 display_manager->GetDisplayInfo(external_id); 120 display_manager->GetDisplayInfo(external_display_id);
127 if (display_info.GetActiveRotation() != display::Display::ROTATE_0 || 121 if (display_info.GetActiveRotation() != display::Display::ROTATE_0 ||
128 display_info.configured_ui_scale() != 1.0f || 122 display_info.configured_ui_scale() != 1.0f ||
129 !display_info.overscan_insets_in_dip().IsEmpty()) { 123 !display_info.overscan_insets_in_dip().IsEmpty()) {
130 name = 124 name =
131 l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATED_NAME, 125 l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATED_NAME,
132 name, GetDisplaySize(external_id)); 126 name, GetDisplaySize(external_display_id));
133 } else if (display_info.overscan_insets_in_dip().IsEmpty() && 127 } else if (display_info.overscan_insets_in_dip().IsEmpty() &&
134 display_info.has_overscan()) { 128 display_info.has_overscan()) {
135 name = l10n_util::GetStringFUTF16( 129 name = l10n_util::GetStringFUTF16(
136 IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATED_NAME, name, 130 IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATED_NAME, name,
137 l10n_util::GetStringUTF16( 131 l10n_util::GetStringUTF16(
138 IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION_OVERSCAN)); 132 IDS_ASH_STATUS_TRAY_DISPLAY_ANNOTATION_OVERSCAN));
139 } 133 }
140 134
141 return name; 135 return name;
142 } 136 }
143 137
144 base::string16 GetDisplayMessage(base::string16* additional_message_out) { 138 // Returns true if docked mode is currently enabled.
139 bool IsDockedModeEnabled() {
145 display::DisplayManager* display_manager = GetDisplayManager(); 140 display::DisplayManager* display_manager = GetDisplayManager();
146 if (display_manager->GetNumDisplays() > 1) { 141 if (!display::Display::HasInternalDisplay())
147 if (display::Display::HasInternalDisplay()) { 142 return false;
148 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, 143
149 GetExternalDisplayName()); 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;
150 } 148 }
149 }
150
151 // We have an internal display but it's not one of the active displays.
152 return true;
153 }
154
155 // Returns the notification message that should be shown to the user when the
156 // docked mode is entered.
157 base::string16 GetDockedModeEnabledMessage(
158 base::string16* out_additional_message) {
159 DCHECK(IsDockedModeEnabled());
160 DCHECK(out_additional_message);
161
162 *out_additional_message = ash::SubstituteChromeOSDeviceType(
163 IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED_DESCRIPTION);
164 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED);
165 }
166
167 // Returns the notification message that should be shown when mirror display
168 // mode is entered.
169 base::string16 GetEnterMirrorModeMessage() {
170 if (display::Display::HasInternalDisplay()) {
171 return l10n_util::GetStringFUTF16(
172 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING,
173 GetDisplayName(GetDisplayManager()->mirroring_display_id()));
174 }
175
176 return l10n_util::GetStringUTF16(
177 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL);
178 }
179
180 // Returns the notification message that should be shown when unified desktop
181 // mode is entered.
182 base::string16 GetEnterUnifiedModeMessage() {
183 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_UNIFIED);
184 }
185
186 // Returns the notification message that should be shown when unified desktop
187 // mode is exited.
188 base::string16 GetExitUnifiedModeMessage() {
189 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_UNIFIED_EXITING);
190 }
191
192 base::string16 GetDisplayRemovedMessage(
193 const display::ManagedDisplayInfo& removed_display_info,
194 base::string16* out_additional_message) {
195 return l10n_util::GetStringFUTF16(
196 IDS_ASH_STATUS_TRAY_DISPLAY_REMOVED,
197 base::UTF8ToUTF16(removed_display_info.name()));
198 }
199
200 base::string16 GetDisplayAddedMessage(int64_t added_display_id,
201 base::string16* additional_message_out) {
202 if (!display::Display::HasInternalDisplay()) {
151 return l10n_util::GetStringUTF16( 203 return l10n_util::GetStringUTF16(
152 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL); 204 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL);
153 } 205 }
154 206
155 if (display_manager->IsInMirrorMode()) { 207 return l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED,
156 if (display::Display::HasInternalDisplay()) { 208 GetExternalDisplayName(added_display_id));
157 return l10n_util::GetStringFUTF16(
158 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING,
159 GetDisplayName(display_manager->mirroring_display_id()));
160 }
161 return l10n_util::GetStringUTF16(
162 IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING_NO_INTERNAL);
163 }
164
165 if (display_manager->IsInUnifiedMode())
166 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_UNIFIED);
167
168 int64_t primary_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
169 if (display::Display::HasInternalDisplay() &&
170 !(display::Display::IsInternalDisplayId(primary_id))) {
171 if (additional_message_out) {
172 *additional_message_out = ash::SubstituteChromeOSDeviceType(
173 IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED_DESCRIPTION);
174 }
175 return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED);
176 }
177
178 return base::string16();
179 } 209 }
180 210
181 } // namespace 211 } // namespace
182 212
183 const char ScreenLayoutObserver::kNotificationId[] = 213 const char ScreenLayoutObserver::kNotificationId[] =
184 "chrome://settings/display"; 214 "chrome://settings/display";
185 215
186 ScreenLayoutObserver::ScreenLayoutObserver() { 216 ScreenLayoutObserver::ScreenLayoutObserver() {
187 WmShell::Get()->AddDisplayObserver(this); 217 WmShell::Get()->AddDisplayObserver(this);
188 UpdateDisplayInfo(NULL); 218 UpdateDisplayInfo(NULL);
(...skipping 11 matching lines...) Expand all
200 230
201 display::DisplayManager* display_manager = GetDisplayManager(); 231 display::DisplayManager* display_manager = GetDisplayManager();
202 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) { 232 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
203 int64_t id = display_manager->GetDisplayAt(i).id(); 233 int64_t id = display_manager->GetDisplayAt(i).id();
204 display_info_[id] = display_manager->GetDisplayInfo(id); 234 display_info_[id] = display_manager->GetDisplayInfo(id);
205 } 235 }
206 } 236 }
207 237
208 bool ScreenLayoutObserver::GetDisplayMessageForNotification( 238 bool ScreenLayoutObserver::GetDisplayMessageForNotification(
209 const ScreenLayoutObserver::DisplayInfoMap& old_info, 239 const ScreenLayoutObserver::DisplayInfoMap& old_info,
210 base::string16* message_out, 240 base::string16* out_message,
211 base::string16* additional_message_out) { 241 base::string16* out_additional_message) {
212 // Display is added or removed. Use the same message as the one in 242 if (old_display_mode_ != current_display_mode_) {
213 // the system tray. 243 // Detect changes in the mirror mode status.
214 if (display_info_.size() != old_info.size()) { 244 if (current_display_mode_ == DisplayMode::MIRRORING) {
215 *message_out = GetDisplayMessage(additional_message_out); 245 *out_message = GetEnterMirrorModeMessage();
216 return true; 246 return true;
217 } 247 }
218 248 if (old_display_mode_ == DisplayMode::MIRRORING &&
219 for (DisplayInfoMap::const_iterator iter = display_info_.begin(); 249 GetExitMirrorModeMessage(out_message, out_additional_message)) {
220 iter != display_info_.end(); ++iter) {
221 DisplayInfoMap::const_iterator old_iter = old_info.find(iter->first);
222 // The display's number is same but different displays. This happens
223 // for the transition between docked mode and mirrored display. Falls back
224 // to GetDisplayMessage().
225 if (old_iter == old_info.end()) {
226 *message_out = GetDisplayMessage(additional_message_out);
227 return true; 250 return true;
228 } 251 }
229 252
230 if (iter->second.configured_ui_scale() != 253 // Detect changes in the unified mode status.
231 old_iter->second.configured_ui_scale()) { 254 if (current_display_mode_ == DisplayMode::UNIFIED) {
232 *additional_message_out = l10n_util::GetStringFUTF16( 255 *out_message = GetEnterUnifiedModeMessage();
233 IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
234 GetDisplayName(iter->first), GetDisplaySize(iter->first));
235 return true; 256 return true;
236 } 257 }
237 if (iter->second.GetActiveRotation() != 258 if (old_display_mode_ == DisplayMode::UNIFIED) {
259 *out_message = GetExitUnifiedModeMessage();
260 return true;
261 }
262
263 if (current_display_mode_ == DisplayMode::DOCKED) {
264 *out_message = GetDockedModeEnabledMessage(out_additional_message);
265 return true;
266 }
267 if (old_display_mode_ == DisplayMode::DOCKED) {
268 *out_message =
269 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_DOCKED_EXITING);
270 return true;
271 }
272 }
273
274 // Displays are added or removed.
275 if (display_info_.size() < old_info.size()) {
276 // A display has been removed.
277 for (const auto& iter : old_info) {
278 if (display_info_.count(iter.first))
279 continue;
280
281 *out_message =
282 GetDisplayRemovedMessage(iter.second, out_additional_message);
283 return true;
284 }
285 } else if (display_info_.size() > old_info.size()) {
286 // A display has been added.
287 for (const auto& iter : display_info_) {
288 if (old_info.count(iter.first))
289 continue;
290
291 *out_message = GetDisplayAddedMessage(iter.first, out_additional_message);
292 return true;
293 }
294 }
295
296 for (const auto& iter : display_info_) {
297 DisplayInfoMap::const_iterator old_iter = old_info.find(iter.first);
298 if (old_iter == old_info.end()) {
299 // The display's number is same but different displays. This happens
300 // for the transition between docked mode and mirrored display.
301 // This condition can never be reached here, since it is handled above.
302 NOTREACHED() << "A display mode transition that should have been handled"
303 "earlier.";
304 return false;
305 }
306
307 if (iter.second.configured_ui_scale() !=
308 old_iter->second.configured_ui_scale()) {
309 *out_additional_message = l10n_util::GetStringFUTF16(
310 IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
311 GetDisplayName(iter.first), GetDisplaySize(iter.first));
312 return true;
313 }
314 if (iter.second.GetActiveRotation() !=
238 old_iter->second.GetActiveRotation()) { 315 old_iter->second.GetActiveRotation()) {
239 int rotation_text_id = 0; 316 int rotation_text_id = 0;
240 switch (iter->second.GetActiveRotation()) { 317 switch (iter.second.GetActiveRotation()) {
241 case display::Display::ROTATE_0: 318 case display::Display::ROTATE_0:
242 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION; 319 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION;
243 break; 320 break;
244 case display::Display::ROTATE_90: 321 case display::Display::ROTATE_90:
245 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90; 322 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90;
246 break; 323 break;
247 case display::Display::ROTATE_180: 324 case display::Display::ROTATE_180:
248 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180; 325 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180;
249 break; 326 break;
250 case display::Display::ROTATE_270: 327 case display::Display::ROTATE_270:
251 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270; 328 rotation_text_id = IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270;
252 break; 329 break;
253 } 330 }
254 *additional_message_out = l10n_util::GetStringFUTF16( 331 *out_additional_message = l10n_util::GetStringFUTF16(
255 IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetDisplayName(iter->first), 332 IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetDisplayName(iter.first),
256 l10n_util::GetStringUTF16(rotation_text_id)); 333 l10n_util::GetStringUTF16(rotation_text_id));
257 return true; 334 return true;
258 } 335 }
259 } 336 }
260 337
261 // Found nothing special 338 // Found nothing special
262 return false; 339 return false;
263 } 340 }
264 341
265 void ScreenLayoutObserver::CreateOrUpdateNotification( 342 void ScreenLayoutObserver::CreateOrUpdateNotification(
(...skipping 30 matching lines...) Expand all
296 WmShell::Get()->RecordUserMetricsAction( 373 WmShell::Get()->RecordUserMetricsAction(
297 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED); 374 UMA_STATUS_AREA_DISPLAY_NOTIFICATION_CREATED);
298 message_center::MessageCenter::Get()->AddNotification( 375 message_center::MessageCenter::Get()->AddNotification(
299 std::move(notification)); 376 std::move(notification));
300 } 377 }
301 378
302 void ScreenLayoutObserver::OnDisplayConfigurationChanged() { 379 void ScreenLayoutObserver::OnDisplayConfigurationChanged() {
303 DisplayInfoMap old_info; 380 DisplayInfoMap old_info;
304 UpdateDisplayInfo(&old_info); 381 UpdateDisplayInfo(&old_info);
305 382
383 old_display_mode_ = current_display_mode_;
384 if (GetDisplayManager()->IsInMirrorMode())
385 current_display_mode_ = DisplayMode::MIRRORING;
386 else if (GetDisplayManager()->IsInUnifiedMode())
387 current_display_mode_ = DisplayMode::UNIFIED;
388 else if (IsDockedModeEnabled())
389 current_display_mode_ = DisplayMode::DOCKED;
390 else if (GetDisplayManager()->GetNumDisplays() > 2)
391 current_display_mode_ = DisplayMode::EXTENDED_3_PLUS;
392 else if (GetDisplayManager()->GetNumDisplays() == 2)
393 current_display_mode_ = DisplayMode::EXTENDED_2;
394 else
395 current_display_mode_ = DisplayMode::SINGLE;
396
306 if (!show_notifications_for_testing) 397 if (!show_notifications_for_testing)
307 return; 398 return;
308 399
309 base::string16 message; 400 base::string16 message;
310 base::string16 additional_message; 401 base::string16 additional_message;
311 if (GetDisplayMessageForNotification(old_info, &message, &additional_message)) 402 if (GetDisplayMessageForNotification(old_info, &message, &additional_message))
312 CreateOrUpdateNotification(message, additional_message); 403 CreateOrUpdateNotification(message, additional_message);
313 } 404 }
314 405
406 bool ScreenLayoutObserver::GetExitMirrorModeMessage(
407 base::string16* out_message,
408 base::string16* out_additional_message) {
409 switch (current_display_mode_) {
410 case DisplayMode::DOCKED:
411 // Handle disabling mirror mode as a result of going to docked mode
412 // when we only have a single display (this means we actually have two
413 // physical displays, one of which is the internal display, but they
414 // were in mirror mode, and hence considered as one. Closing the
415 // internal display disables mirror mode and we still have a single
416 // active display).
417 *out_message = GetDockedModeEnabledMessage(out_additional_message);
418 return true;
419
420 case DisplayMode::EXTENDED_3_PLUS:
421 // Mirror mode was turned off due to having more than two displays.
422 // Show a message that mirror mode for 3+ displays is not supported.
423 *out_message =
424 l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_MIRRORING_NOT_SUPPORTED);
425 return true;
426
427 case DisplayMode::SINGLE:
428 // We're exiting mirror mode because we removed one of the two
429 // displays.
430 *out_message =
431 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT);
432 return true;
433
434 default:
435 // Mirror mode was turned off; other messages should be shown e.g.
436 // extended mode is on, ... etc.
437 return false;
438 }
439 }
440
315 } // namespace ash 441 } // namespace ash
OLDNEW
« no previous file with comments | « ash/system/chromeos/screen_layout_observer.h ('k') | ash/system/chromeos/screen_layout_observer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698