1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148

ash / system / toast / anchored_nudge.h [blame]

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_SYSTEM_TOAST_ANCHORED_NUDGE_H_
#define ASH_SYSTEM_TOAST_ANCHORED_NUDGE_H_

#include <string>

#include "ash/ash_export.h"
#include "ash/public/cpp/system/anchored_nudge_data.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_observer.h"
#include "ash/shell_observer.h"
#include "base/functional/callback_forward.h"
#include "base/scoped_observation.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/display/display_observer.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/widget/widget_observer.h"

namespace views {
class Widget;
}  // namespace views

namespace ui {
class GestureEvent;
class MouseEvent;
}  // namespace ui

namespace aura {
class Window;
}

namespace ash {

class SystemNudgeView;

// Creates and manages the widget and contents view for an anchored nudge.
// TODO(b/285988235): `AnchoredNudge` will replace the existing `SystemNudge`
// and take over its name.
class ASH_EXPORT AnchoredNudge : public display::DisplayObserver,
                                 public ShelfObserver,
                                 public ShellObserver,
                                 public views::BubbleDialogDelegateView,
                                 public views::WidgetObserver {
  METADATA_HEADER(AnchoredNudge, views::BubbleDialogDelegateView)

 public:
  AnchoredNudge(AnchoredNudgeData& nudge_data,
                base::RepeatingCallback<void(/*has_hover_or_focus=*/bool)>
                    hover_or_focus_changed_callback);
  AnchoredNudge(const AnchoredNudge&) = delete;
  AnchoredNudge& operator=(const AnchoredNudge&) = delete;
  ~AnchoredNudge() override;

  // views::BubbleDialogDelegateView:
  gfx::Rect GetBubbleBounds() override;
  void OnBeforeBubbleWidgetInit(views::Widget::InitParams* params,
                                views::Widget* widget) const override;

  // views::WidgetDelegate:
  std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
      views::Widget* widget) override;

  // views::View:
  void AddedToWidget() override;
  bool OnMousePressed(const ui::MouseEvent& event) override;
  bool OnMouseDragged(const ui::MouseEvent& event) override;
  void OnMouseReleased(const ui::MouseEvent& event) override;
  void OnGestureEvent(ui::GestureEvent* event) override;

  // ShelfObserver:
  void OnAutoHideStateChanged(ShelfAutoHideState new_state) override;
  void OnHotseatStateChanged(HotseatState old_state,
                             HotseatState new_state) override;

  // ShellObserver:
  void OnShelfAlignmentChanged(aura::Window* root_window,
                               ShelfAlignment old_alignment) override;

  // display::DisplayObserver:
  void OnDisplayMetricsChanged(const display::Display& display,
                               uint32_t changed_metrics) override;

  // views::WidgetObserver:
  void OnWidgetDestroying(views::Widget* widget) override;
  void OnWidgetBoundsChanged(views::Widget* widget,
                             const gfx::Rect& new_bounds) override;

  // Sets the arrow of the nudge based on the `shelf` alignment.
  void SetArrowFromShelf(Shelf* shelf);

  // Sets the default anchor rect for nudges that do not have an `anchor_view`.
  void SetDefaultAnchorRect();

  const std::string& id() const { return id_; }

  NudgeCatalogName catalog_name() const { return catalog_name_; }

 private:
  // Unique id used to find and dismiss the nudge through the manager.
  const std::string id_;

  // Used to identify nudges that share an id but have different catalog names.
  const NudgeCatalogName catalog_name_;

  // Whether the nudge should set its arrow based on shelf alignment.
  const bool anchored_to_shelf_;

  // Whether the nudge should set its bounds anchored by its corners.
  const bool is_corner_anchored_;

  // Whether the nudge should set its parent as the `anchor_view`.
  const bool set_anchor_view_as_parent_ = false;

  // If not null, the nudge will anchor to one of the anchor widget internal
  // corners. Currently only supports anchoring to the bottom corners.
  raw_ptr<views::Widget> anchor_widget_ = nullptr;

  // The corner of the `anchor_widget_` to which the nudge will anchor.
  views::BubbleBorder::Arrow anchor_widget_corner_ =
      views::BubbleBorder::Arrow::BOTTOM_LEFT;

  // Owned by the views hierarchy. Contents view of the anchored nudge.
  raw_ptr<SystemNudgeView> system_nudge_view_ = nullptr;

  // Nudge action callbacks.
  NudgeClickCallback click_callback_;
  NudgeDismissCallback dismiss_callback_;

  // Used to maintain the shelf visible while a shelf-anchored nudge is shown.
  std::unique_ptr<Shelf::ScopedDisableAutoHide> disable_shelf_auto_hide_;

  base::ScopedObservation<views::Widget, views::WidgetObserver>
      anchor_widget_scoped_observation_{this};

  // Used to observe hotseat state to update nudges default location baseline.
  base::ScopedObservation<Shelf, ShelfObserver> shelf_observation_{this};

  // Observes display configuration changes.
  display::ScopedDisplayObserver display_observer_{this};
};

}  // namespace ash

#endif  // ASH_SYSTEM_TOAST_ANCHORED_NUDGE_H_