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/launcher/launcher_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/wm/window_util.h" 14 #include "base/strings/string16.h" 15 #include "base/time/time.h" 16 #include "ui/aura/root_window.h" 17 #include "ui/base/events/event.h" 18 #include "ui/base/events/event_constants.h" 19 #include "ui/base/events/event_handler.h" 20 #include "ui/base/keycodes/keyboard_codes.h" 21 #include "ui/views/widget/widget.h" 22 23 namespace { 24 25 void SetEventTarget(ui::EventTarget* target, 26 ui::Event* event) { 27 ui::Event::DispatcherApi dispatch_helper(event); 28 dispatch_helper.set_target(target); 29 } 30 31 } 32 33 namespace ash { 34 namespace test { 35 36 class LauncherTooltipManagerTest : public AshTestBase { 37 public: 38 LauncherTooltipManagerTest() {} 39 virtual ~LauncherTooltipManagerTest() {} 40 41 virtual void SetUp() OVERRIDE { 42 AshTestBase::SetUp(); 43 internal::RootWindowController* controller = 44 Shell::GetPrimaryRootWindowController(); 45 tooltip_manager_.reset(new internal::LauncherTooltipManager( 46 controller->GetShelfLayoutManager(), 47 controller->shelf()->launcher()->GetLauncherViewForTest())); 48 } 49 50 virtual void TearDown() OVERRIDE { 51 tooltip_manager_.reset(); 52 AshTestBase::TearDown(); 53 } 54 55 void ShowDelayed() { 56 CreateWidget(); 57 tooltip_manager_->ShowDelayed(dummy_anchor_.get(), base::string16()); 58 } 59 60 void ShowImmediately() { 61 CreateWidget(); 62 tooltip_manager_->ShowImmediately(dummy_anchor_.get(), base::string16()); 63 } 64 65 bool TooltipIsVisible() { 66 return tooltip_manager_->IsVisible(); 67 } 68 69 bool IsTimerRunning() { 70 return tooltip_manager_->timer_.get() != NULL; 71 } 72 73 ui::EventHandler* GetEventHandler() { 74 return tooltip_manager_.get(); 75 } 76 77 views::Widget* GetTooltipWidget() { 78 return tooltip_manager_->widget_; 79 } 80 81 protected: 82 scoped_ptr<views::Widget> widget_; 83 scoped_ptr<views::View> dummy_anchor_; 84 scoped_ptr<internal::LauncherTooltipManager> tooltip_manager_; 85 86 private: 87 void CreateWidget() { 88 dummy_anchor_.reset(new views::View); 89 90 widget_.reset(new views::Widget); 91 views::Widget::InitParams params( 92 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); 93 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 94 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 95 params.parent = Shell::GetContainer( 96 Shell::GetPrimaryRootWindow(), 97 ash::internal::kShellWindowId_ShelfContainer); 98 99 widget_->Init(params); 100 widget_->SetContentsView(dummy_anchor_.get()); 101 } 102 103 DISALLOW_COPY_AND_ASSIGN(LauncherTooltipManagerTest); 104 }; 105 106 TEST_F(LauncherTooltipManagerTest, 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(LauncherTooltipManagerTest, 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(LauncherTooltipManagerTest, 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 internal::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(LauncherTooltipManagerTest, ShouldHideForEvents) { 179 ShowImmediately(); 180 ASSERT_TRUE(TooltipIsVisible()); 181 182 aura::RootWindow* 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(LauncherTooltipManagerTest, HideForMouseEvent) { 221 ShowImmediately(); 222 ASSERT_TRUE(TooltipIsVisible()); 223 224 aura::RootWindow* 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::LocatedEvent::TestApi test_api(&mouse_event); 234 235 SetEventTarget(root_window, &mouse_event); 236 event_handler->OnMouseEvent(&mouse_event); 237 EXPECT_FALSE(mouse_event.handled()); 238 EXPECT_TRUE(TooltipIsVisible()); 239 240 // Should hide if the mouse is out of the tooltip. 241 test_api.set_location(tooltip_rect.origin() + gfx::Vector2d(-1, -1)); 242 event_handler->OnMouseEvent(&mouse_event); 243 EXPECT_FALSE(mouse_event.handled()); 244 RunAllPendingInMessageLoop(); 245 EXPECT_FALSE(TooltipIsVisible()); 246 } 247 248 } // namespace test 249 } // namespace ash 250