| OLD | NEW |
| (Empty) |
| 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/common/wm/workspace/workspace_layout_manager.h" | |
| 6 | |
| 7 #include <string> | |
| 8 #include <utility> | |
| 9 | |
| 10 #include "ash/common/session/session_state_delegate.h" | |
| 11 #include "ash/common/shelf/shelf_constants.h" | |
| 12 #include "ash/common/shelf/shelf_layout_manager.h" | |
| 13 #include "ash/common/shelf/wm_shelf.h" | |
| 14 #include "ash/common/shell_observer.h" | |
| 15 #include "ash/common/test/ash_test.h" | |
| 16 #include "ash/common/test/test_session_state_delegate.h" | |
| 17 #include "ash/common/wm/fullscreen_window_finder.h" | |
| 18 #include "ash/common/wm/maximize_mode/workspace_backdrop_delegate.h" | |
| 19 #include "ash/common/wm/window_state.h" | |
| 20 #include "ash/common/wm/wm_event.h" | |
| 21 #include "ash/common/wm/wm_screen_util.h" | |
| 22 #include "ash/common/wm/workspace/workspace_window_resizer.h" | |
| 23 #include "ash/common/wm_lookup.h" | |
| 24 #include "ash/common/wm_shell.h" | |
| 25 #include "ash/common/wm_window.h" | |
| 26 #include "ash/public/cpp/shell_window_ids.h" | |
| 27 #include "ash/root_window_controller.h" | |
| 28 #include "ash/screen_util.h" | |
| 29 #include "ash/shell.h" | |
| 30 #include "ash/test/ash_test_base.h" | |
| 31 #include "ash/wm/window_state_aura.h" | |
| 32 #include "ash/wm/window_util.h" | |
| 33 #include "base/command_line.h" | |
| 34 #include "base/compiler_specific.h" | |
| 35 #include "base/run_loop.h" | |
| 36 #include "ui/base/ui_base_switches.h" | |
| 37 #include "ui/base/ui_base_types.h" | |
| 38 #include "ui/display/display_layout.h" | |
| 39 #include "ui/display/manager/display_manager.h" | |
| 40 #include "ui/display/screen.h" | |
| 41 #include "ui/display/test/display_manager_test_api.h" | |
| 42 #include "ui/gfx/geometry/insets.h" | |
| 43 #include "ui/keyboard/keyboard_controller.h" | |
| 44 #include "ui/keyboard/keyboard_ui.h" | |
| 45 #include "ui/keyboard/keyboard_util.h" | |
| 46 #include "ui/views/widget/widget.h" | |
| 47 #include "ui/views/widget/widget_delegate.h" | |
| 48 #include "ui/wm/core/window_util.h" | |
| 49 | |
| 50 namespace ash { | |
| 51 namespace { | |
| 52 | |
| 53 class MaximizeDelegateView : public views::WidgetDelegateView { | |
| 54 public: | |
| 55 explicit MaximizeDelegateView(const gfx::Rect& initial_bounds) | |
| 56 : initial_bounds_(initial_bounds) {} | |
| 57 ~MaximizeDelegateView() override {} | |
| 58 | |
| 59 bool GetSavedWindowPlacement(const views::Widget* widget, | |
| 60 gfx::Rect* bounds, | |
| 61 ui::WindowShowState* show_state) const override { | |
| 62 *bounds = initial_bounds_; | |
| 63 *show_state = ui::SHOW_STATE_MAXIMIZED; | |
| 64 return true; | |
| 65 } | |
| 66 | |
| 67 private: | |
| 68 const gfx::Rect initial_bounds_; | |
| 69 | |
| 70 DISALLOW_COPY_AND_ASSIGN(MaximizeDelegateView); | |
| 71 }; | |
| 72 | |
| 73 class TestShellObserver : public ShellObserver { | |
| 74 public: | |
| 75 TestShellObserver() : call_count_(0), is_fullscreen_(false) { | |
| 76 WmShell::Get()->AddShellObserver(this); | |
| 77 } | |
| 78 | |
| 79 ~TestShellObserver() override { WmShell::Get()->RemoveShellObserver(this); } | |
| 80 | |
| 81 void OnFullscreenStateChanged(bool is_fullscreen, | |
| 82 WmWindow* root_window) override { | |
| 83 call_count_++; | |
| 84 is_fullscreen_ = is_fullscreen; | |
| 85 } | |
| 86 | |
| 87 int call_count() const { return call_count_; } | |
| 88 | |
| 89 bool is_fullscreen() const { return is_fullscreen_; } | |
| 90 | |
| 91 private: | |
| 92 int call_count_; | |
| 93 bool is_fullscreen_; | |
| 94 | |
| 95 DISALLOW_COPY_AND_ASSIGN(TestShellObserver); | |
| 96 }; | |
| 97 | |
| 98 } // namespace | |
| 99 | |
| 100 using WorkspaceLayoutManagerTest = AshTest; | |
| 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 std::unique_ptr<WindowOwner> window_owner( | |
| 107 CreateTestWindow(gfx::Rect(1, 2, 3, 4))); | |
| 108 WmWindow* window = window_owner->window(); | |
| 109 gfx::Rect bounds(10, 15, 25, 35); | |
| 110 window->SetBounds(bounds); | |
| 111 | |
| 112 wm::WindowState* window_state = window->GetWindowState(); | |
| 113 | |
| 114 // This will not be used for un-minimizing window. | |
| 115 window_state->SetRestoreBoundsInScreen(gfx::Rect(0, 0, 100, 100)); | |
| 116 window_state->Minimize(); | |
| 117 window_state->Restore(); | |
| 118 EXPECT_EQ("0,0 100x100", window_state->GetRestoreBoundsInScreen().ToString()); | |
| 119 EXPECT_EQ("10,15 25x35", window->GetBounds().ToString()); | |
| 120 | |
| 121 UpdateDisplay("400x300,500x400"); | |
| 122 window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100), GetSecondaryDisplay()); | |
| 123 EXPECT_EQ(WmShell::Get()->GetAllRootWindows()[1], window->GetRootWindow()); | |
| 124 window_state->Minimize(); | |
| 125 // This will not be used for un-minimizing window. | |
| 126 window_state->SetRestoreBoundsInScreen(gfx::Rect(0, 0, 100, 100)); | |
| 127 window_state->Restore(); | |
| 128 EXPECT_EQ("600,0 100x100", window->GetBoundsInScreen().ToString()); | |
| 129 | |
| 130 // Make sure the unminimized window moves inside the display when | |
| 131 // 2nd display is disconnected. | |
| 132 window_state->Minimize(); | |
| 133 UpdateDisplay("400x300"); | |
| 134 window_state->Restore(); | |
| 135 EXPECT_EQ(WmShell::Get()->GetPrimaryRootWindow(), window->GetRootWindow()); | |
| 136 EXPECT_TRUE(WmShell::Get()->GetPrimaryRootWindow()->GetBounds().Intersects( | |
| 137 window->GetBounds())); | |
| 138 } | |
| 139 | |
| 140 TEST_F(WorkspaceLayoutManagerTest, KeepMinimumVisibilityInDisplays) { | |
| 141 UpdateDisplay("300x400,400x500"); | |
| 142 WmWindow::Windows root_windows = WmShell::Get()->GetAllRootWindows(); | |
| 143 | |
| 144 if (!SetSecondaryDisplayPlacement(display::DisplayPlacement::TOP, 0)) | |
| 145 return; | |
| 146 | |
| 147 Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays( | |
| 148 display::test::CreateDisplayLayout(display_manager(), | |
| 149 display::DisplayPlacement::TOP, 0)); | |
| 150 EXPECT_EQ("0,-500 400x500", root_windows[1]->GetBoundsInScreen().ToString()); | |
| 151 | |
| 152 std::unique_ptr<WindowOwner> window1_owner( | |
| 153 CreateTestWindow(gfx::Rect(10, -400, 200, 200))); | |
| 154 EXPECT_EQ("10,-400 200x200", | |
| 155 window1_owner->window()->GetBoundsInScreen().ToString()); | |
| 156 | |
| 157 // Make sure the caption is visible. | |
| 158 std::unique_ptr<WindowOwner> window2_owner( | |
| 159 CreateTestWindow(gfx::Rect(10, -600, 200, 200))); | |
| 160 EXPECT_EQ("10,-500 200x200", | |
| 161 window2_owner->window()->GetBoundsInScreen().ToString()); | |
| 162 } | |
| 163 | |
| 164 TEST_F(WorkspaceLayoutManagerTest, NoMinimumVisibilityForPopupWindows) { | |
| 165 UpdateDisplay("300x400"); | |
| 166 | |
| 167 // Create a popup window out of display boundaries and make sure it is not | |
| 168 // moved to have minimum visibility. | |
| 169 std::unique_ptr<WindowOwner> window_owner( | |
| 170 CreateTestWindow(gfx::Rect(400, 100, 50, 50), ui::wm::WINDOW_TYPE_POPUP)); | |
| 171 EXPECT_EQ("400,100 50x50", | |
| 172 window_owner->window()->GetBoundsInScreen().ToString()); | |
| 173 } | |
| 174 | |
| 175 TEST_F(WorkspaceLayoutManagerTest, KeepRestoredWindowInDisplay) { | |
| 176 std::unique_ptr<WindowOwner> window_owner( | |
| 177 CreateTestWindow(gfx::Rect(1, 2, 30, 40))); | |
| 178 WmWindow* window = window_owner->window(); | |
| 179 wm::WindowState* window_state = window->GetWindowState(); | |
| 180 | |
| 181 // Maximized -> Normal transition. | |
| 182 window_state->Maximize(); | |
| 183 window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 30, 40)); | |
| 184 window_state->Restore(); | |
| 185 EXPECT_TRUE(WmShell::Get()->GetPrimaryRootWindow()->GetBounds().Intersects( | |
| 186 window->GetBounds())); | |
| 187 // Y bounds should not be negative. | |
| 188 EXPECT_EQ("-5,0 30x40", window->GetBounds().ToString()); | |
| 189 | |
| 190 // Minimized -> Normal transition. | |
| 191 window->SetBounds(gfx::Rect(-100, -100, 30, 40)); | |
| 192 window_state->Minimize(); | |
| 193 EXPECT_FALSE(WmShell::Get()->GetPrimaryRootWindow()->GetBounds().Intersects( | |
| 194 window->GetBounds())); | |
| 195 EXPECT_EQ("-100,-100 30x40", window->GetBounds().ToString()); | |
| 196 window->Show(); | |
| 197 EXPECT_TRUE(WmShell::Get()->GetPrimaryRootWindow()->GetBounds().Intersects( | |
| 198 window->GetBounds())); | |
| 199 // Y bounds should not be negative. | |
| 200 EXPECT_EQ("-5,0 30x40", window->GetBounds().ToString()); | |
| 201 | |
| 202 // Fullscreen -> Normal transition. | |
| 203 window->SetBounds(gfx::Rect(0, 0, 30, 40)); // reset bounds. | |
| 204 ASSERT_EQ("0,0 30x40", window->GetBounds().ToString()); | |
| 205 window->SetShowState(ui::SHOW_STATE_FULLSCREEN); | |
| 206 EXPECT_EQ(window->GetBounds(), window->GetRootWindow()->GetBounds()); | |
| 207 window_state->SetRestoreBoundsInScreen(gfx::Rect(-100, -100, 30, 40)); | |
| 208 window_state->Restore(); | |
| 209 EXPECT_TRUE(WmShell::Get()->GetPrimaryRootWindow()->GetBounds().Intersects( | |
| 210 window->GetBounds())); | |
| 211 // Y bounds should not be negative. | |
| 212 EXPECT_EQ("-5,0 30x40", window->GetBounds().ToString()); | |
| 213 } | |
| 214 | |
| 215 TEST_F(WorkspaceLayoutManagerTest, MaximizeInDisplayToBeRestored) { | |
| 216 UpdateDisplay("300x400,400x500"); | |
| 217 | |
| 218 WmWindow::Windows root_windows = WmShell::Get()->GetAllRootWindows(); | |
| 219 | |
| 220 std::unique_ptr<WindowOwner> window_owner( | |
| 221 CreateTestWindow(gfx::Rect(1, 2, 30, 40))); | |
| 222 WmWindow* window = window_owner->window(); | |
| 223 EXPECT_EQ(root_windows[0], window->GetRootWindow()); | |
| 224 | |
| 225 wm::WindowState* window_state = window->GetWindowState(); | |
| 226 window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40)); | |
| 227 // Maximize the window in 2nd display as the restore bounds | |
| 228 // is inside 2nd display. | |
| 229 window_state->Maximize(); | |
| 230 EXPECT_EQ(root_windows[1], window->GetRootWindow()); | |
| 231 EXPECT_EQ( | |
| 232 gfx::Rect(300, 0, 400, 500 - GetShelfConstant(SHELF_SIZE)).ToString(), | |
| 233 window->GetBoundsInScreen().ToString()); | |
| 234 | |
| 235 window_state->Restore(); | |
| 236 EXPECT_EQ(root_windows[1], window->GetRootWindow()); | |
| 237 EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString()); | |
| 238 | |
| 239 // If the restore bounds intersects with the current display, | |
| 240 // don't move. | |
| 241 window_state->SetRestoreBoundsInScreen(gfx::Rect(295, 0, 30, 40)); | |
| 242 window_state->Maximize(); | |
| 243 EXPECT_EQ(root_windows[1], window->GetRootWindow()); | |
| 244 EXPECT_EQ( | |
| 245 gfx::Rect(300, 0, 400, 500 - GetShelfConstant(SHELF_SIZE)).ToString(), | |
| 246 window->GetBoundsInScreen().ToString()); | |
| 247 | |
| 248 window_state->Restore(); | |
| 249 EXPECT_EQ(root_windows[1], window->GetRootWindow()); | |
| 250 EXPECT_EQ("295,0 30x40", window->GetBoundsInScreen().ToString()); | |
| 251 | |
| 252 // Restoring widget state. | |
| 253 std::unique_ptr<views::Widget> w1(new views::Widget); | |
| 254 views::Widget::InitParams params; | |
| 255 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | |
| 256 params.delegate = new MaximizeDelegateView(gfx::Rect(400, 0, 30, 40)); | |
| 257 ConfigureWidgetInitParamsForDisplay(root_windows[0], ¶ms); | |
| 258 w1->Init(params); | |
| 259 WmLookup* wm_lookup = WmLookup::Get(); | |
| 260 EXPECT_EQ(root_windows[0], | |
| 261 wm_lookup->GetWindowForWidget(w1.get())->GetRootWindow()); | |
| 262 w1->Show(); | |
| 263 EXPECT_TRUE(w1->IsMaximized()); | |
| 264 EXPECT_EQ(root_windows[1], | |
| 265 wm_lookup->GetWindowForWidget(w1.get())->GetRootWindow()); | |
| 266 EXPECT_EQ( | |
| 267 gfx::Rect(300, 0, 400, 500 - GetShelfConstant(SHELF_SIZE)).ToString(), | |
| 268 w1->GetWindowBoundsInScreen().ToString()); | |
| 269 w1->Restore(); | |
| 270 EXPECT_EQ(root_windows[1], | |
| 271 wm_lookup->GetWindowForWidget(w1.get())->GetRootWindow()); | |
| 272 EXPECT_EQ("400,0 30x40", w1->GetWindowBoundsInScreen().ToString()); | |
| 273 } | |
| 274 | |
| 275 TEST_F(WorkspaceLayoutManagerTest, FullscreenInDisplayToBeRestored) { | |
| 276 UpdateDisplay("300x400,400x500"); | |
| 277 | |
| 278 WmWindow::Windows root_windows = WmShell::Get()->GetAllRootWindows(); | |
| 279 | |
| 280 std::unique_ptr<WindowOwner> window_owner( | |
| 281 CreateTestWindow(gfx::Rect(1, 2, 30, 40))); | |
| 282 WmWindow* window = window_owner->window(); | |
| 283 EXPECT_EQ(root_windows[0], window->GetRootWindow()); | |
| 284 | |
| 285 wm::WindowState* window_state = window->GetWindowState(); | |
| 286 window_state->SetRestoreBoundsInScreen(gfx::Rect(400, 0, 30, 40)); | |
| 287 // Maximize the window in 2nd display as the restore bounds | |
| 288 // is inside 2nd display. | |
| 289 window->SetShowState(ui::SHOW_STATE_FULLSCREEN); | |
| 290 EXPECT_EQ(root_windows[1], window->GetRootWindow()); | |
| 291 EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString()); | |
| 292 | |
| 293 window_state->Restore(); | |
| 294 EXPECT_EQ(root_windows[1], window->GetRootWindow()); | |
| 295 EXPECT_EQ("400,0 30x40", window->GetBoundsInScreen().ToString()); | |
| 296 | |
| 297 // If the restore bounds intersects with the current display, | |
| 298 // don't move. | |
| 299 window_state->SetRestoreBoundsInScreen(gfx::Rect(295, 0, 30, 40)); | |
| 300 window->SetShowState(ui::SHOW_STATE_FULLSCREEN); | |
| 301 EXPECT_EQ(root_windows[1], window->GetRootWindow()); | |
| 302 EXPECT_EQ("300,0 400x500", window->GetBoundsInScreen().ToString()); | |
| 303 | |
| 304 window_state->Restore(); | |
| 305 EXPECT_EQ(root_windows[1], window->GetRootWindow()); | |
| 306 EXPECT_EQ("295,0 30x40", window->GetBoundsInScreen().ToString()); | |
| 307 } | |
| 308 | |
| 309 // WmWindowObserver implementation used by | |
| 310 // DontClobberRestoreBoundsWindowObserver. This code mirrors what | |
| 311 // BrowserFrameAsh does. In particular when this code sees the window was | |
| 312 // maximized it changes the bounds of a secondary window. The secondary window | |
| 313 // mirrors the status window. | |
| 314 class DontClobberRestoreBoundsWindowObserver : public WmWindowObserver { | |
| 315 public: | |
| 316 DontClobberRestoreBoundsWindowObserver() : window_(nullptr) {} | |
| 317 | |
| 318 void set_window(WmWindow* window) { window_ = window; } | |
| 319 | |
| 320 // WmWindowObserver: | |
| 321 void OnWindowPropertyChanged(WmWindow* window, | |
| 322 WmWindowProperty property) override { | |
| 323 if (!window_) | |
| 324 return; | |
| 325 | |
| 326 if (window->GetWindowState()->IsMaximized()) { | |
| 327 WmWindow* w = window_; | |
| 328 window_ = nullptr; | |
| 329 | |
| 330 gfx::Rect shelf_bounds(AshTest::GetPrimaryShelf()->GetIdealBounds()); | |
| 331 const gfx::Rect& window_bounds(w->GetBounds()); | |
| 332 w->SetBounds(gfx::Rect(window_bounds.x(), shelf_bounds.y() - 1, | |
| 333 window_bounds.width(), window_bounds.height())); | |
| 334 } | |
| 335 } | |
| 336 | |
| 337 private: | |
| 338 WmWindow* window_; | |
| 339 | |
| 340 DISALLOW_COPY_AND_ASSIGN(DontClobberRestoreBoundsWindowObserver); | |
| 341 }; | |
| 342 | |
| 343 // Creates a window, maximized the window and from within the maximized | |
| 344 // notification sets the bounds of a window to overlap the shelf. Verifies this | |
| 345 // doesn't effect the restore bounds. | |
| 346 TEST_F(WorkspaceLayoutManagerTest, DontClobberRestoreBounds) { | |
| 347 DontClobberRestoreBoundsWindowObserver window_observer; | |
| 348 WindowOwner window_owner(WmShell::Get()->NewWindow(ui::wm::WINDOW_TYPE_NORMAL, | |
| 349 ui::LAYER_TEXTURED)); | |
| 350 WmWindow* window = window_owner.window(); | |
| 351 window->SetBounds(gfx::Rect(10, 20, 30, 40)); | |
| 352 // NOTE: for this test to exercise the failure the observer needs to be added | |
| 353 // before the parent set. This mimics what BrowserFrameAsh does. | |
| 354 window->AddObserver(&window_observer); | |
| 355 ParentWindowInPrimaryRootWindow(window); | |
| 356 window->Show(); | |
| 357 | |
| 358 wm::WindowState* window_state = window->GetWindowState(); | |
| 359 window_state->Activate(); | |
| 360 | |
| 361 std::unique_ptr<WindowOwner> window2_owner( | |
| 362 CreateTestWindow(gfx::Rect(12, 20, 30, 40))); | |
| 363 WmWindow* window2 = window2_owner->window(); | |
| 364 AddTransientChild(window, window2); | |
| 365 window2->Show(); | |
| 366 | |
| 367 window_observer.set_window(window2); | |
| 368 window_state->Maximize(); | |
| 369 EXPECT_EQ("10,20 30x40", window_state->GetRestoreBoundsInScreen().ToString()); | |
| 370 window->RemoveObserver(&window_observer); | |
| 371 } | |
| 372 | |
| 373 // Verifies when a window is maximized all descendant windows have a size. | |
| 374 TEST_F(WorkspaceLayoutManagerTest, ChildBoundsResetOnMaximize) { | |
| 375 std::unique_ptr<WindowOwner> window_owner( | |
| 376 CreateTestWindow(gfx::Rect(10, 20, 30, 40))); | |
| 377 WmWindow* window = window_owner->window(); | |
| 378 window->Show(); | |
| 379 wm::WindowState* window_state = window->GetWindowState(); | |
| 380 window_state->Activate(); | |
| 381 std::unique_ptr<WindowOwner> child_window_owner( | |
| 382 CreateChildWindow(window, gfx::Rect(5, 6, 7, 8))); | |
| 383 WmWindow* child_window = child_window_owner->window(); | |
| 384 window_state->Maximize(); | |
| 385 EXPECT_EQ("5,6 7x8", child_window->GetBounds().ToString()); | |
| 386 } | |
| 387 | |
| 388 // Verifies a window created with maximized state has the maximized | |
| 389 // bounds. | |
| 390 TEST_F(WorkspaceLayoutManagerTest, MaximizeWithEmptySize) { | |
| 391 WindowOwner window_owner(WmShell::Get()->NewWindow(ui::wm::WINDOW_TYPE_NORMAL, | |
| 392 ui::LAYER_TEXTURED)); | |
| 393 WmWindow* window = window_owner.window(); | |
| 394 window->GetWindowState()->Maximize(); | |
| 395 WmWindow* default_container = | |
| 396 WmShell::Get()->GetPrimaryRootWindowController()->GetContainer( | |
| 397 kShellWindowId_DefaultContainer); | |
| 398 default_container->AddChild(window); | |
| 399 window->Show(); | |
| 400 gfx::Rect work_area( | |
| 401 display::Screen::GetScreen()->GetPrimaryDisplay().work_area()); | |
| 402 EXPECT_EQ(work_area.ToString(), window->GetBoundsInScreen().ToString()); | |
| 403 } | |
| 404 | |
| 405 TEST_F(WorkspaceLayoutManagerTest, WindowShouldBeOnScreenWhenAdded) { | |
| 406 // Normal window bounds shouldn't be changed. | |
| 407 gfx::Rect window_bounds(100, 100, 200, 200); | |
| 408 std::unique_ptr<WindowOwner> window_owner(CreateTestWindow(window_bounds)); | |
| 409 WmWindow* window = window_owner->window(); | |
| 410 EXPECT_EQ(window_bounds, window->GetBounds()); | |
| 411 | |
| 412 // If the window is out of the workspace, it would be moved on screen. | |
| 413 gfx::Rect root_window_bounds = | |
| 414 WmShell::Get()->GetPrimaryRootWindow()->GetBounds(); | |
| 415 window_bounds.Offset(root_window_bounds.width(), root_window_bounds.height()); | |
| 416 ASSERT_FALSE(window_bounds.Intersects(root_window_bounds)); | |
| 417 std::unique_ptr<WindowOwner> out_window_owner( | |
| 418 CreateTestWindow(window_bounds)); | |
| 419 WmWindow* out_window = out_window_owner->window(); | |
| 420 EXPECT_EQ(window_bounds.size(), out_window->GetBounds().size()); | |
| 421 gfx::Rect bounds = out_window->GetBounds(); | |
| 422 bounds.Intersect(root_window_bounds); | |
| 423 | |
| 424 // 30% of the window edge must be visible. | |
| 425 EXPECT_GT(bounds.width(), out_window->GetBounds().width() * 0.29); | |
| 426 EXPECT_GT(bounds.height(), out_window->GetBounds().height() * 0.29); | |
| 427 | |
| 428 WmWindow* parent = out_window->GetParent(); | |
| 429 parent->RemoveChild(out_window); | |
| 430 out_window->SetBounds(gfx::Rect(-200, -200, 200, 200)); | |
| 431 // UserHasChangedWindowPositionOrSize flag shouldn't turn off this behavior. | |
| 432 window->GetWindowState()->set_bounds_changed_by_user(true); | |
| 433 parent->AddChild(out_window); | |
| 434 EXPECT_GT(bounds.width(), out_window->GetBounds().width() * 0.29); | |
| 435 EXPECT_GT(bounds.height(), out_window->GetBounds().height() * 0.29); | |
| 436 | |
| 437 // Make sure we always make more than 1/3 of the window edge visible even | |
| 438 // if the initial bounds intersects with display. | |
| 439 window_bounds.SetRect(-150, -150, 200, 200); | |
| 440 bounds = window_bounds; | |
| 441 bounds.Intersect(root_window_bounds); | |
| 442 | |
| 443 // Make sure that the initial bounds' visible area is less than 26% | |
| 444 // so that the auto adjustment logic kicks in. | |
| 445 ASSERT_LT(bounds.width(), out_window->GetBounds().width() * 0.26); | |
| 446 ASSERT_LT(bounds.height(), out_window->GetBounds().height() * 0.26); | |
| 447 ASSERT_TRUE(window_bounds.Intersects(root_window_bounds)); | |
| 448 | |
| 449 std::unique_ptr<WindowOwner> partially_out_window_owner( | |
| 450 CreateTestWindow(window_bounds)); | |
| 451 WmWindow* partially_out_window = partially_out_window_owner->window(); | |
| 452 EXPECT_EQ(window_bounds.size(), partially_out_window->GetBounds().size()); | |
| 453 bounds = partially_out_window->GetBounds(); | |
| 454 bounds.Intersect(root_window_bounds); | |
| 455 EXPECT_GT(bounds.width(), out_window->GetBounds().width() * 0.29); | |
| 456 EXPECT_GT(bounds.height(), out_window->GetBounds().height() * 0.29); | |
| 457 | |
| 458 // Make sure the window whose 30% width/height is bigger than display | |
| 459 // will be placed correctly. | |
| 460 window_bounds.SetRect(-1900, -1900, 3000, 3000); | |
| 461 std::unique_ptr<WindowOwner> window_bigger_than_display_owner( | |
| 462 CreateTestWindow(window_bounds)); | |
| 463 WmWindow* window_bigger_than_display = | |
| 464 window_bigger_than_display_owner->window(); | |
| 465 EXPECT_GE(root_window_bounds.width(), | |
| 466 window_bigger_than_display->GetBounds().width()); | |
| 467 EXPECT_GE(root_window_bounds.height(), | |
| 468 window_bigger_than_display->GetBounds().height()); | |
| 469 | |
| 470 bounds = window_bigger_than_display->GetBounds(); | |
| 471 bounds.Intersect(root_window_bounds); | |
| 472 EXPECT_GT(bounds.width(), out_window->GetBounds().width() * 0.29); | |
| 473 EXPECT_GT(bounds.height(), out_window->GetBounds().height() * 0.29); | |
| 474 } | |
| 475 | |
| 476 // Verifies the size of a window is enforced to be smaller than the work area. | |
| 477 TEST_F(WorkspaceLayoutManagerTest, SizeToWorkArea) { | |
| 478 // Normal window bounds shouldn't be changed. | |
| 479 gfx::Size work_area( | |
| 480 display::Screen::GetScreen()->GetPrimaryDisplay().work_area().size()); | |
| 481 const gfx::Rect window_bounds(100, 101, work_area.width() + 1, | |
| 482 work_area.height() + 2); | |
| 483 std::unique_ptr<WindowOwner> window_owner(CreateTestWindow(window_bounds)); | |
| 484 WmWindow* window = window_owner->window(); | |
| 485 EXPECT_EQ(gfx::Rect(gfx::Point(100, 101), work_area).ToString(), | |
| 486 window->GetBounds().ToString()); | |
| 487 | |
| 488 // Directly setting the bounds triggers a slightly different code path. Verify | |
| 489 // that too. | |
| 490 window->SetBounds(window_bounds); | |
| 491 EXPECT_EQ(gfx::Rect(gfx::Point(100, 101), work_area).ToString(), | |
| 492 window->GetBounds().ToString()); | |
| 493 } | |
| 494 | |
| 495 TEST_F(WorkspaceLayoutManagerTest, NotifyFullscreenChanges) { | |
| 496 TestShellObserver observer; | |
| 497 std::unique_ptr<WindowOwner> window1_owner( | |
| 498 CreateTestWindow(gfx::Rect(1, 2, 30, 40))); | |
| 499 WmWindow* window1 = window1_owner->window(); | |
| 500 std::unique_ptr<WindowOwner> window2_owner( | |
| 501 CreateTestWindow(gfx::Rect(1, 2, 30, 40))); | |
| 502 WmWindow* window2 = window2_owner->window(); | |
| 503 wm::WindowState* window_state1 = window1->GetWindowState(); | |
| 504 wm::WindowState* window_state2 = window2->GetWindowState(); | |
| 505 window_state2->Activate(); | |
| 506 | |
| 507 const wm::WMEvent toggle_fullscreen_event(wm::WM_EVENT_TOGGLE_FULLSCREEN); | |
| 508 window_state2->OnWMEvent(&toggle_fullscreen_event); | |
| 509 EXPECT_EQ(1, observer.call_count()); | |
| 510 EXPECT_TRUE(observer.is_fullscreen()); | |
| 511 | |
| 512 // When window1 moves to the front the fullscreen state should change. | |
| 513 window_state1->Activate(); | |
| 514 EXPECT_EQ(2, observer.call_count()); | |
| 515 EXPECT_FALSE(observer.is_fullscreen()); | |
| 516 | |
| 517 // It should change back if window2 becomes active again. | |
| 518 window_state2->Activate(); | |
| 519 EXPECT_EQ(3, observer.call_count()); | |
| 520 EXPECT_TRUE(observer.is_fullscreen()); | |
| 521 | |
| 522 window_state2->OnWMEvent(&toggle_fullscreen_event); | |
| 523 EXPECT_EQ(4, observer.call_count()); | |
| 524 EXPECT_FALSE(observer.is_fullscreen()); | |
| 525 | |
| 526 window_state2->OnWMEvent(&toggle_fullscreen_event); | |
| 527 EXPECT_EQ(5, observer.call_count()); | |
| 528 EXPECT_TRUE(observer.is_fullscreen()); | |
| 529 | |
| 530 // Closing the window should change the fullscreen state. | |
| 531 window2_owner.reset(); | |
| 532 EXPECT_EQ(6, observer.call_count()); | |
| 533 EXPECT_FALSE(observer.is_fullscreen()); | |
| 534 } | |
| 535 | |
| 536 // Following "Solo" tests were originally written for BaseLayoutManager. | |
| 537 using WorkspaceLayoutManagerSoloTest = AshTest; | |
| 538 | |
| 539 // Tests normal->maximize->normal. | |
| 540 TEST_F(WorkspaceLayoutManagerSoloTest, Maximize) { | |
| 541 gfx::Rect bounds(100, 100, 200, 200); | |
| 542 std::unique_ptr<WindowOwner> window_owner(CreateTestWindow(bounds)); | |
| 543 WmWindow* window = window_owner->window(); | |
| 544 window->SetShowState(ui::SHOW_STATE_MAXIMIZED); | |
| 545 // Maximized window fills the work area, not the whole display. | |
| 546 EXPECT_EQ(wm::GetMaximizedWindowBoundsInParent(window).ToString(), | |
| 547 window->GetBounds().ToString()); | |
| 548 window->SetShowState(ui::SHOW_STATE_NORMAL); | |
| 549 EXPECT_EQ(bounds.ToString(), window->GetBounds().ToString()); | |
| 550 } | |
| 551 | |
| 552 // Tests normal->minimize->normal. | |
| 553 TEST_F(WorkspaceLayoutManagerSoloTest, Minimize) { | |
| 554 gfx::Rect bounds(100, 100, 200, 200); | |
| 555 std::unique_ptr<WindowOwner> window_owner(CreateTestWindow(bounds)); | |
| 556 WmWindow* window = window_owner->window(); | |
| 557 window->SetShowState(ui::SHOW_STATE_MINIMIZED); | |
| 558 // Note: Currently minimize doesn't do anything except set the state. | |
| 559 // See crbug.com/104571. | |
| 560 EXPECT_EQ(bounds.ToString(), window->GetBounds().ToString()); | |
| 561 window->SetShowState(ui::SHOW_STATE_NORMAL); | |
| 562 EXPECT_EQ(bounds.ToString(), window->GetBounds().ToString()); | |
| 563 } | |
| 564 | |
| 565 // A WmWindowObserver which sets the focus when the window becomes visible. | |
| 566 class FocusDuringUnminimizeWindowObserver : public WmWindowObserver { | |
| 567 public: | |
| 568 FocusDuringUnminimizeWindowObserver() | |
| 569 : window_(nullptr), show_state_(ui::SHOW_STATE_END) {} | |
| 570 ~FocusDuringUnminimizeWindowObserver() override { SetWindow(nullptr); } | |
| 571 | |
| 572 void SetWindow(WmWindow* window) { | |
| 573 if (window_) | |
| 574 window_->RemoveObserver(this); | |
| 575 window_ = window; | |
| 576 if (window_) | |
| 577 window_->AddObserver(this); | |
| 578 } | |
| 579 | |
| 580 // WmWindowObserver: | |
| 581 void OnWindowVisibilityChanged(WmWindow* window, bool visible) override { | |
| 582 if (window_) { | |
| 583 if (visible) | |
| 584 window_->SetFocused(); | |
| 585 show_state_ = window_->GetShowState(); | |
| 586 } | |
| 587 } | |
| 588 | |
| 589 ui::WindowShowState GetShowStateAndReset() { | |
| 590 ui::WindowShowState ret = show_state_; | |
| 591 show_state_ = ui::SHOW_STATE_END; | |
| 592 return ret; | |
| 593 } | |
| 594 | |
| 595 private: | |
| 596 WmWindow* window_; | |
| 597 ui::WindowShowState show_state_; | |
| 598 | |
| 599 DISALLOW_COPY_AND_ASSIGN(FocusDuringUnminimizeWindowObserver); | |
| 600 }; | |
| 601 | |
| 602 // Make sure that the window's show state is correct in | |
| 603 // WindowObserver::OnWindowTargetVisibilityChanged(), and setting focus in this | |
| 604 // callback doesn't cause DCHECK error. See crbug.com/168383. | |
| 605 TEST_F(WorkspaceLayoutManagerSoloTest, FocusDuringUnminimize) { | |
| 606 FocusDuringUnminimizeWindowObserver observer; | |
| 607 std::unique_ptr<WindowOwner> window_owner( | |
| 608 CreateTestWindow(gfx::Rect(100, 100, 100, 100))); | |
| 609 WmWindow* window = window_owner->window(); | |
| 610 observer.SetWindow(window); | |
| 611 window->SetShowState(ui::SHOW_STATE_MINIMIZED); | |
| 612 EXPECT_FALSE(window->IsVisible()); | |
| 613 EXPECT_EQ(ui::SHOW_STATE_MINIMIZED, observer.GetShowStateAndReset()); | |
| 614 window->Show(); | |
| 615 EXPECT_TRUE(window->IsVisible()); | |
| 616 EXPECT_EQ(ui::SHOW_STATE_NORMAL, observer.GetShowStateAndReset()); | |
| 617 observer.SetWindow(nullptr); | |
| 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 std::unique_ptr<WindowOwner> window_owner(CreateTestWindow(bounds)); | |
| 624 WmWindow* window = window_owner->window(); | |
| 625 window->SetShowState(ui::SHOW_STATE_MAXIMIZED); | |
| 626 gfx::Rect initial_work_area_bounds = | |
| 627 wm::GetMaximizedWindowBoundsInParent(window); | |
| 628 EXPECT_EQ(initial_work_area_bounds.ToString(), | |
| 629 window->GetBounds().ToString()); | |
| 630 // Enlarge the root window. We should still match the work area size. | |
| 631 UpdateDisplay("900x700"); | |
| 632 EXPECT_EQ(wm::GetMaximizedWindowBoundsInParent(window).ToString(), | |
| 633 window->GetBounds().ToString()); | |
| 634 EXPECT_NE(initial_work_area_bounds.ToString(), | |
| 635 wm::GetMaximizedWindowBoundsInParent(window).ToString()); | |
| 636 } | |
| 637 | |
| 638 // Tests normal->fullscreen->normal. | |
| 639 TEST_F(WorkspaceLayoutManagerSoloTest, Fullscreen) { | |
| 640 gfx::Rect bounds(100, 100, 200, 200); | |
| 641 std::unique_ptr<WindowOwner> window_owner(CreateTestWindow(bounds)); | |
| 642 WmWindow* window = window_owner->window(); | |
| 643 window->SetShowState(ui::SHOW_STATE_FULLSCREEN); | |
| 644 // Fullscreen window fills the whole display. | |
| 645 EXPECT_EQ(window->GetDisplayNearestWindow().bounds().ToString(), | |
| 646 window->GetBounds().ToString()); | |
| 647 window->SetShowState(ui::SHOW_STATE_NORMAL); | |
| 648 EXPECT_EQ(bounds.ToString(), window->GetBounds().ToString()); | |
| 649 } | |
| 650 | |
| 651 // Tests that fullscreen window causes always_on_top windows to stack below. | |
| 652 TEST_F(WorkspaceLayoutManagerSoloTest, FullscreenSuspendsAlwaysOnTop) { | |
| 653 gfx::Rect bounds(100, 100, 200, 200); | |
| 654 std::unique_ptr<WindowOwner> fullscreen_window_owner( | |
| 655 CreateTestWindow(bounds)); | |
| 656 WmWindow* fullscreen_window = fullscreen_window_owner->window(); | |
| 657 std::unique_ptr<WindowOwner> always_on_top_window1_owner( | |
| 658 CreateTestWindow(bounds)); | |
| 659 WmWindow* always_on_top_window1 = always_on_top_window1_owner->window(); | |
| 660 std::unique_ptr<WindowOwner> always_on_top_window2_owner( | |
| 661 CreateTestWindow(bounds)); | |
| 662 WmWindow* always_on_top_window2 = always_on_top_window2_owner->window(); | |
| 663 always_on_top_window1->SetAlwaysOnTop(true); | |
| 664 always_on_top_window2->SetAlwaysOnTop(true); | |
| 665 // Making a window fullscreen temporarily suspends always on top state. | |
| 666 fullscreen_window->SetShowState(ui::SHOW_STATE_FULLSCREEN); | |
| 667 EXPECT_FALSE(always_on_top_window1->IsAlwaysOnTop()); | |
| 668 EXPECT_FALSE(always_on_top_window2->IsAlwaysOnTop()); | |
| 669 EXPECT_NE(nullptr, wm::GetWindowForFullscreenMode(fullscreen_window)); | |
| 670 | |
| 671 // Adding a new always-on-top window is not affected by fullscreen. | |
| 672 std::unique_ptr<WindowOwner> always_on_top_window3_owner( | |
| 673 CreateTestWindow(bounds)); | |
| 674 WmWindow* always_on_top_window3 = always_on_top_window3_owner->window(); | |
| 675 always_on_top_window3->SetAlwaysOnTop(true); | |
| 676 EXPECT_TRUE(always_on_top_window3->IsAlwaysOnTop()); | |
| 677 | |
| 678 // Making fullscreen window normal restores always on top windows. | |
| 679 fullscreen_window->SetShowState(ui::SHOW_STATE_NORMAL); | |
| 680 EXPECT_TRUE(always_on_top_window1->IsAlwaysOnTop()); | |
| 681 EXPECT_TRUE(always_on_top_window2->IsAlwaysOnTop()); | |
| 682 EXPECT_TRUE(always_on_top_window3->IsAlwaysOnTop()); | |
| 683 EXPECT_EQ(nullptr, wm::GetWindowForFullscreenMode(fullscreen_window)); | |
| 684 } | |
| 685 | |
| 686 // Similary, pinned window causes always_on_top_ windows to stack below. | |
| 687 TEST_F(WorkspaceLayoutManagerSoloTest, PinnedSuspendsAlwaysOnTop) { | |
| 688 // TODO: mash doesn't support pinning yet http://crbug.com/622486. | |
| 689 if (WmShell::Get()->IsRunningInMash()) | |
| 690 return; | |
| 691 | |
| 692 gfx::Rect bounds(100, 100, 200, 200); | |
| 693 std::unique_ptr<WindowOwner> pinned_window_owner(CreateTestWindow(bounds)); | |
| 694 WmWindow* pinned_window = pinned_window_owner->window(); | |
| 695 std::unique_ptr<WindowOwner> always_on_top_window1_owner( | |
| 696 CreateTestWindow(bounds)); | |
| 697 WmWindow* always_on_top_window1 = always_on_top_window1_owner->window(); | |
| 698 std::unique_ptr<WindowOwner> always_on_top_window2_owner( | |
| 699 CreateTestWindow(bounds)); | |
| 700 WmWindow* always_on_top_window2 = always_on_top_window2_owner->window(); | |
| 701 always_on_top_window1->SetAlwaysOnTop(true); | |
| 702 always_on_top_window2->SetAlwaysOnTop(true); | |
| 703 | |
| 704 // Making a window pinned temporarily suspends always on top state. | |
| 705 const bool trusted = false; | |
| 706 pinned_window->SetPinned(trusted); | |
| 707 EXPECT_FALSE(always_on_top_window1->IsAlwaysOnTop()); | |
| 708 EXPECT_FALSE(always_on_top_window2->IsAlwaysOnTop()); | |
| 709 | |
| 710 // Adding a new always-on-top window also is affected by pinned mode. | |
| 711 std::unique_ptr<WindowOwner> always_on_top_window3_owner( | |
| 712 CreateTestWindow(bounds)); | |
| 713 WmWindow* always_on_top_window3 = always_on_top_window3_owner->window(); | |
| 714 always_on_top_window3->SetAlwaysOnTop(true); | |
| 715 EXPECT_FALSE(always_on_top_window3->IsAlwaysOnTop()); | |
| 716 | |
| 717 // Making pinned window normal restores always on top windows. | |
| 718 pinned_window->GetWindowState()->Restore(); | |
| 719 EXPECT_TRUE(always_on_top_window1->IsAlwaysOnTop()); | |
| 720 EXPECT_TRUE(always_on_top_window2->IsAlwaysOnTop()); | |
| 721 EXPECT_TRUE(always_on_top_window3->IsAlwaysOnTop()); | |
| 722 } | |
| 723 | |
| 724 // Tests fullscreen window size during root window resize. | |
| 725 TEST_F(WorkspaceLayoutManagerSoloTest, FullscreenRootWindowResize) { | |
| 726 gfx::Rect bounds(100, 100, 200, 200); | |
| 727 std::unique_ptr<WindowOwner> window_owner(CreateTestWindow(bounds)); | |
| 728 WmWindow* window = window_owner->window(); | |
| 729 // Fullscreen window fills the whole display. | |
| 730 window->SetShowState(ui::SHOW_STATE_FULLSCREEN); | |
| 731 EXPECT_EQ(window->GetDisplayNearestWindow().bounds().ToString(), | |
| 732 window->GetBounds().ToString()); | |
| 733 // Enlarge the root window. We should still match the display size. | |
| 734 UpdateDisplay("800x600"); | |
| 735 EXPECT_EQ(window->GetDisplayNearestWindow().bounds().ToString(), | |
| 736 window->GetBounds().ToString()); | |
| 737 } | |
| 738 | |
| 739 // Tests that when the screen gets smaller the windows aren't bigger than | |
| 740 // the screen. | |
| 741 TEST_F(WorkspaceLayoutManagerSoloTest, RootWindowResizeShrinksWindows) { | |
| 742 std::unique_ptr<WindowOwner> window_owner( | |
| 743 CreateTestWindow(gfx::Rect(10, 20, 500, 400))); | |
| 744 WmWindow* window = window_owner->window(); | |
| 745 gfx::Rect work_area = window->GetDisplayNearestWindow().work_area(); | |
| 746 // Invariant: Window is smaller than work area. | |
| 747 EXPECT_LE(window->GetBounds().width(), work_area.width()); | |
| 748 EXPECT_LE(window->GetBounds().height(), work_area.height()); | |
| 749 | |
| 750 // Make the root window narrower than our window. | |
| 751 UpdateDisplay("300x400"); | |
| 752 work_area = window->GetDisplayNearestWindow().work_area(); | |
| 753 EXPECT_LE(window->GetBounds().width(), work_area.width()); | |
| 754 EXPECT_LE(window->GetBounds().height(), work_area.height()); | |
| 755 | |
| 756 // Make the root window shorter than our window. | |
| 757 UpdateDisplay("300x200"); | |
| 758 work_area = window->GetDisplayNearestWindow().work_area(); | |
| 759 EXPECT_LE(window->GetBounds().width(), work_area.width()); | |
| 760 EXPECT_LE(window->GetBounds().height(), work_area.height()); | |
| 761 | |
| 762 // Enlarging the root window does not change the window bounds. | |
| 763 gfx::Rect old_bounds = window->GetBounds(); | |
| 764 UpdateDisplay("800x600"); | |
| 765 EXPECT_EQ(old_bounds.width(), window->GetBounds().width()); | |
| 766 EXPECT_EQ(old_bounds.height(), window->GetBounds().height()); | |
| 767 } | |
| 768 | |
| 769 // Verifies maximizing sets the restore bounds, and restoring | |
| 770 // restores the bounds. | |
| 771 TEST_F(WorkspaceLayoutManagerSoloTest, MaximizeSetsRestoreBounds) { | |
| 772 std::unique_ptr<WindowOwner> window_owner( | |
| 773 CreateTestWindow(gfx::Rect(10, 20, 30, 40))); | |
| 774 WmWindow* window = window_owner->window(); | |
| 775 wm::WindowState* window_state = window->GetWindowState(); | |
| 776 | |
| 777 // Maximize it, which will keep the previous restore bounds. | |
| 778 window->SetShowState(ui::SHOW_STATE_MAXIMIZED); | |
| 779 EXPECT_EQ("10,20 30x40", window_state->GetRestoreBoundsInParent().ToString()); | |
| 780 | |
| 781 // Restore it, which should restore bounds and reset restore bounds. | |
| 782 window->SetShowState(ui::SHOW_STATE_NORMAL); | |
| 783 EXPECT_EQ("10,20 30x40", window->GetBounds().ToString()); | |
| 784 EXPECT_FALSE(window_state->HasRestoreBounds()); | |
| 785 } | |
| 786 | |
| 787 // Verifies maximizing keeps the restore bounds if set. | |
| 788 TEST_F(WorkspaceLayoutManagerSoloTest, MaximizeResetsRestoreBounds) { | |
| 789 std::unique_ptr<WindowOwner> window_owner( | |
| 790 CreateTestWindow(gfx::Rect(1, 2, 3, 4))); | |
| 791 WmWindow* window = window_owner->window(); | |
| 792 wm::WindowState* window_state = window->GetWindowState(); | |
| 793 window_state->SetRestoreBoundsInParent(gfx::Rect(10, 11, 12, 13)); | |
| 794 | |
| 795 // Maximize it, which will keep the previous restore bounds. | |
| 796 window->SetShowState(ui::SHOW_STATE_MAXIMIZED); | |
| 797 EXPECT_EQ("10,11 12x13", window_state->GetRestoreBoundsInParent().ToString()); | |
| 798 } | |
| 799 | |
| 800 // Verifies that the restore bounds do not get reset when restoring to a | |
| 801 // maximzied state from a minimized state. | |
| 802 TEST_F(WorkspaceLayoutManagerSoloTest, | |
| 803 BoundsAfterRestoringToMaximizeFromMinimize) { | |
| 804 std::unique_ptr<WindowOwner> window_owner( | |
| 805 CreateTestWindow(gfx::Rect(1, 2, 3, 4))); | |
| 806 WmWindow* window = window_owner->window(); | |
| 807 gfx::Rect bounds(10, 15, 25, 35); | |
| 808 window->SetBounds(bounds); | |
| 809 | |
| 810 wm::WindowState* window_state = window->GetWindowState(); | |
| 811 // Maximize it, which should reset restore bounds. | |
| 812 window_state->Maximize(); | |
| 813 EXPECT_EQ(bounds.ToString(), | |
| 814 window_state->GetRestoreBoundsInParent().ToString()); | |
| 815 // Minimize the window. The restore bounds should not change. | |
| 816 window_state->Minimize(); | |
| 817 EXPECT_EQ(bounds.ToString(), | |
| 818 window_state->GetRestoreBoundsInParent().ToString()); | |
| 819 | |
| 820 // Show the window again. The window should be maximized, and the restore | |
| 821 // bounds should not change. | |
| 822 window->Show(); | |
| 823 EXPECT_EQ(bounds.ToString(), | |
| 824 window_state->GetRestoreBoundsInParent().ToString()); | |
| 825 EXPECT_TRUE(window_state->IsMaximized()); | |
| 826 | |
| 827 window_state->Restore(); | |
| 828 EXPECT_EQ(bounds.ToString(), window->GetBounds().ToString()); | |
| 829 } | |
| 830 | |
| 831 // Verify if the window is not resized during screen lock. See: crbug.com/173127 | |
| 832 TEST_F(WorkspaceLayoutManagerSoloTest, NotResizeWhenScreenIsLocked) { | |
| 833 test::TestSessionStateDelegate::SetCanLockScreen(true); | |
| 834 std::unique_ptr<WindowOwner> window_owner( | |
| 835 CreateTestWindow(gfx::Rect(1, 2, 3, 4))); | |
| 836 WmWindow* window = window_owner->window(); | |
| 837 // window with AlwaysOnTop will be managed by BaseLayoutManager. | |
| 838 window->SetAlwaysOnTop(true); | |
| 839 window->Show(); | |
| 840 | |
| 841 WmShelf* shelf = GetPrimaryShelf(); | |
| 842 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); | |
| 843 | |
| 844 window->SetBounds(wm::GetMaximizedWindowBoundsInParent(window)); | |
| 845 gfx::Rect window_bounds = window->GetBounds(); | |
| 846 EXPECT_EQ(wm::GetMaximizedWindowBoundsInParent(window).ToString(), | |
| 847 window_bounds.ToString()); | |
| 848 | |
| 849 // The window size should not get touched while we are in lock screen. | |
| 850 WmShell::Get()->GetSessionStateDelegate()->LockScreen(); | |
| 851 ShelfLayoutManager* shelf_layout_manager = shelf->shelf_layout_manager(); | |
| 852 shelf_layout_manager->UpdateVisibilityState(); | |
| 853 EXPECT_EQ(window_bounds.ToString(), window->GetBounds().ToString()); | |
| 854 | |
| 855 // Coming out of the lock screen the window size should still remain. | |
| 856 WmShell::Get()->GetSessionStateDelegate()->UnlockScreen(); | |
| 857 shelf_layout_manager->UpdateVisibilityState(); | |
| 858 EXPECT_EQ(wm::GetMaximizedWindowBoundsInParent(window).ToString(), | |
| 859 window_bounds.ToString()); | |
| 860 EXPECT_EQ(window_bounds.ToString(), window->GetBounds().ToString()); | |
| 861 } | |
| 862 | |
| 863 // Following tests are written to test the backdrop functionality. | |
| 864 | |
| 865 namespace { | |
| 866 | |
| 867 WorkspaceLayoutManager* GetWorkspaceLayoutManager(WmWindow* container) { | |
| 868 return static_cast<WorkspaceLayoutManager*>(container->GetLayoutManager()); | |
| 869 } | |
| 870 | |
| 871 class WorkspaceLayoutManagerBackdropTest : public AshTest { | |
| 872 public: | |
| 873 WorkspaceLayoutManagerBackdropTest() : default_container_(nullptr) {} | |
| 874 ~WorkspaceLayoutManagerBackdropTest() override {} | |
| 875 | |
| 876 void SetUp() override { | |
| 877 AshTest::SetUp(); | |
| 878 UpdateDisplay("800x600"); | |
| 879 default_container_ = | |
| 880 WmShell::Get()->GetPrimaryRootWindowController()->GetContainer( | |
| 881 kShellWindowId_DefaultContainer); | |
| 882 } | |
| 883 | |
| 884 // Turn the top window back drop on / off. | |
| 885 void ShowTopWindowBackdrop(bool show) { | |
| 886 std::unique_ptr<WorkspaceLayoutManagerBackdropDelegate> backdrop; | |
| 887 if (show) | |
| 888 backdrop.reset(new WorkspaceBackdropDelegate(default_container_)); | |
| 889 GetWorkspaceLayoutManager(default_container_) | |
| 890 ->SetMaximizeBackdropDelegate(std::move(backdrop)); | |
| 891 // Closing and / or opening can be a delayed operation. | |
| 892 base::RunLoop().RunUntilIdle(); | |
| 893 } | |
| 894 | |
| 895 // Return the default container. | |
| 896 WmWindow* default_container() { return default_container_; } | |
| 897 | |
| 898 // Return the order of windows (top most first) as they are in the default | |
| 899 // container. If the window is visible it will be a big letter, otherwise a | |
| 900 // small one. The backdrop will be an X and unknown windows will be shown as | |
| 901 // '!'. | |
| 902 std::string GetWindowOrderAsString(WmWindow* backdrop, | |
| 903 WmWindow* wa, | |
| 904 WmWindow* wb, | |
| 905 WmWindow* wc) { | |
| 906 std::string result; | |
| 907 WmWindow::Windows children = default_container()->GetChildren(); | |
| 908 for (int i = static_cast<int>(children.size()) - 1; i >= 0; --i) { | |
| 909 if (!result.empty()) | |
| 910 result += ","; | |
| 911 if (children[i] == wa) | |
| 912 result += children[i]->IsVisible() ? "A" : "a"; | |
| 913 else if (children[i] == wb) | |
| 914 result += children[i]->IsVisible() ? "B" : "b"; | |
| 915 else if (children[i] == wc) | |
| 916 result += children[i]->IsVisible() ? "C" : "c"; | |
| 917 else if (children[i] == backdrop) | |
| 918 result += children[i]->IsVisible() ? "X" : "x"; | |
| 919 else | |
| 920 result += "!"; | |
| 921 } | |
| 922 return result; | |
| 923 } | |
| 924 | |
| 925 private: | |
| 926 // The default container. | |
| 927 WmWindow* default_container_; | |
| 928 | |
| 929 DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManagerBackdropTest); | |
| 930 }; | |
| 931 | |
| 932 } // namespace | |
| 933 | |
| 934 // Check that creating the BackDrop without destroying it does not lead into | |
| 935 // a crash. | |
| 936 TEST_F(WorkspaceLayoutManagerBackdropTest, BackdropCrashTest) { | |
| 937 // TODO: Triggers crash in mash: http://crbug.com/652871. | |
| 938 if (WmShell::Get()->IsRunningInMash()) | |
| 939 return; | |
| 940 | |
| 941 ShowTopWindowBackdrop(true); | |
| 942 } | |
| 943 | |
| 944 // Verify basic assumptions about the backdrop. | |
| 945 TEST_F(WorkspaceLayoutManagerBackdropTest, BasicBackdropTests) { | |
| 946 // TODO: Triggers crash in mash: http://crbug.com/652871. | |
| 947 if (WmShell::Get()->IsRunningInMash()) | |
| 948 return; | |
| 949 | |
| 950 // Create a backdrop and see that there is one window (the backdrop) and | |
| 951 // that the size is the same as the default container as well as that it is | |
| 952 // not visible. | |
| 953 ShowTopWindowBackdrop(true); | |
| 954 ASSERT_EQ(1U, default_container()->GetChildren().size()); | |
| 955 EXPECT_FALSE(default_container()->GetChildren()[0]->IsVisible()); | |
| 956 | |
| 957 { | |
| 958 // Add a window and make sure that the backdrop is the second child. | |
| 959 std::unique_ptr<WindowOwner> window_owner( | |
| 960 CreateTestWindow(gfx::Rect(1, 2, 3, 4))); | |
| 961 WmWindow* window = window_owner->window(); | |
| 962 window->Show(); | |
| 963 ASSERT_EQ(2U, default_container()->GetChildren().size()); | |
| 964 EXPECT_TRUE(default_container()->GetChildren()[0]->IsVisible()); | |
| 965 EXPECT_TRUE(default_container()->GetChildren()[1]->IsVisible()); | |
| 966 EXPECT_EQ(window, default_container()->GetChildren()[1]); | |
| 967 EXPECT_EQ(default_container()->GetBounds().ToString(), | |
| 968 default_container()->GetChildren()[0]->GetBounds().ToString()); | |
| 969 } | |
| 970 | |
| 971 // With the window gone the backdrop should be invisible again. | |
| 972 ASSERT_EQ(1U, default_container()->GetChildren().size()); | |
| 973 EXPECT_FALSE(default_container()->GetChildren()[0]->IsVisible()); | |
| 974 | |
| 975 // Destroying the Backdrop should empty the container. | |
| 976 ShowTopWindowBackdrop(false); | |
| 977 ASSERT_EQ(0U, default_container()->GetChildren().size()); | |
| 978 } | |
| 979 | |
| 980 // Verify that the backdrop gets properly created and placed. | |
| 981 TEST_F(WorkspaceLayoutManagerBackdropTest, VerifyBackdropAndItsStacking) { | |
| 982 // TODO: Triggers crash in mash: http://crbug.com/652871. | |
| 983 if (WmShell::Get()->IsRunningInMash()) | |
| 984 return; | |
| 985 | |
| 986 std::unique_ptr<WindowOwner> window1_owner( | |
| 987 CreateTestWindow(gfx::Rect(1, 2, 3, 4))); | |
| 988 WmWindow* window1 = window1_owner->window(); | |
| 989 window1->Show(); | |
| 990 | |
| 991 // Get the default container and check that only a single window is in there. | |
| 992 ASSERT_EQ(1U, default_container()->GetChildren().size()); | |
| 993 EXPECT_EQ(window1, default_container()->GetChildren()[0]); | |
| 994 EXPECT_EQ("A", GetWindowOrderAsString(nullptr, window1, nullptr, nullptr)); | |
| 995 | |
| 996 // Create 2 more windows and check that they are also in the container. | |
| 997 std::unique_ptr<WindowOwner> window2_owner( | |
| 998 CreateTestWindow(gfx::Rect(10, 2, 3, 4))); | |
| 999 WmWindow* window2 = window2_owner->window(); | |
| 1000 std::unique_ptr<WindowOwner> window3_owner( | |
| 1001 CreateTestWindow(gfx::Rect(20, 2, 3, 4))); | |
| 1002 WmWindow* window3 = window3_owner->window(); | |
| 1003 window2->Show(); | |
| 1004 window3->Show(); | |
| 1005 | |
| 1006 WmWindow* backdrop = nullptr; | |
| 1007 EXPECT_EQ("C,B,A", | |
| 1008 GetWindowOrderAsString(backdrop, window1, window2, window3)); | |
| 1009 | |
| 1010 // Turn on the backdrop mode and check that the window shows up where it | |
| 1011 // should be (second highest number). | |
| 1012 ShowTopWindowBackdrop(true); | |
| 1013 backdrop = default_container()->GetChildren()[2]; | |
| 1014 EXPECT_EQ("C,X,B,A", | |
| 1015 GetWindowOrderAsString(backdrop, window1, window2, window3)); | |
| 1016 | |
| 1017 // Switch the order of windows and check that it still remains in that | |
| 1018 // location. | |
| 1019 default_container()->StackChildAtTop(window2); | |
| 1020 EXPECT_EQ("B,X,C,A", | |
| 1021 GetWindowOrderAsString(backdrop, window1, window2, window3)); | |
| 1022 | |
| 1023 // Make the top window invisible and check. | |
| 1024 window2->Hide(); | |
| 1025 EXPECT_EQ("b,C,X,A", | |
| 1026 GetWindowOrderAsString(backdrop, window1, window2, window3)); | |
| 1027 // Then delete window after window and see that everything is in order. | |
| 1028 window1_owner.reset(); | |
| 1029 EXPECT_EQ("b,C,X", | |
| 1030 GetWindowOrderAsString(backdrop, window1, window2, window3)); | |
| 1031 window3_owner.reset(); | |
| 1032 EXPECT_EQ("b,x", GetWindowOrderAsString(backdrop, window1, window2, window3)); | |
| 1033 ShowTopWindowBackdrop(false); | |
| 1034 EXPECT_EQ("b", GetWindowOrderAsString(nullptr, window1, window2, window3)); | |
| 1035 } | |
| 1036 | |
| 1037 // Tests that when hidding the shelf, that the backdrop resizes to fill the | |
| 1038 // entire workspace area. | |
| 1039 TEST_F(WorkspaceLayoutManagerBackdropTest, ShelfVisibilityChangesBounds) { | |
| 1040 // TODO: Triggers crash in mash: http://crbug.com/652871. | |
| 1041 if (WmShell::Get()->IsRunningInMash()) | |
| 1042 return; | |
| 1043 | |
| 1044 WmShelf* shelf = GetPrimaryShelf(); | |
| 1045 ShelfLayoutManager* shelf_layout_manager = shelf->shelf_layout_manager(); | |
| 1046 ShowTopWindowBackdrop(true); | |
| 1047 RunAllPendingInMessageLoop(); | |
| 1048 | |
| 1049 ASSERT_EQ(SHELF_VISIBLE, shelf_layout_manager->visibility_state()); | |
| 1050 gfx::Rect initial_bounds = default_container()->GetChildren()[0]->GetBounds(); | |
| 1051 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN); | |
| 1052 shelf_layout_manager->UpdateVisibilityState(); | |
| 1053 | |
| 1054 // When the shelf is re-shown WorkspaceLayoutManager shrinks all children | |
| 1055 // including the backdrop. | |
| 1056 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); | |
| 1057 shelf_layout_manager->UpdateVisibilityState(); | |
| 1058 gfx::Rect reduced_bounds = default_container()->GetChildren()[0]->GetBounds(); | |
| 1059 EXPECT_LT(reduced_bounds.height(), initial_bounds.height()); | |
| 1060 | |
| 1061 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN); | |
| 1062 shelf_layout_manager->UpdateVisibilityState(); | |
| 1063 | |
| 1064 EXPECT_GT(default_container()->GetChildren()[0]->GetBounds().height(), | |
| 1065 reduced_bounds.height()); | |
| 1066 } | |
| 1067 | |
| 1068 class WorkspaceLayoutManagerKeyboardTest : public AshTest { | |
| 1069 public: | |
| 1070 WorkspaceLayoutManagerKeyboardTest() : layout_manager_(nullptr) {} | |
| 1071 ~WorkspaceLayoutManagerKeyboardTest() override {} | |
| 1072 | |
| 1073 void SetUp() override { | |
| 1074 AshTest::SetUp(); | |
| 1075 UpdateDisplay("800x600"); | |
| 1076 WmWindow* default_container = | |
| 1077 WmShell::Get()->GetPrimaryRootWindowController()->GetContainer( | |
| 1078 kShellWindowId_DefaultContainer); | |
| 1079 layout_manager_ = GetWorkspaceLayoutManager(default_container); | |
| 1080 } | |
| 1081 | |
| 1082 void ShowKeyboard() { | |
| 1083 layout_manager_->OnKeyboardBoundsChanging(keyboard_bounds_); | |
| 1084 restore_work_area_insets_ = | |
| 1085 display::Screen::GetScreen()->GetPrimaryDisplay().GetWorkAreaInsets(); | |
| 1086 WmShell::Get()->SetDisplayWorkAreaInsets( | |
| 1087 WmShell::Get()->GetPrimaryRootWindow(), | |
| 1088 gfx::Insets(0, 0, keyboard_bounds_.height(), 0)); | |
| 1089 } | |
| 1090 | |
| 1091 void HideKeyboard() { | |
| 1092 WmShell::Get()->SetDisplayWorkAreaInsets( | |
| 1093 WmShell::Get()->GetPrimaryRootWindow(), restore_work_area_insets_); | |
| 1094 layout_manager_->OnKeyboardBoundsChanging(gfx::Rect()); | |
| 1095 } | |
| 1096 | |
| 1097 // Initializes the keyboard bounds using the bottom half of the work area. | |
| 1098 void InitKeyboardBounds() { | |
| 1099 gfx::Rect work_area( | |
| 1100 display::Screen::GetScreen()->GetPrimaryDisplay().work_area()); | |
| 1101 keyboard_bounds_.SetRect(work_area.x(), | |
| 1102 work_area.y() + work_area.height() / 2, | |
| 1103 work_area.width(), work_area.height() / 2); | |
| 1104 } | |
| 1105 | |
| 1106 void EnableNewVKMode() { | |
| 1107 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | |
| 1108 if (!command_line->HasSwitch(::switches::kUseNewVirtualKeyboardBehavior)) | |
| 1109 command_line->AppendSwitch(::switches::kUseNewVirtualKeyboardBehavior); | |
| 1110 } | |
| 1111 | |
| 1112 const gfx::Rect& keyboard_bounds() const { return keyboard_bounds_; } | |
| 1113 | |
| 1114 private: | |
| 1115 gfx::Insets restore_work_area_insets_; | |
| 1116 gfx::Rect keyboard_bounds_; | |
| 1117 WorkspaceLayoutManager* layout_manager_; | |
| 1118 | |
| 1119 DISALLOW_COPY_AND_ASSIGN(WorkspaceLayoutManagerKeyboardTest); | |
| 1120 }; | |
| 1121 | |
| 1122 // Tests that when a child window gains focus the top level window containing it | |
| 1123 // is resized to fit the remaining workspace area. | |
| 1124 TEST_F(WorkspaceLayoutManagerKeyboardTest, ChildWindowFocused) { | |
| 1125 InitKeyboardBounds(); | |
| 1126 | |
| 1127 gfx::Rect work_area( | |
| 1128 display::Screen::GetScreen()->GetPrimaryDisplay().work_area()); | |
| 1129 | |
| 1130 std::unique_ptr<WindowOwner> parent_window_owner( | |
| 1131 CreateToplevelTestWindow(work_area)); | |
| 1132 WmWindow* parent_window = parent_window_owner->window(); | |
| 1133 std::unique_ptr<WindowOwner> window_owner(CreateTestWindow(work_area)); | |
| 1134 WmWindow* window = window_owner->window(); | |
| 1135 parent_window->AddChild(window); | |
| 1136 | |
| 1137 window->Activate(); | |
| 1138 | |
| 1139 int available_height = | |
| 1140 display::Screen::GetScreen()->GetPrimaryDisplay().bounds().height() - | |
| 1141 keyboard_bounds().height(); | |
| 1142 | |
| 1143 gfx::Rect initial_window_bounds(50, 50, 100, 500); | |
| 1144 parent_window->SetBounds(initial_window_bounds); | |
| 1145 EXPECT_EQ(initial_window_bounds.ToString(), | |
| 1146 parent_window->GetBounds().ToString()); | |
| 1147 ShowKeyboard(); | |
| 1148 EXPECT_EQ(gfx::Rect(50, 0, 100, available_height).ToString(), | |
| 1149 parent_window->GetBounds().ToString()); | |
| 1150 HideKeyboard(); | |
| 1151 EXPECT_EQ(initial_window_bounds.ToString(), | |
| 1152 parent_window->GetBounds().ToString()); | |
| 1153 } | |
| 1154 | |
| 1155 TEST_F(WorkspaceLayoutManagerKeyboardTest, AdjustWindowForA11yKeyboard) { | |
| 1156 InitKeyboardBounds(); | |
| 1157 gfx::Rect work_area( | |
| 1158 display::Screen::GetScreen()->GetPrimaryDisplay().work_area()); | |
| 1159 | |
| 1160 std::unique_ptr<WindowOwner> window_owner( | |
| 1161 CreateToplevelTestWindow(work_area)); | |
| 1162 WmWindow* window = window_owner->window(); | |
| 1163 | |
| 1164 int available_height = | |
| 1165 display::Screen::GetScreen()->GetPrimaryDisplay().bounds().height() - | |
| 1166 keyboard_bounds().height(); | |
| 1167 | |
| 1168 window->Activate(); | |
| 1169 | |
| 1170 EXPECT_EQ(gfx::Rect(work_area).ToString(), window->GetBounds().ToString()); | |
| 1171 ShowKeyboard(); | |
| 1172 EXPECT_EQ(gfx::Rect(work_area.origin(), | |
| 1173 gfx::Size(work_area.width(), available_height)) | |
| 1174 .ToString(), | |
| 1175 window->GetBounds().ToString()); | |
| 1176 HideKeyboard(); | |
| 1177 EXPECT_EQ(gfx::Rect(work_area).ToString(), window->GetBounds().ToString()); | |
| 1178 | |
| 1179 gfx::Rect small_window_bound(50, 50, 100, 500); | |
| 1180 window->SetBounds(small_window_bound); | |
| 1181 EXPECT_EQ(small_window_bound.ToString(), window->GetBounds().ToString()); | |
| 1182 ShowKeyboard(); | |
| 1183 EXPECT_EQ(gfx::Rect(50, 0, 100, available_height).ToString(), | |
| 1184 window->GetBounds().ToString()); | |
| 1185 HideKeyboard(); | |
| 1186 EXPECT_EQ(small_window_bound.ToString(), window->GetBounds().ToString()); | |
| 1187 | |
| 1188 gfx::Rect occluded_window_bounds( | |
| 1189 50, keyboard_bounds().y() + keyboard_bounds().height() / 2, 50, | |
| 1190 keyboard_bounds().height() / 2); | |
| 1191 window->SetBounds(occluded_window_bounds); | |
| 1192 EXPECT_EQ(occluded_window_bounds.ToString(), | |
| 1193 occluded_window_bounds.ToString()); | |
| 1194 ShowKeyboard(); | |
| 1195 EXPECT_EQ( | |
| 1196 gfx::Rect(50, keyboard_bounds().y() - keyboard_bounds().height() / 2, | |
| 1197 occluded_window_bounds.width(), occluded_window_bounds.height()) | |
| 1198 .ToString(), | |
| 1199 window->GetBounds().ToString()); | |
| 1200 HideKeyboard(); | |
| 1201 EXPECT_EQ(occluded_window_bounds.ToString(), window->GetBounds().ToString()); | |
| 1202 } | |
| 1203 | |
| 1204 TEST_F(WorkspaceLayoutManagerKeyboardTest, IgnoreKeyboardBoundsChange) { | |
| 1205 InitKeyboardBounds(); | |
| 1206 | |
| 1207 std::unique_ptr<WindowOwner> window_owner( | |
| 1208 CreateTestWindow(keyboard_bounds())); | |
| 1209 WmWindow* window = window_owner->window(); | |
| 1210 window->GetWindowState()->set_ignore_keyboard_bounds_change(true); | |
| 1211 window->Activate(); | |
| 1212 | |
| 1213 EXPECT_EQ(keyboard_bounds(), window->GetBounds()); | |
| 1214 ShowKeyboard(); | |
| 1215 EXPECT_EQ(keyboard_bounds(), window->GetBounds()); | |
| 1216 } | |
| 1217 | |
| 1218 TEST_F(WorkspaceLayoutManagerKeyboardTest, ChangeWorkAreaInNonStickyMode) { | |
| 1219 keyboard::SetAccessibilityKeyboardEnabled(true); | |
| 1220 InitKeyboardBounds(); | |
| 1221 Shell::GetInstance()->CreateKeyboard(); | |
| 1222 keyboard::KeyboardController* kb_controller = | |
| 1223 keyboard::KeyboardController::GetInstance(); | |
| 1224 | |
| 1225 gfx::Rect work_area( | |
| 1226 display::Screen::GetScreen()->GetPrimaryDisplay().work_area()); | |
| 1227 | |
| 1228 gfx::Rect orig_window_bounds(0, 100, work_area.width(), | |
| 1229 work_area.height() - 100); | |
| 1230 std::unique_ptr<WindowOwner> window_owner( | |
| 1231 CreateToplevelTestWindow(orig_window_bounds)); | |
| 1232 WmWindow* window = window_owner->window(); | |
| 1233 | |
| 1234 window->Activate(); | |
| 1235 EXPECT_EQ(orig_window_bounds, window->GetBounds()); | |
| 1236 | |
| 1237 // Open keyboard in non-sticky mode. | |
| 1238 kb_controller->ShowKeyboard(false); | |
| 1239 kb_controller->ui()->GetKeyboardWindow()->SetBounds( | |
| 1240 keyboard::FullWidthKeyboardBoundsFromRootBounds( | |
| 1241 WmShell::Get()->GetPrimaryRootWindow()->GetBounds(), 100)); | |
| 1242 | |
| 1243 int shift = | |
| 1244 work_area.height() - kb_controller->GetContainerWindow()->bounds().y(); | |
| 1245 gfx::Rect changed_window_bounds(orig_window_bounds); | |
| 1246 changed_window_bounds.Offset(0, -shift); | |
| 1247 // Window should be shifted up. | |
| 1248 EXPECT_EQ(changed_window_bounds, window->GetBounds()); | |
| 1249 | |
| 1250 kb_controller->HideKeyboard( | |
| 1251 keyboard::KeyboardController::HIDE_REASON_AUTOMATIC); | |
| 1252 EXPECT_EQ(orig_window_bounds, window->GetBounds()); | |
| 1253 | |
| 1254 // Open keyboard in sticky mode. | |
| 1255 kb_controller->ShowKeyboard(true); | |
| 1256 | |
| 1257 // Window should be shifted up. | |
| 1258 EXPECT_EQ(changed_window_bounds, window->GetBounds()); | |
| 1259 | |
| 1260 kb_controller->HideKeyboard( | |
| 1261 keyboard::KeyboardController::HIDE_REASON_AUTOMATIC); | |
| 1262 EXPECT_EQ(orig_window_bounds, window->GetBounds()); | |
| 1263 } | |
| 1264 | |
| 1265 // When kAshUseNewVKWindowBehavior flag enabled, do not change accessibility | |
| 1266 // keyboard work area in non-sticky mode. | |
| 1267 TEST_F(WorkspaceLayoutManagerKeyboardTest, | |
| 1268 IgnoreWorkAreaChangeinNonStickyMode) { | |
| 1269 // Append flag to ignore work area change in non-sticky mode. | |
| 1270 EnableNewVKMode(); | |
| 1271 | |
| 1272 keyboard::SetAccessibilityKeyboardEnabled(true); | |
| 1273 InitKeyboardBounds(); | |
| 1274 Shell::GetInstance()->CreateKeyboard(); | |
| 1275 keyboard::KeyboardController* kb_controller = | |
| 1276 keyboard::KeyboardController::GetInstance(); | |
| 1277 | |
| 1278 gfx::Rect work_area( | |
| 1279 display::Screen::GetScreen()->GetPrimaryDisplay().work_area()); | |
| 1280 | |
| 1281 gfx::Rect orig_window_bounds(0, 100, work_area.width(), | |
| 1282 work_area.height() - 100); | |
| 1283 std::unique_ptr<WindowOwner> window_owner( | |
| 1284 CreateToplevelTestWindow(orig_window_bounds)); | |
| 1285 WmWindow* window = window_owner->window(); | |
| 1286 | |
| 1287 window->Activate(); | |
| 1288 EXPECT_EQ(orig_window_bounds, window->GetBounds()); | |
| 1289 | |
| 1290 // Open keyboard in non-sticky mode. | |
| 1291 kb_controller->ShowKeyboard(false); | |
| 1292 kb_controller->ui()->GetKeyboardWindow()->SetBounds( | |
| 1293 keyboard::FullWidthKeyboardBoundsFromRootBounds( | |
| 1294 WmShell::Get()->GetPrimaryRootWindow()->GetBounds(), 100)); | |
| 1295 | |
| 1296 // Window should not be shifted up. | |
| 1297 EXPECT_EQ(orig_window_bounds, window->GetBounds()); | |
| 1298 | |
| 1299 kb_controller->HideKeyboard( | |
| 1300 keyboard::KeyboardController::HIDE_REASON_AUTOMATIC); | |
| 1301 EXPECT_EQ(orig_window_bounds, window->GetBounds()); | |
| 1302 | |
| 1303 // Open keyboard in sticky mode. | |
| 1304 kb_controller->ShowKeyboard(true); | |
| 1305 | |
| 1306 int shift = | |
| 1307 work_area.height() - kb_controller->GetContainerWindow()->bounds().y(); | |
| 1308 gfx::Rect changed_window_bounds(orig_window_bounds); | |
| 1309 changed_window_bounds.Offset(0, -shift); | |
| 1310 // Window should be shifted up. | |
| 1311 EXPECT_EQ(changed_window_bounds, window->GetBounds()); | |
| 1312 | |
| 1313 kb_controller->HideKeyboard( | |
| 1314 keyboard::KeyboardController::HIDE_REASON_AUTOMATIC); | |
| 1315 EXPECT_EQ(orig_window_bounds, window->GetBounds()); | |
| 1316 } | |
| 1317 | |
| 1318 } // namespace ash | |
| OLD | NEW |