blob: c96a6ca2f2d5431d457b75f86559d0185f16ecd1 [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_BIN_VIRTUAL_KEYBOARD_MANAGER_VIRTUAL_KEYBOARD_COORDINATOR_H_
#define SRC_UI_BIN_VIRTUAL_KEYBOARD_MANAGER_VIRTUAL_KEYBOARD_COORDINATOR_H_
#include <fuchsia/input/virtualkeyboard/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/sys/cpp/component_context.h>
#include <zircon/types.h>
#include <memory>
#include "src/ui/bin/virtual_keyboard_manager/focus_listener.h"
#include "src/ui/bin/virtual_keyboard_manager/virtual_keyboard_controller.h"
#include "src/ui/bin/virtual_keyboard_manager/virtual_keyboard_manager.h"
namespace virtual_keyboard_manager {
class VirtualKeyboardController;
// Methods called by `VirtualKeyboardControllerCreator` and `VirtualKeyboardManager`.
// Factored into a separate class to support unit testing.
class VirtualKeyboardCoordinator : public FocusListener {
public:
virtual ~VirtualKeyboardCoordinator() = default;
// Reports a change in the virtual keyboard's visibility, along with the reason
// for the change.
virtual void NotifyVisibilityChange(
bool is_visible, fuchsia::input::virtualkeyboard::VisibilityChangeReason reason) = 0;
// Requests a change in the visibility and/or text type of the virtual keyboard.
virtual void RequestTypeAndVisibility(zx_koid_t requestor_view_koid,
fuchsia::input::virtualkeyboard::TextType text_type,
bool is_visibile) = 0;
// Reports an error from the Manager. The coordinator should close the corresponding FIDL
// connection with `error`.
virtual void NotifyManagerError(zx_status_t error) = 0;
// Reports a change in view focus. The coordinator should
// a) dismiss the keyboard, and
// b) process any pending RequestTypeAndVisibility() calls for `view_ref`, and
// c) accept new RequestTypeAndVisibility() calls for `view_ref`.
virtual void NotifyFocusChange(fuchsia::ui::views::ViewRef focused_view) = 0;
};
// Coordinates all activities for a single virtual keyboard.
//
// This includes:
// * Publishing the `fuchsia.input.virtualkeyboard.ControllerCreator` FIDL
// protocol, and binding `VirtualKeyboardController`s to the virtual keyboard.
// * Publishing the `fuchsia.input.virtualkeyboard.Manager` FIDL protocol, and
// binding a `VirtualKeyboardManager` to the virtual keyboard.
// * Relaying messages between `VirtualKeyboardController`s and the
// `VirtualKeyboardManager`
class FidlBoundVirtualKeyboardCoordinator
: public fuchsia::input::virtualkeyboard::ControllerCreator,
public VirtualKeyboardCoordinator {
public:
// Constructs a VirtualKeyboardCoordinator, and publishes the relevant FIDLs
// using `component_context`.
//
// Callers _should_ construct this object before entering the event loop.
explicit FidlBoundVirtualKeyboardCoordinator(sys::ComponentContext* component_context);
~FidlBoundVirtualKeyboardCoordinator() override;
fxl::WeakPtr<FidlBoundVirtualKeyboardCoordinator> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
// |VirtualKeyboardCoordinator|
void NotifyVisibilityChange(
bool is_visible, fuchsia::input::virtualkeyboard::VisibilityChangeReason reason) override;
void NotifyManagerError(zx_status_t error) override;
void RequestTypeAndVisibility(zx_koid_t requestor_view_koid,
fuchsia::input::virtualkeyboard::TextType text_type,
bool is_visible) override;
void NotifyFocusChange(fuchsia::ui::views::ViewRef focused_view) override;
void SetControllerForTest(std::unique_ptr<VirtualKeyboardController> controller) {
controller_bindings_.CloseAll();
controller_bindings_.AddBinding(std::move(controller));
}
private:
struct KeyboardConfig {
fuchsia::input::virtualkeyboard::TextType text_type;
bool is_visible;
};
// |fuchsia.input.virtualkeyboard.ControllerCreator|
void Create(fuchsia::ui::views::ViewRef view_ref,
fuchsia::input::virtualkeyboard::TextType text_type,
fidl::InterfaceRequest<fuchsia::input::virtualkeyboard::Controller>
controller_request) override;
// Creates a VirtualKeyboardManager and binds the manager to the provided channel.
void BindManager(fidl::InterfaceRequest<fuchsia::input::virtualkeyboard::Manager>);
// Destroys the VirtualKeyboardManager, and closes the associated channel with
// the provided status as the epitaph.
void HandleManagerBindingError(zx_status_t);
// Applies the `KeyboardConfig` for `focused_view_koid_` in
// `view_koid_to_pending_manager_config_`, if
// a) such a `KeyboardConfig` exists, AND
// b) a `fuchsia.input.virtualkeyboard.Manager` is bound.
//
// Also clears the entry for `focused_view_koid_` in the map,
// if it exists.
//
// Returns the KOID of the View whose request was applied, or
// a string describing why the request was not applied.
std::variant<zx_koid_t, std::string> ApplyFocusedRequest();
fidl::BindingSet<fuchsia::input::virtualkeyboard::ControllerCreator> creator_bindings_;
fidl::BindingSet<fuchsia::input::virtualkeyboard::Controller,
std::unique_ptr<VirtualKeyboardController>>
controller_bindings_;
std::optional<fidl::Binding<fuchsia::input::virtualkeyboard::Manager,
std::unique_ptr<VirtualKeyboardManager>>>
manager_binding_;
// Unfulfilled configuration requests for the virtual keyboard.
//
// * Used to buffer configuration changes when
// * the requestor does not have focus, OR
// * there is no manager client connected.
// * Equal to `nullopt`, except in the transient state where
// * `this` received a RequestTypeAndVisibility() call
// when there was no manager connected, and
// * no manager has connected since the RequestTypeAndVisibility()
// call.
std::map<zx_koid_t /* requestor_view_koid */, KeyboardConfig>
view_koid_to_pending_manager_config_;
// The view that is currently focused.
//
// * This is initially `nullopt`.
// * This will have a value after FocusDispatcher receives the first
// `OnFocusChange()` from Scenic.
// * This will have a value forever thereafter.
std::optional<zx_koid_t> focused_view_koid_;
// Must be last, to invalidate weak pointers held by other fields before their
// destructors are called.
fxl::WeakPtrFactory<FidlBoundVirtualKeyboardCoordinator> weak_ptr_factory_;
};
} // namespace virtual_keyboard_manager
#endif // SRC_UI_BIN_VIRTUAL_KEYBOARD_MANAGER_VIRTUAL_KEYBOARD_COORDINATOR_H_