chromium/ash/wm/window_dimmer.h

// Copyright 2015 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_WM_WINDOW_DIMMER_H_
#define ASH_WM_WINDOW_DIMMER_H_

#include "ash/ash_export.h"
#include "base/memory/raw_ptr.h"
#include "ui/aura/window_observer.h"
#include "ui/color/color_id.h"
#include "ui/color/color_provider_source_observer.h"
#include "ui/wm/public/activation_delegate.h"

namespace ash {

// WindowDimmer creates a window whose opacity is optionally animated by way of
// SetDimOpacity() and whose size matches that of its parent. WindowDimmer is
// intended to be used in cases where a certain set of windows need to appear
// partially obscured. This is achieved by creating WindowDimmer, setting the
// opacity, and then stacking window() above the windows that are to appear
// obscured.
//
// WindowDimmer owns the window it creates, but supports having that window
// deleted out from under it (this generally happens if the parent of the
// window is deleted). If WindowDimmer is deleted and the window it created is
// still valid, then WindowDimmer deletes the window.
class ASH_EXPORT WindowDimmer : public wm::ActivationDelegate,
                                public aura::WindowObserver,
                                public ui::ColorProviderSourceObserver {
 public:
  // Defines an interface for an optional delegate to the WindowDimmer, which
  // will be notified with certain events happening to the window being dimmed.
  class Delegate {
   public:
    // Called when the window being dimmed |dimmed_window| is about to be
    // destroyed.
    // This can be used by the owner of the WindowDimmer to know when it's no
    // longer needed and can be destroyed since the window being dimmed itself
    // is destroying.
    virtual void OnDimmedWindowDestroying(aura::Window* dimmed_window) = 0;

    // Called when the window being dimmed |dimmed_window| changes its parent.
    virtual void OnDimmedWindowParentChanged(aura::Window* dimmed_window) = 0;

   protected:
    virtual ~Delegate() = default;
  };

  // Creates a new WindowDimmer. The window() created by WindowDimmer is added
  // to |parent| and stacked above all other child windows. If |animate| is set
  // to false, the dimming |window_| created by |this| will not animate on its
  // visibility changing, otherwise it'll have a fade animation of a 200-ms
  // duration. |delegate| can be optionally specified to observe some events
  // happening to the window being dimmed (|parent|).
  explicit WindowDimmer(aura::Window* parent,
                        bool animate = true,
                        Delegate* delegate = nullptr);

  WindowDimmer(const WindowDimmer&) = delete;
  WindowDimmer& operator=(const WindowDimmer&) = delete;

  ~WindowDimmer() override;

  aura::Window* window() { return window_; }

  // Set the opacity value of the default dimming color which is Black. If it's
  // desired to specify a certain color with its alpha value, then use the below
  // SetDimColor().
  void SetDimOpacity(float target_opacity);

  // Sets the color of the dimming `window_`'s layer based on the given
  // `color_id`. This color must not be opaque.
  void SetDimColor(ui::ColorId color_id);

  // wm::ActivationDelegate:
  bool ShouldActivate() const override;

  // NOTE: WindowDimmer is an observer for both |parent_| and |window_|.
  // aura::WindowObserver:
  void OnWindowBoundsChanged(aura::Window* window,
                             const gfx::Rect& old_bounds,
                             const gfx::Rect& new_bounds,
                             ui::PropertyChangeReason reason) override;
  void OnWindowDestroying(aura::Window* window) override;
  void OnWindowHierarchyChanging(const HierarchyChangeParams& params) override;
  void OnWindowParentChanged(aura::Window* window,
                             aura::Window* parent) override;
  void OnWindowAddedToRootWindow(aura::Window* window) override;

  // ui::ColorProviderSourceObserver:
  void OnColorProviderChanged() override;

 private:
  // Sets / updates the color of the dimming `window_`'s layer based on
  // `dim_color_type_`.
  void UpdateDimColor();

  raw_ptr<aura::Window> parent_;
  // See class description for details on ownership.
  raw_ptr<aura::Window, DanglingUntriaged> window_;

  raw_ptr<Delegate> delegate_;  // Not owned.

  // Used to get the color for the dimming `window_`'s layer. It's updated
  // through `SetDimColor`. It will be reset when SetDimOpacity() is called.
  std::optional<ui::ColorId> dim_color_type_;
};

}  // namespace ash

#endif  // ASH_WM_WINDOW_DIMMER_H_