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