Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ash / wm / panels / panel_layout_manager_unittest.cc
blobe43ecaa61424981e11a2ae79e05e67e874150417
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.
5 #include "ash/wm/panels/panel_layout_manager.h"
7 #include "ash/ash_switches.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/screen_util.h"
10 #include "ash/shelf/shelf.h"
11 #include "ash/shelf/shelf_button.h"
12 #include "ash/shelf/shelf_layout_manager.h"
13 #include "ash/shelf/shelf_model.h"
14 #include "ash/shelf/shelf_types.h"
15 #include "ash/shelf/shelf_util.h"
16 #include "ash/shelf/shelf_view.h"
17 #include "ash/shelf/shelf_widget.h"
18 #include "ash/shell.h"
19 #include "ash/shell_window_ids.h"
20 #include "ash/test/ash_test_base.h"
21 #include "ash/test/shelf_test_api.h"
22 #include "ash/test/shelf_view_test_api.h"
23 #include "ash/test/shell_test_api.h"
24 #include "ash/test/test_shelf_delegate.h"
25 #include "ash/wm/mru_window_tracker.h"
26 #include "ash/wm/window_state.h"
27 #include "ash/wm/window_util.h"
28 #include "base/basictypes.h"
29 #include "base/command_line.h"
30 #include "base/compiler_specific.h"
31 #include "base/i18n/rtl.h"
32 #include "base/run_loop.h"
33 #include "ui/aura/client/aura_constants.h"
34 #include "ui/aura/test/test_windows.h"
35 #include "ui/aura/window.h"
36 #include "ui/aura/window_event_dispatcher.h"
37 #include "ui/base/l10n/l10n_util.h"
38 #include "ui/events/event_utils.h"
39 #include "ui/events/test/event_generator.h"
40 #include "ui/views/widget/widget.h"
42 namespace ash {
44 using aura::test::WindowIsAbove;
46 class PanelLayoutManagerTest : public test::AshTestBase {
47 public:
48 PanelLayoutManagerTest() {}
49 ~PanelLayoutManagerTest() override {}
51 void SetUp() override {
52 test::AshTestBase::SetUp();
53 ASSERT_TRUE(test::TestShelfDelegate::instance());
55 shelf_view_test_.reset(new test::ShelfViewTestAPI(
56 GetShelfView(Shelf::ForPrimaryDisplay())));
57 shelf_view_test_->SetAnimationDuration(1);
60 aura::Window* CreateNormalWindow(const gfx::Rect& bounds) {
61 return CreateTestWindowInShellWithBounds(bounds);
64 aura::Window* CreatePanelWindowWithDelegate(aura::WindowDelegate* delegate,
65 const gfx::Rect& bounds) {
66 aura::Window* window = CreateTestWindowInShellWithDelegateAndType(
67 delegate, ui::wm::WINDOW_TYPE_PANEL, 0, bounds);
68 test::TestShelfDelegate* shelf_delegate =
69 test::TestShelfDelegate::instance();
70 shelf_delegate->AddShelfItem(window);
71 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
72 return window;
75 aura::Window* CreatePanelWindow(const gfx::Rect& bounds) {
76 return CreatePanelWindowWithDelegate(NULL, bounds);
79 aura::Window* GetPanelContainer(aura::Window* panel) {
80 return Shell::GetContainer(panel->GetRootWindow(),
81 kShellWindowId_PanelContainer);
84 views::Widget* GetCalloutWidgetForPanel(aura::Window* panel) {
85 PanelLayoutManager* manager =
86 static_cast<PanelLayoutManager*>(GetPanelContainer(panel)->
87 layout_manager());
88 DCHECK(manager);
89 PanelLayoutManager::PanelList::iterator found = std::find(
90 manager->panel_windows_.begin(), manager->panel_windows_.end(),
91 panel);
92 DCHECK(found != manager->panel_windows_.end());
93 DCHECK(found->callout_widget);
94 return reinterpret_cast<views::Widget*>(found->callout_widget);
97 void PanelInScreen(aura::Window* panel) {
98 gfx::Rect panel_bounds = panel->GetBoundsInRootWindow();
99 gfx::Point root_point = gfx::Point(panel_bounds.x(), panel_bounds.y());
100 gfx::Display display = ScreenUtil::FindDisplayContainingPoint(root_point);
102 gfx::Rect panel_bounds_in_screen = panel->GetBoundsInScreen();
103 gfx::Point screen_bottom_right = gfx::Point(
104 panel_bounds_in_screen.right(),
105 panel_bounds_in_screen.bottom());
106 gfx::Rect display_bounds = display.bounds();
107 EXPECT_TRUE(screen_bottom_right.x() < display_bounds.width() &&
108 screen_bottom_right.y() < display_bounds.height());
111 void PanelsNotOverlapping(aura::Window* panel1, aura::Window* panel2) {
112 // Waits until all shelf view animations are done.
113 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
114 gfx::Rect window1_bounds = panel1->GetBoundsInRootWindow();
115 gfx::Rect window2_bounds = panel2->GetBoundsInRootWindow();
117 EXPECT_FALSE(window1_bounds.Intersects(window2_bounds));
120 void IsPanelAboveLauncherIcon(const aura::Window* panel) {
121 // Waits until all shelf view animations are done.
122 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
124 Shelf* shelf = RootWindowController::ForShelf(panel)->shelf()->shelf();
125 gfx::Rect icon_bounds = shelf->GetScreenBoundsOfItemIconForWindow(panel);
126 ASSERT_FALSE(icon_bounds.width() == 0 && icon_bounds.height() == 0);
128 gfx::Rect window_bounds = panel->GetBoundsInScreen();
129 ASSERT_LT(icon_bounds.width(), window_bounds.width());
130 ASSERT_LT(icon_bounds.height(), window_bounds.height());
131 gfx::Rect shelf_bounds = shelf->shelf_widget()->GetWindowBoundsInScreen();
132 ShelfAlignment alignment = GetAlignment(panel->GetRootWindow());
134 if (IsHorizontal(alignment)) {
135 // The horizontal bounds of the panel window should contain the bounds of
136 // the shelf icon.
137 EXPECT_LE(window_bounds.x(), icon_bounds.x());
138 EXPECT_GE(window_bounds.right(), icon_bounds.right());
139 } else {
140 // The vertical bounds of the panel window should contain the bounds of
141 // the shelf icon.
142 EXPECT_LE(window_bounds.y(), icon_bounds.y());
143 EXPECT_GE(window_bounds.bottom(), icon_bounds.bottom());
146 switch (alignment) {
147 case SHELF_ALIGNMENT_BOTTOM:
148 EXPECT_EQ(shelf_bounds.y(), window_bounds.bottom());
149 break;
150 case SHELF_ALIGNMENT_LEFT:
151 EXPECT_EQ(shelf_bounds.right(), window_bounds.x());
152 break;
153 case SHELF_ALIGNMENT_RIGHT:
154 EXPECT_EQ(shelf_bounds.x(), window_bounds.right());
155 break;
156 case SHELF_ALIGNMENT_TOP:
157 EXPECT_EQ(shelf_bounds.bottom(), window_bounds.y());
158 break;
162 void IsCalloutAboveLauncherIcon(aura::Window* panel) {
163 // Flush the message loop, since callout updates use a delayed task.
164 base::RunLoop().RunUntilIdle();
165 views::Widget* widget = GetCalloutWidgetForPanel(panel);
167 Shelf* shelf = RootWindowController::ForShelf(panel)->shelf()->shelf();
168 gfx::Rect icon_bounds = shelf->GetScreenBoundsOfItemIconForWindow(panel);
169 ASSERT_FALSE(icon_bounds.IsEmpty());
171 gfx::Rect panel_bounds = panel->GetBoundsInScreen();
172 gfx::Rect callout_bounds = widget->GetWindowBoundsInScreen();
173 ASSERT_FALSE(icon_bounds.IsEmpty());
175 EXPECT_TRUE(widget->IsVisible());
177 ShelfAlignment alignment = GetAlignment(panel->GetRootWindow());
178 switch (alignment) {
179 case SHELF_ALIGNMENT_BOTTOM:
180 EXPECT_EQ(panel_bounds.bottom(), callout_bounds.y());
181 break;
182 case SHELF_ALIGNMENT_LEFT:
183 EXPECT_EQ(panel_bounds.x(), callout_bounds.right());
184 break;
185 case SHELF_ALIGNMENT_RIGHT:
186 EXPECT_EQ(panel_bounds.right(), callout_bounds.x());
187 break;
188 case SHELF_ALIGNMENT_TOP:
189 EXPECT_EQ(panel_bounds.y(), callout_bounds.bottom());
190 break;
193 if (IsHorizontal(alignment)) {
194 EXPECT_NEAR(icon_bounds.CenterPoint().x(),
195 widget->GetWindowBoundsInScreen().CenterPoint().x(),
197 } else {
198 EXPECT_NEAR(icon_bounds.CenterPoint().y(),
199 widget->GetWindowBoundsInScreen().CenterPoint().y(),
204 bool IsPanelCalloutVisible(aura::Window* panel) {
205 views::Widget* widget = GetCalloutWidgetForPanel(panel);
206 return widget->IsVisible();
209 test::ShelfViewTestAPI* shelf_view_test() {
210 return shelf_view_test_.get();
213 // Clicks the shelf items on |shelf_view| that is associated with given
214 // |window|.
215 void ClickShelfItemForWindow(ShelfView* shelf_view, aura::Window* window) {
216 test::ShelfViewTestAPI test_api(shelf_view);
217 test_api.SetAnimationDuration(1);
218 test_api.RunMessageLoopUntilAnimationsDone();
219 ShelfModel* model = test::ShellTestApi(Shell::GetInstance()).shelf_model();
220 int index = model->ItemIndexByID(GetShelfIDForWindow(window));
221 gfx::Rect bounds = test_api.GetButton(index)->GetBoundsInScreen();
223 ui::test::EventGenerator& event_generator = GetEventGenerator();
224 event_generator.MoveMouseTo(bounds.CenterPoint());
225 event_generator.ClickLeftButton();
227 test_api.RunMessageLoopUntilAnimationsDone();
230 void SetAlignment(aura::Window* root_window, ShelfAlignment alignment) {
231 ash::Shell* shell = ash::Shell::GetInstance();
232 shell->SetShelfAlignment(alignment, root_window);
235 ShelfAlignment GetAlignment(const aura::Window* root_window) {
236 ash::Shell* shell = ash::Shell::GetInstance();
237 return shell->GetShelfAlignment(root_window);
240 void SetShelfAutoHideBehavior(aura::Window* window,
241 ShelfAutoHideBehavior behavior) {
242 ShelfLayoutManager* shelf = RootWindowController::ForWindow(window)
243 ->shelf()
244 ->shelf_layout_manager();
245 shelf->SetAutoHideBehavior(behavior);
246 ShelfView* shelf_view = GetShelfView(Shelf::ForWindow(window));
247 test::ShelfViewTestAPI test_api(shelf_view);
248 test_api.RunMessageLoopUntilAnimationsDone();
251 void SetShelfVisibilityState(aura::Window* window,
252 ShelfVisibilityState visibility_state) {
253 ShelfLayoutManager* shelf = RootWindowController::ForWindow(window)
254 ->shelf()
255 ->shelf_layout_manager();
256 shelf->SetState(visibility_state);
259 ShelfView* GetShelfView(Shelf* shelf) {
260 return test::ShelfTestAPI(shelf).shelf_view();
263 private:
264 scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_;
266 bool IsHorizontal(ShelfAlignment alignment) {
267 return alignment == SHELF_ALIGNMENT_BOTTOM ||
268 alignment == SHELF_ALIGNMENT_TOP;
271 DISALLOW_COPY_AND_ASSIGN(PanelLayoutManagerTest);
274 class PanelLayoutManagerTextDirectionTest
275 : public PanelLayoutManagerTest,
276 public testing::WithParamInterface<bool> {
277 public:
278 PanelLayoutManagerTextDirectionTest() : is_rtl_(GetParam()) {}
279 virtual ~PanelLayoutManagerTextDirectionTest() {}
281 void SetUp() override {
282 original_locale = l10n_util::GetApplicationLocale(std::string());
283 if (is_rtl_)
284 base::i18n::SetICUDefaultLocale("he");
285 PanelLayoutManagerTest::SetUp();
286 ASSERT_EQ(is_rtl_, base::i18n::IsRTL());
289 void TearDown() override {
290 if (is_rtl_)
291 base::i18n::SetICUDefaultLocale(original_locale);
292 PanelLayoutManagerTest::TearDown();
295 private:
296 bool is_rtl_;
297 std::string original_locale;
299 DISALLOW_COPY_AND_ASSIGN(PanelLayoutManagerTextDirectionTest);
302 // Tests that a created panel window is above the shelf icon in LTR and RTL.
303 TEST_P(PanelLayoutManagerTextDirectionTest, AddOnePanel) {
304 gfx::Rect bounds(0, 0, 201, 201);
305 scoped_ptr<aura::Window> window(CreatePanelWindow(bounds));
306 EXPECT_EQ(GetPanelContainer(window.get()), window->parent());
307 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(window.get()));
308 EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(window.get()));
311 // Tests that a created panel window is successfully aligned over a hidden
312 // shelf icon.
313 TEST_F(PanelLayoutManagerTest, PanelAlignsToHiddenLauncherIcon) {
314 gfx::Rect bounds(0, 0, 201, 201);
315 SetShelfAutoHideBehavior(Shell::GetPrimaryRootWindow(),
316 SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
317 scoped_ptr<aura::Window> normal_window(CreateNormalWindow(bounds));
318 scoped_ptr<aura::Window> window(CreatePanelWindow(bounds));
319 EXPECT_EQ(GetPanelContainer(window.get()), window->parent());
320 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(window.get()));
323 TEST_F(PanelLayoutManagerTest, PanelAlignsToHiddenLauncherIconSecondDisplay) {
324 if (!SupportsMultipleDisplays())
325 return;
327 // Keep the displays wide so that shelves have enough space for shelves
328 // buttons.
329 UpdateDisplay("400x400,600x400");
330 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
332 scoped_ptr<aura::Window> normal_window(
333 CreateNormalWindow(gfx::Rect(450, 0, 100, 100)));
334 scoped_ptr<aura::Window> panel(CreatePanelWindow(gfx::Rect(400, 0, 50, 50)));
335 EXPECT_EQ(root_windows[1], panel->GetRootWindow());
336 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(panel.get()));
337 gfx::Rect shelf_visible_position = panel->GetBoundsInScreen();
339 SetShelfAutoHideBehavior(root_windows[1],
340 SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
341 // Expect the panel X position to remain the same after the shelf is hidden
342 // but the Y to move down.
343 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(panel.get()));
344 EXPECT_EQ(shelf_visible_position.x(), panel->GetBoundsInScreen().x());
345 EXPECT_GT(panel->GetBoundsInScreen().y(), shelf_visible_position.y());
348 // Tests interactions between multiple panels
349 TEST_F(PanelLayoutManagerTest, MultiplePanelsAreAboveIcons) {
350 gfx::Rect odd_bounds(0, 0, 201, 201);
351 gfx::Rect even_bounds(0, 0, 200, 200);
353 scoped_ptr<aura::Window> w1(CreatePanelWindow(odd_bounds));
354 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
356 scoped_ptr<aura::Window> w2(CreatePanelWindow(even_bounds));
357 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
358 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get()));
360 scoped_ptr<aura::Window> w3(CreatePanelWindow(odd_bounds));
361 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
362 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get()));
363 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get()));
366 TEST_F(PanelLayoutManagerTest, MultiplePanelStacking) {
367 gfx::Rect bounds(0, 0, 201, 201);
368 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
369 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
370 scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
372 // Default stacking order.
373 EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
374 EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
376 // Changing the active window should update the stacking order.
377 wm::ActivateWindow(w1.get());
378 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
379 EXPECT_TRUE(WindowIsAbove(w1.get(), w2.get()));
380 EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
382 wm::ActivateWindow(w2.get());
383 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
384 EXPECT_TRUE(WindowIsAbove(w1.get(), w3.get()));
385 EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
386 EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
388 wm::ActivateWindow(w3.get());
389 EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
390 EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
393 TEST_F(PanelLayoutManagerTest, MultiplePanelStackingVertical) {
394 // Set shelf to be aligned on the right.
395 SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_RIGHT);
397 // Size panels in such a way that ordering them by X coordinate would cause
398 // stacking order to be incorrect. Test that stacking order is based on Y.
399 scoped_ptr<aura::Window> w1(CreatePanelWindow(gfx::Rect(0, 0, 210, 201)));
400 scoped_ptr<aura::Window> w2(CreatePanelWindow(gfx::Rect(0, 0, 220, 201)));
401 scoped_ptr<aura::Window> w3(CreatePanelWindow(gfx::Rect(0, 0, 200, 201)));
403 // Default stacking order.
404 EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
405 EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
407 // Changing the active window should update the stacking order.
408 wm::ActivateWindow(w1.get());
409 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
410 EXPECT_TRUE(WindowIsAbove(w1.get(), w2.get()));
411 EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
413 wm::ActivateWindow(w2.get());
414 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
415 EXPECT_TRUE(WindowIsAbove(w1.get(), w3.get()));
416 EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
417 EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
419 wm::ActivateWindow(w3.get());
420 EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
421 EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
424 TEST_F(PanelLayoutManagerTest, MultiplePanelCallout) {
425 gfx::Rect bounds(0, 0, 200, 200);
426 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
427 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
428 scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
429 scoped_ptr<aura::Window> w4(CreateNormalWindow(gfx::Rect()));
430 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
431 EXPECT_TRUE(IsPanelCalloutVisible(w1.get()));
432 EXPECT_TRUE(IsPanelCalloutVisible(w2.get()));
433 EXPECT_TRUE(IsPanelCalloutVisible(w3.get()));
434 wm::ActivateWindow(w1.get());
435 EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w1.get()));
436 wm::ActivateWindow(w2.get());
437 EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w2.get()));
438 wm::ActivateWindow(w3.get());
439 EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w3.get()));
440 wm::ActivateWindow(w4.get());
441 wm::ActivateWindow(w3.get());
442 EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w3.get()));
443 w3.reset();
444 EXPECT_NO_FATAL_FAILURE(IsCalloutAboveLauncherIcon(w2.get()));
447 // Tests removing panels.
448 TEST_F(PanelLayoutManagerTest, RemoveLeftPanel) {
449 gfx::Rect bounds(0, 0, 201, 201);
450 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
451 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
452 scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
454 // At this point, windows should be stacked with 1 < 2 < 3
455 wm::ActivateWindow(w1.get());
456 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
457 // Now, windows should be stacked 1 > 2 > 3
458 w1.reset();
459 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get()));
460 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get()));
461 EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
464 TEST_F(PanelLayoutManagerTest, RemoveMiddlePanel) {
465 gfx::Rect bounds(0, 0, 201, 201);
466 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
467 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
468 scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
470 // At this point, windows should be stacked with 1 < 2 < 3
471 wm::ActivateWindow(w2.get());
472 // Windows should be stacked 1 < 2 > 3
473 w2.reset();
474 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
475 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get()));
476 EXPECT_TRUE(WindowIsAbove(w3.get(), w1.get()));
479 TEST_F(PanelLayoutManagerTest, RemoveRightPanel) {
480 gfx::Rect bounds(0, 0, 201, 201);
481 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
482 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
483 scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
485 // At this point, windows should be stacked with 1 < 2 < 3
486 wm::ActivateWindow(w3.get());
487 // Order shouldn't change.
488 w3.reset();
489 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
490 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get()));
491 EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
494 TEST_F(PanelLayoutManagerTest, RemoveNonActivePanel) {
495 gfx::Rect bounds(0, 0, 201, 201);
496 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
497 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
498 scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
500 // At this point, windows should be stacked with 1 < 2 < 3
501 wm::ActivateWindow(w2.get());
502 // Windows should be stacked 1 < 2 > 3
503 w1.reset();
504 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w2.get()));
505 EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w3.get()));
506 EXPECT_TRUE(WindowIsAbove(w2.get(), w3.get()));
509 TEST_F(PanelLayoutManagerTest, SplitView) {
510 gfx::Rect bounds(0, 0, 90, 201);
511 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
512 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
514 EXPECT_NO_FATAL_FAILURE(PanelsNotOverlapping(w1.get(), w2.get()));
517 #if defined(OS_WIN)
518 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
519 #define MAYBE_SplitViewOverlapWhenLarge DISABLED_SplitViewOverlapWhenLarge
520 #else
521 #define MAYBE_SplitViewOverlapWhenLarge SplitViewOverlapWhenLarge
522 #endif
524 TEST_F(PanelLayoutManagerTest, MAYBE_SplitViewOverlapWhenLarge) {
525 gfx::Rect bounds(0, 0, 600, 201);
526 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
527 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
529 EXPECT_NO_FATAL_FAILURE(PanelInScreen(w1.get()));
530 EXPECT_NO_FATAL_FAILURE(PanelInScreen(w2.get()));
533 TEST_F(PanelLayoutManagerTest, FanWindows) {
534 gfx::Rect bounds(0, 0, 201, 201);
535 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
536 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
537 scoped_ptr<aura::Window> w3(CreatePanelWindow(bounds));
539 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
540 int window_x1 = w1->GetBoundsInRootWindow().CenterPoint().x();
541 int window_x2 = w2->GetBoundsInRootWindow().CenterPoint().x();
542 int window_x3 = w3->GetBoundsInRootWindow().CenterPoint().x();
543 Shelf* shelf = Shelf::ForPrimaryDisplay();
544 int icon_x1 = shelf->GetScreenBoundsOfItemIconForWindow(w1.get()).x();
545 int icon_x2 = shelf->GetScreenBoundsOfItemIconForWindow(w2.get()).x();
546 EXPECT_EQ(window_x2 - window_x1, window_x3 - window_x2);
547 int spacing = window_x2 - window_x1;
548 EXPECT_GT(spacing, icon_x2 - icon_x1);
551 TEST_F(PanelLayoutManagerTest, FanLargeWindow) {
552 gfx::Rect small_bounds(0, 0, 201, 201);
553 gfx::Rect large_bounds(0, 0, 501, 201);
554 scoped_ptr<aura::Window> w1(CreatePanelWindow(small_bounds));
555 scoped_ptr<aura::Window> w2(CreatePanelWindow(large_bounds));
556 scoped_ptr<aura::Window> w3(CreatePanelWindow(small_bounds));
558 shelf_view_test()->RunMessageLoopUntilAnimationsDone();
559 int window_x1 = w1->GetBoundsInRootWindow().CenterPoint().x();
560 int window_x2 = w2->GetBoundsInRootWindow().CenterPoint().x();
561 int window_x3 = w3->GetBoundsInRootWindow().CenterPoint().x();
562 // The distances may not be equidistant with a large panel but the panels
563 // should be in the correct order with respect to their midpoints.
564 EXPECT_GT(window_x2, window_x1);
565 EXPECT_GT(window_x3, window_x2);
568 TEST_F(PanelLayoutManagerTest, MinimizeRestorePanel) {
569 gfx::Rect bounds(0, 0, 201, 201);
570 scoped_ptr<aura::Window> window(CreatePanelWindow(bounds));
571 // Activate the window, ensure callout is visible.
572 wm::ActivateWindow(window.get());
573 RunAllPendingInMessageLoop();
574 EXPECT_TRUE(IsPanelCalloutVisible(window.get()));
575 // Minimize the panel, callout should be hidden.
576 wm::GetWindowState(window.get())->Minimize();
577 RunAllPendingInMessageLoop();
578 EXPECT_FALSE(IsPanelCalloutVisible(window.get()));
579 // Restore the panel; panel should not be activated by default but callout
580 // should be visible.
581 wm::GetWindowState(window.get())->Unminimize();
582 RunAllPendingInMessageLoop();
583 EXPECT_TRUE(IsPanelCalloutVisible(window.get()));
584 // Activate the window, ensure callout is visible.
585 wm::ActivateWindow(window.get());
586 RunAllPendingInMessageLoop();
587 EXPECT_TRUE(IsPanelCalloutVisible(window.get()));
590 TEST_F(PanelLayoutManagerTest, PanelMoveBetweenMultipleDisplays) {
591 if (!SupportsMultipleDisplays())
592 return;
594 // Keep the displays wide so that shelves have enough space for launcher
595 // buttons.
596 UpdateDisplay("600x400,600x400");
597 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
599 scoped_ptr<aura::Window> p1_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50)));
600 scoped_ptr<aura::Window> p2_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50)));
601 scoped_ptr<aura::Window> p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50)));
602 scoped_ptr<aura::Window> p2_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50)));
604 ShelfView* shelf_view_1st = GetShelfView(Shelf::ForPrimaryDisplay());
605 ShelfView* shelf_view_2nd =
606 GetShelfView(Shelf::ForWindow(root_windows[1]));
608 EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow());
609 EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
610 EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
611 EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow());
613 EXPECT_EQ(kShellWindowId_PanelContainer, p1_d1->parent()->id());
614 EXPECT_EQ(kShellWindowId_PanelContainer, p2_d1->parent()->id());
615 EXPECT_EQ(kShellWindowId_PanelContainer, p1_d2->parent()->id());
616 EXPECT_EQ(kShellWindowId_PanelContainer, p2_d2->parent()->id());
618 // Test a panel on 1st display.
619 // Clicking on the same display has no effect.
620 ClickShelfItemForWindow(shelf_view_1st, p1_d1.get());
621 EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow());
622 EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
623 EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
624 EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
625 EXPECT_FALSE(root_windows[1]->GetBoundsInScreen().Contains(
626 p1_d1->GetBoundsInScreen()));
628 // Test if clicking on another display moves the panel to
629 // that display.
630 ClickShelfItemForWindow(shelf_view_2nd, p1_d1.get());
631 EXPECT_EQ(root_windows[1], p1_d1->GetRootWindow());
632 EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
633 EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
634 EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow());
635 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
636 p1_d1->GetBoundsInScreen()));
638 // Test a panel on 2nd display.
639 // Clicking on the same display has no effect.
640 ClickShelfItemForWindow(shelf_view_2nd, p1_d2.get());
641 EXPECT_EQ(root_windows[1], p1_d1->GetRootWindow());
642 EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
643 EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
644 EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow());
645 EXPECT_TRUE(root_windows[1]->GetBoundsInScreen().Contains(
646 p1_d2->GetBoundsInScreen()));
648 // Test if clicking on another display moves the panel to
649 // that display.
650 ClickShelfItemForWindow(shelf_view_1st, p1_d2.get());
651 EXPECT_EQ(root_windows[1], p1_d1->GetRootWindow());
652 EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
653 EXPECT_EQ(root_windows[0], p1_d2->GetRootWindow());
654 EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow());
655 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
656 p1_d2->GetBoundsInScreen()));
658 // Test if clicking on a previously moved window moves the
659 // panel back to the original display.
660 ClickShelfItemForWindow(shelf_view_1st, p1_d1.get());
661 EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow());
662 EXPECT_EQ(root_windows[0], p2_d1->GetRootWindow());
663 EXPECT_EQ(root_windows[0], p1_d2->GetRootWindow());
664 EXPECT_EQ(root_windows[1], p2_d2->GetRootWindow());
665 EXPECT_TRUE(root_windows[0]->GetBoundsInScreen().Contains(
666 p1_d1->GetBoundsInScreen()));
669 TEST_F(PanelLayoutManagerTest, PanelAttachPositionMultipleDisplays) {
670 if (!SupportsMultipleDisplays())
671 return;
673 // Keep the displays wide so that shelves have enough space for shelf buttons.
674 // Use differently sized displays so the shelf is in a different
675 // position on second display.
676 UpdateDisplay("600x400,600x600");
677 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
679 scoped_ptr<aura::Window> p1_d1(CreatePanelWindow(gfx::Rect(0, 0, 50, 50)));
680 scoped_ptr<aura::Window> p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50)));
682 EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow());
683 EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
685 IsPanelAboveLauncherIcon(p1_d1.get());
686 IsCalloutAboveLauncherIcon(p1_d1.get());
687 IsPanelAboveLauncherIcon(p1_d2.get());
688 IsCalloutAboveLauncherIcon(p1_d2.get());
691 TEST_F(PanelLayoutManagerTest, PanelAlignmentSecondDisplay) {
692 if (!SupportsMultipleDisplays())
693 return;
695 UpdateDisplay("600x400,600x400");
696 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
698 scoped_ptr<aura::Window> p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50)));
699 EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
701 IsPanelAboveLauncherIcon(p1_d2.get());
702 IsCalloutAboveLauncherIcon(p1_d2.get());
704 SetAlignment(root_windows[1], SHELF_ALIGNMENT_RIGHT);
705 IsPanelAboveLauncherIcon(p1_d2.get());
706 IsCalloutAboveLauncherIcon(p1_d2.get());
707 SetAlignment(root_windows[1], SHELF_ALIGNMENT_LEFT);
708 IsPanelAboveLauncherIcon(p1_d2.get());
709 IsCalloutAboveLauncherIcon(p1_d2.get());
710 SetAlignment(root_windows[1], SHELF_ALIGNMENT_TOP);
711 IsPanelAboveLauncherIcon(p1_d2.get());
712 IsCalloutAboveLauncherIcon(p1_d2.get());
715 TEST_F(PanelLayoutManagerTest, AlignmentLeft) {
716 gfx::Rect bounds(0, 0, 201, 201);
717 scoped_ptr<aura::Window> w(CreatePanelWindow(bounds));
718 SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_LEFT);
719 IsPanelAboveLauncherIcon(w.get());
720 IsCalloutAboveLauncherIcon(w.get());
723 TEST_F(PanelLayoutManagerTest, AlignmentRight) {
724 gfx::Rect bounds(0, 0, 201, 201);
725 scoped_ptr<aura::Window> w(CreatePanelWindow(bounds));
726 SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_RIGHT);
727 IsPanelAboveLauncherIcon(w.get());
728 IsCalloutAboveLauncherIcon(w.get());
731 TEST_F(PanelLayoutManagerTest, AlignmentTop) {
732 gfx::Rect bounds(0, 0, 201, 201);
733 scoped_ptr<aura::Window> w(CreatePanelWindow(bounds));
734 SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_TOP);
735 IsPanelAboveLauncherIcon(w.get());
736 IsCalloutAboveLauncherIcon(w.get());
739 // Tests that panels will hide and restore their state with the shelf visibility
740 // state. This ensures that entering full-screen mode will hide your panels
741 // until you leave it.
742 TEST_F(PanelLayoutManagerTest, PanelsHideAndRestoreWithShelf) {
743 gfx::Rect bounds(0, 0, 201, 201);
745 scoped_ptr<aura::Window> w1(CreatePanelWindow(bounds));
746 scoped_ptr<aura::Window> w2(CreatePanelWindow(bounds));
747 scoped_ptr<aura::Window> w3;
748 // Minimize w2.
749 wm::GetWindowState(w2.get())->Minimize();
750 RunAllPendingInMessageLoop();
751 EXPECT_TRUE(w1->IsVisible());
752 EXPECT_FALSE(w2->IsVisible());
754 SetShelfVisibilityState(Shell::GetPrimaryRootWindow(), SHELF_HIDDEN);
755 RunAllPendingInMessageLoop();
757 // w3 is created while in full-screen mode, should only become visible when
758 // we exit fullscreen mode.
759 w3.reset(CreatePanelWindow(bounds));
761 EXPECT_FALSE(w1->IsVisible());
762 EXPECT_FALSE(w2->IsVisible());
763 EXPECT_FALSE(w3->IsVisible());
765 // While in full-screen mode, the panel windows should still be in the
766 // switchable window list - http://crbug.com/313919.
767 MruWindowTracker::WindowList switchable_window_list =
768 Shell::GetInstance()->mru_window_tracker()->BuildMruWindowList();
769 EXPECT_EQ(3u, switchable_window_list.size());
770 EXPECT_NE(switchable_window_list.end(),
771 std::find(switchable_window_list.begin(), switchable_window_list.end(),
772 w1.get()));
773 EXPECT_NE(switchable_window_list.end(),
774 std::find(switchable_window_list.begin(), switchable_window_list.end(),
775 w2.get()));
776 EXPECT_NE(switchable_window_list.end(),
777 std::find(switchable_window_list.begin(), switchable_window_list.end(),
778 w3.get()));
780 SetShelfVisibilityState(Shell::GetPrimaryRootWindow(), SHELF_VISIBLE);
781 RunAllPendingInMessageLoop();
783 // Windows should be restored to their prior state.
784 EXPECT_TRUE(w1->IsVisible());
785 EXPECT_FALSE(w2->IsVisible());
786 EXPECT_TRUE(w3->IsVisible());
789 // Verifies that touches along the attached edge of a panel do not
790 // target the panel itself.
791 TEST_F(PanelLayoutManagerTest, TouchHitTestPanel) {
792 aura::test::TestWindowDelegate delegate;
793 scoped_ptr<aura::Window> w(
794 CreatePanelWindowWithDelegate(&delegate, gfx::Rect(0, 0, 200, 200)));
795 ui::EventTarget* root = w->GetRootWindow();
796 ui::EventTargeter* targeter = root->GetEventTargeter();
798 // Note that the constants used in the touch locations below are
799 // arbitrarily-selected small numbers which will ensure the point is
800 // within the default extended region surrounding the panel. This value
801 // is calculated as
802 // kResizeOutsideBoundsSize * kResizeOutsideBoundsScaleForTouch
803 // in src/ash/root_window_controller.cc.
805 // Hit test outside the right edge with a bottom-aligned shelf.
806 SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_BOTTOM);
807 gfx::Rect bounds(w->bounds());
808 ui::TouchEvent touch(ui::ET_TOUCH_PRESSED,
809 gfx::Point(bounds.right() + 3, bounds.y() + 2),
810 0, ui::EventTimeForNow());
811 ui::EventTarget* target = targeter->FindTargetForEvent(root, &touch);
812 EXPECT_EQ(w.get(), target);
814 // Hit test outside the bottom edge with a bottom-aligned shelf.
815 touch.set_location(gfx::Point(bounds.x() + 6, bounds.bottom() + 5));
816 target = targeter->FindTargetForEvent(root, &touch);
817 EXPECT_NE(w.get(), target);
819 // Hit test outside the bottom edge with a right-aligned shelf.
820 SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_RIGHT);
821 bounds = w->bounds();
822 touch.set_location(gfx::Point(bounds.x() + 6, bounds.bottom() + 5));
823 target = targeter->FindTargetForEvent(root, &touch);
824 EXPECT_EQ(w.get(), target);
826 // Hit test outside the right edge with a right-aligned shelf.
827 touch.set_location(gfx::Point(bounds.right() + 3, bounds.y() + 2));
828 target = targeter->FindTargetForEvent(root, &touch);
829 EXPECT_NE(w.get(), target);
831 // Hit test outside the top edge with a left-aligned shelf.
832 SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_LEFT);
833 bounds = w->bounds();
834 touch.set_location(gfx::Point(bounds.x() + 4, bounds.y() - 6));
835 target = targeter->FindTargetForEvent(root, &touch);
836 EXPECT_EQ(w.get(), target);
838 // Hit test outside the left edge with a left-aligned shelf.
839 touch.set_location(gfx::Point(bounds.x() - 1, bounds.y() + 5));
840 target = targeter->FindTargetForEvent(root, &touch);
841 EXPECT_NE(w.get(), target);
843 // Hit test outside the left edge with a top-aligned shelf.
844 SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_TOP);
845 bounds = w->bounds();
846 touch.set_location(gfx::Point(bounds.x() - 1, bounds.y() + 5));
847 target = targeter->FindTargetForEvent(root, &touch);
848 EXPECT_EQ(w.get(), target);
850 // Hit test outside the top edge with a top-aligned shelf.
851 touch.set_location(gfx::Point(bounds.x() + 4, bounds.y() - 6));
852 target = targeter->FindTargetForEvent(root, &touch);
853 EXPECT_NE(w.get(), target);
856 INSTANTIATE_TEST_CASE_P(LtrRtl, PanelLayoutManagerTextDirectionTest,
857 testing::Bool());
859 } // namespace ash