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/base_layout_manager.h"
      6 
      7 #include "ash/screen_ash.h"
      8 #include "ash/session_state_delegate.h"
      9 #include "ash/shelf/shelf_layout_manager.h"
     10 #include "ash/shell.h"
     11 #include "ash/shell_window_ids.h"
     12 #include "ash/test/ash_test_base.h"
     13 #include "ash/wm/property_util.h"
     14 #include "ash/wm/window_util.h"
     15 #include "ash/wm/workspace/workspace_window_resizer.h"
     16 #include "base/basictypes.h"
     17 #include "base/compiler_specific.h"
     18 #include "ui/aura/client/aura_constants.h"
     19 #include "ui/aura/root_window.h"
     20 #include "ui/aura/test/test_windows.h"
     21 #include "ui/aura/window.h"
     22 #include "ui/base/ui_base_types.h"
     23 #include "ui/gfx/insets.h"
     24 #include "ui/gfx/screen.h"
     25 
     26 namespace ash {
     27 
     28 namespace {
     29 
     30 class BaseLayoutManagerTest : public test::AshTestBase {
     31  public:
     32   BaseLayoutManagerTest() {}
     33   virtual ~BaseLayoutManagerTest() {}
     34 
     35   virtual void SetUp() OVERRIDE {
     36     test::AshTestBase::SetUp();
     37     UpdateDisplay("800x600");
     38     aura::Window* default_container = Shell::GetContainer(
     39         Shell::GetPrimaryRootWindow(),
     40         internal::kShellWindowId_DefaultContainer);
     41     default_container->SetLayoutManager(new internal::BaseLayoutManager(
     42         Shell::GetPrimaryRootWindow()));
     43   }
     44 
     45   aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
     46     return CreateTestWindowInShellWithBounds(bounds);
     47   }
     48 
     49  private:
     50   DISALLOW_COPY_AND_ASSIGN(BaseLayoutManagerTest);
     51 };
     52 
     53 // Tests normal->maximize->normal.
     54 TEST_F(BaseLayoutManagerTest, Maximize) {
     55   gfx::Rect bounds(100, 100, 200, 200);
     56   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
     57   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
     58   // Maximized window fills the work area, not the whole display.
     59   EXPECT_EQ(
     60       ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(),
     61       window->bounds().ToString());
     62   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
     63   EXPECT_EQ(bounds.ToString(), window->bounds().ToString());
     64 }
     65 
     66 // Tests normal->minimize->normal.
     67 TEST_F(BaseLayoutManagerTest, Minimize) {
     68   gfx::Rect bounds(100, 100, 200, 200);
     69   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
     70   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
     71   // Note: Currently minimize doesn't do anything except set the state.
     72   // See crbug.com/104571.
     73   EXPECT_EQ(bounds.ToString(), window->bounds().ToString());
     74   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
     75   EXPECT_EQ(bounds.ToString(), window->bounds().ToString());
     76 }
     77 
     78 // A WindowDelegate which sets the focus when the window
     79 // becomes visible.
     80 class FocusDelegate : public aura::test::TestWindowDelegate {
     81  public:
     82   FocusDelegate()
     83       : window_(NULL),
     84         show_state_(ui::SHOW_STATE_END) {
     85   }
     86   virtual ~FocusDelegate() {}
     87 
     88   void set_window(aura::Window* window) { window_ = window; }
     89 
     90   // aura::test::TestWindowDelegate overrides:
     91   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
     92     if (window_) {
     93       if (visible)
     94         window_->Focus();
     95       show_state_ = window_->GetProperty(aura::client::kShowStateKey);
     96     }
     97   }
     98 
     99   ui::WindowShowState GetShowStateAndReset() {
    100     ui::WindowShowState ret = show_state_;
    101     show_state_ = ui::SHOW_STATE_END;
    102     return ret;
    103   }
    104 
    105  private:
    106   aura::Window* window_;
    107   ui::WindowShowState show_state_;
    108 
    109   DISALLOW_COPY_AND_ASSIGN(FocusDelegate);
    110 };
    111 
    112 // Make sure that the window's show state is correct in
    113 // |WindowDelegate::OnWindowTargetVisibilityChanged|, and setting
    114 // focus in this callback doesn't cause DCHECK error.  See
    115 // crbug.com/168383.
    116 TEST_F(BaseLayoutManagerTest, FocusDuringUnminimize) {
    117   FocusDelegate delegate;
    118   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
    119       &delegate, 0, gfx::Rect(100, 100, 100, 100)));
    120   delegate.set_window(window.get());
    121   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
    122   EXPECT_FALSE(window->IsVisible());
    123   EXPECT_EQ(ui::SHOW_STATE_MINIMIZED, delegate.GetShowStateAndReset());
    124   window->Show();
    125   EXPECT_TRUE(window->IsVisible());
    126   EXPECT_EQ(ui::SHOW_STATE_DEFAULT, delegate.GetShowStateAndReset());
    127 }
    128 
    129 // Tests maximized window size during root window resize.
    130 TEST_F(BaseLayoutManagerTest, MaximizeRootWindowResize) {
    131   gfx::Rect bounds(100, 100, 200, 200);
    132   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
    133   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
    134   gfx::Rect initial_work_area_bounds =
    135       ScreenAsh::GetMaximizedWindowBoundsInParent(window.get());
    136   EXPECT_EQ(initial_work_area_bounds.ToString(), window->bounds().ToString());
    137   // Enlarge the root window.  We should still match the work area size.
    138   UpdateDisplay("900x700");
    139   EXPECT_EQ(
    140       ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(),
    141       window->bounds().ToString());
    142   EXPECT_NE(
    143       initial_work_area_bounds.ToString(),
    144       ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString());
    145 }
    146 
    147 // Tests normal->fullscreen->normal.
    148 TEST_F(BaseLayoutManagerTest, Fullscreen) {
    149   gfx::Rect bounds(100, 100, 200, 200);
    150   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
    151   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
    152   // Fullscreen window fills the whole display.
    153   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
    154                 window.get()).bounds().ToString(),
    155             window->bounds().ToString());
    156   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
    157   EXPECT_EQ(bounds.ToString(), window->bounds().ToString());
    158 }
    159 
    160 // Tests fullscreen window size during root window resize.
    161 TEST_F(BaseLayoutManagerTest, FullscreenRootWindowResize) {
    162   gfx::Rect bounds(100, 100, 200, 200);
    163   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
    164   // Fullscreen window fills the whole display.
    165   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
    166   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
    167                 window.get()).bounds().ToString(),
    168             window->bounds().ToString());
    169   // Enlarge the root window.  We should still match the display size.
    170   UpdateDisplay("800x600");
    171   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
    172                 window.get()).bounds().ToString(),
    173             window->bounds().ToString());
    174 }
    175 
    176 // Fails on Mac only.  Need to be implemented.  http://crbug.com/111279.
    177 #if defined(OS_MACOSX)
    178 #define MAYBE_RootWindowResizeShrinksWindows \
    179   DISABLED_RootWindowResizeShrinksWindows
    180 #else
    181 #define MAYBE_RootWindowResizeShrinksWindows RootWindowResizeShrinksWindows
    182 #endif
    183 // Tests that when the screen gets smaller the windows aren't bigger than
    184 // the screen.
    185 TEST_F(BaseLayoutManagerTest, MAYBE_RootWindowResizeShrinksWindows) {
    186   scoped_ptr<aura::Window> window(
    187       CreateTestWindow(gfx::Rect(10, 20, 500, 400)));
    188   gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
    189       window.get()).work_area();
    190   // Invariant: Window is smaller than work area.
    191   EXPECT_LE(window->bounds().width(), work_area.width());
    192   EXPECT_LE(window->bounds().height(), work_area.height());
    193 
    194   // Make the root window narrower than our window.
    195   UpdateDisplay("300x400");
    196   work_area = Shell::GetScreen()->GetDisplayNearestWindow(
    197       window.get()).work_area();
    198   EXPECT_LE(window->bounds().width(), work_area.width());
    199   EXPECT_LE(window->bounds().height(), work_area.height());
    200 
    201   // Make the root window shorter than our window.
    202   UpdateDisplay("300x200");
    203   work_area = Shell::GetScreen()->GetDisplayNearestWindow(
    204       window.get()).work_area();
    205   EXPECT_LE(window->bounds().width(), work_area.width());
    206   EXPECT_LE(window->bounds().height(), work_area.height());
    207 
    208   // Enlarging the root window does not change the window bounds.
    209   gfx::Rect old_bounds = window->bounds();
    210   UpdateDisplay("800x600");
    211   EXPECT_EQ(old_bounds.width(), window->bounds().width());
    212   EXPECT_EQ(old_bounds.height(), window->bounds().height());
    213 }
    214 
    215 // Tests that a maximized window with too-large restore bounds will be restored
    216 // to smaller than the full work area.
    217 TEST_F(BaseLayoutManagerTest, BoundsWithScreenEdgeVisible) {
    218   // Create a window with bounds that fill the screen.
    219   gfx::Rect bounds = Shell::GetScreen()->GetPrimaryDisplay().bounds();
    220   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
    221   // Maximize it, which writes the old bounds to restore bounds.
    222   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
    223   // Restore it.
    224   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
    225   // It should have the default maximized window bounds, inset by the grid size.
    226   int grid_size = internal::WorkspaceWindowResizer::kScreenEdgeInset;
    227   gfx::Rect max_bounds =
    228       ash::ScreenAsh::GetMaximizedWindowBoundsInParent(window.get());
    229   max_bounds.Inset(grid_size, grid_size);
    230   EXPECT_EQ(max_bounds.ToString(), window->bounds().ToString());
    231 }
    232 
    233 // Verifies maximizing sets the restore bounds, and restoring
    234 // restores the bounds.
    235 TEST_F(BaseLayoutManagerTest, MaximizeSetsRestoreBounds) {
    236   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
    237 
    238   // Maximize it, which will keep the previous restore bounds.
    239   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
    240   EXPECT_EQ("1,2 3x4", GetRestoreBoundsInParent(window.get()).ToString());
    241 
    242   // Restore it, which should restore bounds and reset restore bounds.
    243   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
    244   EXPECT_EQ("1,2 3x4", window->bounds().ToString());
    245   EXPECT_TRUE(GetRestoreBoundsInScreen(window.get()) == NULL);
    246 }
    247 
    248 // Verifies maximizing keeps the restore bounds if set.
    249 TEST_F(BaseLayoutManagerTest, MaximizeResetsRestoreBounds) {
    250   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
    251   SetRestoreBoundsInParent(window.get(), gfx::Rect(10, 11, 12, 13));
    252 
    253   // Maximize it, which will keep the previous restore bounds.
    254   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
    255   EXPECT_EQ("10,11 12x13", GetRestoreBoundsInParent(window.get()).ToString());
    256 }
    257 
    258 // Verifies that the restore bounds do not get reset when restoring to a
    259 // maximzied state from a minimized state.
    260 TEST_F(BaseLayoutManagerTest, BoundsAfterRestoringToMaximizeFromMinimize) {
    261   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
    262   gfx::Rect bounds(10, 15, 25, 35);
    263   window->SetBounds(bounds);
    264 
    265   // Maximize it, which should reset restore bounds.
    266   wm::MaximizeWindow(window.get());
    267   EXPECT_EQ(bounds.ToString(),
    268             GetRestoreBoundsInParent(window.get()).ToString());
    269 
    270   // Minimize the window. The restore bounds should not change.
    271   wm::MinimizeWindow(window.get());
    272   EXPECT_EQ(bounds.ToString(),
    273             GetRestoreBoundsInParent(window.get()).ToString());
    274 
    275   // Show the window again. The window should be maximized, and the restore
    276   // bounds should not change.
    277   window->Show();
    278   EXPECT_EQ(bounds.ToString(),
    279             GetRestoreBoundsInParent(window.get()).ToString());
    280   EXPECT_TRUE(wm::IsWindowMaximized(window.get()));
    281 
    282   wm::RestoreWindow(window.get());
    283   EXPECT_EQ(bounds.ToString(), window->bounds().ToString());
    284 }
    285 
    286 // Verify if the window is not resized during screen lock. See: crbug.com/173127
    287 TEST_F(BaseLayoutManagerTest, NotResizeWhenScreenIsLocked) {
    288   SetCanLockScreen(true);
    289   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
    290   // window with AlwaysOnTop will be managed by BaseLayoutManager.
    291   window->SetProperty(aura::client::kAlwaysOnTopKey, true);
    292   window->Show();
    293 
    294   internal::ShelfLayoutManager* shelf =
    295       internal::ShelfLayoutManager::ForLauncher(window.get());
    296   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    297 
    298   window->SetBounds(ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()));
    299   gfx::Rect window_bounds = window->bounds();
    300   EXPECT_EQ(
    301       ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(),
    302       window_bounds.ToString());
    303 
    304   Shell::GetInstance()->session_state_delegate()->LockScreen();
    305   shelf->UpdateVisibilityState();
    306   EXPECT_NE(
    307       ScreenAsh::GetMaximizedWindowBoundsInParent(window.get()).ToString(),
    308       window_bounds.ToString());
    309 
    310   Shell::GetInstance()->session_state_delegate()->UnlockScreen();
    311   shelf->UpdateVisibilityState();
    312   EXPECT_EQ(window_bounds.ToString(), window->bounds().ToString());
    313 }
    314 
    315 }  // namespace
    316 }  // namespace ash
    317