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