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