910e62b5创建于 1月15日历史提交
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/wm/core/focus_controller.h"

#include <map>

#include "base/memory/raw_ptr.h"
#include "base/test/scoped_feature_list.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/default_capture_client.h"
#include "ui/aura/client/focus_change_observer.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/aura/window_tracker.h"
#include "ui/base/mojom/ui_base_types.mojom-shared.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/event_handler.h"
#include "ui/events/test/event_generator.h"
#include "ui/wm/core/base_focus_rules.h"
#include "ui/wm/core/window_util.h"
#include "ui/wm/public/activation_change_observer.h"
#include "ui/wm/public/activation_client.h"

// EXPECT_DCHECK executes statement and expects a DCHECK death when DCHECK is
// enabled.
#if DCHECK_IS_ON()
#define EXPECT_DCHECK(statement, regex) \
  EXPECT_DEATH_IF_SUPPORTED(statement, regex)
#else
#define EXPECT_DCHECK(statement, regex) \
  { statement; }
#endif

namespace wm {

class FocusNotificationObserver : public ActivationChangeObserver,
                                  public aura::client::FocusChangeObserver {
 public:
  FocusNotificationObserver()
      : last_activation_reason_(ActivationReason::ACTIVATION_CLIENT),
        activation_changed_count_(0),
        focus_changed_count_(0),
        reactivation_count_(0),
        reactivation_requested_window_(nullptr),
        reactivation_actual_window_(nullptr) {}

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

  ~FocusNotificationObserver() override {}

  void ExpectCounts(int activation_changed_count, int focus_changed_count) {
    EXPECT_EQ(activation_changed_count, activation_changed_count_);
    EXPECT_EQ(focus_changed_count, focus_changed_count_);
  }
  ActivationReason last_activation_reason() const {
    return last_activation_reason_;
  }
  int reactivation_count() const { return reactivation_count_; }
  aura::Window* reactivation_requested_window() const {
    return reactivation_requested_window_;
  }
  aura::Window* reactivation_actual_window() const {
    return reactivation_actual_window_;
  }

 private:
  // Overridden from ActivationChangeObserver:
  void OnWindowActivated(ActivationReason reason,
                         aura::Window* gained_active,
                         aura::Window* lost_active) override {
    last_activation_reason_ = reason;
    ++activation_changed_count_;
  }
  void OnAttemptToReactivateWindow(aura::Window* request_active,
                                   aura::Window* actual_active) override {
    ++reactivation_count_;
    reactivation_requested_window_ = request_active;
    reactivation_actual_window_ = actual_active;
  }

  // Overridden from aura::client::FocusChangeObserver:
  void OnWindowFocused(aura::Window* gained_focus,
                       aura::Window* lost_focus) override {
    ++focus_changed_count_;
  }

  ActivationReason last_activation_reason_;
  int activation_changed_count_;
  int focus_changed_count_;
  int reactivation_count_;
  raw_ptr<aura::Window> reactivation_requested_window_;
  raw_ptr<aura::Window> reactivation_actual_window_;
};

class WindowDeleter {
 public:
  virtual aura::Window* GetDeletedWindow() = 0;

 protected:
  virtual ~WindowDeleter() {}
};

// ActivationChangeObserver and FocusChangeObserver that keeps track of whether
// it was notified about activation changes or focus changes with a deleted
// window.
class RecordingActivationAndFocusChangeObserver
    : public ActivationChangeObserver,
      public aura::client::FocusChangeObserver {
 public:
  RecordingActivationAndFocusChangeObserver(aura::Window* root,
                                            WindowDeleter* deleter)
      : root_(root),
        deleter_(deleter),
        was_notified_with_deleted_window_(false) {
    GetActivationClient(root_)->AddObserver(this);
    aura::client::GetFocusClient(root_)->AddObserver(this);
  }

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

  ~RecordingActivationAndFocusChangeObserver() override {
    GetActivationClient(root_)->RemoveObserver(this);
    aura::client::GetFocusClient(root_)->RemoveObserver(this);
  }

  bool was_notified_with_deleted_window() const {
    return was_notified_with_deleted_window_;
  }

  // Overridden from ActivationChangeObserver:
  void OnWindowActivating(ActivationReason reason,
                          aura::Window* gaining_active,
                          aura::Window* losing_active) override {
    if (deleter_->GetDeletedWindow()) {
      // A deleted window during activation should never be return as either the
      // gaining or losing active windows, nor should it be returned as the
      // currently active one.
      auto* active_window = GetActivationClient(root_)->GetActiveWindow();
      EXPECT_NE(active_window, deleter_->GetDeletedWindow());
      EXPECT_NE(gaining_active, deleter_->GetDeletedWindow());
      EXPECT_NE(losing_active, deleter_->GetDeletedWindow());
    }
  }

  void OnWindowActivated(ActivationReason reason,
                         aura::Window* gained_active,
                         aura::Window* lost_active) override {
    if (lost_active && lost_active == deleter_->GetDeletedWindow())
      was_notified_with_deleted_window_ = true;
  }

  // Overridden from aura::client::FocusChangeObserver:
  void OnWindowFocused(aura::Window* gained_focus,
                       aura::Window* lost_focus) override {
    if (lost_focus && lost_focus == deleter_->GetDeletedWindow())
      was_notified_with_deleted_window_ = true;
  }

 private:
  raw_ptr<aura::Window> root_;

  // Not owned.
  raw_ptr<WindowDeleter> deleter_;

  // Whether the observer was notified about the loss of activation or the
  // loss of focus with a window already deleted by |deleter_| as the
  // |lost_active| or |lost_focus| parameter.
  bool was_notified_with_deleted_window_;
};

// Hides a window when activation changes.
class HideOnLoseActivationChangeObserver : public ActivationChangeObserver {
 public:
  explicit HideOnLoseActivationChangeObserver(aura::Window* window_to_hide)
      : root_(window_to_hide->GetRootWindow()),
        window_to_hide_(window_to_hide) {
    GetActivationClient(root_)->AddObserver(this);
  }

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

  ~HideOnLoseActivationChangeObserver() override {
    GetActivationClient(root_)->RemoveObserver(this);
  }

  aura::Window* window_to_hide() { return window_to_hide_; }

 private:
  // Overridden from ActivationChangeObserver:
  void OnWindowActivated(ActivationReason reason,
                         aura::Window* gained_active,
                         aura::Window* lost_active) override {
    if (window_to_hide_) {
      aura::Window* window_to_hide = window_to_hide_;
      window_to_hide_ = nullptr;
      window_to_hide->Hide();
    }
  }

  raw_ptr<aura::Window> root_;
  raw_ptr<aura::Window> window_to_hide_;
};

// ActivationChangeObserver that deletes the window losing activation.
class DeleteOnActivationChangeObserver : public ActivationChangeObserver,
                                         public WindowDeleter {
 public:
  // If |delete_on_activating| is true, |window| will be deleted when
  // OnWindowActivating() is called, otherwise, it will be deleted when
  // OnWindowActivated() is called.
  // If |delete_window_losing_active| is true, |window| will be deleted if it is
  // the window losing activation, otherwise, will be deleted if it is the one
  // gaining activation.
  DeleteOnActivationChangeObserver(aura::Window* window,
                                   bool delete_on_activating,
                                   bool delete_window_losing_active)
      : root_(window->GetRootWindow()),
        window_(window),
        delete_on_activating_(delete_on_activating),
        delete_window_losing_active_(delete_window_losing_active),
        did_delete_(false) {
    GetActivationClient(root_)->AddObserver(this);
  }

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

  ~DeleteOnActivationChangeObserver() override {
    GetActivationClient(root_)->RemoveObserver(this);
  }

  // Overridden from ActivationChangeObserver:
  void OnWindowActivating(ActivationReason reason,
                          aura::Window* gaining_active,
                          aura::Window* losing_active) override {
    if (!delete_on_activating_)
      return;

    auto* window_to_delete =
        delete_window_losing_active_ ? losing_active : gaining_active;
    if (window_ && window_to_delete == window_) {
      delete window_to_delete;
      did_delete_ = true;
    }
  }

  void OnWindowActivated(ActivationReason reason,
                         aura::Window* gained_active,
                         aura::Window* lost_active) override {
    if (delete_on_activating_)
      return;

    auto* window_to_delete =
        delete_window_losing_active_ ? lost_active : gained_active;
    if (window_ && window_to_delete == window_) {
      delete window_to_delete;
      did_delete_ = true;
    }
  }

  // Overridden from WindowDeleter:
  aura::Window* GetDeletedWindow() override {
    return did_delete_ ? window_.get() : nullptr;
  }

 private:
  raw_ptr<aura::Window> root_;
  raw_ptr<aura::Window, DanglingUntriaged> window_;
  const bool delete_on_activating_;
  const bool delete_window_losing_active_;
  bool did_delete_;
};

// FocusChangeObserver that deletes the window losing focus.
class DeleteOnLoseFocusChangeObserver
    : public aura::client::FocusChangeObserver,
      public WindowDeleter {
 public:
  explicit DeleteOnLoseFocusChangeObserver(aura::Window* window)
      : root_(window->GetRootWindow()), window_(window), did_delete_(false) {
    aura::client::GetFocusClient(root_)->AddObserver(this);
  }

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

  ~DeleteOnLoseFocusChangeObserver() override {
    aura::client::GetFocusClient(root_)->RemoveObserver(this);
  }

  // Overridden from aura::client::FocusChangeObserver:
  void OnWindowFocused(aura::Window* gained_focus,
                       aura::Window* lost_focus) override {
    if (window_ && lost_focus == window_) {
      delete lost_focus;
      did_delete_ = true;
    }
  }

  // Overridden from WindowDeleter:
  aura::Window* GetDeletedWindow() override {
    return did_delete_ ? window_.get() : nullptr;
  }

 private:
  raw_ptr<aura::Window> root_;
  raw_ptr<aura::Window, DanglingUntriaged> window_;
  bool did_delete_;
};

class ScopedFocusNotificationObserver : public FocusNotificationObserver {
 public:
  ScopedFocusNotificationObserver(aura::Window* root_window)
      : root_window_(root_window) {
    GetActivationClient(root_window_)->AddObserver(this);
    aura::client::GetFocusClient(root_window_)->AddObserver(this);
  }

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

  ~ScopedFocusNotificationObserver() override {
    GetActivationClient(root_window_)->RemoveObserver(this);
    aura::client::GetFocusClient(root_window_)->RemoveObserver(this);
  }

 private:
  raw_ptr<aura::Window> root_window_;
};

class ScopedTargetFocusNotificationObserver : public FocusNotificationObserver {
 public:
  ScopedTargetFocusNotificationObserver(aura::Window* root_window, int id)
      : target_(root_window->GetChildById(id)) {
    SetActivationChangeObserver(target_, this);
    aura::client::SetFocusChangeObserver(target_, this);
    tracker_.Add(target_);
  }

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

  ~ScopedTargetFocusNotificationObserver() override {
    if (tracker_.Contains(target_)) {
      SetActivationChangeObserver(target_, nullptr);
      aura::client::SetFocusChangeObserver(target_, nullptr);
    }
  }

 private:
  raw_ptr<aura::Window, DanglingUntriaged> target_;
  aura::WindowTracker tracker_;
};

// Used to fake the handling of events in the pre-target phase.
class SimpleEventHandler : public ui::EventHandler {
 public:
  SimpleEventHandler() {}

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

  ~SimpleEventHandler() override {}

  // Overridden from ui::EventHandler:
  void OnMouseEvent(ui::MouseEvent* event) override { event->SetHandled(); }
  void OnGestureEvent(ui::GestureEvent* event) override { event->SetHandled(); }
};

class FocusShiftingActivationObserver : public ActivationChangeObserver {
 public:
  explicit FocusShiftingActivationObserver(aura::Window* activated_window)
      : activated_window_(activated_window), shift_focus_to_(nullptr) {}

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

  ~FocusShiftingActivationObserver() override {}

  void set_shift_focus_to(aura::Window* shift_focus_to) {
    shift_focus_to_ = shift_focus_to;
  }

 private:
  // Overridden from ActivationChangeObserver:
  void OnWindowActivated(ActivationReason reason,
                         aura::Window* gained_active,
                         aura::Window* lost_active) override {
    // Shift focus to a child. This should prevent the default focusing from
    // occurring in FocusController::FocusWindow().
    if (gained_active == activated_window_) {
      aura::client::FocusClient* client =
          aura::client::GetFocusClient(gained_active);
      client->FocusWindow(shift_focus_to_);
    }
  }

  raw_ptr<aura::Window> activated_window_;
  raw_ptr<aura::Window> shift_focus_to_;
};

class ActivateWhileActivatingObserver : public ActivationChangeObserver {
 public:
  ActivateWhileActivatingObserver(aura::Window* to_observe,
                                  aura::Window* to_activate,
                                  aura::Window* to_focus)
      : to_observe_(to_observe),
        to_activate_(to_activate),
        to_focus_(to_focus) {
    GetActivationClient(to_observe_->GetRootWindow())->AddObserver(this);
  }

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

  ~ActivateWhileActivatingObserver() override {
    GetActivationClient(to_observe_->GetRootWindow())->RemoveObserver(this);
  }

 private:
  // Overridden from ActivationChangeObserver:
  void OnWindowActivating(ActivationReason reason,
                          aura::Window* gaining_active,
                          aura::Window* losing_active) override {
    if (gaining_active != to_observe_)
      return;

    if (to_activate_)
      ActivateWindow(to_activate_);
    if (to_focus_)
      FocusWindow(to_focus_);
  }
  void OnWindowActivated(ActivationReason reason,
                         aura::Window* gained_active,
                         aura::Window* lost_active) override {}

  void ActivateWindow(aura::Window* window) {
    GetActivationClient(to_observe_->GetRootWindow())->ActivateWindow(window);
  }

  void FocusWindow(aura::Window* window) {
    aura::client::GetFocusClient(to_observe_->GetRootWindow())
        ->FocusWindow(window);
  }

  raw_ptr<aura::Window> to_observe_;
  raw_ptr<aura::Window> to_activate_;
  raw_ptr<aura::Window> to_focus_;
};

// BaseFocusRules subclass that allows basic overrides of focus/activation to
// be tested. This is intended more as a test that the override system works at
// all, rather than as an exhaustive set of use cases, those should be covered
// in tests for those FocusRules implementations.
class TestFocusRules : public BaseFocusRules {
 public:
  TestFocusRules() : focus_restriction_(nullptr) {}

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

  // Restricts focus and activation to this window and its child hierarchy.
  void set_focus_restriction(aura::Window* focus_restriction) {
    focus_restriction_ = focus_restriction;
  }

  // Overridden from BaseFocusRules:
  bool SupportsChildActivation(const aura::Window* window) const override {
    // In FocusControllerTests, only the RootWindow has activatable children.
    return window->GetRootWindow() == window;
  }
  bool CanActivateWindow(const aura::Window* window) const override {
    // Restricting focus to a non-activatable child window means the activatable
    // parent outside the focus restriction is activatable.
    bool can_activate =
        CanFocusOrActivate(window) || window->Contains(focus_restriction_);
    return can_activate ? BaseFocusRules::CanActivateWindow(window) : false;
  }
  bool CanFocusWindow(const aura::Window* window,
                      const ui::Event* event) const override {
    return CanFocusOrActivate(window)
               ? BaseFocusRules::CanFocusWindow(window, event)
               : false;
  }
  aura::Window* GetActivatableWindow(aura::Window* window) const override {
    return BaseFocusRules::GetActivatableWindow(
        CanFocusOrActivate(window) ? window : focus_restriction_.get());
  }
  aura::Window* GetFocusableWindow(aura::Window* window) const override {
    return BaseFocusRules::GetFocusableWindow(
        CanFocusOrActivate(window) ? window : focus_restriction_.get());
  }
  aura::Window* GetNextActivatableWindow(aura::Window* ignore) const override {
    aura::Window* next_activatable =
        BaseFocusRules::GetNextActivatableWindow(ignore);
    return CanFocusOrActivate(next_activatable)
               ? next_activatable
               : GetActivatableWindow(focus_restriction_);
  }

 private:
  bool CanFocusOrActivate(const aura::Window* window) const {
    return !focus_restriction_ || focus_restriction_->Contains(window);
  }

  raw_ptr<aura::Window> focus_restriction_;
};

// Common infrastructure shared by all FocusController test types.
class FocusControllerTestBase : public aura::test::AuraTestBase {
 public:
  FocusControllerTestBase(const FocusControllerTestBase&) = delete;
  FocusControllerTestBase& operator=(const FocusControllerTestBase&) = delete;

 protected:
  FocusControllerTestBase() {}

  // Overridden from aura::test::AuraTestBase:
  void SetUp() override {
    // FocusController registers itself as an Env observer so it can catch all
    // window initializations, including the root_window()'s, so we create it
    // before allowing the base setup.
    test_focus_rules_ = new TestFocusRules;
    focus_controller_ = std::make_unique<FocusController>(test_focus_rules_);
    aura::test::AuraTestBase::SetUp();
    root_window()->AddPreTargetHandler(focus_controller_.get());
    aura::client::SetFocusClient(root_window(), focus_controller_.get());
    SetActivationClient(root_window(), focus_controller_.get());

    // Hierarchy used by all tests:
    // root_window
    //       +-- w1
    //       |    +-- w11
    //       |    +-- w12
    //       +-- w2
    //       |    +-- w21
    //       |         +-- w211
    //       +-- w3
    aura::Window* w1 =
        aura::test::CreateTestWindow(
            {.delegate =
                 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
             .parent = root_window(),
             .bounds = {50, 50},
             .window_id = 1})
            .release();
    aura::test::CreateTestWindow(
        {.delegate =
             aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
         .parent = w1,
         .bounds = {5, 5, 10, 10},
         .window_id = 11})
        .release();
    aura::test::CreateTestWindow(
        {.delegate =
             aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
         .parent = w1,
         .bounds = {15, 15, 10, 10},
         .window_id = 12})
        .release();
    aura::Window* w2 =
        aura::test::CreateTestWindow(
            {.delegate =
                 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
             .parent = root_window(),
             .bounds = {75, 75, 50, 50},
             .window_id = 2})
            .release();
    aura::Window* w21 =
        aura::test::CreateTestWindow(
            {.delegate =
                 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
             .parent = w2,
             .bounds = {5, 5, 10, 10},
             .window_id = 21})
            .release();
    aura::test::CreateTestWindow(
        {.delegate =
             aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
         .parent = w21,
         .bounds = {1, 1, 5, 5},
         .window_id = 211})
        .release();
    aura::test::CreateTestWindow(
        {.delegate =
             aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
         .parent = root_window(),
         .bounds = {125, 125, 50, 50},
         .window_id = 3})
        .release();
  }
  void TearDown() override {
    root_window()->RemovePreTargetHandler(focus_controller_.get());
    aura::test::AuraTestBase::TearDown();
    test_focus_rules_ = nullptr;  // Owned by FocusController.
    focus_controller_.reset();
  }

  void FocusWindow(aura::Window* window) {
    aura::client::GetFocusClient(root_window())->FocusWindow(window);
  }
  aura::Window* GetFocusedWindow() {
    return aura::client::GetFocusClient(root_window())->GetFocusedWindow();
  }
  int GetFocusedWindowId() {
    aura::Window* focused_window = GetFocusedWindow();
    return focused_window ? focused_window->GetId() : -1;
  }
  void ActivateWindow(aura::Window* window) {
    GetActivationClient(root_window())->ActivateWindow(window);
  }
  void DeactivateWindow(aura::Window* window) {
    GetActivationClient(root_window())->DeactivateWindow(window);
  }
  aura::Window* GetActiveWindow() {
    return GetActivationClient(root_window())->GetActiveWindow();
  }
  int GetActiveWindowId() {
    aura::Window* active_window = GetActiveWindow();
    return active_window ? active_window->GetId() : -1;
  }

  TestFocusRules* test_focus_rules() { return test_focus_rules_; }

  // Test functions.
  virtual void BasicFocus() = 0;
  virtual void BasicActivation() = 0;
  virtual void FocusEvents() = 0;
  virtual void DuplicateFocusEvents() {}
  virtual void ActivationEvents() = 0;
  virtual void ReactivationEvents() {}
  virtual void DuplicateActivationEvents() {}
  virtual void ShiftFocusWithinActiveWindow() {}
  virtual void ShiftFocusToChildOfInactiveWindow() {}
  virtual void ShiftFocusToParentOfFocusedWindow() {}
  virtual void FocusRulesOverride() = 0;
  virtual void ActivationRulesOverride() = 0;
  virtual void ShiftFocusOnActivation() {}
  virtual void ShiftFocusOnActivationDueToHide() {}
  virtual void NoShiftActiveOnActivation() {}
  virtual void FocusChangeDuringDrag() {}
  virtual void ChangeFocusWhenNothingFocusedAndCaptured() {}
  virtual void DontPassDeletedWindow() {}
  virtual void StackWindowAtTopOnActivation() {}
  virtual void HideFocusedWindowDuringActivationLoss() {}
  virtual void ActivateWhileActivating() {}

 private:
  std::unique_ptr<FocusController> focus_controller_;
  raw_ptr<TestFocusRules> test_focus_rules_;
};

// Test base for tests where focus is directly set to a target window.
class FocusControllerDirectTestBase : public FocusControllerTestBase {
 public:
  FocusControllerDirectTestBase(const FocusControllerDirectTestBase&) = delete;
  FocusControllerDirectTestBase& operator=(
      const FocusControllerDirectTestBase&) = delete;

 protected:
  FocusControllerDirectTestBase() {}

  // Different test types shift focus in different ways.
  virtual void FocusWindowDirect(aura::Window* window) = 0;
  virtual void ActivateWindowDirect(aura::Window* window) = 0;
  virtual void DeactivateWindowDirect(aura::Window* window) = 0;

  // Input events do not change focus if the window can not be focused.
  virtual bool IsInputEvent() = 0;

  // Returns the expected ActivationReason caused by calling the
  // ActivatedWindowDirect(...) or DeactivateWindowDirect(...) methods.
  virtual ActivationChangeObserver::ActivationReason
  GetExpectedActivationReason() const = 0;

  void FocusWindowById(int id) {
    aura::Window* window = root_window()->GetChildById(id);
    DCHECK(window);
    FocusWindowDirect(window);
  }
  void ActivateWindowById(int id) {
    aura::Window* window = root_window()->GetChildById(id);
    DCHECK(window);
    ActivateWindowDirect(window);
  }

  void DeactivateWindowById(int id) {
    aura::Window* window = root_window()->GetChildById(id);
    EXPECT_TRUE(window);
    GetActivationClient(root_window())->DeactivateWindow(window);
  }

  // Overridden from FocusControllerTestBase:
  void BasicFocus() override {
    EXPECT_FALSE(GetFocusedWindow());
    FocusWindowById(1);
    EXPECT_EQ(1, GetFocusedWindowId());
    FocusWindowById(2);
    EXPECT_EQ(2, GetFocusedWindowId());
  }
  void BasicActivation() override {
    EXPECT_FALSE(GetActiveWindow());
    ActivateWindowById(1);
    EXPECT_EQ(1, GetActiveWindowId());
    ActivateWindowById(2);
    EXPECT_EQ(2, GetActiveWindowId());
    // Create a new window without activing it. Move it to the
    // top.
    aura::Window* window3 = root_window()->GetChildById(3);
    root_window()->StackChildAtTop(window3);

    // Verify that diactivating a non-active window won't affect the current
    // active window.
    DeactivateWindowById(1);
    EXPECT_EQ(2, GetActiveWindowId());

    // Verify that attempting to deactivate NULL does not crash and does not
    // change activation.
    DeactivateWindow(nullptr);
    EXPECT_EQ(2, GetActiveWindowId());
    DeactivateWindow(GetActiveWindow());
    EXPECT_EQ(3, GetActiveWindowId());
  }
  void FocusEvents() override {
    ScopedFocusNotificationObserver root_observer(root_window());
    ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
    ScopedTargetFocusNotificationObserver observer2(root_window(), 2);

    root_observer.ExpectCounts(0, 0);
    observer1.ExpectCounts(0, 0);
    observer2.ExpectCounts(0, 0);

    FocusWindowById(1);
    root_observer.ExpectCounts(1, 1);
    observer1.ExpectCounts(1, 1);
    observer2.ExpectCounts(0, 0);

    FocusWindowById(2);
    root_observer.ExpectCounts(2, 2);
    observer1.ExpectCounts(2, 2);
    observer2.ExpectCounts(1, 1);
  }
  void DuplicateFocusEvents() override {
    // Focusing an existing focused window should not resend focus events.
    ScopedFocusNotificationObserver root_observer(root_window());
    ScopedTargetFocusNotificationObserver observer1(root_window(), 1);

    root_observer.ExpectCounts(0, 0);
    observer1.ExpectCounts(0, 0);

    FocusWindowById(1);
    root_observer.ExpectCounts(1, 1);
    observer1.ExpectCounts(1, 1);

    FocusWindowById(1);
    root_observer.ExpectCounts(1, 1);
    observer1.ExpectCounts(1, 1);
  }
  void ActivationEvents() override {
    ActivateWindowById(1);

    ScopedFocusNotificationObserver root_observer(root_window());
    ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
    ScopedTargetFocusNotificationObserver observer2(root_window(), 2);

    root_observer.ExpectCounts(0, 0);
    observer1.ExpectCounts(0, 0);
    observer2.ExpectCounts(0, 0);

    ActivateWindowById(2);
    root_observer.ExpectCounts(1, 1);
    EXPECT_EQ(GetExpectedActivationReason(),
              root_observer.last_activation_reason());
    observer1.ExpectCounts(1, 1);
    observer2.ExpectCounts(1, 1);
  }
  void ReactivationEvents() override {
    ActivateWindowById(1);
    ScopedFocusNotificationObserver root_observer(root_window());
    EXPECT_EQ(0, root_observer.reactivation_count());
    root_window()->GetChildById(2)->Hide();
    // When we attempt to activate "2", which cannot be activated because it
    // is not visible, "1" will be reactivated.
    ActivateWindowById(2);
    EXPECT_EQ(1, root_observer.reactivation_count());
    EXPECT_EQ(root_window()->GetChildById(2),
              root_observer.reactivation_requested_window());
    EXPECT_EQ(root_window()->GetChildById(1),
              root_observer.reactivation_actual_window());
  }
  void DuplicateActivationEvents() override {
    // Activating an existing active window should not resend activation events.
    ActivateWindowById(1);

    ScopedFocusNotificationObserver root_observer(root_window());
    ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
    ScopedTargetFocusNotificationObserver observer2(root_window(), 2);

    root_observer.ExpectCounts(0, 0);
    observer1.ExpectCounts(0, 0);
    observer2.ExpectCounts(0, 0);

    ActivateWindowById(2);
    root_observer.ExpectCounts(1, 1);
    observer1.ExpectCounts(1, 1);
    observer2.ExpectCounts(1, 1);

    ActivateWindowById(2);
    root_observer.ExpectCounts(1, 1);
    observer1.ExpectCounts(1, 1);
    observer2.ExpectCounts(1, 1);
  }
  void ShiftFocusWithinActiveWindow() override {
    ActivateWindowById(1);
    EXPECT_EQ(1, GetActiveWindowId());
    EXPECT_EQ(1, GetFocusedWindowId());
    FocusWindowById(11);
    EXPECT_EQ(11, GetFocusedWindowId());
    FocusWindowById(12);
    EXPECT_EQ(12, GetFocusedWindowId());
  }
  void ShiftFocusToChildOfInactiveWindow() override {
    ActivateWindowById(2);
    EXPECT_EQ(2, GetActiveWindowId());
    EXPECT_EQ(2, GetFocusedWindowId());
    FocusWindowById(11);
    EXPECT_EQ(1, GetActiveWindowId());
    EXPECT_EQ(11, GetFocusedWindowId());
  }
  void ShiftFocusToParentOfFocusedWindow() override {
    ActivateWindowById(1);
    EXPECT_EQ(1, GetFocusedWindowId());
    FocusWindowById(11);
    EXPECT_EQ(11, GetFocusedWindowId());
    FocusWindowById(1);
    // Focus should _not_ shift to the parent of the already-focused window.
    EXPECT_EQ(11, GetFocusedWindowId());
  }
  void FocusRulesOverride() override {
    EXPECT_FALSE(GetFocusedWindow());
    FocusWindowById(11);
    EXPECT_EQ(11, GetFocusedWindowId());

    test_focus_rules()->set_focus_restriction(root_window()->GetChildById(211));
    FocusWindowById(12);
    // Input events leave focus unchanged; direct API calls will change focus
    // to the restricted window.
    int focused_window = IsInputEvent() ? 11 : 211;
    EXPECT_EQ(focused_window, GetFocusedWindowId());

    test_focus_rules()->set_focus_restriction(nullptr);
    FocusWindowById(12);
    EXPECT_EQ(12, GetFocusedWindowId());
  }
  void ActivationRulesOverride() override {
    ActivateWindowById(1);
    EXPECT_EQ(1, GetActiveWindowId());
    EXPECT_EQ(1, GetFocusedWindowId());

    aura::Window* w3 = root_window()->GetChildById(3);
    test_focus_rules()->set_focus_restriction(w3);

    ActivateWindowById(2);
    // Input events leave activation unchanged; direct API calls will activate
    // the restricted window.
    int active_window = IsInputEvent() ? 1 : 3;
    EXPECT_EQ(active_window, GetActiveWindowId());
    EXPECT_EQ(active_window, GetFocusedWindowId());

    test_focus_rules()->set_focus_restriction(nullptr);
    ActivateWindowById(2);
    EXPECT_EQ(2, GetActiveWindowId());
    EXPECT_EQ(2, GetFocusedWindowId());
  }
  void ShiftFocusOnActivation() override {
    // When a window is activated, by default that window is also focused.
    // An ActivationChangeObserver may shift focus to another window within the
    // same activatable window.
    ActivateWindowById(2);
    EXPECT_EQ(2, GetFocusedWindowId());
    ActivateWindowById(1);
    EXPECT_EQ(1, GetFocusedWindowId());

    ActivateWindowById(2);

    aura::Window* target = root_window()->GetChildById(1);
    ActivationClient* client = GetActivationClient(root_window());

    std::unique_ptr<FocusShiftingActivationObserver> observer(
        new FocusShiftingActivationObserver(target));
    observer->set_shift_focus_to(target->GetChildById(11));
    client->AddObserver(observer.get());

    ActivateWindowById(1);

    // w1's ActivationChangeObserver shifted focus to this child, pre-empting
    // FocusController's default setting.
    EXPECT_EQ(11, GetFocusedWindowId());

    ActivateWindowById(2);
    EXPECT_EQ(2, GetFocusedWindowId());

    // Simulate a focus reset by the ActivationChangeObserver. This should
    // trigger the default setting in FocusController.
    observer->set_shift_focus_to(nullptr);
    ActivateWindowById(1);
    EXPECT_EQ(1, GetFocusedWindowId());

    client->RemoveObserver(observer.get());

    ActivateWindowById(2);
    EXPECT_EQ(2, GetFocusedWindowId());
    ActivateWindowById(1);
    EXPECT_EQ(1, GetFocusedWindowId());
  }
  void ShiftFocusOnActivationDueToHide() override {
    // Similar to ShiftFocusOnActivation except the activation change is
    // triggered by hiding the active window.
    ActivateWindowById(1);
    EXPECT_EQ(1, GetFocusedWindowId());

    // Removes window 3 as candidate for next activatable window.
    root_window()->GetChildById(3)->Hide();
    EXPECT_EQ(1, GetFocusedWindowId());

    aura::Window* target = root_window()->GetChildById(2);
    ActivationClient* client = GetActivationClient(root_window());

    std::unique_ptr<FocusShiftingActivationObserver> observer(
        new FocusShiftingActivationObserver(target));
    observer->set_shift_focus_to(target->GetChildById(21));
    client->AddObserver(observer.get());

    // Hide the active window.
    root_window()->GetChildById(1)->Hide();

    EXPECT_EQ(21, GetFocusedWindowId());

    client->RemoveObserver(observer.get());
  }
  void NoShiftActiveOnActivation() override {
    // When a window is activated, we need to prevent any change to activation
    // from being made in response to an activation change notification.
  }

  void FocusChangeDuringDrag() override {
    std::unique_ptr<aura::client::DefaultCaptureClient> capture_client(
        new aura::client::DefaultCaptureClient(root_window()));
    // Activating an inactive window during drag should activate the window.
    // This emulates the behavior of tab dragging which is merged into the
    // window below.
    ActivateWindowById(1);

    EXPECT_EQ(1, GetActiveWindowId());
    EXPECT_EQ(1, GetFocusedWindowId());

    aura::Window* w2 = root_window()->GetChildById(2);
    ui::test::EventGenerator generator(root_window(), w2);
    generator.PressLeftButton();
    aura::client::GetCaptureClient(root_window())->SetCapture(w2);
    EXPECT_EQ(2, GetActiveWindowId());
    EXPECT_EQ(2, GetFocusedWindowId());
    generator.MoveMouseTo(gfx::Point(0, 0));

    // Emulate the behavior of merging a tab into an inactive window:
    // transferring the mouse capture and activate the window.
    aura::Window* w1 = root_window()->GetChildById(1);
    aura::client::GetCaptureClient(root_window())->SetCapture(w1);
    GetActivationClient(root_window())->ActivateWindow(w1);
    EXPECT_EQ(1, GetActiveWindowId());
    EXPECT_EQ(1, GetFocusedWindowId());

    generator.ReleaseLeftButton();
    aura::client::GetCaptureClient(root_window())->ReleaseCapture(w1);
  }

  // Verifies focus change is honored while capture held.
  void ChangeFocusWhenNothingFocusedAndCaptured() override {
    std::unique_ptr<aura::client::DefaultCaptureClient> capture_client(
        new aura::client::DefaultCaptureClient(root_window()));
    aura::Window* w1 = root_window()->GetChildById(1);
    aura::client::GetCaptureClient(root_window())->SetCapture(w1);

    EXPECT_EQ(-1, GetActiveWindowId());
    EXPECT_EQ(-1, GetFocusedWindowId());

    FocusWindowById(1);

    EXPECT_EQ(1, GetActiveWindowId());
    EXPECT_EQ(1, GetFocusedWindowId());

    aura::client::GetCaptureClient(root_window())->ReleaseCapture(w1);
  }

  // Verifies if a window that loses activation or focus is deleted during
  // observer notification we don't pass the deleted window to other observers.
  void DontPassDeletedWindow() override {
    FocusWindowById(1);

    EXPECT_EQ(1, GetActiveWindowId());
    EXPECT_EQ(1, GetFocusedWindowId());

    {
      aura::Window* to_delete = root_window()->GetChildById(1);
      DeleteOnActivationChangeObserver observer1(
          to_delete,
          /*delete_on_activating=*/true,
          /*delete_window_losing_active=*/true);
      RecordingActivationAndFocusChangeObserver observer2(root_window(),
                                                          &observer1);

      FocusWindowById(2);

      EXPECT_EQ(2, GetActiveWindowId());
      EXPECT_EQ(2, GetFocusedWindowId());

      EXPECT_EQ(to_delete, observer1.GetDeletedWindow());
      EXPECT_FALSE(observer2.was_notified_with_deleted_window());
    }

    {
      aura::Window* to_delete = root_window()->GetChildById(2);
      DeleteOnActivationChangeObserver observer1(
          to_delete, /*delete_on_activating=*/false,
          /*delete_window_losing_active=*/true);
      RecordingActivationAndFocusChangeObserver observer2(root_window(),
                                                          &observer1);

      FocusWindowById(3);

      EXPECT_EQ(3, GetActiveWindowId());
      EXPECT_EQ(3, GetFocusedWindowId());

      EXPECT_EQ(to_delete, observer1.GetDeletedWindow());
      EXPECT_FALSE(observer2.was_notified_with_deleted_window());
    }

    {
      aura::test::CreateTestWindow(
          {.delegate =
               aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
           .parent = root_window(),
           .bounds = {125, 125, 50, 50},
           .window_id = 4})
          .release();

      EXPECT_EQ(3, GetActiveWindowId());
      EXPECT_EQ(3, GetFocusedWindowId());

      aura::Window* to_delete = root_window()->GetChildById(3);
      DeleteOnLoseFocusChangeObserver observer1(to_delete);
      RecordingActivationAndFocusChangeObserver observer2(root_window(),
                                                          &observer1);

      FocusWindowById(4);

      EXPECT_EQ(4, GetActiveWindowId());
      EXPECT_EQ(4, GetFocusedWindowId());

      EXPECT_EQ(to_delete, observer1.GetDeletedWindow());
      EXPECT_FALSE(observer2.was_notified_with_deleted_window());
    }

    {
      aura::test::CreateTestWindow(
          {.delegate =
               aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
           .parent = root_window(),
           .bounds = {125, 125, 50, 50},
           .window_id = 5})
          .release();
      aura::test::CreateTestWindow(
          {.delegate =
               aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(),
           .parent = root_window(),
           .bounds = {125, 125, 50, 50},
           .window_id = 6})
          .release();

      EXPECT_EQ(4, GetActiveWindowId());
      EXPECT_EQ(4, GetFocusedWindowId());

      // Delete the window that is gaining activation at both the "activating"
      // and "activated" phases. Make sure the activations were interrupted
      // properly and the correct next activatable window is activated.
      aura::Window* to_delete1 = root_window()->GetChildById(5);
      DeleteOnActivationChangeObserver observer1(
          to_delete1, /*delete_on_activating=*/false,
          /*delete_window_losing_active=*/false);
      RecordingActivationAndFocusChangeObserver observer2(root_window(),
                                                          &observer1);
      // Test a recursive scenario by having another observer that would delete
      // the next activatable window during the "activating" phase.
      aura::Window* to_delete2 = root_window()->GetChildById(6);
      DeleteOnActivationChangeObserver observer3(
          to_delete2, /*delete_on_activating=*/true,
          /*delete_window_losing_active=*/false);
      RecordingActivationAndFocusChangeObserver observer4(root_window(),
                                                          &observer3);

      FocusWindowById(5);

      EXPECT_EQ(4, GetActiveWindowId());
      EXPECT_EQ(4, GetFocusedWindowId());

      EXPECT_EQ(to_delete1, observer1.GetDeletedWindow());
      EXPECT_FALSE(observer2.was_notified_with_deleted_window());
      EXPECT_EQ(to_delete2, observer3.GetDeletedWindow());
      EXPECT_FALSE(observer4.was_notified_with_deleted_window());
    }
  }

  // Test that the activation of the current active window will bring the window
  // to the top of the window stack.
  void StackWindowAtTopOnActivation() override {
    // Create a window, show it and then activate it.
    std::unique_ptr<aura::Window> window1 =
        std::make_unique<aura::Window>(nullptr);
    window1->SetType(aura::client::WINDOW_TYPE_NORMAL);
    window1->Init(ui::LAYER_TEXTURED);
    root_window()->AddChild(window1.get());
    window1->Show();
    ActivateWindow(window1.get());
    EXPECT_EQ(window1.get(), root_window()->children().back());
    EXPECT_EQ(window1.get(), GetActiveWindow());

    // Create another window, show it but don't activate it. The window is not
    // the active window but is placed on top of window stack.
    std::unique_ptr<aura::Window> window2 =
        std::make_unique<aura::Window>(nullptr);
    window2->SetType(aura::client::WINDOW_TYPE_NORMAL);
    window2->Init(ui::LAYER_TEXTURED);
    root_window()->AddChild(window2.get());
    window2->Show();
    EXPECT_EQ(window2.get(), root_window()->children().back());
    EXPECT_EQ(window1.get(), GetActiveWindow());

    // Try to reactivate the active window. It should bring the active window
    // to the top of the window stack.
    ActivateWindow(window1.get());
    EXPECT_EQ(window1.get(), root_window()->children().back());
    EXPECT_EQ(window1.get(), GetActiveWindow());
  }

  // Verifies focus isn't left when during notification of an activation change
  // the focused window is hidden.
  void HideFocusedWindowDuringActivationLoss() override {
    aura::Window* w11 = root_window()->GetChildById(11);
    FocusWindow(w11);
    EXPECT_EQ(11, GetFocusedWindowId());
    EXPECT_EQ(1, GetActiveWindowId());
    {
      HideOnLoseActivationChangeObserver observer(w11);
      ActivateWindowById(2);
      EXPECT_EQ(nullptr, observer.window_to_hide());
      EXPECT_EQ(2, GetActiveWindowId());
      EXPECT_EQ(2, GetFocusedWindowId());
    }
  }

  // Tests that activating a window while a window is being activated is a
  // no-op.
  void ActivateWhileActivating() override {
    aura::Window* w1 = root_window()->GetChildById(1);
    aura::Window* w2 = root_window()->GetChildById(2);

    ActivateWindowById(3);
    // Activate a window while it is being activated does not DCHECK and the
    // window is made active.
    {
      ActivateWhileActivatingObserver observer(/*to_observe=*/w1,
                                               /*to_activate=*/w1,
                                               /*to_focus=*/nullptr);
      ActivateWindow(w1);
      EXPECT_EQ(1, GetActiveWindowId());
    }

    ActivateWindowById(3);
    // Focus a window while it is being activated does not DCHECK and the
    // window is made active and focused.
    {
      ActivateWhileActivatingObserver observer(/*to_observe=*/w1,
                                               /*to_activate=*/nullptr,
                                               /*to_focus=*/w1);
      ActivateWindow(w1);
      EXPECT_EQ(1, GetActiveWindowId());
      EXPECT_EQ(1, GetFocusedWindowId());
    }

    ActivateWindowById(3);
    // Shift focus while activating a window is allowed as long as it does
    // not attempt to activate a different window.
    {
      aura::Window* w11 = root_window()->GetChildById(11);
      aura::Window* w12 = root_window()->GetChildById(12);
      ActivateWhileActivatingObserver observer(/*to_observe=*/w1,
                                               /*to_activate=*/nullptr,
                                               /*to_focus=*/w12);
      FocusWindow(w11);
      EXPECT_EQ(1, GetActiveWindowId());
      EXPECT_EQ(12, GetFocusedWindowId());
    }

    ActivateWindowById(3);
    // Activate a different window while activating one fails. The window being
    // activated in the 1st activation request will be activated.
    {
      ActivateWhileActivatingObserver observer(/*to_observe=*/w2,
                                               /*to_activate=*/w1,
                                               /*to_focus=*/nullptr);
      // This should hit a DCHECK.
      EXPECT_DCHECK(
          {
            ActivateWindow(w2);
            EXPECT_EQ(2, GetActiveWindowId());
          },
          "");
    }
  }
};

// Focus and Activation changes via ActivationClient API.
class FocusControllerApiTest : public FocusControllerDirectTestBase {
 public:
  FocusControllerApiTest() {}

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

 private:
  // Overridden from FocusControllerTestBase:
  void FocusWindowDirect(aura::Window* window) override { FocusWindow(window); }
  void ActivateWindowDirect(aura::Window* window) override {
    ActivateWindow(window);
  }
  void DeactivateWindowDirect(aura::Window* window) override {
    DeactivateWindow(window);
  }
  bool IsInputEvent() override { return false; }
  // Overridden from FocusControllerDirectTestBase:
  ActivationChangeObserver::ActivationReason GetExpectedActivationReason()
      const override {
    return ActivationChangeObserver::ActivationReason::ACTIVATION_CLIENT;
  }
};

// Focus and Activation changes via input events.
class FocusControllerMouseEventTest : public FocusControllerDirectTestBase {
 public:
  FocusControllerMouseEventTest() {}

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

  // Tests that a handled mouse or gesture event does not trigger a window
  // activation.
  void IgnoreHandledEvent() {
    EXPECT_FALSE(GetActiveWindow());
    aura::Window* w1 = root_window()->GetChildById(1);
    SimpleEventHandler handler;
    root_window()->AddPreTargetHandler(&handler,
                                       ui::EventTarget::Priority::kSystem);
    ui::test::EventGenerator generator(root_window(), w1);
    generator.ClickLeftButton();
    EXPECT_FALSE(GetActiveWindow());
    generator.GestureTapAt(w1->bounds().CenterPoint());
    EXPECT_FALSE(GetActiveWindow());
    root_window()->RemovePreTargetHandler(&handler);
    generator.ClickLeftButton();
    EXPECT_EQ(1, GetActiveWindowId());
  }

 private:
  // Overridden from FocusControllerTestBase:
  void FocusWindowDirect(aura::Window* window) override {
    ui::test::EventGenerator generator(root_window(), window);
    generator.ClickLeftButton();
  }
  void ActivateWindowDirect(aura::Window* window) override {
    ui::test::EventGenerator generator(root_window(), window);
    generator.ClickLeftButton();
  }
  void DeactivateWindowDirect(aura::Window* window) override {
    aura::Window* next_activatable =
        test_focus_rules()->GetNextActivatableWindow(window);
    ui::test::EventGenerator generator(root_window(), next_activatable);
    generator.ClickLeftButton();
  }
  // Overridden from FocusControllerDirectTestBase:
  bool IsInputEvent() override { return true; }
  ActivationChangeObserver::ActivationReason GetExpectedActivationReason()
      const override {
    return ActivationChangeObserver::ActivationReason::INPUT_EVENT;
  }
};

class FocusControllerMouseEnterEventTest
    : public FocusControllerMouseEventTest {
 public:
  FocusControllerMouseEnterEventTest() {
    scoped_feature_list_.InitAndEnableFeature(features::kFocusFollowsCursor);
  }

  void MouseEnteredEvent() {
    aura::Window::Windows children_before = root_window()->children();
    aura::Window* w2 = root_window()->GetChildById(2);

    ui::test::EventGenerator generator(root_window(), w2);
    generator.SendMouseEnter();

    // The enter event should activate the window, but not stack the window.
    EXPECT_EQ(w2, GetActiveWindow());
    EXPECT_EQ(children_before, root_window()->children());
  }

  void MouseEnteredWithActiveParent() {
    aura::Window* w2 = root_window()->GetChildById(2);
    aura::Window* w21 = root_window()->GetChildById(21);

    ActivateWindow(w2);

    // The enter event should not focus the window.
    ui::test::EventGenerator generator(root_window(), w21);
    generator.SendMouseEnter();

    EXPECT_EQ(w2, GetFocusedWindow());
  }

  base::test::ScopedFeatureList scoped_feature_list_;
};

class FocusControllerGestureEventTest : public FocusControllerDirectTestBase {
 public:
  FocusControllerGestureEventTest() {}

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

 private:
  // Overridden from FocusControllerTestBase:
  void FocusWindowDirect(aura::Window* window) override {
    ui::test::EventGenerator generator(root_window(), window);
    generator.GestureTapAt(window->bounds().CenterPoint());
  }
  void ActivateWindowDirect(aura::Window* window) override {
    ui::test::EventGenerator generator(root_window(), window);
    generator.GestureTapAt(window->bounds().CenterPoint());
  }
  void DeactivateWindowDirect(aura::Window* window) override {
    aura::Window* next_activatable =
        test_focus_rules()->GetNextActivatableWindow(window);
    ui::test::EventGenerator generator(root_window(), next_activatable);
    generator.GestureTapAt(window->bounds().CenterPoint());
  }
  bool IsInputEvent() override { return true; }
  ActivationChangeObserver::ActivationReason GetExpectedActivationReason()
      const override {
    return ActivationChangeObserver::ActivationReason::INPUT_EVENT;
  }
};

// Test base for tests where focus is implicitly set to a window as the result
// of a disposition change to the focused window or the hierarchy that contains
// it.
class FocusControllerImplicitTestBase : public FocusControllerTestBase {
 public:
  FocusControllerImplicitTestBase(const FocusControllerImplicitTestBase&) =
      delete;
  FocusControllerImplicitTestBase& operator=(
      const FocusControllerImplicitTestBase&) = delete;

 protected:
  explicit FocusControllerImplicitTestBase(bool parent) : parent_(parent) {}

  aura::Window* GetDispositionWindow(aura::Window* window) {
    return parent_ ? window->parent() : window;
  }

  // Returns the expected ActivationReason caused by calling the
  // ActivatedWindowDirect(...) or DeactivateWindowDirect(...) methods.
  ActivationChangeObserver::ActivationReason GetExpectedActivationReason()
      const {
    return ActivationChangeObserver::ActivationReason::
        WINDOW_DISPOSITION_CHANGED;
  }

  // Change the disposition of |window| in such a way as it will lose focus.
  virtual void ChangeWindowDisposition(aura::Window* window) = 0;

  // Allow each disposition change test to add additional post-disposition
  // change expectations.
  virtual void PostDispositionChangeExpectations() {}

  // Overridden from FocusControllerTestBase:
  void BasicFocus() override {
    EXPECT_FALSE(GetFocusedWindow());

    aura::Window* w211 = root_window()->GetChildById(211);
    FocusWindow(w211);
    EXPECT_EQ(211, GetFocusedWindowId());

    ChangeWindowDisposition(w211);
    // BasicFocusRules passes focus to the parent.
    EXPECT_EQ(parent_ ? 2 : 21, GetFocusedWindowId());
  }
  void BasicActivation() override {
    DCHECK(!parent_) << "Activation tests don't support parent changes.";

    EXPECT_FALSE(GetActiveWindow());

    aura::Window* w2 = root_window()->GetChildById(2);
    ActivateWindow(w2);
    EXPECT_EQ(2, GetActiveWindowId());

    ChangeWindowDisposition(w2);
    EXPECT_EQ(3, GetActiveWindowId());
    PostDispositionChangeExpectations();
  }
  void FocusEvents() override {
    aura::Window* w211 = root_window()->GetChildById(211);
    FocusWindow(w211);

    ScopedFocusNotificationObserver root_observer(root_window());
    ScopedTargetFocusNotificationObserver observer211(root_window(), 211);
    root_observer.ExpectCounts(0, 0);
    observer211.ExpectCounts(0, 0);

    ChangeWindowDisposition(w211);
    root_observer.ExpectCounts(0, 1);
    observer211.ExpectCounts(0, 1);
  }
  void ActivationEvents() override {
    DCHECK(!parent_) << "Activation tests don't support parent changes.";

    aura::Window* w2 = root_window()->GetChildById(2);
    ActivateWindow(w2);

    ScopedFocusNotificationObserver root_observer(root_window());
    ScopedTargetFocusNotificationObserver observer2(root_window(), 2);
    ScopedTargetFocusNotificationObserver observer3(root_window(), 3);
    root_observer.ExpectCounts(0, 0);
    observer2.ExpectCounts(0, 0);
    observer3.ExpectCounts(0, 0);

    ChangeWindowDisposition(w2);
    root_observer.ExpectCounts(1, 1);
    EXPECT_EQ(GetExpectedActivationReason(),
              root_observer.last_activation_reason());
    observer2.ExpectCounts(1, 1);
    observer3.ExpectCounts(1, 1);
  }
  void FocusRulesOverride() override {
    EXPECT_FALSE(GetFocusedWindow());
    aura::Window* w211 = root_window()->GetChildById(211);
    FocusWindow(w211);
    EXPECT_EQ(211, GetFocusedWindowId());

    test_focus_rules()->set_focus_restriction(root_window()->GetChildById(11));
    ChangeWindowDisposition(w211);
    // Normally, focus would shift to the parent (w21) but the override shifts
    // it to 11.
    EXPECT_EQ(11, GetFocusedWindowId());

    test_focus_rules()->set_focus_restriction(nullptr);
  }
  void ActivationRulesOverride() override {
    DCHECK(!parent_) << "Activation tests don't support parent changes.";

    aura::Window* w1 = root_window()->GetChildById(1);
    ActivateWindow(w1);

    EXPECT_EQ(1, GetActiveWindowId());
    EXPECT_EQ(1, GetFocusedWindowId());

    aura::Window* w3 = root_window()->GetChildById(3);
    test_focus_rules()->set_focus_restriction(w3);

    // Normally, activation/focus would move to w2, but since we have a focus
    // restriction, it should move to w3 instead.
    ChangeWindowDisposition(w1);
    EXPECT_EQ(3, GetActiveWindowId());
    EXPECT_EQ(3, GetFocusedWindowId());

    test_focus_rules()->set_focus_restriction(nullptr);
    ActivateWindow(root_window()->GetChildById(2));
    EXPECT_EQ(2, GetActiveWindowId());
    EXPECT_EQ(2, GetFocusedWindowId());
  }

 private:
  // When true, the disposition change occurs to the parent of the window
  // instead of to the window. This verifies that changes occurring in the
  // hierarchy that contains the window affect the window's focus.
  bool parent_;
};

// Focus and Activation changes in response to window visibility changes.
class FocusControllerHideTest : public FocusControllerImplicitTestBase {
 public:
  FocusControllerHideTest() : FocusControllerImplicitTestBase(false) {}

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

 protected:
  FocusControllerHideTest(bool parent)
      : FocusControllerImplicitTestBase(parent) {}

  // Overridden from FocusControllerImplicitTestBase:
  void ChangeWindowDisposition(aura::Window* window) override {
    GetDispositionWindow(window)->Hide();
  }
};

// Focus and Activation changes in response to window parent visibility
// changes.
class FocusControllerParentHideTest : public FocusControllerHideTest {
 public:
  FocusControllerParentHideTest() : FocusControllerHideTest(true) {}

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

  // The parent window's visibility change should not change its transient child
  // window's modality property.
  void TransientChildWindowActivationTest() {
    aura::Window* w1 = root_window()->GetChildById(1);
    aura::Window* w11 = root_window()->GetChildById(11);
    ::wm::AddTransientChild(w1, w11);
    w11->SetProperty(aura::client::kModalKey, ui::mojom::ModalType::kWindow);

    EXPECT_EQ(ui::mojom::ModalType::kNone,
              w1->GetProperty(aura::client::kModalKey));
    EXPECT_EQ(ui::mojom::ModalType::kWindow,
              w11->GetProperty(aura::client::kModalKey));

    // Hide the parent window w1 and show it again.
    w1->Hide();
    w1->Show();

    // Test that child window w11 doesn't change its modality property.
    EXPECT_EQ(ui::mojom::ModalType::kNone,
              w1->GetProperty(aura::client::kModalKey));
    EXPECT_EQ(ui::mojom::ModalType::kWindow,
              w11->GetProperty(aura::client::kModalKey));
  }
};

// Focus and Activation changes in response to window destruction.
class FocusControllerDestructionTest : public FocusControllerImplicitTestBase {
 public:
  FocusControllerDestructionTest() : FocusControllerImplicitTestBase(false) {}

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

 protected:
  FocusControllerDestructionTest(bool parent)
      : FocusControllerImplicitTestBase(parent) {}

  // Overridden from FocusControllerImplicitTestBase:
  void ChangeWindowDisposition(aura::Window* window) override {
    delete GetDispositionWindow(window);
  }
};

// Focus and Activation changes in response to window parent destruction.
class FocusControllerParentDestructionTest
    : public FocusControllerDestructionTest {
 public:
  FocusControllerParentDestructionTest()
      : FocusControllerDestructionTest(true) {}

  FocusControllerParentDestructionTest(
      const FocusControllerParentDestructionTest&) = delete;
  FocusControllerParentDestructionTest& operator=(
      const FocusControllerParentDestructionTest&) = delete;
};

// Focus and Activation changes in response to window removal.
class FocusControllerRemovalTest : public FocusControllerImplicitTestBase {
 public:
  FocusControllerRemovalTest() : FocusControllerImplicitTestBase(false) {}

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

 protected:
  FocusControllerRemovalTest(bool parent)
      : FocusControllerImplicitTestBase(parent) {}

  // Overridden from FocusControllerImplicitTestBase:
  void ChangeWindowDisposition(aura::Window* window) override {
    aura::Window* disposition_window = GetDispositionWindow(window);
    disposition_window->parent()->RemoveChild(disposition_window);
    window_owner_.reset(disposition_window);
  }
  void TearDown() override {
    window_owner_.reset();
    FocusControllerImplicitTestBase::TearDown();
  }

 private:
  std::unique_ptr<aura::Window> window_owner_;
};

// Focus and Activation changes in response to window parent removal.
class FocusControllerParentRemovalTest : public FocusControllerRemovalTest {
 public:
  FocusControllerParentRemovalTest() : FocusControllerRemovalTest(true) {}

  FocusControllerParentRemovalTest(const FocusControllerParentRemovalTest&) =
      delete;
  FocusControllerParentRemovalTest& operator=(
      const FocusControllerParentRemovalTest&) = delete;
};

#define FOCUS_CONTROLLER_TEST(TESTCLASS, TESTNAME) \
  TEST_F(TESTCLASS, TESTNAME) { TESTNAME(); }

// Runs direct focus change tests (input events and API calls).
#define DIRECT_FOCUS_CHANGE_TESTS(TESTNAME)                           \
  FOCUS_CONTROLLER_TEST(FocusControllerApiTest, TESTNAME)             \
  FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, TESTNAME)      \
  FOCUS_CONTROLLER_TEST(FocusControllerMouseEnterEventTest, TESTNAME) \
  FOCUS_CONTROLLER_TEST(FocusControllerGestureEventTest, TESTNAME)

// Runs implicit focus change tests for disposition changes to target.
#define IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME)              \
  FOCUS_CONTROLLER_TEST(FocusControllerHideTest, TESTNAME)        \
  FOCUS_CONTROLLER_TEST(FocusControllerDestructionTest, TESTNAME) \
  FOCUS_CONTROLLER_TEST(FocusControllerRemovalTest, TESTNAME)

// Runs implicit focus change tests for disposition changes to target's parent
// hierarchy.
#define IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME)                       \
  /* TODO(beng): parent destruction tests are not supported at             \
     present due to workspace manager issues.                              \
  FOCUS_CONTROLLER_TEST(FocusControllerParentDestructionTest, TESTNAME) */ \
  FOCUS_CONTROLLER_TEST(FocusControllerParentHideTest, TESTNAME)           \
  FOCUS_CONTROLLER_TEST(FocusControllerParentRemovalTest, TESTNAME)

// Runs all implicit focus change tests (changes to the target and target's
// parent hierarchy)
#define IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME)  \
  IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \
  IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME)

// Runs all possible focus change tests.
#define ALL_FOCUS_TESTS(TESTNAME)     \
  DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
  IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME)

// Runs focus change tests that apply only to the target. For example,
// implicit activation changes caused by window disposition changes do not
// occur when changes to the containing hierarchy happen.
#define TARGET_FOCUS_TESTS(TESTNAME)  \
  DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
  IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME)

// - Focuses a window, verifies that focus changed.
ALL_FOCUS_TESTS(BasicFocus)

// - Activates a window, verifies that activation changed.
TARGET_FOCUS_TESTS(BasicActivation)

// - Focuses a window, verifies that focus events were dispatched.
ALL_FOCUS_TESTS(FocusEvents)

// - Focuses or activates a window multiple times, verifies that events are only
//   dispatched when focus/activation actually changes.
DIRECT_FOCUS_CHANGE_TESTS(DuplicateFocusEvents)
DIRECT_FOCUS_CHANGE_TESTS(DuplicateActivationEvents)

// - Activates a window, verifies that activation events were dispatched.
TARGET_FOCUS_TESTS(ActivationEvents)

// - Attempts to active a hidden window, verifies that current window is
//   attempted to be reactivated and the appropriate event dispatched.
FOCUS_CONTROLLER_TEST(FocusControllerApiTest, ReactivationEvents)

// - Input events/API calls shift focus between focusable windows within the
//   active window.
DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusWithinActiveWindow)

// - Input events/API calls to a child window of an inactive window shifts
//   activation to the activatable parent and focuses the child.
DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToChildOfInactiveWindow)

// - Input events/API calls to focus the parent of the focused window do not
//   shift focus away from the child.
DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToParentOfFocusedWindow)

// - Verifies that FocusRules determine what can be focused.
ALL_FOCUS_TESTS(FocusRulesOverride)

// - Verifies that FocusRules determine what can be activated.
TARGET_FOCUS_TESTS(ActivationRulesOverride)

// - Verifies that attempts to change focus or activation from a focus or
//   activation change observer are ignored.
DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivation)
DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivationDueToHide)
DIRECT_FOCUS_CHANGE_TESTS(NoShiftActiveOnActivation)

FOCUS_CONTROLLER_TEST(FocusControllerApiTest, FocusChangeDuringDrag)

FOCUS_CONTROLLER_TEST(FocusControllerApiTest,
                      ChangeFocusWhenNothingFocusedAndCaptured)

// See description above DontPassDeletedWindow() for details.
FOCUS_CONTROLLER_TEST(FocusControllerApiTest, DontPassDeletedWindow)

FOCUS_CONTROLLER_TEST(FocusControllerApiTest, StackWindowAtTopOnActivation)

FOCUS_CONTROLLER_TEST(FocusControllerApiTest,
                      HideFocusedWindowDuringActivationLoss)

FOCUS_CONTROLLER_TEST(FocusControllerApiTest, ActivateWhileActivating)

// See description above TransientChildWindowActivationTest() for details.
FOCUS_CONTROLLER_TEST(FocusControllerParentHideTest,
                      TransientChildWindowActivationTest)

// If a mouse event was handled, it should not activate a window.
FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, IgnoreHandledEvent)

// Mouse over window should activate it.
FOCUS_CONTROLLER_TEST(FocusControllerMouseEnterEventTest, MouseEnteredEvent)

// Mouse over window with active parent should not focus it.
FOCUS_CONTROLLER_TEST(FocusControllerMouseEnterEventTest,
                      MouseEnteredWithActiveParent)

}  // namespace wm