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