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