OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 "ash/system/chromeos/screen_layout_observer.h" | |
6 | |
7 #include "ash/common/system/chromeos/devicetype_utils.h" | |
8 #include "ash/common/system/tray/system_tray.h" | |
9 #include "ash/common/test/test_system_tray_delegate.h" | |
10 #include "ash/shell.h" | |
11 #include "ash/strings/grit/ash_strings.h" | |
12 #include "ash/test/ash_test_base.h" | |
13 #include "base/strings/string16.h" | |
14 #include "base/strings/string_util.h" | |
15 #include "base/strings/utf_string_conversions.h" | |
16 #include "ui/accessibility/ax_node_data.h" | |
17 #include "ui/base/l10n/l10n_util.h" | |
18 #include "ui/display/display.h" | |
19 #include "ui/display/display_layout_builder.h" | |
20 #include "ui/display/manager/display_manager.h" | |
21 #include "ui/message_center/message_center.h" | |
22 #include "ui/message_center/notification.h" | |
23 #include "ui/message_center/notification_list.h" | |
24 #include "ui/views/controls/label.h" | |
25 | |
26 namespace ash { | |
27 | |
28 class ScreenLayoutObserverTest : public test::AshTestBase { | |
29 public: | |
30 ScreenLayoutObserverTest(); | |
31 ~ScreenLayoutObserverTest() override; | |
32 | |
33 protected: | |
34 ScreenLayoutObserver* GetScreenLayoutObserver(); | |
35 void CheckUpdate(); | |
36 | |
37 void CloseNotification(); | |
38 base::string16 GetDisplayNotificationText() const; | |
39 base::string16 GetDisplayNotificationAdditionalText() const; | |
40 | |
41 base::string16 GetFirstDisplayName(); | |
42 | |
43 base::string16 GetSecondDisplayName(); | |
44 | |
45 base::string16 GetMirroringDisplayName(); | |
46 | |
47 private: | |
48 const message_center::Notification* GetDisplayNotification() const; | |
49 | |
50 DISALLOW_COPY_AND_ASSIGN(ScreenLayoutObserverTest); | |
51 }; | |
52 | |
53 ScreenLayoutObserverTest::ScreenLayoutObserverTest() {} | |
54 | |
55 ScreenLayoutObserverTest::~ScreenLayoutObserverTest() {} | |
56 | |
57 ScreenLayoutObserver* ScreenLayoutObserverTest::GetScreenLayoutObserver() { | |
58 return Shell::GetInstance()->screen_layout_observer(); | |
59 } | |
60 | |
61 void ScreenLayoutObserverTest::CloseNotification() { | |
62 message_center::MessageCenter::Get()->RemoveNotification( | |
63 ScreenLayoutObserver::kNotificationId, false); | |
64 RunAllPendingInMessageLoop(); | |
65 } | |
66 | |
67 base::string16 ScreenLayoutObserverTest::GetDisplayNotificationText() const { | |
68 const message_center::Notification* notification = GetDisplayNotification(); | |
69 return notification ? notification->title() : base::string16(); | |
70 } | |
71 | |
72 base::string16 ScreenLayoutObserverTest::GetDisplayNotificationAdditionalText() | |
73 const { | |
74 const message_center::Notification* notification = GetDisplayNotification(); | |
75 return notification ? notification->message() : base::string16(); | |
76 } | |
77 | |
78 base::string16 ScreenLayoutObserverTest::GetFirstDisplayName() { | |
79 return base::UTF8ToUTF16(display_manager()->GetDisplayNameForId( | |
80 display_manager()->first_display_id())); | |
81 } | |
82 | |
83 base::string16 ScreenLayoutObserverTest::GetSecondDisplayName() { | |
84 return base::UTF8ToUTF16(display_manager()->GetDisplayNameForId( | |
85 display_manager()->GetSecondaryDisplay().id())); | |
86 } | |
87 | |
88 base::string16 ScreenLayoutObserverTest::GetMirroringDisplayName() { | |
89 return base::UTF8ToUTF16(display_manager()->GetDisplayNameForId( | |
90 display_manager()->mirroring_display_id())); | |
91 } | |
92 | |
93 const message_center::Notification* | |
94 ScreenLayoutObserverTest::GetDisplayNotification() const { | |
95 const message_center::NotificationList::Notifications notifications = | |
96 message_center::MessageCenter::Get()->GetVisibleNotifications(); | |
97 for (const auto* notification : notifications) { | |
98 if (notification->id() == ScreenLayoutObserver::kNotificationId) | |
99 return notification; | |
100 } | |
101 | |
102 return nullptr; | |
103 } | |
104 | |
105 TEST_F(ScreenLayoutObserverTest, DisplayNotifications) { | |
106 Shell::GetInstance() | |
107 ->screen_layout_observer() | |
108 ->set_show_notifications_for_testing(true); | |
109 | |
110 UpdateDisplay("400x400"); | |
111 display::Display::SetInternalDisplayId(display_manager()->first_display_id()); | |
112 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
113 | |
114 // rotation. | |
115 UpdateDisplay("400x400/r"); | |
116 EXPECT_EQ(l10n_util::GetStringFUTF16( | |
117 IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName(), | |
118 l10n_util::GetStringUTF16( | |
119 IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)), | |
120 GetDisplayNotificationAdditionalText()); | |
121 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
122 | |
123 CloseNotification(); | |
124 UpdateDisplay("400x400"); | |
125 EXPECT_EQ(l10n_util::GetStringFUTF16( | |
126 IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetFirstDisplayName(), | |
127 l10n_util::GetStringUTF16( | |
128 IDS_ASH_STATUS_TRAY_DISPLAY_STANDARD_ORIENTATION)), | |
129 GetDisplayNotificationAdditionalText()); | |
130 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
131 | |
132 // UI-scale | |
133 CloseNotification(); | |
134 UpdateDisplay("400x400@1.5"); | |
135 EXPECT_EQ(l10n_util::GetStringFUTF16( | |
136 IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, | |
137 GetFirstDisplayName(), base::UTF8ToUTF16("600x600")), | |
138 GetDisplayNotificationAdditionalText()); | |
139 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
140 | |
141 // UI-scale to 1.0 | |
142 CloseNotification(); | |
143 UpdateDisplay("400x400"); | |
144 EXPECT_EQ(l10n_util::GetStringFUTF16( | |
145 IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, | |
146 GetFirstDisplayName(), base::UTF8ToUTF16("400x400")), | |
147 GetDisplayNotificationAdditionalText()); | |
148 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
149 | |
150 // No-update | |
151 CloseNotification(); | |
152 UpdateDisplay("400x400"); | |
153 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
154 EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); | |
155 | |
156 // Extended. | |
157 CloseNotification(); | |
158 UpdateDisplay("400x400,200x200"); | |
159 EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, | |
160 GetSecondDisplayName()), | |
161 GetDisplayNotificationText()); | |
162 EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); | |
163 | |
164 // Mirroring. | |
165 CloseNotification(); | |
166 display_manager()->SetSoftwareMirroring(true); | |
167 UpdateDisplay("400x400,200x200"); | |
168 EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, | |
169 GetMirroringDisplayName()), | |
170 GetDisplayNotificationText()); | |
171 EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); | |
172 | |
173 // Back to extended. | |
174 CloseNotification(); | |
175 display_manager()->SetSoftwareMirroring(false); | |
176 UpdateDisplay("400x400,200x200"); | |
177 EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED, | |
178 GetSecondDisplayName()), | |
179 GetDisplayNotificationText()); | |
180 EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); | |
181 | |
182 // Resize the first display. | |
183 UpdateDisplay("400x400@1.5,200x200"); | |
184 EXPECT_EQ(l10n_util::GetStringFUTF16( | |
185 IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED, | |
186 GetFirstDisplayName(), base::UTF8ToUTF16("600x600")), | |
187 GetDisplayNotificationAdditionalText()); | |
188 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
189 | |
190 // Rotate the second. | |
191 UpdateDisplay("400x400@1.5,200x200/r"); | |
192 EXPECT_EQ(l10n_util::GetStringFUTF16( | |
193 IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetSecondDisplayName(), | |
194 l10n_util::GetStringUTF16( | |
195 IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)), | |
196 GetDisplayNotificationAdditionalText()); | |
197 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
198 | |
199 // Enters closed lid mode. | |
200 UpdateDisplay("400x400@1.5,200x200"); | |
201 display::Display::SetInternalDisplayId( | |
202 display_manager()->GetSecondaryDisplay().id()); | |
203 UpdateDisplay("400x400@1.5"); | |
204 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
205 } | |
206 | |
207 // Verify that notification shows up when display is switched from dock mode to | |
208 // extend mode. | |
209 TEST_F(ScreenLayoutObserverTest, DisplayConfigurationChangedTwice) { | |
210 Shell::GetInstance() | |
211 ->screen_layout_observer() | |
212 ->set_show_notifications_for_testing(true); | |
213 UpdateDisplay("400x400,200x200"); | |
214 EXPECT_EQ(l10n_util::GetStringUTF16( | |
215 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL), | |
216 GetDisplayNotificationText()); | |
217 | |
218 // OnDisplayConfigurationChanged() may be called more than once for a single | |
219 // update display in case of primary is swapped or recovered from dock mode. | |
220 // Should not remove the notification in such case. | |
221 GetScreenLayoutObserver()->OnDisplayConfigurationChanged(); | |
222 EXPECT_EQ(l10n_util::GetStringUTF16( | |
223 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL), | |
224 GetDisplayNotificationText()); | |
225 | |
226 // Back to the single display. It should show that a display was removed. | |
227 UpdateDisplay("400x400"); | |
228 EXPECT_TRUE(base::StartsWith( | |
229 GetDisplayNotificationText(), | |
230 l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_REMOVED, | |
231 base::UTF8ToUTF16("")), | |
232 base::CompareCase::SENSITIVE)); | |
233 } | |
234 | |
235 // Verify the notification message content when one of the 2 displays that | |
236 // connected to the device is rotated. | |
237 TEST_F(ScreenLayoutObserverTest, UpdateAfterSuppressDisplayNotification) { | |
238 UpdateDisplay("400x400,200x200"); | |
239 | |
240 Shell::GetInstance() | |
241 ->screen_layout_observer() | |
242 ->set_show_notifications_for_testing(true); | |
243 | |
244 // Rotate the second. | |
245 UpdateDisplay("400x400,200x200/r"); | |
246 EXPECT_EQ(l10n_util::GetStringFUTF16( | |
247 IDS_ASH_STATUS_TRAY_DISPLAY_ROTATED, GetSecondDisplayName(), | |
248 l10n_util::GetStringUTF16( | |
249 IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90)), | |
250 GetDisplayNotificationAdditionalText()); | |
251 } | |
252 | |
253 // Verify that no notification is shown when overscan of a screen is changed. | |
254 TEST_F(ScreenLayoutObserverTest, OverscanDisplay) { | |
255 UpdateDisplay("400x400, 300x300"); | |
256 Shell::GetInstance() | |
257 ->screen_layout_observer() | |
258 ->set_show_notifications_for_testing(true); | |
259 display::Display::SetInternalDisplayId(display_manager()->first_display_id()); | |
260 | |
261 // /o creates the default overscan. | |
262 UpdateDisplay("400x400, 300x300/o"); | |
263 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
264 EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); | |
265 | |
266 // Reset the overscan. | |
267 Shell::GetInstance()->display_manager()->SetOverscanInsets( | |
268 display_manager()->GetSecondaryDisplay().id(), gfx::Insets()); | |
269 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
270 EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); | |
271 } | |
272 | |
273 // Tests that exiting mirror mode by closing the lid shows the correct "exiting | |
274 // mirror mode" message. | |
275 TEST_F(ScreenLayoutObserverTest, ExitMirrorModeBecauseOfDockedModeMessage) { | |
276 Shell::GetInstance() | |
277 ->screen_layout_observer() | |
278 ->set_show_notifications_for_testing(true); | |
279 UpdateDisplay("400x400,200x200"); | |
280 display::Display::SetInternalDisplayId( | |
281 display_manager()->GetSecondaryDisplay().id()); | |
282 | |
283 // Mirroring. | |
284 display_manager()->SetSoftwareMirroring(true); | |
285 UpdateDisplay("400x400,200x200"); | |
286 EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, | |
287 GetMirroringDisplayName()), | |
288 GetDisplayNotificationText()); | |
289 | |
290 // Docked. | |
291 CloseNotification(); | |
292 display_manager()->SetSoftwareMirroring(false); | |
293 display::Display::SetInternalDisplayId(display_manager()->first_display_id()); | |
294 UpdateDisplay("200x200"); | |
295 EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT), | |
296 GetDisplayNotificationText()); | |
297 } | |
298 | |
299 // Tests that exiting mirror mode because of adding a third display shows the | |
300 // correct "3+ displays mirror mode is not supported" message. | |
301 TEST_F(ScreenLayoutObserverTest, ExitMirrorModeBecauseOfThirdDisplayMessage) { | |
302 Shell::GetInstance() | |
303 ->screen_layout_observer() | |
304 ->set_show_notifications_for_testing(true); | |
305 UpdateDisplay("400x400,200x200"); | |
306 display::Display::SetInternalDisplayId( | |
307 display_manager()->GetSecondaryDisplay().id()); | |
308 | |
309 // Mirroring. | |
310 display_manager()->SetSoftwareMirroring(true); | |
311 UpdateDisplay("400x400,200x200"); | |
312 EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, | |
313 GetMirroringDisplayName()), | |
314 GetDisplayNotificationText()); | |
315 | |
316 // Adding a third display. Mirror mode for 3+ displays is not supported. | |
317 CloseNotification(); | |
318 display_manager()->SetSoftwareMirroring(false); | |
319 UpdateDisplay("400x400,200x200,100x100"); | |
320 EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_MIRRORING_NOT_SUPPORTED), | |
321 GetDisplayNotificationText()); | |
322 } | |
323 | |
324 // Special case: tests that exiting mirror mode by removing a display shows the | |
325 // correct message. | |
326 TEST_F(ScreenLayoutObserverTest, | |
327 ExitMirrorModeNoInternalDisplayBecauseOfDisplayRemovedMessage) { | |
328 Shell::GetInstance() | |
329 ->screen_layout_observer() | |
330 ->set_show_notifications_for_testing(true); | |
331 UpdateDisplay("400x400,200x200"); | |
332 display::Display::SetInternalDisplayId( | |
333 display_manager()->GetSecondaryDisplay().id()); | |
334 | |
335 // Mirroring. | |
336 display_manager()->SetSoftwareMirroring(true); | |
337 UpdateDisplay("400x400,200x200"); | |
338 EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRRORING, | |
339 GetMirroringDisplayName()), | |
340 GetDisplayNotificationText()); | |
341 | |
342 // Removing one of the displays. We show that we exited mirror mode. | |
343 CloseNotification(); | |
344 display_manager()->SetSoftwareMirroring(false); | |
345 UpdateDisplay("400x400"); | |
346 EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_MIRROR_EXIT), | |
347 GetDisplayNotificationText()); | |
348 } | |
349 | |
350 // Tests notification messages shown when adding and removing displays in | |
351 // extended mode. | |
352 TEST_F(ScreenLayoutObserverTest, AddingRemovingDisplayExtendedModeMessage) { | |
353 Shell::GetInstance() | |
354 ->screen_layout_observer() | |
355 ->set_show_notifications_for_testing(true); | |
356 UpdateDisplay("400x400"); | |
357 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
358 | |
359 // Adding a display in extended mode. | |
360 UpdateDisplay("400x400,200x200"); | |
361 EXPECT_EQ(l10n_util::GetStringUTF16( | |
362 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL), | |
363 GetDisplayNotificationText()); | |
364 | |
365 // Removing a display. | |
366 CloseNotification(); | |
367 UpdateDisplay("400x400"); | |
368 EXPECT_TRUE(base::StartsWith( | |
369 GetDisplayNotificationText(), | |
370 l10n_util::GetStringFUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_REMOVED, | |
371 base::UTF8ToUTF16("")), | |
372 base::CompareCase::SENSITIVE)); | |
373 } | |
374 | |
375 // Tests notification messages shown when entering and exiting unified desktop | |
376 // mode. | |
377 TEST_F(ScreenLayoutObserverTest, EnteringExitingUnifiedModeMessage) { | |
378 Shell::GetInstance() | |
379 ->screen_layout_observer() | |
380 ->set_show_notifications_for_testing(true); | |
381 UpdateDisplay("400x400"); | |
382 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
383 | |
384 // Adding a display in extended mode. | |
385 UpdateDisplay("400x400,200x200"); | |
386 EXPECT_EQ(l10n_util::GetStringUTF16( | |
387 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL), | |
388 GetDisplayNotificationText()); | |
389 | |
390 // Enter unified mode. | |
391 display_manager()->SetUnifiedDesktopEnabled(true); | |
392 EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_UNIFIED), | |
393 GetDisplayNotificationText()); | |
394 | |
395 // Exit unified mode. | |
396 display_manager()->SetUnifiedDesktopEnabled(false); | |
397 EXPECT_EQ( | |
398 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_UNIFIED_EXITING), | |
399 GetDisplayNotificationText()); | |
400 | |
401 // Enter unified mode again and exit via closing the lid. The message "Exiting | |
402 // unified mode" should be shown. | |
403 display_manager()->SetUnifiedDesktopEnabled(true); | |
404 EXPECT_EQ(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_UNIFIED), | |
405 GetDisplayNotificationText()); | |
406 | |
407 // Close the lid. | |
408 display::Display::SetInternalDisplayId(display_manager()->first_display_id()); | |
409 UpdateDisplay("200x200"); | |
410 display_manager()->SetUnifiedDesktopEnabled(false); | |
411 EXPECT_EQ( | |
412 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISPLAY_UNIFIED_EXITING), | |
413 GetDisplayNotificationText()); | |
414 } | |
415 | |
416 // Special case: Tests notification messages shown when entering docked mode | |
417 // by closing the lid and the internal display is the secondary display. | |
418 TEST_F(ScreenLayoutObserverTest, DockedModeWithExternalPrimaryDisplayMessage) { | |
419 Shell::GetInstance() | |
420 ->screen_layout_observer() | |
421 ->set_show_notifications_for_testing(true); | |
422 UpdateDisplay("400x400,200x200"); | |
423 EXPECT_EQ(l10n_util::GetStringUTF16( | |
424 IDS_ASH_STATUS_TRAY_DISPLAY_EXTENDED_NO_INTERNAL), | |
425 GetDisplayNotificationText()); | |
426 CloseNotification(); | |
427 | |
428 const int64_t primary_id = display_manager()->GetDisplayAt(0).id(); | |
429 const int64_t internal_secondary_id = display_manager()->GetDisplayAt(1).id(); | |
430 display::Display::SetInternalDisplayId(internal_secondary_id); | |
431 display::DisplayLayoutBuilder builder(primary_id); | |
432 builder.AddDisplayPlacement(internal_secondary_id, primary_id, | |
433 display::DisplayPlacement::LEFT, 0); | |
434 display_manager()->SetLayoutForCurrentDisplays(builder.Build()); | |
435 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
436 | |
437 // Close the lid. We go to docked mode, but we show no notifications. | |
438 UpdateDisplay("400x400"); | |
439 EXPECT_TRUE(GetDisplayNotificationText().empty()); | |
440 EXPECT_TRUE(GetDisplayNotificationAdditionalText().empty()); | |
441 } | |
442 | |
443 } // namespace ash | |
OLD | NEW |