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, false);
    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       ui::ET_GESTURE_BEGIN, 0, 0, ui::EF_NONE,
    211       base::TimeDelta::FromMilliseconds(base::Time::Now().ToDoubleT() * 1000),
    212       ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0.0f, 0.0f), 0);
    213   SetEventTarget(tooltip_widget->GetNativeWindow(), &gesture_event);
    214   event_handler->OnGestureEvent(&gesture_event);
    215   EXPECT_FALSE(gesture_event.handled());
    216   RunAllPendingInMessageLoop();
    217   EXPECT_FALSE(TooltipIsVisible());
    218 }
    219 
    220 TEST_F(ShelfTooltipManagerTest, HideForMouseMoveEvent) {
    221   ShowImmediately();
    222   ASSERT_TRUE(TooltipIsVisible());
    223 
    224   aura::Window* root_window = Shell::GetInstance()->GetPrimaryRootWindow();
    225   ui::EventHandler* event_handler = GetEventHandler();
    226 
    227   gfx::Rect tooltip_rect = GetTooltipWidget()->GetNativeWindow()->bounds();
    228   ASSERT_FALSE(tooltip_rect.IsEmpty());
    229 
    230   // Shouldn't hide if the mouse is in the tooltip.
    231   ui::MouseEvent mouse_event(ui::ET_MOUSE_MOVED, tooltip_rect.CenterPoint(),
    232                              tooltip_rect.CenterPoint(), ui::EF_NONE,
    233                              ui::EF_NONE);
    234   ui::LocatedEventTestApi test_api(&mouse_event);
    235 
    236   SetEventTarget(root_window, &mouse_event);
    237   event_handler->OnMouseEvent(&mouse_event);
    238   EXPECT_FALSE(mouse_event.handled());
    239   EXPECT_TRUE(TooltipIsVisible());
    240 
    241   // Should hide if the mouse is out of the tooltip.
    242   test_api.set_location(tooltip_rect.origin() + gfx::Vector2d(-1, -1));
    243   event_handler->OnMouseEvent(&mouse_event);
    244   EXPECT_FALSE(mouse_event.handled());
    245   RunAllPendingInMessageLoop();
    246   EXPECT_FALSE(TooltipIsVisible());
    247 }
    248 
    249 // Checks that tooltip is hidden when mouse is pressed in anywhere.
    250 TEST_F(ShelfTooltipManagerTest, HideForMouseClickEvent) {
    251   ShowImmediately();
    252   ASSERT_TRUE(TooltipIsVisible());
    253 
    254   aura::Window* root_window = Shell::GetInstance()->GetPrimaryRootWindow();
    255   ui::EventHandler* event_handler = GetEventHandler();
    256 
    257   gfx::Rect tooltip_rect = GetTooltipWidget()->GetNativeWindow()->bounds();
    258   ASSERT_FALSE(tooltip_rect.IsEmpty());
    259 
    260   // Should hide if the mouse is pressed in the tooltip.
    261   ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, tooltip_rect.CenterPoint(),
    262                              tooltip_rect.CenterPoint(), ui::EF_NONE,
    263                              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