Home | History | Annotate | Download | only in shelf
      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/shelf/shelf_tooltip_manager.h"
      6 
      7 #include "ash/root_window_controller.h"
      8 #include "ash/shelf/shelf_layout_manager.h"
      9 #include "ash/shelf/shelf_widget.h"
     10 #include "ash/shell.h"
     11 #include "ash/shell_window_ids.h"
     12 #include "ash/test/ash_test_base.h"
     13 #include "ash/test/launcher_test_api.h"
     14 #include "ash/wm/window_util.h"
     15 #include "base/strings/string16.h"
     16 #include "base/time/time.h"
     17 #include "ui/aura/root_window.h"
     18 #include "ui/events/event.h"
     19 #include "ui/events/event_constants.h"
     20 #include "ui/events/event_handler.h"
     21 #include "ui/events/keycodes/keyboard_codes.h"
     22 #include "ui/events/test/events_test_utils.h"
     23 #include "ui/views/widget/widget.h"
     24 
     25 namespace {
     26 
     27 void SetEventTarget(ui::EventTarget* target,
     28                     ui::Event* event) {
     29   ui::Event::DispatcherApi dispatch_helper(event);
     30   dispatch_helper.set_target(target);
     31 }
     32 
     33 }
     34 
     35 namespace ash {
     36 namespace test {
     37 
     38 class ShelfTooltipManagerTest : public AshTestBase {
     39  public:
     40   ShelfTooltipManagerTest() {}
     41   virtual ~ShelfTooltipManagerTest() {}
     42 
     43   virtual void SetUp() OVERRIDE {
     44     AshTestBase::SetUp();
     45     internal::RootWindowController* controller =
     46         Shell::GetPrimaryRootWindowController();
     47     tooltip_manager_.reset(new internal::ShelfTooltipManager(
     48         controller->GetShelfLayoutManager(),
     49         LauncherTestAPI(controller->shelf()->launcher()).shelf_view()));
     50   }
     51 
     52   virtual void TearDown() OVERRIDE {
     53     tooltip_manager_.reset();
     54     AshTestBase::TearDown();
     55   }
     56 
     57   void ShowDelayed() {
     58     CreateWidget();
     59     tooltip_manager_->ShowDelayed(dummy_anchor_.get(), base::string16());
     60   }
     61 
     62   void ShowImmediately() {
     63     CreateWidget();
     64     tooltip_manager_->ShowImmediately(dummy_anchor_.get(), base::string16());
     65   }
     66 
     67   bool TooltipIsVisible() {
     68     return tooltip_manager_->IsVisible();
     69   }
     70 
     71   bool IsTimerRunning() {
     72     return tooltip_manager_->timer_.get() != NULL;
     73   }
     74 
     75   ui::EventHandler* GetEventHandler() {
     76     return tooltip_manager_.get();
     77   }
     78 
     79   views::Widget* GetTooltipWidget() {
     80     return tooltip_manager_->widget_;
     81   }
     82 
     83  protected:
     84   scoped_ptr<views::Widget> widget_;
     85   scoped_ptr<views::View> dummy_anchor_;
     86   scoped_ptr<internal::ShelfTooltipManager> tooltip_manager_;
     87 
     88  private:
     89   void CreateWidget() {
     90     dummy_anchor_.reset(new views::View);
     91 
     92     widget_.reset(new views::Widget);
     93     views::Widget::InitParams params(
     94         views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
     95     params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
     96     params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
     97     params.parent = Shell::GetContainer(
     98         Shell::GetPrimaryRootWindow(),
     99         ash::internal::kShellWindowId_ShelfContainer);
    100 
    101     widget_->Init(params);
    102     widget_->SetContentsView(dummy_anchor_.get());
    103   }
    104 
    105   DISALLOW_COPY_AND_ASSIGN(ShelfTooltipManagerTest);
    106 };
    107 
    108 TEST_F(ShelfTooltipManagerTest, ShowingBasics) {
    109   // ShowDelayed() should just start the timer instead of showing immediately.
    110   ShowDelayed();
    111   EXPECT_FALSE(TooltipIsVisible());
    112   EXPECT_TRUE(IsTimerRunning());
    113 
    114   ShowImmediately();
    115   EXPECT_TRUE(TooltipIsVisible());
    116   EXPECT_FALSE(IsTimerRunning());
    117 }
    118 
    119 TEST_F(ShelfTooltipManagerTest, HideWhenShelfIsHidden) {
    120   ShowImmediately();
    121   ASSERT_TRUE(TooltipIsVisible());
    122 
    123   // Create a full-screen window to hide the shelf.
    124   scoped_ptr<views::Widget> widget(new views::Widget);
    125   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
    126   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    127   params.context = CurrentContext();
    128   widget->Init(params);
    129   widget->SetFullscreen(true);
    130   widget->Show();
    131 
    132   // Once the shelf is hidden, the tooltip should be invisible.
    133   ASSERT_EQ(
    134       SHELF_HIDDEN,
    135       Shell::GetPrimaryRootWindowController()->
    136           GetShelfLayoutManager()->visibility_state());
    137   EXPECT_FALSE(TooltipIsVisible());
    138 
    139   // Do not show the view if the shelf is hidden.
    140   ShowImmediately();
    141   EXPECT_FALSE(TooltipIsVisible());
    142 
    143   // ShowDelayed() doesn't even start the timer for the hidden shelf.
    144   ShowDelayed();
    145   EXPECT_FALSE(IsTimerRunning());
    146 }
    147 
    148 TEST_F(ShelfTooltipManagerTest, HideWhenShelfIsAutoHide) {
    149   // Create a visible window so auto-hide behavior is enforced.
    150   views::Widget* dummy = new views::Widget;
    151   views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
    152   params.bounds = gfx::Rect(0, 0, 200, 200);
    153   params.context = CurrentContext();
    154   dummy->Init(params);
    155   dummy->Show();
    156 
    157   ShowImmediately();
    158   ASSERT_TRUE(TooltipIsVisible());
    159 
    160   internal::ShelfLayoutManager* shelf =
    161       Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
    162   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
    163   shelf->UpdateAutoHideState();
    164   ASSERT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
    165 
    166   // Tooltip visibility change for auto hide may take time.
    167   EXPECT_TRUE(TooltipIsVisible());
    168   RunAllPendingInMessageLoop();
    169   EXPECT_FALSE(TooltipIsVisible());
    170 
    171   // Do not show the view if the shelf is hidden.
    172   ShowImmediately();
    173   EXPECT_FALSE(TooltipIsVisible());
    174 
    175   // ShowDelayed doesn't even run the timer for the hidden shelf.
    176   ShowDelayed();
    177   EXPECT_FALSE(IsTimerRunning());
    178 }
    179 
    180 TEST_F(ShelfTooltipManagerTest, ShouldHideForEvents) {
    181   ShowImmediately();
    182   ASSERT_TRUE(TooltipIsVisible());
    183 
    184   aura::Window* root_window = Shell::GetInstance()->GetPrimaryRootWindow();
    185   ui::EventHandler* event_handler = GetEventHandler();
    186 
    187   // Should not hide for key events.
    188   ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE, false);
    189   SetEventTarget(root_window, &key_event);
    190   event_handler->OnKeyEvent(&key_event);
    191   EXPECT_FALSE(key_event.handled());
    192   EXPECT_TRUE(TooltipIsVisible());
    193 
    194   // Should hide for touch events.
    195   ui::TouchEvent touch_event(
    196       ui::ET_TOUCH_PRESSED, gfx::Point(), 0, base::TimeDelta());
    197   SetEventTarget(root_window, &touch_event);
    198   event_handler->OnTouchEvent(&touch_event);
    199   EXPECT_FALSE(touch_event.handled());
    200   EXPECT_FALSE(TooltipIsVisible());
    201 
    202   // Shouldn't hide if the touch happens on the tooltip.
    203   ShowImmediately();
    204   views::Widget* tooltip_widget = GetTooltipWidget();
    205   SetEventTarget(tooltip_widget->GetNativeWindow(), &touch_event);
    206   event_handler->OnTouchEvent(&touch_event);
    207   EXPECT_FALSE(touch_event.handled());
    208   EXPECT_TRUE(TooltipIsVisible());
    209 
    210   // Should hide for gesture events.
    211   ui::GestureEvent gesture_event(
    212       ui::ET_GESTURE_BEGIN, 0, 0, ui::EF_NONE,
    213       base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000),
    214       ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0.0f, 0.0f), 0);
    215   SetEventTarget(tooltip_widget->GetNativeWindow(), &gesture_event);
    216   event_handler->OnGestureEvent(&gesture_event);
    217   EXPECT_FALSE(gesture_event.handled());
    218   RunAllPendingInMessageLoop();
    219   EXPECT_FALSE(TooltipIsVisible());
    220 }
    221 
    222 TEST_F(ShelfTooltipManagerTest, HideForMouseMoveEvent) {
    223   ShowImmediately();
    224   ASSERT_TRUE(TooltipIsVisible());
    225 
    226   aura::Window* root_window = Shell::GetInstance()->GetPrimaryRootWindow();
    227   ui::EventHandler* event_handler = GetEventHandler();
    228 
    229   gfx::Rect tooltip_rect = GetTooltipWidget()->GetNativeWindow()->bounds();
    230   ASSERT_FALSE(tooltip_rect.IsEmpty());
    231 
    232   // Shouldn't hide if the mouse is in the tooltip.
    233   ui::MouseEvent mouse_event(ui::ET_MOUSE_MOVED, tooltip_rect.CenterPoint(),
    234                              tooltip_rect.CenterPoint(), ui::EF_NONE);
    235   ui::LocatedEventTestApi test_api(&mouse_event);
    236 
    237   SetEventTarget(root_window, &mouse_event);
    238   event_handler->OnMouseEvent(&mouse_event);
    239   EXPECT_FALSE(mouse_event.handled());
    240   EXPECT_TRUE(TooltipIsVisible());
    241 
    242   // Should hide if the mouse is out of the tooltip.
    243   test_api.set_location(tooltip_rect.origin() + gfx::Vector2d(-1, -1));
    244   event_handler->OnMouseEvent(&mouse_event);
    245   EXPECT_FALSE(mouse_event.handled());
    246   RunAllPendingInMessageLoop();
    247   EXPECT_FALSE(TooltipIsVisible());
    248 }
    249 
    250 // Checks that tooltip is hidden when mouse is pressed in anywhere.
    251 TEST_F(ShelfTooltipManagerTest, HideForMouseClickEvent) {
    252   ShowImmediately();
    253   ASSERT_TRUE(TooltipIsVisible());
    254 
    255   aura::Window* root_window = Shell::GetInstance()->GetPrimaryRootWindow();
    256   ui::EventHandler* event_handler = GetEventHandler();
    257 
    258   gfx::Rect tooltip_rect = GetTooltipWidget()->GetNativeWindow()->bounds();
    259   ASSERT_FALSE(tooltip_rect.IsEmpty());
    260 
    261   // Should hide if the mouse is pressed in the tooltip.
    262   ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, tooltip_rect.CenterPoint(),
    263                              tooltip_rect.CenterPoint(), ui::EF_NONE);
    264 
    265   SetEventTarget(root_window, &mouse_event);
    266   event_handler->OnMouseEvent(&mouse_event);
    267   EXPECT_FALSE(mouse_event.handled());
    268   RunAllPendingInMessageLoop();
    269   EXPECT_FALSE(TooltipIsVisible());
    270 
    271   // Should hide if the mouse is pressed outside of the tooltip.
    272   ShowImmediately();
    273   ASSERT_TRUE(TooltipIsVisible());
    274 
    275   ui::LocatedEventTestApi test_api(&mouse_event);
    276   test_api.set_location(tooltip_rect.origin() + gfx::Vector2d(-1, -1));
    277 
    278   SetEventTarget(root_window, &mouse_event);
    279   event_handler->OnMouseEvent(&mouse_event);
    280   EXPECT_FALSE(mouse_event.handled());
    281   RunAllPendingInMessageLoop();
    282   EXPECT_FALSE(TooltipIsVisible());
    283 }
    284 
    285 }  // namespace test
    286 }  // namespace ash
    287