blob: f2d382919c1b24ad9ffa67e29eb413f8daa944ec [file] [log] [blame]
// Copyright 2021 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_SCENIC_LIB_FOCUS_VIEW_REF_FOCUSED_REGISTRY_H_
#define SRC_UI_SCENIC_LIB_FOCUS_VIEW_REF_FOCUSED_REGISTRY_H_
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <zircon/types.h>
#include <optional>
#include <unordered_map>
#include "src/ui/scenic/lib/view_tree/snapshot_types.h"
namespace focus {
// An object for managing fuchsia.ui.views.ViewRefFocused lifecycle, starting with FIDL requests and
// ending with cleanup.
class ViewRefFocusedRegistry {
public:
// Stores a FIDL request for fuchsia.ui.views.ViewRefFocused to |pending_requests_|.
// Pre: |session_id| is unassociated with any fuchsia.ui.views.ViewRefFocused.
void Register(zx_koid_t view_ref_koid,
fidl::InterfaceRequest<fuchsia::ui::views::ViewRefFocused> view_focuser);
// Binds and registers endpoints in |pending_requests_| if its |view_ref_koid| is present in
// |snapshot|. Remove and destroy any registered endpoint not present in |snapshot|.
void Update(const view_tree::Snapshot& snapshot);
// Focus changed, update state.
void UpdateFocus(zx_koid_t old_focus, zx_koid_t new_focus);
private:
class Endpoint : public fuchsia::ui::views::ViewRefFocused {
public:
explicit Endpoint(fidl::InterfaceRequest<fuchsia::ui::views::ViewRefFocused> view_focuser);
Endpoint(Endpoint&& original) noexcept; // for emplace
// |fuchsia.ui.views.ViewRefFocused|
void Watch(fuchsia::ui::views::ViewRefFocused::WatchCallback callback) override;
// Track focus changes for this ViewRef.
void UpdateFocus(bool focused);
private:
// The accumulated focus changes associated with a view ref.
// - If empty: no focus change to report.
// - Otherwise, the next response callback should read then clear this field.
std::optional<bool> focused_state_;
// The response action is stored here, if the last |Watch| call did not immediately issue a
// response (i.e., there was not a focus change to report). A subsequent focus change should
// trigger the response callback, and clear this field.
fuchsia::ui::views::ViewRefFocused::WatchCallback response_;
// Server-side endpoint.
fidl::Binding<fuchsia::ui::views::ViewRefFocused> endpoint_;
};
// Associates ViewRef KOID to ViewRefFocused server-side endpoint.
std::unordered_map<zx_koid_t, Endpoint> endpoints_;
// Holds unbound ViewRefFocused endpoints. An endpoint here is moved out to the registration map,
// |endpoints_|, when the client calls Present() on its view.
std::unordered_map<zx_koid_t, fidl::InterfaceRequest<fuchsia::ui::views::ViewRefFocused>>
pending_requests_;
};
} // namespace focus
#endif // SRC_UI_SCENIC_LIB_FOCUS_VIEW_REF_FOCUSED_REGISTRY_H_