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

#ifndef UI_VIEWS_TEST_MOCK_ACTIVATION_CONTROLLER_H_
#define UI_VIEWS_TEST_MOCK_ACTIVATION_CONTROLLER_H_

#include <string>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "ui/views/buildflags.h"
#include "ui/views/widget/widget_activation_delegate.h"
#include "ui/views/widget/widget_observer.h"

// Only desktop aura platforms or macOS needs the activation emulation.
#if BUILDFLAG(ENABLE_DESKTOP_AURA) || BUILDFLAG(IS_MAC)
#define USE_MOCK_ACTIVATION_CONTROLLER 1

namespace views {
class Widget;
namespace test {

// MockActivationController class provides platform-independent widget
// activation by emulating the window stacking, activation, and deactivation.
//
// Normally, the underlying platform/OS handles activation/deactivation, but
// relying on such an environment prevents us from running multiple tests in
// parallel because there is only one active window at a time, and activating a
// window in one test may deactivate a window in another test. This class allows
// such tests to run in parallel.
//
// Caveats:
// 1) Do not use this class directly in test code. Just instantiating this class
// should enable the emulation.
// 2) This can only handle a window created by views::Widget. If you create a
// native window (e.g. aura::Window) without the views framework, it will not be
// emulated. Such a case should not exist, as a window that should be activated
// should have UI elements.
// 3) Mac does not support Widget::Deactivate, but deactivation can still
// happen by hiding a Widget. This class emulates this scenario as well.
// 4) This class is not allowed in interactive_ui_tests by default to ensure
// they use real activation. If you must use it in an interactive_ui_test,
// pass `allow_in_interactive_ui_tests = true` to the constructor.
class MockActivationController : public views::WidgetObserver,
                                 public WidgetActivationDelegate {
 public:
  explicit MockActivationController(bool allow_in_interactive_ui_tests = false);
  MockActivationController(const MockActivationController&) = delete;
  MockActivationController operator=(const MockActivationController&) = delete;
  ~MockActivationController() override;

  void MaybeActivate(Widget* widget, bool activate) override;
  void Deactivate(Widget* widget) override;
  bool IsActive(const Widget* widget) override;
  bool IsTrackedForTesting(const Widget* widget) const;

 private:
  // WidgetObserver:
  void OnWidgetDestroying(Widget* widget) override;
  void OnWidgetVisibilityChanged(Widget* widget, bool visible) override;

  using WidgetList = std::vector<raw_ptr<Widget, VectorExperimental>>;

  Widget* FindActivatableWidget(Widget* skip_widget = nullptr);

  WidgetList widgets_;
  raw_ptr<Widget> active_widget_ = nullptr;
};

}  // namespace test
}  // namespace views

#endif  // BUILDFLAG(ENABLE_DESKTOP_AURA) || BUILDFLAG(IS_MAC)

#endif  // UI_VIEWS_TEST_MOCK_ACTIVATION_CONTROLLER_H_
