shelf_tooltip_manager.cc 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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
  3. // found in the LICENSE file.
  4. #include "ash/shelf/shelf_tooltip_manager.h"
  5. #include <string>
  6. #include "ash/constants/ash_switches.h"
  7. #include "ash/shelf/shelf.h"
  8. #include "ash/shelf/shelf_tooltip_bubble.h"
  9. #include "ash/shelf/shelf_tooltip_delegate.h"
  10. #include "ash/shelf/shelf_tooltip_preview_bubble.h"
  11. #include "ash/shelf/shelf_widget.h"
  12. #include "ash/shell.h"
  13. #include "base/bind.h"
  14. #include "base/threading/thread_task_runner_handle.h"
  15. #include "base/time/time.h"
  16. #include "ui/aura/window.h"
  17. #include "ui/events/event.h"
  18. #include "ui/events/types/event_type.h"
  19. #include "ui/gfx/geometry/insets.h"
  20. #include "ui/wm/core/window_animations.h"
  21. namespace ash {
  22. namespace {
  23. const int kTooltipAppearanceDelay = 250; // msec
  24. } // namespace
  25. ShelfTooltipManager::ShelfTooltipManager(Shelf* shelf)
  26. : timer_delay_(kTooltipAppearanceDelay), shelf_(shelf) {
  27. shelf_->AddObserver(this);
  28. Shell::Get()->AddPreTargetHandler(this);
  29. }
  30. ShelfTooltipManager::~ShelfTooltipManager() {
  31. Shell::Get()->RemovePreTargetHandler(this);
  32. shelf_->RemoveObserver(this);
  33. }
  34. void ShelfTooltipManager::Close(bool animate) {
  35. // Cancel any timer set to show a tooltip after a delay.
  36. timer_.Stop();
  37. if (!bubble_)
  38. return;
  39. if (!animate) {
  40. // Cancel the typical hiding animation to hide the bubble immediately.
  41. ::wm::SetWindowVisibilityAnimationTransition(
  42. bubble_->GetWidget()->GetNativeWindow(), ::wm::ANIMATE_NONE);
  43. }
  44. bubble_->GetWidget()->Close();
  45. bubble_ = nullptr;
  46. }
  47. bool ShelfTooltipManager::IsVisible() const {
  48. return bubble_ && bubble_->GetWidget()->IsVisible();
  49. }
  50. views::View* ShelfTooltipManager::GetCurrentAnchorView() const {
  51. return bubble_ ? bubble_->GetAnchorView() : nullptr;
  52. }
  53. void ShelfTooltipManager::ShowTooltip(views::View* view) {
  54. // Hide the old bubble immediately, skipping the typical closing animation.
  55. Close(false /*animate*/);
  56. if (!ShouldShowTooltipForView(view))
  57. return;
  58. const std::vector<aura::Window*> open_windows =
  59. shelf_tooltip_delegate_->GetOpenWindowsForView(view);
  60. const ShelfAlignment alignment = shelf_->alignment();
  61. if (switches::ShouldShowShelfHoverPreviews() && open_windows.size() > 0) {
  62. bubble_ =
  63. new ShelfTooltipPreviewBubble(view, open_windows, this, alignment);
  64. } else {
  65. bubble_ = new ShelfTooltipBubble(
  66. view, alignment, shelf_tooltip_delegate_->GetTitleForView(view));
  67. }
  68. aura::Window* window = bubble_->GetWidget()->GetNativeWindow();
  69. ::wm::SetWindowVisibilityAnimationType(
  70. window, ::wm::WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL);
  71. ::wm::SetWindowVisibilityAnimationTransition(window, ::wm::ANIMATE_HIDE);
  72. // Do not trigger a highlight when hovering over shelf items.
  73. bubble_->set_highlight_button_when_shown(false);
  74. bubble_->GetWidget()->Show();
  75. }
  76. void ShelfTooltipManager::ShowTooltipWithDelay(views::View* view) {
  77. if (ShouldShowTooltipForView(view)) {
  78. timer_.Start(FROM_HERE, base::Milliseconds(timer_delay_),
  79. base::BindOnce(&ShelfTooltipManager::ShowTooltip,
  80. weak_factory_.GetWeakPtr(), view));
  81. }
  82. }
  83. void ShelfTooltipManager::OnMouseEvent(ui::MouseEvent* event) {
  84. if (bubble_ && event->type() == ui::ET_MOUSE_PRESSED) {
  85. ProcessPressedEvent(*event);
  86. return;
  87. }
  88. if (bubble_ && event->type() == ui::ET_MOUSE_EXITED &&
  89. bubble_->ShouldCloseOnMouseExit()) {
  90. Close();
  91. return;
  92. }
  93. // Happens in tests where mouse events are picked up before
  94. // |shelf_tooltip_delegate_| is set.
  95. if (!shelf_tooltip_delegate_)
  96. return;
  97. views::View* delegate_view = shelf_tooltip_delegate_->GetViewForEvent(*event);
  98. // The code below handles mouse move events within the shelf window.
  99. if (event->type() != ui::ET_MOUSE_MOVED || !delegate_view) {
  100. // Don't show delayed tooltips if the mouse is being active elsewhere.
  101. timer_.Stop();
  102. return;
  103. }
  104. gfx::Point point = event->location();
  105. views::View::ConvertPointFromWidget(delegate_view, &point);
  106. views::View* view = delegate_view->GetTooltipHandlerForPoint(point);
  107. const bool should_show = ShouldShowTooltipForView(view);
  108. timer_.Stop();
  109. if (IsVisible() && should_show && bubble_->GetAnchorView() != view)
  110. ShowTooltip(view);
  111. else if (!IsVisible() && should_show)
  112. ShowTooltipWithDelay(view);
  113. else if (IsVisible() && shelf_tooltip_delegate_->ShouldHideTooltip(point))
  114. Close();
  115. }
  116. void ShelfTooltipManager::OnTouchEvent(ui::TouchEvent* event) {
  117. if (bubble_ && event->type() == ui::ET_TOUCH_PRESSED)
  118. ProcessPressedEvent(*event);
  119. }
  120. void ShelfTooltipManager::OnScrollEvent(ui::ScrollEvent* event) {
  121. // Close any currently shown bubble.
  122. Close();
  123. }
  124. void ShelfTooltipManager::OnKeyEvent(ui::KeyEvent* event) {
  125. // Close any currently shown bubble.
  126. Close();
  127. }
  128. void ShelfTooltipManager::WillChangeVisibilityState(
  129. ShelfVisibilityState new_state) {
  130. if (new_state == SHELF_HIDDEN)
  131. Close();
  132. }
  133. void ShelfTooltipManager::OnAutoHideStateChanged(ShelfAutoHideState new_state) {
  134. if (new_state == SHELF_AUTO_HIDE_HIDDEN)
  135. Close();
  136. }
  137. bool ShelfTooltipManager::ShouldShowTooltipForView(views::View* view) {
  138. const bool shelf_visibility =
  139. shelf_ && (shelf_->GetVisibilityState() == SHELF_VISIBLE ||
  140. (shelf_->GetVisibilityState() == SHELF_AUTO_HIDE &&
  141. shelf_->GetAutoHideState() == SHELF_AUTO_HIDE_SHOWN));
  142. if (!shelf_visibility)
  143. return false;
  144. return shelf_tooltip_delegate_->ShouldShowTooltipForView(view);
  145. }
  146. void ShelfTooltipManager::ProcessPressedEvent(const ui::LocatedEvent& event) {
  147. // Always close the tooltip on press events outside the tooltip.
  148. if (bubble_->ShouldCloseOnPressDown() ||
  149. event.target() != bubble_->GetWidget()->GetNativeWindow()) {
  150. Close();
  151. }
  152. }
  153. } // namespace ash