blob: 9743624532879b2514708f074537a85ef6871f45 [file]
// Copyright 2026 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.
#include "src/ui/scenic/lib/input/input_manager.h"
#include <fidl/fuchsia.ui.pointer/cpp/hlcpp_conversion.h>
#include <fidl/fuchsia.ui.views/cpp/hlcpp_conversion.h>
#include <lib/fidl/cpp/hlcpp_conversion.h>
#include <lib/inspect/cpp/inspect.h>
#include "src/ui/scenic/lib/utils/check_is_on_thread.h"
namespace scenic_impl::input {
InputManager::InputManager(async_dispatcher_t* input_dispatcher,
std::shared_ptr<view_tree::SnapshotHolder> snapshot_holder,
inspect::Node parent_node, bool use_auto_focus)
: inspect_node_(std::move(parent_node)),
use_auto_focus_(use_auto_focus),
geometry_provider_(snapshot_holder),
focus_manager_(input_dispatcher, snapshot_holder, inspect_node_.CreateChild("FocusManager")),
observer_registry_(geometry_provider_),
scoped_observer_registry_(geometry_provider_),
view_ref_installed_impl_(snapshot_holder),
input_(input_dispatcher, snapshot_holder, inspect_node_,
[this](zx_koid_t koid, const view_tree::Snapshot& snapshot) {
if (!use_auto_focus_)
return;
const auto& focus_chain = focus_manager_.GetFocusChain(snapshot);
if (!focus_chain.empty()) {
const zx_koid_t requestor = focus_chain[0];
const zx_koid_t request = koid != ZX_KOID_INVALID ? koid : requestor;
focus_manager_.RequestFocus(requestor, request, snapshot);
}
}) {
// Constructed and executed entirely on the dedicated input thread.
// Note that we don't explicitly publish `InputSystem` or its sub-components; these are
// "view bound protocols" connected to via e.g. the Flatland API, not routed by Fuchsia's
// component manager.
utils::CheckIsOnInputThread();
}
void InputManager::RegisterViewFocuser(fidl::ServerEnd<fuchsia_ui_views::Focuser> focuser,
zx_koid_t view_ref_koid) {
focus_manager_.RegisterViewFocuser(view_ref_koid, fidl::NaturalToHLCPP(std::move(focuser)));
}
void InputManager::RegisterViewRefFocused(fidl::ServerEnd<fuchsia_ui_views::ViewRefFocused> vrf,
zx_koid_t view_ref_koid) {
focus_manager_.RegisterViewRefFocused(view_ref_koid, fidl::NaturalToHLCPP(std::move(vrf)));
}
void InputManager::RegisterTouchSource(
fidl::ServerEnd<fuchsia_ui_pointer::TouchSource> touch_source, zx_koid_t view_ref_koid) {
input_.RegisterTouchSource(fidl::NaturalToHLCPP(std::move(touch_source)), view_ref_koid);
}
void InputManager::RegisterMouseSource(
fidl::ServerEnd<fuchsia_ui_pointer::MouseSource> mouse_source, zx_koid_t view_ref_koid) {
input_.RegisterMouseSource(fidl::NaturalToHLCPP(std::move(mouse_source)), view_ref_koid);
}
void InputManager::OnNewViewTreeSnapshot() {
// All of these run on the dedicated input thread. Because they are updated synchronously
// here on the input thread, there is no risk of race conditions or thread synchronization
// overhead when a FIDL client observes a change and sends a subsequent message to another
// input or focus protocol served on this thread.
utils::CheckIsOnInputThread();
// Poke FocusManager to eagerly respond to the new snapshot; it might have outstanding hanging
// gets that otherwise wouldn't notice.
focus_manager_.OnNewViewTreeSnapshot();
view_ref_installed_impl_.OnNewViewTreeSnapshot();
geometry_provider_.OnNewViewTreeSnapshot();
}
void InputManager::BindFocusChainListenerRegistry(
fidl::InterfaceRequest<fuchsia::ui::focus::FocusChainListenerRegistry> request) {
focus_manager_.Bind(std::move(request));
}
void InputManager::BindViewRefInstalled(
fidl::InterfaceRequest<fuchsia::ui::views::ViewRefInstalled> request) {
view_ref_installed_impl_.Bind(std::move(request));
}
void InputManager::BindObserverRegistry(
fidl::InterfaceRequest<fuchsia::ui::observation::test::Registry> request) {
observer_registry_.Bind(std::move(request));
}
void InputManager::BindScopedObserverRegistry(
fidl::InterfaceRequest<fuchsia::ui::observation::scope::Registry> request) {
scoped_observer_registry_.Bind(std::move(request));
}
#if !defined(FUCHSIA_DSO)
void InputManager::BindPointerinjectorRegistry(
fidl::InterfaceRequest<fuchsia::ui::pointerinjector::Registry> request) {
input_.BindPointerinjectorRegistry(std::move(request));
}
#else
void InputManager::BindPointerinjectorRegistry(zx::channel channel) {
input_.BindPointerinjectorRegistry(std::move(channel));
}
#endif
void InputManager::BindLocalHit(
fidl::InterfaceRequest<fuchsia::ui::pointer::augment::LocalHit> request) {
input_.BindLocalHit(std::move(request));
}
void InputManager::BindA11yPointerEventRegistry(
fidl::InterfaceRequest<fuchsia::ui::input::accessibility::PointerEventRegistry> request) {
input_.BindA11yPointerEventRegistry(std::move(request));
}
} // namespace scenic_impl::input