blob: fdb7f3ea0b7e98b90860fa06a7dda00c988d8072 [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 <fuchsia/ui/views/cpp/fidl.h>
#include <lib/async/cpp/wait.h>
#include <unordered_map>
namespace a11y {
// A11yFocusManager class is responsible for storing the node in a11y focus for every view along
// with storing the current view in a11y focus. A11yFocusManager is also responsible for exposing
// methods to set a11y focus to a particular view using fuchsia::ui::views::Focuser protocol, and to
// get current A11y Focus state.
class A11yFocusManager {
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;
// 1. FocuserPtr: Client-side channel of the focuser protocol. This is used for requesting
// a11y focus on a specific view. Focuser is already instantiated before passing to the
// constructor.
explicit A11yFocusManager(fuchsia::ui::views::FocuserPtr focuser);
~A11yFocusManager();
// Returns A11yFocusInfo of the view which currently has a11y focus. Doesn't return a value if no
// view has a11y focus.
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.
// SetA11yFocusCallback is used to notify the called whether the operation is successful or not.
// SetA11yFocus fails when either the view doesn't match any existing view or if the
// RequestFocus() is declined.
void SetA11yFocus(zx_koid_t koid, uint32_t node_id, SetA11yFocusCallback callback);
// Test-only function to set a11y focus to a specific ViewRef.
// TODO(fxb/44503): Make this function private when callback is implemented to receive focus chain
// from FocusChainManager.
void AddViewRef(fuchsia::ui::views::ViewRef view_ref);
private:
// CleanUpRemovedView is called when ViewRef peer is destroyed. It is responsible for deleting all
// the entries in the hash-map, related to the ViewRef. It also updates the current_focused_view_,
// if the view in a11y focus is deleted.
void CleanUpRemovedView(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
const zx_packet_signal* signal);
// Helper function to initialize WaitMethod() to invoke CleanUpRemovedView() when any view_ref is
// invalidated.
void InitializeWaitMethod(zx_koid_t koid);
// 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_;
// Map for accessing view_refs with koid.
std::unordered_map<zx_koid_t /* viewref_koid */, fuchsia::ui::views::ViewRef /* view_ref */>
koid_to_viewref_map_;
// Stores the koid of the view which is currently in a11y focus.
zx_koid_t currently_focused_view_ = ZX_KOID_INVALID;
// Map for storing wait method for every viewref.
std::unordered_map<
zx_koid_t,
std::unique_ptr<async::WaitMethod<A11yFocusManager, &A11yFocusManager::CleanUpRemovedView>>>
wait_map_;
// Client-side channel of the focuser protocol (fuchsia.ui.views.focuser).
fuchsia::ui::views::FocuserPtr focuser_;
};
} // namespace a11y
#endif // SRC_UI_A11Y_LIB_SCREEN_READER_FOCUS_A11Y_FOCUS_MANAGER_H_