Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ash / wm / panels / panel_layout_manager_unittest.cc
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/wm/panels/panel_layout_manager.h"
6
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"
41
42 namespace ash {
43
44 using aura::test::WindowIsAbove;
45
46 class PanelLayoutManagerTest : public test::AshTestBase {
47  public:
48   PanelLayoutManagerTest() {}
49   virtual ~PanelLayoutManagerTest() {}
50
51   virtual void SetUp() OVERRIDE {
52     test::AshTestBase::SetUp();
53     ASSERT_TRUE(test::TestShelfDelegate::instance());
54
55     shelf_view_test_.reset(new test::ShelfViewTestAPI(
56         GetShelfView(Shelf::ForPrimaryDisplay())));
57     shelf_view_test_->SetAnimationDuration(1);
58   }
59
60   aura::Window* CreateNormalWindow(const gfx::Rect& bounds) {
61     return CreateTestWindowInShellWithBounds(bounds);
62   }
63
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;
73   }
74
75   aura::Window* CreatePanelWindow(const gfx::Rect& bounds) {
76     return CreatePanelWindowWithDelegate(NULL, bounds);
77   }
78
79   aura::Window* GetPanelContainer(aura::Window* panel) {
80     return Shell::GetContainer(panel->GetRootWindow(),
81                                kShellWindowId_PanelContainer);
82   }
83
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);
95   }
96
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);
101
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());
109   }
110
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();
116
117     EXPECT_FALSE(window1_bounds.Intersects(window2_bounds));
118   }
119
120   void IsPanelAboveLauncherIcon(const aura::Window* panel) {
121     // Waits until all shelf view animations are done.
122     shelf_view_test()->RunMessageLoopUntilAnimationsDone();
123
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);
127
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());
133
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());
144     }
145
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;
159     }
160   }
161
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);
166
167     Shelf* shelf = RootWindowController::ForShelf(panel)->shelf()->shelf();
168     gfx::Rect icon_bounds = shelf->GetScreenBoundsOfItemIconForWindow(panel);
169     ASSERT_FALSE(icon_bounds.IsEmpty());
170
171     gfx::Rect panel_bounds = panel->GetBoundsInScreen();
172     gfx::Rect callout_bounds = widget->GetWindowBoundsInScreen();
173     ASSERT_FALSE(icon_bounds.IsEmpty());
174
175     EXPECT_TRUE(widget->IsVisible());
176
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;
191     }
192
193     if (IsHorizontal(alignment)) {
194       EXPECT_NEAR(icon_bounds.CenterPoint().x(),
195                   widget->GetWindowBoundsInScreen().CenterPoint().x(),
196                   1);
197     } else {
198       EXPECT_NEAR(icon_bounds.CenterPoint().y(),
199                   widget->GetWindowBoundsInScreen().CenterPoint().y(),
200                   1);
201     }
202   }
203
204   bool IsPanelCalloutVisible(aura::Window* panel) {
205     views::Widget* widget = GetCalloutWidgetForPanel(panel);
206     return widget->IsVisible();
207   }
208
209   test::ShelfViewTestAPI* shelf_view_test() {
210     return shelf_view_test_.get();
211   }
212
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();
222
223     ui::test::EventGenerator& event_generator = GetEventGenerator();
224     event_generator.MoveMouseTo(bounds.CenterPoint());
225     event_generator.ClickLeftButton();
226
227     test_api.RunMessageLoopUntilAnimationsDone();
228   }
229
230   void SetAlignment(aura::Window* root_window, ShelfAlignment alignment) {
231     ash::Shell* shell = ash::Shell::GetInstance();
232     shell->SetShelfAlignment(alignment, root_window);
233   }
234
235   ShelfAlignment GetAlignment(const aura::Window* root_window) {
236     ash::Shell* shell = ash::Shell::GetInstance();
237     return shell->GetShelfAlignment(root_window);
238   }
239
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();
249   }
250
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);
257   }
258
259   ShelfView* GetShelfView(Shelf* shelf) {
260     return test::ShelfTestAPI(shelf).shelf_view();
261   }
262
263  private:
264   scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_;
265
266   bool IsHorizontal(ShelfAlignment alignment) {
267     return alignment == SHELF_ALIGNMENT_BOTTOM ||
268            alignment == SHELF_ALIGNMENT_TOP;
269   }
270
271   DISALLOW_COPY_AND_ASSIGN(PanelLayoutManagerTest);
272 };
273
274 class PanelLayoutManagerTextDirectionTest
275     : public PanelLayoutManagerTest,
276       public testing::WithParamInterface<bool> {
277  public:
278   PanelLayoutManagerTextDirectionTest() : is_rtl_(GetParam()) {}
279   virtual ~PanelLayoutManagerTextDirectionTest() {}
280
281   virtual 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());
287   }
288
289   virtual void TearDown() OVERRIDE {
290     if (is_rtl_)
291       base::i18n::SetICUDefaultLocale(original_locale);
292     PanelLayoutManagerTest::TearDown();
293   }
294
295  private:
296   bool is_rtl_;
297   std::string original_locale;
298
299   DISALLOW_COPY_AND_ASSIGN(PanelLayoutManagerTextDirectionTest);
300 };
301
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()));
309 }
310
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()));
321 }
322
323 TEST_F(PanelLayoutManagerTest, PanelAlignsToHiddenLauncherIconSecondDisplay) {
324   if (!SupportsMultipleDisplays())
325     return;
326
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();
331
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();
338
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());
346 }
347
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);
352
353   scoped_ptr<aura::Window> w1(CreatePanelWindow(odd_bounds));
354   EXPECT_NO_FATAL_FAILURE(IsPanelAboveLauncherIcon(w1.get()));
355
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()));
359
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()));
364 }
365
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));
371
372   // Default stacking order.
373   EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
374   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
375
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()));
381
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()));
387
388   wm::ActivateWindow(w3.get());
389   EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
390   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
391 }
392
393 TEST_F(PanelLayoutManagerTest, MultiplePanelStackingVertical) {
394   // Set shelf to be aligned on the right.
395   SetAlignment(Shell::GetPrimaryRootWindow(), SHELF_ALIGNMENT_RIGHT);
396
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)));
402
403   // Default stacking order.
404   EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
405   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
406
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()));
412
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()));
418
419   wm::ActivateWindow(w3.get());
420   EXPECT_TRUE(WindowIsAbove(w3.get(), w2.get()));
421   EXPECT_TRUE(WindowIsAbove(w2.get(), w1.get()));
422 }
423
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()));
445 }
446
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));
453
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()));
462 }
463
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));
469
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()));
477 }
478
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));
484
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()));
492 }
493
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));
499
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()));
507 }
508
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));
513
514   EXPECT_NO_FATAL_FAILURE(PanelsNotOverlapping(w1.get(), w2.get()));
515 }
516
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
523
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));
528
529   EXPECT_NO_FATAL_FAILURE(PanelInScreen(w1.get()));
530   EXPECT_NO_FATAL_FAILURE(PanelInScreen(w2.get()));
531 }
532
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));
538
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);
549 }
550
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));
557
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);
566 }
567
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()));
588 }
589
590 TEST_F(PanelLayoutManagerTest, PanelMoveBetweenMultipleDisplays) {
591   if (!SupportsMultipleDisplays())
592     return;
593
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();
598
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)));
603
604   ShelfView* shelf_view_1st = GetShelfView(Shelf::ForPrimaryDisplay());
605   ShelfView* shelf_view_2nd =
606       GetShelfView(Shelf::ForWindow(root_windows[1]));
607
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());
612
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());
617
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()));
627
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()));
637
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()));
647
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()));
657
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()));
667 }
668
669 TEST_F(PanelLayoutManagerTest, PanelAttachPositionMultipleDisplays) {
670   if (!SupportsMultipleDisplays())
671     return;
672
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();
678
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)));
681
682   EXPECT_EQ(root_windows[0], p1_d1->GetRootWindow());
683   EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
684
685   IsPanelAboveLauncherIcon(p1_d1.get());
686   IsCalloutAboveLauncherIcon(p1_d1.get());
687   IsPanelAboveLauncherIcon(p1_d2.get());
688   IsCalloutAboveLauncherIcon(p1_d2.get());
689 }
690
691 TEST_F(PanelLayoutManagerTest, PanelAlignmentSecondDisplay) {
692   if (!SupportsMultipleDisplays())
693     return;
694
695   UpdateDisplay("600x400,600x400");
696   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
697
698   scoped_ptr<aura::Window> p1_d2(CreatePanelWindow(gfx::Rect(600, 0, 50, 50)));
699   EXPECT_EQ(root_windows[1], p1_d2->GetRootWindow());
700
701   IsPanelAboveLauncherIcon(p1_d2.get());
702   IsCalloutAboveLauncherIcon(p1_d2.get());
703
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());
713 }
714
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());
721 }
722
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());
729 }
730
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());
737 }
738
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);
744
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());
753
754   SetShelfVisibilityState(Shell::GetPrimaryRootWindow(), SHELF_HIDDEN);
755   RunAllPendingInMessageLoop();
756
757   // w3 is created while in full-screen mode, should only become visible when
758   // we exit fullscreen mode.
759   w3.reset(CreatePanelWindow(bounds));
760
761   EXPECT_FALSE(w1->IsVisible());
762   EXPECT_FALSE(w2->IsVisible());
763   EXPECT_FALSE(w3->IsVisible());
764
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()));
779
780   SetShelfVisibilityState(Shell::GetPrimaryRootWindow(), SHELF_VISIBLE);
781   RunAllPendingInMessageLoop();
782
783   // Windows should be restored to their prior state.
784   EXPECT_TRUE(w1->IsVisible());
785   EXPECT_FALSE(w2->IsVisible());
786   EXPECT_TRUE(w3->IsVisible());
787 }
788
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();
797
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.
804
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);
813
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);
818
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);
825
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);
830
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);
837
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);
842
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);
849
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);
854 }
855
856 INSTANTIATE_TEST_CASE_P(LtrRtl, PanelLayoutManagerTextDirectionTest,
857                         testing::Bool());
858
859 }  // namespace ash