Home | History | Annotate | Download | only in display
      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/display/root_window_transformers.h"
      6 
      7 #include "ash/display/display_info.h"
      8 #include "ash/display/display_manager.h"
      9 #include "ash/launcher/launcher.h"
     10 #include "ash/magnifier/magnification_controller.h"
     11 #include "ash/screen_ash.h"
     12 #include "ash/shelf/shelf_widget.h"
     13 #include "ash/shell.h"
     14 #include "ash/test/ash_test_base.h"
     15 #include "ash/test/cursor_manager_test_api.h"
     16 #include "ash/test/mirror_window_test_api.h"
     17 #include "base/synchronization/waitable_event.h"
     18 #include "ui/aura/env.h"
     19 #include "ui/aura/root_window.h"
     20 #include "ui/aura/root_window_transformer.h"
     21 #include "ui/aura/test/event_generator.h"
     22 #include "ui/aura/window_tracker.h"
     23 #include "ui/events/event_handler.h"
     24 #include "ui/gfx/display.h"
     25 #include "ui/gfx/rect_conversions.h"
     26 #include "ui/gfx/screen.h"
     27 #include "ui/views/widget/widget.h"
     28 
     29 namespace ash {
     30 namespace internal {
     31 
     32 namespace {
     33 
     34 const char kDesktopBackgroundView[] = "DesktopBackgroundView";
     35 
     36 class TestEventHandler : public ui::EventHandler {
     37  public:
     38   TestEventHandler() : target_root_(NULL),
     39                        touch_radius_x_(0.0),
     40                        touch_radius_y_(0.0),
     41                        scroll_x_offset_(0.0),
     42                        scroll_y_offset_(0.0),
     43                        scroll_x_offset_ordinal_(0.0),
     44                        scroll_y_offset_ordinal_(0.0) {}
     45   virtual ~TestEventHandler() {}
     46 
     47   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
     48     if (event->flags() & ui::EF_IS_SYNTHESIZED)
     49       return;
     50     aura::Window* target = static_cast<aura::Window*>(event->target());
     51     mouse_location_ = event->root_location();
     52     target_root_ = target->GetRootWindow();
     53     event->StopPropagation();
     54   }
     55 
     56   virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
     57     aura::Window* target = static_cast<aura::Window*>(event->target());
     58     // Only record when the target is the background which covers
     59     // entire root window.
     60     if (target->name() != kDesktopBackgroundView)
     61       return;
     62     touch_radius_x_ = event->radius_x();
     63     touch_radius_y_ = event->radius_y();
     64     event->StopPropagation();
     65   }
     66 
     67   virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
     68     aura::Window* target = static_cast<aura::Window*>(event->target());
     69     // Only record when the target is the background which covers
     70     // entire root window.
     71     if (target->name() != kDesktopBackgroundView)
     72       return;
     73 
     74     if (event->type() == ui::ET_SCROLL) {
     75       scroll_x_offset_ = event->x_offset();
     76       scroll_y_offset_ = event->y_offset();
     77       scroll_x_offset_ordinal_ = event->x_offset_ordinal();
     78       scroll_y_offset_ordinal_ = event->y_offset_ordinal();
     79     }
     80     event->StopPropagation();
     81   }
     82 
     83   std::string GetLocationAndReset() {
     84     std::string result = mouse_location_.ToString();
     85     mouse_location_.SetPoint(0, 0);
     86     target_root_ = NULL;
     87     return result;
     88   }
     89 
     90   float touch_radius_x() const { return touch_radius_x_; }
     91   float touch_radius_y() const { return touch_radius_y_; }
     92   float scroll_x_offset() const { return scroll_x_offset_; }
     93   float scroll_y_offset() const { return scroll_y_offset_; }
     94   float scroll_x_offset_ordinal() const { return scroll_x_offset_ordinal_; }
     95   float scroll_y_offset_ordinal() const { return scroll_y_offset_ordinal_; }
     96 
     97  private:
     98   gfx::Point mouse_location_;
     99   aura::Window* target_root_;
    100 
    101   float touch_radius_x_;
    102   float touch_radius_y_;
    103   float scroll_x_offset_;
    104   float scroll_y_offset_;
    105   float scroll_x_offset_ordinal_;
    106   float scroll_y_offset_ordinal_;
    107 
    108   DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
    109 };
    110 
    111 gfx::Display::Rotation GetStoredRotation(int64 id) {
    112   return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).rotation();
    113 }
    114 
    115 float GetStoredUIScale(int64 id) {
    116   return Shell::GetInstance()->display_manager()->GetDisplayInfo(id).
    117       GetEffectiveUIScale();
    118 }
    119 
    120 }  // namespace
    121 
    122 typedef test::AshTestBase RootWindowTransformersTest;
    123 
    124 #if defined(OS_WIN)
    125 // TODO(scottmg): RootWindow doesn't get resized on Windows
    126 // Ash. http://crbug.com/247916.
    127 #define MAYBE_RotateAndMagnify DISABLED_RotateAndMagniy
    128 #define MAYBE_TouchScaleAndMagnify DISABLED_TouchScaleAndMagnify
    129 #define MAYBE_ConvertHostToRootCoords DISABLED_ConvertHostToRootCoords
    130 #else
    131 #define MAYBE_RotateAndMagnify RotateAndMagniy
    132 #define MAYBE_TouchScaleAndMagnify TouchScaleAndMagnify
    133 #define MAYBE_ConvertHostToRootCoords ConvertHostToRootCoords
    134 #endif
    135 
    136 TEST_F(RootWindowTransformersTest, MAYBE_RotateAndMagnify) {
    137   MagnificationController* magnifier =
    138       Shell::GetInstance()->magnification_controller();
    139   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
    140 
    141   TestEventHandler event_handler;
    142   Shell::GetInstance()->AddPreTargetHandler(&event_handler);
    143 
    144   UpdateDisplay("120x200,300x400*2");
    145   gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
    146   int64 display2_id = ScreenAsh::GetSecondaryDisplay().id();
    147 
    148   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    149   aura::test::EventGenerator generator1(root_windows[0]);
    150   aura::test::EventGenerator generator2(root_windows[1]);
    151 
    152   magnifier->SetEnabled(true);
    153   EXPECT_EQ(2.0f, magnifier->GetScale());
    154   EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
    155   EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
    156   EXPECT_EQ("120,0 150x200",
    157             ScreenAsh::GetSecondaryDisplay().bounds().ToString());
    158   generator1.MoveMouseToInHost(40, 80);
    159   EXPECT_EQ("50,90", event_handler.GetLocationAndReset());
    160   EXPECT_EQ("50,90",
    161             aura::Env::GetInstance()->last_mouse_location().ToString());
    162   EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display1.id()));
    163   EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
    164   magnifier->SetEnabled(false);
    165 
    166   display_manager->SetDisplayRotation(display1.id(),
    167                                       gfx::Display::ROTATE_90);
    168   // Move the cursor to the center of the first root window.
    169   generator1.MoveMouseToInHost(59, 100);
    170 
    171   magnifier->SetEnabled(true);
    172   EXPECT_EQ(2.0f, magnifier->GetScale());
    173   EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
    174   EXPECT_EQ("150x200", root_windows[1]->bounds().size().ToString());
    175   EXPECT_EQ("200,0 150x200",
    176             ScreenAsh::GetSecondaryDisplay().bounds().ToString());
    177   generator1.MoveMouseToInHost(39, 120);
    178   EXPECT_EQ("110,70", event_handler.GetLocationAndReset());
    179   EXPECT_EQ("110,70",
    180             aura::Env::GetInstance()->last_mouse_location().ToString());
    181   EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
    182   EXPECT_EQ(gfx::Display::ROTATE_0, GetStoredRotation(display2_id));
    183   magnifier->SetEnabled(false);
    184 
    185   DisplayLayout display_layout(DisplayLayout::BOTTOM, 50);
    186   display_manager->SetLayoutForCurrentDisplays(display_layout);
    187   EXPECT_EQ("50,120 150x200",
    188             ScreenAsh::GetSecondaryDisplay().bounds().ToString());
    189 
    190   display_manager->SetDisplayRotation(display2_id,
    191                                       gfx::Display::ROTATE_270);
    192   // Move the cursor to the center of the second root window.
    193   generator2.MoveMouseToInHost(151, 199);
    194 
    195   magnifier->SetEnabled(true);
    196   EXPECT_EQ("200x120", root_windows[0]->bounds().size().ToString());
    197   EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
    198   EXPECT_EQ("50,120 200x150",
    199             ScreenAsh::GetSecondaryDisplay().bounds().ToString());
    200   generator2.MoveMouseToInHost(172, 219);
    201   EXPECT_EQ("95,80", event_handler.GetLocationAndReset());
    202   EXPECT_EQ("145,200",
    203             aura::Env::GetInstance()->last_mouse_location().ToString());
    204   EXPECT_EQ(gfx::Display::ROTATE_90, GetStoredRotation(display1.id()));
    205   EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
    206   magnifier->SetEnabled(false);
    207 
    208   display_manager->SetDisplayRotation(display1.id(),
    209                                       gfx::Display::ROTATE_180);
    210   // Move the cursor to the center of the first root window.
    211   generator1.MoveMouseToInHost(59, 99);
    212 
    213   magnifier->SetEnabled(true);
    214   EXPECT_EQ("120x200", root_windows[0]->bounds().size().ToString());
    215   EXPECT_EQ("200x150", root_windows[1]->bounds().size().ToString());
    216   // Dislay must share at least 100, so the x's offset becomes 20.
    217   EXPECT_EQ("20,200 200x150",
    218             ScreenAsh::GetSecondaryDisplay().bounds().ToString());
    219   generator1.MoveMouseToInHost(39, 59);
    220   EXPECT_EQ("70,120", event_handler.GetLocationAndReset());
    221   EXPECT_EQ(gfx::Display::ROTATE_180, GetStoredRotation(display1.id()));
    222   EXPECT_EQ(gfx::Display::ROTATE_270, GetStoredRotation(display2_id));
    223   magnifier->SetEnabled(false);
    224 
    225   Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
    226 }
    227 
    228 TEST_F(RootWindowTransformersTest, ScaleAndMagnify) {
    229   if (!SupportsMultipleDisplays())
    230     return;
    231 
    232   TestEventHandler event_handler;
    233   Shell::GetInstance()->AddPreTargetHandler(&event_handler);
    234 
    235   UpdateDisplay("600x400*2 (at) 1.5,500x300");
    236 
    237   gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
    238   gfx::Display::SetInternalDisplayId(display1.id());
    239   gfx::Display display2 = ScreenAsh::GetSecondaryDisplay();
    240   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    241   MagnificationController* magnifier =
    242       Shell::GetInstance()->magnification_controller();
    243 
    244   magnifier->SetEnabled(true);
    245   EXPECT_EQ(2.0f, magnifier->GetScale());
    246   EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
    247   EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
    248   EXPECT_EQ("450,0 500x300", display2.bounds().ToString());
    249   EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
    250   EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
    251 
    252   aura::test::EventGenerator generator(root_windows[0]);
    253   generator.MoveMouseToInHost(500, 200);
    254   EXPECT_EQ("299,150", event_handler.GetLocationAndReset());
    255   magnifier->SetEnabled(false);
    256 
    257   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
    258   display_manager->SetDisplayUIScale(display1.id(), 1.25);
    259   display1 = Shell::GetScreen()->GetPrimaryDisplay();
    260   display2 = ScreenAsh::GetSecondaryDisplay();
    261   magnifier->SetEnabled(true);
    262   EXPECT_EQ(2.0f, magnifier->GetScale());
    263   EXPECT_EQ("0,0 375x250", display1.bounds().ToString());
    264   EXPECT_EQ("0,0 375x250", root_windows[0]->bounds().ToString());
    265   EXPECT_EQ("375,0 500x300", display2.bounds().ToString());
    266   EXPECT_EQ(1.25f, GetStoredUIScale(display1.id()));
    267   EXPECT_EQ(1.0f, GetStoredUIScale(display2.id()));
    268   magnifier->SetEnabled(false);
    269 
    270   Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
    271 }
    272 
    273 TEST_F(RootWindowTransformersTest, MAYBE_TouchScaleAndMagnify) {
    274   TestEventHandler event_handler;
    275   Shell::GetInstance()->AddPreTargetHandler(&event_handler);
    276 
    277   UpdateDisplay("200x200*2");
    278   gfx::Display display = Shell::GetScreen()->GetPrimaryDisplay();
    279   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    280   aura::Window* root_window = root_windows[0];
    281   aura::test::EventGenerator generator(root_window);
    282   MagnificationController* magnifier =
    283       Shell::GetInstance()->magnification_controller();
    284 
    285   magnifier->SetEnabled(true);
    286   EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale());
    287   magnifier->SetScale(2.5f, false);
    288   EXPECT_FLOAT_EQ(2.5f, magnifier->GetScale());
    289   generator.PressMoveAndReleaseTouchTo(50, 50);
    290   // Default test touches have radius_x/y = 1.0, with device scale
    291   // factor = 2, the scaled radius_x/y should be 0.5.
    292   EXPECT_FLOAT_EQ(0.2f, event_handler.touch_radius_x());
    293   EXPECT_FLOAT_EQ(0.2f, event_handler.touch_radius_y());
    294 
    295   generator.ScrollSequence(gfx::Point(0,0),
    296                            base::TimeDelta::FromMilliseconds(100),
    297                            10.0, 1.0, 5, 1);
    298 
    299   // ordinal_offset is invariant to the device scale factor.
    300   EXPECT_FLOAT_EQ(event_handler.scroll_x_offset(),
    301                   event_handler.scroll_x_offset_ordinal());
    302   EXPECT_FLOAT_EQ(event_handler.scroll_y_offset(),
    303                   event_handler.scroll_y_offset_ordinal());
    304   magnifier->SetEnabled(false);
    305 
    306   Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
    307 }
    308 
    309 TEST_F(RootWindowTransformersTest, MAYBE_ConvertHostToRootCoords) {
    310   TestEventHandler event_handler;
    311   Shell::GetInstance()->AddPreTargetHandler(&event_handler);
    312   MagnificationController* magnifier =
    313       Shell::GetInstance()->magnification_controller();
    314 
    315   // Test 1
    316   UpdateDisplay("600x400*2/r (at) 1.5");
    317 
    318   gfx::Display display1 = Shell::GetScreen()->GetPrimaryDisplay();
    319   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    320   EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
    321   EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
    322   EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
    323 
    324   aura::test::EventGenerator generator(root_windows[0]);
    325   generator.MoveMouseToInHost(300, 200);
    326   magnifier->SetEnabled(true);
    327   EXPECT_EQ("150,224", event_handler.GetLocationAndReset());
    328   EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale());
    329 
    330   generator.MoveMouseToInHost(300, 200);
    331   EXPECT_EQ("150,224", event_handler.GetLocationAndReset());
    332   generator.MoveMouseToInHost(200, 300);
    333   EXPECT_EQ("187,261", event_handler.GetLocationAndReset());
    334   generator.MoveMouseToInHost(100, 400);
    335   EXPECT_EQ("237,299", event_handler.GetLocationAndReset());
    336   generator.MoveMouseToInHost(0, 0);
    337   EXPECT_EQ("137,348", event_handler.GetLocationAndReset());
    338 
    339   magnifier->SetEnabled(false);
    340   EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale());
    341 
    342   // Test 2
    343   UpdateDisplay("600x400*2/u (at) 1.5");
    344   display1 = Shell::GetScreen()->GetPrimaryDisplay();
    345   root_windows = Shell::GetAllRootWindows();
    346   EXPECT_EQ("0,0 450x300", display1.bounds().ToString());
    347   EXPECT_EQ("0,0 450x300", root_windows[0]->bounds().ToString());
    348   EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
    349 
    350   generator.MoveMouseToInHost(300, 200);
    351   magnifier->SetEnabled(true);
    352   EXPECT_EQ("224,149", event_handler.GetLocationAndReset());
    353   EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale());
    354 
    355   generator.MoveMouseToInHost(300, 200);
    356   EXPECT_EQ("224,148", event_handler.GetLocationAndReset());
    357   generator.MoveMouseToInHost(200, 300);
    358   EXPECT_EQ("261,111", event_handler.GetLocationAndReset());
    359   generator.MoveMouseToInHost(100, 400);
    360   EXPECT_EQ("299,60", event_handler.GetLocationAndReset());
    361   generator.MoveMouseToInHost(0, 0);
    362   EXPECT_EQ("348,159", event_handler.GetLocationAndReset());
    363 
    364   magnifier->SetEnabled(false);
    365   EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale());
    366 
    367   // Test 3
    368   UpdateDisplay("600x400*2/l (at) 1.5");
    369   display1 = Shell::GetScreen()->GetPrimaryDisplay();
    370   root_windows = Shell::GetAllRootWindows();
    371   EXPECT_EQ("0,0 300x450", display1.bounds().ToString());
    372   EXPECT_EQ("0,0 300x450", root_windows[0]->bounds().ToString());
    373   EXPECT_EQ(1.5f, GetStoredUIScale(display1.id()));
    374 
    375   generator.MoveMouseToInHost(300, 200);
    376   magnifier->SetEnabled(true);
    377   EXPECT_EQ("149,225", event_handler.GetLocationAndReset());
    378   EXPECT_FLOAT_EQ(2.0f, magnifier->GetScale());
    379 
    380   generator.MoveMouseToInHost(300, 200);
    381   EXPECT_EQ("148,224", event_handler.GetLocationAndReset());
    382   generator.MoveMouseToInHost(200, 300);
    383   EXPECT_EQ("111,187", event_handler.GetLocationAndReset());
    384   generator.MoveMouseToInHost(100, 400);
    385   EXPECT_EQ("60,149", event_handler.GetLocationAndReset());
    386   generator.MoveMouseToInHost(0, 0);
    387   EXPECT_EQ("159,99", event_handler.GetLocationAndReset());
    388 
    389   magnifier->SetEnabled(false);
    390   EXPECT_FLOAT_EQ(1.0f, magnifier->GetScale());
    391 
    392   Shell::GetInstance()->RemovePreTargetHandler(&event_handler);
    393 }
    394 
    395 TEST_F(RootWindowTransformersTest, LetterBoxPillarBox) {
    396   if (!SupportsMultipleDisplays())
    397     return;
    398   test::MirrorWindowTestApi test_api;
    399   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
    400   display_manager->SetSecondDisplayMode(DisplayManager::MIRRORING);
    401   UpdateDisplay("400x200,500x500");
    402   scoped_ptr<aura::RootWindowTransformer> transformer(
    403       test_api.CreateCurrentRootWindowTransformer());
    404   // Y margin must be margin is (500 - 500/400 * 200) / 2 = 125.
    405   EXPECT_EQ("0,125,0,125", transformer->GetHostInsets().ToString());
    406 
    407   UpdateDisplay("200x400,500x500");
    408   // The aspect ratio is flipped, so X margin is now 125.
    409   transformer = test_api.CreateCurrentRootWindowTransformer();
    410   EXPECT_EQ("125,0,125,0", transformer->GetHostInsets().ToString());
    411 }
    412 
    413 }  // namespace test
    414 }  // namespace ash
    415