blob: 0289fdfbb1641f0615b0eb679d50db8eb9eba4e1 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_ACCESSIBILITY_SCOPED_MODE_COLLECTION_H_
#define CONTENT_BROWSER_ACCESSIBILITY_SCOPED_MODE_COLLECTION_H_
#include <list>
#include <memory>
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/types/pass_key.h"
#include "content/common/content_export.h"
#include "ui/accessibility/ax_mode.h"
namespace content {
class ScopedAccessibilityMode;
// A collection of ScopedAccessibilityMode instances. The collection maintains
// an always up-to-date view of the union of all contained scopers, accessible
// via `accessibility_mode()`. Any change to this value (via calls to `Add()` to
// add a new item to the collection or via destruction of a scoper belonging to
// the collection) results in notifying the delegate. The delegate may filter
// mode flags during recomputation of the effective mode. It is permissible for
// the collection to be destroyed while scopers minted from it remain alive.
class CONTENT_EXPORT ScopedModeCollection {
public:
class Delegate {
public:
// Called when the effective mode for the collection changes (i.e., when the
// union of all mode flags indicated by the scopers in the collection
// changes).
virtual void OnModeChanged(ui::AXMode old_mode, ui::AXMode new_mode) = 0;
// Filters `mode`, returning some subset of `mode`. Called once for each
// scoper in the collection while computing the collection's effective mode.
virtual ui::AXMode FilterModeFlags(ui::AXMode mode) = 0;
protected:
Delegate() = default;
~Delegate() = default;
// Returns a PassKey for use by the Delegate so that it may force
// recomputation if its filtering policy changes.
static base::PassKey<Delegate> MakePassKey() {
return base::PassKey<Delegate>();
}
};
explicit ScopedModeCollection(Delegate& delegate);
ScopedModeCollection(const ScopedModeCollection&) = delete;
ScopedModeCollection& operator=(const ScopedModeCollection&) = delete;
~ScopedModeCollection();
// Returns the union of all mode flags indicated by the scopers in the
// collection. Recalculated on each addition, removal, and modification of
// a scoper in the collection.
ui::AXMode accessibility_mode() const { return accessibility_mode_; }
// Returns a new scoper for `mode`, recalculating the effective
// accessibility mode for the collection and running `on_mode_changed` if it
// has changed. When the returned scoper is destroyed, the effective
// accessibility mode for the collection is once again computed and
// `on_mode_changed` is run if it has changed.
std::unique_ptr<ScopedAccessibilityMode> Add(ui::AXMode mode);
// Returns true if the collection is empty.
bool empty() const { return scopers_.empty(); }
// Forces a recomputation of the collection's effective mode. To be called by
// the delegate when the behavior of the delegate's filter function changes.
void Recompute(base::PassKey<Delegate>);
private:
class ScopedAccessibilityModeImpl;
using ScoperContainer = std::list<raw_ptr<ScopedAccessibilityModeImpl>>;
using ScoperKey = ScoperContainer::iterator;
// Removes the scoper identified by `scoper_key`, recalculates the effective
// accessibility mode for the collection, and runs `on_mode_changed` if it
// has changed.
void OnDestroyed(ScoperKey scoper_key);
// Recalculate the effective mode following a change to the collection of
// scopers. Runs `on_mode_changed` if there is a change.
void RecalculateEffectiveModeAndNotify();
const raw_ref<Delegate> delegate_;
// The collection of ScopedAccessibilityMode instances.
ScoperContainer scopers_;
// The effective accessibility mode computed from all scopers held by this
// instance. Recalculated each time a scoper is added, removed, or modified.
ui::AXMode accessibility_mode_;
};
} // namespace content
#endif // CONTENT_BROWSER_ACCESSIBILITY_SCOPED_MODE_COLLECTION_H_