Home | History | Annotate | Download | only in wm
      1 // Copyright 2013 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/wm/immersive_fullscreen_controller.h"
      6 
      7 #include "ash/display/display_manager.h"
      8 #include "ash/display/mouse_cursor_event_filter.h"
      9 #include "ash/root_window_controller.h"
     10 #include "ash/shelf/shelf_layout_manager.h"
     11 #include "ash/shelf/shelf_types.h"
     12 #include "ash/shell.h"
     13 #include "ash/test/ash_test_base.h"
     14 #include "ash/wm/window_state.h"
     15 #include "ui/aura/client/aura_constants.h"
     16 #include "ui/aura/client/cursor_client.h"
     17 #include "ui/aura/env.h"
     18 #include "ui/aura/test/test_window_delegate.h"
     19 #include "ui/aura/window.h"
     20 #include "ui/aura/window_event_dispatcher.h"
     21 #include "ui/events/event_utils.h"
     22 #include "ui/events/test/event_generator.h"
     23 #include "ui/events/test/test_event_handler.h"
     24 #include "ui/gfx/animation/slide_animation.h"
     25 #include "ui/views/bubble/bubble_delegate.h"
     26 #include "ui/views/controls/native/native_view_host.h"
     27 #include "ui/views/view.h"
     28 #include "ui/views/widget/widget.h"
     29 
     30 namespace ash {
     31 
     32 namespace {
     33 
     34 class MockImmersiveFullscreenControllerDelegate
     35     : public ImmersiveFullscreenController::Delegate {
     36  public:
     37   MockImmersiveFullscreenControllerDelegate(views::View* top_container_view)
     38       : top_container_view_(top_container_view),
     39         enabled_(false),
     40         visible_fraction_(1) {
     41   }
     42   virtual ~MockImmersiveFullscreenControllerDelegate() {}
     43 
     44   // ImmersiveFullscreenController::Delegate overrides:
     45   virtual void OnImmersiveRevealStarted() OVERRIDE {
     46     enabled_ = true;
     47     visible_fraction_ = 0;
     48   }
     49   virtual void OnImmersiveRevealEnded() OVERRIDE {
     50     visible_fraction_ = 0;
     51   }
     52   virtual void OnImmersiveFullscreenExited() OVERRIDE {
     53     enabled_ = false;
     54     visible_fraction_ = 1;
     55   }
     56   virtual void SetVisibleFraction(double visible_fraction) OVERRIDE {
     57     visible_fraction_ = visible_fraction;
     58   }
     59   virtual std::vector<gfx::Rect> GetVisibleBoundsInScreen() const OVERRIDE {
     60     std::vector<gfx::Rect> bounds_in_screen;
     61     bounds_in_screen.push_back(top_container_view_->GetBoundsInScreen());
     62     return bounds_in_screen;
     63   }
     64 
     65   bool is_enabled() const {
     66     return enabled_;
     67   }
     68 
     69   double visible_fraction() const {
     70     return visible_fraction_;
     71   }
     72 
     73  private:
     74   views::View* top_container_view_;
     75   bool enabled_;
     76   double visible_fraction_;
     77 
     78   DISALLOW_COPY_AND_ASSIGN(MockImmersiveFullscreenControllerDelegate);
     79 };
     80 
     81 class ConsumeEventHandler : public ui::test::TestEventHandler {
     82  public:
     83   ConsumeEventHandler() {}
     84   virtual ~ConsumeEventHandler() {}
     85 
     86  private:
     87   virtual void OnEvent(ui::Event* event) OVERRIDE {
     88     ui::test::TestEventHandler::OnEvent(event);
     89     if (event->cancelable())
     90       event->SetHandled();
     91   }
     92 
     93   DISALLOW_COPY_AND_ASSIGN(ConsumeEventHandler);
     94 };
     95 
     96 }  // namespace
     97 
     98 /////////////////////////////////////////////////////////////////////////////
     99 
    100 class ImmersiveFullscreenControllerTest : public ash::test::AshTestBase {
    101  public:
    102   enum Modality {
    103     MODALITY_MOUSE,
    104     MODALITY_GESTURE_TAP,
    105     MODALITY_GESTURE_SCROLL
    106   };
    107 
    108   ImmersiveFullscreenControllerTest()
    109       : widget_(NULL),
    110         top_container_(NULL),
    111         content_view_(NULL) {}
    112   virtual ~ImmersiveFullscreenControllerTest() {}
    113 
    114   ImmersiveFullscreenController* controller() {
    115     return controller_.get();
    116   }
    117 
    118   views::NativeViewHost* content_view() {
    119     return content_view_;
    120   }
    121 
    122   views::View* top_container() {
    123     return top_container_;
    124   }
    125 
    126   views::Widget* widget() { return widget_; }
    127 
    128   aura::Window* window() {
    129     return widget_->GetNativeWindow();
    130   }
    131 
    132   MockImmersiveFullscreenControllerDelegate* delegate() {
    133     return delegate_.get();
    134   }
    135 
    136   // Access to private data from the controller.
    137   bool top_edge_hover_timer_running() const {
    138     return controller_->top_edge_hover_timer_.IsRunning();
    139   }
    140   int mouse_x_when_hit_top() const {
    141     return controller_->mouse_x_when_hit_top_in_screen_;
    142   }
    143 
    144   // ash::test::AshTestBase overrides:
    145   virtual void SetUp() OVERRIDE {
    146     ash::test::AshTestBase::SetUp();
    147 
    148     widget_ = new views::Widget();
    149     views::Widget::InitParams params;
    150     params.context = CurrentContext();
    151     widget_->Init(params);
    152     widget_->Show();
    153 
    154     window()->SetProperty(aura::client::kShowStateKey,
    155                           ui::SHOW_STATE_FULLSCREEN);
    156 
    157     gfx::Size window_size = widget_->GetWindowBoundsInScreen().size();
    158     content_view_ = new views::NativeViewHost();
    159     content_view_->SetBounds(0, 0, window_size.width(), window_size.height());
    160     widget_->GetContentsView()->AddChildView(content_view_);
    161 
    162     top_container_ = new views::View();
    163     top_container_->SetBounds(
    164         0, 0, window_size.width(), 100);
    165     top_container_->SetFocusable(true);
    166     widget_->GetContentsView()->AddChildView(top_container_);
    167 
    168     delegate_.reset(
    169         new MockImmersiveFullscreenControllerDelegate(top_container_));
    170     controller_.reset(new ImmersiveFullscreenController);
    171     controller_->Init(delegate_.get(), widget_, top_container_);
    172     controller_->SetupForTest();
    173 
    174     // The mouse is moved so that it is not over |top_container_| by
    175     // AshTestBase.
    176   }
    177 
    178   // Enables / disables immersive fullscreen.
    179   void SetEnabled(bool enabled) {
    180     controller_->SetEnabled(ImmersiveFullscreenController::WINDOW_TYPE_OTHER,
    181                             enabled);
    182   }
    183 
    184   // Attempt to reveal the top-of-window views via |modality|.
    185   // The top-of-window views can only be revealed via mouse hover or a gesture.
    186   void AttemptReveal(Modality modality) {
    187     ASSERT_NE(modality, MODALITY_GESTURE_TAP);
    188     AttemptRevealStateChange(true, modality);
    189   }
    190 
    191   // Attempt to unreveal the top-of-window views via |modality|. The
    192   // top-of-window views can be unrevealed via any modality.
    193   void AttemptUnreveal(Modality modality) {
    194     AttemptRevealStateChange(false, modality);
    195   }
    196 
    197   // Sets whether the mouse is hovered above |top_container_|.
    198   // SetHovered(true) moves the mouse over the |top_container_| but does not
    199   // move it to the top of the screen so will not initiate a reveal.
    200   void SetHovered(bool is_mouse_hovered) {
    201     MoveMouse(0, is_mouse_hovered ? 10 : top_container_->height() + 100);
    202   }
    203 
    204   // Move the mouse to the given coordinates. The coordinates should be in
    205   // |top_container_| coordinates.
    206   void MoveMouse(int x, int y) {
    207     gfx::Point screen_position(x, y);
    208     views::View::ConvertPointToScreen(top_container_, &screen_position);
    209     GetEventGenerator().MoveMouseTo(screen_position.x(), screen_position.y());
    210 
    211     // If the top edge timer started running as a result of the mouse move, run
    212     // the task which occurs after the timer delay. This reveals the
    213     // top-of-window views synchronously if the mouse is hovered at the top of
    214     // the screen.
    215     if (controller()->top_edge_hover_timer_.IsRunning()) {
    216       controller()->top_edge_hover_timer_.user_task().Run();
    217       controller()->top_edge_hover_timer_.Stop();
    218     }
    219   }
    220 
    221  private:
    222   // Attempt to change the revealed state to |revealed| via |modality|.
    223   void AttemptRevealStateChange(bool revealed, Modality modality) {
    224     // Compute the event position in |top_container_| coordinates.
    225     gfx::Point event_position(0, revealed ? 0 : top_container_->height() + 100);
    226     switch (modality) {
    227       case MODALITY_MOUSE: {
    228         MoveMouse(event_position.x(), event_position.y());
    229         break;
    230       }
    231       case MODALITY_GESTURE_TAP: {
    232         gfx::Point screen_position = event_position;
    233         views::View::ConvertPointToScreen(top_container_, &screen_position);
    234         ui::test::EventGenerator& event_generator(GetEventGenerator());
    235         event_generator.MoveTouch(event_position);
    236         event_generator.PressTouch();
    237         event_generator.ReleaseTouch();
    238         break;
    239       }
    240       case MODALITY_GESTURE_SCROLL: {
    241         gfx::Point start(0, revealed ? 0 : top_container_->height() - 2);
    242         gfx::Vector2d scroll_delta(0, 40);
    243         gfx::Point end = revealed ? start + scroll_delta : start - scroll_delta;
    244         views::View::ConvertPointToScreen(top_container_, &start);
    245         views::View::ConvertPointToScreen(top_container_, &end);
    246         ui::test::EventGenerator& event_generator(GetEventGenerator());
    247         event_generator.GestureScrollSequence(
    248             start, end,
    249             base::TimeDelta::FromMilliseconds(30), 1);
    250         break;
    251       }
    252     }
    253   }
    254 
    255   scoped_ptr<ImmersiveFullscreenController> controller_;
    256   scoped_ptr<MockImmersiveFullscreenControllerDelegate> delegate_;
    257   views::Widget* widget_;  // Owned by the native widget.
    258   views::View* top_container_;  // Owned by |widget_|'s root-view.
    259   views::NativeViewHost* content_view_;  // Owned by |widget_|'s root-view.
    260 
    261   DISALLOW_COPY_AND_ASSIGN(ImmersiveFullscreenControllerTest);
    262 };
    263 
    264 // Test the initial state and that the delegate gets notified of the
    265 // top-of-window views getting hidden and revealed.
    266 TEST_F(ImmersiveFullscreenControllerTest, Delegate) {
    267   // Initial state.
    268   EXPECT_FALSE(controller()->IsEnabled());
    269   EXPECT_FALSE(controller()->IsRevealed());
    270   EXPECT_FALSE(delegate()->is_enabled());
    271 
    272   // Enabling initially hides the top views.
    273   SetEnabled(true);
    274   EXPECT_TRUE(controller()->IsEnabled());
    275   EXPECT_FALSE(controller()->IsRevealed());
    276   EXPECT_TRUE(delegate()->is_enabled());
    277   EXPECT_EQ(0, delegate()->visible_fraction());
    278 
    279   // Revealing shows the top views.
    280   AttemptReveal(MODALITY_MOUSE);
    281   EXPECT_TRUE(controller()->IsEnabled());
    282   EXPECT_TRUE(controller()->IsRevealed());
    283   EXPECT_TRUE(delegate()->is_enabled());
    284   EXPECT_EQ(1, delegate()->visible_fraction());
    285 
    286   // Disabling ends the immersive reveal.
    287   SetEnabled(false);
    288   EXPECT_FALSE(controller()->IsEnabled());
    289   EXPECT_FALSE(controller()->IsRevealed());
    290   EXPECT_FALSE(delegate()->is_enabled());
    291 }
    292 
    293 // GetRevealedLock() specific tests.
    294 TEST_F(ImmersiveFullscreenControllerTest, RevealedLock) {
    295   scoped_ptr<ImmersiveRevealedLock> lock1;
    296   scoped_ptr<ImmersiveRevealedLock> lock2;
    297 
    298   // Immersive fullscreen is not on by default.
    299   EXPECT_FALSE(controller()->IsEnabled());
    300 
    301   // 1) Test acquiring and releasing a revealed state lock while immersive
    302   // fullscreen is disabled. Acquiring or releasing the lock should have no
    303   // effect till immersive fullscreen is enabled.
    304   lock1.reset(controller()->GetRevealedLock(
    305       ImmersiveFullscreenController::ANIMATE_REVEAL_NO));
    306   EXPECT_FALSE(controller()->IsEnabled());
    307   EXPECT_FALSE(controller()->IsRevealed());
    308 
    309   // Immersive fullscreen should start in the revealed state due to the lock.
    310   SetEnabled(true);
    311   EXPECT_TRUE(controller()->IsEnabled());
    312   EXPECT_TRUE(controller()->IsRevealed());
    313 
    314   SetEnabled(false);
    315   EXPECT_FALSE(controller()->IsEnabled());
    316   EXPECT_FALSE(controller()->IsRevealed());
    317 
    318   lock1.reset();
    319   EXPECT_FALSE(controller()->IsEnabled());
    320   EXPECT_FALSE(controller()->IsRevealed());
    321 
    322   // Immersive fullscreen should start in the closed state because the lock is
    323   // no longer held.
    324   SetEnabled(true);
    325   EXPECT_TRUE(controller()->IsEnabled());
    326   EXPECT_FALSE(controller()->IsRevealed());
    327 
    328   // 2) Test that acquiring a lock reveals the top-of-window views if they are
    329   // hidden.
    330   lock1.reset(controller()->GetRevealedLock(
    331       ImmersiveFullscreenController::ANIMATE_REVEAL_NO));
    332   EXPECT_TRUE(controller()->IsRevealed());
    333 
    334   // 3) Test that the top-of-window views are only hidden when all of the locks
    335   // are released.
    336   lock2.reset(controller()->GetRevealedLock(
    337       ImmersiveFullscreenController::ANIMATE_REVEAL_NO));
    338   lock1.reset();
    339   EXPECT_TRUE(controller()->IsRevealed());
    340 
    341   lock2.reset();
    342   EXPECT_FALSE(controller()->IsRevealed());
    343 }
    344 
    345 // Test mouse event processing for top-of-screen reveal triggering.
    346 TEST_F(ImmersiveFullscreenControllerTest, OnMouseEvent) {
    347   // Set up initial state.
    348   SetEnabled(true);
    349   ASSERT_TRUE(controller()->IsEnabled());
    350   ASSERT_FALSE(controller()->IsRevealed());
    351 
    352   ui::test::EventGenerator& event_generator(GetEventGenerator());
    353 
    354   gfx::Rect top_container_bounds_in_screen =
    355       top_container()->GetBoundsInScreen();
    356   // A position along the top edge of TopContainerView in screen coordinates.
    357   gfx::Point top_edge_pos(top_container_bounds_in_screen.x() + 100,
    358                           top_container_bounds_in_screen.y());
    359 
    360   // Mouse wheel event does nothing.
    361   ui::MouseEvent wheel(
    362       ui::ET_MOUSEWHEEL, top_edge_pos, top_edge_pos, ui::EF_NONE, ui::EF_NONE);
    363   event_generator.Dispatch(&wheel);
    364   EXPECT_FALSE(top_edge_hover_timer_running());
    365 
    366   // Move to top edge of screen starts hover timer running. We cannot use
    367   // MoveMouse() because MoveMouse() stops the timer if it started running.
    368   event_generator.MoveMouseTo(top_edge_pos);
    369   EXPECT_TRUE(top_edge_hover_timer_running());
    370   EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top());
    371 
    372   // Moving |ImmersiveFullscreenControllerTest::kMouseRevealBoundsHeight| down
    373   // from the top edge stops it.
    374   event_generator.MoveMouseBy(0,
    375       ImmersiveFullscreenController::kMouseRevealBoundsHeight);
    376   EXPECT_FALSE(top_edge_hover_timer_running());
    377 
    378   // Moving back to the top starts the timer again.
    379   event_generator.MoveMouseTo(top_edge_pos);
    380   EXPECT_TRUE(top_edge_hover_timer_running());
    381   EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top());
    382 
    383   // Slight move to the right keeps the timer running for the same hit point.
    384   event_generator.MoveMouseBy(1, 0);
    385   EXPECT_TRUE(top_edge_hover_timer_running());
    386   EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top());
    387 
    388   // Moving back to the left also keeps the timer running.
    389   event_generator.MoveMouseBy(-1, 0);
    390   EXPECT_TRUE(top_edge_hover_timer_running());
    391   EXPECT_EQ(top_edge_pos.x(), mouse_x_when_hit_top());
    392 
    393   // Large move right restarts the timer (so it is still running) and considers
    394   // this a new hit at the top.
    395   event_generator.MoveMouseTo(top_edge_pos.x() + 100, top_edge_pos.y());
    396   EXPECT_TRUE(top_edge_hover_timer_running());
    397   EXPECT_EQ(top_edge_pos.x() + 100, mouse_x_when_hit_top());
    398 
    399   // Moving off the top edge horizontally stops the timer.
    400   event_generator.MoveMouseTo(top_container_bounds_in_screen.right() + 1,
    401                               top_container_bounds_in_screen.y());
    402   EXPECT_FALSE(top_edge_hover_timer_running());
    403 
    404   // Once revealed, a move just a little below the top container doesn't end a
    405   // reveal.
    406   AttemptReveal(MODALITY_MOUSE);
    407   event_generator.MoveMouseTo(top_container_bounds_in_screen.x(),
    408                               top_container_bounds_in_screen.bottom() + 1);
    409   EXPECT_TRUE(controller()->IsRevealed());
    410 
    411   // Once revealed, clicking just below the top container ends the reveal.
    412   event_generator.ClickLeftButton();
    413   EXPECT_FALSE(controller()->IsRevealed());
    414 
    415   // Moving a lot below the top container ends a reveal.
    416   AttemptReveal(MODALITY_MOUSE);
    417   EXPECT_TRUE(controller()->IsRevealed());
    418   event_generator.MoveMouseTo(top_container_bounds_in_screen.x(),
    419                               top_container_bounds_in_screen.bottom() + 50);
    420   EXPECT_FALSE(controller()->IsRevealed());
    421 
    422   // The mouse position cannot cause a reveal when the top container's widget
    423   // has capture.
    424   views::Widget* widget = top_container()->GetWidget();
    425   widget->SetCapture(top_container());
    426   AttemptReveal(MODALITY_MOUSE);
    427   EXPECT_FALSE(controller()->IsRevealed());
    428   widget->ReleaseCapture();
    429 
    430   // The mouse position cannot end the reveal while the top container's widget
    431   // has capture.
    432   AttemptReveal(MODALITY_MOUSE);
    433   EXPECT_TRUE(controller()->IsRevealed());
    434   widget->SetCapture(top_container());
    435   event_generator.MoveMouseTo(top_container_bounds_in_screen.x(),
    436                               top_container_bounds_in_screen.bottom() + 51);
    437   EXPECT_TRUE(controller()->IsRevealed());
    438 
    439   // Releasing capture should end the reveal.
    440   widget->ReleaseCapture();
    441   EXPECT_FALSE(controller()->IsRevealed());
    442 }
    443 
    444 // Test mouse event processing for top-of-screen reveal triggering when the
    445 // top container's widget is inactive.
    446 TEST_F(ImmersiveFullscreenControllerTest, Inactive) {
    447   // Set up initial state.
    448   views::Widget* popup_widget = views::Widget::CreateWindowWithContextAndBounds(
    449       NULL,
    450       CurrentContext(),
    451       gfx::Rect(0, 0, 200, 200));
    452   popup_widget->Show();
    453   ASSERT_FALSE(top_container()->GetWidget()->IsActive());
    454 
    455   SetEnabled(true);
    456   ASSERT_TRUE(controller()->IsEnabled());
    457   ASSERT_FALSE(controller()->IsRevealed());
    458 
    459   gfx::Rect top_container_bounds_in_screen =
    460       top_container()->GetBoundsInScreen();
    461   gfx::Rect popup_bounds_in_screen = popup_widget->GetWindowBoundsInScreen();
    462   ASSERT_EQ(top_container_bounds_in_screen.origin().ToString(),
    463             popup_bounds_in_screen.origin().ToString());
    464   ASSERT_GT(top_container_bounds_in_screen.right(),
    465             popup_bounds_in_screen.right());
    466 
    467   // The top-of-window views should stay hidden if the cursor is at the top edge
    468   // but above an obscured portion of the top-of-window views.
    469   MoveMouse(popup_bounds_in_screen.x(),
    470             top_container_bounds_in_screen.y());
    471   EXPECT_FALSE(controller()->IsRevealed());
    472 
    473   // The top-of-window views should reveal if the cursor is at the top edge and
    474   // above an unobscured portion of the top-of-window views.
    475   MoveMouse(top_container_bounds_in_screen.right() - 1,
    476             top_container_bounds_in_screen.y());
    477   EXPECT_TRUE(controller()->IsRevealed());
    478 
    479   // The top-of-window views should stay revealed if the cursor is moved off
    480   // of the top edge.
    481   MoveMouse(top_container_bounds_in_screen.right() - 1,
    482             top_container_bounds_in_screen.bottom() - 1);
    483   EXPECT_TRUE(controller()->IsRevealed());
    484 
    485   // Moving way off of the top-of-window views should end the immersive reveal.
    486   MoveMouse(top_container_bounds_in_screen.right() - 1,
    487             top_container_bounds_in_screen.bottom() + 50);
    488   EXPECT_FALSE(controller()->IsRevealed());
    489 
    490   // Moving way off of the top-of-window views in a region where the
    491   // top-of-window views are obscured should also end the immersive reveal.
    492   // Ideally, the immersive reveal would end immediately when the cursor moves
    493   // to an obscured portion of the top-of-window views.
    494   MoveMouse(top_container_bounds_in_screen.right() - 1,
    495             top_container_bounds_in_screen.y());
    496   EXPECT_TRUE(controller()->IsRevealed());
    497   MoveMouse(top_container_bounds_in_screen.x(),
    498             top_container_bounds_in_screen.bottom() + 50);
    499   EXPECT_FALSE(controller()->IsRevealed());
    500 }
    501 
    502 // Test mouse event processing for top-of-screen reveal triggering when the user
    503 // has a vertical display layout (primary display above/below secondary display)
    504 // and the immersive fullscreen window is on the bottom display.
    505 TEST_F(ImmersiveFullscreenControllerTest, MouseEventsVerticalDisplayLayout) {
    506   if (!SupportsMultipleDisplays())
    507     return;
    508 
    509   // Set up initial state.
    510   UpdateDisplay("800x600,800x600");
    511   ash::DisplayLayout display_layout(ash::DisplayLayout::TOP, 0);
    512   ash::Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
    513       display_layout);
    514 
    515   SetEnabled(true);
    516   ASSERT_TRUE(controller()->IsEnabled());
    517   ASSERT_FALSE(controller()->IsRevealed());
    518 
    519   aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows();
    520   ASSERT_EQ(root_windows[0],
    521             top_container()->GetWidget()->GetNativeWindow()->GetRootWindow());
    522 
    523   gfx::Rect primary_root_window_bounds_in_screen =
    524       root_windows[0]->GetBoundsInScreen();
    525   // Do not set |x| to the root window's x position because the display's
    526   // corners have special behavior.
    527   int x = primary_root_window_bounds_in_screen.x() + 10;
    528   // The y position of the top edge of the primary display.
    529   int y_top_edge = primary_root_window_bounds_in_screen.y();
    530 
    531   ui::test::EventGenerator& event_generator(GetEventGenerator());
    532 
    533   // Moving right below the top edge starts the hover timer running. We
    534   // cannot use MoveMouse() because MoveMouse() stops the timer if it started
    535   // running.
    536   event_generator.MoveMouseTo(x, y_top_edge + 1);
    537   EXPECT_TRUE(top_edge_hover_timer_running());
    538   EXPECT_EQ(y_top_edge + 1,
    539             aura::Env::GetInstance()->last_mouse_location().y());
    540 
    541   // The timer should continue running if the user moves the mouse to the top
    542   // edge even though the mouse is warped to the secondary display.
    543   event_generator.MoveMouseTo(x, y_top_edge);
    544   EXPECT_TRUE(top_edge_hover_timer_running());
    545 
    546   // The timer should continue running if the user overshoots the top edge
    547   // a bit.
    548   event_generator.MoveMouseTo(x, y_top_edge - 2);
    549   EXPECT_TRUE(top_edge_hover_timer_running());
    550 
    551   // The timer should stop running if the user overshoots the top edge by
    552   // a lot.
    553   event_generator.MoveMouseTo(x, y_top_edge - 20);
    554   EXPECT_FALSE(top_edge_hover_timer_running());
    555 
    556   // The timer should not start if the user moves the mouse to the bottom of the
    557   // secondary display without crossing the top edge first.
    558   event_generator.MoveMouseTo(x, y_top_edge - 2);
    559 
    560   // Reveal the top-of-window views by overshooting the top edge slightly.
    561   event_generator.MoveMouseTo(x, y_top_edge + 1);
    562   // MoveMouse() runs the timer task.
    563   MoveMouse(x, y_top_edge - 2);
    564   EXPECT_TRUE(controller()->IsRevealed());
    565 
    566   // The top-of-window views should stay revealed if the user moves the mouse
    567   // around in the bottom region of the secondary display.
    568   event_generator.MoveMouseTo(x + 10, y_top_edge - 3);
    569   EXPECT_TRUE(controller()->IsRevealed());
    570 
    571   // The top-of-window views should hide if the user moves the mouse away from
    572   // the bottom region of the secondary display.
    573   event_generator.MoveMouseTo(x, y_top_edge - 20);
    574   EXPECT_FALSE(controller()->IsRevealed());
    575 
    576   // Test that it is possible to reveal the top-of-window views by overshooting
    577   // the top edge slightly when the top container's widget is not active.
    578   views::Widget* popup_widget = views::Widget::CreateWindowWithContextAndBounds(
    579       NULL,
    580       CurrentContext(),
    581       gfx::Rect(0, 200, 100, 100));
    582   popup_widget->Show();
    583   ASSERT_FALSE(top_container()->GetWidget()->IsActive());
    584   ASSERT_FALSE(top_container()->GetBoundsInScreen().Intersects(
    585       popup_widget->GetWindowBoundsInScreen()));
    586   event_generator.MoveMouseTo(x, y_top_edge + 1);
    587   MoveMouse(x, y_top_edge - 2);
    588   EXPECT_TRUE(controller()->IsRevealed());
    589 }
    590 
    591 // Test behavior when the mouse becomes hovered without moving.
    592 TEST_F(ImmersiveFullscreenControllerTest, MouseHoveredWithoutMoving) {
    593   SetEnabled(true);
    594   scoped_ptr<ImmersiveRevealedLock> lock;
    595 
    596   // 1) Test that if the mouse becomes hovered without the mouse moving due to a
    597   // lock causing the top-of-window views to be revealed (and the mouse
    598   // happening to be near the top of the screen), the top-of-window views do not
    599   // hide till the mouse moves off of the top-of-window views.
    600   SetHovered(true);
    601   EXPECT_FALSE(controller()->IsRevealed());
    602   lock.reset(controller()->GetRevealedLock(
    603       ImmersiveFullscreenController::ANIMATE_REVEAL_NO));
    604   EXPECT_TRUE(controller()->IsRevealed());
    605   lock.reset();
    606   EXPECT_TRUE(controller()->IsRevealed());
    607   SetHovered(false);
    608   EXPECT_FALSE(controller()->IsRevealed());
    609 
    610   // 2) Test that if the mouse becomes hovered without moving because of a
    611   // reveal in ImmersiveFullscreenController::SetEnabled(true) and there are no
    612   // locks keeping the top-of-window views revealed, that mouse hover does not
    613   // prevent the top-of-window views from closing.
    614   SetEnabled(false);
    615   SetHovered(true);
    616   EXPECT_FALSE(controller()->IsRevealed());
    617   SetEnabled(true);
    618   EXPECT_FALSE(controller()->IsRevealed());
    619 
    620   // 3) Test that if the mouse becomes hovered without moving because of a
    621   // reveal in ImmersiveFullscreenController::SetEnabled(true) and there is a
    622   // lock keeping the top-of-window views revealed, that the top-of-window views
    623   // do not hide till the mouse moves off of the top-of-window views.
    624   SetEnabled(false);
    625   SetHovered(true);
    626   lock.reset(controller()->GetRevealedLock(
    627       ImmersiveFullscreenController::ANIMATE_REVEAL_NO));
    628   EXPECT_FALSE(controller()->IsRevealed());
    629   SetEnabled(true);
    630   EXPECT_TRUE(controller()->IsRevealed());
    631   lock.reset();
    632   EXPECT_TRUE(controller()->IsRevealed());
    633   SetHovered(false);
    634   EXPECT_FALSE(controller()->IsRevealed());
    635 }
    636 
    637 // Test revealing the top-of-window views using one modality and ending
    638 // the reveal via another. For instance, initiating the reveal via a SWIPE_OPEN
    639 // edge gesture, switching to using the mouse and ending the reveal by moving
    640 // the mouse off of the top-of-window views.
    641 TEST_F(ImmersiveFullscreenControllerTest, DifferentModalityEnterExit) {
    642   SetEnabled(true);
    643   EXPECT_TRUE(controller()->IsEnabled());
    644   EXPECT_FALSE(controller()->IsRevealed());
    645 
    646   // Initiate reveal via gesture, end reveal via mouse.
    647   AttemptReveal(MODALITY_GESTURE_SCROLL);
    648   EXPECT_TRUE(controller()->IsRevealed());
    649   MoveMouse(1, 1);
    650   EXPECT_TRUE(controller()->IsRevealed());
    651   AttemptUnreveal(MODALITY_MOUSE);
    652   EXPECT_FALSE(controller()->IsRevealed());
    653 
    654   // Initiate reveal via gesture, end reveal via touch.
    655   AttemptReveal(MODALITY_GESTURE_SCROLL);
    656   EXPECT_TRUE(controller()->IsRevealed());
    657   AttemptUnreveal(MODALITY_GESTURE_TAP);
    658   EXPECT_FALSE(controller()->IsRevealed());
    659 
    660   // Initiate reveal via mouse, end reveal via gesture.
    661   AttemptReveal(MODALITY_MOUSE);
    662   EXPECT_TRUE(controller()->IsRevealed());
    663   AttemptUnreveal(MODALITY_GESTURE_SCROLL);
    664   EXPECT_FALSE(controller()->IsRevealed());
    665 
    666   // Initiate reveal via mouse, end reveal via touch.
    667   AttemptReveal(MODALITY_MOUSE);
    668   EXPECT_TRUE(controller()->IsRevealed());
    669   AttemptUnreveal(MODALITY_GESTURE_TAP);
    670   EXPECT_FALSE(controller()->IsRevealed());
    671 }
    672 
    673 // Test when the SWIPE_CLOSE edge gesture closes the top-of-window views.
    674 #if defined(OS_WIN)
    675 // On Windows, touch events do not result in mouse events being disabled.  As
    676 // a result, the last part of this test which ends the reveal via a gesture will
    677 // not work correctly.  See crbug.com/332430, and the function
    678 // ShouldHideCursorOnTouch() in compound_event_filter.cc.
    679 #define MAYBE_EndRevealViaGesture DISABLED_EndRevealViaGesture
    680 #else
    681 #define MAYBE_EndRevealViaGesture EndRevealViaGesture
    682 #endif
    683 TEST_F(ImmersiveFullscreenControllerTest, MAYBE_EndRevealViaGesture) {
    684   SetEnabled(true);
    685   EXPECT_TRUE(controller()->IsEnabled());
    686   EXPECT_FALSE(controller()->IsRevealed());
    687 
    688   // A gesture should be able to close the top-of-window views when
    689   // top-of-window views have focus.
    690   AttemptReveal(MODALITY_MOUSE);
    691   top_container()->RequestFocus();
    692   EXPECT_TRUE(controller()->IsRevealed());
    693   AttemptUnreveal(MODALITY_GESTURE_SCROLL);
    694   EXPECT_FALSE(controller()->IsRevealed());
    695 
    696   // The top-of-window views should no longer have focus. Clearing focus is
    697   // important because it closes focus-related popup windows like the touch
    698   // selection handles.
    699   EXPECT_FALSE(top_container()->HasFocus());
    700 
    701   // If some other code is holding onto a lock, a gesture should not be able to
    702   // end the reveal.
    703   AttemptReveal(MODALITY_MOUSE);
    704   scoped_ptr<ImmersiveRevealedLock> lock(controller()->GetRevealedLock(
    705       ImmersiveFullscreenController::ANIMATE_REVEAL_NO));
    706   EXPECT_TRUE(controller()->IsRevealed());
    707   AttemptUnreveal(MODALITY_GESTURE_SCROLL);
    708   EXPECT_TRUE(controller()->IsRevealed());
    709   lock.reset();
    710   EXPECT_FALSE(controller()->IsRevealed());
    711 }
    712 
    713 // Tests that touch-gesture can be used to reveal the top-of-window views when
    714 // the child window consumes all events.
    715 TEST_F(ImmersiveFullscreenControllerTest, RevealViaGestureChildConsumesEvents) {
    716   // Enabling initially hides the top views.
    717   SetEnabled(true);
    718   EXPECT_TRUE(controller()->IsEnabled());
    719   EXPECT_FALSE(controller()->IsRevealed());
    720 
    721   aura::test::TestWindowDelegate child_delegate;
    722   scoped_ptr<aura::Window> child(
    723       CreateTestWindowInShellWithDelegateAndType(&child_delegate,
    724                                                  ui::wm::WINDOW_TYPE_CONTROL,
    725                                                  1234,
    726                                                  gfx::Rect()));
    727   content_view()->Attach(child.get());
    728   child->Show();
    729 
    730   ConsumeEventHandler handler;
    731   child->AddPreTargetHandler(&handler);
    732 
    733   // Reveal the top views using a touch-scroll gesture. The child window should
    734   // not receive the touch events.
    735   AttemptReveal(MODALITY_GESTURE_SCROLL);
    736   EXPECT_TRUE(controller()->IsRevealed());
    737   EXPECT_EQ(0, handler.num_touch_events());
    738 
    739   AttemptUnreveal(MODALITY_GESTURE_TAP);
    740   EXPECT_FALSE(controller()->IsRevealed());
    741   EXPECT_GT(handler.num_touch_events(), 0);
    742   child->RemovePreTargetHandler(&handler);
    743 }
    744 
    745 // Make sure touch events towards the top of the window do not leak through to
    746 // windows underneath.
    747 TEST_F(ImmersiveFullscreenControllerTest, EventsDoNotLeakToWindowUnderneath) {
    748   gfx::Rect window_bounds = window()->GetBoundsInScreen();
    749   aura::test::TestWindowDelegate child_delegate;
    750   scoped_ptr<aura::Window> behind(CreateTestWindowInShellWithDelegate(
    751       &child_delegate, 1234, window_bounds));
    752   behind->Show();
    753   behind->SetBounds(window_bounds);
    754   widget()->StackAbove(behind.get());
    755 
    756   // Make sure the windows are aligned on top.
    757   EXPECT_EQ(behind->GetBoundsInScreen().y(), window()->GetBoundsInScreen().y());
    758   int top = behind->GetBoundsInScreen().y();
    759 
    760   ui::TouchEvent touch(ui::ET_TOUCH_MOVED, gfx::Point(10, top), 0,
    761                        ui::EventTimeForNow());
    762   ui::EventTarget* root = window()->GetRootWindow();
    763   ui::EventTargeter* targeter = root->GetEventTargeter();
    764   EXPECT_EQ(window(), targeter->FindTargetForEvent(root, &touch));
    765 
    766   SetEnabled(true);
    767   EXPECT_FALSE(controller()->IsRevealed());
    768   // Make sure the windows are still aligned on top.
    769   EXPECT_EQ(behind->GetBoundsInScreen().y(), window()->GetBoundsInScreen().y());
    770   top = behind->GetBoundsInScreen().y();
    771   ui::TouchEvent touch2(ui::ET_TOUCH_MOVED, gfx::Point(10, top), 0,
    772                         ui::EventTimeForNow());
    773   // The event should still be targeted to window().
    774   EXPECT_EQ(window(), targeter->FindTargetForEvent(root, &touch2));
    775 }
    776 
    777 // Check that the window state gets properly marked for immersive fullscreen.
    778 TEST_F(ImmersiveFullscreenControllerTest, WindowStateImmersiveFullscreen) {
    779   ash::wm::WindowState* window_state = ash::wm::GetWindowState(window());
    780 
    781   EXPECT_FALSE(window_state->in_immersive_fullscreen());
    782   SetEnabled(true);
    783   ASSERT_TRUE(controller()->IsEnabled());
    784   EXPECT_TRUE(window_state->in_immersive_fullscreen());
    785 
    786   SetEnabled(false);
    787   ASSERT_FALSE(controller()->IsEnabled());
    788   EXPECT_FALSE(window_state->in_immersive_fullscreen());
    789 }
    790 
    791 // Do not test under windows because focus testing is not reliable on
    792 // Windows. (crbug.com/79493)
    793 #if !defined(OS_WIN)
    794 
    795 // Test how focus and activation affects whether the top-of-window views are
    796 // revealed.
    797 TEST_F(ImmersiveFullscreenControllerTest, Focus) {
    798   // Add views to the view hierarchy which we will focus and unfocus during the
    799   // test.
    800   views::View* child_view = new views::View();
    801   child_view->SetBounds(0, 0, 10, 10);
    802   child_view->SetFocusable(true);
    803   top_container()->AddChildView(child_view);
    804   views::View* unrelated_view = new views::View();
    805   unrelated_view->SetBounds(0, 100, 10, 10);
    806   unrelated_view->SetFocusable(true);
    807   top_container()->parent()->AddChildView(unrelated_view);
    808   views::FocusManager* focus_manager =
    809       top_container()->GetWidget()->GetFocusManager();
    810 
    811   SetEnabled(true);
    812 
    813   // 1) Test that the top-of-window views stay revealed as long as either a
    814   // |child_view| has focus or the mouse is hovered above the top-of-window
    815   // views.
    816   AttemptReveal(MODALITY_MOUSE);
    817   child_view->RequestFocus();
    818   focus_manager->ClearFocus();
    819   EXPECT_TRUE(controller()->IsRevealed());
    820   child_view->RequestFocus();
    821   SetHovered(false);
    822   EXPECT_TRUE(controller()->IsRevealed());
    823   focus_manager->ClearFocus();
    824   EXPECT_FALSE(controller()->IsRevealed());
    825 
    826   // 2) Test that focusing |unrelated_view| hides the top-of-window views.
    827   // Note: In this test we can cheat and trigger a reveal via focus because
    828   // the top container does not hide when the top-of-window views are not
    829   // revealed.
    830   child_view->RequestFocus();
    831   EXPECT_TRUE(controller()->IsRevealed());
    832   unrelated_view->RequestFocus();
    833   EXPECT_FALSE(controller()->IsRevealed());
    834 
    835   // 3) Test that a loss of focus of |child_view| to |unrelated_view|
    836   // while immersive mode is disabled is properly registered.
    837   child_view->RequestFocus();
    838   EXPECT_TRUE(controller()->IsRevealed());
    839   SetEnabled(false);
    840   EXPECT_FALSE(controller()->IsRevealed());
    841   unrelated_view->RequestFocus();
    842   SetEnabled(true);
    843   EXPECT_FALSE(controller()->IsRevealed());
    844 
    845   // Repeat test but with a revealed lock acquired when immersive mode is
    846   // disabled because the code path is different.
    847   child_view->RequestFocus();
    848   EXPECT_TRUE(controller()->IsRevealed());
    849   SetEnabled(false);
    850   scoped_ptr<ImmersiveRevealedLock> lock(controller()->GetRevealedLock(
    851       ImmersiveFullscreenController::ANIMATE_REVEAL_NO));
    852   EXPECT_FALSE(controller()->IsRevealed());
    853   unrelated_view->RequestFocus();
    854   SetEnabled(true);
    855   EXPECT_TRUE(controller()->IsRevealed());
    856   lock.reset();
    857   EXPECT_FALSE(controller()->IsRevealed());
    858 }
    859 
    860 // Test how transient windows affect whether the top-of-window views are
    861 // revealed.
    862 TEST_F(ImmersiveFullscreenControllerTest, Transient) {
    863   views::Widget* top_container_widget = top_container()->GetWidget();
    864 
    865   SetEnabled(true);
    866   ASSERT_FALSE(controller()->IsRevealed());
    867 
    868   // 1) Test that a transient window which is not a bubble does not trigger a
    869   // reveal but does keep the top-of-window views revealed if they are already
    870   // revealed.
    871   views::Widget::InitParams transient_params;
    872   transient_params.ownership =
    873       views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    874   transient_params.parent = top_container_widget->GetNativeView();
    875   transient_params.bounds = gfx::Rect(0, 100, 100, 100);
    876   scoped_ptr<views::Widget> transient_widget(new views::Widget());
    877   transient_widget->Init(transient_params);
    878 
    879   EXPECT_FALSE(controller()->IsRevealed());
    880   AttemptReveal(MODALITY_MOUSE);
    881   EXPECT_TRUE(controller()->IsRevealed());
    882   transient_widget->Show();
    883   SetHovered(false);
    884   EXPECT_TRUE(controller()->IsRevealed());
    885   transient_widget.reset();
    886   EXPECT_FALSE(controller()->IsRevealed());
    887 
    888   // 2) Test that activating a non-transient window does not keep the
    889   // top-of-window views revealed.
    890   views::Widget::InitParams non_transient_params;
    891   non_transient_params.ownership =
    892       views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    893   non_transient_params.context = top_container_widget->GetNativeView();
    894   non_transient_params.bounds = gfx::Rect(0, 100, 100, 100);
    895   scoped_ptr<views::Widget> non_transient_widget(new views::Widget());
    896   non_transient_widget->Init(non_transient_params);
    897 
    898   EXPECT_FALSE(controller()->IsRevealed());
    899   AttemptReveal(MODALITY_MOUSE);
    900   EXPECT_TRUE(controller()->IsRevealed());
    901   non_transient_widget->Show();
    902   SetHovered(false);
    903   EXPECT_FALSE(controller()->IsRevealed());
    904 }
    905 
    906 // Test how bubbles affect whether the top-of-window views are revealed.
    907 TEST_F(ImmersiveFullscreenControllerTest, Bubbles) {
    908   scoped_ptr<ImmersiveRevealedLock> revealed_lock;
    909   views::Widget* top_container_widget = top_container()->GetWidget();
    910 
    911   // Add views to the view hierarchy to which we will anchor bubbles.
    912   views::View* child_view = new views::View();
    913   child_view->SetBounds(0, 0, 10, 10);
    914   top_container()->AddChildView(child_view);
    915   views::View* unrelated_view = new views::View();
    916   unrelated_view->SetBounds(0, 100, 10, 10);
    917   top_container()->parent()->AddChildView(unrelated_view);
    918 
    919   SetEnabled(true);
    920   ASSERT_FALSE(controller()->IsRevealed());
    921 
    922   // 1) Test that a bubble anchored to a child of the top container triggers
    923   // a reveal and keeps the top-of-window views revealed for the duration of
    924   // its visibility.
    925   views::Widget* bubble_widget1(views::BubbleDelegateView::CreateBubble(
    926       new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE)));
    927   bubble_widget1->Show();
    928   EXPECT_TRUE(controller()->IsRevealed());
    929 
    930   // Activating |top_container_widget| will close |bubble_widget1|.
    931   top_container_widget->Activate();
    932   AttemptReveal(MODALITY_MOUSE);
    933   revealed_lock.reset(controller()->GetRevealedLock(
    934       ImmersiveFullscreenController::ANIMATE_REVEAL_NO));
    935   EXPECT_TRUE(controller()->IsRevealed());
    936 
    937   views::Widget* bubble_widget2 = views::BubbleDelegateView::CreateBubble(
    938       new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE));
    939   bubble_widget2->Show();
    940   EXPECT_TRUE(controller()->IsRevealed());
    941   revealed_lock.reset();
    942   SetHovered(false);
    943   EXPECT_TRUE(controller()->IsRevealed());
    944   bubble_widget2->Close();
    945   EXPECT_FALSE(controller()->IsRevealed());
    946 
    947   // 2) Test that transitioning from keeping the top-of-window views revealed
    948   // because of a bubble to keeping the top-of-window views revealed because of
    949   // mouse hover by activating |top_container_widget| works.
    950   views::Widget* bubble_widget3 = views::BubbleDelegateView::CreateBubble(
    951       new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE));
    952   bubble_widget3->Show();
    953   SetHovered(true);
    954   EXPECT_TRUE(controller()->IsRevealed());
    955   top_container_widget->Activate();
    956   EXPECT_TRUE(controller()->IsRevealed());
    957 
    958   // 3) Test that the top-of-window views stay revealed as long as at least one
    959   // bubble anchored to a child of the top container is visible.
    960   SetHovered(false);
    961   EXPECT_FALSE(controller()->IsRevealed());
    962 
    963   views::BubbleDelegateView* bubble_delegate4(new views::BubbleDelegateView(
    964       child_view, views::BubbleBorder::NONE));
    965   bubble_delegate4->set_can_activate(false);
    966   views::Widget* bubble_widget4(views::BubbleDelegateView::CreateBubble(
    967       bubble_delegate4));
    968   bubble_widget4->Show();
    969 
    970   views::BubbleDelegateView* bubble_delegate5(new views::BubbleDelegateView(
    971       child_view, views::BubbleBorder::NONE));
    972   bubble_delegate5->set_can_activate(false);
    973   views::Widget* bubble_widget5(views::BubbleDelegateView::CreateBubble(
    974       bubble_delegate5));
    975   bubble_widget5->Show();
    976 
    977   EXPECT_TRUE(controller()->IsRevealed());
    978   bubble_widget4->Hide();
    979   EXPECT_TRUE(controller()->IsRevealed());
    980   bubble_widget5->Hide();
    981   EXPECT_FALSE(controller()->IsRevealed());
    982   bubble_widget5->Show();
    983   EXPECT_TRUE(controller()->IsRevealed());
    984 
    985   // 4) Test that visibility changes which occur while immersive fullscreen is
    986   // disabled are handled upon reenabling immersive fullscreen.
    987   SetEnabled(false);
    988   bubble_widget5->Hide();
    989   SetEnabled(true);
    990   EXPECT_FALSE(controller()->IsRevealed());
    991 
    992   // We do not need |bubble_widget4| or |bubble_widget5| anymore, close them.
    993   bubble_widget4->Close();
    994   bubble_widget5->Close();
    995 
    996   // 5) Test that a bubble added while immersive fullscreen is disabled is
    997   // handled upon reenabling immersive fullscreen.
    998   SetEnabled(false);
    999 
   1000   views::Widget* bubble_widget6 = views::BubbleDelegateView::CreateBubble(
   1001       new views::BubbleDelegateView(child_view, views::BubbleBorder::NONE));
   1002   bubble_widget6->Show();
   1003 
   1004   SetEnabled(true);
   1005   EXPECT_TRUE(controller()->IsRevealed());
   1006 
   1007   bubble_widget6->Close();
   1008 
   1009   // 6) Test that a bubble which is not anchored to a child of the
   1010   // TopContainerView does not trigger a reveal or keep the
   1011   // top-of-window views revealed if they are already revealed.
   1012   views::Widget* bubble_widget7 = views::BubbleDelegateView::CreateBubble(
   1013       new views::BubbleDelegateView(unrelated_view, views::BubbleBorder::NONE));
   1014   bubble_widget7->Show();
   1015   EXPECT_FALSE(controller()->IsRevealed());
   1016 
   1017   // Activating |top_container_widget| will close |bubble_widget6|.
   1018   top_container_widget->Activate();
   1019   AttemptReveal(MODALITY_MOUSE);
   1020   EXPECT_TRUE(controller()->IsRevealed());
   1021 
   1022   views::Widget* bubble_widget8 = views::BubbleDelegateView::CreateBubble(
   1023       new views::BubbleDelegateView(unrelated_view, views::BubbleBorder::NONE));
   1024   bubble_widget8->Show();
   1025   SetHovered(false);
   1026   EXPECT_FALSE(controller()->IsRevealed());
   1027   bubble_widget8->Close();
   1028 }
   1029 
   1030 #endif  // defined(OS_WIN)
   1031 
   1032 // Test that the shelf is set to auto hide as long as the window is in
   1033 // immersive fullscreen and that the shelf's state before entering immersive
   1034 // fullscreen is restored upon exiting immersive fullscreen.
   1035 TEST_F(ImmersiveFullscreenControllerTest, Shelf) {
   1036   ash::ShelfLayoutManager* shelf =
   1037       ash::Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
   1038 
   1039   // Shelf is visible by default.
   1040   window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
   1041   ASSERT_FALSE(controller()->IsEnabled());
   1042   ASSERT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state());
   1043 
   1044   // Entering immersive fullscreen sets the shelf to auto hide.
   1045   window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
   1046   SetEnabled(true);
   1047   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
   1048 
   1049   // Disabling immersive fullscreen puts it back.
   1050   SetEnabled(false);
   1051   window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
   1052   ASSERT_FALSE(controller()->IsEnabled());
   1053   EXPECT_EQ(ash::SHELF_VISIBLE, shelf->visibility_state());
   1054 
   1055   // The user could toggle the shelf auto-hide behavior.
   1056   shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   1057   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
   1058 
   1059   // Entering immersive fullscreen keeps auto-hide.
   1060   window()->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
   1061   SetEnabled(true);
   1062   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
   1063 
   1064   // Disabling immersive fullscreen maintains the user's auto-hide selection.
   1065   SetEnabled(false);
   1066   window()->SetProperty(aura::client::kShowStateKey,
   1067                         ui::SHOW_STATE_NORMAL);
   1068   EXPECT_EQ(ash::SHELF_AUTO_HIDE, shelf->visibility_state());
   1069 }
   1070 
   1071 }  // namespase ash
   1072