Home | History | Annotate | Download | only in wm
      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 "ash/root_window_controller.h"
      6 #include "ash/screen_util.h"
      7 #include "ash/shell.h"
      8 #include "ash/shell_window_ids.h"
      9 #include "ash/test/ash_test_base.h"
     10 #include "ash/wm/window_state.h"
     11 #include "base/basictypes.h"
     12 #include "base/command_line.h"
     13 #include "ui/aura/client/aura_constants.h"
     14 #include "ui/aura/window.h"
     15 #include "ui/gfx/screen.h"
     16 #include "ui/keyboard/keyboard_controller.h"
     17 #include "ui/keyboard/keyboard_controller_proxy.h"
     18 #include "ui/keyboard/keyboard_switches.h"
     19 #include "ui/keyboard/keyboard_util.h"
     20 #include "ui/views/widget/widget.h"
     21 #include "ui/views/widget/widget_delegate.h"
     22 
     23 namespace ash {
     24 namespace test {
     25 
     26 namespace {
     27 
     28 const int kVirtualKeyboardHeight = 100;
     29 
     30 // A login implementation of WidgetDelegate.
     31 class LoginTestWidgetDelegate : public views::WidgetDelegate {
     32  public:
     33   explicit LoginTestWidgetDelegate(views::Widget* widget) : widget_(widget) {
     34   }
     35   virtual ~LoginTestWidgetDelegate() {}
     36 
     37   // Overridden from WidgetDelegate:
     38   virtual void DeleteDelegate() OVERRIDE {
     39     delete this;
     40   }
     41   virtual views::Widget* GetWidget() OVERRIDE {
     42     return widget_;
     43   }
     44   virtual const views::Widget* GetWidget() const OVERRIDE {
     45     return widget_;
     46   }
     47   virtual bool CanActivate() const OVERRIDE {
     48     return true;
     49   }
     50   virtual bool ShouldAdvanceFocusToTopLevelWidget() const OVERRIDE {
     51     return true;
     52   }
     53 
     54  private:
     55   views::Widget* widget_;
     56 
     57   DISALLOW_COPY_AND_ASSIGN(LoginTestWidgetDelegate);
     58 };
     59 
     60 }  // namespace
     61 
     62 class LockLayoutManagerTest : public AshTestBase {
     63  public:
     64   virtual void SetUp() OVERRIDE {
     65     // Allow a virtual keyboard (and initialize it per default).
     66     CommandLine::ForCurrentProcess()->AppendSwitch(
     67         keyboard::switches::kEnableVirtualKeyboard);
     68     AshTestBase::SetUp();
     69     Shell::GetPrimaryRootWindowController()->ActivateKeyboard(
     70         keyboard::KeyboardController::GetInstance());
     71   }
     72 
     73   virtual void TearDown() OVERRIDE {
     74     Shell::GetPrimaryRootWindowController()->DeactivateKeyboard(
     75         keyboard::KeyboardController::GetInstance());
     76     AshTestBase::TearDown();
     77   }
     78 
     79   aura::Window* CreateTestLoginWindow(views::Widget::InitParams params,
     80                                       bool use_delegate) {
     81     aura::Window* parent = Shell::GetPrimaryRootWindowController()->
     82         GetContainer(ash::kShellWindowId_LockScreenContainer);
     83     params.parent = parent;
     84     views::Widget* widget = new views::Widget;
     85     if (use_delegate)
     86       params.delegate = new LoginTestWidgetDelegate(widget);
     87     widget->Init(params);
     88     widget->Show();
     89     aura::Window* window = widget->GetNativeView();
     90     return window;
     91   }
     92 
     93   // Show or hide the keyboard.
     94   void ShowKeyboard(bool show) {
     95     keyboard::KeyboardController* keyboard =
     96         keyboard::KeyboardController::GetInstance();
     97     ASSERT_TRUE(keyboard);
     98     if (show == keyboard->keyboard_visible())
     99       return;
    100 
    101     if (show) {
    102       keyboard->ShowKeyboard(true);
    103       if (keyboard->proxy()->GetKeyboardWindow()->bounds().height() == 0) {
    104         keyboard->proxy()->GetKeyboardWindow()->SetBounds(
    105             keyboard::KeyboardBoundsFromWindowBounds(
    106                 keyboard->GetContainerWindow()->bounds(),
    107                 kVirtualKeyboardHeight));
    108       }
    109     } else {
    110       keyboard->HideKeyboard(keyboard::KeyboardController::HIDE_REASON_MANUAL);
    111     }
    112 
    113     DCHECK_EQ(show, keyboard->keyboard_visible());
    114   }
    115 };
    116 
    117 TEST_F(LockLayoutManagerTest, NorwmalWindowBoundsArePreserved) {
    118   gfx::Rect screen_bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds();
    119 
    120   views::Widget::InitParams widget_params(
    121       views::Widget::InitParams::TYPE_WINDOW);
    122   const gfx::Rect bounds = gfx::Rect(10, 10, 300, 300);
    123   widget_params.bounds = bounds;
    124   scoped_ptr<aura::Window> window(
    125       CreateTestLoginWindow(widget_params, false /* use_delegate */));
    126   EXPECT_EQ(bounds.ToString(), window->GetBoundsInScreen().ToString());
    127 
    128   gfx::Rect work_area =
    129       ScreenUtil::GetDisplayWorkAreaBoundsInParent(window.get());
    130   window->SetBounds(work_area);
    131 
    132   EXPECT_EQ(work_area.ToString(), window->GetBoundsInScreen().ToString());
    133   EXPECT_NE(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
    134 
    135   const gfx::Rect bounds2 = gfx::Rect(100, 100, 200, 200);
    136   window->SetBounds(bounds2);
    137   EXPECT_EQ(bounds2.ToString(), window->GetBoundsInScreen().ToString());
    138 }
    139 
    140 TEST_F(LockLayoutManagerTest, MaximizedFullscreenWindowBoundsAreEqualToScreen) {
    141   gfx::Rect screen_bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds();
    142 
    143   views::Widget::InitParams widget_params(
    144       views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    145   widget_params.show_state = ui::SHOW_STATE_MAXIMIZED;
    146   const gfx::Rect bounds = gfx::Rect(10, 10, 300, 300);
    147   widget_params.bounds = bounds;
    148   // Maximized TYPE_WINDOW_FRAMELESS windows needs a delegate defined otherwise
    149   // it won't get initial SetBounds event.
    150   scoped_ptr<aura::Window> maximized_window(
    151       CreateTestLoginWindow(widget_params, true /* use_delegate */));
    152 
    153   widget_params.show_state = ui::SHOW_STATE_FULLSCREEN;
    154   widget_params.delegate = NULL;
    155   scoped_ptr<aura::Window> fullscreen_window(
    156       CreateTestLoginWindow(widget_params, false  /* use_delegate */));
    157 
    158   EXPECT_EQ(screen_bounds.ToString(),
    159             maximized_window->GetBoundsInScreen().ToString());
    160   EXPECT_EQ(screen_bounds.ToString(),
    161             fullscreen_window->GetBoundsInScreen().ToString());
    162 
    163   gfx::Rect work_area =
    164       ScreenUtil::GetDisplayWorkAreaBoundsInParent(maximized_window.get());
    165   maximized_window->SetBounds(work_area);
    166 
    167   EXPECT_NE(work_area.ToString(),
    168             maximized_window->GetBoundsInScreen().ToString());
    169   EXPECT_EQ(screen_bounds.ToString(),
    170             maximized_window->GetBoundsInScreen().ToString());
    171 
    172   work_area =
    173       ScreenUtil::GetDisplayWorkAreaBoundsInParent(fullscreen_window.get());
    174   fullscreen_window->SetBounds(work_area);
    175   EXPECT_NE(work_area.ToString(),
    176             fullscreen_window->GetBoundsInScreen().ToString());
    177   EXPECT_EQ(screen_bounds.ToString(),
    178             fullscreen_window->GetBoundsInScreen().ToString());
    179 
    180   const gfx::Rect bounds2 = gfx::Rect(100, 100, 200, 200);
    181   maximized_window->SetBounds(bounds2);
    182   fullscreen_window->SetBounds(bounds2);
    183   EXPECT_EQ(screen_bounds.ToString(),
    184             maximized_window->GetBoundsInScreen().ToString());
    185   EXPECT_EQ(screen_bounds.ToString(),
    186             fullscreen_window->GetBoundsInScreen().ToString());
    187 }
    188 
    189 TEST_F(LockLayoutManagerTest, KeyboardBounds) {
    190   gfx::Rect screen_bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds();
    191 
    192   views::Widget::InitParams widget_params(
    193       views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    194   widget_params.show_state = ui::SHOW_STATE_FULLSCREEN;
    195   scoped_ptr<aura::Window> window(
    196       CreateTestLoginWindow(widget_params, false /* use_delegate */));
    197 
    198   EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
    199 
    200   // When virtual keyboard overscroll is enabled keyboard bounds should not
    201   // affect window bounds.
    202   keyboard::SetKeyboardOverscrollOverride(
    203        keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_ENABLED);
    204   ShowKeyboard(true);
    205   EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
    206   ShowKeyboard(false);
    207 
    208   // When virtual keyboard overscroll is disabled keyboard bounds do
    209   // affect window bounds.
    210   keyboard::SetKeyboardOverscrollOverride(
    211        keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_DISABLED);
    212   ShowKeyboard(true);
    213   keyboard::KeyboardController* keyboard =
    214         keyboard::KeyboardController::GetInstance();
    215   gfx::Rect target_bounds(screen_bounds);
    216   target_bounds.set_height(target_bounds.height() -
    217       keyboard->proxy()->GetKeyboardWindow()->bounds().height());
    218   EXPECT_EQ(target_bounds.ToString(), window->GetBoundsInScreen().ToString());
    219   ShowKeyboard(false);
    220 
    221   keyboard::SetKeyboardOverscrollOverride(
    222       keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_NONE);
    223 }
    224 
    225 TEST_F(LockLayoutManagerTest, MultipleMonitors) {
    226   if (!SupportsMultipleDisplays())
    227     return;
    228 
    229   UpdateDisplay("300x400,400x500");
    230   gfx::Rect screen_bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds();
    231   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
    232 
    233   views::Widget::InitParams widget_params(
    234       views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    235   widget_params.show_state = ui::SHOW_STATE_FULLSCREEN;
    236   scoped_ptr<aura::Window> window(
    237       CreateTestLoginWindow(widget_params, false /* use_delegate */));
    238   window->SetProperty(aura::client::kCanMaximizeKey, true);
    239 
    240   EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
    241 
    242   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    243 
    244   wm::WindowState* window_state = wm::GetWindowState(window.get());
    245   window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40));
    246 
    247   // Maximize the window with as the restore bounds is inside 2nd display but
    248   // lock container windows are always on primary display.
    249   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
    250   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    251   EXPECT_EQ("0,0 300x400", window->GetBoundsInScreen().ToString());
    252 
    253   window_state->Restore();
    254   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    255   EXPECT_EQ("0,0 300x400", window->GetBoundsInScreen().ToString());
    256 
    257   window_state->SetRestoreBoundsInScreen(gfx::Rect(280, 0, 30, 40));
    258   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
    259   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    260   EXPECT_EQ("0,0 300x400", window->GetBoundsInScreen().ToString());
    261 
    262   window_state->Restore();
    263   EXPECT_EQ(root_windows[0], window->GetRootWindow());
    264   EXPECT_EQ("0,0 300x400", window->GetBoundsInScreen().ToString());
    265 
    266   gfx::Rect work_area =
    267       ScreenUtil::GetDisplayWorkAreaBoundsInParent(window.get());
    268   window->SetBounds(work_area);
    269   // Usually work_area takes Shelf into account but that doesn't affect
    270   // LockScreen container windows.
    271   EXPECT_NE(work_area.ToString(), window->GetBoundsInScreen().ToString());
    272   EXPECT_EQ(screen_bounds.ToString(), window->GetBoundsInScreen().ToString());
    273 }
    274 
    275 }  // namespace test
    276 }  // namespace ash
    277