window_state_unittest.cc revision 23730a6e56a168d1879203e4b3819bb36e3d8f1f
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/wm/window_state.h"
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/screen_util.h"
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/shell.h"
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/test/ash_test_base.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/wm/window_state.h"
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ash/wm/wm_event.h"
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/test/test_window_delegate.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window.h"
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace ash {
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace wm {
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace {
1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)class AlwaysMaximizeTestState : public WindowState::State {
2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public:
2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  explicit AlwaysMaximizeTestState(WindowStateType initial_state_type)
2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      : state_type_(initial_state_type) {}
2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual ~AlwaysMaximizeTestState() {}
2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // WindowState::State overrides:
2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual void OnWMEvent(WindowState* window_state,
2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                         const WMEvent* event) OVERRIDE {
2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // We don't do anything here.
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual WindowStateType GetType() const OVERRIDE {
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return state_type_;
3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual void AttachState(
3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      WindowState* window_state,
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      WindowState::State* previous_state) OVERRIDE {
3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // We always maximize.
3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    if (state_type_ != WINDOW_STATE_TYPE_MAXIMIZED) {
3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      window_state->Maximize();
3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      state_type_ = WINDOW_STATE_TYPE_MAXIMIZED;
4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    }
4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual void DetachState(WindowState* window_state) OVERRIDE {}
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private:
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WindowStateType state_type_;
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AlwaysMaximizeTestState);
4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)};
4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}  // namespace
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)typedef test::AshTestBase WindowStateTest;
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Test that a window gets properly snapped to the display's edges in a
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// multi monitor environment.
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(WindowStateTest, SnapWindowBasic) {
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!SupportsMultipleDisplays())
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  UpdateDisplay("0+0-500x400, 0+500-600x400");
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const gfx::Rect kPrimaryDisplayWorkAreaBounds =
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const gfx::Rect kSecondaryDisplayWorkAreaBounds =
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ScreenUtil::GetSecondaryDisplay().work_area();
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<aura::Window> window(
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WindowState* window_state = GetWindowState(window.get());
6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const WMEvent snap_left(WM_EVENT_SNAP_LEFT);
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->OnWMEvent(&snap_left);
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect expected = gfx::Rect(
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kPrimaryDisplayWorkAreaBounds.x(),
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kPrimaryDisplayWorkAreaBounds.y(),
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kPrimaryDisplayWorkAreaBounds.width() / 2,
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kPrimaryDisplayWorkAreaBounds.height());
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const WMEvent snap_right(WM_EVENT_SNAP_RIGHT);
79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->OnWMEvent(&snap_right);
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  expected.set_x(kPrimaryDisplayWorkAreaBounds.right() - expected.width());
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Move the window to the secondary display.
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100),
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                            ScreenUtil::GetSecondaryDisplay());
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->OnWMEvent(&snap_right);
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  expected = gfx::Rect(
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kSecondaryDisplayWorkAreaBounds.x() +
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          kSecondaryDisplayWorkAreaBounds.width() / 2,
91a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kSecondaryDisplayWorkAreaBounds.y(),
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kSecondaryDisplayWorkAreaBounds.width() / 2,
93a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kSecondaryDisplayWorkAreaBounds.height());
94a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->OnWMEvent(&snap_left);
97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  expected.set_x(kSecondaryDisplayWorkAreaBounds.x());
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Test how the minimum and maximum size specified by the aura::WindowDelegate
102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// affect snapping.
103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(WindowStateTest, SnapWindowMinimumSize) {
104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!SupportsHostWindowResize())
105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  UpdateDisplay("0+0-600x900");
108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const gfx::Rect kWorkAreaBounds =
109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  aura::test::TestWindowDelegate delegate;
112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      &delegate, -1, gfx::Rect(0, 100, kWorkAreaBounds.width() - 1, 100)));
114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // It should be possible to snap a window with a minimum size.
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  delegate.set_minimum_size(gfx::Size(kWorkAreaBounds.width() - 1, 0));
11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WindowState* window_state = GetWindowState(window.get());
118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(window_state->CanSnap());
11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const WMEvent snap_right(WM_EVENT_SNAP_RIGHT);
120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->OnWMEvent(&snap_right);
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x() + 1,
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 kWorkAreaBounds.y(),
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 kWorkAreaBounds.width() - 1,
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 kWorkAreaBounds.height());
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // It should not be possible to snap a window with a maximum size.
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  delegate.set_minimum_size(gfx::Size());
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  delegate.set_maximum_size(gfx::Size(kWorkAreaBounds.width() - 1, INT_MAX));
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_FALSE(window_state->CanSnap());
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Test that setting the bounds of a snapped window keeps its snapped.
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(WindowStateTest, SnapWindowSetBounds) {
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!SupportsHostWindowResize())
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return;
137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  UpdateDisplay("0+0-900x600");
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const gfx::Rect kWorkAreaBounds =
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<aura::Window> window(
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WindowState* window_state = GetWindowState(window.get());
14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const WMEvent snap_left(WM_EVENT_SNAP_LEFT);
146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->OnWMEvent(&snap_left);
147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(),
149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 kWorkAreaBounds.y(),
150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 kWorkAreaBounds.width() / 2,
151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                 kWorkAreaBounds.height());
152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Snapped windows can have any width.
155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  expected.set_width(500);
156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window->SetBounds(gfx::Rect(10, 10, 500, 300));
157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Test that snapping left/right preserves the restore bounds.
162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(WindowStateTest, RestoreBounds) {
163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<aura::Window> window(
164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
16523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WindowState* window_state = GetWindowState(window.get());
166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(window_state->IsNormalStateType());
168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // 1) Start with restored window with restore bounds set.
170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect restore_bounds = window->GetBoundsInScreen();
171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  restore_bounds.set_width(restore_bounds.width() + 1);
172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->SetRestoreBoundsInScreen(restore_bounds);
17323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const WMEvent snap_left(WM_EVENT_SNAP_LEFT);
174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->OnWMEvent(&snap_left);
17523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const WMEvent snap_right(WM_EVENT_SNAP_RIGHT);
176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->OnWMEvent(&snap_right);
177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_NE(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(restore_bounds.ToString(),
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            window_state->GetRestoreBoundsInScreen().ToString());
180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->Restore();
181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // 2) Start with restored bounds set as a result of maximizing the window.
184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->Maximize();
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect maximized_bounds = window->GetBoundsInScreen();
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_NE(maximized_bounds.ToString(), restore_bounds.ToString());
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(restore_bounds.ToString(),
188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            window_state->GetRestoreBoundsInScreen().ToString());
189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->OnWMEvent(&snap_left);
191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_NE(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_NE(maximized_bounds.ToString(),
193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            window->GetBoundsInScreen().ToString());
194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(restore_bounds.ToString(),
195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            window_state->GetRestoreBoundsInScreen().ToString());
196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->Restore();
198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Test that maximizing an auto managed window, then snapping it puts the window
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// at the snapped bounds and not at the auto-managed (centered) bounds.
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(WindowStateTest, AutoManaged) {
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
20523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WindowState* window_state = GetWindowState(window.get());
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->set_window_position_managed(true);
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window->Hide();
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window->SetBounds(gfx::Rect(100, 100, 100, 100));
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window->Show();
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->Maximize();
21223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const WMEvent snap_right(WM_EVENT_SNAP_RIGHT);
213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  window_state->OnWMEvent(&snap_right);
214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const gfx::Rect kWorkAreaBounds =
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  gfx::Rect expected_snapped_bounds(
218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kWorkAreaBounds.x() + kWorkAreaBounds.width() / 2,
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kWorkAreaBounds.y(),
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kWorkAreaBounds.width() / 2,
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      kWorkAreaBounds.height());
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_EQ(expected_snapped_bounds.ToString(),
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            window->GetBoundsInScreen().ToString());
224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // The window should still be auto managed despite being right maximized.
226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  EXPECT_TRUE(window_state->window_position_managed());
227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
22923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Test that the replacement of a State object works as expected.
23023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)TEST_F(WindowStateTest, SimpleStateSwap) {
23123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
23223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WindowState* window_state = GetWindowState(window.get());
23323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_FALSE(window_state->IsMaximized());
23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  window_state->SetStateObject(
23523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      scoped_ptr<WindowState::State> (new AlwaysMaximizeTestState(
23623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          window_state->GetStateType())));
23723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_TRUE(window_state->IsMaximized());
23823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
23923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
24023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Test that the replacement of a state object, following a restore with the
24123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// original one restores the window to its original state.
24223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)TEST_F(WindowStateTest, StateSwapRestore) {
24323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
24423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  WindowState* window_state = GetWindowState(window.get());
24523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_FALSE(window_state->IsMaximized());
24623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  scoped_ptr<WindowState::State> old(window_state->SetStateObject(
24723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      scoped_ptr<WindowState::State> (new AlwaysMaximizeTestState(
24823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          window_state->GetStateType()))).Pass());
24923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_TRUE(window_state->IsMaximized());
25023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  window_state->SetStateObject(old.Pass());
25123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  EXPECT_FALSE(window_state->IsMaximized());
25223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
25323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
25423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// TODO(skuhne): Add more unit test to verify the correctness for the restore
25523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// operation.
25623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace wm
258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}  // namespace ash
259