app_list_presenter_event_filter.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright 2021 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/app_list/app_list_presenter_event_filter.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "ash/app_list/app_list_controller_impl.h"
  8. #include "ash/app_list/app_list_presenter_impl.h"
  9. #include "ash/app_list/app_list_util.h"
  10. #include "ash/app_list/views/app_list_main_view.h"
  11. #include "ash/app_list/views/search_box_view.h"
  12. #include "ash/bubble/bubble_utils.h"
  13. #include "ash/shelf/back_button.h"
  14. #include "ash/shelf/home_button.h"
  15. #include "ash/shelf/hotseat_widget.h"
  16. #include "ash/shelf/shelf.h"
  17. #include "ash/shelf/shelf_layout_manager.h"
  18. #include "ash/shelf/shelf_navigation_widget.h"
  19. #include "ash/shelf/shelf_widget.h"
  20. #include "ash/shell.h"
  21. #include "ash/system/status_area_widget.h"
  22. #include "base/check.h"
  23. #include "third_party/abseil-cpp/absl/types/optional.h"
  24. #include "ui/aura/window.h"
  25. #include "ui/events/event.h"
  26. #include "ui/gfx/geometry/point.h"
  27. #include "ui/views/view.h"
  28. #include "ui/views/widget/widget.h"
  29. namespace ash {
  30. AppListPresenterEventFilter::AppListPresenterEventFilter(
  31. AppListControllerImpl* controller,
  32. AppListPresenterImpl* presenter,
  33. AppListView* view)
  34. : controller_(controller), presenter_(presenter), view_(view) {
  35. DCHECK(controller_);
  36. DCHECK(presenter_);
  37. DCHECK(view_);
  38. Shell::Get()->AddPreTargetHandler(this);
  39. }
  40. AppListPresenterEventFilter::~AppListPresenterEventFilter() {
  41. Shell::Get()->RemovePreTargetHandler(this);
  42. }
  43. void AppListPresenterEventFilter::OnMouseEvent(ui::MouseEvent* event) {
  44. // Moving the mouse shouldn't hide focus rings.
  45. if (event->IsAnyButton())
  46. controller_->SetKeyboardTraversalMode(false);
  47. if (event->type() == ui::ET_MOUSE_PRESSED)
  48. ProcessLocatedEvent(event);
  49. }
  50. void AppListPresenterEventFilter::OnGestureEvent(ui::GestureEvent* event) {
  51. controller_->SetKeyboardTraversalMode(false);
  52. // Checks tap types instead of ui::ET_TOUCH_PRESSED so that swipes on the
  53. // shelf do not close the launcher. https://crbug.com/750274
  54. if (event->type() == ui::ET_GESTURE_TAP ||
  55. event->type() == ui::ET_GESTURE_TWO_FINGER_TAP ||
  56. event->type() == ui::ET_GESTURE_LONG_PRESS) {
  57. ProcessLocatedEvent(event);
  58. }
  59. }
  60. void AppListPresenterEventFilter::OnKeyEvent(ui::KeyEvent* event) {
  61. // If keyboard traversal is already engaged, no-op.
  62. if (controller_->KeyboardTraversalEngaged())
  63. return;
  64. // If the home launcher is not shown in tablet mode, ignore events.
  65. if (Shell::Get()->IsInTabletMode() && !controller_->IsVisible())
  66. return;
  67. // Don't absorb the first event for the search box while it is open.
  68. if (view_->search_box_view()->is_search_box_active())
  69. return;
  70. // Don't absorb the first event when renaming folder.
  71. if (view_->IsFolderBeingRenamed())
  72. return;
  73. // Arrow keys or Tab will engage the traversal mode.
  74. if ((IsUnhandledArrowKeyEvent(*event) || event->key_code() == ui::VKEY_TAB)) {
  75. // Handle the first arrow key event to just show the focus rings (if not
  76. // showing Assistant). Don't absorb the first event when showing Assistant.
  77. if (!view_->IsShowingEmbeddedAssistantUI())
  78. event->SetHandled();
  79. controller_->SetKeyboardTraversalMode(true);
  80. }
  81. }
  82. void AppListPresenterEventFilter::ProcessLocatedEvent(ui::LocatedEvent* event) {
  83. // Check the general rules for closing bubbles.
  84. if (!bubble_utils::ShouldCloseBubbleForEvent(*event))
  85. return;
  86. aura::Window* target = static_cast<aura::Window*>(event->target());
  87. if (!target)
  88. return;
  89. // If the event happened on the home button's widget, it'll get handled by the
  90. // button.
  91. Shelf* shelf = Shelf::ForWindow(target);
  92. HomeButton* home_button = shelf->navigation_widget()->GetHomeButton();
  93. if (home_button && home_button->GetWidget() &&
  94. target == home_button->GetWidget()->GetNativeWindow()) {
  95. gfx::Point location_in_home_button = event->location();
  96. views::View::ConvertPointFromWidget(home_button, &location_in_home_button);
  97. if (home_button->HitTestPoint(location_in_home_button))
  98. return;
  99. }
  100. // If the event happened on the back button, it'll get handled by the
  101. // button.
  102. BackButton* back_button = shelf->navigation_widget()->GetBackButton();
  103. if (back_button && back_button->GetWidget() &&
  104. target == back_button->GetWidget()->GetNativeWindow()) {
  105. gfx::Point location_in_back_button = event->location();
  106. views::View::ConvertPointFromWidget(back_button, &location_in_back_button);
  107. if (back_button->HitTestPoint(location_in_back_button))
  108. return;
  109. }
  110. aura::Window* window = view_->GetWidget()->GetNativeView()->parent();
  111. if (window->Contains(target))
  112. return;
  113. // Try to close an open folder window: return if an open folder view was
  114. // closed successfully.
  115. if (presenter_->HandleCloseOpenFolder())
  116. return;
  117. if (!Shell::Get()->IsInTabletMode()) {
  118. // Do not dismiss the app list if the event is targeting shelf area
  119. // containing app icons.
  120. if (target == shelf->hotseat_widget()->GetNativeWindow() &&
  121. shelf->hotseat_widget()->EventTargetsShelfView(*event)) {
  122. return;
  123. }
  124. // Don't dismiss the auto-hide shelf if event happened in status area. Then
  125. // the event can still be propagated.
  126. const aura::Window* status_window =
  127. shelf->shelf_widget()->status_area_widget()->GetNativeWindow();
  128. if (status_window && status_window->Contains(target))
  129. return;
  130. // Record the current AppListViewState to be used later for metrics. The
  131. // AppListViewState will change on app launch, so this will record the
  132. // AppListViewState before the app was launched.
  133. controller_->RecordAppListState();
  134. presenter_->Dismiss(event->time_stamp());
  135. }
  136. }
  137. } // namespace ash