Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / ash / shelf / shelf_layout_manager_unittest.cc
blob968be66f25f081c33887ecdf39963919bd965039
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/shelf/shelf_layout_manager.h"
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_controller.h"
11 #include "ash/display/display_manager.h"
12 #include "ash/focus_cycler.h"
13 #include "ash/root_window_controller.h"
14 #include "ash/session/session_state_delegate.h"
15 #include "ash/shelf/shelf.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/shelf_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/client/window_tree_client.h"
32 #include "ui/aura/window.h"
33 #include "ui/aura/window_event_dispatcher.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/events/gesture_detection/gesture_configuration.h"
38 #include "ui/events/test/event_generator.h"
39 #include "ui/gfx/display.h"
40 #include "ui/gfx/screen.h"
41 #include "ui/views/controls/label.h"
42 #include "ui/views/layout/fill_layout.h"
43 #include "ui/views/view.h"
44 #include "ui/views/widget/widget.h"
46 #if defined(OS_WIN)
47 #include "base/win/windows_version.h"
48 #endif
50 namespace ash {
51 namespace {
53 void StepWidgetLayerAnimatorToEnd(views::Widget* widget) {
54 widget->GetNativeView()->layer()->GetAnimator()->Step(
55 base::TimeTicks::Now() + base::TimeDelta::FromSeconds(1));
58 ShelfWidget* GetShelfWidget() {
59 return Shell::GetPrimaryRootWindowController()->shelf();
62 ShelfLayoutManager* GetShelfLayoutManager() {
63 return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
66 SystemTray* GetSystemTray() {
67 return Shell::GetPrimaryRootWindowController()->GetSystemTray();
70 // Class which waits till the shelf finishes animating to the target size and
71 // counts the number of animation steps.
72 class ShelfAnimationWaiter : views::WidgetObserver {
73 public:
74 explicit ShelfAnimationWaiter(const gfx::Rect& target_bounds)
75 : target_bounds_(target_bounds),
76 animation_steps_(0),
77 done_waiting_(false) {
78 GetShelfWidget()->AddObserver(this);
81 ~ShelfAnimationWaiter() override { GetShelfWidget()->RemoveObserver(this); }
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();
91 // Returns true if the animation has completed and it was valid.
92 bool WasValidAnimation() const {
93 return done_waiting_ && animation_steps_ > 0;
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);
108 // views::WidgetObserver override.
109 void OnWidgetBoundsChanged(views::Widget* widget,
110 const gfx::Rect& new_bounds) override {
111 if (done_waiting_)
112 return;
114 ++animation_steps_;
115 if (IsDoneAnimating()) {
116 done_waiting_ = true;
117 base::MessageLoop::current()->Quit();
121 gfx::Rect target_bounds_;
122 int animation_steps_;
123 bool done_waiting_;
125 DISALLOW_COPY_AND_ASSIGN(ShelfAnimationWaiter);
128 class 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());
137 virtual ~ShelfDragCallback() {
140 void ProcessScroll(ui::EventType type, const gfx::Vector2dF& delta) {
141 if (GetShelfLayoutManager()->visibility_state() == ash::SHELF_HIDDEN)
142 return;
144 if (type == ui::ET_GESTURE_SCROLL_BEGIN) {
145 scroll_ = gfx::Vector2dF();
146 was_visible_on_drag_start_ = GetShelfLayoutManager()->IsVisible();
147 return;
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;
154 if (type == ui::ET_GESTURE_SCROLL_UPDATE)
155 scroll_.Add(delta);
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());
171 // if the shelf is being dimmed test dimmer bounds as well.
172 if (GetShelfWidget()->GetDimsShelf())
173 EXPECT_EQ(GetShelfWidget()->GetWindowBoundsInScreen(),
174 GetShelfWidget()->GetDimmerBoundsForTest());
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));
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));
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_;
230 DISALLOW_COPY_AND_ASSIGN(ShelfDragCallback);
233 class ShelfLayoutObserverTest : public ShelfLayoutManagerObserver {
234 public:
235 ShelfLayoutObserverTest()
236 : changed_auto_hide_state_(false) {
239 ~ShelfLayoutObserverTest() override {}
241 bool changed_auto_hide_state() const { return changed_auto_hide_state_; }
243 private:
244 void OnAutoHideStateChanged(ShelfAutoHideState new_state) override {
245 changed_auto_hide_state_ = true;
248 bool changed_auto_hide_state_;
250 DISALLOW_COPY_AND_ASSIGN(ShelfLayoutObserverTest);
253 // Trivial item implementation that tracks its views for testing.
254 class TestItem : public SystemTrayItem {
255 public:
256 TestItem()
257 : SystemTrayItem(GetSystemTray()),
258 tray_view_(NULL),
259 default_view_(NULL),
260 detailed_view_(NULL),
261 notification_view_(NULL) {}
263 views::View* CreateTrayView(user::LoginStatus status) override {
264 tray_view_ = new views::View;
265 // Add a label so it has non-zero width.
266 tray_view_->SetLayoutManager(new views::FillLayout);
267 tray_view_->AddChildView(new views::Label(base::UTF8ToUTF16("Tray")));
268 return tray_view_;
271 views::View* CreateDefaultView(user::LoginStatus status) override {
272 default_view_ = new views::View;
273 default_view_->SetLayoutManager(new views::FillLayout);
274 default_view_->AddChildView(new views::Label(base::UTF8ToUTF16("Default")));
275 return default_view_;
278 views::View* CreateDetailedView(user::LoginStatus status) override {
279 detailed_view_ = new views::View;
280 detailed_view_->SetLayoutManager(new views::FillLayout);
281 detailed_view_->AddChildView(
282 new views::Label(base::UTF8ToUTF16("Detailed")));
283 return detailed_view_;
286 views::View* CreateNotificationView(user::LoginStatus status) override {
287 notification_view_ = new views::View;
288 return notification_view_;
291 void DestroyTrayView() override { tray_view_ = NULL; }
293 void DestroyDefaultView() override { default_view_ = NULL; }
295 void DestroyDetailedView() override { detailed_view_ = NULL; }
297 void DestroyNotificationView() override { notification_view_ = NULL; }
299 void UpdateAfterLoginStatusChange(user::LoginStatus status) override {}
301 views::View* tray_view() const { return tray_view_; }
302 views::View* default_view() const { return default_view_; }
303 views::View* detailed_view() const { return detailed_view_; }
304 views::View* notification_view() const { return notification_view_; }
306 private:
307 views::View* tray_view_;
308 views::View* default_view_;
309 views::View* detailed_view_;
310 views::View* notification_view_;
312 DISALLOW_COPY_AND_ASSIGN(TestItem);
315 } // namespace
317 class ShelfLayoutManagerTest : public ash::test::AshTestBase {
318 public:
319 ShelfLayoutManagerTest() {}
321 void SetState(ShelfLayoutManager* shelf,
322 ShelfVisibilityState state) {
323 shelf->SetState(state);
326 void UpdateAutoHideStateNow() {
327 GetShelfLayoutManager()->UpdateAutoHideStateNow();
330 aura::Window* CreateTestWindow() {
331 aura::Window* window = new aura::Window(NULL);
332 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
333 window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
334 window->Init(ui::LAYER_TEXTURED);
335 ParentWindowInPrimaryRootWindow(window);
336 return window;
339 aura::Window* CreateTestWindowInParent(aura::Window* root_window) {
340 aura::Window* window = new aura::Window(NULL);
341 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
342 window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
343 window->Init(ui::LAYER_TEXTURED);
344 aura::client::ParentWindowWithContext(window, root_window, gfx::Rect());
345 return window;
348 views::Widget* CreateTestWidgetWithParams(
349 const views::Widget::InitParams& params) {
350 views::Widget* out = new views::Widget;
351 out->Init(params);
352 out->Show();
353 return out;
356 // Create a simple widget attached to the current context (will
357 // delete on TearDown).
358 views::Widget* CreateTestWidget() {
359 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
360 params.bounds = gfx::Rect(0, 0, 200, 200);
361 params.context = CurrentContext();
362 return CreateTestWidgetWithParams(params);
365 void RunGestureDragTests(gfx::Vector2d);
367 // Turn on the lock screen.
368 void LockScreen() {
369 Shell::GetInstance()->session_state_delegate()->LockScreen();
370 // The test session state delegate does not fire the lock state change.
371 Shell::GetInstance()->OnLockStateChanged(true);
374 // Turn off the lock screen.
375 void UnlockScreen() {
376 Shell::GetInstance()->session_state_delegate()->UnlockScreen();
377 // The test session state delegate does not fire the lock state change.
378 Shell::GetInstance()->OnLockStateChanged(false);
381 // Open the add user screen if |show| is true, otherwise end it.
382 void ShowAddUserScreen(bool show) {
383 SetUserAddingScreenRunning(show);
384 ShelfLayoutManager* manager = GetShelfWidget()->shelf_layout_manager();
385 manager->SessionStateChanged(
386 show ? SessionStateDelegate::SESSION_STATE_LOGIN_SECONDARY :
387 SessionStateDelegate::SESSION_STATE_ACTIVE);
390 private:
391 DISALLOW_COPY_AND_ASSIGN(ShelfLayoutManagerTest);
394 void ShelfLayoutManagerTest::RunGestureDragTests(gfx::Vector2d delta) {
395 ShelfLayoutManager* shelf = GetShelfLayoutManager();
396 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
397 views::Widget* widget = new views::Widget;
398 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
399 params.bounds = gfx::Rect(0, 0, 200, 200);
400 params.context = CurrentContext();
401 widget->Init(params);
402 widget->Show();
403 widget->Maximize();
405 // The time delta should be large enough to prevent accidental fling creation.
406 const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
408 aura::Window* window = widget->GetNativeWindow();
409 shelf->LayoutShelf();
411 gfx::Rect shelf_shown = GetShelfWidget()->GetWindowBoundsInScreen();
412 gfx::Rect bounds_shelf = window->bounds();
413 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
415 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
416 shelf->LayoutShelf();
417 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
419 gfx::Rect bounds_noshelf = window->bounds();
420 gfx::Rect shelf_hidden = GetShelfWidget()->GetWindowBoundsInScreen();
422 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
423 shelf->LayoutShelf();
425 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
426 const int kNumScrollSteps = 4;
427 ShelfDragCallback handler(shelf_hidden, shelf_shown);
429 // Swipe up on the shelf. This should not change any state.
430 gfx::Point start = GetShelfWidget()->GetWindowBoundsInScreen().CenterPoint();
431 gfx::Point end = start + delta;
433 // Swipe down on the shelf to hide it.
434 generator.GestureScrollSequenceWithCallback(
435 start,
436 end,
437 kTimeDelta,
438 kNumScrollSteps,
439 base::Bind(&ShelfDragCallback::ProcessScroll,
440 base::Unretained(&handler)));
441 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
442 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
443 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
444 EXPECT_NE(bounds_shelf.ToString(), window->bounds().ToString());
445 EXPECT_NE(shelf_shown.ToString(),
446 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
448 // Swipe up to show the shelf.
449 generator.GestureScrollSequenceWithCallback(
450 end,
451 start,
452 kTimeDelta,
453 kNumScrollSteps,
454 base::Bind(&ShelfDragCallback::ProcessScroll,
455 base::Unretained(&handler)));
456 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
457 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
458 EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
459 EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
460 GetShelfWidget()->GetWindowBoundsInScreen());
461 EXPECT_EQ(shelf_shown.ToString(),
462 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
464 // Swipe up again. The shelf should hide.
465 end = start - delta;
466 generator.GestureScrollSequenceWithCallback(
467 start,
468 end,
469 kTimeDelta,
470 kNumScrollSteps,
471 base::Bind(&ShelfDragCallback::ProcessScroll,
472 base::Unretained(&handler)));
473 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
474 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
475 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
476 EXPECT_EQ(shelf_hidden.ToString(),
477 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
479 // Swipe up yet again to show it.
480 end = start + delta;
481 generator.GestureScrollSequenceWithCallback(
482 end,
483 start,
484 kTimeDelta,
485 kNumScrollSteps,
486 base::Bind(&ShelfDragCallback::ProcessScroll,
487 base::Unretained(&handler)));
489 // Swipe down very little. It shouldn't change any state.
490 if (GetShelfLayoutManager()->IsHorizontalAlignment())
491 end.set_y(start.y() + shelf_shown.height() * 3 / 10);
492 else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
493 end.set_x(start.x() - shelf_shown.width() * 3 / 10);
494 else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
495 end.set_x(start.x() + shelf_shown.width() * 3 / 10);
496 generator.GestureScrollSequence(start, end, kTimeDelta, 5);
497 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
498 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
499 EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
500 EXPECT_EQ(shelf_shown.ToString(),
501 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
503 // Swipe down again to hide.
504 end = start + delta;
505 generator.GestureScrollSequenceWithCallback(
506 start,
507 end,
508 kTimeDelta,
509 kNumScrollSteps,
510 base::Bind(&ShelfDragCallback::ProcessScroll,
511 base::Unretained(&handler)));
512 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
513 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
514 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
515 EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
516 EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
517 EXPECT_EQ(shelf_hidden.ToString(),
518 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
520 // Swipe up in extended hit region to show it.
521 gfx::Point extended_start = start;
522 if (GetShelfLayoutManager()->IsHorizontalAlignment())
523 extended_start.set_y(GetShelfWidget()->GetWindowBoundsInScreen().y() -1);
524 else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
525 extended_start.set_x(
526 GetShelfWidget()->GetWindowBoundsInScreen().right() + 1);
527 else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
528 extended_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().x() - 1);
529 end = extended_start - delta;
530 generator.GestureScrollSequenceWithCallback(
531 extended_start,
532 end,
533 kTimeDelta,
534 kNumScrollSteps,
535 base::Bind(&ShelfDragCallback::ProcessScroll,
536 base::Unretained(&handler)));
537 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
538 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
539 EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
540 EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
541 GetShelfWidget()->GetWindowBoundsInScreen());
542 EXPECT_EQ(shelf_shown.ToString(),
543 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
545 // Swipe down again to hide.
546 end = start + delta;
547 generator.GestureScrollSequenceWithCallback(
548 start,
549 end,
550 kTimeDelta,
551 kNumScrollSteps,
552 base::Bind(&ShelfDragCallback::ProcessScroll,
553 base::Unretained(&handler)));
554 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
555 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
556 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
557 EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
558 EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
559 EXPECT_EQ(shelf_hidden.ToString(),
560 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
562 // Swipe up outside the hit area. This should not change anything.
563 gfx::Point outside_start = gfx::Point(
564 (GetShelfWidget()->GetWindowBoundsInScreen().x() +
565 GetShelfWidget()->GetWindowBoundsInScreen().right())/2,
566 GetShelfWidget()->GetWindowBoundsInScreen().y() - 50);
567 end = outside_start + delta;
568 generator.GestureScrollSequence(
569 outside_start, end, kTimeDelta, kNumScrollSteps);
570 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
571 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
572 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
573 EXPECT_EQ(shelf_hidden.ToString(),
574 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
576 // Swipe up from below the shelf where a bezel would be, this should show the
577 // shelf.
578 gfx::Point below_start = start;
579 if (GetShelfLayoutManager()->IsHorizontalAlignment())
580 below_start.set_y(GetShelfWidget()->GetWindowBoundsInScreen().bottom() + 1);
581 else if (SHELF_ALIGNMENT_LEFT == GetShelfLayoutManager()->GetAlignment())
582 below_start.set_x(
583 GetShelfWidget()->GetWindowBoundsInScreen().x() - 1);
584 else if (SHELF_ALIGNMENT_RIGHT == GetShelfLayoutManager()->GetAlignment())
585 below_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().right() + 1);
586 end = below_start - delta;
587 generator.GestureScrollSequence(
588 below_start, end, kTimeDelta, kNumScrollSteps);
589 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
590 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
591 EXPECT_EQ(bounds_shelf.ToString(), window->bounds().ToString());
592 EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(),
593 GetShelfWidget()->GetWindowBoundsInScreen());
594 EXPECT_EQ(shelf_shown.ToString(),
595 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
597 // Swipe down again to hide.
598 end = start + delta;
599 generator.GestureScrollSequenceWithCallback(
600 start,
601 end,
602 kTimeDelta,
603 kNumScrollSteps,
604 base::Bind(&ShelfDragCallback::ProcessScroll,
605 base::Unretained(&handler)));
606 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
607 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
608 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
609 EXPECT_EQ(GetShelfWidget()->GetDimmerBoundsForTest(), gfx::Rect());
610 EXPECT_EQ(bounds_noshelf.ToString(), window->bounds().ToString());
611 EXPECT_EQ(shelf_hidden.ToString(),
612 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
614 // Put |widget| into fullscreen. Set the shelf to be auto hidden when |widget|
615 // is fullscreen. (eg browser immersive fullscreen).
616 widget->SetFullscreen(true);
617 wm::GetWindowState(window)->set_hide_shelf_when_fullscreen(false);
618 shelf->UpdateVisibilityState();
620 gfx::Rect bounds_fullscreen = window->bounds();
621 EXPECT_TRUE(widget->IsFullscreen());
622 EXPECT_NE(bounds_noshelf.ToString(), bounds_fullscreen.ToString());
624 // Swipe up. This should show the shelf.
625 end = below_start - delta;
626 generator.GestureScrollSequenceWithCallback(
627 below_start,
628 end,
629 kTimeDelta,
630 kNumScrollSteps,
631 base::Bind(&ShelfDragCallback::ProcessScroll,
632 base::Unretained(&handler)));
633 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
634 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
635 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
636 EXPECT_EQ(shelf_shown.ToString(),
637 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
638 EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
640 // Swipe up again. This should hide the shelf.
641 generator.GestureScrollSequenceWithCallback(
642 below_start,
643 end,
644 kTimeDelta,
645 kNumScrollSteps,
646 base::Bind(&ShelfDragCallback::ProcessScroll,
647 base::Unretained(&handler)));
648 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
649 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
650 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
651 EXPECT_EQ(shelf_hidden.ToString(),
652 GetShelfWidget()->GetWindowBoundsInScreen().ToString());
653 EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
655 // Set the shelf to be hidden when |widget| is fullscreen. (eg tab fullscreen
656 // with or without immersive browser fullscreen).
657 wm::GetWindowState(window)->set_hide_shelf_when_fullscreen(true);
658 shelf->UpdateVisibilityState();
659 EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
660 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
662 // Swipe-up. This should not change anything.
663 end = start - delta;
664 generator.GestureScrollSequenceWithCallback(
665 below_start,
666 end,
667 kTimeDelta,
668 kNumScrollSteps,
669 base::Bind(&ShelfDragCallback::ProcessScroll,
670 base::Unretained(&handler)));
671 EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
672 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
673 EXPECT_EQ(bounds_fullscreen.ToString(), window->bounds().ToString());
675 // Close actually, otherwise further event may be affected since widget
676 // is fullscreen status.
677 widget->Close();
678 RunAllPendingInMessageLoop();
680 // The shelf should be shown because there are no more visible windows.
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());
685 // Swipe-up to hide. This should have no effect because there are no visible
686 // windows.
687 end = below_start - delta;
688 generator.GestureScrollSequenceWithCallback(
689 below_start,
690 end,
691 kTimeDelta,
692 kNumScrollSteps,
693 base::Bind(&ShelfDragCallback::ProcessScroll,
694 base::Unretained(&handler)));
695 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
696 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
697 EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS, shelf->auto_hide_behavior());
700 // Need to be implemented. http://crbug.com/111279.
701 #if defined(OS_WIN)
702 #define MAYBE_SetVisible DISABLED_SetVisible
703 #else
704 #define MAYBE_SetVisible SetVisible
705 #endif
706 // Makes sure SetVisible updates work area and widget appropriately.
707 TEST_F(ShelfLayoutManagerTest, MAYBE_SetVisible) {
708 ShelfWidget* shelf = GetShelfWidget();
709 ShelfLayoutManager* manager = shelf->shelf_layout_manager();
710 // Force an initial layout.
711 manager->LayoutShelf();
712 EXPECT_EQ(SHELF_VISIBLE, manager->visibility_state());
714 gfx::Rect status_bounds(
715 shelf->status_area_widget()->GetWindowBoundsInScreen());
716 gfx::Rect shelf_bounds(
717 shelf->GetWindowBoundsInScreen());
718 int shelf_height = manager->GetIdealBounds().height();
719 gfx::Screen* screen = Shell::GetScreen();
720 gfx::Display display = screen->GetDisplayNearestWindow(
721 Shell::GetPrimaryRootWindow());
722 ASSERT_NE(-1, display.id());
723 // Bottom inset should be the max of widget heights.
724 EXPECT_EQ(shelf_height, display.GetWorkAreaInsets().bottom());
726 // Hide the shelf.
727 SetState(manager, SHELF_HIDDEN);
728 // Run the animation to completion.
729 StepWidgetLayerAnimatorToEnd(shelf);
730 StepWidgetLayerAnimatorToEnd(shelf->status_area_widget());
731 EXPECT_EQ(SHELF_HIDDEN, manager->visibility_state());
732 display = screen->GetDisplayNearestWindow(
733 Shell::GetPrimaryRootWindow());
735 EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
737 // Make sure the bounds of the two widgets changed.
738 EXPECT_GE(shelf->GetNativeView()->bounds().y(),
739 screen->GetPrimaryDisplay().bounds().bottom());
740 EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(),
741 screen->GetPrimaryDisplay().bounds().bottom());
743 // And show it again.
744 SetState(manager, SHELF_VISIBLE);
745 // Run the animation to completion.
746 StepWidgetLayerAnimatorToEnd(shelf);
747 StepWidgetLayerAnimatorToEnd(shelf->status_area_widget());
748 EXPECT_EQ(SHELF_VISIBLE, manager->visibility_state());
749 display = screen->GetDisplayNearestWindow(
750 Shell::GetPrimaryRootWindow());
751 EXPECT_EQ(shelf_height, display.GetWorkAreaInsets().bottom());
753 // Make sure the bounds of the two widgets changed.
754 shelf_bounds = shelf->GetNativeView()->bounds();
755 EXPECT_LT(shelf_bounds.y(), screen->GetPrimaryDisplay().bounds().bottom());
756 status_bounds = shelf->status_area_widget()->GetNativeView()->bounds();
757 EXPECT_LT(status_bounds.y(),
758 screen->GetPrimaryDisplay().bounds().bottom());
761 // Makes sure shelf alignment is correct for lock screen.
762 TEST_F(ShelfLayoutManagerTest, SideAlignmentInteractionWithLockScreen) {
763 ShelfLayoutManager* manager = GetShelfWidget()->shelf_layout_manager();
764 manager->SetAlignment(SHELF_ALIGNMENT_LEFT);
765 EXPECT_EQ(SHELF_ALIGNMENT_LEFT, manager->GetAlignment());
766 LockScreen();
767 EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, manager->GetAlignment());
768 UnlockScreen();
769 EXPECT_EQ(SHELF_ALIGNMENT_LEFT, manager->GetAlignment());
772 // Makes sure shelf alignment is correct for add user screen.
773 TEST_F(ShelfLayoutManagerTest, SideAlignmentInteractionWithAddUserScreen) {
774 ShelfLayoutManager* manager = GetShelfWidget()->shelf_layout_manager();
775 manager->SetAlignment(SHELF_ALIGNMENT_LEFT);
776 EXPECT_EQ(SHELF_ALIGNMENT_LEFT, manager->GetAlignment());
777 ShowAddUserScreen(true);
778 EXPECT_EQ(SHELF_ALIGNMENT_BOTTOM, manager->GetAlignment());
779 ShowAddUserScreen(false);
780 EXPECT_EQ(SHELF_ALIGNMENT_LEFT, manager->GetAlignment());
783 // Makes sure shelf alignment is correct for login screen.
784 TEST_F(ShelfLayoutManagerTest, SideAlignmentInteractionWithLoginScreen) {
785 ShelfLayoutManager* manager = GetShelfWidget()->shelf_layout_manager();
786 ASSERT_EQ(SHELF_ALIGNMENT_BOTTOM, manager->GetAlignment());
787 SetUserLoggedIn(false);
788 SetSessionStarted(false);
790 // The test session state delegate does not fire state changes.
791 SetSessionStarting();
792 manager->SessionStateChanged(
793 Shell::GetInstance()->session_state_delegate()->GetSessionState());
795 // Login sets alignment preferences before the session completes startup.
796 manager->SetAlignment(SHELF_ALIGNMENT_LEFT);
797 SetUserLoggedIn(true);
798 SetSessionStarted(true);
800 EXPECT_EQ(SHELF_ALIGNMENT_LEFT, manager->GetAlignment());
801 // Ensure that the shelf has been notified.
802 EXPECT_EQ(SHELF_ALIGNMENT_LEFT, GetShelfWidget()->shelf()->alignment());
805 // Makes sure LayoutShelf invoked while animating cleans things up.
806 TEST_F(ShelfLayoutManagerTest, LayoutShelfWhileAnimating) {
807 ShelfWidget* shelf = GetShelfWidget();
808 // Force an initial layout.
809 shelf->shelf_layout_manager()->LayoutShelf();
810 EXPECT_EQ(SHELF_VISIBLE, shelf->shelf_layout_manager()->visibility_state());
812 // Hide the shelf.
813 SetState(shelf->shelf_layout_manager(), SHELF_HIDDEN);
814 shelf->shelf_layout_manager()->LayoutShelf();
815 EXPECT_EQ(SHELF_HIDDEN, shelf->shelf_layout_manager()->visibility_state());
816 gfx::Display display = Shell::GetScreen()->GetDisplayNearestWindow(
817 Shell::GetPrimaryRootWindow());
818 EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
820 // Make sure the bounds of the two widgets changed.
821 EXPECT_GE(shelf->GetNativeView()->bounds().y(),
822 Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
823 EXPECT_GE(shelf->status_area_widget()->GetNativeView()->bounds().y(),
824 Shell::GetScreen()->GetPrimaryDisplay().bounds().bottom());
827 // Test that switching to a different visibility state does not restart the
828 // shelf show / hide animation if it is already running. (crbug.com/250918)
829 TEST_F(ShelfLayoutManagerTest, SetStateWhileAnimating) {
830 ShelfWidget* shelf = GetShelfWidget();
831 SetState(shelf->shelf_layout_manager(), SHELF_VISIBLE);
832 gfx::Rect initial_shelf_bounds = shelf->GetWindowBoundsInScreen();
833 gfx::Rect initial_status_bounds =
834 shelf->status_area_widget()->GetWindowBoundsInScreen();
836 ui::ScopedAnimationDurationScaleMode normal_animation_duration(
837 ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
838 SetState(shelf->shelf_layout_manager(), SHELF_HIDDEN);
839 SetState(shelf->shelf_layout_manager(), SHELF_VISIBLE);
841 gfx::Rect current_shelf_bounds = shelf->GetWindowBoundsInScreen();
842 gfx::Rect current_status_bounds =
843 shelf->status_area_widget()->GetWindowBoundsInScreen();
845 const int small_change = initial_shelf_bounds.height() / 2;
846 EXPECT_LE(
847 std::abs(initial_shelf_bounds.height() - current_shelf_bounds.height()),
848 small_change);
849 EXPECT_LE(
850 std::abs(initial_status_bounds.height() - current_status_bounds.height()),
851 small_change);
854 // Makes sure the shelf is sized when the status area changes size.
855 TEST_F(ShelfLayoutManagerTest, ShelfUpdatedWhenStatusAreaChangesSize) {
856 Shelf* shelf = Shelf::ForPrimaryDisplay();
857 ASSERT_TRUE(shelf);
858 ShelfWidget* shelf_widget = GetShelfWidget();
859 ASSERT_TRUE(shelf_widget);
860 ASSERT_TRUE(shelf_widget->status_area_widget());
861 shelf_widget->status_area_widget()->SetBounds(
862 gfx::Rect(0, 0, 200, 200));
863 EXPECT_EQ(200, shelf_widget->GetContentsView()->width() -
864 test::ShelfTestAPI(shelf).shelf_view()->width());
868 #if defined(OS_WIN)
869 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
870 #define MAYBE_AutoHide DISABLED_AutoHide
871 #else
872 #define MAYBE_AutoHide AutoHide
873 #endif
875 // Various assertions around auto-hide.
876 TEST_F(ShelfLayoutManagerTest, MAYBE_AutoHide) {
877 aura::Window* root = Shell::GetPrimaryRootWindow();
878 ui::test::EventGenerator generator(root, root);
879 generator.MoveMouseTo(0, 0);
881 ShelfLayoutManager* shelf = GetShelfLayoutManager();
882 shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
883 views::Widget* widget = new views::Widget;
884 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
885 params.bounds = gfx::Rect(0, 0, 200, 200);
886 params.context = CurrentContext();
887 // Widget is now owned by the parent window.
888 widget->Init(params);
889 widget->Maximize();
890 widget->Show();
891 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
892 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
894 // LayoutShelf() forces the animation to completion, at which point the
895 // shelf should go off the screen.
896 shelf->LayoutShelf();
897 EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
898 GetShelfWidget()->GetWindowBoundsInScreen().y());
899 EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
900 Shell::GetScreen()->GetDisplayNearestWindow(
901 root).work_area().bottom());
903 // Move the mouse to the bottom of the screen.
904 generator.MoveMouseTo(0, root->bounds().bottom() - 1);
906 // Shelf should be shown again (but it shouldn't have changed the work area).
907 SetState(shelf, SHELF_AUTO_HIDE);
908 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
909 shelf->LayoutShelf();
910 EXPECT_EQ(root->bounds().bottom() - shelf->GetIdealBounds().height(),
911 GetShelfWidget()->GetWindowBoundsInScreen().y());
912 EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
913 Shell::GetScreen()->GetDisplayNearestWindow(
914 root).work_area().bottom());
916 // Move mouse back up.
917 generator.MoveMouseTo(0, 0);
918 SetState(shelf, SHELF_AUTO_HIDE);
919 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
920 shelf->LayoutShelf();
921 EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
922 GetShelfWidget()->GetWindowBoundsInScreen().y());
924 // Drag mouse to bottom of screen.
925 generator.PressLeftButton();
926 generator.MoveMouseTo(0, root->bounds().bottom() - 1);
927 UpdateAutoHideStateNow();
928 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
930 generator.ReleaseLeftButton();
931 generator.MoveMouseTo(1, root->bounds().bottom() - 1);
932 UpdateAutoHideStateNow();
933 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
934 generator.PressLeftButton();
935 generator.MoveMouseTo(1, root->bounds().bottom() - 1);
936 UpdateAutoHideStateNow();
937 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
940 // Test the behavior of the shelf when it is auto hidden and it is on the
941 // boundary between the primary and the secondary display.
942 TEST_F(ShelfLayoutManagerTest, AutoHideShelfOnScreenBoundary) {
943 if (!SupportsMultipleDisplays())
944 return;
946 UpdateDisplay("800x600,800x600");
947 DisplayLayout display_layout(DisplayLayout::RIGHT, 0);
948 Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
949 display_layout);
950 // Put the primary monitor's shelf on the display boundary.
951 ShelfLayoutManager* shelf = GetShelfLayoutManager();
952 shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
954 // Create a window because the shelf is always shown when no windows are
955 // visible.
956 CreateTestWidget();
958 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
959 ASSERT_EQ(root_windows[0],
960 GetShelfWidget()->GetNativeWindow()->GetRootWindow());
962 shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
963 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
965 int right_edge = root_windows[0]->GetBoundsInScreen().right() - 1;
966 int y = root_windows[0]->GetBoundsInScreen().y();
968 // Start off the mouse nowhere near the shelf; the shelf should be hidden.
969 ui::test::EventGenerator& generator(GetEventGenerator());
970 generator.MoveMouseTo(right_edge - 50, y);
971 UpdateAutoHideStateNow();
972 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
974 // Moving the mouse over the light bar (but not to the edge of the screen)
975 // should show the shelf.
976 generator.MoveMouseTo(right_edge - 1, y);
977 UpdateAutoHideStateNow();
978 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
979 EXPECT_EQ(right_edge - 1, Shell::GetScreen()->GetCursorScreenPoint().x());
981 // Moving the mouse off the light bar should hide the shelf.
982 generator.MoveMouseTo(right_edge - 50, y);
983 UpdateAutoHideStateNow();
984 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
986 // Moving the mouse to the right edge of the screen crossing the light bar
987 // should show the shelf despite the mouse cursor getting warped to the
988 // secondary display.
989 generator.MoveMouseTo(right_edge - 1, y);
990 generator.MoveMouseTo(right_edge, y);
991 UpdateAutoHideStateNow();
992 EXPECT_NE(right_edge - 1, Shell::GetScreen()->GetCursorScreenPoint().x());
993 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
995 // Hide the shelf.
996 generator.MoveMouseTo(right_edge - 50, y);
997 UpdateAutoHideStateNow();
998 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1000 // Moving the mouse to the right edge of the screen crossing the light bar and
1001 // overshooting by a lot should keep the shelf hidden.
1002 generator.MoveMouseTo(right_edge - 1, y);
1003 generator.MoveMouseTo(right_edge + 50, y);
1004 UpdateAutoHideStateNow();
1005 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1007 // Moving the mouse to the right edge of the screen crossing the light bar and
1008 // overshooting a bit should show the shelf.
1009 generator.MoveMouseTo(right_edge - 1, y);
1010 generator.MoveMouseTo(right_edge + 2, y);
1011 UpdateAutoHideStateNow();
1012 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1014 // Keeping the mouse close to the left edge of the secondary display after the
1015 // shelf is shown should keep the shelf shown.
1016 generator.MoveMouseTo(right_edge + 2, y + 1);
1017 UpdateAutoHideStateNow();
1018 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1020 // Moving the mouse far from the left edge of the secondary display should
1021 // hide the shelf.
1022 generator.MoveMouseTo(right_edge + 50, y);
1023 UpdateAutoHideStateNow();
1024 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1026 // Moving to the left edge of the secondary display without first crossing
1027 // the primary display's right aligned shelf first should not show the shelf.
1028 generator.MoveMouseTo(right_edge + 2, y);
1029 UpdateAutoHideStateNow();
1030 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1033 // Assertions around the lock screen showing.
1034 TEST_F(ShelfLayoutManagerTest, VisibleWhenLockScreenShowing) {
1035 // Since ShelfLayoutManager queries for mouse location, move the mouse so
1036 // it isn't over the shelf.
1037 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1038 gfx::Point());
1039 generator.MoveMouseTo(0, 0);
1041 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1042 shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1043 views::Widget* widget = new views::Widget;
1044 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1045 params.bounds = gfx::Rect(0, 0, 200, 200);
1046 params.context = CurrentContext();
1047 // Widget is now owned by the parent window.
1048 widget->Init(params);
1049 widget->Maximize();
1050 widget->Show();
1051 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1052 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1054 aura::Window* root = Shell::GetPrimaryRootWindow();
1055 // LayoutShelf() forces the animation to completion, at which point the
1056 // shelf should go off the screen.
1057 shelf->LayoutShelf();
1058 EXPECT_EQ(root->bounds().bottom() - ShelfLayoutManager::kAutoHideSize,
1059 GetShelfWidget()->GetWindowBoundsInScreen().y());
1061 aura::Window* lock_container = Shell::GetContainer(
1062 Shell::GetPrimaryRootWindow(), kShellWindowId_LockScreenContainer);
1064 views::Widget* lock_widget = new views::Widget;
1065 views::Widget::InitParams lock_params(
1066 views::Widget::InitParams::TYPE_WINDOW);
1067 lock_params.bounds = gfx::Rect(0, 0, 200, 200);
1068 params.context = CurrentContext();
1069 lock_params.parent = lock_container;
1070 // Widget is now owned by the parent window.
1071 lock_widget->Init(lock_params);
1072 lock_widget->Maximize();
1073 lock_widget->Show();
1075 // Lock the screen.
1076 LockScreen();
1077 // Showing a widget in the lock screen should force the shelf to be visibile.
1078 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1080 UnlockScreen();
1081 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1084 // Assertions around SetAutoHideBehavior.
1085 TEST_F(ShelfLayoutManagerTest, SetAutoHideBehavior) {
1086 // Since ShelfLayoutManager queries for mouse location, move the mouse so
1087 // it isn't over the shelf.
1088 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1089 gfx::Point());
1090 generator.MoveMouseTo(0, 0);
1092 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1093 views::Widget* widget = new views::Widget;
1094 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1095 params.bounds = gfx::Rect(0, 0, 200, 200);
1096 params.context = CurrentContext();
1097 // Widget is now owned by the parent window.
1098 widget->Init(params);
1099 widget->Show();
1100 aura::Window* window = widget->GetNativeWindow();
1101 gfx::Rect display_bounds(
1102 Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
1104 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1105 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1107 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1108 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1110 widget->Maximize();
1111 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1112 EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
1113 window).work_area().bottom(),
1114 widget->GetWorkAreaBoundsInScreen().bottom());
1116 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1117 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1118 EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
1119 window).work_area().bottom(),
1120 widget->GetWorkAreaBoundsInScreen().bottom());
1122 ui::ScopedAnimationDurationScaleMode animation_duration(
1123 ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
1125 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1126 ShelfWidget* shelf_widget = GetShelfWidget();
1127 EXPECT_TRUE(shelf_widget->status_area_widget()->IsVisible());
1128 StepWidgetLayerAnimatorToEnd(shelf_widget);
1129 StepWidgetLayerAnimatorToEnd(shelf_widget->status_area_widget());
1130 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1131 EXPECT_EQ(Shell::GetScreen()->GetDisplayNearestWindow(
1132 window).work_area().bottom(),
1133 widget->GetWorkAreaBoundsInScreen().bottom());
1136 // Basic assertions around the dimming of the shelf.
1137 TEST_F(ShelfLayoutManagerTest, DimmingBehavior) {
1138 // Since ShelfLayoutManager queries for mouse location, move the mouse so
1139 // it isn't over the shelf.
1140 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1141 gfx::Point());
1142 generator.MoveMouseTo(0, 0);
1144 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1145 shelf->shelf_widget()->DisableDimmingAnimationsForTest();
1147 views::Widget* widget = new views::Widget;
1148 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1149 params.bounds = gfx::Rect(0, 0, 200, 200);
1150 params.context = CurrentContext();
1151 // Widget is now owned by the parent window.
1152 widget->Init(params);
1153 widget->Show();
1154 aura::Window* window = widget->GetNativeWindow();
1155 gfx::Rect display_bounds(
1156 Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
1158 gfx::Point off_shelf = display_bounds.CenterPoint();
1159 gfx::Point on_shelf =
1160 shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
1162 // Test there is no dimming object active at this point.
1163 generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
1164 EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
1165 generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
1166 EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
1168 // After maximization, the shelf should be visible and the dimmer created.
1169 widget->Maximize();
1171 on_shelf = shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
1172 EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1174 // Moving the mouse off the shelf should dim the bar.
1175 generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
1176 EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1178 // Adding touch events outside the shelf should still keep the shelf in
1179 // dimmed state.
1180 generator.PressTouch();
1181 generator.MoveTouch(off_shelf);
1182 EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1183 // Move the touch into the shelf area should undim.
1184 generator.MoveTouch(on_shelf);
1185 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1186 generator.ReleaseTouch();
1187 // And a release dims again.
1188 EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1190 // Moving the mouse on the shelf should undim the bar.
1191 generator.MoveMouseTo(on_shelf);
1192 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1194 // No matter what the touch events do, the shelf should stay undimmed.
1195 generator.PressTouch();
1196 generator.MoveTouch(off_shelf);
1197 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1198 generator.MoveTouch(on_shelf);
1199 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1200 generator.MoveTouch(off_shelf);
1201 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1202 generator.MoveTouch(on_shelf);
1203 generator.ReleaseTouch();
1205 // After restore, the dimming object should be deleted again.
1206 widget->Restore();
1207 EXPECT_EQ(-1, shelf->shelf_widget()->GetDimmingAlphaForTest());
1210 // Test that dimming works correctly with multiple displays.
1211 TEST_F(ShelfLayoutManagerTest, DimmingBehaviorDualDisplay) {
1212 if (!SupportsMultipleDisplays())
1213 return;
1215 // Create two displays.
1216 Shell* shell = Shell::GetInstance();
1217 UpdateDisplay("0+0-200x200,+200+0-100x100");
1218 EXPECT_EQ(2U, shell->display_manager()->GetNumDisplays());
1220 DisplayController* display_controller = shell->display_controller();
1221 aura::Window::Windows root_windows = display_controller->GetAllRootWindows();
1222 EXPECT_EQ(root_windows.size(), 2U);
1224 std::vector<ShelfWidget*> shelf_widgets;
1225 for (auto& root_window : root_windows) {
1226 ShelfLayoutManager* shelf =
1227 GetRootWindowController(root_window)->GetShelfLayoutManager();
1228 shelf_widgets.push_back(shelf->shelf_widget());
1230 // For disabling the dimming animation to work, the animation must be
1231 // disabled prior to creating the dimmer.
1232 shelf_widgets.back()->DisableDimmingAnimationsForTest();
1234 // Create a maximized window to create the dimmer.
1235 views::Widget* widget = new views::Widget;
1236 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1237 params.context = root_window;
1238 params.bounds = root_window->GetBoundsInScreen();
1239 params.show_state = ui::SHOW_STATE_MAXIMIZED;
1240 widget->Init(params);
1241 widget->Show();
1244 ui::test::EventGenerator& generator(GetEventGenerator());
1246 generator.MoveMouseTo(root_windows[0]->GetBoundsInScreen().CenterPoint());
1247 EXPECT_LT(0, shelf_widgets[0]->GetDimmingAlphaForTest());
1248 EXPECT_LT(0, shelf_widgets[1]->GetDimmingAlphaForTest());
1250 generator.MoveMouseTo(
1251 shelf_widgets[0]->GetWindowBoundsInScreen().CenterPoint());
1252 EXPECT_EQ(0, shelf_widgets[0]->GetDimmingAlphaForTest());
1253 EXPECT_LT(0, shelf_widgets[1]->GetDimmingAlphaForTest());
1255 generator.MoveMouseTo(
1256 shelf_widgets[1]->GetWindowBoundsInScreen().CenterPoint());
1257 EXPECT_LT(0, shelf_widgets[0]->GetDimmingAlphaForTest());
1258 EXPECT_EQ(0, shelf_widgets[1]->GetDimmingAlphaForTest());
1260 generator.MoveMouseTo(root_windows[1]->GetBoundsInScreen().CenterPoint());
1261 EXPECT_LT(0, shelf_widgets[0]->GetDimmingAlphaForTest());
1262 EXPECT_LT(0, shelf_widgets[1]->GetDimmingAlphaForTest());
1265 // Assertions around the dimming of the shelf in conjunction with menus.
1266 TEST_F(ShelfLayoutManagerTest, DimmingBehaviorWithMenus) {
1267 // Since ShelfLayoutManager queries for mouse location, move the mouse so
1268 // it isn't over the shelf.
1269 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1270 gfx::Point());
1271 generator.MoveMouseTo(0, 0);
1273 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1274 shelf->shelf_widget()->DisableDimmingAnimationsForTest();
1276 views::Widget* widget = new views::Widget;
1277 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1278 params.bounds = gfx::Rect(0, 0, 200, 200);
1279 params.context = CurrentContext();
1280 // Widget is now owned by the parent window.
1281 widget->Init(params);
1282 widget->Show();
1283 aura::Window* window = widget->GetNativeWindow();
1284 gfx::Rect display_bounds(
1285 Shell::GetScreen()->GetDisplayNearestWindow(window).bounds());
1287 // After maximization, the shelf should be visible and the dimmer created.
1288 widget->Maximize();
1290 gfx::Point off_shelf = display_bounds.CenterPoint();
1291 gfx::Point on_shelf =
1292 shelf->shelf_widget()->GetWindowBoundsInScreen().CenterPoint();
1294 // Moving the mouse on the shelf should undim the bar.
1295 generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
1296 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1298 // Simulate a menu opening.
1299 shelf->shelf_widget()->ForceUndimming(true);
1301 // Moving the mouse off the shelf should not dim the bar.
1302 generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
1303 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1305 // No matter what the touch events do, the shelf should stay undimmed.
1306 generator.PressTouch();
1307 generator.MoveTouch(off_shelf);
1308 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1309 generator.MoveTouch(on_shelf);
1310 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1311 generator.MoveTouch(off_shelf);
1312 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1313 generator.ReleaseTouch();
1314 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1316 // "Closing the menu" should now turn off the menu since no event is inside
1317 // the shelf any longer.
1318 shelf->shelf_widget()->ForceUndimming(false);
1319 EXPECT_LT(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1321 // Moving the mouse again on the shelf which should undim the bar again.
1322 // This time we check that the bar stays undimmed when the mouse remains on
1323 // the bar and the "menu gets closed".
1324 generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
1325 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1326 shelf->shelf_widget()->ForceUndimming(true);
1327 generator.MoveMouseTo(off_shelf.x(), off_shelf.y());
1328 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1329 generator.MoveMouseTo(on_shelf.x(), on_shelf.y());
1330 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1331 shelf->shelf_widget()->ForceUndimming(true);
1332 EXPECT_EQ(0, shelf->shelf_widget()->GetDimmingAlphaForTest());
1335 // Verifies the shelf is visible when status/shelf is focused.
1336 TEST_F(ShelfLayoutManagerTest, VisibleWhenStatusOrShelfFocused) {
1337 // Since ShelfLayoutManager queries for mouse location, move the mouse so
1338 // it isn't over the shelf.
1339 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1340 gfx::Point());
1341 generator.MoveMouseTo(0, 0);
1343 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1344 views::Widget* widget = new views::Widget;
1345 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1346 params.bounds = gfx::Rect(0, 0, 200, 200);
1347 params.context = CurrentContext();
1348 // Widget is now owned by the parent window.
1349 widget->Init(params);
1350 widget->Show();
1351 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1352 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1353 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1355 // Focus the shelf. Have to go through the focus cycler as normal focus
1356 // requests to it do nothing.
1357 GetShelfWidget()->GetFocusCycler()->RotateFocus(FocusCycler::FORWARD);
1358 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1360 widget->Activate();
1361 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1363 // Trying to activate the status should fail, since we only allow activating
1364 // it when the user is using the keyboard (i.e. through FocusCycler).
1365 GetShelfWidget()->status_area_widget()->Activate();
1366 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1368 GetShelfWidget()->GetFocusCycler()->RotateFocus(FocusCycler::FORWARD);
1369 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1372 // Makes sure shelf will be visible when app list opens as shelf is in
1373 // SHELF_VISIBLE state,and toggling app list won't change shelf
1374 // visibility state.
1375 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfVisibleState) {
1376 Shell* shell = Shell::GetInstance();
1377 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1378 shelf->LayoutShelf();
1379 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1381 // Create a normal unmaximized windowm shelf should be visible.
1382 aura::Window* window = CreateTestWindow();
1383 window->SetBounds(gfx::Rect(0, 0, 100, 100));
1384 window->Show();
1385 EXPECT_FALSE(shell->GetAppListTargetVisibility());
1386 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1388 // Show app list and the shelf stays visible.
1389 shell->ShowAppList(NULL);
1390 EXPECT_TRUE(shell->GetAppListTargetVisibility());
1391 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1393 // Hide app list and the shelf stays visible.
1394 shell->DismissAppList();
1395 EXPECT_FALSE(shell->GetAppListTargetVisibility());
1396 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1399 // Makes sure shelf will be shown with SHELF_AUTO_HIDE_SHOWN state
1400 // when app list opens as shelf is in SHELF_AUTO_HIDE state, and
1401 // toggling app list won't change shelf visibility state.
1402 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfAutoHideState) {
1403 Shell* shell = Shell::GetInstance();
1404 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1405 shelf->LayoutShelf();
1406 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1408 // Create a window and show it in maximized state.
1409 aura::Window* window = CreateTestWindow();
1410 window->SetBounds(gfx::Rect(0, 0, 100, 100));
1411 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1412 window->Show();
1413 wm::ActivateWindow(window);
1415 EXPECT_FALSE(shell->GetAppListTargetVisibility());
1416 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1418 // Show app list.
1419 shell->ShowAppList(NULL);
1420 // The shelf's auto hide state won't be changed until the timer fires, so
1421 // calling shell->UpdateShelfVisibility() is kind of manually helping it to
1422 // update the state.
1423 shell->UpdateShelfVisibility();
1424 EXPECT_TRUE(shell->GetAppListTargetVisibility());
1425 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1426 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1428 // Hide app list.
1429 shell->DismissAppList();
1430 EXPECT_FALSE(shell->GetAppListTargetVisibility());
1431 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1434 // Makes sure that when we have dual displays, with one or both shelves are set
1435 // to AutoHide, viewing the AppList on one of them doesn't unhide the other
1436 // hidden shelf.
1437 TEST_F(ShelfLayoutManagerTest, DualDisplayOpenAppListWithShelfAutoHideState) {
1438 if (!SupportsMultipleDisplays())
1439 return;
1441 // Create two displays.
1442 Shell* shell = Shell::GetInstance();
1443 DisplayManager* display_manager = shell->display_manager();
1444 EXPECT_EQ(1U, display_manager->GetNumDisplays());
1445 UpdateDisplay("0+0-200x200,+200+0-100x100");
1446 EXPECT_EQ(2U, display_manager->GetNumDisplays());
1448 DisplayController* display_controller = shell->display_controller();
1449 aura::Window::Windows root_windows = display_controller->GetAllRootWindows();
1450 EXPECT_EQ(root_windows.size(), 2U);
1452 // Get the shelves in both displays and set them to be 'AutoHide'.
1453 ShelfLayoutManager* shelf_1 =
1454 GetRootWindowController(root_windows[0])->GetShelfLayoutManager();
1455 ShelfLayoutManager* shelf_2 =
1456 GetRootWindowController(root_windows[1])->GetShelfLayoutManager();
1457 EXPECT_NE(shelf_1, shelf_2);
1458 EXPECT_NE(shelf_1->shelf_widget()->GetNativeWindow()->GetRootWindow(),
1459 shelf_2->shelf_widget()->GetNativeWindow()->
1460 GetRootWindow());
1461 shelf_1->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1462 shelf_1->LayoutShelf();
1463 shelf_2->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1464 shelf_2->LayoutShelf();
1466 // Create a window in each display and show them in maximized state.
1467 aura::Window* window_1 =
1468 CreateTestWindowInParent(root_windows[0]);
1469 window_1->SetBounds(gfx::Rect(0, 0, 100, 100));
1470 window_1->SetProperty(aura::client::kShowStateKey,
1471 ui::SHOW_STATE_MAXIMIZED);
1472 window_1->Show();
1473 aura::Window* window_2 =
1474 CreateTestWindowInParent(root_windows[1]);
1475 window_2->SetBounds(gfx::Rect(201, 0, 100, 100));
1476 window_2->SetProperty(aura::client::kShowStateKey,
1477 ui::SHOW_STATE_MAXIMIZED);
1478 window_2->Show();
1480 EXPECT_EQ(shelf_1->shelf_widget()->GetNativeWindow()->GetRootWindow(),
1481 window_1->GetRootWindow());
1482 EXPECT_EQ(shelf_2->shelf_widget()->GetNativeWindow()->GetRootWindow(),
1483 window_2->GetRootWindow());
1485 // Activate one window in one display and manually trigger the update of shelf
1486 // visibility.
1487 wm::ActivateWindow(window_1);
1488 shell->UpdateShelfVisibility();
1490 EXPECT_FALSE(shell->GetAppListTargetVisibility());
1491 EXPECT_EQ(SHELF_AUTO_HIDE, shelf_1->visibility_state());
1492 EXPECT_EQ(SHELF_AUTO_HIDE, shelf_2->visibility_state());
1493 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf_1->auto_hide_state());
1494 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf_2->auto_hide_state());
1496 // Show app list.
1497 shell->ShowAppList(NULL);
1498 shell->UpdateShelfVisibility();
1500 // Only the shelf in the active display should be shown, the other is hidden.
1501 EXPECT_TRUE(shell->GetAppListTargetVisibility());
1502 EXPECT_EQ(SHELF_AUTO_HIDE, shelf_1->visibility_state());
1503 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf_1->auto_hide_state());
1504 EXPECT_EQ(SHELF_AUTO_HIDE, shelf_2->visibility_state());
1505 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf_2->auto_hide_state());
1507 // Hide app list, both shelves should be hidden.
1508 shell->DismissAppList();
1509 EXPECT_FALSE(shell->GetAppListTargetVisibility());
1510 EXPECT_EQ(SHELF_AUTO_HIDE, shelf_1->visibility_state());
1511 EXPECT_EQ(SHELF_AUTO_HIDE, shelf_2->visibility_state());
1512 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf_1->auto_hide_state());
1513 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf_2->auto_hide_state());
1516 // Makes sure the shelf will be hidden when we have a fullscreen window, and it
1517 // will unhide when we open the app list.
1518 TEST_F(ShelfLayoutManagerTest, OpenAppListWithShelfHiddenState) {
1519 Shell* shell = Shell::GetInstance();
1520 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1521 // For shelf to be visible, app list is not open in initial state.
1522 shelf->LayoutShelf();
1524 // Create a window and make it full screen.
1525 aura::Window* window = CreateTestWindow();
1526 window->SetBounds(gfx::Rect(0, 0, 100, 100));
1527 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
1528 window->Show();
1529 wm::ActivateWindow(window);
1531 // App list and shelf is not shown.
1532 EXPECT_FALSE(shell->GetAppListTargetVisibility());
1533 EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
1535 // Show app list.
1536 shell->ShowAppList(NULL);
1537 EXPECT_TRUE(shell->GetAppListTargetVisibility());
1538 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1540 // Hide app list.
1541 shell->DismissAppList();
1542 EXPECT_FALSE(shell->GetAppListTargetVisibility());
1543 EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
1546 // Tests the correct behavior of the shelf when there is a system modal window
1547 // open when we have a single display.
1548 TEST_F(ShelfLayoutManagerTest, ShelfWithSystemModalWindowSingleDisplay) {
1549 Shell* shell = Shell::GetInstance();
1550 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1551 shelf->LayoutShelf();
1552 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1554 aura::Window* window = CreateTestWindow();
1555 window->SetBounds(gfx::Rect(0, 0, 100, 100));
1556 window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1557 window->Show();
1558 wm::ActivateWindow(window);
1560 // Enable system modal dialog, and make sure shelf is still hidden.
1561 shell->SimulateModalWindowOpenForTesting(true);
1562 EXPECT_TRUE(shell->IsSystemModalWindowOpen());
1563 EXPECT_FALSE(wm::CanActivateWindow(window));
1564 shell->UpdateShelfVisibility();
1565 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1566 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1569 // Tests the correct behavior of the shelf when there is a system modal window
1570 // open when we have dual display.
1571 TEST_F(ShelfLayoutManagerTest, ShelfWithSystemModalWindowDualDisplay) {
1572 if (!SupportsMultipleDisplays())
1573 return;
1575 // Create two displays.
1576 Shell* shell = Shell::GetInstance();
1577 DisplayManager* display_manager = shell->display_manager();
1578 UpdateDisplay("200x200,100x100");
1579 EXPECT_EQ(2U, display_manager->GetNumDisplays());
1581 DisplayController* display_controller = shell->display_controller();
1582 aura::Window::Windows root_windows = display_controller->GetAllRootWindows();
1583 EXPECT_EQ(root_windows.size(), 2U);
1585 // Get the shelves in both displays and set them to be 'AutoHide'.
1586 ShelfLayoutManager* shelf_1 =
1587 GetRootWindowController(root_windows[0])->GetShelfLayoutManager();
1588 ShelfLayoutManager* shelf_2 =
1589 GetRootWindowController(root_windows[1])->GetShelfLayoutManager();
1590 EXPECT_NE(shelf_1, shelf_2);
1591 EXPECT_NE(shelf_1->shelf_widget()->GetNativeWindow()->GetRootWindow(),
1592 shelf_2->shelf_widget()->GetNativeWindow()->GetRootWindow());
1593 shelf_1->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1594 shelf_1->LayoutShelf();
1595 shelf_2->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1596 shelf_2->LayoutShelf();
1598 // Create a window in each display and show them in maximized state.
1599 aura::Window* window_1 = CreateTestWindowInParent(root_windows[0]);
1600 window_1->SetBounds(gfx::Rect(0, 0, 100, 100));
1601 window_1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1602 window_1->Show();
1603 aura::Window* window_2 = CreateTestWindowInParent(root_windows[1]);
1604 window_2->SetBounds(gfx::Rect(201, 0, 100, 100));
1605 window_2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1606 window_2->Show();
1608 EXPECT_EQ(shelf_1->shelf_widget()->GetNativeWindow()->GetRootWindow(),
1609 window_1->GetRootWindow());
1610 EXPECT_EQ(shelf_2->shelf_widget()->GetNativeWindow()->GetRootWindow(),
1611 window_2->GetRootWindow());
1612 EXPECT_TRUE(window_1->IsVisible());
1613 EXPECT_TRUE(window_2->IsVisible());
1615 // Enable system modal dialog, and make sure both shelves are still hidden.
1616 shell->SimulateModalWindowOpenForTesting(true);
1617 EXPECT_TRUE(shell->IsSystemModalWindowOpen());
1618 EXPECT_FALSE(wm::CanActivateWindow(window_1));
1619 EXPECT_FALSE(wm::CanActivateWindow(window_2));
1620 shell->UpdateShelfVisibility();
1621 EXPECT_EQ(SHELF_AUTO_HIDE, shelf_1->visibility_state());
1622 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf_1->auto_hide_state());
1623 EXPECT_EQ(SHELF_AUTO_HIDE, shelf_2->visibility_state());
1624 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf_2->auto_hide_state());
1627 // Tests that the shelf is only hidden for a fullscreen window at the front and
1628 // toggles visibility when another window is activated.
1629 TEST_F(ShelfLayoutManagerTest, FullscreenWindowInFrontHidesShelf) {
1630 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1632 // Create a window and make it full screen.
1633 aura::Window* window1 = CreateTestWindow();
1634 window1->SetBounds(gfx::Rect(0, 0, 100, 100));
1635 window1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
1636 window1->Show();
1638 aura::Window* window2 = CreateTestWindow();
1639 window2->SetBounds(gfx::Rect(0, 0, 100, 100));
1640 window2->Show();
1642 wm::GetWindowState(window1)->Activate();
1643 EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
1645 wm::GetWindowState(window2)->Activate();
1646 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1648 wm::GetWindowState(window1)->Activate();
1649 EXPECT_EQ(SHELF_HIDDEN, shelf->visibility_state());
1652 // Test the behavior of the shelf when a window on one display is fullscreen
1653 // but the other display has the active window.
1654 TEST_F(ShelfLayoutManagerTest, FullscreenWindowOnSecondDisplay) {
1655 if (!SupportsMultipleDisplays())
1656 return;
1658 UpdateDisplay("800x600,800x600");
1659 DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1660 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1661 Shell::RootWindowControllerList root_window_controllers =
1662 Shell::GetAllRootWindowControllers();
1664 // Create windows on either display.
1665 aura::Window* window1 = CreateTestWindow();
1666 window1->SetBoundsInScreen(
1667 gfx::Rect(0, 0, 100, 100),
1668 display_manager->GetDisplayAt(0));
1669 window1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
1670 window1->Show();
1672 aura::Window* window2 = CreateTestWindow();
1673 window2->SetBoundsInScreen(
1674 gfx::Rect(800, 0, 100, 100),
1675 display_manager->GetDisplayAt(1));
1676 window2->Show();
1678 EXPECT_EQ(root_windows[0], window1->GetRootWindow());
1679 EXPECT_EQ(root_windows[1], window2->GetRootWindow());
1681 wm::GetWindowState(window2)->Activate();
1682 EXPECT_EQ(SHELF_HIDDEN,
1683 root_window_controllers[0]->GetShelfLayoutManager()->visibility_state());
1684 EXPECT_EQ(SHELF_VISIBLE,
1685 root_window_controllers[1]->GetShelfLayoutManager()->visibility_state());
1689 #if defined(OS_WIN)
1690 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
1691 #define MAYBE_SetAlignment DISABLED_SetAlignment
1692 #else
1693 #define MAYBE_SetAlignment SetAlignment
1694 #endif
1696 // Tests SHELF_ALIGNMENT_(LEFT, RIGHT, TOP).
1697 TEST_F(ShelfLayoutManagerTest, MAYBE_SetAlignment) {
1698 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1699 // Force an initial layout.
1700 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1701 shelf->LayoutShelf();
1702 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1704 shelf->SetAlignment(SHELF_ALIGNMENT_LEFT);
1705 gfx::Rect shelf_bounds(
1706 GetShelfWidget()->GetWindowBoundsInScreen());
1707 const gfx::Screen* screen = Shell::GetScreen();
1708 gfx::Display display =
1709 screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1710 ASSERT_NE(-1, display.id());
1711 EXPECT_EQ(shelf->GetIdealBounds().width(),
1712 display.GetWorkAreaInsets().left());
1713 EXPECT_GE(
1714 shelf_bounds.width(),
1715 GetShelfWidget()->GetContentsView()->GetPreferredSize().width());
1716 EXPECT_EQ(SHELF_ALIGNMENT_LEFT, GetSystemTray()->shelf_alignment());
1717 StatusAreaWidget* status_area_widget = GetShelfWidget()->status_area_widget();
1718 gfx::Rect status_bounds(status_area_widget->GetWindowBoundsInScreen());
1719 EXPECT_GE(status_bounds.width(),
1720 status_area_widget->GetContentsView()->GetPreferredSize().width());
1721 EXPECT_EQ(shelf->GetIdealBounds().width(),
1722 display.GetWorkAreaInsets().left());
1723 EXPECT_EQ(0, display.GetWorkAreaInsets().top());
1724 EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
1725 EXPECT_EQ(0, display.GetWorkAreaInsets().right());
1726 EXPECT_EQ(display.bounds().x(), shelf_bounds.x());
1727 EXPECT_EQ(display.bounds().y(), shelf_bounds.y());
1728 EXPECT_EQ(display.bounds().height(), shelf_bounds.height());
1729 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1730 display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1731 EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
1732 display.GetWorkAreaInsets().left());
1733 EXPECT_EQ(ShelfLayoutManager::kAutoHideSize, display.work_area().x());
1735 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1736 shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
1737 display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1738 shelf_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
1739 display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1740 ASSERT_NE(-1, display.id());
1741 EXPECT_EQ(shelf->GetIdealBounds().width(),
1742 display.GetWorkAreaInsets().right());
1743 EXPECT_GE(shelf_bounds.width(),
1744 GetShelfWidget()->GetContentsView()->GetPreferredSize().width());
1745 EXPECT_EQ(SHELF_ALIGNMENT_RIGHT, GetSystemTray()->shelf_alignment());
1746 status_bounds = gfx::Rect(status_area_widget->GetWindowBoundsInScreen());
1747 EXPECT_GE(status_bounds.width(),
1748 status_area_widget->GetContentsView()->GetPreferredSize().width());
1749 EXPECT_EQ(shelf->GetIdealBounds().width(),
1750 display.GetWorkAreaInsets().right());
1751 EXPECT_EQ(0, display.GetWorkAreaInsets().top());
1752 EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
1753 EXPECT_EQ(0, display.GetWorkAreaInsets().left());
1754 EXPECT_EQ(display.work_area().right(), shelf_bounds.x());
1755 EXPECT_EQ(display.bounds().y(), shelf_bounds.y());
1756 EXPECT_EQ(display.bounds().height(), shelf_bounds.height());
1757 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1758 display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1759 EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
1760 display.GetWorkAreaInsets().right());
1761 EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
1762 display.bounds().right() - display.work_area().right());
1764 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1765 shelf->SetAlignment(SHELF_ALIGNMENT_TOP);
1766 display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1767 shelf_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
1768 display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1769 ASSERT_NE(-1, display.id());
1770 EXPECT_EQ(shelf->GetIdealBounds().height(),
1771 display.GetWorkAreaInsets().top());
1772 EXPECT_GE(shelf_bounds.height(),
1773 GetShelfWidget()->GetContentsView()->GetPreferredSize().height());
1774 EXPECT_EQ(SHELF_ALIGNMENT_TOP, GetSystemTray()->shelf_alignment());
1775 status_bounds = gfx::Rect(status_area_widget->GetWindowBoundsInScreen());
1776 EXPECT_GE(status_bounds.height(),
1777 status_area_widget->GetContentsView()->GetPreferredSize().height());
1778 EXPECT_EQ(shelf->GetIdealBounds().height(),
1779 display.GetWorkAreaInsets().top());
1780 EXPECT_EQ(0, display.GetWorkAreaInsets().right());
1781 EXPECT_EQ(0, display.GetWorkAreaInsets().bottom());
1782 EXPECT_EQ(0, display.GetWorkAreaInsets().left());
1783 EXPECT_EQ(display.work_area().y(), shelf_bounds.bottom());
1784 EXPECT_EQ(display.bounds().x(), shelf_bounds.x());
1785 EXPECT_EQ(display.bounds().width(), shelf_bounds.width());
1786 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1787 display = screen->GetDisplayNearestWindow(Shell::GetPrimaryRootWindow());
1788 EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
1789 display.GetWorkAreaInsets().top());
1790 EXPECT_EQ(ShelfLayoutManager::kAutoHideSize,
1791 display.work_area().y() - display.bounds().y());
1794 TEST_F(ShelfLayoutManagerTest, GestureEdgeSwipe) {
1795 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1796 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
1797 views::Widget* widget = new views::Widget;
1798 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
1799 params.bounds = gfx::Rect(0, 0, 200, 200);
1800 params.context = CurrentContext();
1801 widget->Init(params);
1802 widget->Show();
1803 widget->Maximize();
1805 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1807 aura::Window* window = widget->GetNativeWindow();
1808 shelf->LayoutShelf();
1810 gfx::Rect shelf_shown = GetShelfWidget()->GetWindowBoundsInScreen();
1811 gfx::Rect bounds_shelf = window->bounds();
1813 // Edge swipe when SHELF_VISIBLE should not change visibility state.
1814 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1815 generator.GestureEdgeSwipe();
1816 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1818 // Edge swipe when AUTO_HIDE_HIDDEN should change to AUTO_HIDE_SHOWN.
1819 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1820 shelf->LayoutShelf();
1821 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1822 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1823 generator.GestureEdgeSwipe();
1824 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1825 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1827 widget->SetFullscreen(true);
1828 wm::GetWindowState(window)->set_hide_shelf_when_fullscreen(false);
1829 shelf->UpdateVisibilityState();
1831 // Edge swipe in fullscreen + AUTO_HIDE_HIDDEN should show the shelf and
1832 // remain fullscreen.
1833 EXPECT_TRUE(widget->IsFullscreen());
1834 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1835 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1836 generator.GestureEdgeSwipe();
1837 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1838 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1839 EXPECT_TRUE(widget->IsFullscreen());
1842 #if defined(OS_WIN)
1843 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
1844 #define MAYBE_GestureDrag DISABLED_GestureDrag
1845 #else
1846 #define MAYBE_GestureDrag GestureDrag
1847 #endif
1849 TEST_F(ShelfLayoutManagerTest, MAYBE_GestureDrag) {
1850 // Slop is an implementation detail of gesture recognition, and complicates
1851 // these tests. Ignore it.
1852 ui::GestureConfiguration::GetInstance()
1853 ->set_max_touch_move_in_pixels_for_click(0);
1854 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1856 SCOPED_TRACE("BOTTOM");
1857 RunGestureDragTests(gfx::Vector2d(0, 120));
1861 SCOPED_TRACE("LEFT");
1862 shelf->SetAlignment(SHELF_ALIGNMENT_LEFT);
1863 RunGestureDragTests(gfx::Vector2d(-120, 0));
1867 SCOPED_TRACE("RIGHT");
1868 shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
1869 RunGestureDragTests(gfx::Vector2d(120, 0));
1873 TEST_F(ShelfLayoutManagerTest, WindowVisibilityDisablesAutoHide) {
1874 if (!SupportsMultipleDisplays())
1875 return;
1877 UpdateDisplay("800x600,800x600");
1878 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1879 shelf->LayoutShelf();
1880 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1882 // Create a visible window so auto-hide behavior is enforced
1883 views::Widget* dummy = CreateTestWidget();
1885 // Window visible => auto hide behaves normally.
1886 shelf->UpdateVisibilityState();
1887 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1889 // Window minimized => auto hide disabled.
1890 dummy->Minimize();
1891 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1893 // Window closed => auto hide disabled.
1894 dummy->CloseNow();
1895 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1897 // Multiple window test
1898 views::Widget* window1 = CreateTestWidget();
1899 views::Widget* window2 = CreateTestWidget();
1901 // both visible => normal autohide
1902 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1904 // either minimzed => normal autohide
1905 window2->Minimize();
1906 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1907 window2->Restore();
1908 window1->Minimize();
1909 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1911 // both minimized => disable auto hide
1912 window2->Minimize();
1913 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1915 // Test moving windows to/from other display.
1916 window2->Restore();
1917 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1918 // Move to second display.
1919 window2->SetBounds(gfx::Rect(850, 50, 50, 50));
1920 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1921 // Move back to primary display.
1922 window2->SetBounds(gfx::Rect(50, 50, 50, 50));
1923 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1926 // Test that the shelf animates back to its normal position upon a user
1927 // completing a gesture drag.
1928 TEST_F(ShelfLayoutManagerTest, ShelfAnimatesWhenGestureComplete) {
1929 if (!SupportsHostWindowResize())
1930 return;
1932 // Test the shelf animates back to its original visible bounds when it is
1933 // dragged when there are no visible windows.
1934 ShelfLayoutManager* shelf = GetShelfLayoutManager();
1935 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1936 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1937 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1938 gfx::Rect visible_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
1940 // Enable animations so that we can make sure that they occur.
1941 ui::ScopedAnimationDurationScaleMode regular_animations(
1942 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1944 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1945 gfx::Rect shelf_bounds_in_screen =
1946 GetShelfWidget()->GetWindowBoundsInScreen();
1947 gfx::Point start(shelf_bounds_in_screen.CenterPoint());
1948 gfx::Point end(start.x(), shelf_bounds_in_screen.bottom());
1949 generator.GestureScrollSequence(start, end,
1950 base::TimeDelta::FromMilliseconds(10), 5);
1951 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1952 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
1954 ShelfAnimationWaiter waiter(visible_bounds);
1955 // Wait till the animation completes and check that it occurred.
1956 waiter.WaitTillDoneAnimating();
1957 EXPECT_TRUE(waiter.WasValidAnimation());
1960 // Create a visible window so auto-hide behavior is enforced.
1961 CreateTestWidget();
1963 // Get the bounds of the shelf when it is hidden.
1964 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1965 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1966 gfx::Rect auto_hidden_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
1969 // Enable the animations so that we can make sure they do occur.
1970 ui::ScopedAnimationDurationScaleMode regular_animations(
1971 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1973 gfx::Point start =
1974 GetShelfWidget()->GetWindowBoundsInScreen().CenterPoint();
1975 gfx::Point end(start.x(), start.y() - 100);
1976 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
1978 // Test that the shelf animates to the visible bounds after a swipe up on
1979 // the auto hidden shelf.
1980 generator.GestureScrollSequence(start, end,
1981 base::TimeDelta::FromMilliseconds(10), 1);
1982 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1983 ShelfAnimationWaiter waiter1(visible_bounds);
1984 waiter1.WaitTillDoneAnimating();
1985 EXPECT_TRUE(waiter1.WasValidAnimation());
1987 // Test that the shelf animates to the auto hidden bounds after a swipe up
1988 // on the visible shelf.
1989 EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
1990 generator.GestureScrollSequence(start, end,
1991 base::TimeDelta::FromMilliseconds(10), 1);
1992 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
1993 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
1994 ShelfAnimationWaiter waiter2(auto_hidden_bounds);
1995 waiter2.WaitTillDoneAnimating();
1996 EXPECT_TRUE(waiter2.WasValidAnimation());
2000 TEST_F(ShelfLayoutManagerTest, ShelfFlickerOnTrayActivation) {
2001 ShelfLayoutManager* shelf = GetShelfLayoutManager();
2003 // Create a visible window so auto-hide behavior is enforced.
2004 CreateTestWidget();
2006 // Turn on auto-hide for the shelf.
2007 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
2008 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
2009 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
2011 // Show the status menu. That should make the shelf visible again.
2012 Shell::GetInstance()->accelerator_controller()->PerformActionIfEnabled(
2013 SHOW_SYSTEM_TRAY_BUBBLE);
2014 EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
2015 EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
2016 EXPECT_TRUE(GetSystemTray()->HasSystemBubble());
2019 TEST_F(ShelfLayoutManagerTest, WorkAreaChangeWorkspace) {
2020 // Make sure the shelf is always visible.
2021 ShelfLayoutManager* shelf = GetShelfLayoutManager();
2022 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
2023 shelf->LayoutShelf();
2025 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
2026 params.bounds = gfx::Rect(0, 0, 200, 200);
2027 params.context = CurrentContext();
2028 views::Widget* widget_one = CreateTestWidgetWithParams(params);
2029 widget_one->Maximize();
2031 views::Widget* widget_two = CreateTestWidgetWithParams(params);
2032 widget_two->Maximize();
2033 widget_two->Activate();
2035 // Both windows are maximized. They should be of the same size.
2036 EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
2037 widget_two->GetNativeWindow()->bounds().ToString());
2038 int area_when_shelf_shown =
2039 widget_one->GetNativeWindow()->bounds().size().GetArea();
2041 // Now hide the shelf.
2042 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
2044 // Both windows should be resized according to the shelf status.
2045 EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
2046 widget_two->GetNativeWindow()->bounds().ToString());
2047 // Resized to small.
2048 EXPECT_LT(area_when_shelf_shown,
2049 widget_one->GetNativeWindow()->bounds().size().GetArea());
2051 // Now show the shelf.
2052 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
2054 // Again both windows should be of the same size.
2055 EXPECT_EQ(widget_one->GetNativeWindow()->bounds().ToString(),
2056 widget_two->GetNativeWindow()->bounds().ToString());
2057 EXPECT_EQ(area_when_shelf_shown,
2058 widget_one->GetNativeWindow()->bounds().size().GetArea());
2061 // Confirm that the shelf is dimmed only when content is maximized and
2062 // shelf is not autohidden.
2063 TEST_F(ShelfLayoutManagerTest, Dimming) {
2064 GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
2065 scoped_ptr<aura::Window> w1(CreateTestWindow());
2066 w1->Show();
2067 wm::ActivateWindow(w1.get());
2069 // Normal window doesn't dim shelf.
2070 w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
2071 ShelfWidget* shelf = GetShelfWidget();
2072 EXPECT_FALSE(shelf->GetDimsShelf());
2074 // Maximized window does.
2075 w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
2076 EXPECT_TRUE(shelf->GetDimsShelf());
2078 // Change back to normal stops dimming.
2079 w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
2080 EXPECT_FALSE(shelf->GetDimsShelf());
2082 // Changing back to maximized dims again.
2083 w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
2084 EXPECT_TRUE(shelf->GetDimsShelf());
2086 // Changing shelf to autohide stops dimming.
2087 GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
2088 EXPECT_FALSE(shelf->GetDimsShelf());
2091 // Make sure that the shelf will not hide if the mouse is between a bubble and
2092 // the shelf.
2093 TEST_F(ShelfLayoutManagerTest, BubbleEnlargesShelfMouseHitArea) {
2094 ShelfLayoutManager* shelf = GetShelfLayoutManager();
2095 StatusAreaWidget* status_area_widget =
2096 Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget();
2097 SystemTray* tray = GetSystemTray();
2099 // Create a visible window so auto-hide behavior is enforced.
2100 CreateTestWidget();
2102 shelf->LayoutShelf();
2103 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
2105 // Make two iterations - first without a message bubble which should make
2106 // the shelf disappear and then with a message bubble which should keep it
2107 // visible.
2108 for (int i = 0; i < 2; i++) {
2109 // Make sure the shelf is visible and position the mouse over it. Then
2110 // allow auto hide.
2111 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
2112 EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2113 gfx::Point center =
2114 status_area_widget->GetWindowBoundsInScreen().CenterPoint();
2115 generator.MoveMouseTo(center.x(), center.y());
2116 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
2117 EXPECT_TRUE(shelf->IsVisible());
2118 if (!i) {
2119 // In our first iteration we make sure there is no bubble.
2120 tray->CloseSystemBubble();
2121 EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2122 } else {
2123 // In our second iteration we show a bubble.
2124 TestItem *item = new TestItem;
2125 tray->AddTrayItem(item);
2126 tray->ShowNotificationView(item);
2127 EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
2129 // Move the pointer over the edge of the shelf.
2130 generator.MoveMouseTo(
2131 center.x(), status_area_widget->GetWindowBoundsInScreen().y() - 8);
2132 shelf->UpdateVisibilityState();
2133 if (i) {
2134 EXPECT_TRUE(shelf->IsVisible());
2135 EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
2136 } else {
2137 EXPECT_FALSE(shelf->IsVisible());
2138 EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2143 TEST_F(ShelfLayoutManagerTest, ShelfBackgroundColor) {
2144 EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
2146 scoped_ptr<aura::Window> w1(CreateTestWindow());
2147 w1->Show();
2148 wm::ActivateWindow(w1.get());
2149 EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
2150 w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
2151 EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
2153 scoped_ptr<aura::Window> w2(CreateTestWindow());
2154 w2->Show();
2155 wm::ActivateWindow(w2.get());
2156 // Overlaps with shelf.
2157 w2->SetBounds(GetShelfLayoutManager()->GetIdealBounds());
2159 // Still background is 'maximized'.
2160 EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
2162 w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
2163 EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
2164 w2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
2165 EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
2167 w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
2168 EXPECT_EQ(SHELF_BACKGROUND_MAXIMIZED, GetShelfWidget()->GetBackgroundType());
2169 w1.reset();
2170 EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
2173 // Verify that the shelf doesn't have the opaque background if it's auto-hide
2174 // status.
2175 TEST_F(ShelfLayoutManagerTest, ShelfBackgroundColorAutoHide) {
2176 EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget ()->GetBackgroundType());
2178 GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
2179 scoped_ptr<aura::Window> w1(CreateTestWindow());
2180 w1->Show();
2181 wm::ActivateWindow(w1.get());
2182 EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
2183 w1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
2184 EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
2187 #if defined(OS_CHROMEOS)
2188 #define MAYBE_StatusAreaHitBoxCoversEdge StatusAreaHitBoxCoversEdge
2189 #else
2190 #define MAYBE_StatusAreaHitBoxCoversEdge DISABLED_StatusAreaHitBoxCoversEdge
2191 #endif
2193 // Verify the hit bounds of the status area extend to the edge of the shelf.
2194 TEST_F(ShelfLayoutManagerTest, MAYBE_StatusAreaHitBoxCoversEdge) {
2195 UpdateDisplay("400x400");
2196 ShelfLayoutManager* shelf = GetShelfLayoutManager();
2197 StatusAreaWidget* status_area_widget =
2198 Shell::GetPrimaryRootWindowController()->shelf()->status_area_widget();
2199 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
2200 generator.MoveMouseTo(399,399);
2202 // Test bottom right pixel for bottom alignment.
2203 EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2204 generator.ClickLeftButton();
2205 EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
2206 generator.ClickLeftButton();
2207 EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2209 // Test bottom right pixel for right alignment.
2210 shelf->SetAlignment(SHELF_ALIGNMENT_RIGHT);
2211 EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2212 generator.ClickLeftButton();
2213 EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
2214 generator.ClickLeftButton();
2215 EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2217 // Test bottom left pixel for left alignment.
2218 generator.MoveMouseTo(0, 399);
2219 shelf->SetAlignment(SHELF_ALIGNMENT_LEFT);
2220 EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2221 generator.ClickLeftButton();
2222 EXPECT_TRUE(status_area_widget->IsMessageBubbleShown());
2223 generator.ClickLeftButton();
2224 EXPECT_FALSE(status_area_widget->IsMessageBubbleShown());
2227 // Tests that when the auto-hide behaviour is changed during an animation the
2228 // target bounds are updated to reflect the new state.
2229 TEST_F(ShelfLayoutManagerTest,
2230 ShelfAutoHideToggleDuringAnimationUpdatesBounds) {
2231 ShelfLayoutManager* shelf_manager = GetShelfLayoutManager();
2232 aura::Window* status_window = GetShelfWidget()->status_area_widget()->
2233 GetNativeView();
2234 gfx::Rect initial_bounds = status_window->bounds();
2236 ui::ScopedAnimationDurationScaleMode regular_animations(
2237 ui::ScopedAnimationDurationScaleMode::SLOW_DURATION);
2238 shelf_manager->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
2239 gfx::Rect hide_target_bounds = status_window->GetTargetBounds();
2240 EXPECT_GT(hide_target_bounds.y(), initial_bounds.y());
2242 shelf_manager->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
2243 gfx::Rect reshow_target_bounds = status_window->GetTargetBounds();
2244 EXPECT_EQ(initial_bounds, reshow_target_bounds);
2247 // Tests that during shutdown, that window activation changes are properly
2248 // handled, and do not crash (crbug.com/458768)
2249 TEST_F(ShelfLayoutManagerTest, ShutdownHandlesWindowActivation) {
2250 ShelfLayoutManager* shelf_manager = GetShelfLayoutManager();
2251 ShelfWidget* shelf = GetShelfWidget();
2252 shelf_manager->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
2254 aura::Window* window1 = CreateTestWindowInShellWithId(0);
2255 window1->SetBounds(gfx::Rect(0, 0, 100, 100));
2256 window1->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
2257 window1->Show();
2258 scoped_ptr<aura::Window> window2(CreateTestWindowInShellWithId(0));
2259 window2->SetBounds(gfx::Rect(0, 0, 100, 100));
2260 window2->Show();
2261 wm::ActivateWindow(window1);
2263 shelf->ShutdownStatusAreaWidget();
2264 shelf_manager->PrepareForShutdown();
2266 // Deleting a focused maximized window will switch focus to |window2|. This
2267 // would normally cause the ShelfLayoutManager to update its state. However
2268 // during shutdown we want to handle this without crashing.
2269 delete window1;
2272 } // namespace ash