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

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

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

Powered by Google App Engine
This is Rietveld 408576698