Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ash / shelf / shelf_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/shelf/shelf_layout_manager.h"
6
7 #include "ash/accelerators/accelerator_controller.h"
8 #include "ash/accelerators/accelerator_table.h"
9 #include "ash/ash_switches.h"
10 #include "ash/display/display_manager.h"
11 #include "ash/focus_cycler.h"
12 #include "ash/root_window_controller.h"
13 #include "ash/session/session_state_delegate.h"
14 #include "ash/shelf/shelf.h"
15 #include "ash/shelf/shelf_layout_manager_observer.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/system/status_area_widget.h"
21 #include "ash/system/tray/system_tray.h"
22 #include "ash/system/tray/system_tray_item.h"
23 #include "ash/test/ash_test_base.h"
24 #include "ash/test/shelf_test_api.h"
25 #include "ash/wm/window_state.h"
26 #include "ash/wm/window_util.h"
27 #include "base/command_line.h"
28 #include "base/strings/utf_string_conversions.h"
29 #include "ui/aura/client/aura_constants.h"
30 #include "ui/aura/test/event_generator.h"
31 #include "ui/aura/window.h"
32 #include "ui/aura/window_event_dispatcher.h"
33 #include "ui/compositor/layer.h"
34 #include "ui/compositor/layer_animator.h"
35 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
36 #include "ui/events/gestures/gesture_configuration.h"
37 #include "ui/gfx/animation/animation_container_element.h"
38 #include "ui/gfx/display.h"
39 #include "ui/gfx/screen.h"
40 #include "ui/views/controls/label.h"
41 #include "ui/views/layout/fill_layout.h"
42 #include "ui/views/view.h"
43 #include "ui/views/widget/widget.h"
44
45 #if defined(OS_WIN)
46 #include "base/win/windows_version.h"
47 #endif
48
49 namespace ash {
50 namespace {
51
52 void StepWidgetLayerAnimatorToEnd(views::Widget* widget) {
53   gfx::AnimationContainerElement* element =
54       static_cast<gfx::AnimationContainerElement*>(
55       widget->GetNativeView()->layer()->GetAnimator());
56   element->Step(base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1));
57 }
58
59 ShelfWidget* GetShelfWidget() {
60   return Shell::GetPrimaryRootWindowController()->shelf();
61 }
62
63 ShelfLayoutManager* GetShelfLayoutManager() {
64   return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
65 }
66
67 SystemTray* GetSystemTray() {
68   return Shell::GetPrimaryRootWindowController()->GetSystemTray();
69 }
70
71 // Class which waits till the shelf finishes animating to the target size and
72 // counts the number of animation steps.
73 class ShelfAnimationWaiter : views::WidgetObserver {
74  public:
75   explicit ShelfAnimationWaiter(const gfx::Rect& target_bounds)
76       : target_bounds_(target_bounds),
77         animation_steps_(0),
78         done_waiting_(false) {
79     GetShelfWidget()->AddObserver(this);
80   }
81
82   virtual ~ShelfAnimationWaiter() {
83     GetShelfWidget()->RemoveObserver(this);
84   }
85
86   // Wait till the shelf finishes animating to its expected bounds.
87   void WaitTillDoneAnimating() {
88     if (IsDoneAnimating())
89       done_waiting_ = true;
90     else
91       base::MessageLoop::current()->Run();
92   }
93
94   // Returns true if the animation has completed and it was valid.
95   bool WasValidAnimation() const {
96     return done_waiting_ && animation_steps_ > 0;
97   }
98
99  private:
100   // Returns true if shelf has finished animating to the target size.
101   bool IsDoneAnimating() const {
102     ShelfLayoutManager* layout_manager = GetShelfLayoutManager();
103     gfx::Rect current_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
104     int size = layout_manager->PrimaryAxisValue(current_bounds.height(),
105         current_bounds.width());
106     int desired_size = layout_manager->PrimaryAxisValue(target_bounds_.height(),
107         target_bounds_.width());
108     return (size == desired_size);
109   }
110
111   // views::WidgetObserver override.
112   virtual void OnWidgetBoundsChanged(views::Widget* widget,
113                                      const gfx::Rect& new_bounds) OVERRIDE {
114     if (done_waiting_)
115       return;
116
117     ++animation_steps_;
118     if (IsDoneAnimating()) {
119       done_waiting_ = true;
120       base::MessageLoop::current()->Quit();
121     }
122   }
123
124   gfx::Rect target_bounds_;
125   int animation_steps_;
126   bool done_waiting_;
127
128   DISALLOW_COPY_AND_ASSIGN(ShelfAnimationWaiter);
129 };
130
131 class ShelfDragCallback {
132  public:
133   ShelfDragCallback(const gfx::Rect& not_visible, const gfx::Rect& visible)
134       : not_visible_bounds_(not_visible),
135         visible_bounds_(visible),
136         was_visible_on_drag_start_(false) {
137     EXPECT_EQ(not_visible_bounds_.bottom(), visible_bounds_.bottom());
138   }
139
140   virtual ~ShelfDragCallback() {
141   }
142
143   void ProcessScroll(ui::EventType type, const gfx::Vector2dF& delta) {
144     if (GetShelfLayoutManager()->visibility_state() == ash::SHELF_HIDDEN)
145       return;
146
147     if (type == ui::ET_GESTURE_SCROLL_BEGIN) {
148       scroll_ = gfx::Vector2dF();
149       was_visible_on_drag_start_ = GetShelfLayoutManager()->IsVisible();
150       return;
151     }
152
153     // The state of the shelf at the end of the gesture is tested separately.
154     if (type == ui::ET_GESTURE_SCROLL_END)
155       return;
156
157     if (type == ui::ET_GESTURE_SCROLL_UPDATE)
158       scroll_.Add(delta);
159
160     gfx::Rect shelf_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
161     if (GetShelfLayoutManager()->IsHorizontalAlignment()) {
162       EXPECT_EQ(not_visible_bounds_.bottom(), shelf_bounds.bottom());
163       EXPECT_EQ(visible_bounds_.bottom(), shelf_bounds.bottom());
164     } else if (SHELF_ALIGNMENT_RIGHT ==
165         GetShelfLayoutManager()->GetAlignment()){
166       EXPECT_EQ(not_visible_bounds_.right(), shelf_bounds.right());
167       EXPECT_EQ(visible_bounds_.right(), shelf_bounds.right());
168     } else if (SHELF_ALIGNMENT_LEFT ==
169         GetShelfLayoutManager()->GetAlignment()) {
170       EXPECT_EQ(not_visible_bounds_.x(), shelf_bounds.x());
171       EXPECT_EQ(visible_bounds_.x(), shelf_bounds.x());
172     }
173
174     // if the shelf is being dimmed test dimmer bounds as well.
175     if (GetShelfWidget()->GetDimsShelf())
176       EXPECT_EQ(GetShelfWidget()->GetWindowBoundsInScreen(),
177                 GetShelfWidget()->GetDimmerBoundsForTest());
178
179     // The shelf should never be smaller than the hidden state.
180     EXPECT_GE(shelf_bounds.height(), not_visible_bounds_.height());
181     float scroll_delta = GetShelfLayoutManager()->PrimaryAxisValue(
182         scroll_.y(),
183         scroll_.x());
184     bool increasing_drag =
185         GetShelfLayoutManager()->SelectValueForShelfAlignment(
186             scroll_delta < 0,
187             scroll_delta > 0,
188             scroll_delta < 0,
189             scroll_delta > 0);
190     int shelf_size = GetShelfLayoutManager()->PrimaryAxisValue(
191         shelf_bounds.height(),
192         shelf_bounds.width());
193     int visible_bounds_size = GetShelfLayoutManager()->PrimaryAxisValue(
194         visible_bounds_.height(),
195         visible_bounds_.width());
196     int not_visible_bounds_size = GetShelfLayoutManager()->PrimaryAxisValue(
197         not_visible_bounds_.height(),
198         not_visible_bounds_.width());
199     if (was_visible_on_drag_start_) {
200       if (increasing_drag) {
201         // If dragging inwards from the visible state, then the shelf should
202         // increase in size, but not more than the scroll delta.
203         EXPECT_LE(visible_bounds_size, shelf_size);
204         EXPECT_LE(abs(shelf_size - visible_bounds_size),
205                   abs(scroll_delta));
206       } else {
207         if (shelf_size > not_visible_bounds_size) {
208           // If dragging outwards from the visible state, then the shelf
209           // should decrease in size, until it reaches the minimum size.
210           EXPECT_EQ(shelf_size, visible_bounds_size - abs(scroll_delta));
211         }
212       }
213     } else {
214       if (fabs(scroll_delta) <
215           visible_bounds_size - not_visible_bounds_size) {
216         // Tests that the shelf sticks with the touch point during the drag
217         // until the shelf is completely visible.
218         EXPECT_EQ(shelf_size, not_visible_bounds_size + abs(scroll_delta));
219       } else {
220         // Tests that after the shelf is completely visible, the shelf starts
221         // resisting the drag.
222         EXPECT_LT(shelf_size, not_visible_bounds_size + abs(scroll_delta));
223       }
224     }
225   }
226
227  private:
228   const gfx::Rect not_visible_bounds_;
229   const gfx::Rect visible_bounds_;
230   gfx::Vector2dF scroll_;
231   bool was_visible_on_drag_start_;
232
233   DISALLOW_COPY_AND_ASSIGN(ShelfDragCallback);
234 };
235
236 class ShelfLayoutObserverTest : public ShelfLayoutManagerObserver {
237  public:
238   ShelfLayoutObserverTest()
239       : changed_auto_hide_state_(false) {
240   }
241
242   virtual ~ShelfLayoutObserverTest() {}
243
244   bool changed_auto_hide_state() const { return changed_auto_hide_state_; }
245
246  private:
247   virtual void OnAutoHideStateChanged(
248       ShelfAutoHideState new_state) OVERRIDE {
249     changed_auto_hide_state_ = true;
250   }
251
252   bool changed_auto_hide_state_;
253
254   DISALLOW_COPY_AND_ASSIGN(ShelfLayoutObserverTest);
255 };
256
257 // Trivial item implementation that tracks its views for testing.
258 class TestItem : public SystemTrayItem {
259  public:
260   TestItem()
261       : SystemTrayItem(GetSystemTray()),
262         tray_view_(NULL),
263         default_view_(NULL),
264         detailed_view_(NULL),
265         notification_view_(NULL) {}
266
267   virtual views::View* CreateTrayView(user::LoginStatus status) OVERRIDE {
268     tray_view_ = new views::View;
269     // Add a label so it has non-zero width.
270     tray_view_->SetLayoutManager(new views::FillLayout);
271     tray_view_->AddChildView(new views::Label(base::UTF8ToUTF16("Tray")));
272     return tray_view_;
273   }
274
275   virtual views::View* CreateDefaultView(user::LoginStatus status) OVERRIDE {
276     default_view_ = new views::View;
277     default_view_->SetLayoutManager(new views::FillLayout);
278     default_view_->AddChildView(new views::Label(base::UTF8ToUTF16("Default")));
279     return default_view_;
280   }
281
282   virtual views::View* CreateDetailedView(user::LoginStatus status) OVERRIDE {
283     detailed_view_ = new views::View;
284     detailed_view_->SetLayoutManager(new views::FillLayout);
285     detailed_view_->AddChildView(
286         new views::Label(base::UTF8ToUTF16("Detailed")));
287     return detailed_view_;
288   }
289
290   virtual views::View* CreateNotificationView(
291       user::LoginStatus status) OVERRIDE {
292     notification_view_ = new views::View;
293     return notification_view_;
294   }
295
296   virtual void DestroyTrayView() OVERRIDE {
297     tray_view_ = NULL;
298   }
299
300   virtual void DestroyDefaultView() OVERRIDE {
301     default_view_ = NULL;
302   }
303
304   virtual void DestroyDetailedView() OVERRIDE {
305     detailed_view_ = NULL;
306   }
307
308   virtual void DestroyNotificationView() OVERRIDE {
309     notification_view_ = NULL;
310   }
311
312   virtual void UpdateAfterLoginStatusChange(
313       user::LoginStatus status) OVERRIDE {}
314
315   views::View* tray_view() const { return tray_view_; }
316   views::View* default_view() const { return default_view_; }
317   views::View* detailed_view() const { return detailed_view_; }
318   views::View* notification_view() const { return notification_view_; }
319
320  private:
321   views::View* tray_view_;
322   views::View* default_view_;
323   views::View* detailed_view_;
324   views::View* notification_view_;
325
326   DISALLOW_COPY_AND_ASSIGN(TestItem);
327 };
328
329 }  // namespace
330
331 class ShelfLayoutManagerTest : public ash::test::AshTestBase {
332  public:
333   ShelfLayoutManagerTest() {}
334
335   void SetState(ShelfLayoutManager* shelf,
336                 ShelfVisibilityState state) {
337     shelf->SetState(state);
338   }
339
340   void UpdateAutoHideStateNow() {
341     GetShelfLayoutManager()->UpdateAutoHideStateNow();
342   }
343
344   aura::Window* CreateTestWindow() {
345     aura::Window* window = new aura::Window(NULL);
346     window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
347     window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
348     window->Init(aura::WINDOW_LAYER_TEXTURED);
349     ParentWindowInPrimaryRootWindow(window);
350     return window;
351   }
352
353   views::Widget* CreateTestWidgetWithParams(
354       const views::Widget::InitParams& params) {
355     views::Widget* out = new views::Widget;
356     out->Init(params);
357     out->Show();
358     return out;
359   }
360
361   // Create a simple widget attached to the current context (will
362   // delete on TearDown).
363   views::Widget* CreateTestWidget() {
364     views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
365     params.bounds = gfx::Rect(0, 0, 200, 200);
366     params.context = CurrentContext();
367     return CreateTestWidgetWithParams(params);
368   }
369
370   // Overridden from AshTestBase:
371   virtual void SetUp() OVERRIDE {
372     CommandLine::ForCurrentProcess()->AppendSwitch(
373         ash::switches::kAshEnableTrayDragging);
374     test::AshTestBase::SetUp();
375   }
376
377   void RunGestureDragTests(gfx::Vector2d);
378
379  private:
380   DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManagerTest);
381 };
382
383 void ShelfLayoutManagerTest::RunGestureDragTests(gfx::Vector2d delta) {
384   ShelfLayoutManager* shelf = GetShelfLayoutManager();
385   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
386   views::Widget* widget = new views::Widget;
387   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
388   params.bounds = gfx::Rect(0, 0, 200, 200);
389   params.context = CurrentContext();
390   widget->Init(params);
391   widget->Show();
392   widget->Maximize();
393
394   aura::Window* window = widget->GetNativeWindow();
395   shelf->LayoutShelf();
396
397   gfx::Rect shelf_shown = GetShelfWidget()->GetWindowBoundsInScreen();
398   gfx::Rect bounds_shelf = window->bounds();
399   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
400
401   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
402   shelf->LayoutShelf();
403   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
404
405   gfx::Rect bounds_noshelf = window->bounds();
406   gfx::Rect shelf_hidden = GetShelfWidget()->GetWindowBoundsInScreen();
407
408   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
409   shelf->LayoutShelf();
410
411   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
412   const int kNumScrollSteps = 4;
413   ShelfDragCallback handler(shelf_hidden, shelf_shown);
414
415   // Swipe up on the shelf. This should not change any state.
416   gfx::Point start = GetShelfWidget()->GetWindowBoundsInScreen().CenterPoint();
417   gfx::Point end = start + delta;
418
419   // Swipe down on the shelf to hide it.
420   generator.GestureScrollSequenceWithCallback(start, end,
421       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
422       base::Bind(&ShelfDragCallback::ProcessScroll,
423                  base::Unretained(&handler)));
424   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
425   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
426   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
427   EXPECT_NE(bounds_shelf.ToString(), window->bounds().ToString());
428   EXPECT_NE(shelf_shown.ToString(),
429             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
430
431   // Swipe up to show the shelf.
432   generator.GestureScrollSequenceWithCallback(end, start,
433       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
434       base::Bind(&ShelfDragCallback::ProcessScroll,
435                  base::Unretained(&handler)));
436   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
437   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
438   EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
439   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
440             GetShelfWidget()->GetWindowBoundsInScreen());
441   EXPECT_EQ(shelf_shown.ToString(),
442             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
443
444   // Swipe up again. The shelf should hide.
445   end = start - delta;
446   generator.GestureScrollSequenceWithCallback(start, end,
447       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
448       base::Bind(&ShelfDragCallback::ProcessScroll,
449                  base::Unretained(&handler)));
450   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
451   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
452   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
453   EXPECT_EQ(shelf_hidden.ToString(),
454             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
455
456   // Swipe up yet again to show it.
457   end = start + delta;
458   generator.GestureScrollSequenceWithCallback(end, start,
459       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
460       base::Bind(&ShelfDragCallback::ProcessScroll,
461                  base::Unretained(&handler)));
462
463   // Swipe down very little. It shouldn't change any state.
464   if (GetShelfLayoutManager()->IsHorizontalAlignment())
465     end.set_y(start.y() + shelf_shown.height() * 3 / 10);
466   else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
467     end.set_x(start.x() - shelf_shown.width() * 3 / 10);
468   else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
469     end.set_x(start.x() + shelf_shown.width() * 3 / 10);
470   generator.GestureScrollSequence(start, end,
471                                   base::TimeDelta::FromMilliseconds(10), 5);
472   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
473   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
474   EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
475   EXPECT_EQ(shelf_shown.ToString(),
476             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
477
478   // Swipe down again to hide.
479   end = start + delta;
480   generator.GestureScrollSequenceWithCallback(start, end,
481       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
482       base::Bind(&ShelfDragCallback::ProcessScroll,
483                  base::Unretained(&handler)));
484   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
485   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
486   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
487   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
488   EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
489   EXPECT_EQ(shelf_hidden.ToString(),
490             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
491
492   // Swipe up in extended hit region to show it.
493   gfx::Point extended_start = start;
494   if (GetShelfLayoutManager()->IsHorizontalAlignment())
495     extended_start.set_y(GetShelfWidget()->GetWindowBoundsInScreen().y() -1);
496   else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
497     extended_start.set_x(
498         GetShelfWidget()->GetWindowBoundsInScreen().right() + 1);
499   else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
500     extended_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().x() - 1);
501   end = extended_start - delta;
502   generator.GestureScrollSequenceWithCallback(extended_start, end,
503       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
504       base::Bind(&ShelfDragCallback::ProcessScroll,
505                  base::Unretained(&handler)));
506   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
507   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
508   EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
509   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
510             GetShelfWidget()->GetWindowBoundsInScreen());
511   EXPECT_EQ(shelf_shown.ToString(),
512             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
513
514   // Swipe down again to hide.
515   end = start + delta;
516   generator.GestureScrollSequenceWithCallback(start, end,
517       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
518       base::Bind(&ShelfDragCallback::ProcessScroll,
519                  base::Unretained(&handler)));
520   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
521   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
522   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
523   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
524   EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
525   EXPECT_EQ(shelf_hidden.ToString(),
526             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
527
528   // Swipe up outside the hit area. This should not change anything.
529   gfx::Point outside_start = gfx::Point(
530       (GetShelfWidget()->GetWindowBoundsInScreen().x() +
531        GetShelfWidget()->GetWindowBoundsInScreen().right())/2,
532       GetShelfWidget()->GetWindowBoundsInScreen().y() - 50);
533   end = outside_start + delta;
534   generator.GestureScrollSequence(outside_start,
535                                   end,
536                                   base::TimeDelta::FromMilliseconds(10),
537                                   kNumScrollSteps);
538   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
539   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
540   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
541   EXPECT_EQ(shelf_hidden.ToString(),
542             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
543
544   // Swipe up from below the shelf where a bezel would be, this should show the
545   // shelf.
546   gfx::Point below_start = start;
547   if (GetShelfLayoutManager()->IsHorizontalAlignment())
548     below_start.set_y(GetShelfWidget()->GetWindowBoundsInScreen().bottom() + 1);
549   else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
550     below_start.set_x(
551         GetShelfWidget()->GetWindowBoundsInScreen().x() - 1);
552   else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
553     below_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().right() + 1);
554   end = below_start - delta;
555   generator.GestureScrollSequence(below_start,
556                                   end,
557                                   base::TimeDelta::FromMilliseconds(10),
558                                   kNumScrollSteps);
559   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
560   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
561   EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
562   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
563             GetShelfWidget()->GetWindowBoundsInScreen());
564   EXPECT_EQ(shelf_shown.ToString(),
565             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
566
567   // Swipe down again to hide.
568   end = start + delta;
569   generator.GestureScrollSequenceWithCallback(start, end,
570       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
571       base::Bind(&ShelfDragCallback::ProcessScroll,
572                  base::Unretained(&handler)));
573   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
574   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
575   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
576   EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
577   EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
578   EXPECT_EQ(shelf_hidden.ToString(),
579             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
580
581   // Put |widget| into fullscreen. Set the shelf to be auto hidden when |widget|
582   // is fullscreen. (eg browser immersive fullscreen).
583   widget->SetFullscreen(true);
584   wm::GetWindowState(window)->set_hide_shelf_when_fullscreen(false);
585   shelf->UpdateVisibilityState();
586
587   gfx::Rect bounds_fullscreen = window->bounds();
588   EXPECT_TRUE(widget->IsFullscreen());
589   EXPECT_NE(bounds_noshelf.ToString(), bounds_fullscreen.ToString());
590
591   // Swipe up. This should show the shelf.
592   end = below_start - delta;
593   generator.GestureScrollSequenceWithCallback(below_start, end,
594       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
595       base::Bind(&ShelfDragCallback::ProcessScroll,
596                  base::Unretained(&handler)));
597   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
598   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
599   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
600   EXPECT_EQ(shelf_shown.ToString(),
601             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
602   EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
603
604   // Swipe up again. This should hide the shelf.
605   generator.GestureScrollSequenceWithCallback(below_start, end,
606       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
607       base::Bind(&ShelfDragCallback::ProcessScroll,
608                  base::Unretained(&handler)));
609   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
610   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
611   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
612   EXPECT_EQ(shelf_hidden.ToString(),
613             GetShelfWidget()->GetWindowBoundsInScreen().ToString());
614   EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
615
616   // Set the shelf to be hidden when |widget| is fullscreen. (eg tab fullscreen
617   // with or without immersive browser fullscreen).
618   wm::GetWindowState(window)->set_hide_shelf_when_fullscreen(true);
619   shelf->UpdateVisibilityState();
620   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
621   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
622
623   // Swipe-up. This should not change anything.
624   end = start - delta;
625   generator.GestureScrollSequenceWithCallback(below_start, end,
626       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
627       base::Bind(&ShelfDragCallback::ProcessScroll,
628                  base::Unretained(&handler)));
629   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
630   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
631   EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
632
633   // Close actually, otherwise further event may be affected since widget
634   // is fullscreen status.
635   widget->Close();
636   RunAllPendingInMessageLoop();
637
638   // The shelf should be shown because there are no more visible windows.
639   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
640   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
641   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
642
643   // Swipe-up to hide. This should have no effect because there are no visible
644   // windows.
645   end = below_start - delta;
646   generator.GestureScrollSequenceWithCallback(below_start, end,
647       base::TimeDelta::FromMilliseconds(10), kNumScrollSteps,
648       base::Bind(&ShelfDragCallback::ProcessScroll,
649                  base::Unretained(&handler)));
650   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
651   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
652   EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
653 }
654
655 // Need to be implemented.  http://crbug.com/111279.
656 #if defined(OS_WIN)
657 #define MAYBE_SetVisible DISABLED_SetVisible
658 #else
659 #define MAYBE_SetVisible SetVisible
660 #endif
661 // Makes sure SetVisible updates work area and widget appropriately.
662 TEST_F(ShelfLayoutManagerTest, MAYBE_SetVisible) {
663   ShelfWidget* shelf = GetShelfWidget();
664   ShelfLayoutManager* manager = shelf->shelf_layout_manager();
665   // Force an initial layout.
666   manager->LayoutShelf();
667   EXPECT_EQ(SHELF_VISIBLE, manager->visibility_state());
668
669   gfx::Rect status_bounds(
670       shelf->status_area_widget()->GetWindowBoundsInScreen());
671   gfx::Rect shelf_bounds(
672       shelf->GetWindowBoundsInScreen());
673   int shelf_height = manager->GetIdealBounds().height();
674   gfx::Screen* screen = Shell::GetScreen();
675   gfx::Display display = screen->GetDisplayNearestWindow(
676       Shell::GetPrimaryRootWindow());
677   ASSERT_NE(-1, display.id());
678   // Bottom inset should be the max of widget heights.
679   EXPECT_EQ(shelf_height, display.GetWorkAreaInsets().bottom());
680
681   // Hide the shelf.
682   SetState(manager, SHELF_HIDDEN);
683   // Run the animation to completion.
684   StepWidgetLayerAnimatorToEnd(shelf);
685   StepWidgetLayerAnimatorToEnd(shelf->status_area_widget());
686   EXPECT_EQ(SHELF_HIDDEN, manager->visibility_state());
687   display = screen->GetDisplayNearestWindow(
688       Shell::GetPrimaryRootWindow());
689
690   EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
691
692   // Make sure the bounds of the two widgets changed.
693   EXPECT_GE(shelf->GetNativeView()->bounds().y(),
694             screen->GetPrimaryDisplay().bounds().bottom());
695   EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(),
696             screen->GetPrimaryDisplay().bounds().bottom());
697
698   // And show it again.
699   SetState(manager, SHELF_VISIBLE);
700   // Run the animation to completion.
701   StepWidgetLayerAnimatorToEnd(shelf);
702   StepWidgetLayerAnimatorToEnd(shelf->status_area_widget());
703   EXPECT_EQ(SHELF_VISIBLE, manager->visibility_state());
704   display = screen->GetDisplayNearestWindow(
705       Shell::GetPrimaryRootWindow());
706   EXPECT_EQ(shelf_height, display.GetWorkAreaInsets().bottom());
707
708   // Make sure the bounds of the two widgets changed.
709   shelf_bounds = shelf->GetNativeView()->bounds();
710   EXPECT_LT(shelf_bounds.y(), screen->GetPrimaryDisplay().bounds().bottom());
711   status_bounds = shelf->status_area_widget()->GetNativeView()->bounds();
712   EXPECT_LT(status_bounds.y(),
713             screen->GetPrimaryDisplay().bounds().bottom());
714 }
715
716 // Makes sure shelf alignment is correct for lock screen.
717 TEST_F(ShelfLayoutManagerTest, SideAlignmentInteractionWithLockScreen) {
718   ShelfLayoutManager* manager = GetShelfWidget()->shelf_layout_manager();
719   manager->SetAlignment(SHELF_ALIGNMENT_LEFT);
720   EXPECT_EQ(SHELF_ALIGNMENT_LEFT, manager->GetAlignment());
721   Shell::GetInstance()->session_state_delegate()->LockScreen();
722   EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, manager->GetAlignment());
723   Shell::GetInstance()->session_state_delegate()->UnlockScreen();
724   EXPECT_EQ(SHELF_ALIGNMENT_LEFT, manager->GetAlignment());
725 }
726
727 // Makes sure LayoutShelf invoked while animating cleans things up.
728 TEST_F(ShelfLayoutManagerTest, LayoutShelfWhileAnimating) {
729   ShelfWidget* shelf = GetShelfWidget();
730   // Force an initial layout.
731   shelf->shelf_layout_manager()->LayoutShelf();
732   EXPECT_EQ(SHELF_VISIBLE, shelf->shelf_layout_manager()->visibility_state());
733
734   // Hide the shelf.
735   SetState(shelf->shelf_layout_manager(), SHELF_HIDDEN);
736   shelf->shelf_layout_manager()->LayoutShelf();
737   EXPECT_EQ(SHELF_HIDDEN, shelf->shelf_layout_manager()->visibility_state());
738   gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
739       Shell::GetPrimaryRootWindow());
740   EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
741
742   // Make sure the bounds of the two widgets changed.
743   EXPECT_GE(shelf->GetNativeView()->bounds().y(),
744             Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
745   EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(),
746             Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
747 }
748
749 // Test that switching to a different visibility state does not restart the
750 // shelf show / hide animation if it is already running. (crbug.com/250918)
751 TEST_F(ShelfLayoutManagerTest, SetStateWhileAnimating) {
752   ShelfWidget* shelf = GetShelfWidget();
753   SetState(shelf->shelf_layout_manager(), SHELF_VISIBLE);
754   gfx::Rect initial_shelf_bounds = shelf->GetWindowBoundsInScreen();
755   gfx::Rect initial_status_bounds =
756       shelf->status_area_widget()->GetWindowBoundsInScreen();
757
758   ui::ScopedAnimationDurationScaleMode normal_animation_duration(
759       ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
760   SetState(shelf->shelf_layout_manager(), SHELF_HIDDEN);
761   SetState(shelf->shelf_layout_manager(), SHELF_VISIBLE);
762
763   gfx::Rect current_shelf_bounds = shelf->GetWindowBoundsInScreen();
764   gfx::Rect current_status_bounds =
765       shelf->status_area_widget()->GetWindowBoundsInScreen();
766
767   const int small_change = initial_shelf_bounds.height() / 2;
768   EXPECT_LE(
769       std::abs(initial_shelf_bounds.height() - current_shelf_bounds.height()),
770       small_change);
771   EXPECT_LE(
772       std::abs(initial_status_bounds.height() - current_status_bounds.height()),
773       small_change);
774 }
775
776 // Makes sure the shelf is sized when the status area changes size.
777 TEST_F(ShelfLayoutManagerTest, ShelfUpdatedWhenStatusAreaChangesSize) {
778   Shelf* shelf = Shelf::ForPrimaryDisplay();
779   ASSERT_TRUE(shelf);
780   ShelfWidget* shelf_widget = GetShelfWidget();
781   ASSERT_TRUE(shelf_widget);
782   ASSERT_TRUE(shelf_widget->status_area_widget());
783   shelf_widget->status_area_widget()->SetBounds(
784       gfx::Rect(0, 0, 200, 200));
785   EXPECT_EQ(200, shelf_widget->GetContentsView()->width() -
786             test::ShelfTestAPI(shelf).shelf_view()->width());
787 }
788
789
790 #if defined(OS_WIN)
791 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
792 #define MAYBE_AutoHide DISABLED_AutoHide
793 #else
794 #define MAYBE_AutoHide AutoHide
795 #endif
796
797 // Various assertions around auto-hide.
798 TEST_F(ShelfLayoutManagerTest, MAYBE_AutoHide) {
799   aura::Window* root = Shell::GetPrimaryRootWindow();
800   aura::test::EventGenerator generator(root, root);
801   generator.MoveMouseTo(0, 0);
802
803   ShelfLayoutManager* shelf = GetShelfLayoutManager();
804   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
805   views::Widget* widget = new views::Widget;
806   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
807   params.bounds = gfx::Rect(0, 0, 200, 200);
808   params.context = CurrentContext();
809   // Widget is now owned by the parent window.
810   widget->Init(params);
811   widget->Maximize();
812   widget->Show();
813   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
814   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
815
816   // LayoutShelf() forces the animation to completion, at which point the
817   // shelf should go off the screen.
818   shelf->LayoutShelf();
819   EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
820             GetShelfWidget()->GetWindowBoundsInScreen().y());
821   EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
822             Shell::GetScreen()->GetDisplayNearestWindow(
823                 root).work_area().bottom());
824
825   // Move the mouse to the bottom of the screen.
826   generator.MoveMouseTo(0, root->bounds().bottom() - 1);
827
828   // Shelf should be shown again (but it shouldn't have changed the work area).
829   SetState(shelf, SHELF_AUTO_HIDE);
830   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
831   shelf->LayoutShelf();
832   EXPECT_EQ(root->bounds().bottom() - shelf->GetIdealBounds().height(),
833             GetShelfWidget()->GetWindowBoundsInScreen().y());
834   EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
835             Shell::GetScreen()->GetDisplayNearestWindow(
836                 root).work_area().bottom());
837
838   // Move mouse back up.
839   generator.MoveMouseTo(0, 0);
840   SetState(shelf, SHELF_AUTO_HIDE);
841   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
842   shelf->LayoutShelf();
843   EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
844             GetShelfWidget()->GetWindowBoundsInScreen().y());
845
846   // Drag mouse to bottom of screen.
847   generator.PressLeftButton();
848   generator.MoveMouseTo(0, root->bounds().bottom() - 1);
849   UpdateAutoHideStateNow();
850   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
851
852   generator.ReleaseLeftButton();
853   generator.MoveMouseTo(1, root->bounds().bottom() - 1);
854   UpdateAutoHideStateNow();
855   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
856   generator.PressLeftButton();
857   generator.MoveMouseTo(1, root->bounds().bottom() - 1);
858   UpdateAutoHideStateNow();
859   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
860 }
861
862 // Check that swipes and mouse interactions do have no impact in Maximize mode.
863 TEST_F(ShelfLayoutManagerTest, MaximizeModePreventsMouseHide) {
864   aura::Window* root = Shell::GetPrimaryRootWindow();
865   aura::test::EventGenerator generator(root, root);
866   generator.MoveMouseTo(0, 0);
867
868   ShelfLayoutManager* shelf = GetShelfLayoutManager();
869   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
870   views::Widget* widget = new views::Widget;
871   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
872   params.bounds = gfx::Rect(0, 0, 200, 200);
873   params.context = CurrentContext();
874   // Widget is now owned by the parent window.
875   widget->Init(params);
876   widget->Maximize();
877   widget->Show();
878   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
879   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
880
881   shelf->OnMaximizeModeStarted();
882   // LayoutShelf() forces the animation to completion.
883   shelf->LayoutShelf();
884
885   // Drag mouse to bottom of screen. In contrast to normal operation the shelf
886   // should remain visible.
887   generator.MoveMouseTo(0, 0);
888   generator.PressLeftButton();
889   generator.MoveMouseTo(0, root->bounds().bottom() - 1);
890   UpdateAutoHideStateNow();
891   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
892 }
893
894 // Test the behavior of the shelf when it is auto hidden and it is on the
895 // boundary between the primary and the secondary display.
896 TEST_F(ShelfLayoutManagerTest, AutoHideShelfOnScreenBoundary) {
897   if (!SupportsMultipleDisplays())
898     return;
899
900   UpdateDisplay("800x600,800x600");
901   DisplayLayout display_layout(DisplayLayout::RIGHT, 0);
902   Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
903       display_layout);
904   // Put the primary monitor's shelf on the display boundary.
905   ShelfLayoutManager* shelf = GetShelfLayoutManager();
906   shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
907
908   // Create a window because the shelf is always shown when no windows are
909   // visible.
910   CreateTestWidget();
911
912   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
913   ASSERT_EQ(root_windows[0],
914             GetShelfWidget()->GetNativeWindow()->GetRootWindow());
915
916   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
917   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
918
919   int right_edge = root_windows[0]->GetBoundsInScreen().right() - 1;
920   int y = root_windows[0]->GetBoundsInScreen().y();
921
922   // Start off the mouse nowhere near the shelf; the shelf should be hidden.
923   aura::test::EventGenerator& generator(GetEventGenerator());
924   generator.MoveMouseTo(right_edge - 50, y);
925   UpdateAutoHideStateNow();
926   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
927
928   // Moving the mouse over the light bar (but not to the edge of the screen)
929   // should show the shelf.
930   generator.MoveMouseTo(right_edge - 1, y);
931   UpdateAutoHideStateNow();
932   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
933   EXPECT_EQ(right_edge - 1, Shell::GetScreen()->GetCursorScreenPoint().x());
934
935   // Moving the mouse off the light bar should hide the shelf.
936   generator.MoveMouseTo(right_edge - 50, y);
937   UpdateAutoHideStateNow();
938   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
939
940   // Moving the mouse to the right edge of the screen crossing the light bar
941   // should show the shelf despite the mouse cursor getting warped to the
942   // secondary display.
943   generator.MoveMouseTo(right_edge - 1, y);
944   generator.MoveMouseTo(right_edge, y);
945   UpdateAutoHideStateNow();
946   EXPECT_NE(right_edge - 1, Shell::GetScreen()->GetCursorScreenPoint().x());
947   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
948
949   // Hide the shelf.
950   generator.MoveMouseTo(right_edge - 50, y);
951   UpdateAutoHideStateNow();
952   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
953
954   // Moving the mouse to the right edge of the screen crossing the light bar and
955   // overshooting by a lot should keep the shelf hidden.
956   generator.MoveMouseTo(right_edge - 1, y);
957   generator.MoveMouseTo(right_edge + 50, y);
958   UpdateAutoHideStateNow();
959   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
960
961   // Moving the mouse to the right edge of the screen crossing the light bar and
962   // overshooting a bit should show the shelf.
963   generator.MoveMouseTo(right_edge - 1, y);
964   generator.MoveMouseTo(right_edge + 2, y);
965   UpdateAutoHideStateNow();
966   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
967
968   // Keeping the mouse close to the left edge of the secondary display after the
969   // shelf is shown should keep the shelf shown.
970   generator.MoveMouseTo(right_edge + 2, y + 1);
971   UpdateAutoHideStateNow();
972   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
973
974   // Moving the mouse far from the left edge of the secondary display should
975   // hide the shelf.
976   generator.MoveMouseTo(right_edge + 50, y);
977   UpdateAutoHideStateNow();
978   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
979
980   // Moving to the left edge of the secondary display without first crossing
981   // the primary display's right aligned shelf first should not show the shelf.
982   generator.MoveMouseTo(right_edge + 2, y);
983   UpdateAutoHideStateNow();
984   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
985 }
986
987 // Assertions around the lock screen showing.
988 TEST_F(ShelfLayoutManagerTest, VisibleWhenLockScreenShowing) {
989   // Since ShelfLayoutManager queries for mouse location, move the mouse so
990   // it isn't over the shelf.
991   aura::test::EventGenerator generator(
992       Shell::GetPrimaryRootWindow(), gfx::Point());
993   generator.MoveMouseTo(0, 0);
994
995   ShelfLayoutManager* shelf = GetShelfLayoutManager();
996   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
997   views::Widget* widget = new views::Widget;
998   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
999   params.bounds = gfx::Rect(0, 0, 200, 200);
1000   params.context = CurrentContext();
1001   // Widget is now owned by the parent window.
1002   widget->Init(params);
1003   widget->Maximize();
1004   widget->Show();
1005   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1006   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1007
1008   aura::Window* root = Shell::GetPrimaryRootWindow();
1009   // LayoutShelf() forces the animation to completion, at which point the
1010   // shelf should go off the screen.
1011   shelf->LayoutShelf();
1012   EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
1013             GetShelfWidget()->GetWindowBoundsInScreen().y());
1014
1015   aura::Window* lock_container = Shell::GetContainer(
1016       Shell::GetPrimaryRootWindow(), kShellWindowId_LockScreenContainer);
1017
1018   views::Widget* lock_widget = new views::Widget;
1019   views::Widget::InitParams lock_params(
1020       views::Widget::InitParams::TYPE_WINDOW);
1021   lock_params.bounds = gfx::Rect(0, 0, 200, 200);
1022   params.context = CurrentContext();
1023   lock_params.parent = lock_container;
1024   // Widget is now owned by the parent window.
1025   lock_widget->Init(lock_params);
1026   lock_widget->Maximize();
1027   lock_widget->Show();
1028
1029   // Lock the screen.
1030   Shell::GetInstance()->session_state_delegate()->LockScreen();
1031   shelf->UpdateVisibilityState();
1032   // Showing a widget in the lock screen should force the shelf to be visibile.
1033   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1034
1035   Shell::GetInstance()->session_state_delegate()->UnlockScreen();
1036   shelf->UpdateVisibilityState();
1037   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1038 }
1039
1040 // Assertions around SetAutoHideBehavior.
1041 TEST_F(ShelfLayoutManagerTest, SetAutoHideBehavior) {
1042   // Since ShelfLayoutManager queries for mouse location, move the mouse so
1043   // it isn't over the shelf.
1044   aura::test::EventGenerator generator(
1045       Shell::GetPrimaryRootWindow(), gfx::Point());
1046   generator.MoveMouseTo(0, 0);
1047
1048   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1049   views::Widget* widget = new views::Widget;
1050   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1051   params.bounds = gfx::Rect(0, 0, 200, 200);
1052   params.context = CurrentContext();
1053   // Widget is now owned by the parent window.
1054   widget->Init(params);
1055   widget->Show();
1056   aura::Window* window = widget->GetNativeWindow();
1057   gfx::Rect display_bounds(
1058       Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
1059
1060   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1061   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1062
1063   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1064   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1065
1066   widget->Maximize();
1067   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1068   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
1069                 window).work_area().bottom(),
1070             widget->GetWorkAreaBoundsInScreen().bottom());
1071
1072   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1073   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1074   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
1075                 window).work_area().bottom(),
1076             widget->GetWorkAreaBoundsInScreen().bottom());
1077
1078   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1079   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1080   EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
1081                 window).work_area().bottom(),
1082             widget->GetWorkAreaBoundsInScreen().bottom());
1083 }
1084
1085 // Basic assertions around the dimming of the shelf.
1086 TEST_F(ShelfLayoutManagerTest, TestDimmingBehavior) {
1087   // Since ShelfLayoutManager queries for mouse location, move the mouse so
1088   // it isn't over the shelf.
1089   aura::test::EventGenerator generator(
1090       Shell::GetPrimaryRootWindow(), gfx::Point());
1091   generator.MoveMouseTo(0, 0);
1092
1093   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1094   shelf->shelf_widget()->DisableDimmingAnimationsForTest();
1095
1096   views::Widget* widget = new views::Widget;
1097   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1098   params.bounds = gfx::Rect(0, 0, 200, 200);
1099   params.context = CurrentContext();
1100   // Widget is now owned by the parent window.
1101   widget->Init(params);
1102   widget->Show();
1103   aura::Window* window = widget->GetNativeWindow();
1104   gfx::Rect display_bounds(
1105       Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
1106
1107   gfx::Point off_shelf = display_bounds.CenterPoint();
1108   gfx::Point on_shelf =
1109       shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
1110
1111   // Test there is no dimming object active at this point.
1112   generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
1113   EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
1114   generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
1115   EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
1116
1117   // After maximization, the shelf should be visible and the dimmer created.
1118   widget->Maximize();
1119
1120   on_shelf = shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
1121   EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1122
1123   // Moving the mouse off the shelf should dim the bar.
1124   generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
1125   EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1126
1127   // Adding touch events outside the shelf should still keep the shelf in
1128   // dimmed state.
1129   generator.PressTouch();
1130   generator.MoveTouch(off_shelf);
1131   EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1132   // Move the touch into the shelf area should undim.
1133   generator.MoveTouch(on_shelf);
1134   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1135   generator.ReleaseTouch();
1136   // And a release dims again.
1137   EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1138
1139   // Moving the mouse on the shelf should undim the bar.
1140   generator.MoveMouseTo(on_shelf);
1141   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1142
1143   // No matter what the touch events do, the shelf should stay undimmed.
1144   generator.PressTouch();
1145   generator.MoveTouch(off_shelf);
1146   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1147   generator.MoveTouch(on_shelf);
1148   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1149   generator.MoveTouch(off_shelf);
1150   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1151   generator.MoveTouch(on_shelf);
1152   generator.ReleaseTouch();
1153
1154   // After restore, the dimming object should be deleted again.
1155   widget->Restore();
1156   EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
1157 }
1158
1159 // Assertions around the dimming of the shelf in conjunction with menus.
1160 TEST_F(ShelfLayoutManagerTest, TestDimmingBehaviorWithMenus) {
1161   // Since ShelfLayoutManager queries for mouse location, move the mouse so
1162   // it isn't over the shelf.
1163   aura::test::EventGenerator generator(
1164       Shell::GetPrimaryRootWindow(), gfx::Point());
1165   generator.MoveMouseTo(0, 0);
1166
1167   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1168   shelf->shelf_widget()->DisableDimmingAnimationsForTest();
1169
1170   views::Widget* widget = new views::Widget;
1171   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1172   params.bounds = gfx::Rect(0, 0, 200, 200);
1173   params.context = CurrentContext();
1174   // Widget is now owned by the parent window.
1175   widget->Init(params);
1176   widget->Show();
1177   aura::Window* window = widget->GetNativeWindow();
1178   gfx::Rect display_bounds(
1179       Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
1180
1181   // After maximization, the shelf should be visible and the dimmer created.
1182   widget->Maximize();
1183
1184   gfx::Point off_shelf = display_bounds.CenterPoint();
1185   gfx::Point on_shelf =
1186       shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
1187
1188   // Moving the mouse on the shelf should undim the bar.
1189   generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
1190   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1191
1192   // Simulate a menu opening.
1193   shelf->shelf_widget()->ForceUndimming(true);
1194
1195   // Moving the mouse off the shelf should not dim the bar.
1196   generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
1197   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1198
1199   // No matter what the touch events do, the shelf should stay undimmed.
1200   generator.PressTouch();
1201   generator.MoveTouch(off_shelf);
1202   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1203   generator.MoveTouch(on_shelf);
1204   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1205   generator.MoveTouch(off_shelf);
1206   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1207   generator.ReleaseTouch();
1208   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1209
1210   // "Closing the menu" should now turn off the menu since no event is inside
1211   // the shelf any longer.
1212   shelf->shelf_widget()->ForceUndimming(false);
1213   EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1214
1215   // Moving the mouse again on the shelf which should undim the bar again.
1216   // This time we check that the bar stays undimmed when the mouse remains on
1217   // the bar and the "menu gets closed".
1218   generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
1219   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1220   shelf->shelf_widget()->ForceUndimming(true);
1221   generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
1222   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1223   generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
1224   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1225   shelf->shelf_widget()->ForceUndimming(true);
1226   EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1227 }
1228
1229 // Verifies the shelf is visible when status/shelf is focused.
1230 TEST_F(ShelfLayoutManagerTest, VisibleWhenStatusOrShelfFocused) {
1231   // Since ShelfLayoutManager queries for mouse location, move the mouse so
1232   // it isn't over the shelf.
1233   aura::test::EventGenerator generator(
1234       Shell::GetPrimaryRootWindow(), gfx::Point());
1235   generator.MoveMouseTo(0, 0);
1236
1237   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1238   views::Widget* widget = new views::Widget;
1239   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1240   params.bounds = gfx::Rect(0, 0, 200, 200);
1241   params.context = CurrentContext();
1242   // Widget is now owned by the parent window.
1243   widget->Init(params);
1244   widget->Show();
1245   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1246   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1247   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1248
1249   // Focus the shelf. Have to go through the focus cycler as normal focus
1250   // requests to it do nothing.
1251   GetShelfWidget()->GetFocusCycler()->RotateFocus(FocusCycler::FORWARD);
1252   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1253
1254   widget->Activate();
1255   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1256
1257   // Trying to activate the status should fail, since we only allow activating
1258   // it when the user is using the keyboard (i.e. through FocusCycler).
1259   GetShelfWidget()->status_area_widget()->Activate();
1260   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1261
1262   GetShelfWidget()->GetFocusCycler()->RotateFocus(FocusCycler::FORWARD);
1263   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1264 }
1265
1266 // Makes sure shelf will be visible when app list opens as shelf is in
1267 // SHELF_VISIBLE state,and toggling app list won't change shelf
1268 // visibility state.
1269 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfVisibleState) {
1270   Shell* shell = Shell::GetInstance();
1271   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1272   shelf->LayoutShelf();
1273   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1274
1275   // Create a normal unmaximized windowm shelf should be visible.
1276   aura::Window* window = CreateTestWindow();
1277   window->SetBounds(gfx::Rect(0, 0, 100, 100));
1278   window->Show();
1279   EXPECT_FALSE(shell->GetAppListTargetVisibility());
1280   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1281
1282   // Toggle app list to show, and the shelf stays visible.
1283   shell->ToggleAppList(NULL);
1284   EXPECT_TRUE(shell->GetAppListTargetVisibility());
1285   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1286
1287   // Toggle app list to hide, and the shelf stays visible.
1288   shell->ToggleAppList(NULL);
1289   EXPECT_FALSE(shell->GetAppListTargetVisibility());
1290   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1291 }
1292
1293 // Makes sure shelf will be shown with SHELF_AUTO_HIDE_SHOWN state
1294 // when app list opens as shelf is in SHELF_AUTO_HIDE state, and
1295 // toggling app list won't change shelf visibility state.
1296 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfAutoHideState) {
1297   Shell* shell = Shell::GetInstance();
1298   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1299   shelf->LayoutShelf();
1300   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1301
1302   // Create a window and show it in maximized state.
1303   aura::Window* window = CreateTestWindow();
1304   window->SetBounds(gfx::Rect(0, 0, 100, 100));
1305   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1306   window->Show();
1307   wm::ActivateWindow(window);
1308
1309   EXPECT_FALSE(shell->GetAppListTargetVisibility());
1310   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1311
1312   // Toggle app list to show.
1313   shell->ToggleAppList(NULL);
1314   // The shelf's auto hide state won't be changed until the timer fires, so
1315   // calling shell->UpdateShelfVisibility() is kind of manually helping it to
1316   // update the state.
1317   shell->UpdateShelfVisibility();
1318   EXPECT_TRUE(shell->GetAppListTargetVisibility());
1319   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1320   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1321
1322   // Toggle app list to hide.
1323   shell->ToggleAppList(NULL);
1324   EXPECT_FALSE(shell->GetAppListTargetVisibility());
1325   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1326 }
1327
1328 // Makes sure shelf will be hidden when app list opens as shelf is in HIDDEN
1329 // state, and toggling app list won't change shelf visibility state.
1330 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfHiddenState) {
1331   Shell* shell = Shell::GetInstance();
1332   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1333   // For shelf to be visible, app list is not open in initial state.
1334   shelf->LayoutShelf();
1335
1336   // Create a window and make it full screen.
1337   aura::Window* window = CreateTestWindow();
1338   window->SetBounds(gfx::Rect(0, 0, 100, 100));
1339   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
1340   window->Show();
1341   wm::ActivateWindow(window);
1342
1343   // App list and shelf is not shown.
1344   EXPECT_FALSE(shell->GetAppListTargetVisibility());
1345   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
1346
1347   // Toggle app list to show.
1348   shell->ToggleAppList(NULL);
1349   EXPECT_TRUE(shell->GetAppListTargetVisibility());
1350   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
1351
1352   // Toggle app list to hide.
1353   shell->ToggleAppList(NULL);
1354   EXPECT_FALSE(shell->GetAppListTargetVisibility());
1355   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
1356 }
1357
1358 // Tests that the shelf is only hidden for a fullscreen window at the front and
1359 // toggles visibility when another window is activated.
1360 TEST_F(ShelfLayoutManagerTest, FullscreenWindowInFrontHidesShelf) {
1361   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1362
1363   // Create a window and make it full screen.
1364   aura::Window* window1 = CreateTestWindow();
1365   window1->SetBounds(gfx::Rect(0, 0, 100, 100));
1366   window1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
1367   window1->Show();
1368
1369   aura::Window* window2 = CreateTestWindow();
1370   window2->SetBounds(gfx::Rect(0, 0, 100, 100));
1371   window2->Show();
1372
1373   wm::GetWindowState(window1)->Activate();
1374   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
1375
1376   wm::GetWindowState(window2)->Activate();
1377   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1378
1379   wm::GetWindowState(window1)->Activate();
1380   EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
1381 }
1382
1383 // Test the behavior of the shelf when a window on one display is fullscreen
1384 // but the other display has the active window.
1385 TEST_F(ShelfLayoutManagerTest, FullscreenWindowOnSecondDisplay) {
1386   if (!SupportsMultipleDisplays())
1387     return;
1388
1389   UpdateDisplay("800x600,800x600");
1390   DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1391   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1392   Shell::RootWindowControllerList root_window_controllers =
1393       Shell::GetAllRootWindowControllers();
1394
1395   // Create windows on either display.
1396   aura::Window* window1 = CreateTestWindow();
1397   window1->SetBoundsInScreen(
1398       gfx::Rect(0, 0, 100, 100),
1399       display_manager->GetDisplayAt(0));
1400   window1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
1401   window1->Show();
1402
1403   aura::Window* window2 = CreateTestWindow();
1404   window2->SetBoundsInScreen(
1405       gfx::Rect(800, 0, 100, 100),
1406       display_manager->GetDisplayAt(1));
1407   window2->Show();
1408
1409   EXPECT_EQ(root_windows[0], window1->GetRootWindow());
1410   EXPECT_EQ(root_windows[1], window2->GetRootWindow());
1411
1412   wm::GetWindowState(window2)->Activate();
1413   EXPECT_EQ(SHELF_HIDDEN,
1414       root_window_controllers[0]->GetShelfLayoutManager()->visibility_state());
1415   EXPECT_EQ(SHELF_VISIBLE,
1416       root_window_controllers[1]->GetShelfLayoutManager()->visibility_state());
1417 }
1418
1419
1420 #if defined(OS_WIN)
1421 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
1422 #define MAYBE_SetAlignment DISABLED_SetAlignment
1423 #else
1424 #define MAYBE_SetAlignment SetAlignment
1425 #endif
1426
1427 // Tests SHELF_ALIGNMENT_(LEFT, RIGHT, TOP).
1428 TEST_F(ShelfLayoutManagerTest, MAYBE_SetAlignment) {
1429   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1430   // Force an initial layout.
1431   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1432   shelf->LayoutShelf();
1433   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1434
1435   shelf->SetAlignment(SHELF_ALIGNMENT_LEFT);
1436   gfx::Rect shelf_bounds(
1437       GetShelfWidget()->GetWindowBoundsInScreen());
1438   const gfx::Screen* screen = Shell::GetScreen();
1439   gfx::Display display =
1440       screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1441   ASSERT_NE(-1, display.id());
1442   EXPECT_EQ(shelf->GetIdealBounds().width(),
1443             display.GetWorkAreaInsets().left());
1444   EXPECT_GE(
1445       shelf_bounds.width(),
1446       GetShelfWidget()->GetContentsView()->GetPreferredSize().width());
1447   EXPECT_EQ(SHELF_ALIGNMENT_LEFT, GetSystemTray()->shelf_alignment());
1448   StatusAreaWidget* status_area_widget = GetShelfWidget()->status_area_widget();
1449   gfx::Rect status_bounds(status_area_widget->GetWindowBoundsInScreen());
1450   EXPECT_GE(status_bounds.width(),
1451             status_area_widget->GetContentsView()->GetPreferredSize().width());
1452   EXPECT_EQ(shelf->GetIdealBounds().width(),
1453             display.GetWorkAreaInsets().left());
1454   EXPECT_EQ(0, display.GetWorkAreaInsets().top());
1455   EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
1456   EXPECT_EQ(0, display.GetWorkAreaInsets().right());
1457   EXPECT_EQ(display.bounds().x(), shelf_bounds.x());
1458   EXPECT_EQ(display.bounds().y(), shelf_bounds.y());
1459   EXPECT_EQ(display.bounds().height(), shelf_bounds.height());
1460   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1461   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1462   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
1463       display.GetWorkAreaInsets().left());
1464   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize, display.work_area().x());
1465
1466   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1467   shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
1468   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1469   shelf_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
1470   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1471   ASSERT_NE(-1, display.id());
1472   EXPECT_EQ(shelf->GetIdealBounds().width(),
1473             display.GetWorkAreaInsets().right());
1474   EXPECT_GE(shelf_bounds.width(),
1475             GetShelfWidget()->GetContentsView()->GetPreferredSize().width());
1476   EXPECT_EQ(SHELF_ALIGNMENT_RIGHT, GetSystemTray()->shelf_alignment());
1477   status_bounds = gfx::Rect(status_area_widget->GetWindowBoundsInScreen());
1478   EXPECT_GE(status_bounds.width(),
1479             status_area_widget->GetContentsView()->GetPreferredSize().width());
1480   EXPECT_EQ(shelf->GetIdealBounds().width(),
1481             display.GetWorkAreaInsets().right());
1482   EXPECT_EQ(0, display.GetWorkAreaInsets().top());
1483   EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
1484   EXPECT_EQ(0, display.GetWorkAreaInsets().left());
1485   EXPECT_EQ(display.work_area().right(), shelf_bounds.x());
1486   EXPECT_EQ(display.bounds().y(), shelf_bounds.y());
1487   EXPECT_EQ(display.bounds().height(), shelf_bounds.height());
1488   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1489   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1490   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
1491       display.GetWorkAreaInsets().right());
1492   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
1493       display.bounds().right() - display.work_area().right());
1494
1495   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1496   shelf->SetAlignment(SHELF_ALIGNMENT_TOP);
1497   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1498   shelf_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
1499   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1500   ASSERT_NE(-1, display.id());
1501   EXPECT_EQ(shelf->GetIdealBounds().height(),
1502             display.GetWorkAreaInsets().top());
1503   EXPECT_GE(shelf_bounds.height(),
1504             GetShelfWidget()->GetContentsView()->GetPreferredSize().height());
1505   EXPECT_EQ(SHELF_ALIGNMENT_TOP, GetSystemTray()->shelf_alignment());
1506   status_bounds = gfx::Rect(status_area_widget->GetWindowBoundsInScreen());
1507   EXPECT_GE(status_bounds.height(),
1508             status_area_widget->GetContentsView()->GetPreferredSize().height());
1509   EXPECT_EQ(shelf->GetIdealBounds().height(),
1510             display.GetWorkAreaInsets().top());
1511   EXPECT_EQ(0, display.GetWorkAreaInsets().right());
1512   EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
1513   EXPECT_EQ(0, display.GetWorkAreaInsets().left());
1514   EXPECT_EQ(display.work_area().y(), shelf_bounds.bottom());
1515   EXPECT_EQ(display.bounds().x(), shelf_bounds.x());
1516   EXPECT_EQ(display.bounds().width(), shelf_bounds.width());
1517   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1518   display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1519   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
1520       display.GetWorkAreaInsets().top());
1521   EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
1522             display.work_area().y() - display.bounds().y());
1523 }
1524
1525 TEST_F(ShelfLayoutManagerTest, GestureEdgeSwipe) {
1526   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1527   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1528   views::Widget* widget = new views::Widget;
1529   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1530   params.bounds = gfx::Rect(0, 0, 200, 200);
1531   params.context = CurrentContext();
1532   widget->Init(params);
1533   widget->Show();
1534   widget->Maximize();
1535
1536   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1537
1538   aura::Window* window = widget->GetNativeWindow();
1539   shelf->LayoutShelf();
1540
1541   gfx::Rect shelf_shown = GetShelfWidget()->GetWindowBoundsInScreen();
1542   gfx::Rect bounds_shelf = window->bounds();
1543
1544   // Edge swipe when SHELF_VISIBLE should not change visibility state.
1545   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1546   generator.GestureEdgeSwipe();
1547   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1548
1549   // Edge swipe when AUTO_HIDE_HIDDEN should change to AUTO_HIDE_SHOWN.
1550   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1551   shelf->LayoutShelf();
1552   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1553   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1554   generator.GestureEdgeSwipe();
1555   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1556   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1557
1558   widget->SetFullscreen(true);
1559   wm::GetWindowState(window)->set_hide_shelf_when_fullscreen(false);
1560   shelf->UpdateVisibilityState();
1561
1562   // Edge swipe in fullscreen + AUTO_HIDE_HIDDEN should show the shelf and
1563   // remain fullscreen.
1564   EXPECT_TRUE(widget->IsFullscreen());
1565   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1566   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1567   generator.GestureEdgeSwipe();
1568   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1569   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1570   EXPECT_TRUE(widget->IsFullscreen());
1571 }
1572
1573 // Test that starting the maximize mode does still allow the shelf to be made
1574 // visible when an (immersive mode) full screen app is running.
1575 TEST_F(ShelfLayoutManagerTest, GestureEdgeSwipeInMaximizeMode) {
1576   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1577   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1578   views::Widget* widget = new views::Widget;
1579   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1580   params.bounds = gfx::Rect(0, 0, 200, 200);
1581   params.context = CurrentContext();
1582   widget->Init(params);
1583   widget->Show();
1584   aura::Window* window = widget->GetNativeWindow();
1585   wm::GetWindowState(window)->set_hide_shelf_when_fullscreen(false);
1586   widget->SetFullscreen(true);
1587
1588   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1589
1590   // The maximize mode gets started.
1591   shelf->OnMaximizeModeStarted();
1592   shelf->LayoutShelf();
1593   shelf->UpdateVisibilityState();
1594
1595   // Edge swipe in fullscreen + AUTO_HIDE_HIDDEN should show the shelf and
1596   // remain fullscreen.
1597   EXPECT_TRUE(widget->IsFullscreen());
1598   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1599   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1600   generator.GestureEdgeSwipe();
1601   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1602   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1603   EXPECT_TRUE(widget->IsFullscreen());
1604 }
1605
1606 // Check that in maximize mode gesture swipes on the shelf have no effect.
1607 TEST_F(ShelfLayoutManagerTest, MaximizeModeGestureEdgeSwipe) {
1608   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1609   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1610   views::Widget* widget = new views::Widget;
1611   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1612   params.bounds = gfx::Rect(0, 0, 200, 200);
1613   params.context = CurrentContext();
1614   widget->Init(params);
1615   widget->Show();
1616   widget->Maximize();
1617
1618   shelf->LayoutShelf();
1619
1620   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1621   shelf->LayoutShelf();
1622   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1623
1624   shelf->OnMaximizeModeStarted();
1625   shelf->LayoutShelf();
1626   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1627
1628   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1629   generator.GestureEdgeSwipe();
1630
1631   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1632 }
1633
1634 #if defined(OS_WIN)
1635 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
1636 #define MAYBE_GestureDrag DISABLED_GestureDrag
1637 #else
1638 #define MAYBE_GestureDrag GestureDrag
1639 #endif
1640
1641 TEST_F(ShelfLayoutManagerTest, MAYBE_GestureDrag) {
1642   // Slop is an implementation detail of gesture recognition, and complicates
1643   // these tests. Ignore it.
1644   ui::GestureConfiguration::set_max_touch_move_in_pixels_for_click(0);
1645   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1646   {
1647     SCOPED_TRACE("BOTTOM");
1648     RunGestureDragTests(gfx::Vector2d(0, 120));
1649   }
1650
1651   {
1652     SCOPED_TRACE("LEFT");
1653     shelf->SetAlignment(SHELF_ALIGNMENT_LEFT);
1654     RunGestureDragTests(gfx::Vector2d(-120, 0));
1655   }
1656
1657   {
1658     SCOPED_TRACE("RIGHT");
1659     shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
1660     RunGestureDragTests(gfx::Vector2d(120, 0));
1661   }
1662 }
1663
1664 TEST_F(ShelfLayoutManagerTest, WindowVisibilityDisablesAutoHide) {
1665   if (!SupportsMultipleDisplays())
1666     return;
1667
1668   UpdateDisplay("800x600,800x600");
1669   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1670   shelf->LayoutShelf();
1671   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1672
1673   // Create a visible window so auto-hide behavior is enforced
1674   views::Widget* dummy = CreateTestWidget();
1675
1676   // Window visible => auto hide behaves normally.
1677   shelf->UpdateVisibilityState();
1678   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1679
1680   // Window minimized => auto hide disabled.
1681   dummy->Minimize();
1682   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1683
1684   // Window closed => auto hide disabled.
1685   dummy->CloseNow();
1686   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1687
1688   // Multiple window test
1689   views::Widget* window1 = CreateTestWidget();
1690   views::Widget* window2 = CreateTestWidget();
1691
1692   // both visible => normal autohide
1693   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1694
1695   // either minimzed => normal autohide
1696   window2->Minimize();
1697   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1698   window2->Restore();
1699   window1->Minimize();
1700   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1701
1702   // both minimized => disable auto hide
1703   window2->Minimize();
1704   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1705
1706   // Test moving windows to/from other display.
1707   window2->Restore();
1708   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1709   // Move to second display.
1710   window2->SetBounds(gfx::Rect(850, 50, 50, 50));
1711   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1712   // Move back to primary display.
1713   window2->SetBounds(gfx::Rect(50, 50, 50, 50));
1714   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1715 }
1716
1717 // Test that the shelf animates back to its normal position upon a user
1718 // completing a gesture drag.
1719 TEST_F(ShelfLayoutManagerTest, ShelfAnimatesWhenGestureComplete) {
1720   if (!SupportsHostWindowResize())
1721     return;
1722
1723   // Test the shelf animates back to its original visible bounds when it is
1724   // dragged when there are no visible windows.
1725   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1726   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1727   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1728   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1729   gfx::Rect visible_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
1730   {
1731     // Enable animations so that we can make sure that they occur.
1732     ui::ScopedAnimationDurationScaleMode regular_animations(
1733         ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
1734
1735     aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1736     gfx::Rect shelf_bounds_in_screen =
1737         GetShelfWidget()->GetWindowBoundsInScreen();
1738     gfx::Point start(shelf_bounds_in_screen.CenterPoint());
1739     gfx::Point end(start.x(), shelf_bounds_in_screen.bottom());
1740     generator.GestureScrollSequence(start, end,
1741         base::TimeDelta::FromMilliseconds(10), 5);
1742     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1743     EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1744
1745     ShelfAnimationWaiter waiter(visible_bounds);
1746     // Wait till the animation completes and check that it occurred.
1747     waiter.WaitTillDoneAnimating();
1748     EXPECT_TRUE(waiter.WasValidAnimation());
1749   }
1750
1751   // Create a visible window so auto-hide behavior is enforced.
1752   CreateTestWidget();
1753
1754   // Get the bounds of the shelf when it is hidden.
1755   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1756   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1757   gfx::Rect auto_hidden_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
1758
1759   {
1760     // Enable the animations so that we can make sure they do occur.
1761     ui::ScopedAnimationDurationScaleMode regular_animations(
1762         ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
1763
1764     gfx::Point start =
1765         GetShelfWidget()->GetWindowBoundsInScreen().CenterPoint();
1766     gfx::Point end(start.x(), start.y() - 100);
1767     aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1768
1769     // Test that the shelf animates to the visible bounds after a swipe up on
1770     // the auto hidden shelf.
1771     generator.GestureScrollSequence(start, end,
1772         base::TimeDelta::FromMilliseconds(10), 1);
1773     EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1774     ShelfAnimationWaiter waiter1(visible_bounds);
1775     waiter1.WaitTillDoneAnimating();
1776     EXPECT_TRUE(waiter1.WasValidAnimation());
1777
1778     // Test that the shelf animates to the auto hidden bounds after a swipe up
1779     // on the visible shelf.
1780     EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1781     generator.GestureScrollSequence(start, end,
1782         base::TimeDelta::FromMilliseconds(10), 1);
1783     EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1784     EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1785     ShelfAnimationWaiter waiter2(auto_hidden_bounds);
1786     waiter2.WaitTillDoneAnimating();
1787     EXPECT_TRUE(waiter2.WasValidAnimation());
1788   }
1789 }
1790
1791 TEST_F(ShelfLayoutManagerTest, GestureRevealsTrayBubble) {
1792   if (!SupportsHostWindowResize())
1793     return;
1794
1795   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1796   shelf->LayoutShelf();
1797
1798   // Create a visible window so auto-hide behavior is enforced.
1799   CreateTestWidget();
1800
1801   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1802   SystemTray* tray = GetSystemTray();
1803
1804   // First, make sure the shelf is visible.
1805   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1806   EXPECT_FALSE(tray->HasSystemBubble());
1807
1808   // Now, drag up on the tray to show the bubble.
1809   gfx::Point start = GetShelfWidget()->status_area_widget()->
1810       GetWindowBoundsInScreen().CenterPoint();
1811   gfx::Point end(start.x(), start.y() - 100);
1812   generator.GestureScrollSequence(start, end,
1813       base::TimeDelta::FromMilliseconds(10), 1);
1814   EXPECT_TRUE(tray->HasSystemBubble());
1815   tray->CloseSystemBubble();
1816   RunAllPendingInMessageLoop();
1817   EXPECT_FALSE(tray->HasSystemBubble());
1818
1819   // Drag again, but only a small amount, and slowly. The bubble should not be
1820   // visible.
1821   end.set_y(start.y() - 30);
1822   generator.GestureScrollSequence(start, end,
1823       base::TimeDelta::FromMilliseconds(500), 100);
1824   EXPECT_FALSE(tray->HasSystemBubble());
1825
1826   // Now, hide the shelf.
1827   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1828
1829   // Start a drag from the bezel, and drag up to show both the shelf and the
1830   // tray bubble.
1831   start.set_y(start.y() + 100);
1832   end.set_y(start.y() - 400);
1833   generator.GestureScrollSequence(start, end,
1834       base::TimeDelta::FromMilliseconds(10), 1);
1835   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1836   EXPECT_TRUE(tray->HasSystemBubble());
1837 }
1838
1839 TEST_F(ShelfLayoutManagerTest, ShelfFlickerOnTrayActivation) {
1840   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1841
1842   // Create a visible window so auto-hide behavior is enforced.
1843   CreateTestWidget();
1844
1845   // Turn on auto-hide for the shelf.
1846   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1847   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1848   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1849
1850   // Show the status menu. That should make the shelf visible again.
1851   Shell::GetInstance()->accelerator_controller()->PerformAction(
1852       SHOW_SYSTEM_TRAY_BUBBLE, ui::Accelerator());
1853   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1854   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1855   EXPECT_TRUE(GetSystemTray()->HasSystemBubble());
1856 }
1857
1858 TEST_F(ShelfLayoutManagerTest, WorkAreaChangeWorkspace) {
1859   // Make sure the shelf is always visible.
1860   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1861   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1862   shelf->LayoutShelf();
1863
1864   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1865   params.bounds = gfx::Rect(0, 0, 200, 200);
1866   params.context = CurrentContext();
1867   views::Widget* widget_one = CreateTestWidgetWithParams(params);
1868   widget_one->Maximize();
1869
1870   views::Widget* widget_two = CreateTestWidgetWithParams(params);
1871   widget_two->Maximize();
1872   widget_two->Activate();
1873
1874   // Both windows are maximized. They should be of the same size.
1875   EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
1876             widget_two->GetNativeWindow()->bounds().ToString());
1877   int area_when_shelf_shown =
1878       widget_one->GetNativeWindow()->bounds().size().GetArea();
1879
1880   // Now hide the shelf.
1881   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1882
1883   // Both windows should be resized according to the shelf status.
1884   EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
1885             widget_two->GetNativeWindow()->bounds().ToString());
1886   // Resized to small.
1887   EXPECT_LT(area_when_shelf_shown,
1888             widget_one->GetNativeWindow()->bounds().size().GetArea());
1889
1890   // Now show the shelf.
1891   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1892
1893   // Again both windows should be of the same size.
1894   EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
1895             widget_two->GetNativeWindow()->bounds().ToString());
1896   EXPECT_EQ(area_when_shelf_shown,
1897             widget_one->GetNativeWindow()->bounds().size().GetArea());
1898 }
1899
1900 // Confirm that the shelf is dimmed only when content is maximized and
1901 // shelf is not autohidden.
1902 TEST_F(ShelfLayoutManagerTest, Dimming) {
1903   GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1904   scoped_ptr<aura::Window> w1(CreateTestWindow());
1905   w1->Show();
1906   wm::ActivateWindow(w1.get());
1907
1908   // Normal window doesn't dim shelf.
1909   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
1910   ShelfWidget* shelf = GetShelfWidget();
1911   EXPECT_FALSE(shelf->GetDimsShelf());
1912
1913   // Maximized window does.
1914   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1915   EXPECT_TRUE(shelf->GetDimsShelf());
1916
1917   // Change back to normal stops dimming.
1918   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
1919   EXPECT_FALSE(shelf->GetDimsShelf());
1920
1921   // Changing back to maximized dims again.
1922   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1923   EXPECT_TRUE(shelf->GetDimsShelf());
1924
1925   // Changing shelf to autohide stops dimming.
1926   GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1927   EXPECT_FALSE(shelf->GetDimsShelf());
1928 }
1929
1930 // Make sure that the shelf will not hide if the mouse is between a bubble and
1931 // the shelf.
1932 TEST_F(ShelfLayoutManagerTest, BubbleEnlargesShelfMouseHitArea) {
1933   ShelfLayoutManager* shelf = GetShelfLayoutManager();
1934   StatusAreaWidget* status_area_widget =
1935       Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget();
1936   SystemTray* tray = GetSystemTray();
1937
1938   // Create a visible window so auto-hide behavior is enforced.
1939   CreateTestWidget();
1940
1941   shelf->LayoutShelf();
1942   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1943
1944   // Make two iterations - first without a message bubble which should make
1945   // the shelf disappear and then with a message bubble which should keep it
1946   // visible.
1947   for (int i = 0; i < 2; i++) {
1948     // Make sure the shelf is visible and position the mouse over it. Then
1949     // allow auto hide.
1950     shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1951     EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
1952     gfx::Point center =
1953         status_area_widget->GetWindowBoundsInScreen().CenterPoint();
1954     generator.MoveMouseTo(center.x(), center.y());
1955     shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1956     EXPECT_TRUE(shelf->IsVisible());
1957     if (!i) {
1958       // In our first iteration we make sure there is no bubble.
1959       tray->CloseSystemBubble();
1960       EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
1961     } else {
1962       // In our second iteration we show a bubble.
1963       TestItem *item = new TestItem;
1964       tray->AddTrayItem(item);
1965       tray->ShowNotificationView(item);
1966       EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
1967     }
1968     // Move the pointer over the edge of the shelf.
1969     generator.MoveMouseTo(
1970         center.x(), status_area_widget->GetWindowBoundsInScreen().y() - 8);
1971     shelf->UpdateVisibilityState();
1972     if (i) {
1973       EXPECT_TRUE(shelf->IsVisible());
1974       EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
1975     } else {
1976       EXPECT_FALSE(shelf->IsVisible());
1977       EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
1978     }
1979   }
1980 }
1981
1982 TEST_F(ShelfLayoutManagerTest, ShelfBackgroundColor) {
1983   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
1984
1985   scoped_ptr<aura::Window> w1(CreateTestWindow());
1986   w1->Show();
1987   wm::ActivateWindow(w1.get());
1988   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
1989   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1990   EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
1991
1992   scoped_ptr<aura::Window> w2(CreateTestWindow());
1993   w2->Show();
1994   wm::ActivateWindow(w2.get());
1995   // Overlaps with shelf.
1996   w2->SetBounds(GetShelfLayoutManager()->GetIdealBounds());
1997
1998   // Still background is 'maximized'.
1999   EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
2000
2001   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
2002   EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
2003   w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
2004   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
2005
2006   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
2007   EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
2008   w1.reset();
2009   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
2010 }
2011
2012 // Verify that the shelf doesn't have the opaque background if it's auto-hide
2013 // status.
2014 TEST_F(ShelfLayoutManagerTest, ShelfBackgroundColorAutoHide) {
2015   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget ()->GetBackgroundType());
2016
2017   GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
2018   scoped_ptr<aura::Window> w1(CreateTestWindow());
2019   w1->Show();
2020   wm::ActivateWindow(w1.get());
2021   EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
2022   w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
2023   EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
2024 }
2025
2026 // Verify that setting the shelf's auto hide mode in maximize mode does not
2027 // hide.
2028 TEST_F(ShelfLayoutManagerTest, DoesNotHideInMaximizeMode) {
2029   EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
2030
2031   GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
2032   scoped_ptr<aura::Window> w1(CreateTestWindow());
2033   w1->Show();
2034   ShelfLayoutManager* shelf = GetShelfLayoutManager();
2035
2036   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
2037   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
2038   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
2039
2040   GetShelfLayoutManager()->OnMaximizeModeStarted();
2041   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
2042   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
2043
2044   // Setting the state again should have no impact.
2045   GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
2046   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
2047   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
2048
2049   GetShelfLayoutManager()->OnMaximizeModeEnded();
2050   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
2051   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
2052 }
2053
2054 #if defined(OS_CHROMEOS)
2055 #define MAYBE_StatusAreaHitBoxCoversEdge StatusAreaHitBoxCoversEdge
2056 #else
2057 #define MAYBE_StatusAreaHitBoxCoversEdge DISABLED_StatusAreaHitBoxCoversEdge
2058 #endif
2059
2060 // Verify the hit bounds of the status area extend to the edge of the shelf.
2061 TEST_F(ShelfLayoutManagerTest, MAYBE_StatusAreaHitBoxCoversEdge) {
2062   UpdateDisplay("400x400");
2063   ShelfLayoutManager* shelf = GetShelfLayoutManager();
2064   StatusAreaWidget* status_area_widget =
2065       Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget();
2066   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
2067   generator.MoveMouseTo(399,399);
2068
2069   // Test bottom right pixel for bottom alignment.
2070   EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2071   generator.ClickLeftButton();
2072   EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
2073   generator.ClickLeftButton();
2074   EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2075
2076   // Test bottom right pixel for right alignment.
2077   shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
2078   EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2079   generator.ClickLeftButton();
2080   EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
2081   generator.ClickLeftButton();
2082   EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2083
2084   // Test bottom left pixel for left alignment.
2085   generator.MoveMouseTo(0, 399);
2086   shelf->SetAlignment(SHELF_ALIGNMENT_LEFT);
2087   EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2088   generator.ClickLeftButton();
2089   EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
2090   generator.ClickLeftButton();
2091   EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2092 }
2093
2094 }  // namespace ash