blob: 4cb42e17332dcfa3d23e7a75f595e797dc8727dc [file] [log] [blame]
// Copyright 2022 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_INTERACTION_WIDGET_FOCUS_OBSERVER_H_
#define UI_VIEWS_INTERACTION_WIDGET_FOCUS_OBSERVER_H_
#include <vector>
#include "base/callback_list.h"
#include "base/functional/callback_forward.h"
#include "ui/base/interaction/framework_specific_implementation.h"
#include "ui/base/interaction/framework_specific_registration_list.h"
#include "ui/base/interaction/state_observer.h"
#include "ui/views/widget/widget.h"
namespace views::test {
namespace internal {
// Represents a singleton object that observes widget activation in some way.
// Useful because not all browser activations register as low-level widget
// activations, and there needs to be a way to track non-browser windows too, so
// there is no single system that can provide this information.
//
// Subclasses should be private to a specific Interactive[X]TestApi
// implementation, and be registered on the test's `WidgetFocusSupplierFrame`.
class WidgetFocusSupplier : public ui::FrameworkSpecificImplementation {
public:
WidgetFocusSupplier();
~WidgetFocusSupplier() override;
// Allows a specific WidgetFocusObserver to register for callbacks.
using WidgetFocusChangedCallback =
base::RepeatingCallback<void(Widget*)>;
base::CallbackListSubscription AddWidgetFocusChangedCallback(
WidgetFocusChangedCallback callback);
protected:
// Derived classes should call this when the focus changes.
void OnWidgetFocusChanged(Widget* focused_now);
// Used to retrieve a set of widgets. Results from multiple suppliers may be
// combined to get a full set.
virtual Widget::Widgets GetAllWidgets() const = 0;
private:
friend class WidgetFocusSupplierFrame;
base::RepeatingCallbackList<void(Widget*)> callbacks_;
};
// Creates a frame in which WidgetFocusSuppliers can be registered.
// Use `GetCurrentFrame()->supplier_list()`.
class WidgetFocusSupplierFrame {
public:
WidgetFocusSupplierFrame();
~WidgetFocusSupplierFrame();
WidgetFocusSupplierFrame(const WidgetFocusSupplierFrame&) = delete;
void operator=(const WidgetFocusSupplierFrame&) = delete;
// Returns the current frame (there should only be one).
static WidgetFocusSupplierFrame* GetCurrentFrame();
using SupplierList =
ui::FrameworkSpecificRegistrationList<WidgetFocusSupplier>;
SupplierList& supplier_list() { return supplier_list_; }
// Returns the current active widget, if it can be determined, or null
// otherwise.
Widget* GetActiveWidget();
private:
// The actual list of widget focus suppliers.
SupplierList supplier_list_;
};
} // namespace internal
// Tracks widget focus as a `StateObserver`. Use ObserveState and WaitForState.
// Can only be created inside of a `WidgetFocusSupplierFrame`.
class WidgetFocusObserver : public ui::test::StateObserver<Widget*> {
public:
WidgetFocusObserver();
~WidgetFocusObserver() override;
// ui::test::StateObserver:
Widget* GetStateObserverInitialState() const override;
private:
void OnWidgetFocusChanged(Widget* focused_now);
std::vector<base::CallbackListSubscription> subscriptions_;
};
// Since there is only one WidgetFocusManager, there only ever needs to be one
// WidgetFocusObserver.
DECLARE_STATE_IDENTIFIER_VALUE(WidgetFocusObserver, kCurrentWidgetFocus);
} // namespace views::test
#endif // UI_VIEWS_INTERACTION_WIDGET_FOCUS_OBSERVER_H_