blob: b49f1e73d9139bb78b96167f6cd9d6862f551555 [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.
#include "src/ui/bin/root_presenter/virtual_keyboard_manager.h"
#include <fuchsia/input/virtualkeyboard/cpp/fidl.h>
#include <lib/fidl/cpp/interface_request.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/types.h>
#include <utility>
#include "src/lib/fxl/memory/weak_ptr.h"
#include "src/ui/bin/root_presenter/virtual_keyboard_coordinator.h"
namespace root_presenter {
VirtualKeyboardManager::VirtualKeyboardManager(
fxl::WeakPtr<VirtualKeyboardCoordinator> coordinator, sys::ComponentContext* component_context,
fuchsia::input::virtualkeyboard::TextType initial_text_type)
: coordinator_(std::move(coordinator)), manager_binding_(this) {
FX_DCHECK(component_context);
pending_config_ = KeyboardConfig{.text_type = initial_text_type, .is_visible = false};
component_context->outgoing()->AddPublicService<fuchsia::input::virtualkeyboard::Manager>(
[this](fidl::InterfaceRequest<fuchsia::input::virtualkeyboard::Manager> request) {
MaybeBind(std::move(request));
});
}
void VirtualKeyboardManager::WatchTypeAndVisibility(WatchTypeAndVisibilityCallback callback) {
FX_LOGS(INFO) << __FUNCTION__;
if (watch_callback_) {
// The caller has violated the constraints of the protocol. Close the connection
// to signal the error, and reset the callback, to ensure that other method calls
// on |this| don't write to the closed connection.
manager_binding_.Close(ZX_ERR_BAD_STATE);
watch_callback_ = {};
return;
}
watch_callback_ = std::move(callback);
MaybeNotifyWatcher();
}
void VirtualKeyboardManager::Notify(bool is_visible,
fuchsia::input::virtualkeyboard::VisibilityChangeReason reason,
NotifyCallback callback) {
FX_LOGS(INFO) << __FUNCTION__;
if (coordinator_) {
coordinator_->NotifyVisibilityChange(is_visible, reason);
} else {
FX_LOGS(WARNING) << "Ignorning Notify() call: no `coordinator_`";
}
callback();
}
void VirtualKeyboardManager::OnTypeOrVisibilityChange(
fuchsia::input::virtualkeyboard::TextType text_type, bool is_visible) {
const KeyboardConfig proposed_config = {.text_type = text_type, .is_visible = is_visible};
if (last_sent_config_ != proposed_config) {
pending_config_ = proposed_config;
MaybeNotifyWatcher();
}
}
void VirtualKeyboardManager::MaybeBind(
fidl::InterfaceRequest<fuchsia::input::virtualkeyboard::Manager> request) {
if (manager_binding_.is_bound()) {
FX_LOGS(WARNING) << "Ignoring interface request; already bound";
} else {
manager_binding_.Bind(std::move(request));
manager_binding_.set_error_handler([](zx_status_t status) {
FX_LOGS(WARNING) << "manager closed with status=" << status << " ("
<< zx_status_get_string(status) << ")";
});
}
}
void VirtualKeyboardManager::MaybeNotifyWatcher() {
if (watch_callback_ && pending_config_) {
watch_callback_(pending_config_->text_type, pending_config_->is_visible);
last_sent_config_ = pending_config_;
pending_config_.reset();
watch_callback_ = {};
}
}
} // namespace root_presenter