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