Home | History | Annotate | Download | only in wm
      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
      3 // found in the LICENSE file.
      4 
      5 #include "ash/wm/system_modal_container_layout_manager.h"
      6 
      7 #include "ash/root_window_controller.h"
      8 #include "ash/session/session_state_delegate.h"
      9 #include "ash/shell.h"
     10 #include "ash/shell_window_ids.h"
     11 #include "ash/test/ash_test_base.h"
     12 #include "ash/wm/window_util.h"
     13 #include "base/command_line.h"
     14 #include "base/compiler_specific.h"
     15 #include "base/run_loop.h"
     16 #include "ui/aura/window.h"
     17 #include "ui/aura/window_event_dispatcher.h"
     18 #include "ui/compositor/layer.h"
     19 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
     20 #include "ui/compositor/test/layer_animator_test_controller.h"
     21 #include "ui/events/test/event_generator.h"
     22 #include "ui/gfx/screen.h"
     23 #include "ui/keyboard/keyboard_controller.h"
     24 #include "ui/keyboard/keyboard_controller_proxy.h"
     25 #include "ui/keyboard/keyboard_switches.h"
     26 #include "ui/keyboard/keyboard_util.h"
     27 #include "ui/views/test/capture_tracking_view.h"
     28 #include "ui/views/widget/widget.h"
     29 #include "ui/views/widget/widget_delegate.h"
     30 #include "ui/wm/core/window_util.h"
     31 
     32 namespace ash {
     33 namespace test {
     34 
     35 namespace {
     36 
     37 aura::Window* GetModalContainer() {
     38   return Shell::GetPrimaryRootWindowController()->GetContainer(
     39       ash::kShellWindowId_SystemModalContainer);
     40 }
     41 
     42 bool AllRootWindowsHaveModalBackgroundsForContainer(int container_id) {
     43   std::vector<aura::Window*> containers =
     44       Shell::GetContainersFromAllRootWindows(container_id, NULL);
     45   bool has_modal_screen = !containers.empty();
     46   for (std::vector<aura::Window*>::iterator iter = containers.begin();
     47        iter != containers.end(); ++iter) {
     48     has_modal_screen &= static_cast<SystemModalContainerLayoutManager*>(
     49                             (*iter)->layout_manager())->has_modal_background();
     50   }
     51   return has_modal_screen;
     52 }
     53 
     54 bool AllRootWindowsHaveLockedModalBackgrounds() {
     55   return AllRootWindowsHaveModalBackgroundsForContainer(
     56       kShellWindowId_LockSystemModalContainer);
     57 }
     58 
     59 bool AllRootWindowsHaveModalBackgrounds() {
     60   return AllRootWindowsHaveModalBackgroundsForContainer(
     61       kShellWindowId_SystemModalContainer);
     62 }
     63 
     64 class TestWindow : public views::WidgetDelegateView {
     65  public:
     66   explicit TestWindow(bool modal) : modal_(modal) {}
     67   virtual ~TestWindow() {}
     68 
     69   // The window needs be closed from widget in order for
     70   // aura::client::kModalKey property to be reset.
     71   static void CloseTestWindow(aura::Window* window) {
     72     views::Widget::GetWidgetForNativeWindow(window)->Close();
     73   }
     74 
     75   // Overridden from views::View:
     76   virtual gfx::Size GetPreferredSize() const OVERRIDE {
     77     return gfx::Size(50, 50);
     78   }
     79 
     80   // Overridden from views::WidgetDelegate:
     81   virtual views::View* GetContentsView() OVERRIDE {
     82     return this;
     83   }
     84   virtual ui::ModalType GetModalType() const OVERRIDE {
     85     return modal_ ? ui::MODAL_TYPE_SYSTEM : ui::MODAL_TYPE_NONE;
     86   }
     87 
     88  private:
     89   bool modal_;
     90 
     91   DISALLOW_COPY_AND_ASSIGN(TestWindow);
     92 };
     93 
     94 class EventTestWindow : public TestWindow {
     95  public:
     96   explicit EventTestWindow(bool modal) : TestWindow(modal),
     97                                          mouse_presses_(0) {}
     98   virtual ~EventTestWindow() {}
     99 
    100   aura::Window* OpenTestWindowWithContext(aura::Window* context) {
    101     views::Widget* widget =
    102         views::Widget::CreateWindowWithContext(this, context);
    103     widget->Show();
    104     return widget->GetNativeView();
    105   }
    106 
    107   aura::Window* OpenTestWindowWithParent(aura::Window* parent) {
    108     DCHECK(parent);
    109     views::Widget* widget =
    110         views::Widget::CreateWindowWithParent(this, parent);
    111     widget->Show();
    112     return widget->GetNativeView();
    113   }
    114 
    115   // Overridden from views::View:
    116   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
    117     mouse_presses_++;
    118     return false;
    119   }
    120 
    121   int mouse_presses() const { return mouse_presses_; }
    122  private:
    123   int mouse_presses_;
    124 
    125   DISALLOW_COPY_AND_ASSIGN(EventTestWindow);
    126 };
    127 
    128 class TransientWindowObserver : public aura::WindowObserver {
    129  public:
    130   TransientWindowObserver() : destroyed_(false) {}
    131   virtual ~TransientWindowObserver() {}
    132 
    133   bool destroyed() const { return destroyed_; }
    134 
    135   // Overridden from aura::WindowObserver:
    136   virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE {
    137     destroyed_ = true;
    138   }
    139 
    140  private:
    141   bool destroyed_;
    142 
    143   DISALLOW_COPY_AND_ASSIGN(TransientWindowObserver);
    144 };
    145 
    146 }  // namespace
    147 
    148 class SystemModalContainerLayoutManagerTest : public AshTestBase {
    149  public:
    150   virtual void SetUp() OVERRIDE {
    151     // Allow a virtual keyboard (and initialize it per default).
    152     CommandLine::ForCurrentProcess()->AppendSwitch(
    153         keyboard::switches::kEnableVirtualKeyboard);
    154     AshTestBase::SetUp();
    155     Shell::GetPrimaryRootWindowController()->ActivateKeyboard(
    156         keyboard::KeyboardController::GetInstance());
    157   }
    158 
    159   virtual void TearDown() OVERRIDE {
    160     Shell::GetPrimaryRootWindowController()->DeactivateKeyboard(
    161         keyboard::KeyboardController::GetInstance());
    162     AshTestBase::TearDown();
    163   }
    164 
    165   aura::Window* OpenToplevelTestWindow(bool modal) {
    166     views::Widget* widget = views::Widget::CreateWindowWithContext(
    167         new TestWindow(modal), CurrentContext());
    168     widget->Show();
    169     return widget->GetNativeView();
    170   }
    171 
    172   aura::Window* OpenTestWindowWithParent(aura::Window* parent, bool modal) {
    173     views::Widget* widget =
    174         views::Widget::CreateWindowWithParent(new TestWindow(modal), parent);
    175     widget->Show();
    176     return widget->GetNativeView();
    177   }
    178 
    179   // Show or hide the keyboard.
    180   void ShowKeyboard(bool show) {
    181     keyboard::KeyboardController* keyboard =
    182         keyboard::KeyboardController::GetInstance();
    183     ASSERT_TRUE(keyboard);
    184     if (show == keyboard->keyboard_visible())
    185       return;
    186 
    187     if (show) {
    188       keyboard->ShowKeyboard(true);
    189       if (keyboard->proxy()->GetKeyboardWindow()->bounds().height() == 0) {
    190         keyboard->proxy()->GetKeyboardWindow()->SetBounds(
    191             keyboard::KeyboardBoundsFromWindowBounds(
    192                 keyboard->GetContainerWindow()->bounds(), 100));
    193       }
    194     } else {
    195       keyboard->HideKeyboard(keyboard::KeyboardController::HIDE_REASON_MANUAL);
    196     }
    197 
    198     DCHECK_EQ(show, keyboard->keyboard_visible());
    199   }
    200 
    201 };
    202 
    203 TEST_F(SystemModalContainerLayoutManagerTest, NonModalTransient) {
    204   scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
    205   aura::Window* transient = OpenTestWindowWithParent(parent.get(), false);
    206   TransientWindowObserver destruction_observer;
    207   transient->AddObserver(&destruction_observer);
    208 
    209   EXPECT_EQ(parent.get(), ::wm::GetTransientParent(transient));
    210   EXPECT_EQ(parent->parent(), transient->parent());
    211 
    212   // The transient should be destroyed with its parent.
    213   parent.reset();
    214   EXPECT_TRUE(destruction_observer.destroyed());
    215 }
    216 
    217 TEST_F(SystemModalContainerLayoutManagerTest, ModalTransient) {
    218   scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
    219   // parent should be active.
    220   EXPECT_TRUE(wm::IsActiveWindow(parent.get()));
    221   aura::Window* t1 = OpenTestWindowWithParent(parent.get(), true);
    222 
    223   TransientWindowObserver do1;
    224   t1->AddObserver(&do1);
    225 
    226   EXPECT_EQ(parent.get(), ::wm::GetTransientParent(t1));
    227   EXPECT_EQ(GetModalContainer(), t1->parent());
    228 
    229   // t1 should now be active.
    230   EXPECT_TRUE(wm::IsActiveWindow(t1));
    231 
    232   // Attempting to click the parent should result in no activation change.
    233   ui::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), parent.get());
    234   e1.ClickLeftButton();
    235   EXPECT_TRUE(wm::IsActiveWindow(t1));
    236 
    237   // Now open another modal transient parented to the original modal transient.
    238   aura::Window* t2 = OpenTestWindowWithParent(t1, true);
    239   TransientWindowObserver do2;
    240   t2->AddObserver(&do2);
    241 
    242   EXPECT_TRUE(wm::IsActiveWindow(t2));
    243 
    244   EXPECT_EQ(t1, ::wm::GetTransientParent(t2));
    245   EXPECT_EQ(GetModalContainer(), t2->parent());
    246 
    247   // t2 should still be active, even after clicking on t1.
    248   ui::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), t1);
    249   e2.ClickLeftButton();
    250   EXPECT_TRUE(wm::IsActiveWindow(t2));
    251 
    252   // Both transients should be destroyed with parent.
    253   parent.reset();
    254   EXPECT_TRUE(do1.destroyed());
    255   EXPECT_TRUE(do2.destroyed());
    256 }
    257 
    258 TEST_F(SystemModalContainerLayoutManagerTest, ModalNonTransient) {
    259   scoped_ptr<aura::Window> t1(OpenToplevelTestWindow(true));
    260   // parent should be active.
    261   EXPECT_TRUE(wm::IsActiveWindow(t1.get()));
    262   TransientWindowObserver do1;
    263   t1->AddObserver(&do1);
    264 
    265   EXPECT_EQ(NULL, ::wm::GetTransientParent(t1.get()));
    266   EXPECT_EQ(GetModalContainer(), t1->parent());
    267 
    268   // t1 should now be active.
    269   EXPECT_TRUE(wm::IsActiveWindow(t1.get()));
    270 
    271   // Attempting to click the parent should result in no activation change.
    272   ui::test::EventGenerator e1(Shell::GetPrimaryRootWindow(),
    273                               Shell::GetPrimaryRootWindow());
    274   e1.ClickLeftButton();
    275   EXPECT_TRUE(wm::IsActiveWindow(t1.get()));
    276 
    277   // Now open another modal transient parented to the original modal transient.
    278   aura::Window* t2 = OpenTestWindowWithParent(t1.get(), true);
    279   TransientWindowObserver do2;
    280   t2->AddObserver(&do2);
    281 
    282   EXPECT_TRUE(wm::IsActiveWindow(t2));
    283 
    284   EXPECT_EQ(t1, ::wm::GetTransientParent(t2));
    285   EXPECT_EQ(GetModalContainer(), t2->parent());
    286 
    287   // t2 should still be active, even after clicking on t1.
    288   ui::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), t1.get());
    289   e2.ClickLeftButton();
    290   EXPECT_TRUE(wm::IsActiveWindow(t2));
    291 
    292   // Both transients should be destroyed with parent.
    293   t1.reset();
    294   EXPECT_TRUE(do1.destroyed());
    295   EXPECT_TRUE(do2.destroyed());
    296 }
    297 
    298 // Tests that we can activate an unrelated window after a modal window is closed
    299 // for a window.
    300 TEST_F(SystemModalContainerLayoutManagerTest, CanActivateAfterEndModalSession) {
    301   scoped_ptr<aura::Window> unrelated(OpenToplevelTestWindow(false));
    302   unrelated->SetBounds(gfx::Rect(100, 100, 50, 50));
    303   scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
    304   // parent should be active.
    305   EXPECT_TRUE(wm::IsActiveWindow(parent.get()));
    306 
    307   scoped_ptr<aura::Window> transient(
    308       OpenTestWindowWithParent(parent.get(), true));
    309   // t1 should now be active.
    310   EXPECT_TRUE(wm::IsActiveWindow(transient.get()));
    311 
    312   // Attempting to click the parent should result in no activation change.
    313   ui::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), parent.get());
    314   e1.ClickLeftButton();
    315   EXPECT_TRUE(wm::IsActiveWindow(transient.get()));
    316 
    317   // Now close the transient.
    318   transient->Hide();
    319   TestWindow::CloseTestWindow(transient.release());
    320 
    321   base::RunLoop().RunUntilIdle();
    322 
    323   // parent should now be active again.
    324   EXPECT_TRUE(wm::IsActiveWindow(parent.get()));
    325 
    326   // Attempting to click unrelated should activate it.
    327   ui::test::EventGenerator e2(Shell::GetPrimaryRootWindow(), unrelated.get());
    328   e2.ClickLeftButton();
    329   EXPECT_TRUE(wm::IsActiveWindow(unrelated.get()));
    330 }
    331 
    332 TEST_F(SystemModalContainerLayoutManagerTest, EventFocusContainers) {
    333   // Create a normal window and attempt to receive a click event.
    334   EventTestWindow* main_delegate = new EventTestWindow(false);
    335   scoped_ptr<aura::Window> main(
    336       main_delegate->OpenTestWindowWithContext(CurrentContext()));
    337   EXPECT_TRUE(wm::IsActiveWindow(main.get()));
    338   ui::test::EventGenerator e1(Shell::GetPrimaryRootWindow(), main.get());
    339   e1.ClickLeftButton();
    340   EXPECT_EQ(1, main_delegate->mouse_presses());
    341 
    342   // Create a modal window for the main window and verify that the main window
    343   // no longer receives mouse events.
    344   EventTestWindow* transient_delegate = new EventTestWindow(true);
    345   aura::Window* transient =
    346       transient_delegate->OpenTestWindowWithParent(main.get());
    347   EXPECT_TRUE(wm::IsActiveWindow(transient));
    348   e1.ClickLeftButton();
    349   EXPECT_EQ(1, transient_delegate->mouse_presses());
    350 
    351   for (int block_reason = FIRST_BLOCK_REASON;
    352        block_reason < NUMBER_OF_BLOCK_REASONS;
    353        ++block_reason) {
    354     // Create a window in the lock screen container and ensure that it receives
    355     // the mouse event instead of the modal window (crbug.com/110920).
    356     BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
    357     EventTestWindow* lock_delegate = new EventTestWindow(false);
    358     scoped_ptr<aura::Window> lock(lock_delegate->OpenTestWindowWithParent(
    359         Shell::GetPrimaryRootWindowController()->GetContainer(
    360             ash::kShellWindowId_LockScreenContainer)));
    361     EXPECT_TRUE(wm::IsActiveWindow(lock.get()));
    362     e1.ClickLeftButton();
    363     EXPECT_EQ(1, lock_delegate->mouse_presses());
    364 
    365     // Make sure that a modal container created by the lock screen can still
    366     // receive mouse events.
    367     EventTestWindow* lock_modal_delegate = new EventTestWindow(true);
    368     aura::Window* lock_modal =
    369         lock_modal_delegate->OpenTestWindowWithParent(lock.get());
    370     EXPECT_TRUE(wm::IsActiveWindow(lock_modal));
    371     e1.ClickLeftButton();
    372     // Verify that none of the other containers received any more mouse presses.
    373     EXPECT_EQ(1, lock_modal_delegate->mouse_presses());
    374     EXPECT_EQ(1, lock_delegate->mouse_presses());
    375     EXPECT_EQ(1, main_delegate->mouse_presses());
    376     EXPECT_EQ(1, transient_delegate->mouse_presses());
    377     UnblockUserSession();
    378   }
    379 }
    380 
    381 // Makes sure we don't crash if a modal window is shown while the parent window
    382 // is hidden.
    383 TEST_F(SystemModalContainerLayoutManagerTest, ShowModalWhileHidden) {
    384   // Hide the lock screen.
    385   Shell::GetPrimaryRootWindowController()
    386       ->GetContainer(kShellWindowId_SystemModalContainer)
    387       ->layer()
    388       ->SetOpacity(0);
    389 
    390   // Create a modal window.
    391   scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
    392   scoped_ptr<aura::Window> modal_window(
    393       OpenTestWindowWithParent(parent.get(), true));
    394   parent->Show();
    395   modal_window->Show();
    396 }
    397 
    398 // Verifies we generate a capture lost when showing a modal window.
    399 TEST_F(SystemModalContainerLayoutManagerTest, ChangeCapture) {
    400   views::Widget* widget = views::Widget::CreateWindowWithContext(
    401       new TestWindow(false), CurrentContext());
    402   scoped_ptr<aura::Window> widget_window(widget->GetNativeView());
    403   views::test::CaptureTrackingView* view = new views::test::CaptureTrackingView;
    404   widget->GetContentsView()->AddChildView(view);
    405   view->SetBoundsRect(widget->GetContentsView()->bounds());
    406   widget->Show();
    407 
    408   gfx::Point center(view->width() / 2, view->height() / 2);
    409   views::View::ConvertPointToScreen(view, &center);
    410   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), center);
    411   generator.PressLeftButton();
    412   EXPECT_TRUE(view->got_press());
    413   scoped_ptr<aura::Window> modal_window(
    414       OpenTestWindowWithParent(widget->GetNativeView(), true));
    415   modal_window->Show();
    416   EXPECT_TRUE(view->got_capture_lost());
    417 }
    418 
    419 // Verifies that the window gets moved into the visible screen area upon screen
    420 // resize.
    421 TEST_F(SystemModalContainerLayoutManagerTest, KeepVisible) {
    422   GetModalContainer()->SetBounds(gfx::Rect(0, 0, 1024, 768));
    423   scoped_ptr<aura::Window> main(OpenTestWindowWithParent(GetModalContainer(),
    424                                                          true));
    425   main->SetBounds(gfx::Rect(924, 668, 100, 100));
    426   // We set now the bounds of the root window to something new which will
    427   // Then trigger the repos operation.
    428   GetModalContainer()->SetBounds(gfx::Rect(0, 0, 800, 600));
    429 
    430   gfx::Rect bounds = main->bounds();
    431   EXPECT_EQ(bounds, gfx::Rect(700, 500, 100, 100));
    432 }
    433 
    434 // Verifies that centered windows will remain centered after the visible screen
    435 // area changed.
    436 TEST_F(SystemModalContainerLayoutManagerTest, KeepCentered) {
    437   GetModalContainer()->SetBounds(gfx::Rect(0, 0, 800, 600));
    438   scoped_ptr<aura::Window> main(OpenTestWindowWithParent(GetModalContainer(),
    439                                                          true));
    440   // Center the window.
    441   main->SetBounds(gfx::Rect((800 - 512) / 2, (600 - 256) / 2, 512, 256));
    442 
    443   // We set now the bounds of the root window to something new which will
    444   // Then trigger the reposition operation.
    445   GetModalContainer()->SetBounds(gfx::Rect(0, 0, 1024, 768));
    446 
    447   // The window should still be centered.
    448   gfx::Rect bounds = main->bounds();
    449   EXPECT_EQ(bounds.ToString(), gfx::Rect(256, 256, 512, 256).ToString());
    450 }
    451 
    452 TEST_F(SystemModalContainerLayoutManagerTest, ShowNormalBackgroundOrLocked) {
    453   scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
    454   scoped_ptr<aura::Window> modal_window(
    455       OpenTestWindowWithParent(parent.get(), true));
    456   parent->Show();
    457   modal_window->Show();
    458 
    459   // Normal system modal window.  Shows normal system modal background and not
    460   // locked.
    461   EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
    462   EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds());
    463 
    464   TestWindow::CloseTestWindow(modal_window.release());
    465   EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds());
    466   EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds());
    467 
    468   for (int block_reason = FIRST_BLOCK_REASON;
    469        block_reason < NUMBER_OF_BLOCK_REASONS;
    470        ++block_reason) {
    471     // Normal system modal window while blocked.  Shows blocked system modal
    472     // background.
    473     BlockUserSession(static_cast<UserSessionBlockReason>(block_reason));
    474     scoped_ptr<aura::Window> lock_parent(OpenTestWindowWithParent(
    475         Shell::GetPrimaryRootWindowController()->GetContainer(
    476             ash::kShellWindowId_LockScreenContainer),
    477         false));
    478     scoped_ptr<aura::Window> lock_modal_window(OpenTestWindowWithParent(
    479         lock_parent.get(), true));
    480     lock_parent->Show();
    481     lock_modal_window->Show();
    482     EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds());
    483     EXPECT_TRUE(AllRootWindowsHaveLockedModalBackgrounds());
    484     TestWindow::CloseTestWindow(lock_modal_window.release());
    485 
    486     // Normal system modal window while blocked, but it belongs to the normal
    487     // window.  Shouldn't show blocked system modal background, but normal.
    488     scoped_ptr<aura::Window> modal_window(
    489         OpenTestWindowWithParent(parent.get(), true));
    490     modal_window->Show();
    491     EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
    492     EXPECT_FALSE(AllRootWindowsHaveLockedModalBackgrounds());
    493     TestWindow::CloseTestWindow(modal_window.release());
    494     UnblockUserSession();
    495     // Here we should check the behavior of the locked system modal dialog when
    496     // unlocked, but such case isn't handled very well right now.
    497     // See crbug.com/157660
    498     // TODO(mukai): add the test case when the bug is fixed.
    499   }
    500 }
    501 
    502 TEST_F(SystemModalContainerLayoutManagerTest, MultiDisplays) {
    503   if (!SupportsMultipleDisplays())
    504     return;
    505 
    506   UpdateDisplay("500x500,500x500");
    507 
    508   scoped_ptr<aura::Window> normal(OpenToplevelTestWindow(false));
    509   normal->SetBounds(gfx::Rect(100, 100, 50, 50));
    510 
    511   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    512   EXPECT_EQ(2U, root_windows.size());
    513   aura::Window* container1 = Shell::GetContainer(
    514       root_windows[0], ash::kShellWindowId_SystemModalContainer);
    515   aura::Window* container2 = Shell::GetContainer(
    516       root_windows[1], ash::kShellWindowId_SystemModalContainer);
    517 
    518   scoped_ptr<aura::Window> modal1(
    519       OpenTestWindowWithParent(container1, true));
    520   EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
    521   EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
    522 
    523   scoped_ptr<aura::Window> modal11(
    524       OpenTestWindowWithParent(container1, true));
    525   EXPECT_TRUE(wm::IsActiveWindow(modal11.get()));
    526 
    527   scoped_ptr<aura::Window> modal2(
    528       OpenTestWindowWithParent(container2, true));
    529   EXPECT_TRUE(wm::IsActiveWindow(modal2.get()));
    530 
    531   // Sanity check if they're on the correct containers.
    532   EXPECT_EQ(container1, modal1->parent());
    533   EXPECT_EQ(container1, modal11->parent());
    534   EXPECT_EQ(container2, modal2->parent());
    535 
    536   TestWindow::CloseTestWindow(modal2.release());
    537   EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
    538   EXPECT_TRUE(wm::IsActiveWindow(modal11.get()));
    539 
    540   TestWindow::CloseTestWindow(modal11.release());
    541   EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
    542   EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
    543 
    544   UpdateDisplay("500x500");
    545   EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
    546   EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
    547 
    548   UpdateDisplay("500x500,600x600");
    549   EXPECT_TRUE(AllRootWindowsHaveModalBackgrounds());
    550   EXPECT_TRUE(wm::IsActiveWindow(modal1.get()));
    551 
    552   // No more modal screen.
    553   modal1->Hide();
    554   TestWindow::CloseTestWindow(modal1.release());
    555   EXPECT_FALSE(AllRootWindowsHaveModalBackgrounds());
    556   EXPECT_TRUE(wm::IsActiveWindow(normal.get()));
    557 }
    558 
    559 // Test that with the visible keyboard, an existing system modal dialog gets
    560 // positioned into the visible area.
    561 TEST_F(SystemModalContainerLayoutManagerTest,
    562        SystemModalDialogGetPushedFromKeyboard) {
    563   const gfx::Rect& container_bounds = GetModalContainer()->bounds();
    564   // Place the window at the bottom of the screen.
    565   gfx::Size modal_size(100, 100);
    566   gfx::Point modal_origin = gfx::Point(
    567       (container_bounds.right() - modal_size.width()) / 2,  // X centered
    568       container_bounds.bottom() - modal_size.height());     // at bottom
    569   gfx::Rect modal_bounds = gfx::Rect(modal_origin, modal_size);
    570 
    571   // Create a modal window.
    572   scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
    573   scoped_ptr<aura::Window> modal_window(
    574       OpenTestWindowWithParent(parent.get(), true));
    575   modal_window->SetBounds(modal_bounds);
    576   parent->Show();
    577   modal_window->Show();
    578 
    579   EXPECT_EQ(modal_bounds.ToString(), modal_window->bounds().ToString());
    580 
    581   // The keyboard gets shown and the dialog should get pushed.
    582   ShowKeyboard(true);
    583   EXPECT_NE(modal_bounds.ToString(), modal_window->bounds().ToString());
    584   EXPECT_GT(modal_bounds.y(), modal_window->bounds().y());
    585   EXPECT_EQ(modal_size.ToString(), modal_window->bounds().size().ToString());
    586   EXPECT_EQ(modal_origin.x(), modal_window->bounds().x());
    587 
    588   // After the keyboard is gone, the window will remain where it was.
    589   ShowKeyboard(false);
    590   EXPECT_NE(modal_bounds.ToString(), modal_window->bounds().ToString());
    591   EXPECT_EQ(modal_size.ToString(), modal_window->bounds().size().ToString());
    592   EXPECT_EQ(modal_origin.x(), modal_window->bounds().x());
    593 }
    594 
    595 // Test that windows will not get cropped through the visible virtual keyboard -
    596 // if centered.
    597 TEST_F(SystemModalContainerLayoutManagerTest,
    598        SystemModalDialogGetPushedButNotCroppedFromKeyboard) {
    599   const gfx::Rect& container_bounds = GetModalContainer()->bounds();
    600   const gfx::Size screen_size = Shell::GetPrimaryRootWindow()->bounds().size();
    601   // Place the window at the bottom of the screen.
    602   gfx::Size modal_size(100, screen_size.height() - 70);
    603   gfx::Point modal_origin = gfx::Point(
    604       (container_bounds.right() - modal_size.width()) / 2,  // X centered
    605       container_bounds.bottom() - modal_size.height());     // at bottom
    606   gfx::Rect modal_bounds = gfx::Rect(modal_origin, modal_size);
    607 
    608   // Create a modal window.
    609   scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
    610   scoped_ptr<aura::Window> modal_window(
    611       OpenTestWindowWithParent(parent.get(), true));
    612   modal_window->SetBounds(modal_bounds);
    613   parent->Show();
    614   modal_window->Show();
    615 
    616   EXPECT_EQ(modal_bounds.ToString(), modal_window->bounds().ToString());
    617 
    618   // The keyboard gets shown and the dialog should get pushed up, but not get
    619   // cropped (and aligned to the top).
    620   ShowKeyboard(true);
    621   EXPECT_EQ(modal_size.ToString(), modal_window->bounds().size().ToString());
    622   EXPECT_EQ(modal_origin.x(), modal_window->bounds().x());
    623   EXPECT_EQ(0, modal_window->bounds().y());
    624 
    625   ShowKeyboard(false);
    626 }
    627 
    628 // Test that windows will not get cropped through the visible virtual keyboard -
    629 // if not centered.
    630 TEST_F(SystemModalContainerLayoutManagerTest,
    631        SystemModalDialogGetPushedButNotCroppedFromKeyboardIfNotCentered) {
    632   const gfx::Size screen_size = Shell::GetPrimaryRootWindow()->bounds().size();
    633   // Place the window at the bottom of the screen.
    634   gfx::Size modal_size(100, screen_size.height() - 70);
    635   gfx::Point modal_origin = gfx::Point(10, 20);
    636   gfx::Rect modal_bounds = gfx::Rect(modal_origin, modal_size);
    637 
    638   // Create a modal window.
    639   scoped_ptr<aura::Window> parent(OpenToplevelTestWindow(false));
    640   scoped_ptr<aura::Window> modal_window(
    641       OpenTestWindowWithParent(parent.get(), true));
    642   modal_window->SetBounds(modal_bounds);
    643   parent->Show();
    644   modal_window->Show();
    645 
    646   EXPECT_EQ(modal_bounds.ToString(), modal_window->bounds().ToString());
    647 
    648   // The keyboard gets shown and the dialog should get pushed up, but not get
    649   // cropped (and aligned to the top).
    650   ShowKeyboard(true);
    651   EXPECT_EQ(modal_size.ToString(), modal_window->bounds().size().ToString());
    652   EXPECT_EQ(modal_origin.x(), modal_window->bounds().x());
    653   EXPECT_EQ(0, modal_window->bounds().y());
    654 
    655   ShowKeyboard(false);
    656 }
    657 
    658 }  // namespace test
    659 }  // namespace ash
    660