tray_bubble_view.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. #ifndef ASH_SYSTEM_TRAY_TRAY_BUBBLE_VIEW_H_
  5. #define ASH_SYSTEM_TRAY_TRAY_BUBBLE_VIEW_H_
  6. #include <memory>
  7. #include "ash/ash_export.h"
  8. #include "ash/bubble/bubble_constants.h"
  9. #include "ash/public/cpp/accelerators.h"
  10. #include "ash/public/cpp/shelf_types.h"
  11. #include "ash/system/status_area_widget.h"
  12. #include "base/memory/weak_ptr.h"
  13. #include "third_party/abseil-cpp/absl/types/optional.h"
  14. #include "ui/accessibility/ax_enums.mojom-forward.h"
  15. #include "ui/base/metadata/metadata_header_macros.h"
  16. #include "ui/events/event.h"
  17. #include "ui/gfx/geometry/insets.h"
  18. #include "ui/gfx/geometry/rect.h"
  19. #include "ui/gfx/native_widget_types.h"
  20. #include "ui/views/bubble/bubble_dialog_delegate_view.h"
  21. #include "ui/views/metadata/view_factory.h"
  22. #include "ui/views/mouse_watcher.h"
  23. namespace views {
  24. class BoxLayout;
  25. class View;
  26. class Widget;
  27. } // namespace views
  28. namespace ash {
  29. class SystemShadow;
  30. // Specialized bubble view for bubbles associated with a tray icon (e.g. the
  31. // Ash status area). Mostly this handles custom anchor location and arrow and
  32. // border rendering. This also has its own delegate for handling mouse events
  33. // and other implementation specific details.
  34. class ASH_EXPORT TrayBubbleView : public views::BubbleDialogDelegateView,
  35. public views::MouseWatcherListener {
  36. public:
  37. METADATA_HEADER(TrayBubbleView);
  38. class ASH_EXPORT Delegate {
  39. public:
  40. Delegate();
  41. Delegate(const Delegate&) = delete;
  42. Delegate& operator=(const Delegate&) = delete;
  43. virtual ~Delegate();
  44. // Called when the view is destroyed. Any pointers to the view should be
  45. // cleared when this gets called.
  46. virtual void BubbleViewDestroyed();
  47. // Called when the mouse enters/exits the view.
  48. // Note: This event will only be called if the mouse gets actively moved by
  49. // the user to enter the view.
  50. virtual void OnMouseEnteredView();
  51. virtual void OnMouseExitedView();
  52. // Called from GetAccessibleNodeData(); should return the appropriate
  53. // accessible name for the bubble.
  54. virtual std::u16string GetAccessibleNameForBubble();
  55. // Should return true if extra keyboard accessibility is enabled.
  56. // TrayBubbleView will put focus on the default item if extra keyboard
  57. // accessibility is enabled.
  58. virtual bool ShouldEnableExtraKeyboardAccessibility();
  59. // Called when a bubble wants to hide/destroy itself (e.g. last visible
  60. // child view was closed).
  61. virtual void HideBubble(const TrayBubbleView* bubble_view);
  62. // Returns the accelerator action associated with the delegate's bubble
  63. // view.
  64. virtual absl::optional<AcceleratorAction> GetAcceleratorAction() const;
  65. // Return a WeakPtr to `this`.
  66. base::WeakPtr<Delegate> GetWeakPtr();
  67. private:
  68. base::WeakPtrFactory<Delegate> weak_ptr_factory_{this};
  69. };
  70. // Anchor mode being set at creation.
  71. enum class AnchorMode {
  72. // Anchor to |anchor_view|. This is the default.
  73. kView,
  74. // Anchor to |anchor_rect|. Used for anchoring to the shelf.
  75. kRect
  76. };
  77. struct ASH_EXPORT InitParams {
  78. InitParams();
  79. ~InitParams();
  80. InitParams(const InitParams& other);
  81. // Used by the `tray_bubble_view` to call into its
  82. // respective tray. This needs to be a WeakPtr because it is possible for
  83. // the tray to be destroyed while the bubble is still around. This can
  84. // happen because the bubble's widget is destroyed asynchronously so
  85. // `tray_bubble_view`'s destructor can be called well after it's
  86. // corresponding tray has been cleaned up.
  87. base::WeakPtr<Delegate> delegate = nullptr;
  88. gfx::NativeWindow parent_window = nullptr;
  89. View* anchor_view = nullptr;
  90. AnchorMode anchor_mode = AnchorMode::kView;
  91. // Only used if anchor_mode == AnchorMode::kRect.
  92. gfx::Rect anchor_rect;
  93. bool is_anchored_to_status_area = true;
  94. ShelfAlignment shelf_alignment = ShelfAlignment::kBottom;
  95. int preferred_width = 0;
  96. int max_height = 0;
  97. bool close_on_deactivate = true;
  98. // Indicates whether tray bubble view should add a pre target event handler.
  99. bool reroute_event_handler = false;
  100. int corner_radius = kBubbleCornerRadius;
  101. absl::optional<gfx::Insets> insets;
  102. absl::optional<gfx::Insets> margin;
  103. bool has_shadow = true;
  104. SystemShadow::Type shadow_type = kBubbleShadowType;
  105. // Use half opaque widget instead of fully opaque.
  106. bool translucent = false;
  107. // Whether the view is fully transparent (only serves as a container).
  108. bool transparent = false;
  109. };
  110. explicit TrayBubbleView(const InitParams& init_params);
  111. TrayBubbleView(const TrayBubbleView&) = delete;
  112. TrayBubbleView& operator=(const TrayBubbleView&) = delete;
  113. ~TrayBubbleView() override;
  114. // Sets up animations, and show the bubble. Must occur after CreateBubble()
  115. // is called.
  116. void InitializeAndShowBubble();
  117. // Called whenever the bubble size or location may have changed.
  118. void UpdateBubble();
  119. // Sets the maximum bubble height and resizes the bubble.
  120. void SetMaxHeight(int height);
  121. // Sets the bottom padding that child views will be laid out within.
  122. void SetBottomPadding(int padding);
  123. // Sets the bubble width.
  124. void SetPreferredWidth(int width);
  125. // Returns the border insets. Called by TrayEventFilter.
  126. gfx::Insets GetBorderInsets() const;
  127. // Returns the accelerator action associated with this bubble view.
  128. absl::optional<AcceleratorAction> GetAcceleratorAction() const;
  129. // Called when the delegate is destroyed. This must be called before the
  130. // delegate is actually destroyed. TrayBubbleView will do clean up in
  131. // ResetDelegate.
  132. void ResetDelegate();
  133. // Anchors the bubble to |anchor_view|.
  134. // Only eligible if anchor_mode == AnchorMode::kView.
  135. void ChangeAnchorView(views::View* anchor_view);
  136. // Anchors the bubble to |anchor_rect|. Exclusive with ChangeAnchorView().
  137. // Only eligible if anchor_mode == AnchorMode::kRect.
  138. void ChangeAnchorRect(const gfx::Rect& anchor_rect);
  139. // Change anchor alignment mode when anchoring either the rect or view.
  140. void ChangeAnchorAlignment(ShelfAlignment alignment);
  141. // Returns true if the bubble is an anchored status area bubble. Override
  142. // this function for a bubble which is not anchored directly to the status
  143. // area.
  144. virtual bool IsAnchoredToStatusArea() const;
  145. // Stops rerouting key events to this view. If this view is not currently
  146. // rerouting events, then this function will be idempotent.
  147. void StopReroutingEvents();
  148. Delegate* delegate() { return delegate_.get(); }
  149. void set_gesture_dragging(bool dragging) { is_gesture_dragging_ = dragging; }
  150. bool is_gesture_dragging() const { return is_gesture_dragging_; }
  151. // views::WidgetDelegate:
  152. std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
  153. views::Widget* widget) override;
  154. bool WidgetHasHitTestMask() const override;
  155. void GetWidgetHitTestMask(SkPath* mask) const override;
  156. std::u16string GetAccessibleWindowTitle() const override;
  157. // views::BubbleDialogDelegateView:
  158. void OnWidgetClosing(views::Widget* widget) override;
  159. void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
  160. ui::LayerType GetLayerType() const override;
  161. // views::View:
  162. gfx::Size CalculatePreferredSize() const override;
  163. int GetHeightForWidth(int width) const override;
  164. void OnMouseEntered(const ui::MouseEvent& event) override;
  165. void OnMouseExited(const ui::MouseEvent& event) override;
  166. void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
  167. void OnThemeChanged() override;
  168. // views::MouseWatcherListener:
  169. void MouseMovedOutOfHost() override;
  170. protected:
  171. // views::View:
  172. void ChildPreferredSizeChanged(View* child) override;
  173. // Changes the insets from the bubble border. These were initially set using
  174. // the InitParams.insets, but may need to be reset programmatically.
  175. void SetBubbleBorderInsets(gfx::Insets insets);
  176. private:
  177. // This reroutes receiving key events to the TrayBubbleView passed in the
  178. // constructor. TrayBubbleView is not activated by default. But we want to
  179. // activate it if user tries to interact it with keyboard. To capture those
  180. // key events in early stage, RerouteEventHandler installs this handler to
  181. // aura::Env. RerouteEventHandler also sends key events to ViewsDelegate to
  182. // process accelerator as menu is currently open.
  183. class RerouteEventHandler : public ui::EventHandler {
  184. public:
  185. explicit RerouteEventHandler(TrayBubbleView* tray_bubble_view);
  186. RerouteEventHandler(const RerouteEventHandler&) = delete;
  187. RerouteEventHandler& operator=(const RerouteEventHandler&) = delete;
  188. ~RerouteEventHandler() override;
  189. // Overridden from ui::EventHandler
  190. void OnKeyEvent(ui::KeyEvent* event) override;
  191. private:
  192. // TrayBubbleView to which key events are going to be rerouted. Not owned.
  193. TrayBubbleView* tray_bubble_view_;
  194. };
  195. void CloseBubbleView();
  196. InitParams params_;
  197. views::BoxLayout* layout_;
  198. base::WeakPtr<Delegate> delegate_;
  199. int preferred_width_;
  200. bool is_gesture_dragging_;
  201. // True once the mouse cursor was actively moved by the user over the bubble.
  202. // Only then the OnMouseExitedView() event will get passed on to listeners.
  203. bool mouse_actively_entered_;
  204. // Used to find any mouse movements.
  205. std::unique_ptr<views::MouseWatcher> mouse_watcher_;
  206. // Used to activate tray bubble view if user tries to interact the tray with
  207. // keyboard.
  208. std::unique_ptr<EventHandler> reroute_event_handler_;
  209. std::unique_ptr<SystemShadow> shadow_;
  210. absl::optional<StatusAreaWidget::ScopedTrayBubbleCounter>
  211. tray_bubble_counter_;
  212. };
  213. BEGIN_VIEW_BUILDER(ASH_EXPORT, TrayBubbleView, views::BubbleDialogDelegateView)
  214. END_VIEW_BUILDER
  215. } // namespace ash
  216. DEFINE_VIEW_BUILDER(ASH_EXPORT, ash::TrayBubbleView)
  217. #endif // ASH_SYSTEM_TRAY_TRAY_BUBBLE_VIEW_H_