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