Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ash / wm / workspace / workspace_layout_manager_unittest.cc
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/workspace/workspace_layout_manager.h"
6
7 #include <string>
8
9 #include "ash/display/display_layout.h"
10 #include "ash/display/display_manager.h"
11 #include "ash/root_window_controller.h"
12 #include "ash/screen_util.h"
13 #include "ash/session/session_state_delegate.h"
14 #include "ash/shelf/shelf_layout_manager.h"
15 #include "ash/shell.h"
16 #include "ash/shell_observer.h"
17 #include "ash/shell_window_ids.h"
18 #include "ash/test/ash_test_base.h"
19 #include "ash/wm/maximize_mode/workspace_backdrop_delegate.h"
20 #include "ash/wm/window_state.h"
21 #include "ash/wm/window_util.h"
22 #include "ash/wm/wm_event.h"
23 #include "ash/wm/workspace/workspace_window_resizer.h"
24 #include "base/basictypes.h"
25 #include "base/compiler_specific.h"
26 #include "ui/aura/client/aura_constants.h"
27 #include "ui/aura/test/test_windows.h"
28 #include "ui/aura/window.h"
29 #include "ui/aura/window_event_dispatcher.h"
30 #include "ui/base/ime/dummy_text_input_client.h"
31 #include "ui/base/ime/input_method.h"
32 #include "ui/base/ime/text_input_focus_manager.h"
33 #include "ui/base/ui_base_switches_util.h"
34 #include "ui/base/ui_base_types.h"
35 #include "ui/gfx/insets.h"
36 #include "ui/gfx/screen.h"
37 #include "ui/views/widget/widget.h"
38 #include "ui/views/widget/widget_delegate.h"
39 #include "ui/wm/core/window_util.h"
40
41 namespace ash {
42 namespace {
43
44 class MaximizeDelegateView : public views::WidgetDelegateView {
45  public:
46   explicit MaximizeDelegateView(const gfx::Rect& initial_bounds)
47       : initial_bounds_(initial_bounds) {
48   }
49   virtual ~MaximizeDelegateView() {}
50
51   virtual bool GetSavedWindowPlacement(
52       const views::Widget* widget,
53       gfx::Rect* bounds,
54       ui::WindowShowState* show_state) const OVERRIDE {
55     *bounds = initial_bounds_;
56     *show_state = ui::SHOW_STATE_MAXIMIZED;
57     return true;
58   }
59
60  private:
61   const gfx::Rect initial_bounds_;
62
63   DISALLOW_COPY_AND_ASSIGN(MaximizeDelegateView);
64 };
65
66 class TestShellObserver : public ShellObserver {
67  public:
68   TestShellObserver() : call_count_(0),
69                         is_fullscreen_(false) {
70     Shell::GetInstance()->AddShellObserver(this);
71   }
72
73   virtual ~TestShellObserver() {
74     Shell::GetInstance()->RemoveShellObserver(this);
75   }
76
77   virtual void OnFullscreenStateChanged(bool is_fullscreen,
78                                         aura::Window* root_window) OVERRIDE {
79     call_count_++;
80     is_fullscreen_ = is_fullscreen;
81   }
82
83   int call_count() const {
84     return call_count_;
85   }
86
87   bool is_fullscreen() const {
88     return is_fullscreen_;
89   }
90
91  private:
92   int call_count_;
93   bool is_fullscreen_;
94
95   DISALLOW_COPY_AND_ASSIGN(TestShellObserver);
96 };
97
98 }  // namespace
99
100 typedef test::AshTestBase WorkspaceLayoutManagerTest;
101
102 // Verifies that a window containing a restore coordinate will be restored to
103 // to the size prior to minimize, keeping the restore rectangle in tact (if
104 // there is one).
105 TEST_F(WorkspaceLayoutManagerTest, RestoreFromMinimizeKeepsRestore) {
106   scoped_ptr<aura::Window> window(
107       CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 3, 4)));
108   gfx::Rect bounds(10, 15, 25, 35);
109   window->SetBounds(bounds);
110
111   wm::WindowState* window_state = wm::GetWindowState(window.get());
112
113   // This will not be used for un-minimizing window.
114   window_state->SetRestoreBoundsInScreen(gfx::Rect(0, 0, 100, 100));
115   window_state->Minimize();
116   window_state->Restore();
117   EXPECT_EQ("0,0 100x100", window_state->GetRestoreBoundsInScreen().ToString());
118   EXPECT_EQ("10,15 25x35", window.get()->bounds().ToString());
119
120   if (!SupportsMultipleDisplays())
121     return;
122
123   UpdateDisplay("400x300,500x400");
124   window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100),
125                             ScreenUtil::GetSecondaryDisplay());
126   EXPECT_EQ(Shell::GetAllRootWindows()[1], window->GetRootWindow());
127   window_state->Minimize();
128   // This will not be used for un-minimizing window.
129   window_state->SetRestoreBoundsInScreen(gfx::Rect(0, 0, 100, 100));
130   window_state->Restore();
131   EXPECT_EQ("600,0 100x100", window->GetBoundsInScreen().ToString());
132
133   // Make sure the unminimized window moves inside the display when
134   // 2nd display is disconnected.
135   window_state->Minimize();
136   UpdateDisplay("400x300");
137   window_state->Restore();
138   EXPECT_EQ(Shell::GetPrimaryRootWindow(), window->GetRootWindow());
139   EXPECT_TRUE(
140       Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds()));
141 }
142
143 TEST_F(WorkspaceLayoutManagerTest, KeepMinimumVisibilityInDisplays) {
144   if (!SupportsMultipleDisplays())
145     return;
146
147   UpdateDisplay("300x400,400x500");
148   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
149
150   DisplayLayout layout(DisplayLayout::TOP, 0);
151   Shell::GetInstance()->display_manager()->
152       SetLayoutForCurrentDisplays(layout);
153   EXPECT_EQ("0,-500 400x500", root_windows[1]->GetBoundsInScreen().ToString());
154
155   scoped_ptr<aura::Window> window1(
156       CreateTestWindowInShellWithBounds(gfx::Rect(10, -400, 200, 200)));
157   EXPECT_EQ("10,-400 200x200", window1->GetBoundsInScreen().ToString());
158
159   // Make sure the caption is visible.
160   scoped_ptr<aura::Window> window2(
161       CreateTestWindowInShellWithBounds(gfx::Rect(10, -600, 200, 200)));
162   EXPECT_EQ("10,-500 200x200", window2->GetBoundsInScreen().ToString());
163 }
164
165 TEST_F(WorkspaceLayoutManagerTest, NoMinimumVisibilityForPopupWindows) {
166   UpdateDisplay("300x400");
167
168   // Create a popup window out of display boundaries and make sure it is not
169   // moved to have minimum visibility.
170   scoped_ptr<aura::Window> window(
171       CreateTestWindowInShellWithDelegateAndType(NULL,
172                                                  ui::wm::WINDOW_TYPE_POPUP,
173                                                  0,
174                                                  gfx::Rect(400, 100, 50, 50)));
175   EXPECT_EQ("400,100 50x50", window->GetBoundsInScreen().ToString());
176 }
177
178 TEST_F(WorkspaceLayoutManagerTest, KeepRestoredWindowInDisplay) {
179   if (!SupportsHostWindowResize())
180     return;
181   scoped_ptr<aura::Window> window(
182       CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40)));
183   wm::WindowState* window_state = wm::GetWindowState(window.get());
184
185   // Maximized -> Normal transition.
186   window_state->Maximize();
187   window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 30, 40));
188   window_state->Restore();
189   EXPECT_TRUE(
190       Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds()));
191   // Y bounds should not be negative.
192   EXPECT_EQ("-20,0 30x40", window->bounds().ToString());
193
194   // Minimized -> Normal transition.
195   window->SetBounds(gfx::Rect(-100, -100, 30, 40));
196   window_state->Minimize();
197   EXPECT_FALSE(
198       Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds()));
199   EXPECT_EQ("-100,-100 30x40", window->bounds().ToString());
200   window->Show();
201   EXPECT_TRUE(
202       Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds()));
203   // Y bounds should not be negative.
204   EXPECT_EQ("-20,0 30x40", window->bounds().ToString());
205
206   // Fullscreen -> Normal transition.
207   window->SetBounds(gfx::Rect(0, 0, 30, 40));  // reset bounds.
208   ASSERT_EQ("0,0 30x40", window->bounds().ToString());
209   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
210   EXPECT_EQ(window->bounds(), window->GetRootWindow()->bounds());
211   window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 30, 40));
212   window_state->Restore();
213   EXPECT_TRUE(
214       Shell::GetPrimaryRootWindow()->bounds().Intersects(window->bounds()));
215   // Y bounds should not be negative.
216   EXPECT_EQ("-20,0 30x40", window->bounds().ToString());
217 }
218
219 TEST_F(WorkspaceLayoutManagerTest, MaximizeInDisplayToBeRestored) {
220   if (!SupportsMultipleDisplays())
221     return;
222   UpdateDisplay("300x400,400x500");
223
224   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
225
226   scoped_ptr<aura::Window> window(
227       CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40)));
228   EXPECT_EQ(root_windows[0], window->GetRootWindow());
229
230   wm::WindowState* window_state = wm::GetWindowState(window.get());
231   window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40));
232   // Maximize the window in 2nd display as the restore bounds
233   // is inside 2nd display.
234   window_state->Maximize();
235   EXPECT_EQ(root_windows[1], window->GetRootWindow());
236   EXPECT_EQ("300,0 400x453", window->GetBoundsInScreen().ToString());
237
238   window_state->Restore();
239   EXPECT_EQ(root_windows[1], window->GetRootWindow());
240   EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString());
241
242   // If the restore bounds intersects with the current display,
243   // don't move.
244   window_state->SetRestoreBoundsInScreen(gfx::Rect(280, 0, 30, 40));
245   window_state->Maximize();
246   EXPECT_EQ(root_windows[1], window->GetRootWindow());
247   EXPECT_EQ("300,0 400x453", window->GetBoundsInScreen().ToString());
248
249   window_state->Restore();
250   EXPECT_EQ(root_windows[1], window->GetRootWindow());
251   EXPECT_EQ("280,0 30x40", window->GetBoundsInScreen().ToString());
252
253   // Restoring widget state.
254   scoped_ptr<views::Widget> w1(new views::Widget);
255   views::Widget::InitParams params;
256   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
257   params.delegate = new MaximizeDelegateView(gfx::Rect(400, 0, 30, 40));
258   params.context = root_windows[0];
259   w1->Init(params);
260   w1->Show();
261   EXPECT_TRUE(w1->IsMaximized());
262   EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow());
263   EXPECT_EQ("300,0 400x453", w1->GetWindowBoundsInScreen().ToString());
264   w1->Restore();
265   EXPECT_EQ(root_windows[1], w1->GetNativeView()->GetRootWindow());
266   EXPECT_EQ("400,0 30x40", w1->GetWindowBoundsInScreen().ToString());
267 }
268
269 TEST_F(WorkspaceLayoutManagerTest, FullscreenInDisplayToBeRestored) {
270   if (!SupportsMultipleDisplays())
271     return;
272   UpdateDisplay("300x400,400x500");
273
274   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
275
276   scoped_ptr<aura::Window> window(
277       CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40)));
278   EXPECT_EQ(root_windows[0], window->GetRootWindow());
279
280   wm::WindowState* window_state = wm::GetWindowState(window.get());
281   window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40));
282   // Maximize the window in 2nd display as the restore bounds
283   // is inside 2nd display.
284   window->SetProperty(aura::client::kShowStateKey,
285                       ui::SHOW_STATE_FULLSCREEN);
286   EXPECT_EQ(root_windows[1], window->GetRootWindow());
287   EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString());
288
289   window_state->Restore();
290   EXPECT_EQ(root_windows[1], window->GetRootWindow());
291   EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString());
292
293   // If the restore bounds intersects with the current display,
294   // don't move.
295   window_state->SetRestoreBoundsInScreen(gfx::Rect(280, 0, 30, 40));
296   window->SetProperty(aura::client::kShowStateKey,
297                       ui::SHOW_STATE_FULLSCREEN);
298   EXPECT_EQ(root_windows[1], window->GetRootWindow());
299   EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString());
300
301   window_state->Restore();
302   EXPECT_EQ(root_windows[1], window->GetRootWindow());
303   EXPECT_EQ("280,0 30x40", window->GetBoundsInScreen().ToString());
304 }
305
306 // WindowObserver implementation used by DontClobberRestoreBoundsWindowObserver.
307 // This code mirrors what BrowserFrameAsh does. In particular when this code
308 // sees the window was maximized it changes the bounds of a secondary
309 // window. The secondary window mirrors the status window.
310 class DontClobberRestoreBoundsWindowObserver : public aura::WindowObserver {
311  public:
312   DontClobberRestoreBoundsWindowObserver() : window_(NULL) {}
313
314   void set_window(aura::Window* window) { window_ = window; }
315
316   virtual void OnWindowPropertyChanged(aura::Window* window,
317                                        const void* key,
318                                        intptr_t old) OVERRIDE {
319     if (!window_)
320       return;
321
322     if (wm::GetWindowState(window)->IsMaximized()) {
323       aura::Window* w = window_;
324       window_ = NULL;
325
326       gfx::Rect shelf_bounds(Shell::GetPrimaryRootWindowController()->
327                              GetShelfLayoutManager()->GetIdealBounds());
328       const gfx::Rect& window_bounds(w->bounds());
329       w->SetBounds(gfx::Rect(window_bounds.x(), shelf_bounds.y() - 1,
330                              window_bounds.width(), window_bounds.height()));
331     }
332   }
333
334  private:
335   aura::Window* window_;
336
337   DISALLOW_COPY_AND_ASSIGN(DontClobberRestoreBoundsWindowObserver);
338 };
339
340 // Creates a window, maximized the window and from within the maximized
341 // notification sets the bounds of a window to overlap the shelf. Verifies this
342 // doesn't effect the restore bounds.
343 TEST_F(WorkspaceLayoutManagerTest, DontClobberRestoreBounds) {
344   DontClobberRestoreBoundsWindowObserver window_observer;
345   scoped_ptr<aura::Window> window(new aura::Window(NULL));
346   window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
347   window->Init(aura::WINDOW_LAYER_TEXTURED);
348   window->SetBounds(gfx::Rect(10, 20, 30, 40));
349   // NOTE: for this test to exercise the failure the observer needs to be added
350   // before the parent set. This mimics what BrowserFrameAsh does.
351   window->AddObserver(&window_observer);
352   ParentWindowInPrimaryRootWindow(window.get());
353   window->Show();
354
355   wm::WindowState* window_state = wm::GetWindowState(window.get());
356   window_state->Activate();
357
358   scoped_ptr<aura::Window> window2(
359       CreateTestWindowInShellWithBounds(gfx::Rect(12, 20, 30, 40)));
360   ::wm::AddTransientChild(window.get(), window2.get());
361   window2->Show();
362
363   window_observer.set_window(window2.get());
364   window_state->Maximize();
365   EXPECT_EQ("10,20 30x40",
366             window_state->GetRestoreBoundsInScreen().ToString());
367   window->RemoveObserver(&window_observer);
368 }
369
370 // Verifies when a window is maximized all descendant windows have a size.
371 TEST_F(WorkspaceLayoutManagerTest, ChildBoundsResetOnMaximize) {
372   scoped_ptr<aura::Window> window(
373       CreateTestWindowInShellWithBounds(gfx::Rect(10, 20, 30, 40)));
374   window->Show();
375   wm::WindowState* window_state = wm::GetWindowState(window.get());
376   window_state->Activate();
377   scoped_ptr<aura::Window> child_window(
378       aura::test::CreateTestWindowWithBounds(gfx::Rect(5, 6, 7, 8),
379                                              window.get()));
380   child_window->Show();
381   window_state->Maximize();
382   EXPECT_EQ("5,6 7x8", child_window->bounds().ToString());
383 }
384
385 // Verifies a window created with maximized state has the maximized
386 // bounds.
387 TEST_F(WorkspaceLayoutManagerTest, MaximizeWithEmptySize) {
388   scoped_ptr<aura::Window> window(
389       aura::test::CreateTestWindowWithBounds(gfx::Rect(0, 0, 0, 0),
390                                              NULL));
391   wm::GetWindowState(window.get())->Maximize();
392   aura::Window* default_container = Shell::GetContainer(
393       Shell::GetPrimaryRootWindow(), kShellWindowId_DefaultContainer);
394   default_container->AddChild(window.get());
395   window->Show();
396   gfx::Rect work_area(
397       Shell::GetScreen()->GetPrimaryDisplay().work_area());
398   EXPECT_EQ(work_area.ToString(), window->GetBoundsInScreen().ToString());
399 }
400
401 TEST_F(WorkspaceLayoutManagerTest, WindowShouldBeOnScreenWhenAdded) {
402   // Normal window bounds shouldn't be changed.
403   gfx::Rect window_bounds(100, 100, 200, 200);
404   scoped_ptr<aura::Window> window(
405       CreateTestWindowInShellWithBounds(window_bounds));
406   EXPECT_EQ(window_bounds, window->bounds());
407
408   // If the window is out of the workspace, it would be moved on screen.
409   gfx::Rect root_window_bounds =
410       Shell::GetInstance()->GetPrimaryRootWindow()->bounds();
411   window_bounds.Offset(root_window_bounds.width(), root_window_bounds.height());
412   ASSERT_FALSE(window_bounds.Intersects(root_window_bounds));
413   scoped_ptr<aura::Window> out_window(
414       CreateTestWindowInShellWithBounds(window_bounds));
415   EXPECT_EQ(window_bounds.size(), out_window->bounds().size());
416   gfx::Rect bounds = out_window->bounds();
417   bounds.Intersect(root_window_bounds);
418
419   // 30% of the window edge must be visible.
420   EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29);
421   EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29);
422
423   aura::Window* parent = out_window->parent();
424   parent->RemoveChild(out_window.get());
425   out_window->SetBounds(gfx::Rect(-200, -200, 200, 200));
426   // UserHasChangedWindowPositionOrSize flag shouldn't turn off this behavior.
427   wm::GetWindowState(window.get())->set_bounds_changed_by_user(true);
428   parent->AddChild(out_window.get());
429   EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29);
430   EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29);
431
432   // Make sure we always make more than 1/3 of the window edge visible even
433   // if the initial bounds intersects with display.
434   window_bounds.SetRect(-150, -150, 200, 200);
435   bounds = window_bounds;
436   bounds.Intersect(root_window_bounds);
437
438   // Make sure that the initial bounds' visible area is less than 26%
439   // so that the auto adjustment logic kicks in.
440   ASSERT_LT(bounds.width(), out_window->bounds().width() * 0.26);
441   ASSERT_LT(bounds.height(), out_window->bounds().height() * 0.26);
442   ASSERT_TRUE(window_bounds.Intersects(root_window_bounds));
443
444   scoped_ptr<aura::Window> partially_out_window(
445       CreateTestWindowInShellWithBounds(window_bounds));
446   EXPECT_EQ(window_bounds.size(), partially_out_window->bounds().size());
447   bounds = partially_out_window->bounds();
448   bounds.Intersect(root_window_bounds);
449   EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29);
450   EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29);
451
452   // Make sure the window whose 30% width/height is bigger than display
453   // will be placed correctly.
454   window_bounds.SetRect(-1900, -1900, 3000, 3000);
455   scoped_ptr<aura::Window> window_bigger_than_display(
456       CreateTestWindowInShellWithBounds(window_bounds));
457   EXPECT_GE(root_window_bounds.width(),
458             window_bigger_than_display->bounds().width());
459   EXPECT_GE(root_window_bounds.height(),
460             window_bigger_than_display->bounds().height());
461
462   bounds = window_bigger_than_display->bounds();
463   bounds.Intersect(root_window_bounds);
464   EXPECT_GT(bounds.width(), out_window->bounds().width() * 0.29);
465   EXPECT_GT(bounds.height(), out_window->bounds().height() * 0.29);
466 }
467
468 // Verifies the size of a window is enforced to be smaller than the work area.
469 TEST_F(WorkspaceLayoutManagerTest, SizeToWorkArea) {
470   // Normal window bounds shouldn't be changed.
471   gfx::Size work_area(
472       Shell::GetScreen()->GetPrimaryDisplay().work_area().size());
473   const gfx::Rect window_bounds(
474       100, 101, work_area.width() + 1, work_area.height() + 2);
475   scoped_ptr<aura::Window> window(
476       CreateTestWindowInShellWithBounds(window_bounds));
477   EXPECT_EQ(gfx::Rect(gfx::Point(100, 101), work_area).ToString(),
478       window->bounds().ToString());
479
480   // Directly setting the bounds triggers a slightly different code path. Verify
481   // that too.
482   window->SetBounds(window_bounds);
483   EXPECT_EQ(gfx::Rect(gfx::Point(100, 101), work_area).ToString(),
484       window->bounds().ToString());
485 }
486
487 TEST_F(WorkspaceLayoutManagerTest, NotifyFullscreenChanges) {
488   TestShellObserver observer;
489   scoped_ptr<aura::Window> window1(
490       CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40)));
491   scoped_ptr<aura::Window> window2(
492       CreateTestWindowInShellWithBounds(gfx::Rect(1, 2, 30, 40)));
493   wm::WindowState* window_state1 = wm::GetWindowState(window1.get());
494   wm::WindowState* window_state2 = wm::GetWindowState(window2.get());
495   window_state2->Activate();
496
497   const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN);
498   window_state2->OnWMEvent(&toggle_fullscreen_event);
499   EXPECT_EQ(1, observer.call_count());
500   EXPECT_TRUE(observer.is_fullscreen());
501
502   // When window1 moves to the front the fullscreen state should change.
503   window_state1->Activate();
504   EXPECT_EQ(2, observer.call_count());
505   EXPECT_FALSE(observer.is_fullscreen());
506
507   // It should change back if window2 becomes active again.
508   window_state2->Activate();
509   EXPECT_EQ(3, observer.call_count());
510   EXPECT_TRUE(observer.is_fullscreen());
511
512   window_state2->OnWMEvent(&toggle_fullscreen_event);
513   EXPECT_EQ(4, observer.call_count());
514   EXPECT_FALSE(observer.is_fullscreen());
515
516   window_state2->OnWMEvent(&toggle_fullscreen_event);
517   EXPECT_EQ(5, observer.call_count());
518   EXPECT_TRUE(observer.is_fullscreen());
519
520   // Closing the window should change the fullscreen state.
521   window2.reset();
522   EXPECT_EQ(6, observer.call_count());
523   EXPECT_FALSE(observer.is_fullscreen());
524 }
525
526 // Following "Solo" tests were originally written for BaseLayoutManager.
527 namespace {
528
529 class WorkspaceLayoutManagerSoloTest : public test::AshTestBase {
530  public:
531   WorkspaceLayoutManagerSoloTest() {}
532   virtual ~WorkspaceLayoutManagerSoloTest() {}
533
534   aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
535     return CreateTestWindowInShellWithBounds(bounds);
536   }
537
538  private:
539   DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManagerSoloTest);
540 };
541
542 }  // namespace
543
544 // Tests normal->maximize->normal.
545 TEST_F(WorkspaceLayoutManagerSoloTest, Maximize) {
546   gfx::Rect bounds(100, 100, 200, 200);
547   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
548   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
549   // Maximized window fills the work area, not the whole display.
550   EXPECT_EQ(
551       ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(),
552       window->bounds().ToString());
553   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
554   EXPECT_EQ(bounds.ToString(), window->bounds().ToString());
555 }
556
557 // Tests normal->minimize->normal.
558 TEST_F(WorkspaceLayoutManagerSoloTest, Minimize) {
559   gfx::Rect bounds(100, 100, 200, 200);
560   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
561   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
562   // Note: Currently minimize doesn't do anything except set the state.
563   // See crbug.com/104571.
564   EXPECT_EQ(bounds.ToString(), window->bounds().ToString());
565   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
566   EXPECT_EQ(bounds.ToString(), window->bounds().ToString());
567 }
568
569 // A WindowDelegate which sets the focus when the window
570 // becomes visible.
571 class FocusDelegate : public aura::test::TestWindowDelegate {
572  public:
573   FocusDelegate()
574       : window_(NULL),
575         show_state_(ui::SHOW_STATE_END) {
576   }
577   virtual ~FocusDelegate() {}
578
579   void set_window(aura::Window* window) { window_ = window; }
580
581   // aura::test::TestWindowDelegate overrides:
582   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
583     if (window_) {
584       if (visible)
585         window_->Focus();
586       show_state_ = window_->GetProperty(aura::client::kShowStateKey);
587     }
588   }
589
590   ui::WindowShowState GetShowStateAndReset() {
591     ui::WindowShowState ret = show_state_;
592     show_state_ = ui::SHOW_STATE_END;
593     return ret;
594   }
595
596  private:
597   aura::Window* window_;
598   ui::WindowShowState show_state_;
599
600   DISALLOW_COPY_AND_ASSIGN(FocusDelegate);
601 };
602
603 // Make sure that the window's show state is correct in
604 // |WindowDelegate::OnWindowTargetVisibilityChanged|, and setting
605 // focus in this callback doesn't cause DCHECK error.  See
606 // crbug.com/168383.
607 TEST_F(WorkspaceLayoutManagerSoloTest, FocusDuringUnminimize) {
608   FocusDelegate delegate;
609   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
610       &delegate, 0, gfx::Rect(100, 100, 100, 100)));
611   delegate.set_window(window.get());
612   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
613   EXPECT_FALSE(window->IsVisible());
614   EXPECT_EQ(ui::SHOW_STATE_MINIMIZED, delegate.GetShowStateAndReset());
615   window->Show();
616   EXPECT_TRUE(window->IsVisible());
617   EXPECT_EQ(ui::SHOW_STATE_NORMAL, delegate.GetShowStateAndReset());
618 }
619
620 // Tests maximized window size during root window resize.
621 TEST_F(WorkspaceLayoutManagerSoloTest, MaximizeRootWindowResize) {
622   gfx::Rect bounds(100, 100, 200, 200);
623   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
624   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
625   gfx::Rect initial_work_area_bounds =
626       ScreenUtil::GetMaximizedWindowBoundsInParent(window.get());
627   EXPECT_EQ(initial_work_area_bounds.ToString(), window->bounds().ToString());
628   // Enlarge the root window.  We should still match the work area size.
629   UpdateDisplay("900x700");
630   EXPECT_EQ(
631       ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(),
632       window->bounds().ToString());
633   EXPECT_NE(
634       initial_work_area_bounds.ToString(),
635       ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString());
636 }
637
638 // Tests normal->fullscreen->normal.
639 TEST_F(WorkspaceLayoutManagerSoloTest, Fullscreen) {
640   gfx::Rect bounds(100, 100, 200, 200);
641   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
642   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
643   // Fullscreen window fills the whole display.
644   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
645                 window.get()).bounds().ToString(),
646             window->bounds().ToString());
647   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
648   EXPECT_EQ(bounds.ToString(), window->bounds().ToString());
649 }
650
651 // Tests fullscreen window size during root window resize.
652 TEST_F(WorkspaceLayoutManagerSoloTest, FullscreenRootWindowResize) {
653   gfx::Rect bounds(100, 100, 200, 200);
654   scoped_ptr<aura::Window> window(CreateTestWindow(bounds));
655   // Fullscreen window fills the whole display.
656   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
657   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
658                 window.get()).bounds().ToString(),
659             window->bounds().ToString());
660   // Enlarge the root window.  We should still match the display size.
661   UpdateDisplay("800x600");
662   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
663                 window.get()).bounds().ToString(),
664             window->bounds().ToString());
665 }
666
667 // Tests that when the screen gets smaller the windows aren't bigger than
668 // the screen.
669 TEST_F(WorkspaceLayoutManagerSoloTest, RootWindowResizeShrinksWindows) {
670   scoped_ptr<aura::Window> window(
671       CreateTestWindow(gfx::Rect(10, 20, 500, 400)));
672   gfx::Rect work_area = Shell::GetScreen()->GetDisplayNearestWindow(
673       window.get()).work_area();
674   // Invariant: Window is smaller than work area.
675   EXPECT_LE(window->bounds().width(), work_area.width());
676   EXPECT_LE(window->bounds().height(), work_area.height());
677
678   // Make the root window narrower than our window.
679   UpdateDisplay("300x400");
680   work_area = Shell::GetScreen()->GetDisplayNearestWindow(
681       window.get()).work_area();
682   EXPECT_LE(window->bounds().width(), work_area.width());
683   EXPECT_LE(window->bounds().height(), work_area.height());
684
685   // Make the root window shorter than our window.
686   UpdateDisplay("300x200");
687   work_area = Shell::GetScreen()->GetDisplayNearestWindow(
688       window.get()).work_area();
689   EXPECT_LE(window->bounds().width(), work_area.width());
690   EXPECT_LE(window->bounds().height(), work_area.height());
691
692   // Enlarging the root window does not change the window bounds.
693   gfx::Rect old_bounds = window->bounds();
694   UpdateDisplay("800x600");
695   EXPECT_EQ(old_bounds.width(), window->bounds().width());
696   EXPECT_EQ(old_bounds.height(), window->bounds().height());
697 }
698
699 // Verifies maximizing sets the restore bounds, and restoring
700 // restores the bounds.
701 TEST_F(WorkspaceLayoutManagerSoloTest, MaximizeSetsRestoreBounds) {
702   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(10, 20, 30, 40)));
703   wm::WindowState* window_state = wm::GetWindowState(window.get());
704
705   // Maximize it, which will keep the previous restore bounds.
706   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
707   EXPECT_EQ("10,20 30x40", window_state->GetRestoreBoundsInParent().ToString());
708
709   // Restore it, which should restore bounds and reset restore bounds.
710   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
711   EXPECT_EQ("10,20 30x40", window->bounds().ToString());
712   EXPECT_FALSE(window_state->HasRestoreBounds());
713 }
714
715 // Verifies maximizing keeps the restore bounds if set.
716 TEST_F(WorkspaceLayoutManagerSoloTest, MaximizeResetsRestoreBounds) {
717   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
718
719   wm::WindowState* window_state = wm::GetWindowState(window.get());
720   window_state->SetRestoreBoundsInParent(gfx::Rect(10, 11, 12, 13));
721
722   // Maximize it, which will keep the previous restore bounds.
723   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
724   EXPECT_EQ("10,11 12x13", window_state->GetRestoreBoundsInParent().ToString());
725 }
726
727 // Verifies that the restore bounds do not get reset when restoring to a
728 // maximzied state from a minimized state.
729 TEST_F(WorkspaceLayoutManagerSoloTest,
730        BoundsAfterRestoringToMaximizeFromMinimize) {
731   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
732   gfx::Rect bounds(10, 15, 25, 35);
733   window->SetBounds(bounds);
734
735   wm::WindowState* window_state = wm::GetWindowState(window.get());
736   // Maximize it, which should reset restore bounds.
737   window_state->Maximize();
738   EXPECT_EQ(bounds.ToString(),
739             window_state->GetRestoreBoundsInParent().ToString());
740   // Minimize the window. The restore bounds should not change.
741   window_state->Minimize();
742   EXPECT_EQ(bounds.ToString(),
743             window_state->GetRestoreBoundsInParent().ToString());
744
745   // Show the window again. The window should be maximized, and the restore
746   // bounds should not change.
747   window->Show();
748   EXPECT_EQ(bounds.ToString(),
749             window_state->GetRestoreBoundsInParent().ToString());
750   EXPECT_TRUE(window_state->IsMaximized());
751
752   window_state->Restore();
753   EXPECT_EQ(bounds.ToString(), window->bounds().ToString());
754 }
755
756 // Verify if the window is not resized during screen lock. See: crbug.com/173127
757 TEST_F(WorkspaceLayoutManagerSoloTest, NotResizeWhenScreenIsLocked) {
758   SetCanLockScreen(true);
759   scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
760   // window with AlwaysOnTop will be managed by BaseLayoutManager.
761   window->SetProperty(aura::client::kAlwaysOnTopKey, true);
762   window->Show();
763
764   ShelfLayoutManager* shelf = ShelfLayoutManager::ForShelf(window.get());
765   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
766
767   window->SetBounds(ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()));
768   gfx::Rect window_bounds = window->bounds();
769   EXPECT_EQ(
770       ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(),
771       window_bounds.ToString());
772
773   Shell::GetInstance()->session_state_delegate()->LockScreen();
774   shelf->UpdateVisibilityState();
775   EXPECT_NE(
776       ScreenUtil::GetMaximizedWindowBoundsInParent(window.get()).ToString(),
777       window_bounds.ToString());
778
779   Shell::GetInstance()->session_state_delegate()->UnlockScreen();
780   shelf->UpdateVisibilityState();
781   EXPECT_EQ(window_bounds.ToString(), window->bounds().ToString());
782 }
783
784 // Following tests are written to test the backdrop functionality.
785
786 namespace {
787
788 class WorkspaceLayoutManagerBackdropTest : public test::AshTestBase {
789  public:
790   WorkspaceLayoutManagerBackdropTest() {}
791   virtual ~WorkspaceLayoutManagerBackdropTest() {}
792
793   virtual void SetUp() OVERRIDE {
794     test::AshTestBase::SetUp();
795     UpdateDisplay("800x600");
796     default_container_ = Shell::GetContainer(Shell::GetPrimaryRootWindow(),
797                                              kShellWindowId_DefaultContainer);
798   }
799
800   aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
801     aura::Window* window = CreateTestWindowInShellWithBounds(bounds);
802     return window;
803   }
804
805   // Turn the top window back drop on / off.
806   void ShowTopWindowBackdrop(bool show) {
807     scoped_ptr<ash::WorkspaceLayoutManagerDelegate> backdrop;
808     if (show) {
809       backdrop.reset(new ash::WorkspaceBackdropDelegate(default_container_));
810     }
811     (static_cast<WorkspaceLayoutManager*>(default_container_->layout_manager()))
812         ->SetMaximizeBackdropDelegate(backdrop.Pass());
813     // Closing and / or opening can be a delayed operation.
814     base::MessageLoop::current()->RunUntilIdle();
815   }
816
817   // Return the default container.
818   aura::Window* default_container() { return default_container_; }
819
820   // Return the order of windows (top most first) as they are in the default
821   // container. If the window is visible it will be a big letter, otherwise a
822   // small one. The backdrop will be an X and unknown windows will be shown as
823   // '!'.
824   std::string GetWindowOrderAsString(aura::Window* backdrop,
825                                      aura::Window* wa,
826                                      aura::Window* wb,
827                                      aura::Window* wc) {
828     std::string result;
829     for (int i = static_cast<int>(default_container()->children().size()) - 1;
830          i >= 0;
831          --i) {
832       if (!result.empty())
833         result += ",";
834       if (default_container()->children()[i] == wa)
835         result += default_container()->children()[i]->IsVisible() ? "A" : "a";
836       else if (default_container()->children()[i] == wb)
837         result += default_container()->children()[i]->IsVisible() ? "B" : "b";
838       else if (default_container()->children()[i] == wc)
839         result += default_container()->children()[i]->IsVisible() ? "C" : "c";
840       else if (default_container()->children()[i] == backdrop)
841         result += default_container()->children()[i]->IsVisible() ? "X" : "x";
842       else
843         result += "!";
844     }
845     return result;
846   }
847
848  private:
849   // The default container.
850   aura::Window* default_container_;
851
852   DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManagerBackdropTest);
853 };
854
855 }  // namespace
856
857 // Check that creating the BackDrop without destroying it does not lead into
858 // a crash.
859 TEST_F(WorkspaceLayoutManagerBackdropTest, BackdropCrashTest) {
860   ShowTopWindowBackdrop(true);
861 }
862
863 // Verify basic assumptions about the backdrop.
864 TEST_F(WorkspaceLayoutManagerBackdropTest, BasicBackdropTests) {
865   // Create a backdrop and see that there is one window (the backdrop) and
866   // that the size is the same as the default container as well as that it is
867   // not visible.
868   ShowTopWindowBackdrop(true);
869   ASSERT_EQ(1U, default_container()->children().size());
870   EXPECT_FALSE(default_container()->children()[0]->IsVisible());
871
872   {
873     // Add a window and make sure that the backdrop is the second child.
874     scoped_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
875     window->Show();
876     ASSERT_EQ(2U, default_container()->children().size());
877     EXPECT_TRUE(default_container()->children()[0]->IsVisible());
878     EXPECT_TRUE(default_container()->children()[1]->IsVisible());
879     EXPECT_EQ(window.get(), default_container()->children()[1]);
880     EXPECT_EQ(default_container()->bounds().ToString(),
881               default_container()->children()[0]->bounds().ToString());
882   }
883
884   // With the window gone the backdrop should be invisible again.
885   ASSERT_EQ(1U, default_container()->children().size());
886   EXPECT_FALSE(default_container()->children()[0]->IsVisible());
887
888   // Destroying the Backdrop should empty the container.
889   ShowTopWindowBackdrop(false);
890   ASSERT_EQ(0U, default_container()->children().size());
891 }
892
893 // Verify that the backdrop gets properly created and placed.
894 TEST_F(WorkspaceLayoutManagerBackdropTest, VerifyBackdropAndItsStacking) {
895   scoped_ptr<aura::Window> window1(CreateTestWindow(gfx::Rect(1, 2, 3, 4)));
896   window1->Show();
897
898   // Get the default container and check that only a single window is in there.
899   ASSERT_EQ(1U, default_container()->children().size());
900   EXPECT_EQ(window1.get(), default_container()->children()[0]);
901   EXPECT_EQ("A", GetWindowOrderAsString(NULL, window1.get(), NULL, NULL));
902
903   // Create 2 more windows and check that they are also in the container.
904   scoped_ptr<aura::Window> window2(CreateTestWindow(gfx::Rect(10, 2, 3, 4)));
905   scoped_ptr<aura::Window> window3(CreateTestWindow(gfx::Rect(20, 2, 3, 4)));
906   window2->Show();
907   window3->Show();
908
909   aura::Window* backdrop = NULL;
910   EXPECT_EQ("C,B,A",
911             GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
912                                    window3.get()));
913
914   // Turn on the backdrop mode and check that the window shows up where it
915   // should be (second highest number).
916   ShowTopWindowBackdrop(true);
917   backdrop = default_container()->children()[2];
918   EXPECT_EQ("C,X,B,A",
919             GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
920                                    window3.get()));
921
922   // Switch the order of windows and check that it still remains in that
923   // location.
924   default_container()->StackChildAtTop(window2.get());
925   EXPECT_EQ("B,X,C,A",
926             GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
927                                    window3.get()));
928
929   // Make the top window invisible and check.
930   window2.get()->Hide();
931   EXPECT_EQ("b,C,X,A",
932             GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
933                                    window3.get()));
934   // Then delete window after window and see that everything is in order.
935   window1.reset();
936   EXPECT_EQ("b,C,X",
937             GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
938                                    window3.get()));
939   window3.reset();
940   EXPECT_EQ("b,x",
941             GetWindowOrderAsString(backdrop, window1.get(), window2.get(),
942                                    window3.get()));
943   ShowTopWindowBackdrop(false);
944   EXPECT_EQ("b",
945             GetWindowOrderAsString(NULL, window1.get(), window2.get(),
946                                    window3.get()));
947 }
948
949 // Tests that when hidding the shelf, that the backdrop resizes to fill the
950 // entire workspace area.
951 TEST_F(WorkspaceLayoutManagerBackdropTest, ShelfVisibilityChangesBounds) {
952   ShelfLayoutManager* shelf_layout_manager =
953       Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
954   ShowTopWindowBackdrop(true);
955   RunAllPendingInMessageLoop();
956
957   ASSERT_EQ(SHELF_VISIBLE, shelf_layout_manager->visibility_state());
958   gfx::Rect initial_bounds = default_container()->children()[0]->bounds();
959   shelf_layout_manager->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
960   shelf_layout_manager->UpdateVisibilityState();
961
962   // When the shelf is re-shown WorkspaceLayoutManager shrinks all children
963   // including the backdrop.
964   shelf_layout_manager->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
965   shelf_layout_manager->UpdateVisibilityState();
966   gfx::Rect reduced_bounds = default_container()->children()[0]->bounds();
967   EXPECT_LT(reduced_bounds.height(), initial_bounds.height());
968
969   shelf_layout_manager->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
970   shelf_layout_manager->UpdateVisibilityState();
971
972   EXPECT_GT(default_container()->children()[0]->bounds().height(),
973             reduced_bounds.height());
974 }
975
976 class WorkspaceLayoutManagerKeyboardTest : public test::AshTestBase {
977  public:
978   WorkspaceLayoutManagerKeyboardTest() {}
979   virtual ~WorkspaceLayoutManagerKeyboardTest() {}
980
981   virtual void SetUp() OVERRIDE {
982     test::AshTestBase::SetUp();
983     UpdateDisplay("800x600");
984     aura::Window* default_container = Shell::GetContainer(
985         Shell::GetPrimaryRootWindow(), kShellWindowId_DefaultContainer);
986     layout_manager_ = static_cast<WorkspaceLayoutManager*>(
987         default_container->layout_manager());
988   }
989
990   aura::Window* CreateTestWindow(const gfx::Rect& bounds) {
991     return CreateTestWindowInShellWithBounds(bounds);
992   }
993
994   void ShowKeyboard() {
995     restore_work_area_insets_ = Shell::GetScreen()->GetPrimaryDisplay().
996         GetWorkAreaInsets();
997     Shell::GetInstance()->SetDisplayWorkAreaInsets(
998         Shell::GetPrimaryRootWindow(),
999         gfx::Insets(0, 0, keyboard_bounds_.height(), 0));
1000     layout_manager_->OnKeyboardBoundsChanging(keyboard_bounds_);
1001   }
1002
1003   void HideKeyboard() {
1004     Shell::GetInstance()->SetDisplayWorkAreaInsets(
1005         Shell::GetPrimaryRootWindow(),
1006         restore_work_area_insets_);
1007     layout_manager_->OnKeyboardBoundsChanging(gfx::Rect());
1008   }
1009
1010   void SetKeyboardBounds(const gfx::Rect& bounds) {
1011     keyboard_bounds_ = bounds;
1012   }
1013
1014  private:
1015   gfx::Insets restore_work_area_insets_;
1016   gfx::Rect keyboard_bounds_;
1017   WorkspaceLayoutManager* layout_manager_;
1018
1019   DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManagerKeyboardTest);
1020 };
1021
1022 class FakeTextInputClient : public ui::DummyTextInputClient {
1023  public:
1024   explicit FakeTextInputClient(gfx::NativeWindow window) : window_(window) {}
1025   virtual ~FakeTextInputClient() {}
1026
1027   virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE {
1028     return window_;
1029   }
1030
1031  private:
1032   gfx::NativeWindow window_;
1033
1034   DISALLOW_COPY_AND_ASSIGN(FakeTextInputClient);
1035 };
1036
1037 TEST_F(WorkspaceLayoutManagerKeyboardTest, AdjustWindowForA11yKeyboard) {
1038   gfx::Rect work_area(
1039       Shell::GetScreen()->GetPrimaryDisplay().work_area());
1040   gfx::Rect keyboard_bounds(work_area.x(),
1041                             work_area.y() + work_area.height() / 2,
1042                             work_area.width(),
1043                             work_area.height() / 2);
1044
1045   SetKeyboardBounds(keyboard_bounds);
1046   scoped_ptr<aura::Window> window(
1047       CreateTestWindowInShellWithBounds(work_area));
1048
1049   aura::Window* root_window = ash::Shell::GetInstance()->GetPrimaryRootWindow();
1050   FakeTextInputClient text_input_client(window.get());
1051   ui::InputMethod* input_method =
1052       root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
1053   if (switches::IsTextInputFocusManagerEnabled()) {
1054     ui::TextInputFocusManager::GetInstance()->FocusTextInputClient(
1055         &text_input_client);
1056   } else {
1057     input_method->SetFocusedTextInputClient(&text_input_client);
1058   }
1059
1060   int available_height =
1061       Shell::GetScreen()->GetPrimaryDisplay().bounds().height() -
1062       keyboard_bounds.height();
1063
1064   EXPECT_EQ(gfx::Rect(work_area).ToString(),
1065       window->bounds().ToString());
1066   ShowKeyboard();
1067   EXPECT_EQ(gfx::Rect(work_area.origin(),
1068             gfx::Size(work_area.width(), available_height)).ToString(),
1069             window->bounds().ToString());
1070   HideKeyboard();
1071
1072   window->SetBounds(gfx::Rect(50, 50, 100, 500));
1073   EXPECT_EQ("50,50 100x500", window->bounds().ToString());
1074   ShowKeyboard();
1075   EXPECT_EQ(gfx::Rect(50, 0, 100, available_height).ToString(),
1076             window->bounds().ToString());
1077   HideKeyboard();
1078   if (switches::IsTextInputFocusManagerEnabled()) {
1079     ui::TextInputFocusManager::GetInstance()->BlurTextInputClient(
1080         &text_input_client);
1081   } else {
1082     input_method->SetFocusedTextInputClient(NULL);
1083   }
1084 }
1085
1086 }  // namespace ash