blob: d5f8371ea26224ddd44a0aa3ee823ce1405a4882 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_UI_A11Y_LIB_SCREEN_READER_FOCUS_A11Y_FOCUS_MANAGER_H_
#define SRC_UI_A11Y_LIB_SCREEN_READER_FOCUS_A11Y_FOCUS_MANAGER_H_
#include <lib/async/cpp/wait.h>
#include <lib/inspect/cpp/inspect.h>
#include <unordered_map>
#include "src/ui/a11y/lib/annotation/focus_highlight_manager.h"
#include "src/ui/a11y/lib/focus_chain/accessibility_focus_chain_listener.h"
#include "src/ui/a11y/lib/focus_chain/accessibility_focus_chain_requester.h"
namespace a11y {
// The A11yFocusManager keeps track of the a11y focus per view that is providing
// semantics.
//
// The a11y focus is defined as the semantic node which is selected in a certain
// view by the screen reader. There is only one active a11y focus, meaning that
// the screen reader cares only about one node per time. If the system changes
// the Focus Chain to a different view, the a11y focus also changes. This
// manager caches all a11y focus in each view as well as the active a11y focus.
//
// The a11y focus can be changed, which may trigger a Focus Chain Update if the active a11y focus is
// moving to another view.
class A11yFocusManager : public AccessibilityFocusChainListener {
public:
// Defines which view is currently in a11y focus along with the node_id of the node inside that
// view.
struct A11yFocusInfo {
zx_koid_t view_ref_koid;
uint32_t node_id;
};
// Callback which will be used to notify that an error is encountered while trying to set a11y
// focus.
using SetA11yFocusCallback = fit::function<void(bool)>;
// Root node id, which will be used to set the default node_id for a view.
static constexpr uint32_t kRootNodeId = 0;
static constexpr char kCurrentlyFocusedKoidInspectNodeName[] = "currently_focused_koid";
static constexpr char kCurrentlyFocusedNodeIdInspectNodeName[] = "currently_focused_node_id";
// |focus_chain_requester| and |registry| must outlive this object.
explicit A11yFocusManager(AccessibilityFocusChainRequester* focus_chain_requester,
AccessibilityFocusChainRegistry* registry,
FocusHighlightManager* focus_highlight_manager,
inspect::Node inspect_node = inspect::Node());
virtual ~A11yFocusManager();
// Returns the current a11y focus if it exists.
virtual std::optional<A11yFocusInfo> GetA11yFocus();
// Sets the a11y focus to a different node. If the current focused view is different than the one
// in this request, a focus Chain is first performed to change the focus to the other view.
// |callback| is invoked when this operation is done, indicating if the request was granted. The
// request can fail if the View is not providing semantics or if the Focus Chain request was
// denied.
virtual void SetA11yFocus(zx_koid_t koid, uint32_t node_id, SetA11yFocusCallback callback);
// Clears existing a11y focus.
virtual void ClearA11yFocus();
// Removes current highlights (if any), and highlights node specified by identifier
// |{currently_focused_view,
// focused_node_in_view_map_[currently_focused_view_]}|.
virtual void UpdateHighlights();
protected:
// For mocks only.
A11yFocusManager();
private:
// |AccessibilityFocusChainListener|
void OnViewFocus(zx_koid_t view_ref_koid) override;
// Helper function to update inspect info.
void UpdateInspectProperties();
// Map for storing node_id which is in a11y focus for every viewref_koid.
// By default, root-node(node_id = 0) is set for a view in a11y focus.
std::unordered_map<zx_koid_t /* viewref_koid */, uint32_t /* node_id */>
focused_node_in_view_map_;
// Stores the koid of the view which is currently in a11y focus.
zx_koid_t currently_focused_view_ = ZX_KOID_INVALID;
// Interface used to request Focus Chain Updates.
AccessibilityFocusChainRequester* const focus_chain_requester_ = nullptr;
// Used to manipulate semantic annotations.
FocusHighlightManager* const focus_highlight_manager_ = nullptr;
fxl::WeakPtrFactory<AccessibilityFocusChainListener> weak_ptr_factory_;
// Inspect node to which to publish debug info.
inspect::Node inspect_node_;
// Inspect properties to store current a11y focus.
inspect::UintProperty inspect_property_current_focus_koid_;
inspect::UintProperty inspect_property_current_focus_node_id_;
};
} // namespace a11y
#endif // SRC_UI_A11Y_LIB_SCREEN_READER_FOCUS_A11Y_FOCUS_MANAGER_H_