Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1231)

Side by Side Diff: ash/wm/workspace/workspace_layout_manager_unittest.cc

Issue 2703853003: Remove unreferenced workspace_layout_manager_unittest.cc (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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], &params);
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698