[fuchsia] Stop calling FIDL from Dart in Flutter integration tests (flutter/engine#41669)

As we move the Dart FIDL bindings we need to stop calling FIDL methods
from Dart in the Flutter repo. This only affects some integration tests.

This moves the FIDL calls into C++ and uses platform messages to make
the functionality available to the Dart tests.
This commit is contained in:
Ian McKellar 2023-05-08 18:34:21 -07:00 committed by GitHub
parent de642efdac
commit 4579687380
21 changed files with 475 additions and 298 deletions

View File

@ -2799,7 +2799,6 @@ ORIGIN: ../../../flutter/shell/platform/fuchsia/dart_runner/dart_runner.h + ../.
ORIGIN: ../../../flutter/shell/platform/fuchsia/dart_runner/dart_test_component_controller.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/dart_runner/dart_test_component_controller.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/dart_runner/embedder/builtin.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/dart_runner/embedder/script_runner_snapshot.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/dart_runner/embedder/shim.dart + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/dart_runner/embedder/snapshot.cc.tmpl + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/shell/platform/fuchsia/dart_runner/embedder/snapshot.dart + ../../../flutter/LICENSE
@ -5422,7 +5421,6 @@ FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/dart_runner.h
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/dart_test_component_controller.cc
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/dart_test_component_controller.h
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/embedder/builtin.dart
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/embedder/script_runner_snapshot.dart
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/embedder/shim.dart
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/embedder/snapshot.cc.tmpl
FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/embedder/snapshot.dart

View File

@ -1,31 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Core SDK libraries.
import 'dart:async';
import 'dart:core';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'dart:math';
import 'dart:fuchsia.builtin';
import 'dart:zircon';
import 'dart:fuchsia';
import 'dart:typed_data';
// If new imports are added to this list, then it is also necessary to ensure
// that the dart_deps parameter in the rule
// gen_snapshot_cc("script_runner_snapshot") in the BUILD.gn file in this
// directory is updated with any new dependencies.
import 'package:fuchsia/fuchsia.dart';
import 'package:zircon/zircon.dart';
// FIDL bindings and application libraries.
import 'package:lib.app.dart/app.dart';
import 'package:fidl/fidl.dart';
// From //sdk/fidl/fuchsia.modular
import 'package:fidl_fuchsia_modular/fidl_async.dart';

View File

@ -162,9 +162,10 @@ template("runner_sources") {
"$fuchsia_sdk_root/fidl:fuchsia.ui.app",
"$fuchsia_sdk_root/fidl:fuchsia.ui.composition",
"$fuchsia_sdk_root/fidl:fuchsia.ui.pointer",
"$fuchsia_sdk_root/fidl:fuchsia.ui.views",
"$fuchsia_sdk_root/fidl:fuchsia.ui.scenic",
"$fuchsia_sdk_root/fidl:fuchsia.ui.pointerinjector",
"$fuchsia_sdk_root/fidl:fuchsia.ui.scenic",
"$fuchsia_sdk_root/fidl:fuchsia.ui.test.input",
"$fuchsia_sdk_root/fidl:fuchsia.ui.views",
"$fuchsia_sdk_root/pkg:async-cpp",
"$fuchsia_sdk_root/pkg:async-default",
"$fuchsia_sdk_root/pkg:async-loop",

View File

@ -582,7 +582,7 @@ void Engine::Initialize(
session_connection_->AwaitVsyncForSecondaryCallback(cb);
}
},
product_config](flutter::Shell& shell) mutable {
product_config, svc](flutter::Shell& shell) mutable {
OnShaderWarmup on_shader_warmup = nullptr;
if (product_config.enable_shader_warmup()) {
FML_DCHECK(surface_producer_);
@ -636,7 +636,8 @@ void Engine::Initialize(
std::move(on_request_announce_callback),
std::move(on_shader_warmup),
std::move(await_vsync_callback),
std::move(await_vsync_for_secondary_callback_callback));
std::move(await_vsync_for_secondary_callback_callback),
std::move(svc));
} else {
platform_view = std::make_unique<flutter_runner::GfxPlatformView>(
shell, shell.GetTaskRunners(), std::move(view_ref),
@ -655,7 +656,8 @@ void Engine::Initialize(
std::move(on_semantics_node_update_callback),
std::move(on_request_announce_callback),
std::move(on_shader_warmup), std::move(await_vsync_callback),
std::move(await_vsync_for_secondary_callback_callback));
std::move(await_vsync_for_secondary_callback_callback),
std::move(svc));
}
return platform_view;
});

View File

@ -32,7 +32,8 @@ FlatlandPlatformView::FlatlandPlatformView(
OnShaderWarmup on_shader_warmup,
AwaitVsyncCallback await_vsync_callback,
AwaitVsyncForSecondaryCallbackCallback
await_vsync_for_secondary_callback_callback)
await_vsync_for_secondary_callback_callback,
std::shared_ptr<sys::ServiceDirectory> dart_application_svc)
: PlatformView(true /* is_flatland */,
delegate,
std::move(task_runners),
@ -52,7 +53,8 @@ FlatlandPlatformView::FlatlandPlatformView(
std::move(on_request_announce_callback),
std::move(on_shader_warmup),
std::move(await_vsync_callback),
std::move(await_vsync_for_secondary_callback_callback)),
std::move(await_vsync_for_secondary_callback_callback),
std::move(dart_application_svc)),
parent_viewport_watcher_(parent_viewport_watcher.Bind()),
on_create_view_callback_(std::move(on_create_view_callback)),
on_destroy_view_callback_(std::move(on_destroy_view_callback)),

View File

@ -46,7 +46,8 @@ class FlatlandPlatformView final : public flutter_runner::PlatformView {
OnShaderWarmup on_shader_warmup,
AwaitVsyncCallback await_vsync_callback,
AwaitVsyncForSecondaryCallbackCallback
await_vsync_for_secondary_callback_callback);
await_vsync_for_secondary_callback_callback,
std::shared_ptr<sys::ServiceDirectory> dart_application_svc);
~FlatlandPlatformView() override;
void OnGetLayout(fuchsia::ui::composition::LayoutInfo info);

View File

@ -33,7 +33,8 @@ GfxPlatformView::GfxPlatformView(
OnShaderWarmup on_shader_warmup,
AwaitVsyncCallback await_vsync_callback,
AwaitVsyncForSecondaryCallbackCallback
await_vsync_for_secondary_callback_callback)
await_vsync_for_secondary_callback_callback,
std::shared_ptr<sys::ServiceDirectory> dart_application_svc)
: PlatformView(false /* is_flatland */,
delegate,
std::move(task_runners),
@ -53,7 +54,8 @@ GfxPlatformView::GfxPlatformView(
std::move(on_request_announce_callback),
std::move(on_shader_warmup),
std::move(await_vsync_callback),
std::move(await_vsync_for_secondary_callback_callback)),
std::move(await_vsync_for_secondary_callback_callback),
std::move(dart_application_svc)),
session_listener_binding_(this, std::move(session_listener_request)),
session_listener_error_callback_(
std::move(on_session_listener_error_callback)),

View File

@ -50,7 +50,8 @@ class GfxPlatformView final : public flutter_runner::PlatformView,
OnShaderWarmup on_shader_warmup,
AwaitVsyncCallback await_vsync_callback,
AwaitVsyncForSecondaryCallbackCallback
await_vsync_for_secondary_callback_callback);
await_vsync_for_secondary_callback_callback,
std::shared_ptr<sys::ServiceDirectory> dart_application_svc);
~GfxPlatformView() override;

View File

@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flow/embedded_views.h"
#include "pointer_injector_delegate.h"
#define RAPIDJSON_HAS_STDSTRING 1
#include "platform_view.h"
#include <fuchsia/ui/app/cpp/fidl.h>
#include <zircon/status.h>
#include <algorithm>
#include <cstring>
#include <limits>
@ -24,16 +25,35 @@
#include "third_party/rapidjson/include/rapidjson/writer.h"
#include "logging.h"
#include "pointer_injector_delegate.h"
#include "runtime/dart/utils/inlines.h"
#include "text_delegate.h"
#include "vsync_waiter.h"
namespace {
// Helper to extract a given member with a given type from a rapidjson object.
template <typename T, typename O, typename F>
bool CallWithMember(O obj, const char* member_name, F func) {
auto it = obj.FindMember(member_name);
if (it == obj.MemberEnd()) {
return false;
}
if (!it->value.template Is<T>()) {
return false;
}
func(it->value.template Get<T>());
return true;
}
} // namespace
namespace flutter_runner {
static constexpr char kFlutterPlatformChannel[] = "flutter/platform";
static constexpr char kAccessibilityChannel[] = "flutter/accessibility";
static constexpr char kFlutterPlatformViewsChannel[] = "flutter/platform_views";
static constexpr char kFuchsiaShaderWarmupChannel[] = "fuchsia/shader_warmup";
static constexpr char kFuchsiaInputTestChannel[] = "fuchsia/input_test";
static constexpr char kFuchsiaChildViewChannel[] = "fuchsia/child_view";
PlatformView::PlatformView(
bool is_flatland,
@ -56,7 +76,8 @@ PlatformView::PlatformView(
OnShaderWarmup on_shader_warmup,
AwaitVsyncCallback await_vsync_callback,
AwaitVsyncForSecondaryCallbackCallback
await_vsync_for_secondary_callback_callback)
await_vsync_for_secondary_callback_callback,
std::shared_ptr<sys::ServiceDirectory> dart_application_svc)
: flutter::PlatformView(delegate, std::move(task_runners)),
external_view_embedder_(external_view_embedder),
focus_delegate_(
@ -75,6 +96,7 @@ PlatformView::PlatformView(
await_vsync_callback_(await_vsync_callback),
await_vsync_for_secondary_callback_callback_(
await_vsync_for_secondary_callback_callback),
dart_application_svc_(dart_application_svc),
weak_factory_(this) {
fuchsia::ui::views::ViewRef view_ref_clone;
fidl::Clone(view_ref, &view_ref_clone);
@ -140,6 +162,51 @@ PlatformView::PlatformView(
std::move(pointerinjector_registry), std::move(view_ref_clone),
is_flatland);
// This is only used by the integration tests.
if (dart_application_svc) {
// Connect to TouchInputListener
fuchsia::ui::test::input::TouchInputListenerHandle touch_input_listener;
zx_status_t touch_input_listener_status =
dart_application_svc
->Connect<fuchsia::ui::test::input::TouchInputListener>(
touch_input_listener.NewRequest());
if (touch_input_listener_status != ZX_OK) {
FML_LOG(WARNING)
<< "fuchsia::ui::test::input::TouchInputListener connection failed: "
<< zx_status_get_string(touch_input_listener_status);
} else {
touch_input_listener_.Bind(std::move(touch_input_listener));
}
// Connect to KeyboardInputListener
fuchsia::ui::test::input::KeyboardInputListenerHandle
keyboard_input_listener;
zx_status_t keyboard_input_listener_status =
dart_application_svc
->Connect<fuchsia::ui::test::input::KeyboardInputListener>(
keyboard_input_listener.NewRequest());
if (keyboard_input_listener_status != ZX_OK) {
FML_LOG(WARNING) << "fuchsia::ui::test::input::KeyboardInputListener "
"connection failed: "
<< zx_status_get_string(keyboard_input_listener_status);
} else {
keyboard_input_listener_.Bind(std::move(keyboard_input_listener));
}
// Connect to MouseInputListener
fuchsia::ui::test::input::MouseInputListenerHandle mouse_input_listener;
zx_status_t mouse_input_listener_status =
dart_application_svc
->Connect<fuchsia::ui::test::input::MouseInputListener>(
mouse_input_listener.NewRequest());
if (mouse_input_listener_status != ZX_OK) {
FML_LOG(WARNING)
<< "fuchsia::ui::test::input::MouseInputListener connection failed: "
<< zx_status_get_string(mouse_input_listener_status);
} else {
mouse_input_listener_.Bind(std::move(mouse_input_listener));
}
}
// Finally! Register the native platform message handlers.
RegisterPlatformMessageHandlers();
}
@ -162,6 +229,12 @@ void PlatformView::RegisterPlatformMessageHandlers() {
platform_message_handlers_[kFuchsiaShaderWarmupChannel] =
std::bind(&HandleFuchsiaShaderWarmupChannelPlatformMessage,
on_shader_warmup_, std::placeholders::_1);
platform_message_handlers_[kFuchsiaInputTestChannel] =
std::bind(&PlatformView::HandleFuchsiaInputTestChannelPlatformMessage,
this, std::placeholders::_1);
platform_message_handlers_[kFuchsiaChildViewChannel] =
std::bind(&PlatformView::HandleFuchsiaChildViewChannelPlatformMessage,
this, std::placeholders::_1);
}
static flutter::PointerData::Change GetChangeFromPointerEventPhase(
@ -673,4 +746,224 @@ bool PlatformView::HandleFuchsiaShaderWarmupChannelPlatformMessage(
return true;
}
// Channel handler for kFuchsiaInputTestChannel
bool PlatformView::HandleFuchsiaInputTestChannelPlatformMessage(
std::unique_ptr<flutter::PlatformMessage> message) {
FML_DCHECK(message->channel() == kFuchsiaInputTestChannel);
const auto& data = message->data();
rapidjson::Document document;
document.Parse(reinterpret_cast<const char*>(data.GetMapping()),
data.GetSize());
if (document.HasParseError() || !document.IsObject()) {
FML_LOG(ERROR) << "Could not parse document";
return false;
}
auto root = document.GetObject();
auto method = root.FindMember("method");
if (method == root.MemberEnd() || !method->value.IsString()) {
FML_LOG(ERROR) << "Missing method";
return false;
}
FML_LOG(INFO) << "fuchsia/input_test: method=" << method->value.GetString();
if (method->value == "TouchInputListener.ReportTouchInput") {
if (!touch_input_listener_) {
FML_LOG(ERROR) << "TouchInputListener not found.";
return false;
}
fuchsia::ui::test::input::TouchInputListenerReportTouchInputRequest request;
CallWithMember<double>(
root, "local_x", [&](double local_x) { request.set_local_x(local_x); });
CallWithMember<double>(
root, "local_y", [&](double local_y) { request.set_local_y(local_y); });
CallWithMember<int64_t>(root, "time_received", [&](uint64_t time_received) {
request.set_time_received(time_received);
});
CallWithMember<std::string>(root, "component_name",
[&](std::string component_name) {
request.set_component_name(component_name);
});
touch_input_listener_->ReportTouchInput(std::move(request));
return true;
}
if (method->value == "KeyboardInputListener.ReportTextInput") {
if (!keyboard_input_listener_) {
FML_LOG(ERROR) << "KeyboardInputListener not found.";
return false;
}
fuchsia::ui::test::input::KeyboardInputListenerReportTextInputRequest
request;
CallWithMember<std::string>(
root, "text", [&](std::string text) { request.set_text(text); });
keyboard_input_listener_->ReportTextInput(std::move(request));
return true;
}
if (method->value == "MouseInputListener.ReportMouseInput") {
if (!mouse_input_listener_) {
FML_LOG(ERROR) << "MouseInputListener not found.";
return false;
}
fuchsia::ui::test::input::MouseInputListenerReportMouseInputRequest request;
CallWithMember<double>(
root, "local_x", [&](double local_x) { request.set_local_x(local_x); });
CallWithMember<double>(
root, "local_y", [&](double local_y) { request.set_local_y(local_y); });
CallWithMember<int64_t>(root, "time_received", [&](uint64_t time_received) {
request.set_time_received(time_received);
});
CallWithMember<std::string>(root, "component_name",
[&](std::string component_name) {
request.set_component_name(component_name);
});
CallWithMember<int>(root, "buttons", [&](int button_mask) {
std::vector<fuchsia::ui::test::input::MouseButton> buttons;
if (button_mask & 1) {
buttons.push_back(fuchsia::ui::test::input::MouseButton::FIRST);
}
if (button_mask & 2) {
buttons.push_back(fuchsia::ui::test::input::MouseButton::SECOND);
}
if (button_mask & 4) {
buttons.push_back(fuchsia::ui::test::input::MouseButton::THIRD);
}
request.set_buttons(buttons);
});
CallWithMember<std::string>(root, "phase", [&](std::string phase) {
if (phase == "add") {
request.set_phase(fuchsia::ui::test::input::MouseEventPhase::ADD);
} else if (phase == "hover") {
request.set_phase(fuchsia::ui::test::input::MouseEventPhase::HOVER);
} else if (phase == "down") {
request.set_phase(fuchsia::ui::test::input::MouseEventPhase::DOWN);
} else if (phase == "move") {
request.set_phase(fuchsia::ui::test::input::MouseEventPhase::MOVE);
} else if (phase == "up") {
request.set_phase(fuchsia::ui::test::input::MouseEventPhase::UP);
} else {
FML_LOG(ERROR) << "Unexpected mouse phase: " << phase;
}
});
CallWithMember<double>(
root, "wheel_x_physical_pixel", [&](double wheel_x_physical_pixel) {
request.set_wheel_x_physical_pixel(wheel_x_physical_pixel);
});
CallWithMember<double>(
root, "wheel_y_physical_pixel", [&](double wheel_y_physical_pixel) {
request.set_wheel_y_physical_pixel(wheel_y_physical_pixel);
});
mouse_input_listener_->ReportMouseInput(std::move(request));
return true;
}
FML_LOG(ERROR) << "fuchsia/input_test: unrecognized method "
<< method->value.GetString();
return false;
}
// Channel handler for kFuchsiaChildViewChannel
bool PlatformView::HandleFuchsiaChildViewChannelPlatformMessage(
std::unique_ptr<flutter::PlatformMessage> message) {
FML_DCHECK(message->channel() == kFuchsiaChildViewChannel);
if (message->data().GetSize() != 1 ||
(message->data().GetMapping()[0] != '0' &&
message->data().GetMapping()[0] != '1')) {
FML_LOG(ERROR) << kFuchsiaChildViewChannel
<< " data must be '0' (for gfx) or '1' (for flatland).";
return false;
}
bool flatland = message->data().GetMapping()[0] == '1';
if (!message->response()) {
FML_LOG(ERROR) << kFuchsiaChildViewChannel
<< " must have a response callback.";
return false;
}
if (!dart_application_svc_) {
FML_LOG(ERROR) << "No service directory.";
return false;
}
fuchsia::ui::app::ViewProviderHandle view_provider_handle;
zx_status_t status =
dart_application_svc_->Connect(view_provider_handle.NewRequest());
if (status != ZX_OK) {
FML_LOG(ERROR) << "Failed to connect to view provider.";
return false;
}
fuchsia::ui::app::ViewProviderPtr view_provider;
view_provider.Bind(std::move(view_provider_handle));
zx::handle view_id;
if (flatland) {
zx::channel view_tokens[2];
fuchsia::ui::views::ViewportCreationToken viewport_creation_token;
fuchsia::ui::views::ViewCreationToken view_creation_token;
status = zx::channel::create(0, &viewport_creation_token.value,
&view_creation_token.value);
if (status != ZX_OK) {
FML_LOG(ERROR) << "Creating view tokens: "
<< zx_status_get_string(status);
return false;
}
fuchsia::ui::app::CreateView2Args create_view_args;
create_view_args.set_view_creation_token(std::move(view_creation_token));
view_provider->CreateView2(std::move(create_view_args));
view_id = std::move(viewport_creation_token.value);
} else {
zx::eventpair view_tokens[2];
status = zx::eventpair::create(0, &view_tokens[0], &view_tokens[1]);
if (status != ZX_OK) {
FML_LOG(ERROR) << "Creating view tokens: "
<< zx_status_get_string(status);
return false;
}
fuchsia::ui::views::ViewHolderToken view_holder_token;
view_holder_token.value = std::move(view_tokens[0]);
zx::eventpair view_refs[2];
status = zx::eventpair::create(0, &view_refs[0], &view_refs[1]);
if (status != ZX_OK) {
FML_LOG(ERROR) << "Creating view refs: " << zx_status_get_string(status);
return false;
}
fuchsia::ui::views::ViewRefControl view_ref_control;
view_refs[0].duplicate(ZX_DEFAULT_EVENTPAIR_RIGHTS & ~ZX_RIGHT_DUPLICATE,
&view_ref_control.reference);
fuchsia::ui::views::ViewRef view_ref;
view_refs[1].duplicate(ZX_RIGHTS_BASIC, &view_ref.reference);
view_provider->CreateViewWithViewRef(std::move(view_tokens[1]),
std::move(view_ref_control),
std::move(view_ref));
view_id = std::move(view_holder_token.value);
}
if (view_id) {
message->response()->Complete(
std::make_unique<fml::DataMapping>(std::to_string(view_id.release())
));
return true;
} else {
return false;
}
}
} // namespace flutter_runner

View File

@ -10,6 +10,7 @@
#include <fuchsia/ui/input3/cpp/fidl.h>
#include <fuchsia/ui/pointer/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <fuchsia/ui/test/input/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fit/function.h>
#include <lib/sys/cpp/service_directory.h>
@ -84,7 +85,8 @@ class PlatformView : public flutter::PlatformView {
OnShaderWarmup on_shader_warmup,
AwaitVsyncCallback await_vsync_callback,
AwaitVsyncForSecondaryCallbackCallback
await_vsync_for_secondary_callback_callback);
await_vsync_for_secondary_callback_callback,
std::shared_ptr<sys::ServiceDirectory> dart_application_svc);
~PlatformView() override;
@ -136,6 +138,14 @@ class PlatformView : public flutter::PlatformView {
OnShaderWarmup on_shader_warmup,
std::unique_ptr<flutter::PlatformMessage> message);
// Channel handler for kFuchsiaInputTestChannel.
bool HandleFuchsiaInputTestChannelPlatformMessage(
std::unique_ptr<flutter::PlatformMessage> message);
// Channel handler for kFuchsiaChildViewChannel.
bool HandleFuchsiaChildViewChannelPlatformMessage(
std::unique_ptr<flutter::PlatformMessage> message);
virtual void OnCreateView(ViewCallback on_view_created,
int64_t view_id_raw,
bool hit_testable,
@ -186,6 +196,14 @@ class PlatformView : public flutter::PlatformView {
AwaitVsyncForSecondaryCallbackCallback
await_vsync_for_secondary_callback_callback_;
// Proxies for input tests.
fuchsia::ui::test::input::TouchInputListenerPtr touch_input_listener_;
fuchsia::ui::test::input::KeyboardInputListenerPtr keyboard_input_listener_;
fuchsia::ui::test::input::MouseInputListenerPtr mouse_input_listener_;
// Component's service directory.
std::shared_ptr<sys::ServiceDirectory> dart_application_svc_;
fml::WeakPtrFactory<PlatformView> weak_factory_; // Must be the last member.
FML_DISALLOW_COPY_AND_ASSIGN(PlatformView);

View File

@ -331,7 +331,8 @@ class PlatformViewBuilder {
std::move(on_create_surface_callback_),
std::move(on_semantics_node_update_callback_),
std::move(on_request_announce_callback_),
std::move(on_shader_warmup_callback_), [](auto...) {}, [](auto...) {});
std::move(on_shader_warmup_callback_), [](auto...) {}, [](auto...) {},
nullptr);
}
private:

View File

@ -436,7 +436,8 @@ class PlatformViewBuilder {
std::move(on_create_surface_callback_),
std::move(on_semantics_node_update_callback_),
std::move(on_request_announce_callback_),
std::move(on_shader_warmup_callback_), [](auto...) {}, [](auto...) {});
std::move(on_shader_warmup_callback_), [](auto...) {}, [](auto...) {},
nullptr);
}
private:

View File

@ -2,21 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'dart:io';
import 'dart:ui';
import 'package:args/args.dart';
import 'package:fidl_fuchsia_ui_app/fidl_async.dart';
import 'package:fidl_fuchsia_ui_views/fidl_async.dart';
import 'package:fuchsia_services/services.dart';
import 'package:vector_math/vector_math_64.dart' as vector_math_64;
import 'package:zircon/zircon.dart';
final _argsCsvFilePath = '/config/data/args.csv';
void main(List<String> args) {
void main(List<String> args) async {
print('parent-view: starting');
args = args + _GetArgsFromConfigFile();
@ -32,21 +30,12 @@ void main(List<String> args) {
TestApp app;
final useFlatland = arguments['useFlatland'];
if (useFlatland) {
app = TestApp(
ChildView(_launchFlatlandChildView()),
showOverlay: arguments['showOverlay'],
hitTestable: arguments['hitTestable'],
focusable: arguments['focusable'],
);
} else {
app = TestApp(
ChildView.gfx(_launchGfxChildView()),
showOverlay: arguments['showOverlay'],
hitTestable: arguments['hitTestable'],
focusable: arguments['focusable'],
);
}
app = TestApp(
ChildView(await _launchChildView(useFlatland)),
showOverlay: arguments['showOverlay'],
hitTestable: arguments['hitTestable'],
focusable: arguments['focusable'],
);
app.run();
}
@ -62,35 +51,33 @@ class TestApp {
Color _backgroundColor = _blue;
TestApp(
this.childView,
{this.showOverlay = false,
this.hitTestable = true,
this.focusable = true}) {
}
TestApp(this.childView,
{this.showOverlay = false,
this.hitTestable = true,
this.focusable = true}) {}
void run() {
childView.create(hitTestable, focusable, (ByteData reply) {
// Set up window allbacks.
window.onPointerDataPacket = (PointerDataPacket packet) {
for (final data in packet.data) {
if (data.change == PointerChange.down) {
this._backgroundColor = _black;
}
// Set up window allbacks.
window.onPointerDataPacket = (PointerDataPacket packet) {
for (final data in packet.data) {
if (data.change == PointerChange.down) {
this._backgroundColor = _black;
}
window.scheduleFrame();
};
window.onMetricsChanged = () {
window.scheduleFrame();
};
window.onBeginFrame = (Duration duration) {
this.beginFrame(duration);
};
// The child view should be attached to Scenic now.
// Ready to build the scene.
}
window.scheduleFrame();
});
};
window.onMetricsChanged = () {
window.scheduleFrame();
};
window.onBeginFrame = (Duration duration) {
this.beginFrame(duration);
};
// The child view should be attached to Scenic now.
// Ready to build the scene.
window.scheduleFrame();
});
}
void beginFrame(Duration duration) {
@ -114,18 +101,16 @@ class TestApp {
// Alignment.center
final windowCenter = windowSize.center(Offset.zero);
final windowPhysicalCenter = window.physicalSize.center(Offset.zero);
final childPhysicalOffset = windowPhysicalCenter - childPhysicalSize.center(Offset.zero);
final childPhysicalOffset =
windowPhysicalCenter - childPhysicalSize.center(Offset.zero);
sceneBuilder
..pushTransform(
vector_math_64.Matrix4.translationValues(childPhysicalOffset.dx,
childPhysicalOffset.dy,
0.0).storage)
..pushTransform(vector_math_64.Matrix4.translationValues(
childPhysicalOffset.dx, childPhysicalOffset.dy, 0.0)
.storage)
..addPlatformView(childView.viewId,
width: childPhysicalSize.width,
height: childPhysicalSize.height)
..pop()
;
width: childPhysicalSize.width, height: childPhysicalSize.height)
..pop();
if (showOverlay) {
final containerSize = windowSize * .66;
@ -135,15 +120,16 @@ class TestApp {
final overlaySize = containerSize * 0.5;
// Alignment.topRight
final overlayOffset = Offset(
containerOffset.dx + containerSize.width - overlaySize.width,
containerOffset.dy);
containerOffset.dx + containerSize.width - overlaySize.width,
containerOffset.dy);
final overlayPhysicalSize = overlaySize * pixelRatio;
final overlayPhysicalOffset = overlayOffset * pixelRatio;
final overlayPhysicalBounds = overlayPhysicalOffset & overlayPhysicalSize;
final recorder = PictureRecorder();
final overlayCullRect = Offset.zero & overlayPhysicalSize; // in canvas physical coordinates
final overlayCullRect =
Offset.zero & overlayPhysicalSize; // in canvas physical coordinates
final canvas = Canvas(recorder, overlayCullRect);
canvas.scale(pixelRatio);
final paint = Paint()..color = Color.fromARGB(255, 0, 255, 0);
@ -152,8 +138,7 @@ class TestApp {
sceneBuilder
..pushClipRect(overlayPhysicalBounds) // in window physical coordinates
..addPicture(overlayPhysicalOffset, overlayPicture)
..pop()
;
..pop();
}
sceneBuilder.pop();
@ -162,22 +147,12 @@ class TestApp {
}
class ChildView {
final ViewHolderToken viewHolderToken;
final ViewportCreationToken viewportCreationToken;
final int viewId;
ChildView(this.viewportCreationToken) : viewHolderToken = null, viewId = viewportCreationToken.value.handle.handle {
assert(viewId != null);
}
ChildView(this.viewId);
ChildView.gfx(this.viewHolderToken) : viewportCreationToken = null, viewId = viewHolderToken.value.handle.handle {
assert(viewId != null);
}
void create(
bool hitTestable,
bool focusable,
PlatformMessageResponseCallback callback) {
void create(bool hitTestable, bool focusable,
PlatformMessageResponseCallback callback) {
// Construct the dart:ui platform message to create the view, and when the
// return callback is invoked, build the scene. At that point, it is safe
// to embed the child-view2 in the scene.
@ -195,59 +170,31 @@ class ChildView {
],
};
final ByteData createViewMessage = utf8.encoder.convert(
json.encode(<String, Object>{
'method': 'View.create',
'args': args,
})
).buffer.asByteData();
final ByteData createViewMessage = utf8.encoder
.convert(json.encode(<String, Object>{
'method': 'View.create',
'args': args,
}))
.buffer
.asByteData();
final platformViewsChannel = 'flutter/platform_views';
PlatformDispatcher.instance.sendPlatformMessage(
platformViewsChannel,
createViewMessage,
callback);
PlatformDispatcher.instance
.sendPlatformMessage(platformViewsChannel, createViewMessage, callback);
}
}
ViewportCreationToken _launchFlatlandChildView() {
ViewProviderProxy viewProvider = ViewProviderProxy();
Incoming.fromSvcPath()
..connectToService(viewProvider)
..close();
Future<int> _launchChildView(bool useFlatland) async {
final message = Int8List.fromList([useFlatland ? 0x31 : 0x30]);
final completer = new Completer<ByteData>();
PlatformDispatcher.instance.sendPlatformMessage(
'fuchsia/child_view', ByteData.sublistView(message), (ByteData reply) {
completer.complete(reply);
});
final viewTokens = ChannelPair();
assert(viewTokens.status == ZX.OK);
final viewportCreationToken = ViewportCreationToken(value: viewTokens.first);
final viewCreationToken = ViewCreationToken(value: viewTokens.second);
final createViewArgs = CreateView2Args(viewCreationToken: viewCreationToken);
viewProvider.createView2(createViewArgs);
viewProvider.ctrl.close();
return viewportCreationToken;
}
ViewHolderToken _launchGfxChildView() {
ViewProviderProxy viewProvider = ViewProviderProxy();
Incoming.fromSvcPath()
..connectToService(viewProvider)
..close();
final viewTokens = EventPairPair();
assert(viewTokens.status == ZX.OK);
final viewHolderToken = ViewHolderToken(value: viewTokens.first);
final viewRefs = EventPairPair();
assert(viewRefs.status == ZX.OK);
final viewRefControl = ViewRefControl(reference: viewRefs.first.duplicate(ZX.DEFAULT_EVENTPAIR_RIGHTS & ~ZX.RIGHT_DUPLICATE));
final viewRef = ViewRef(reference: viewRefs.second.duplicate(ZX.RIGHTS_BASIC));
viewProvider.createViewWithViewRef(viewTokens.second, viewRefControl, viewRef);
viewProvider.ctrl.close();
return viewHolderToken;
return int.parse(
ascii.decode(((await completer.future).buffer.asUint8List())));
}
List<String> _GetArgsFromConfigFile() {

View File

@ -14,9 +14,7 @@ dart_library("lib") {
deps = [
"//flutter/shell/platform/fuchsia/dart:args",
"//flutter/tools/fuchsia/dart:fuchsia_services",
"//flutter/tools/fuchsia/dart:zircon",
"//flutter/tools/fuchsia/fidl:fuchsia.ui.test.input",
]
}

View File

@ -6,8 +6,6 @@ import 'dart:convert';
import 'dart:typed_data';
import 'dart:ui';
import 'package:fidl_fuchsia_ui_test_input/fidl_async.dart' as test_mouse;
import 'package:fuchsia_services/services.dart';
import 'package:zircon/zircon.dart';
void main() {
@ -16,38 +14,6 @@ void main() {
app.run();
}
List<test_mouse.MouseButton> getPressedButtons(int buttons) {
var pressed_buttons = <test_mouse.MouseButton>[];
if (buttons & 0x1 != 0) {
pressed_buttons.add(test_mouse.MouseButton.first);
}
if (buttons & (0x1 >> 1) != 0) {
pressed_buttons.add(test_mouse.MouseButton.second);
}
if (buttons & (0x1 >> 2) != 0) {
pressed_buttons.add(test_mouse.MouseButton.third);
}
return pressed_buttons;
}
test_mouse.MouseEventPhase getPhase(String event_type) {
switch (event_type) {
case 'add':
return test_mouse.MouseEventPhase.add;
case 'hover':
return test_mouse.MouseEventPhase.hover;
case 'down':
return test_mouse.MouseEventPhase.down;
case 'move':
return test_mouse.MouseEventPhase.move;
case 'up':
return test_mouse.MouseEventPhase.up;
default:
print('Invalid event type: ${event_type}');
}
}
class MyApp {
static const _red = Color.fromARGB(255, 244, 67, 54);
static const _orange = Color.fromARGB(255, 255, 152, 0);
@ -67,11 +33,8 @@ class MyApp {
// Each tap will increment the counter, we then determine what color to choose
int _touchCounter = 0;
final _responseListener = test_mouse.MouseInputListenerProxy();
void run() {
Incoming.fromSvcPath()
..connectToService(_responseListener);
// Set up window callbacks.
window.onPointerDataPacket = (PointerDataPacket packet) {
this.pointerDataPacket(packet);
@ -122,28 +85,45 @@ class MyApp {
_touchCounter++;
}
// Incoming.fromSvcPath()
// ..connectToService(_responseListener)
// ..close();
_respond(test_mouse.MouseInputListenerReportMouseInputRequest(
_reportMouseInput(
localX: data.physicalX,
localY: data.physicalY,
buttons: getPressedButtons(data.buttons),
phase: getPhase(data.change.name),
buttons: data.buttons,
phase: data.change.name,
timeReceived: nowNanos,
wheelXPhysicalPixel: data.scrollDeltaX,
wheelYPhysicalPixel: data.scrollDeltaY,
componentName: 'mouse-input-view',
));
);
}
}
window.scheduleFrame();
}
void _respond(test_mouse.MouseInputListenerReportMouseInputRequest request) async {
void _reportMouseInput(
{double localX,
double localY,
int timeReceived,
int buttons,
String phase,
double wheelXPhysicalPixel,
double wheelYPhysicalPixel}) {
print('mouse-input-view reporting mouse input to MouseInputListener');
await _responseListener.reportMouseInput(request);
final message = utf8.encoder
.convert(json.encode({
'method': 'MouseInputListener.ReportMouseInput',
'local_x': localX,
'local_y': localY,
'time_received': timeReceived,
'component_name': 'touch-input-view',
'buttons': buttons,
'phase': 'asdf',
'wheel_x_physical_pixel': wheelXPhysicalPixel,
'wheel_y_physical_pixel': wheelYPhysicalPixel,
}))
.buffer
.asByteData();
PlatformDispatcher.instance
.sendPlatformMessage('fuchsia/input_test', message, null);
}
}

View File

@ -12,12 +12,7 @@ dart_library("lib") {
testonly = true
package_name = "text-input-view"
sources = [ "text_input_view.dart" ]
deps = [
"//flutter/shell/platform/fuchsia/dart:args",
"//flutter/tools/fuchsia/dart:fuchsia_services",
"//flutter/tools/fuchsia/dart:zircon",
"//flutter/tools/fuchsia/fidl:fuchsia.ui.test.input",
]
deps = [ "//flutter/shell/platform/fuchsia/dart:args" ]
}
flutter_component("component") {

View File

@ -10,10 +10,6 @@ import 'dart:convert';
import 'dart:typed_data';
import 'dart:ui';
import 'package:fidl_fuchsia_ui_test_input/fidl_async.dart' as test_text;
import 'package:fuchsia_services/services.dart';
import 'package:zircon/zircon.dart';
// Corresponds to the USB HID values provided in fidl.fuchsia.input
// https://fuchsia.dev/reference/fidl/fuchsia.input
final Map<int, String> hidToKey = {
@ -39,11 +35,7 @@ class TestApp {
static const _yellow = Color.fromARGB(255, 255, 255, 0);
Color _backgroundColor = _yellow;
final _responseListener = test_text.KeyboardInputListenerProxy();
void run() {
// Connect to keyboard input response listener
Incoming.fromSvcPath().connectToService(_responseListener);
// Set up window callbacks
window.onPlatformMessage = (String name, ByteData data, PlatformMessageResponseCallback callback) {
this.decodeAndReportPlatformMessage(name, data);
@ -89,17 +81,20 @@ class TestApp {
if (name == "flutter/keyevent" && decodedJson["type"] == "keydown") {
if (hidToKey[decodedJson["hidUsage"]] != null) {
await _respond(test_text.KeyboardInputListenerReportTextInputRequest(
text: hidToKey[decodedJson["hidUsage"]],
));
_reportTextInput(hidToKey[decodedJson["hidUsage"]]);
}
}
window.scheduleFrame();
}
void _respond(test_text.KeyboardInputListenerReportTextInputRequest request) async {
void _reportTextInput(String text) {
print('text-input-view reporting keyboard input to KeyboardInputListener');
await _responseListener.reportTextInput(request);
final message = utf8.encoder.convert(json.encode({
'method': 'KeyboardInputListener.ReportTextInput',
'text': text,
})).buffer.asByteData();
PlatformDispatcher.instance.sendPlatformMessage('fuchsia/input_test', message, null);
}
}

View File

@ -15,12 +15,7 @@ dart_library("lib") {
deps = [
"//flutter/shell/platform/fuchsia/dart:args",
"//flutter/shell/platform/fuchsia/dart:vector_math",
"//flutter/tools/fuchsia/dart:fuchsia_services",
"//flutter/tools/fuchsia/dart:zircon",
"//flutter/tools/fuchsia/fidl:fuchsia.ui.app",
"//flutter/tools/fuchsia/fidl:fuchsia.ui.scenic",
"//flutter/tools/fuchsia/fidl:fuchsia.ui.test.input",
"//flutter/tools/fuchsia/fidl:fuchsia.ui.views",
]
}

View File

@ -2,22 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'dart:io';
import 'dart:ui';
import 'package:args/args.dart';
import 'package:fidl_fuchsia_ui_app/fidl_async.dart';
import 'package:fidl_fuchsia_ui_views/fidl_async.dart';
import 'package:fidl_fuchsia_ui_test_input/fidl_async.dart' as test_touch;
import 'package:fuchsia_services/services.dart';
import 'package:vector_math/vector_math_64.dart' as vector_math_64;
import 'package:zircon/zircon.dart';
final _argsCsvFilePath = '/config/data/args.csv';
void main(List<String> args) {
void main(List<String> args) async {
print('Launching embedding-flutter-view');
args = args + _GetArgsFromConfigFile();
@ -33,7 +30,7 @@ void main(List<String> args) {
// TODO(fxbug.dev/125514): Support Flatland Child View.
TestApp app = TestApp(
ChildView.gfx(_launchGfxChildView()),
ChildView(await _launchChildView(false)),
showOverlay: arguments['showOverlay'],
hitTestable: arguments['hitTestable'],
focusable: arguments['focusable'],
@ -50,7 +47,6 @@ class TestApp {
final bool showOverlay;
final bool hitTestable;
final bool focusable;
final _responseListener = test_touch.TouchInputListenerProxy();
Color _backgroundColor = _blue;
@ -159,40 +155,34 @@ class TestApp {
}
if (data.change == PointerChange.down || data.change == PointerChange.move) {
Incoming.fromSvcPath()
..connectToService(_responseListener)
..close();
_respond(test_touch.TouchInputListenerReportTouchInputRequest(
_reportTouchInput(
localX: data.physicalX,
localY: data.physicalY,
timeReceived: nowNanos,
componentName: 'embedding-flutter-view',
));
);
}
}
window.scheduleFrame();
}
void _respond(test_touch.TouchInputListenerReportTouchInputRequest request) async {
void _reportTouchInput({double localX, double localY, int timeReceived}) {
print('embedding-flutter-view reporting touch input to TouchInputListener');
await _responseListener.reportTouchInput(request);
final message = utf8.encoder.convert(json.encode({
'method': 'TouchInputListener.ReportTouchInput',
'local_x': localX,
'local_y': localY,
'time_received': timeReceived,
'component_name': 'embedding-flutter-view',
})).buffer.asByteData();
PlatformDispatcher.instance.sendPlatformMessage('fuchsia/input_test', message, null);
}
}
class ChildView {
final ViewHolderToken viewHolderToken;
final ViewportCreationToken viewportCreationToken;
final int viewId;
ChildView(this.viewportCreationToken) : viewHolderToken = null, viewId = viewportCreationToken.value.handle.handle {
assert(viewId != null);
}
ChildView.gfx(this.viewHolderToken) : viewportCreationToken = null, viewId = viewHolderToken.value.handle.handle {
assert(viewId != null);
}
ChildView(this.viewId);
void create(
bool hitTestable,
@ -230,27 +220,19 @@ class ChildView {
}
}
ViewHolderToken _launchGfxChildView() {
ViewProviderProxy viewProvider = ViewProviderProxy();
Incoming.fromSvcPath()
..connectToService(viewProvider)
..close();
Future<int> _launchChildView(bool useFlatland) async {
final message = Int8List.fromList([useFlatland ? 0x31 : 0x30]);
final completer = new Completer<ByteData>();
PlatformDispatcher.instance.sendPlatformMessage(
'fuchsia/child_view', ByteData.sublistView(message), (ByteData reply) {
completer.complete(reply);
});
final viewTokens = EventPairPair();
assert(viewTokens.status == ZX.OK);
final viewHolderToken = ViewHolderToken(value: viewTokens.first);
final viewRefs = EventPairPair();
assert(viewRefs.status == ZX.OK);
final viewRefControl = ViewRefControl(reference: viewRefs.first.duplicate(ZX.DEFAULT_EVENTPAIR_RIGHTS & ~ZX.RIGHT_DUPLICATE));
final viewRef = ViewRef(reference: viewRefs.second.duplicate(ZX.RIGHTS_BASIC));
viewProvider.createViewWithViewRef(viewTokens.second, viewRefControl, viewRef);
viewProvider.ctrl.close();
return viewHolderToken;
return int.parse(
ascii.decode(((await completer.future).buffer.asUint8List())));
}
List<String> _GetArgsFromConfigFile() {
List<String> args;
final f = File(_argsCsvFilePath);

View File

@ -14,9 +14,7 @@ dart_library("lib") {
deps = [
"//flutter/shell/platform/fuchsia/dart:args",
"//flutter/tools/fuchsia/dart:fuchsia_services",
"//flutter/tools/fuchsia/dart:zircon",
"//flutter/tools/fuchsia/fidl:fuchsia.ui.test.input",
]
}

View File

@ -6,8 +6,6 @@ import 'dart:convert';
import 'dart:typed_data';
import 'dart:ui';
import 'package:fidl_fuchsia_ui_test_input/fidl_async.dart' as test_touch;
import 'package:fuchsia_services/services.dart';
import 'package:zircon/zircon.dart';
void main() {
@ -22,8 +20,6 @@ class TestApp {
Color _backgroundColor = _pink;
final _responseListener = test_touch.TouchInputListenerProxy();
void run() {
// Set up window callbacks.
window.onPointerDataPacket = (PointerDataPacket packet) {
@ -74,24 +70,26 @@ class TestApp {
}
if (data.change == PointerChange.down || data.change == PointerChange.move) {
Incoming.fromSvcPath()
..connectToService(_responseListener)
..close();
_respond(test_touch.TouchInputListenerReportTouchInputRequest(
_reportTouchInput(
localX: data.physicalX,
localY: data.physicalY,
timeReceived: nowNanos,
componentName: 'touch-input-view',
));
);
}
}
window.scheduleFrame();
}
void _respond(test_touch.TouchInputListenerReportTouchInputRequest request) async {
void _reportTouchInput({double localX, double localY, int timeReceived}) {
print('touch-input-view reporting touch input to TouchInputListener');
await _responseListener.reportTouchInput(request);
final message = utf8.encoder.convert(json.encode({
'method': 'TouchInputListener.ReportTouchInput',
'local_x': localX,
'local_y': localY,
'time_received': timeReceived,
'component_name': 'touch-input-view',
})).buffer.asByteData();
PlatformDispatcher.instance.sendPlatformMessage('fuchsia/input_test', message, null);
}
}