tray_event_filter_unittest.cc 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // Copyright 2017 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 "ash/system/tray/tray_event_filter.h"
  5. #include "ash/root_window_controller.h"
  6. #include "ash/shelf/shelf.h"
  7. #include "ash/shell.h"
  8. #include "ash/system/message_center/ash_message_popup_collection.h"
  9. #include "ash/system/message_center/unified_message_center_bubble.h"
  10. #include "ash/system/status_area_widget.h"
  11. #include "ash/system/unified/unified_system_tray.h"
  12. #include "ash/test/ash_test_base.h"
  13. #include "testing/gtest/include/gtest/gtest.h"
  14. #include "ui/aura/client/aura_constants.h"
  15. #include "ui/aura/window.h"
  16. #include "ui/message_center/message_center.h"
  17. using message_center::MessageCenter;
  18. using message_center::Notification;
  19. namespace ash {
  20. namespace {
  21. class TrayEventFilterTest : public AshTestBase {
  22. public:
  23. TrayEventFilterTest() = default;
  24. TrayEventFilterTest(const TrayEventFilterTest&) = delete;
  25. TrayEventFilterTest& operator=(const TrayEventFilterTest&) = delete;
  26. ~TrayEventFilterTest() override = default;
  27. // AshTestBase:
  28. void SetUp() override {
  29. AshTestBase::SetUp();
  30. }
  31. ui::MouseEvent outside_event() {
  32. const gfx::Rect tray_bounds = GetSystemTrayBoundsInScreen();
  33. const gfx::Point point = tray_bounds.bottom_right() + gfx::Vector2d(1, 1);
  34. const base::TimeTicks time = base::TimeTicks::Now();
  35. return ui::MouseEvent(ui::ET_MOUSE_PRESSED, point, point, time, 0, 0);
  36. }
  37. ui::MouseEvent inside_event() {
  38. const gfx::Rect tray_bounds = GetSystemTrayBoundsInScreen();
  39. const gfx::Point point = tray_bounds.origin();
  40. const base::TimeTicks time = base::TimeTicks::Now();
  41. return ui::MouseEvent(ui::ET_MOUSE_PRESSED, point, point, time, 0, 0);
  42. }
  43. ui::MouseEvent InsideMessageCenterEvent() {
  44. const gfx::Rect message_center_bounds = GetMessageCenterBoundsInScreen();
  45. const gfx::Point point = message_center_bounds.origin();
  46. const base::TimeTicks time = base::TimeTicks::Now();
  47. return ui::MouseEvent(ui::ET_MOUSE_PRESSED, point, point, time, 0, 0);
  48. }
  49. protected:
  50. std::string AddNotification() {
  51. std::string notification_id = base::NumberToString(notification_id_++);
  52. MessageCenter::Get()->AddNotification(std::make_unique<Notification>(
  53. message_center::NOTIFICATION_TYPE_SIMPLE, notification_id,
  54. u"test title", u"test message", ui::ImageModel(),
  55. std::u16string() /* display_source */, GURL(),
  56. message_center::NotifierId(), message_center::RichNotificationData(),
  57. new message_center::NotificationDelegate()));
  58. return notification_id;
  59. }
  60. void ShowSystemTrayMainView() { GetPrimaryUnifiedSystemTray()->ShowBubble(); }
  61. bool IsBubbleShown() {
  62. return GetPrimaryUnifiedSystemTray()->IsBubbleShown();
  63. }
  64. bool IsMessageCenterBubbleShown() {
  65. return GetPrimaryUnifiedSystemTray()->IsMessageCenterBubbleShown();
  66. }
  67. gfx::Rect GetSystemTrayBoundsInScreen() {
  68. return GetPrimaryUnifiedSystemTray()->GetBubbleBoundsInScreen();
  69. }
  70. TrayEventFilter* GetTrayEventFilter() {
  71. return GetPrimaryUnifiedSystemTray()->tray_event_filter();
  72. }
  73. UnifiedSystemTray* GetPrimaryUnifiedSystemTray() {
  74. return GetPrimaryShelf()->GetStatusAreaWidget()->unified_system_tray();
  75. }
  76. UnifiedMessageCenterBubble* GetMessageCenterBubble() {
  77. return GetPrimaryUnifiedSystemTray()->message_center_bubble();
  78. }
  79. gfx::Rect GetMessageCenterBoundsInScreen() {
  80. return GetMessageCenterBubble()->GetBubbleView()->GetBoundsInScreen();
  81. }
  82. private:
  83. int notification_id_ = 0;
  84. };
  85. TEST_F(TrayEventFilterTest, ClickingOutsideCloseBubble) {
  86. ShowSystemTrayMainView();
  87. EXPECT_TRUE(IsBubbleShown());
  88. // Clicking outside should close the bubble.
  89. ui::MouseEvent event = outside_event();
  90. GetTrayEventFilter()->OnMouseEvent(&event);
  91. EXPECT_FALSE(IsBubbleShown());
  92. }
  93. TEST_F(TrayEventFilterTest, ClickingInsideDoesNotCloseBubble) {
  94. ShowSystemTrayMainView();
  95. EXPECT_TRUE(IsBubbleShown());
  96. // Clicking inside should not close the bubble
  97. ui::MouseEvent event = inside_event();
  98. GetTrayEventFilter()->OnMouseEvent(&event);
  99. EXPECT_TRUE(IsBubbleShown());
  100. }
  101. TEST_F(TrayEventFilterTest, DraggingInsideDoesNotCloseBubble) {
  102. ShowSystemTrayMainView();
  103. EXPECT_TRUE(IsBubbleShown());
  104. // Dragging within the bubble should not close the bubble.
  105. const gfx::Rect tray_bounds = GetSystemTrayBoundsInScreen();
  106. const gfx::Point start = tray_bounds.origin();
  107. const gfx::Point end_inside = start + gfx::Vector2d(5, 5);
  108. GetEventGenerator()->GestureScrollSequence(start, end_inside,
  109. base::Milliseconds(100), 4);
  110. EXPECT_TRUE(IsBubbleShown());
  111. // Dragging from inside to outside of the bubble should not close the bubble.
  112. const gfx::Point start_inside = end_inside;
  113. const gfx::Point end_outside = start + gfx::Vector2d(-5, -5);
  114. GetEventGenerator()->GestureScrollSequence(start_inside, end_outside,
  115. base::Milliseconds(100), 4);
  116. EXPECT_TRUE(IsBubbleShown());
  117. }
  118. TEST_F(TrayEventFilterTest, ClickingOnMenuContainerDoesNotCloseBubble) {
  119. // Create a menu window and place it in the menu container window.
  120. std::unique_ptr<aura::Window> menu_window = CreateTestWindow();
  121. menu_window->set_owned_by_parent(false);
  122. Shell::GetPrimaryRootWindowController()
  123. ->GetContainer(kShellWindowId_MenuContainer)
  124. ->AddChild(menu_window.get());
  125. ShowSystemTrayMainView();
  126. EXPECT_TRUE(IsBubbleShown());
  127. // Clicking on MenuContainer should not close the bubble.
  128. ui::MouseEvent event = outside_event();
  129. ui::Event::DispatcherApi(&event).set_target(menu_window.get());
  130. GetTrayEventFilter()->OnMouseEvent(&event);
  131. EXPECT_TRUE(IsBubbleShown());
  132. }
  133. TEST_F(TrayEventFilterTest, ClickingOnPopupDoesNotCloseBubble) {
  134. // Set up a popup window.
  135. auto popup_widget = std::make_unique<views::Widget>();
  136. views::Widget::InitParams popup_params;
  137. popup_params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  138. auto ash_message_center_popup_collection =
  139. std::make_unique<AshMessagePopupCollection>(GetPrimaryShelf());
  140. ash_message_center_popup_collection->ConfigureWidgetInitParamsForContainer(
  141. popup_widget.get(), &popup_params);
  142. popup_widget->Init(std::move(popup_params));
  143. std::unique_ptr<aura::Window> popup_window =
  144. CreateTestWindow(gfx::Rect(), aura::client::WINDOW_TYPE_POPUP);
  145. popup_window->set_owned_by_parent(false);
  146. popup_widget->GetNativeView()->AddChild(popup_window.get());
  147. popup_widget->GetNativeView()->SetProperty(aura::client::kZOrderingKey,
  148. ui::ZOrderLevel::kFloatingWindow);
  149. ShowSystemTrayMainView();
  150. EXPECT_TRUE(IsBubbleShown());
  151. // Clicking on StatusContainer should not close the bubble.
  152. ui::MouseEvent event = outside_event();
  153. ui::Event::DispatcherApi(&event).set_target(popup_window.get());
  154. GetTrayEventFilter()->OnMouseEvent(&event);
  155. EXPECT_TRUE(IsBubbleShown());
  156. }
  157. TEST_F(TrayEventFilterTest, ClickingOnKeyboardContainerDoesNotCloseBubble) {
  158. // Simulate the virtual keyboard being open. In production the virtual
  159. // keyboard container only exists while the keyboard is open.
  160. std::unique_ptr<aura::Window> keyboard_container =
  161. CreateTestWindow(gfx::Rect(), aura::client::WINDOW_TYPE_NORMAL,
  162. kShellWindowId_VirtualKeyboardContainer);
  163. std::unique_ptr<aura::Window> keyboard_window = CreateTestWindow();
  164. keyboard_window->set_owned_by_parent(false);
  165. keyboard_container->AddChild(keyboard_window.get());
  166. ShowSystemTrayMainView();
  167. EXPECT_TRUE(IsBubbleShown());
  168. // Clicking on KeyboardContainer should not close the bubble.
  169. ui::MouseEvent event = outside_event();
  170. ui::Event::DispatcherApi(&event).set_target(keyboard_window.get());
  171. GetTrayEventFilter()->OnMouseEvent(&event);
  172. EXPECT_TRUE(IsBubbleShown());
  173. }
  174. TEST_F(TrayEventFilterTest, DraggingOnTrayClosesBubble) {
  175. ShowSystemTrayMainView();
  176. EXPECT_TRUE(IsBubbleShown());
  177. // Dragging on the tray background view should close the bubble.
  178. const gfx::Rect tray_bounds =
  179. GetPrimaryUnifiedSystemTray()->GetBoundsInScreen();
  180. const gfx::Point start = tray_bounds.CenterPoint();
  181. const gfx::Point end_inside = start + gfx::Vector2d(0, 10);
  182. GetEventGenerator()->GestureScrollSequence(start, end_inside,
  183. base::Milliseconds(100), 4);
  184. EXPECT_FALSE(IsBubbleShown());
  185. }
  186. TEST_F(TrayEventFilterTest, MessageCenterAndSystemTrayStayOpenTogether) {
  187. AddNotification();
  188. ShowSystemTrayMainView();
  189. EXPECT_TRUE(GetMessageCenterBubble()->GetBubbleWidget()->IsVisible());
  190. EXPECT_TRUE(IsBubbleShown());
  191. // Clicking inside system tray should not close either bubble.
  192. ui::MouseEvent event = inside_event();
  193. GetTrayEventFilter()->OnMouseEvent(&event);
  194. EXPECT_TRUE(GetMessageCenterBubble()->GetBubbleWidget()->IsVisible());
  195. EXPECT_TRUE(IsBubbleShown());
  196. // Clicking inside the message center bubble should not close either bubble.
  197. event = InsideMessageCenterEvent();
  198. GetTrayEventFilter()->OnMouseEvent(&event);
  199. EXPECT_TRUE(GetMessageCenterBubble()->GetBubbleWidget()->IsVisible());
  200. EXPECT_TRUE(IsBubbleShown());
  201. }
  202. TEST_F(TrayEventFilterTest, MessageCenterAndSystemTrayCloseTogether) {
  203. AddNotification();
  204. ShowSystemTrayMainView();
  205. EXPECT_TRUE(IsMessageCenterBubbleShown());
  206. EXPECT_TRUE(IsBubbleShown());
  207. // Clicking outside should close both bubbles.
  208. ui::MouseEvent event = outside_event();
  209. GetTrayEventFilter()->OnMouseEvent(&event);
  210. EXPECT_FALSE(IsMessageCenterBubbleShown());
  211. EXPECT_FALSE(IsBubbleShown());
  212. }
  213. } // namespace
  214. } // namespace ash