Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / ash / wm / workspace / snap_sizer_unittest.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/wm/workspace/snap_sizer.h"
6
7 #include "ash/ash_switches.h"
8 #include "ash/screen_util.h"
9 #include "ash/shell.h"
10 #include "ash/test/ash_test_base.h"
11 #include "ash/wm/window_state.h"
12 #include "ash/wm/window_util.h"
13 #include "base/command_line.h"
14 #include "ui/aura/root_window.h"
15 #include "ui/aura/test/test_window_delegate.h"
16 #include "ui/aura/window.h"
17 #include "ui/gfx/screen.h"
18
19 namespace ash {
20
21 typedef test::AshTestBase SnapSizerTest;
22
23 using internal::SnapSizer;
24
25 // Test that a window gets properly snapped to the display's edges in a
26 // multi monitor environment.
27 TEST_F(SnapSizerTest, MultipleDisplays) {
28   if (!SupportsMultipleDisplays())
29     return;
30
31   UpdateDisplay("0+0-500x400, 0+500-600x400");
32   const gfx::Rect kPrimaryDisplayWorkAreaBounds =
33       ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
34   const gfx::Rect kSecondaryDisplayWorkAreaBounds =
35       ScreenUtil::GetSecondaryDisplay().work_area();
36
37   scoped_ptr<aura::Window> window(
38       CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
39   wm::WindowState* window_state = wm::GetWindowState(window.get());
40   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
41   gfx::Rect expected = gfx::Rect(
42       kPrimaryDisplayWorkAreaBounds.x(),
43       kPrimaryDisplayWorkAreaBounds.y(),
44       window->bounds().width(), // No expectation for the width.
45       kPrimaryDisplayWorkAreaBounds.height());
46   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
47
48   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
49   // The width should not change when a window switches from being snapped to
50   // the left edge to being snapped to the right edge.
51   expected.set_x(kPrimaryDisplayWorkAreaBounds.right() - expected.width());
52   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
53
54   // Move the window to the secondary display.
55   window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100),
56                             ScreenUtil::GetSecondaryDisplay());
57
58   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
59   expected = gfx::Rect(
60       kSecondaryDisplayWorkAreaBounds.right() - window->bounds().width(),
61       kSecondaryDisplayWorkAreaBounds.y(),
62       window->bounds().width(),  // No expectation for the width.
63       kSecondaryDisplayWorkAreaBounds.height());
64   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
65
66   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
67   // The width should not change when a window switches from being snapped to
68   // the right edge to being snapped to the left edge.
69   expected.set_x(kSecondaryDisplayWorkAreaBounds.x());
70   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
71 }
72
73 // Test how the minimum and maximum size specified by the aura::WindowDelegate
74 // affect snapping.
75 TEST_F(SnapSizerTest, MinimumSize) {
76   if (!SupportsHostWindowResize())
77     return;
78
79   UpdateDisplay("0+0-600x800");
80   const gfx::Rect kWorkAreaBounds =
81       ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
82
83   aura::test::TestWindowDelegate delegate;
84   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
85       &delegate, -1, gfx::Rect(0, 100, kWorkAreaBounds.width() - 1, 100)));
86
87   // It should be possible to snap a window with a minimum size.
88   delegate.set_minimum_size(gfx::Size(kWorkAreaBounds.width() - 1, 0));
89   wm::WindowState* window_state = wm::GetWindowState(window.get());
90   EXPECT_TRUE(window_state->CanSnap());
91   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
92   gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x() + 1,
93                                  kWorkAreaBounds.y(),
94                                  kWorkAreaBounds.width() - 1,
95                                  kWorkAreaBounds.height());
96   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
97
98   // It should not be possible to snap a window with a maximum size.
99   delegate.set_minimum_size(gfx::Size());
100   delegate.set_maximum_size(gfx::Size(kWorkAreaBounds.width() - 1, INT_MAX));
101   EXPECT_FALSE(window_state->CanSnap());
102 }
103
104 // Test that repeatedly calling SnapSizer::SnapWindow() when the
105 // --ash-multiple-snap-window-widths flag is set steps through the ideal widths
106 // in descending order as well as 90% and 50% of the work area's width.
107 TEST_F(SnapSizerTest, StepThroughSizes) {
108   if (!SupportsHostWindowResize())
109     return;
110   CommandLine::ForCurrentProcess()->AppendSwitch(
111       switches::kAshMultipleSnapWindowWidths);
112
113   UpdateDisplay("1024x800");
114   const gfx::Rect kWorkAreaBounds =
115       ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
116
117   scoped_ptr<aura::Window> window(
118       CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
119   wm::WindowState* window_state = wm::GetWindowState(window.get());
120
121   // Make sure that the work area is the size we expect it to be.
122   EXPECT_GT(kWorkAreaBounds.width() * 0.9, 768);
123
124   // The first width should be 1024 * 0.9 because the larger ideal widths
125   // (1280, 1024) > 1024 * 0.9.
126   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
127   gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(),
128                                  kWorkAreaBounds.y(),
129                                  kWorkAreaBounds.width() * 0.9,
130                                  kWorkAreaBounds.height());
131   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
132
133   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
134   expected.set_width(768);
135   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
136
137   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
138   expected.set_width(640);
139   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
140
141   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
142   expected.set_width(kWorkAreaBounds.width() * 0.5);
143   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
144
145   // Wrap around.
146   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
147   expected.set_width(kWorkAreaBounds.width() * 0.9);
148   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
149
150   // Repeat the test snapping right.
151   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
152   expected.set_width(kWorkAreaBounds.width() * 0.9);
153   expected.set_x(kWorkAreaBounds.right() - expected.width());
154   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
155
156   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
157   expected.set_width(768);
158   expected.set_x(kWorkAreaBounds.right() - expected.width());
159   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
160
161   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
162   expected.set_width(640);
163   expected.set_x(kWorkAreaBounds.right() - expected.width());
164   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
165
166   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
167   expected.set_width(kWorkAreaBounds.width() * 0.5);
168   expected.set_x(kWorkAreaBounds.right() - expected.width());
169   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
170
171   // Wrap around.
172   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
173   expected.set_width(kWorkAreaBounds.width() * 0.9);
174   expected.set_x(kWorkAreaBounds.right() - expected.width());
175   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
176 }
177
178 // Test that a SnapSizer's target bounds always start from the widest possible
179 // bounds and that calling Update() steps through the ideal widths in descending
180 // order as well as 90% and 50% of the work area's width.
181 TEST_F(SnapSizerTest, Update) {
182   if (!SupportsHostWindowResize())
183     return;
184   CommandLine::ForCurrentProcess()->AppendSwitch(
185       switches::kAshMultipleSnapWindowWidths);
186   UpdateDisplay("1024x800");
187   const gfx::Rect kWorkAreaBounds =
188       ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
189
190   // Make sure that the work area is the size we expect it to be.
191   EXPECT_GT(kWorkAreaBounds.width() * 0.9, 768);
192
193   scoped_ptr<aura::Window> window(
194       CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
195   wm::WindowState* window_state = wm::GetWindowState(window.get());
196
197   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
198   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
199   gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(),
200                                  kWorkAreaBounds.y(),
201                                  768,
202                                  kWorkAreaBounds.height());
203
204   // The SnapSizer's target bounds should always start from the widest bounds
205   // (instead of the bounds with the next ideal width).
206   SnapSizer sizer(window_state, gfx::Point(800, 0), SnapSizer::LEFT_EDGE,
207       SnapSizer::OTHER_INPUT);
208   sizer.SnapWindowToTargetBounds();
209   expected.set_width(kWorkAreaBounds.width() * .9);
210   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
211
212   sizer.Update(gfx::Point(600, 0));
213   sizer.SnapWindowToTargetBounds();
214   expected.set_width(768);
215   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
216
217   sizer.Update(gfx::Point(400, 0));
218   sizer.SnapWindowToTargetBounds();
219   expected.set_width(640);
220   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
221
222   sizer.Update(gfx::Point(200, 0));
223   sizer.SnapWindowToTargetBounds();
224   expected.set_width(kWorkAreaBounds.width() * 0.5);
225   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
226
227   // Do not wrap around.
228   sizer.Update(gfx::Point(0, 0));
229   sizer.SnapWindowToTargetBounds();
230   expected.set_width(kWorkAreaBounds.width() * 0.5);
231   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
232 }
233
234 // Tests the SnapSizer's target bounds when resizing is disabled and the
235 // --ash-multiple-snap-window-widths flag is set.
236 TEST_F(SnapSizerTest, Default) {
237   if (!SupportsHostWindowResize())
238     return;
239   CommandLine::ForCurrentProcess()->AppendSwitch(
240       switches::kAshMultipleSnapWindowWidths);
241
242   scoped_ptr<aura::Window> window(
243       CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
244   SnapSizer sizer(wm::GetWindowState(window.get()), gfx::Point(),
245                   SnapSizer::LEFT_EDGE, SnapSizer::OTHER_INPUT);
246
247   // For small workspace widths, we should snap to 90% of the workspace width
248   // because it is the largest width the window can snap to.
249   UpdateDisplay("0+0-800x600");
250   sizer.SelectDefaultSizeAndDisableResize();
251
252   gfx::Rect work_area =
253       ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
254   gfx::Rect expected(work_area);
255   expected.set_width(work_area.width() * 0.9);
256   EXPECT_EQ(expected.ToString(),
257             ScreenUtil::ConvertRectToScreen(window->parent(),
258                                             sizer.target_bounds()).ToString());
259
260   // If the largest width the window can snap to is between 1024 and 1280, we
261   // should snap to 1024.
262   UpdateDisplay("0+0-1280x800");
263   sizer.SelectDefaultSizeAndDisableResize();
264   sizer.SnapWindowToTargetBounds();
265   EXPECT_EQ(1024, window->bounds().width());
266
267   // We should snap to a width of 50% of the work area if it is the largest
268   // width the window can snap to.
269   UpdateDisplay("0+0-2560x1080");
270   work_area = ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
271   sizer.SelectDefaultSizeAndDisableResize();
272   sizer.SnapWindowToTargetBounds();
273   EXPECT_EQ(work_area.width() / 2, window->bounds().width());
274 }
275
276 // Test that the window only snaps to 50% of the work area width when the
277 // --ash-multiple-snap-window-widths flag is not set.
278 TEST_F(SnapSizerTest, SingleSnapWindowWidth) {
279   if (!SupportsHostWindowResize())
280     return;
281
282   if (CommandLine::ForCurrentProcess()->HasSwitch(
283           switches::kAshMultipleSnapWindowWidths)) {
284     return;
285   }
286
287   UpdateDisplay("0+0-800x600");
288   const gfx::Rect kWorkAreaBounds =
289       ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
290
291   scoped_ptr<aura::Window> window(
292       CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
293   wm::WindowState* window_state = wm::GetWindowState(window.get());
294   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
295   gfx::Rect expected = gfx::Rect(kWorkAreaBounds.x(),
296                                  kWorkAreaBounds.y(),
297                                  kWorkAreaBounds.width() / 2,
298                                  kWorkAreaBounds.height());
299   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
300
301   // Because a window can only be snapped to one size when using the alternate
302   // caption button style, a second call to SnapSizer::SnapWindow() should have
303   // no effect.
304   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
305   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
306
307   // It should still be possible to switch a window from being snapped to the
308   // left edge to being snapped to the right edge.
309   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
310   expected.set_x(kWorkAreaBounds.right() - expected.width());
311   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
312
313   // If resizing is disabled, the window should be snapped to 50% too.
314   SnapSizer sizer1(window_state, gfx::Point(), SnapSizer::RIGHT_EDGE,
315       SnapSizer::OTHER_INPUT);
316   sizer1.SelectDefaultSizeAndDisableResize();
317   sizer1.SnapWindowToTargetBounds();
318   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
319
320   // Snapping to a SnapSizer's initial bounds snaps to 50% too.
321   SnapSizer sizer2(window_state, gfx::Point(), SnapSizer::LEFT_EDGE,
322       SnapSizer::OTHER_INPUT);
323   sizer2.SnapWindowToTargetBounds();
324   expected.set_x(kWorkAreaBounds.x());
325   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
326   EXPECT_EQ(wm::SHOW_TYPE_LEFT_SNAPPED, window_state->window_show_type());
327
328   // Setting bounds should keep the window snapped.
329   expected = kWorkAreaBounds;
330   expected.set_width(500);
331   window->SetBounds(gfx::Rect(10, 10, 500, 300));
332   EXPECT_EQ(expected.ToString(), window->GetBoundsInScreen().ToString());
333 }
334
335 // Test that snapping left/right preserves the restore bounds.
336 TEST_F(SnapSizerTest, RestoreBounds) {
337   scoped_ptr<aura::Window> window(
338       CreateTestWindowInShellWithBounds(gfx::Rect(100, 100, 100, 100)));
339   wm::WindowState* window_state = wm::GetWindowState(window.get());
340
341   EXPECT_TRUE(window_state->IsNormalShowState());
342
343   // 1) Start with restored window with restore bounds set.
344   gfx::Rect restore_bounds = window->GetBoundsInScreen();
345   restore_bounds.set_width(restore_bounds.width() + 1);
346   window_state->SetRestoreBoundsInScreen(restore_bounds);
347   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
348   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
349   EXPECT_NE(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
350   EXPECT_EQ(restore_bounds.ToString(),
351             window_state->GetRestoreBoundsInScreen().ToString());
352   window_state->Restore();
353   EXPECT_EQ(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
354
355   // 2) Start with restored bounds set as a result of maximizing the window.
356   window_state->Maximize();
357   gfx::Rect maximized_bounds = window->GetBoundsInScreen();
358   EXPECT_NE(maximized_bounds.ToString(), restore_bounds.ToString());
359   EXPECT_EQ(restore_bounds.ToString(),
360             window_state->GetRestoreBoundsInScreen().ToString());
361
362   SnapSizer::SnapWindow(window_state, SnapSizer::LEFT_EDGE);
363   EXPECT_NE(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
364   EXPECT_NE(maximized_bounds.ToString(),
365             window->GetBoundsInScreen().ToString());
366   EXPECT_EQ(restore_bounds.ToString(),
367             window_state->GetRestoreBoundsInScreen().ToString());
368
369   window_state->Restore();
370   EXPECT_EQ(restore_bounds.ToString(), window->GetBoundsInScreen().ToString());
371 }
372
373 // Test that maximizing an auto managed window, then snapping it puts the window
374 // at the snapped bounds and not at the auto-managed (centered) bounds.
375 TEST_F(SnapSizerTest, AutoManaged) {
376   scoped_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
377   wm::WindowState* window_state = wm::GetWindowState(window.get());
378   window_state->set_window_position_managed(true);
379   window->Hide();
380   window->SetBounds(gfx::Rect(100, 100, 100, 100));
381   window->Show();
382
383   window_state->Maximize();
384   SnapSizer::SnapWindow(window_state, SnapSizer::RIGHT_EDGE);
385
386   const gfx::Rect kWorkAreaBounds =
387       ash::Shell::GetScreen()->GetPrimaryDisplay().work_area();
388   gfx::Rect expected_snapped_bounds(
389       kWorkAreaBounds.right() - window->bounds().width(),
390       kWorkAreaBounds.y(),
391       window->bounds().width(), // No expectation for the width.
392       kWorkAreaBounds.height());
393   EXPECT_EQ(expected_snapped_bounds.ToString(),
394             window->GetBoundsInScreen().ToString());
395
396   // The window should still be auto managed despite being right maximized.
397   EXPECT_TRUE(window_state->window_position_managed());
398 }
399
400 }  // namespace ash