// Copyright 2016 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_TOAST_OVERLAY_H_
#define ASH_SYSTEM_TOAST_TOAST_OVERLAY_H_
#include <memory>
#include <string>
#include "ash/ash_export.h"
#include "ash/public/cpp/keyboard/keyboard_controller_observer.h"
#include "ash/public/cpp/system/toast_data.h"
#include "ash/shelf/shelf_observer.h"
#include "ash/system/unified/unified_system_tray.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/paint_vector_icon.h"
namespace aura {
class Window;
}
namespace gfx {
class Rect;
}
namespace views {
class LabelButton;
class Widget;
}
namespace ash {
class SystemToastView;
class ToastManagerImplTest;
class ASH_EXPORT ToastOverlay : public ui::ImplicitAnimationObserver,
public KeyboardControllerObserver,
public ShelfObserver,
public UnifiedSystemTray::Observer {
public:
class ASH_EXPORT Delegate {
public:
virtual ~Delegate() {}
virtual void CloseToast() = 0;
// Called when a toast's hover state changed if the toast is supposed to
// persist on hover.
virtual void OnToastHoverStateChanged(bool is_hovering) = 0;
};
// Offset of the overlay from the edge of the work area.
static constexpr int kOffset = 8;
// Creates the Toast overlay UI. `text` is the message to be shown, and
// `dismiss_text` is the dismiss button's text. The dismiss button will only
// be displayed if `dismiss_text` is not empty. `dismiss_callback` will be
// called when the dismiss button is pressed. An icon will show on the left
// side if `leading_icon` is not empty.
// To test different Toast UI variations, enable debug shortcuts by building
// with flag `--ash-debug-shortcuts` and use command "Shift + Ctrl + Alt + O".
ToastOverlay(Delegate* delegate,
const ToastData& toast_data,
aura::Window* root_window);
ToastOverlay(const ToastOverlay&) = delete;
ToastOverlay& operator=(const ToastOverlay&) = delete;
~ToastOverlay() override;
// Shows or hides the overlay.
void Show(bool visible);
// Update the position and size of toast.
void UpdateOverlayBounds();
const std::u16string GetText() const;
// Requests focus on the toast's dismiss button. Return true if it was
// successful.
bool RequestFocusOnActiveToastDismissButton();
// Returns if the dismiss button is focused in the toast. If the toast does
// not have a dismiss button, it returns false.
bool IsDismissButtonFocused() const;
// UnifiedSystemTray::Observer:
void OnSliderBubbleHeightChanged() override;
private:
friend class ToastManagerImplTest;
friend class DesksTestApi;
class ToastDisplayObserver;
class ToastHoverObserver;
// Returns the current bounds of the overlay, which is based on visibility.
gfx::Rect CalculateOverlayBounds();
// Calculates the y offset used to shift side aligned toasts up whenever a
// slider bubble is visible.
int CalculateSliderBubbleOffset();
// Executed the callback and closes the toast.
void OnButtonClicked();
// Callback called by `hover_observer_` when the mouse hover enters or exits
// the toast.
void OnHoverStateChanged(bool is_hovering);
// ui::ImplicitAnimationObserver:
void OnImplicitAnimationsScheduled() override;
void OnImplicitAnimationsCompleted() override;
// KeyboardControllerObserver:
void OnKeyboardOccludedBoundsChanged(const gfx::Rect& new_bounds) override;
// ShelfObserver:
void OnShelfWorkAreaInsetsChanged() override;
void OnHotseatStateChanged(HotseatState old_state,
HotseatState new_state) override;
views::Widget* widget_for_testing();
views::LabelButton* dismiss_button_for_testing();
const raw_ptr<Delegate> delegate_;
const std::u16string text_;
const std::u16string dismiss_text_;
std::unique_ptr<views::Widget> overlay_widget_;
std::unique_ptr<SystemToastView> overlay_view_;
std::unique_ptr<ToastDisplayObserver> display_observer_;
raw_ptr<aura::Window> root_window_;
base::RepeatingClosure dismiss_callback_;
// Used to pause and resume the `ToastManagerImpl`'s
// `current_toast_expiration_timer_` if we are allowing for the toast to
// persist on hover.
std::unique_ptr<ToastHoverObserver> hover_observer_;
base::ScopedObservation<UnifiedSystemTray, UnifiedSystemTray::Observer>
scoped_unified_system_tray_observer_{this};
// Used to observe shelf and hotseat state to update toast baseline.
base::ScopedObservation<Shelf, ShelfObserver> shelf_observation_{this};
};
} // namespace ash
#endif // ASH_SYSTEM_TOAST_TOAST_OVERLAY_H_