1// Copyright 2014 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 "extensions/browser/api/system_display/display_info_provider.h"
6
7#include "ash/display/display_controller.h"
8#include "ash/display/display_manager.h"
9#include "ash/screen_util.h"
10#include "ash/shell.h"
11#include "ash/test/ash_test_base.h"
12#include "ash/test/display_manager_test_api.h"
13#include "base/strings/string_number_conversions.h"
14#include "base/strings/stringprintf.h"
15#include "extensions/common/api/system_display.h"
16#include "ui/gfx/display.h"
17#include "ui/gfx/rect.h"
18
19namespace extensions {
20namespace {
21
22class DisplayInfoProviderChromeosTest : public ash::test::AshTestBase {
23 public:
24  DisplayInfoProviderChromeosTest() {}
25
26  virtual ~DisplayInfoProviderChromeosTest() {}
27
28 protected:
29  void CallSetDisplayUnitInfo(
30      const std::string& display_id,
31      const core_api::system_display::DisplayProperties& info,
32      bool* success,
33      std::string* error) {
34    // Reset error messsage.
35    (*error).clear();
36    *success = DisplayInfoProvider::Get()->SetInfo(display_id, info, error);
37  }
38
39  bool DisplayExists(int64 display_id) const {
40    const gfx::Display& display =
41        GetDisplayManager()->GetDisplayForId(display_id);
42    return display.id() != gfx::Display::kInvalidDisplayID;
43  }
44
45  ash::DisplayManager* GetDisplayManager() const {
46    return ash::Shell::GetInstance()->display_manager();
47  }
48
49  ash::DisplayController* GetDisplayController() const {
50    return ash::Shell::GetInstance()->display_controller();
51  }
52
53  std::string SystemInfoDisplayInsetsToString(
54      const core_api::system_display::Insets& insets) const {
55    // Order to match gfx::Insets::ToString().
56    return base::StringPrintf(
57        "%d,%d,%d,%d", insets.top, insets.left, insets.bottom, insets.right);
58  }
59
60  std::string SystemInfoDisplayBoundsToString(
61      const core_api::system_display::Bounds& bounds) const {
62    // Order to match gfx::Rect::ToString().
63    return base::StringPrintf(
64        "%d,%d %dx%d", bounds.left, bounds.top, bounds.width, bounds.height);
65  }
66
67 private:
68  DISALLOW_COPY_AND_ASSIGN(DisplayInfoProviderChromeosTest);
69};
70
71TEST_F(DisplayInfoProviderChromeosTest, GetBasic) {
72  UpdateDisplay("500x600,400x520");
73  DisplayInfo result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
74
75  ASSERT_EQ(2u, result.size());
76
77  int64 display_id;
78  ASSERT_TRUE(base::StringToInt64(result[0]->id, &display_id))
79      << "Display id must be convertable to integer: " << result[0]->id;
80
81  ASSERT_TRUE(DisplayExists(display_id)) << display_id << " not found";
82  EXPECT_EQ("0,0 500x600", SystemInfoDisplayBoundsToString(result[0]->bounds));
83  EXPECT_EQ("0,0,0,0", SystemInfoDisplayInsetsToString(result[0]->overscan));
84  EXPECT_EQ(0, result[0]->rotation);
85  EXPECT_TRUE(result[0]->is_primary);
86  EXPECT_EQ(96, result[0]->dpi_x);
87  EXPECT_EQ(96, result[0]->dpi_y);
88  EXPECT_TRUE(result[0]->mirroring_source_id.empty());
89  EXPECT_TRUE(result[0]->is_enabled);
90
91  ASSERT_TRUE(base::StringToInt64(result[1]->id, &display_id))
92      << "Display id must be convertable to integer: " << result[0]->id;
93
94  ASSERT_TRUE(DisplayExists(display_id)) << display_id << " not found";
95  EXPECT_EQ(GetDisplayManager()->GetDisplayNameForId(display_id),
96            result[1]->name);
97  // The second display is positioned left of the primary display, whose width
98  // is 500.
99  EXPECT_EQ("500,0 400x520",
100            SystemInfoDisplayBoundsToString(result[1]->bounds));
101  EXPECT_EQ("0,0,0,0", SystemInfoDisplayInsetsToString(result[1]->overscan));
102  EXPECT_EQ(0, result[1]->rotation);
103  EXPECT_FALSE(result[1]->is_primary);
104  EXPECT_EQ(96, result[1]->dpi_x);
105  EXPECT_EQ(96, result[1]->dpi_y);
106  EXPECT_TRUE(result[1]->mirroring_source_id.empty());
107  EXPECT_TRUE(result[1]->is_enabled);
108}
109
110TEST_F(DisplayInfoProviderChromeosTest, GetRotation) {
111  UpdateDisplay("500x600/r");
112  DisplayInfo result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
113
114  ASSERT_EQ(1u, result.size());
115
116  int64 display_id;
117  ASSERT_TRUE(base::StringToInt64(result[0]->id, &display_id))
118      << "Display id must be convertable to integer: " << result[0]->id;
119
120  ASSERT_TRUE(DisplayExists(display_id)) << display_id << " not found";
121  EXPECT_EQ("0,0 600x500", SystemInfoDisplayBoundsToString(result[0]->bounds));
122  EXPECT_EQ(90, result[0]->rotation);
123
124  GetDisplayManager()->SetDisplayRotation(display_id, gfx::Display::ROTATE_270);
125
126  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
127
128  ASSERT_EQ(1u, result.size());
129
130  EXPECT_EQ(base::Int64ToString(display_id), result[0]->id);
131  EXPECT_EQ("0,0 600x500", SystemInfoDisplayBoundsToString(result[0]->bounds));
132  EXPECT_EQ(270, result[0]->rotation);
133
134  GetDisplayManager()->SetDisplayRotation(display_id, gfx::Display::ROTATE_180);
135
136  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
137
138  ASSERT_EQ(1u, result.size());
139
140  EXPECT_EQ(base::Int64ToString(display_id), result[0]->id);
141  EXPECT_EQ("0,0 500x600", SystemInfoDisplayBoundsToString(result[0]->bounds));
142  EXPECT_EQ(180, result[0]->rotation);
143
144  GetDisplayManager()->SetDisplayRotation(display_id, gfx::Display::ROTATE_0);
145
146  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
147
148  ASSERT_EQ(1u, result.size());
149
150  EXPECT_EQ(base::Int64ToString(display_id), result[0]->id);
151  EXPECT_EQ("0,0 500x600", SystemInfoDisplayBoundsToString(result[0]->bounds));
152  EXPECT_EQ(0, result[0]->rotation);
153}
154
155TEST_F(DisplayInfoProviderChromeosTest, GetHiDPI) {
156  UpdateDisplay("500x600,400x520*2");
157  DisplayInfo result;
158  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
159
160  ASSERT_EQ(2u, result.size());
161
162  EXPECT_EQ("0,0 500x600", SystemInfoDisplayBoundsToString(result[0]->bounds));
163  EXPECT_EQ(96, result[0]->dpi_x);
164  EXPECT_EQ(96, result[0]->dpi_y);
165
166  EXPECT_EQ("500,0 200x260",
167            SystemInfoDisplayBoundsToString(result[1]->bounds));
168  EXPECT_EQ(2 * 96, result[1]->dpi_x);
169  EXPECT_EQ(2 * 96, result[1]->dpi_y);
170
171  GetDisplayController()->SwapPrimaryDisplay();
172
173  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
174
175  ASSERT_EQ(2u, result.size());
176
177  EXPECT_EQ("-500,0 500x600",
178            SystemInfoDisplayBoundsToString(result[0]->bounds));
179  EXPECT_EQ(96, result[0]->dpi_x);
180  EXPECT_EQ(96, result[0]->dpi_y);
181
182  EXPECT_EQ("0,0 200x260", SystemInfoDisplayBoundsToString(result[1]->bounds));
183  EXPECT_EQ(2 * 96, result[1]->dpi_x);
184  EXPECT_EQ(2 * 96, result[1]->dpi_y);
185}
186
187TEST_F(DisplayInfoProviderChromeosTest, GetVisibleArea) {
188  UpdateDisplay("640x720*2/o, 400x520/o");
189  DisplayInfo result;
190  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
191
192  ASSERT_EQ(2u, result.size());
193
194  int64 display_id;
195  ASSERT_TRUE(base::StringToInt64(result[1]->id, &display_id))
196      << "Display id must be convertable to integer: " << result[1]->id;
197  ASSERT_TRUE(DisplayExists(display_id)) << display_id << " not found";
198
199  // Default overscan is 5%.
200  EXPECT_EQ("304,0 380x494",
201            SystemInfoDisplayBoundsToString(result[1]->bounds));
202  EXPECT_EQ("13,10,13,10",
203            SystemInfoDisplayInsetsToString(result[1]->overscan));
204
205  GetDisplayManager()->SetOverscanInsets(display_id,
206                                         gfx::Insets(20, 30, 50, 60));
207  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
208
209  ASSERT_EQ(2u, result.size());
210
211  EXPECT_EQ(base::Int64ToString(display_id), result[1]->id);
212  EXPECT_EQ("304,0 310x450",
213            SystemInfoDisplayBoundsToString(result[1]->bounds));
214  EXPECT_EQ("20,30,50,60",
215            SystemInfoDisplayInsetsToString(result[1]->overscan));
216
217  // Set insets for the primary screen. Note that it has 2x scale.
218  ASSERT_TRUE(base::StringToInt64(result[0]->id, &display_id))
219      << "Display id must be convertable to integer: " << result[0]->id;
220  ASSERT_TRUE(DisplayExists(display_id)) << display_id << " not found";
221
222  EXPECT_EQ("0,0 304x342", SystemInfoDisplayBoundsToString(result[0]->bounds));
223  EXPECT_EQ("9,8,9,8", SystemInfoDisplayInsetsToString(result[0]->overscan));
224
225  GetDisplayManager()->SetOverscanInsets(display_id,
226                                         gfx::Insets(10, 20, 30, 40));
227  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
228
229  ASSERT_EQ(2u, result.size());
230
231  EXPECT_EQ(base::Int64ToString(display_id), result[0]->id);
232  EXPECT_EQ("0,0 260x320", SystemInfoDisplayBoundsToString(result[0]->bounds));
233  EXPECT_EQ("10,20,30,40",
234            SystemInfoDisplayInsetsToString(result[0]->overscan));
235}
236
237TEST_F(DisplayInfoProviderChromeosTest, GetMirroring) {
238  UpdateDisplay("600x600, 400x520/o");
239  DisplayInfo result;
240  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
241
242  ASSERT_EQ(2u, result.size());
243
244  int64 display_id_primary;
245  ASSERT_TRUE(base::StringToInt64(result[0]->id, &display_id_primary))
246      << "Display id must be convertable to integer: " << result[0]->id;
247  ASSERT_TRUE(DisplayExists(display_id_primary)) << display_id_primary
248                                                 << " not found";
249
250  int64 display_id_secondary;
251  ASSERT_TRUE(base::StringToInt64(result[1]->id, &display_id_secondary))
252      << "Display id must be convertable to integer: " << result[1]->id;
253  ASSERT_TRUE(DisplayExists(display_id_secondary)) << display_id_secondary
254                                                   << " not found";
255
256  ASSERT_FALSE(GetDisplayManager()->IsMirrored());
257  EXPECT_TRUE(result[0]->mirroring_source_id.empty());
258  EXPECT_TRUE(result[1]->mirroring_source_id.empty());
259
260  GetDisplayManager()->SetMirrorMode(true);
261  ASSERT_TRUE(GetDisplayManager()->IsMirrored());
262
263  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
264
265  ASSERT_EQ(1u, result.size());
266  EXPECT_EQ(base::Int64ToString(display_id_primary), result[0]->id);
267  EXPECT_EQ(base::Int64ToString(display_id_secondary),
268            result[0]->mirroring_source_id);
269
270  GetDisplayManager()->SetMirrorMode(false);
271  ASSERT_FALSE(GetDisplayManager()->IsMirrored());
272
273  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
274
275  ASSERT_EQ(2u, result.size());
276  EXPECT_EQ(base::Int64ToString(display_id_primary), result[0]->id);
277  EXPECT_TRUE(result[0]->mirroring_source_id.empty());
278  EXPECT_EQ(base::Int64ToString(display_id_secondary), result[1]->id);
279  EXPECT_TRUE(result[1]->mirroring_source_id.empty());
280}
281
282TEST_F(DisplayInfoProviderChromeosTest, GetBounds) {
283  UpdateDisplay("600x600, 400x520");
284  GetDisplayManager()->SetLayoutForCurrentDisplays(
285      ash::DisplayLayout::FromInts(ash::DisplayLayout::LEFT, -40));
286
287  DisplayInfo result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
288
289  ASSERT_EQ(2u, result.size());
290  EXPECT_EQ("0,0 600x600", SystemInfoDisplayBoundsToString(result[0]->bounds));
291  EXPECT_EQ("-400,-40 400x520",
292            SystemInfoDisplayBoundsToString(result[1]->bounds));
293
294  GetDisplayManager()->SetLayoutForCurrentDisplays(
295      ash::DisplayLayout::FromInts(ash::DisplayLayout::TOP, 40));
296
297  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
298
299  ASSERT_EQ(2u, result.size());
300  EXPECT_EQ("0,0 600x600", SystemInfoDisplayBoundsToString(result[0]->bounds));
301  EXPECT_EQ("40,-520 400x520",
302            SystemInfoDisplayBoundsToString(result[1]->bounds));
303
304  GetDisplayManager()->SetLayoutForCurrentDisplays(
305      ash::DisplayLayout::FromInts(ash::DisplayLayout::BOTTOM, 80));
306
307  result = DisplayInfoProvider::Get()->GetAllDisplaysInfo();
308  ASSERT_EQ(2u, result.size());
309  EXPECT_EQ("0,0 600x600", SystemInfoDisplayBoundsToString(result[0]->bounds));
310  EXPECT_EQ("80,600 400x520",
311            SystemInfoDisplayBoundsToString(result[1]->bounds));
312}
313
314TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginLeftExact) {
315  UpdateDisplay("1200x600,520x400");
316
317  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
318  core_api::system_display::DisplayProperties info;
319  info.bounds_origin_x.reset(new int(-520));
320  info.bounds_origin_y.reset(new int(50));
321
322  bool success = false;
323  std::string error;
324  CallSetDisplayUnitInfo(
325      base::Int64ToString(secondary.id()), info, &success, &error);
326
327  ASSERT_TRUE(success);
328  ASSERT_TRUE(error.empty());
329
330  EXPECT_EQ("-520,50 520x400", secondary.bounds().ToString());
331}
332
333TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginRightExact) {
334  UpdateDisplay("1200x600,520x400");
335
336  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
337  core_api::system_display::DisplayProperties info;
338  info.bounds_origin_x.reset(new int(1200));
339  info.bounds_origin_y.reset(new int(100));
340
341  bool success = false;
342  std::string error;
343  CallSetDisplayUnitInfo(
344      base::Int64ToString(secondary.id()), info, &success, &error);
345
346  ASSERT_TRUE(success);
347  ASSERT_TRUE(error.empty());
348
349  EXPECT_EQ("1200,100 520x400", secondary.bounds().ToString());
350}
351
352TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginTopExact) {
353  UpdateDisplay("1200x600,520x400");
354
355  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
356  core_api::system_display::DisplayProperties info;
357  info.bounds_origin_x.reset(new int(1100));
358  info.bounds_origin_y.reset(new int(-400));
359
360  bool success = false;
361  std::string error;
362  CallSetDisplayUnitInfo(
363      base::Int64ToString(secondary.id()), info, &success, &error);
364
365  ASSERT_TRUE(success);
366  ASSERT_TRUE(error.empty());
367
368  EXPECT_EQ("1100,-400 520x400", secondary.bounds().ToString());
369}
370
371TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginBottomExact) {
372  UpdateDisplay("1200x600,520x400");
373
374  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
375  core_api::system_display::DisplayProperties info;
376  info.bounds_origin_x.reset(new int(-350));
377  info.bounds_origin_y.reset(new int(600));
378
379  bool success = false;
380  std::string error;
381  CallSetDisplayUnitInfo(
382      base::Int64ToString(secondary.id()), info, &success, &error);
383
384  ASSERT_TRUE(success);
385  ASSERT_TRUE(error.empty());
386
387  EXPECT_EQ("-350,600 520x400", secondary.bounds().ToString());
388}
389
390TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginSameCenter) {
391  UpdateDisplay("1200x600,520x400");
392
393  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
394  core_api::system_display::DisplayProperties info;
395  info.bounds_origin_x.reset(new int(340));
396  info.bounds_origin_y.reset(new int(100));
397
398  bool success = false;
399  std::string error;
400  CallSetDisplayUnitInfo(
401      base::Int64ToString(secondary.id()), info, &success, &error);
402
403  ASSERT_TRUE(success);
404  ASSERT_TRUE(error.empty());
405
406  EXPECT_EQ("1200,100 520x400", secondary.bounds().ToString());
407}
408
409TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginLeftOutside) {
410  UpdateDisplay("1200x600,520x400");
411
412  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
413  core_api::system_display::DisplayProperties info;
414  info.bounds_origin_x.reset(new int(-1040));
415  info.bounds_origin_y.reset(new int(100));
416
417  bool success = false;
418  std::string error;
419  CallSetDisplayUnitInfo(
420      base::Int64ToString(secondary.id()), info, &success, &error);
421
422  ASSERT_TRUE(success);
423  ASSERT_TRUE(error.empty());
424
425  EXPECT_EQ("-520,100 520x400", secondary.bounds().ToString());
426}
427
428TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginTopOutside) {
429  UpdateDisplay("1200x600,520x400");
430
431  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
432  core_api::system_display::DisplayProperties info;
433  info.bounds_origin_x.reset(new int(-360));
434  info.bounds_origin_y.reset(new int(-301));
435
436  bool success = false;
437  std::string error;
438  CallSetDisplayUnitInfo(
439      base::Int64ToString(secondary.id()), info, &success, &error);
440
441  ASSERT_TRUE(success);
442  ASSERT_TRUE(error.empty());
443
444  EXPECT_EQ("-360,-400 520x400", secondary.bounds().ToString());
445}
446
447TEST_F(DisplayInfoProviderChromeosTest,
448       SetBoundsOriginLeftButSharesBottomSide) {
449  UpdateDisplay("1200x600,1000x100");
450
451  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
452  core_api::system_display::DisplayProperties info;
453  info.bounds_origin_x.reset(new int(-650));
454  info.bounds_origin_y.reset(new int(700));
455
456  bool success = false;
457  std::string error;
458  CallSetDisplayUnitInfo(
459      base::Int64ToString(secondary.id()), info, &success, &error);
460
461  ASSERT_TRUE(success);
462  ASSERT_TRUE(error.empty());
463
464  EXPECT_EQ("-650,600 1000x100", secondary.bounds().ToString());
465}
466
467TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginRightButSharesTopSide) {
468  UpdateDisplay("1200x600,1000x100");
469
470  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
471  core_api::system_display::DisplayProperties info;
472  info.bounds_origin_x.reset(new int(850));
473  info.bounds_origin_y.reset(new int(-150));
474
475  bool success = false;
476  std::string error;
477  CallSetDisplayUnitInfo(
478      base::Int64ToString(secondary.id()), info, &success, &error);
479
480  ASSERT_TRUE(success);
481  ASSERT_TRUE(error.empty());
482
483  EXPECT_EQ("850,-100 1000x100", secondary.bounds().ToString());
484}
485
486TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginTopButSharesLeftSide) {
487  UpdateDisplay("1200x600,1000x100/l");
488
489  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
490  core_api::system_display::DisplayProperties info;
491  info.bounds_origin_x.reset(new int(-150));
492  info.bounds_origin_y.reset(new int(-650));
493
494  bool success = false;
495  std::string error;
496  CallSetDisplayUnitInfo(
497      base::Int64ToString(secondary.id()), info, &success, &error);
498
499  ASSERT_TRUE(success);
500  ASSERT_TRUE(error.empty());
501
502  EXPECT_EQ("-100,-650 100x1000", secondary.bounds().ToString());
503}
504
505TEST_F(DisplayInfoProviderChromeosTest,
506       SetBoundsOriginBottomButSharesRightSide) {
507  UpdateDisplay("1200x600,1000x100/l");
508
509  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
510  core_api::system_display::DisplayProperties info;
511  info.bounds_origin_x.reset(new int(1350));
512  info.bounds_origin_y.reset(new int(450));
513
514  bool success = false;
515  std::string error;
516  CallSetDisplayUnitInfo(
517      base::Int64ToString(secondary.id()), info, &success, &error);
518
519  ASSERT_TRUE(success);
520  ASSERT_TRUE(error.empty());
521
522  EXPECT_EQ("1200,450 100x1000", secondary.bounds().ToString());
523}
524
525TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginPrimaryHiDPI) {
526  UpdateDisplay("1200x600*2,500x500");
527
528  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
529  core_api::system_display::DisplayProperties info;
530  info.bounds_origin_x.reset(new int(250));
531  info.bounds_origin_y.reset(new int(-100));
532
533  bool success = false;
534  std::string error;
535  CallSetDisplayUnitInfo(
536      base::Int64ToString(secondary.id()), info, &success, &error);
537
538  ASSERT_TRUE(success);
539  ASSERT_TRUE(error.empty());
540
541  EXPECT_EQ("600,-100 500x500", secondary.bounds().ToString());
542}
543
544TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginSecondaryHiDPI) {
545  UpdateDisplay("1200x600,600x1000*2");
546
547  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
548  core_api::system_display::DisplayProperties info;
549  info.bounds_origin_x.reset(new int(450));
550  info.bounds_origin_y.reset(new int(-100));
551
552  bool success = false;
553  std::string error;
554  CallSetDisplayUnitInfo(
555      base::Int64ToString(secondary.id()), info, &success, &error);
556
557  ASSERT_TRUE(success);
558  ASSERT_TRUE(error.empty());
559
560  EXPECT_EQ("450,-500 300x500", secondary.bounds().ToString());
561}
562
563TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginOutOfBounds) {
564  UpdateDisplay("1200x600,600x1000*2");
565
566  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
567  core_api::system_display::DisplayProperties info;
568  info.bounds_origin_x.reset(new int(0x200001));
569  info.bounds_origin_y.reset(new int(-100));
570
571  bool success = false;
572  std::string error;
573  CallSetDisplayUnitInfo(
574      base::Int64ToString(secondary.id()), info, &success, &error);
575
576  ASSERT_FALSE(success);
577  ASSERT_EQ("Bounds origin x out of bounds.", error);
578
579  EXPECT_EQ("1200,0 300x500", secondary.bounds().ToString());
580}
581
582TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginOutOfBoundsNegative) {
583  UpdateDisplay("1200x600,600x1000*2");
584
585  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
586  core_api::system_display::DisplayProperties info;
587  info.bounds_origin_x.reset(new int(300));
588  info.bounds_origin_y.reset(new int(-0x200001));
589
590  bool success = false;
591  std::string error;
592  CallSetDisplayUnitInfo(
593      base::Int64ToString(secondary.id()), info, &success, &error);
594
595  ASSERT_FALSE(success);
596  ASSERT_EQ("Bounds origin y out of bounds.", error);
597
598  EXPECT_EQ("1200,0 300x500", secondary.bounds().ToString());
599}
600
601TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginMaxValues) {
602  UpdateDisplay("1200x4600,600x1000*2");
603
604  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
605  core_api::system_display::DisplayProperties info;
606  info.bounds_origin_x.reset(new int(200000));
607  info.bounds_origin_y.reset(new int(10));
608
609  bool success = false;
610  std::string error;
611  CallSetDisplayUnitInfo(
612      base::Int64ToString(secondary.id()), info, &success, &error);
613
614  ASSERT_TRUE(success);
615  EXPECT_TRUE(error.empty());
616
617  EXPECT_EQ("1200,10 300x500", secondary.bounds().ToString());
618}
619
620TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginOnPrimary) {
621  UpdateDisplay("1200x600,600x1000*2");
622
623  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
624  core_api::system_display::DisplayProperties info;
625  info.bounds_origin_x.reset(new int(300));
626  info.is_primary.reset(new bool(true));
627
628  bool success = false;
629  std::string error;
630  CallSetDisplayUnitInfo(
631      base::Int64ToString(secondary.id()), info, &success, &error);
632
633  ASSERT_FALSE(success);
634  ASSERT_EQ("Bounds origin not allowed for the primary display.", error);
635
636  EXPECT_EQ("1200,0 300x500", secondary.bounds().ToString());
637  // The operation failed because the primary property would be set before
638  // setting bounds. The primary display shouldn't have been changed, though.
639  EXPECT_NE(ash::Shell::GetScreen()->GetPrimaryDisplay().id(), secondary.id());
640}
641
642TEST_F(DisplayInfoProviderChromeosTest, SetBoundsOriginWithMirroring) {
643  UpdateDisplay("1200x600,600x1000*2");
644
645  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
646  const gfx::Display& primary = ash::Shell::GetScreen()->GetPrimaryDisplay();
647
648  core_api::system_display::DisplayProperties info;
649  info.bounds_origin_x.reset(new int(300));
650  info.mirroring_source_id.reset(
651      new std::string(base::Int64ToString(primary.id())));
652
653  bool success = false;
654  std::string error;
655  CallSetDisplayUnitInfo(
656      base::Int64ToString(secondary.id()), info, &success, &error);
657
658  ASSERT_FALSE(success);
659  ASSERT_EQ("No other parameter should be set alongside mirroringSourceId.",
660            error);
661}
662
663TEST_F(DisplayInfoProviderChromeosTest, SetRotation) {
664  UpdateDisplay("1200x600,600x1000*2");
665
666  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
667  core_api::system_display::DisplayProperties info;
668  info.rotation.reset(new int(90));
669
670  bool success = false;
671  std::string error;
672  CallSetDisplayUnitInfo(
673      base::Int64ToString(secondary.id()), info, &success, &error);
674
675  ASSERT_TRUE(success);
676  EXPECT_TRUE(error.empty());
677
678  EXPECT_EQ("1200,0 500x300", secondary.bounds().ToString());
679  EXPECT_EQ(gfx::Display::ROTATE_90, secondary.rotation());
680
681  info.rotation.reset(new int(270));
682  CallSetDisplayUnitInfo(
683      base::Int64ToString(secondary.id()), info, &success, &error);
684
685  ASSERT_TRUE(success);
686  EXPECT_TRUE(error.empty());
687
688  EXPECT_EQ("1200,0 500x300", secondary.bounds().ToString());
689  EXPECT_EQ(gfx::Display::ROTATE_270, secondary.rotation());
690
691  info.rotation.reset(new int(180));
692  // Switch primary display.
693  info.is_primary.reset(new bool(true));
694  CallSetDisplayUnitInfo(
695      base::Int64ToString(secondary.id()), info, &success, &error);
696
697  ASSERT_TRUE(success);
698  EXPECT_TRUE(error.empty());
699
700  EXPECT_EQ("0,0 300x500", secondary.bounds().ToString());
701  EXPECT_EQ(gfx::Display::ROTATE_180, secondary.rotation());
702  EXPECT_EQ(ash::Shell::GetScreen()->GetPrimaryDisplay().id(), secondary.id());
703
704  info.rotation.reset(new int(0));
705  CallSetDisplayUnitInfo(
706      base::Int64ToString(secondary.id()), info, &success, &error);
707
708  ASSERT_TRUE(success);
709  EXPECT_TRUE(error.empty());
710
711  EXPECT_EQ("0,0 300x500", secondary.bounds().ToString());
712  EXPECT_EQ(gfx::Display::ROTATE_0, secondary.rotation());
713  EXPECT_EQ(ash::Shell::GetScreen()->GetPrimaryDisplay().id(), secondary.id());
714}
715
716TEST_F(DisplayInfoProviderChromeosTest, SetInvalidRotation) {
717  UpdateDisplay("1200x600,600x1000*2");
718
719  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
720  core_api::system_display::DisplayProperties info;
721  info.rotation.reset(new int(91));
722
723  bool success = false;
724  std::string error;
725  CallSetDisplayUnitInfo(
726      base::Int64ToString(secondary.id()), info, &success, &error);
727
728  ASSERT_FALSE(success);
729  EXPECT_EQ("Invalid rotation.", error);
730}
731
732TEST_F(DisplayInfoProviderChromeosTest, SetNegativeOverscan) {
733  UpdateDisplay("1200x600,600x1000*2");
734
735  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
736  core_api::system_display::DisplayProperties info;
737  info.overscan.reset(new core_api::system_display::Insets);
738  info.overscan->left = -10;
739
740  bool success = false;
741  std::string error;
742  CallSetDisplayUnitInfo(
743      base::Int64ToString(secondary.id()), info, &success, &error);
744
745  ASSERT_FALSE(success);
746  EXPECT_EQ("Negative overscan not allowed.", error);
747
748  EXPECT_EQ("1200,0 300x500", secondary.bounds().ToString());
749
750  info.overscan->left = 0;
751  info.overscan->right = -200;
752
753  CallSetDisplayUnitInfo(
754      base::Int64ToString(secondary.id()), info, &success, &error);
755
756  ASSERT_FALSE(success);
757  EXPECT_EQ("Negative overscan not allowed.", error);
758
759  EXPECT_EQ("1200,0 300x500", secondary.bounds().ToString());
760
761  info.overscan->right = 0;
762  info.overscan->top = -300;
763
764  CallSetDisplayUnitInfo(
765      base::Int64ToString(secondary.id()), info, &success, &error);
766
767  ASSERT_FALSE(success);
768  EXPECT_EQ("Negative overscan not allowed.", error);
769
770  EXPECT_EQ("1200,0 300x500", secondary.bounds().ToString());
771
772  info.overscan->right = 0;
773  info.overscan->top = -1000;
774
775  CallSetDisplayUnitInfo(
776      base::Int64ToString(secondary.id()), info, &success, &error);
777
778  ASSERT_FALSE(success);
779  EXPECT_EQ("Negative overscan not allowed.", error);
780
781  EXPECT_EQ("1200,0 300x500", secondary.bounds().ToString());
782
783  info.overscan->right = 0;
784  info.overscan->top = 0;
785
786  CallSetDisplayUnitInfo(
787      base::Int64ToString(secondary.id()), info, &success, &error);
788
789  ASSERT_TRUE(success);
790  EXPECT_TRUE(error.empty());
791
792  EXPECT_EQ("1200,0 300x500", secondary.bounds().ToString());
793}
794
795TEST_F(DisplayInfoProviderChromeosTest, SetOverscanLargerThanHorizontalBounds) {
796  UpdateDisplay("1200x600,600x1000*2");
797
798  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
799  core_api::system_display::DisplayProperties info;
800  info.overscan.reset(new core_api::system_display::Insets);
801  // Horizontal overscan is 151, which would make the bounds width 149.
802  info.overscan->left = 50;
803  info.overscan->top = 10;
804  info.overscan->right = 101;
805  info.overscan->bottom = 20;
806
807  bool success = false;
808  std::string error;
809  CallSetDisplayUnitInfo(
810      base::Int64ToString(secondary.id()), info, &success, &error);
811
812  ASSERT_FALSE(success);
813  EXPECT_EQ("Horizontal overscan is more than half of the screen width.",
814            error);
815}
816
817TEST_F(DisplayInfoProviderChromeosTest, SetOverscanLargerThanVerticalBounds) {
818  UpdateDisplay("1200x600,600x1000");
819
820  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
821  core_api::system_display::DisplayProperties info;
822  info.overscan.reset(new core_api::system_display::Insets);
823  // Vertical overscan is 501, which would make the bounds height 499.
824  info.overscan->left = 20;
825  info.overscan->top = 250;
826  info.overscan->right = 101;
827  info.overscan->bottom = 251;
828
829  bool success = false;
830  std::string error;
831  CallSetDisplayUnitInfo(
832      base::Int64ToString(secondary.id()), info, &success, &error);
833
834  ASSERT_FALSE(success);
835  EXPECT_EQ("Vertical overscan is more than half of the screen height.", error);
836}
837
838TEST_F(DisplayInfoProviderChromeosTest, SetOverscan) {
839  UpdateDisplay("1200x600,600x1000*2");
840
841  const gfx::Display& secondary = ash::ScreenUtil::GetSecondaryDisplay();
842  core_api::system_display::DisplayProperties info;
843  info.overscan.reset(new core_api::system_display::Insets);
844  info.overscan->left = 20;
845  info.overscan->top = 199;
846  info.overscan->right = 130;
847  info.overscan->bottom = 51;
848
849  bool success = false;
850  std::string error;
851  CallSetDisplayUnitInfo(
852      base::Int64ToString(secondary.id()), info, &success, &error);
853
854  ASSERT_TRUE(success);
855  EXPECT_TRUE(error.empty());
856
857  EXPECT_EQ("1200,0 150x250", secondary.bounds().ToString());
858  const gfx::Insets overscan =
859      GetDisplayManager()->GetOverscanInsets(secondary.id());
860
861  EXPECT_EQ(20, overscan.left());
862  EXPECT_EQ(199, overscan.top());
863  EXPECT_EQ(130, overscan.right());
864  EXPECT_EQ(51, overscan.bottom());
865}
866
867TEST_F(DisplayInfoProviderChromeosTest, SetOverscanForInternal) {
868  UpdateDisplay("1200x600,600x1000*2");
869  const int64 internal_display_id =
870      ash::test::DisplayManagerTestApi(GetDisplayManager())
871          .SetFirstDisplayAsInternalDisplay();
872
873  core_api::system_display::DisplayProperties info;
874  info.overscan.reset(new core_api::system_display::Insets);
875  // Vertical overscan is 501, which would make the bounds height 499.
876  info.overscan->left = 20;
877  info.overscan->top = 20;
878  info.overscan->right = 20;
879  info.overscan->bottom = 20;
880
881  bool success = false;
882  std::string error;
883  CallSetDisplayUnitInfo(
884      base::Int64ToString(internal_display_id), info, &success, &error);
885
886  ASSERT_FALSE(success);
887  EXPECT_EQ("Overscan changes not allowed for the internal monitor.", error);
888}
889
890}  // namespace
891}  // namespace extensions
892