tooltip_controller_unittest.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. #include "ui/views/corewm/tooltip_controller.h"
  5. #include <memory>
  6. #include "ash/public/cpp/shell_window_ids.h"
  7. #include "ash/shell.h"
  8. #include "ash/test/ash_test_base.h"
  9. #include "ash/wm/desks/desks_util.h"
  10. #include "base/run_loop.h"
  11. #include "base/strings/utf_string_conversions.h"
  12. #include "ui/aura/env.h"
  13. #include "ui/aura/window.h"
  14. #include "ui/aura/window_event_dispatcher.h"
  15. #include "ui/events/test/event_generator.h"
  16. #include "ui/gfx/font.h"
  17. #include "ui/gfx/geometry/point.h"
  18. #include "ui/views/corewm/tooltip_controller_test_helper.h"
  19. #include "ui/views/view.h"
  20. #include "ui/views/widget/widget.h"
  21. #include "ui/wm/public/tooltip_client.h"
  22. using views::corewm::TooltipController;
  23. using views::corewm::TooltipTrigger;
  24. using views::corewm::test::TooltipControllerTestHelper;
  25. using views::corewm::test::TooltipTestView;
  26. // The tests in this file exercise bits of TooltipController that are hard to
  27. // test outside of ash. Meaning these tests require the shell and related things
  28. // to be installed.
  29. namespace ash {
  30. namespace {
  31. views::Widget* CreateNewWidgetWithBoundsOn(int display,
  32. const gfx::Rect& bounds) {
  33. views::Widget* widget = new views::Widget;
  34. views::Widget::InitParams params;
  35. params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
  36. params.accept_events = true;
  37. params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  38. params.parent =
  39. Shell::Get()->GetContainer(Shell::GetAllRootWindows().at(display),
  40. desks_util::GetActiveDeskContainerId());
  41. params.bounds = bounds;
  42. widget->Init(std::move(params));
  43. widget->Show();
  44. return widget;
  45. }
  46. views::Widget* CreateNewWidgetOn(int display) {
  47. return CreateNewWidgetWithBoundsOn(display, gfx::Rect());
  48. }
  49. void AddViewToWidgetAndResize(views::Widget* widget, views::View* view) {
  50. if (!widget->GetContentsView())
  51. widget->SetContentsView(std::make_unique<views::View>());
  52. views::View* contents_view = widget->GetContentsView();
  53. contents_view->AddChildView(view);
  54. view->SetBounds(contents_view->width(), 0, 100, 100);
  55. gfx::Rect contents_view_bounds = contents_view->bounds();
  56. contents_view_bounds.Union(view->bounds());
  57. contents_view->SetBoundsRect(contents_view_bounds);
  58. widget->SetBounds(gfx::Rect(widget->GetWindowBoundsInScreen().origin(),
  59. contents_view_bounds.size()));
  60. }
  61. TooltipController* GetController() {
  62. return static_cast<TooltipController*>(
  63. ::wm::GetTooltipClient(Shell::GetPrimaryRootWindow()));
  64. }
  65. } // namespace
  66. class TooltipControllerTest : public AshTestBase {
  67. public:
  68. TooltipControllerTest() = default;
  69. TooltipControllerTest(const TooltipControllerTest&) = delete;
  70. TooltipControllerTest& operator=(const TooltipControllerTest&) = delete;
  71. ~TooltipControllerTest() override = default;
  72. void SetUp() override {
  73. AshTestBase::SetUp();
  74. helper_ = std::make_unique<TooltipControllerTestHelper>(GetController());
  75. }
  76. protected:
  77. std::unique_ptr<TooltipControllerTestHelper> helper_;
  78. };
  79. TEST_F(TooltipControllerTest, NonNullTooltipClient) {
  80. EXPECT_TRUE(::wm::GetTooltipClient(Shell::GetPrimaryRootWindow()) != NULL);
  81. EXPECT_EQ(std::u16string(), helper_->GetTooltipText());
  82. EXPECT_EQ(NULL, helper_->GetTooltipParentWindow());
  83. EXPECT_FALSE(helper_->IsTooltipVisible());
  84. }
  85. TEST_F(TooltipControllerTest, HideTooltipWhenCursorHidden) {
  86. std::unique_ptr<views::Widget> widget(CreateNewWidgetOn(0));
  87. TooltipTestView* view = new TooltipTestView;
  88. AddViewToWidgetAndResize(widget.get(), view);
  89. view->set_tooltip_text(u"Tooltip Text");
  90. EXPECT_EQ(std::u16string(), helper_->GetTooltipText());
  91. EXPECT_EQ(NULL, helper_->GetTooltipParentWindow());
  92. ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
  93. generator.MoveMouseRelativeTo(widget->GetNativeView(),
  94. view->bounds().CenterPoint());
  95. std::u16string expected_tooltip = u"Tooltip Text";
  96. // Mouse event triggers tooltip update so it becomes visible.
  97. EXPECT_TRUE(helper_->IsTooltipVisible());
  98. // Disable mouse event which hides the cursor and check again.
  99. Shell::Get()->cursor_manager()->DisableMouseEvents();
  100. base::RunLoop().RunUntilIdle();
  101. EXPECT_FALSE(Shell::Get()->cursor_manager()->IsCursorVisible());
  102. helper_->UpdateIfRequired(TooltipTrigger::kCursor);
  103. EXPECT_FALSE(helper_->IsTooltipVisible());
  104. // Enable mouse event which shows the cursor and re-check.
  105. Shell::Get()->cursor_manager()->EnableMouseEvents();
  106. base::RunLoop().RunUntilIdle();
  107. EXPECT_TRUE(Shell::Get()->cursor_manager()->IsCursorVisible());
  108. generator.MoveMouseBy(0, 1);
  109. helper_->UpdateIfRequired(TooltipTrigger::kCursor);
  110. EXPECT_TRUE(helper_->IsTooltipVisible());
  111. }
  112. TEST_F(TooltipControllerTest, TooltipsOnMultiDisplayShouldNotCrash) {
  113. UpdateDisplay("1000x600,600x400");
  114. aura::Window::Windows root_windows = Shell::GetAllRootWindows();
  115. std::unique_ptr<views::Widget> widget1(
  116. CreateNewWidgetWithBoundsOn(0, gfx::Rect(10, 10, 100, 100)));
  117. TooltipTestView* view1 = new TooltipTestView;
  118. AddViewToWidgetAndResize(widget1.get(), view1);
  119. view1->set_tooltip_text(u"Tooltip Text for view 1");
  120. EXPECT_EQ(widget1->GetNativeView()->GetRootWindow(), root_windows[0]);
  121. std::unique_ptr<views::Widget> widget2(
  122. CreateNewWidgetWithBoundsOn(1, gfx::Rect(1200, 10, 100, 100)));
  123. TooltipTestView* view2 = new TooltipTestView;
  124. AddViewToWidgetAndResize(widget2.get(), view2);
  125. view2->set_tooltip_text(u"Tooltip Text for view 2");
  126. EXPECT_EQ(widget2->GetNativeView()->GetRootWindow(), root_windows[1]);
  127. // Show tooltip on second display.
  128. ui::test::EventGenerator generator(root_windows[1]);
  129. generator.MoveMouseRelativeTo(widget2->GetNativeView(),
  130. view2->bounds().CenterPoint());
  131. EXPECT_TRUE(helper_->IsTooltipVisible());
  132. // Get rid of secondary display. This destroy's the tooltip's aura window. If
  133. // we have handled this case, we will not crash in the following statement.
  134. UpdateDisplay("1000x600");
  135. EXPECT_FALSE(helper_->IsTooltipVisible());
  136. EXPECT_EQ(widget2->GetNativeView()->GetRootWindow(), root_windows[0]);
  137. // The tooltip should create a new aura window for itself, so we should still
  138. // be able to show tooltips on the primary display.
  139. ui::test::EventGenerator generator1(root_windows[0]);
  140. generator1.MoveMouseRelativeTo(widget1->GetNativeView(),
  141. view1->bounds().CenterPoint());
  142. EXPECT_TRUE(helper_->IsTooltipVisible());
  143. }
  144. TEST_F(TooltipControllerTest, HideTooltipWhenViewHidden) {
  145. std::unique_ptr<views::Widget> widget(CreateNewWidgetOn(0));
  146. TooltipTestView* view = new TooltipTestView;
  147. AddViewToWidgetAndResize(widget.get(), view);
  148. view->set_tooltip_text(u"Tooltip Text");
  149. EXPECT_EQ(std::u16string(), helper_->GetTooltipText());
  150. EXPECT_EQ(nullptr, helper_->GetTooltipParentWindow());
  151. ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
  152. generator.MoveMouseRelativeTo(widget->GetNativeView(),
  153. view->bounds().CenterPoint());
  154. // Mouse event triggers tooltip update so it becomes visible.
  155. EXPECT_TRUE(helper_->IsTooltipVisible());
  156. view->SetVisible(false);
  157. EXPECT_FALSE(helper_->IsTooltipVisible());
  158. }
  159. } // namespace ash