mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Move platform specific information to PlatformConfiguration class (#19652)
This commit is contained in:
parent
13e993ed1a
commit
98cfd1db78
@ -399,6 +399,9 @@ FILE: ../../../flutter/lib/ui/ui_benchmarks.cc
|
||||
FILE: ../../../flutter/lib/ui/ui_dart_state.cc
|
||||
FILE: ../../../flutter/lib/ui/ui_dart_state.h
|
||||
FILE: ../../../flutter/lib/ui/window.dart
|
||||
FILE: ../../../flutter/lib/ui/window/platform_configuration.cc
|
||||
FILE: ../../../flutter/lib/ui/window/platform_configuration.h
|
||||
FILE: ../../../flutter/lib/ui/window/platform_configuration_unittests.cc
|
||||
FILE: ../../../flutter/lib/ui/window/platform_message.cc
|
||||
FILE: ../../../flutter/lib/ui/window/platform_message.h
|
||||
FILE: ../../../flutter/lib/ui/window/platform_message_response.cc
|
||||
@ -575,6 +578,8 @@ FILE: ../../../flutter/runtime/dart_vm_unittests.cc
|
||||
FILE: ../../../flutter/runtime/embedder_resources.cc
|
||||
FILE: ../../../flutter/runtime/embedder_resources.h
|
||||
FILE: ../../../flutter/runtime/fixtures/runtime_test.dart
|
||||
FILE: ../../../flutter/runtime/platform_data.cc
|
||||
FILE: ../../../flutter/runtime/platform_data.h
|
||||
FILE: ../../../flutter/runtime/ptrace_ios.cc
|
||||
FILE: ../../../flutter/runtime/ptrace_ios.h
|
||||
FILE: ../../../flutter/runtime/runtime_controller.cc
|
||||
@ -587,8 +592,6 @@ FILE: ../../../flutter/runtime/skia_concurrent_executor.cc
|
||||
FILE: ../../../flutter/runtime/skia_concurrent_executor.h
|
||||
FILE: ../../../flutter/runtime/test_font_data.cc
|
||||
FILE: ../../../flutter/runtime/test_font_data.h
|
||||
FILE: ../../../flutter/runtime/window_data.cc
|
||||
FILE: ../../../flutter/runtime/window_data.h
|
||||
FILE: ../../../flutter/shell/common/animator.cc
|
||||
FILE: ../../../flutter/shell/common/animator.h
|
||||
FILE: ../../../flutter/shell/common/animator_unittests.cc
|
||||
|
||||
@ -93,6 +93,8 @@ source_set_maybe_fuchsia_legacy("ui") {
|
||||
"text/text_box.h",
|
||||
"ui_dart_state.cc",
|
||||
"ui_dart_state.h",
|
||||
"window/platform_configuration.cc",
|
||||
"window/platform_configuration.h",
|
||||
"window/platform_message.cc",
|
||||
"window/platform_message.h",
|
||||
"window/platform_message_response.cc",
|
||||
@ -180,6 +182,7 @@ if (enable_unittests) {
|
||||
sources = [
|
||||
"painting/image_encoding_unittests.cc",
|
||||
"painting/vertices_unittests.cc",
|
||||
"window/platform_configuration_unittests.cc",
|
||||
"window/pointer_data_packet_converter_unittests.cc",
|
||||
]
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include "flutter/lib/ui/painting/image.h"
|
||||
#include "flutter/lib/ui/painting/picture.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "third_party/skia/include/core/SkImageInfo.h"
|
||||
#include "third_party/skia/include/core/SkSurface.h"
|
||||
@ -41,7 +42,10 @@ Scene::Scene(std::shared_ptr<flutter::Layer> rootLayer,
|
||||
uint32_t rasterizerTracingThreshold,
|
||||
bool checkerboardRasterCacheImages,
|
||||
bool checkerboardOffscreenLayers) {
|
||||
auto viewport_metrics = UIDartState::Current()->window()->viewport_metrics();
|
||||
auto viewport_metrics = UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->window()
|
||||
->viewport_metrics();
|
||||
|
||||
layer_tree_ = std::make_unique<LayerTree>(
|
||||
SkISize::Make(viewport_metrics.physical_width,
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
#include "flutter/lib/ui/text/font_collection.h"
|
||||
#include "flutter/lib/ui/text/paragraph.h"
|
||||
#include "flutter/lib/ui/text/paragraph_builder.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
#include "third_party/tonic/converter/dart_converter.h"
|
||||
#include "third_party/tonic/logging/dart_error.h"
|
||||
|
||||
@ -85,7 +85,7 @@ void DartUI::InitForGlobal() {
|
||||
SemanticsUpdate::RegisterNatives(g_natives);
|
||||
SemanticsUpdateBuilder::RegisterNatives(g_natives);
|
||||
Vertices::RegisterNatives(g_natives);
|
||||
Window::RegisterNatives(g_natives);
|
||||
PlatformConfiguration::RegisterNatives(g_natives);
|
||||
#if defined(LEGACY_FUCHSIA_EMBEDDER)
|
||||
SceneHost::RegisterNatives(g_natives);
|
||||
#endif
|
||||
|
||||
@ -34,6 +34,7 @@ void createVertices() {
|
||||
);
|
||||
_validateVertices(vertices);
|
||||
}
|
||||
|
||||
void _validateVertices(Vertices vertices) native 'ValidateVertices';
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
@ -42,8 +43,10 @@ void frameCallback(FrameInfo info) {
|
||||
}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void messageCallback(dynamic data) {
|
||||
}
|
||||
void messageCallback(dynamic data) {}
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void validateConfiguration() native 'ValidateConfiguration';
|
||||
|
||||
|
||||
// Draw a circle on a Canvas that has a PictureRecorder. Take the image from
|
||||
|
||||
@ -238,7 +238,7 @@ void _runMainZoned(Function startMainIsolateFunction,
|
||||
}, null);
|
||||
}
|
||||
|
||||
void _reportUnhandledException(String error, String stackTrace) native 'Window_reportUnhandledException';
|
||||
void _reportUnhandledException(String error, String stackTrace) native 'PlatformConfiguration_reportUnhandledException';
|
||||
|
||||
/// Invokes [callback] inside the given [zone].
|
||||
void _invoke(void callback()?, Zone zone) {
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include "flutter/lib/ui/painting/image.h"
|
||||
#include "flutter/lib/ui/painting/matrix.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
@ -474,8 +475,11 @@ void Canvas::drawShadow(const CanvasPath* path,
|
||||
ToDart("Canvas.drawShader called with non-genuine Path."));
|
||||
return;
|
||||
}
|
||||
SkScalar dpr =
|
||||
UIDartState::Current()->window()->viewport_metrics().device_pixel_ratio;
|
||||
SkScalar dpr = UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->window()
|
||||
->viewport_metrics()
|
||||
.device_pixel_ratio;
|
||||
external_allocation_size_ += path->path().approximateBytesUsed();
|
||||
flutter::PhysicalShapeLayer::DrawShadow(canvas_, path->path(), color,
|
||||
elevation, transparentOccluder, dpr);
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
#include "flutter/lib/ui/text/asset_manager_font_provider.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
#include "flutter/runtime/test_font_data.h"
|
||||
#include "rapidjson/document.h"
|
||||
#include "rapidjson/rapidjson.h"
|
||||
@ -30,8 +30,10 @@ namespace {
|
||||
void LoadFontFromList(tonic::Uint8List& font_data, // NOLINT
|
||||
Dart_Handle callback,
|
||||
std::string family_name) {
|
||||
FontCollection& font_collection =
|
||||
UIDartState::Current()->window()->client()->GetFontCollection();
|
||||
FontCollection& font_collection = UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->client()
|
||||
->GetFontCollection();
|
||||
font_collection.LoadFontFromList(font_data.data(), font_data.num_elements(),
|
||||
family_name);
|
||||
font_data.Release();
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include "flutter/fml/task_runner.h"
|
||||
#include "flutter/lib/ui/text/font_collection.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
#include "flutter/third_party/txt/src/txt/font_style.h"
|
||||
#include "flutter/third_party/txt/src/txt/font_weight.h"
|
||||
#include "flutter/third_party/txt/src/txt/paragraph_style.h"
|
||||
@ -288,8 +288,10 @@ ParagraphBuilder::ParagraphBuilder(
|
||||
style.locale = locale;
|
||||
}
|
||||
|
||||
FontCollection& font_collection =
|
||||
UIDartState::Current()->window()->client()->GetFontCollection();
|
||||
FontCollection& font_collection = UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->client()
|
||||
->GetFontCollection();
|
||||
|
||||
#if FLUTTER_ENABLE_SKSHAPER
|
||||
#define FLUTTER_PARAGRAPH_BUILDER txt::ParagraphBuilder::CreateSkiaBuilder
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
|
||||
#include "flutter/fml/message_loop.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
#include "third_party/tonic/converter/dart_converter.h"
|
||||
#include "third_party/tonic/dart_message_handler.h"
|
||||
|
||||
@ -73,8 +73,9 @@ void UIDartState::ThrowIfUIOperationsProhibited() {
|
||||
|
||||
void UIDartState::SetDebugName(const std::string debug_name) {
|
||||
debug_name_ = debug_name;
|
||||
if (window_) {
|
||||
window_->client()->UpdateIsolateDescription(debug_name_, main_port_);
|
||||
if (platform_configuration_) {
|
||||
platform_configuration_->client()->UpdateIsolateDescription(debug_name_,
|
||||
main_port_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,10 +83,12 @@ UIDartState* UIDartState::Current() {
|
||||
return static_cast<UIDartState*>(DartState::Current());
|
||||
}
|
||||
|
||||
void UIDartState::SetWindow(std::unique_ptr<Window> window) {
|
||||
window_ = std::move(window);
|
||||
if (window_) {
|
||||
window_->client()->UpdateIsolateDescription(debug_name_, main_port_);
|
||||
void UIDartState::SetPlatformConfiguration(
|
||||
std::unique_ptr<PlatformConfiguration> platform_configuration) {
|
||||
platform_configuration_ = std::move(platform_configuration);
|
||||
if (platform_configuration_) {
|
||||
platform_configuration_->client()->UpdateIsolateDescription(debug_name_,
|
||||
main_port_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
namespace flutter {
|
||||
class FontSelector;
|
||||
class Window;
|
||||
class PlatformConfiguration;
|
||||
|
||||
class UIDartState : public tonic::DartState {
|
||||
public:
|
||||
@ -44,7 +44,9 @@ class UIDartState : public tonic::DartState {
|
||||
|
||||
const std::string& logger_prefix() const { return logger_prefix_; }
|
||||
|
||||
Window* window() const { return window_.get(); }
|
||||
PlatformConfiguration* platform_configuration() const {
|
||||
return platform_configuration_.get();
|
||||
}
|
||||
|
||||
const TaskRunners& GetTaskRunners() const;
|
||||
|
||||
@ -97,7 +99,8 @@ class UIDartState : public tonic::DartState {
|
||||
|
||||
~UIDartState() override;
|
||||
|
||||
void SetWindow(std::unique_ptr<Window> window);
|
||||
void SetPlatformConfiguration(
|
||||
std::unique_ptr<PlatformConfiguration> platform_configuration);
|
||||
|
||||
const std::string& GetAdvisoryScriptURI() const;
|
||||
|
||||
@ -119,7 +122,7 @@ class UIDartState : public tonic::DartState {
|
||||
Dart_Port main_port_ = ILLEGAL_PORT;
|
||||
const bool is_root_isolate_;
|
||||
std::string debug_name_;
|
||||
std::unique_ptr<Window> window_;
|
||||
std::unique_ptr<PlatformConfiguration> platform_configuration_;
|
||||
tonic::DartMicrotaskQueue microtask_queue_;
|
||||
UnhandledExceptionCallback unhandled_exception_callback_;
|
||||
const std::shared_ptr<IsolateNameServer> isolate_name_server_;
|
||||
|
||||
@ -823,7 +823,7 @@ class Window {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
List<String> _computePlatformResolvedLocale(List<String?> supportedLocalesData) native 'Window_computePlatformResolvedLocale';
|
||||
List<String> _computePlatformResolvedLocale(List<String?> supportedLocalesData) native 'PlatformConfiguration_computePlatformResolvedLocale';
|
||||
|
||||
/// A callback that is invoked whenever [locale] changes value.
|
||||
///
|
||||
@ -1001,7 +1001,7 @@ class Window {
|
||||
}
|
||||
|
||||
late _SetNeedsReportTimingsFunc _setNeedsReportTimings;
|
||||
void _nativeSetNeedsReportTimings(bool value) native 'Window_setNeedsReportTimings';
|
||||
void _nativeSetNeedsReportTimings(bool value) native 'PlatformConfiguration_setNeedsReportTimings';
|
||||
|
||||
/// A callback that is invoked when pointer data is available.
|
||||
///
|
||||
@ -1051,7 +1051,7 @@ class Window {
|
||||
/// * [SystemChannels.navigation], which handles subsequent navigation
|
||||
/// requests from the embedder.
|
||||
String get defaultRouteName => _defaultRouteName();
|
||||
String _defaultRouteName() native 'Window_defaultRouteName';
|
||||
String _defaultRouteName() native 'PlatformConfiguration_defaultRouteName';
|
||||
|
||||
/// Requests that, at the next appropriate opportunity, the [onBeginFrame]
|
||||
/// and [onDrawFrame] callbacks be invoked.
|
||||
@ -1060,7 +1060,7 @@ class Window {
|
||||
///
|
||||
/// * [SchedulerBinding], the Flutter framework class which manages the
|
||||
/// scheduling of frames.
|
||||
void scheduleFrame() native 'Window_scheduleFrame';
|
||||
void scheduleFrame() native 'PlatformConfiguration_scheduleFrame';
|
||||
|
||||
/// Updates the application's rendering on the GPU with the newly provided
|
||||
/// [Scene]. This function must be called within the scope of the
|
||||
@ -1086,7 +1086,7 @@ class Window {
|
||||
/// scheduling of frames.
|
||||
/// * [RendererBinding], the Flutter framework class which manages layout and
|
||||
/// painting.
|
||||
void render(Scene scene) native 'Window_render';
|
||||
void render(Scene scene) native 'PlatformConfiguration_render';
|
||||
|
||||
/// Whether the user has requested that [updateSemantics] be called when
|
||||
/// the semantic contents of window changes.
|
||||
@ -1126,7 +1126,7 @@ class Window {
|
||||
|
||||
/// Additional accessibility features that may be enabled by the platform.
|
||||
AccessibilityFeatures get accessibilityFeatures => _accessibilityFeatures;
|
||||
// The zero value matches the default value in `window_data.h`.
|
||||
// The zero value matches the default value in `platform_data.h`.
|
||||
AccessibilityFeatures _accessibilityFeatures = const AccessibilityFeatures._(0);
|
||||
|
||||
/// A callback that is invoked when the value of [accessibilityFeatures] changes.
|
||||
@ -1148,7 +1148,7 @@ class Window {
|
||||
///
|
||||
/// In either case, this function disposes the given update, which means the
|
||||
/// semantics update cannot be used further.
|
||||
void updateSemantics(SemanticsUpdate update) native 'Window_updateSemantics';
|
||||
void updateSemantics(SemanticsUpdate update) native 'PlatformConfiguration_updateSemantics';
|
||||
|
||||
/// Set the debug name associated with this window's root isolate.
|
||||
///
|
||||
@ -1158,7 +1158,7 @@ class Window {
|
||||
/// This can be combined with flutter tools `--isolate-filter` flag to debug
|
||||
/// specific root isolates. For example: `flutter attach --isolate-filter=[name]`.
|
||||
/// Note that this does not rename any child isolates of the root.
|
||||
void setIsolateDebugName(String name) native 'Window_setIsolateDebugName';
|
||||
void setIsolateDebugName(String name) native 'PlatformConfiguration_setIsolateDebugName';
|
||||
|
||||
/// Sends a message to a platform-specific plugin.
|
||||
///
|
||||
@ -1179,7 +1179,7 @@ class Window {
|
||||
}
|
||||
String? _sendPlatformMessage(String name,
|
||||
PlatformMessageResponseCallback? callback,
|
||||
ByteData? data) native 'Window_sendPlatformMessage';
|
||||
ByteData? data) native 'PlatformConfiguration_sendPlatformMessage';
|
||||
|
||||
/// Called whenever this window receives a message from a platform-specific
|
||||
/// plugin.
|
||||
@ -1204,7 +1204,7 @@ class Window {
|
||||
|
||||
/// Called by [_dispatchPlatformMessage].
|
||||
void _respondToPlatformMessage(int responseId, ByteData? data)
|
||||
native 'Window_respondToPlatformMessage';
|
||||
native 'PlatformConfiguration_respondToPlatformMessage';
|
||||
|
||||
/// Wraps the given [callback] in another callback that ensures that the
|
||||
/// original callback is called in the zone it was registered in.
|
||||
@ -1230,7 +1230,7 @@ class Window {
|
||||
///
|
||||
/// For asynchronous communication between the embedder and isolate, a
|
||||
/// platform channel may be used.
|
||||
ByteData? getPersistentIsolateData() native 'Window_getPersistentIsolateData';
|
||||
ByteData? getPersistentIsolateData() native 'PlatformConfiguration_getPersistentIsolateData';
|
||||
}
|
||||
|
||||
/// Additional accessibility features that may be enabled by the platform.
|
||||
|
||||
437
lib/ui/window/platform_configuration.cc
Normal file
437
lib/ui/window/platform_configuration.cc
Normal file
@ -0,0 +1,437 @@
|
||||
// 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.
|
||||
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
|
||||
#include "flutter/lib/ui/compositing/scene.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/platform_message_response_dart.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "third_party/tonic/converter/dart_converter.h"
|
||||
#include "third_party/tonic/dart_args.h"
|
||||
#include "third_party/tonic/dart_library_natives.h"
|
||||
#include "third_party/tonic/dart_microtask_queue.h"
|
||||
#include "third_party/tonic/logging/dart_invoke.h"
|
||||
#include "third_party/tonic/typed_data/dart_byte_data.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace {
|
||||
|
||||
void DefaultRouteName(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
std::string routeName = UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->client()
|
||||
->DefaultRouteName();
|
||||
Dart_SetReturnValue(args, tonic::StdStringToDart(routeName));
|
||||
}
|
||||
|
||||
void ScheduleFrame(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
UIDartState::Current()->platform_configuration()->client()->ScheduleFrame();
|
||||
}
|
||||
|
||||
void Render(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
Dart_Handle exception = nullptr;
|
||||
Scene* scene =
|
||||
tonic::DartConverter<Scene*>::FromArguments(args, 1, exception);
|
||||
if (exception) {
|
||||
Dart_ThrowException(exception);
|
||||
return;
|
||||
}
|
||||
UIDartState::Current()->platform_configuration()->client()->Render(scene);
|
||||
}
|
||||
|
||||
void UpdateSemantics(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
Dart_Handle exception = nullptr;
|
||||
SemanticsUpdate* update =
|
||||
tonic::DartConverter<SemanticsUpdate*>::FromArguments(args, 1, exception);
|
||||
if (exception) {
|
||||
Dart_ThrowException(exception);
|
||||
return;
|
||||
}
|
||||
UIDartState::Current()->platform_configuration()->client()->UpdateSemantics(
|
||||
update);
|
||||
}
|
||||
|
||||
void SetIsolateDebugName(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
Dart_Handle exception = nullptr;
|
||||
const std::string name =
|
||||
tonic::DartConverter<std::string>::FromArguments(args, 1, exception);
|
||||
if (exception) {
|
||||
Dart_ThrowException(exception);
|
||||
return;
|
||||
}
|
||||
UIDartState::Current()->SetDebugName(name);
|
||||
}
|
||||
|
||||
void SetNeedsReportTimings(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
Dart_Handle exception = nullptr;
|
||||
bool value = tonic::DartConverter<bool>::FromArguments(args, 1, exception);
|
||||
UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->client()
|
||||
->SetNeedsReportTimings(value);
|
||||
}
|
||||
|
||||
void ReportUnhandledException(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
|
||||
Dart_Handle exception = nullptr;
|
||||
|
||||
auto error_name =
|
||||
tonic::DartConverter<std::string>::FromArguments(args, 0, exception);
|
||||
if (exception) {
|
||||
Dart_ThrowException(exception);
|
||||
return;
|
||||
}
|
||||
|
||||
auto stack_trace =
|
||||
tonic::DartConverter<std::string>::FromArguments(args, 1, exception);
|
||||
if (exception) {
|
||||
Dart_ThrowException(exception);
|
||||
return;
|
||||
}
|
||||
|
||||
UIDartState::Current()->ReportUnhandledException(std::move(error_name),
|
||||
std::move(stack_trace));
|
||||
}
|
||||
|
||||
Dart_Handle SendPlatformMessage(Dart_Handle window,
|
||||
const std::string& name,
|
||||
Dart_Handle callback,
|
||||
Dart_Handle data_handle) {
|
||||
UIDartState* dart_state = UIDartState::Current();
|
||||
|
||||
if (!dart_state->platform_configuration()) {
|
||||
return tonic::ToDart(
|
||||
"Platform messages can only be sent from the main isolate");
|
||||
}
|
||||
|
||||
fml::RefPtr<PlatformMessageResponse> response;
|
||||
if (!Dart_IsNull(callback)) {
|
||||
response = fml::MakeRefCounted<PlatformMessageResponseDart>(
|
||||
tonic::DartPersistentValue(dart_state, callback),
|
||||
dart_state->GetTaskRunners().GetUITaskRunner());
|
||||
}
|
||||
if (Dart_IsNull(data_handle)) {
|
||||
dart_state->platform_configuration()->client()->HandlePlatformMessage(
|
||||
fml::MakeRefCounted<PlatformMessage>(name, response));
|
||||
} else {
|
||||
tonic::DartByteData data(data_handle);
|
||||
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
|
||||
dart_state->platform_configuration()->client()->HandlePlatformMessage(
|
||||
fml::MakeRefCounted<PlatformMessage>(
|
||||
name, std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()),
|
||||
response));
|
||||
}
|
||||
|
||||
return Dart_Null();
|
||||
}
|
||||
|
||||
void _SendPlatformMessage(Dart_NativeArguments args) {
|
||||
tonic::DartCallStatic(&SendPlatformMessage, args);
|
||||
}
|
||||
|
||||
void RespondToPlatformMessage(Dart_Handle window,
|
||||
int response_id,
|
||||
const tonic::DartByteData& data) {
|
||||
if (Dart_IsNull(data.dart_handle())) {
|
||||
UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->CompletePlatformMessageEmptyResponse(response_id);
|
||||
} else {
|
||||
// TODO(engine): Avoid this copy.
|
||||
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
|
||||
UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->CompletePlatformMessageResponse(
|
||||
response_id,
|
||||
std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()));
|
||||
}
|
||||
}
|
||||
|
||||
void _RespondToPlatformMessage(Dart_NativeArguments args) {
|
||||
tonic::DartCallStatic(&RespondToPlatformMessage, args);
|
||||
}
|
||||
|
||||
void GetPersistentIsolateData(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
|
||||
auto persistent_isolate_data = UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->client()
|
||||
->GetPersistentIsolateData();
|
||||
|
||||
if (!persistent_isolate_data) {
|
||||
Dart_SetReturnValue(args, Dart_Null());
|
||||
return;
|
||||
}
|
||||
|
||||
Dart_SetReturnValue(
|
||||
args, tonic::DartByteData::Create(persistent_isolate_data->GetMapping(),
|
||||
persistent_isolate_data->GetSize()));
|
||||
}
|
||||
|
||||
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer) {
|
||||
return tonic::DartByteData::Create(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PlatformConfigurationClient::~PlatformConfigurationClient() {}
|
||||
|
||||
PlatformConfiguration::PlatformConfiguration(
|
||||
PlatformConfigurationClient* client)
|
||||
: client_(client) {}
|
||||
|
||||
PlatformConfiguration::~PlatformConfiguration() {}
|
||||
|
||||
void PlatformConfiguration::DidCreateIsolate() {
|
||||
library_.Set(tonic::DartState::Current(),
|
||||
Dart_LookupLibrary(tonic::ToDart("dart:ui")));
|
||||
window_.reset(new Window({1.0, 0.0, 0.0}));
|
||||
}
|
||||
|
||||
void PlatformConfiguration::UpdateLocales(
|
||||
const std::vector<std::string>& locales) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
tonic::LogIfError(tonic::DartInvokeField(
|
||||
library_.value(), "_updateLocales",
|
||||
{
|
||||
tonic::ToDart<std::vector<std::string>>(locales),
|
||||
}));
|
||||
}
|
||||
|
||||
void PlatformConfiguration::UpdateUserSettingsData(const std::string& data) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(),
|
||||
"_updateUserSettingsData",
|
||||
{
|
||||
tonic::StdStringToDart(data),
|
||||
}));
|
||||
}
|
||||
|
||||
void PlatformConfiguration::UpdateLifecycleState(const std::string& data) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(),
|
||||
"_updateLifecycleState",
|
||||
{
|
||||
tonic::StdStringToDart(data),
|
||||
}));
|
||||
}
|
||||
|
||||
void PlatformConfiguration::UpdateSemanticsEnabled(bool enabled) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(
|
||||
library_.value(), "_updateSemanticsEnabled", {tonic::ToDart(enabled)}));
|
||||
}
|
||||
|
||||
void PlatformConfiguration::UpdateAccessibilityFeatures(int32_t values) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(),
|
||||
"_updateAccessibilityFeatures",
|
||||
{tonic::ToDart(values)}));
|
||||
}
|
||||
|
||||
void PlatformConfiguration::DispatchPlatformMessage(
|
||||
fml::RefPtr<PlatformMessage> message) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
FML_DLOG(WARNING)
|
||||
<< "Dropping platform message for lack of DartState on channel: "
|
||||
<< message->channel();
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
Dart_Handle data_handle =
|
||||
(message->hasData()) ? ToByteData(message->data()) : Dart_Null();
|
||||
if (Dart_IsError(data_handle)) {
|
||||
FML_DLOG(WARNING)
|
||||
<< "Dropping platform message because of a Dart error on channel: "
|
||||
<< message->channel();
|
||||
return;
|
||||
}
|
||||
|
||||
int response_id = 0;
|
||||
if (auto response = message->response()) {
|
||||
response_id = next_response_id_++;
|
||||
pending_responses_[response_id] = response;
|
||||
}
|
||||
|
||||
tonic::LogIfError(
|
||||
tonic::DartInvokeField(library_.value(), "_dispatchPlatformMessage",
|
||||
{tonic::ToDart(message->channel()), data_handle,
|
||||
tonic::ToDart(response_id)}));
|
||||
}
|
||||
|
||||
void PlatformConfiguration::DispatchSemanticsAction(int32_t id,
|
||||
SemanticsAction action,
|
||||
std::vector<uint8_t> args) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
Dart_Handle args_handle = (args.empty()) ? Dart_Null() : ToByteData(args);
|
||||
|
||||
if (Dart_IsError(args_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(
|
||||
library_.value(), "_dispatchSemanticsAction",
|
||||
{tonic::ToDart(id), tonic::ToDart(static_cast<int32_t>(action)),
|
||||
args_handle}));
|
||||
}
|
||||
|
||||
void PlatformConfiguration::BeginFrame(fml::TimePoint frameTime) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
int64_t microseconds = (frameTime - fml::TimePoint()).ToMicroseconds();
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(), "_beginFrame",
|
||||
{
|
||||
Dart_NewInteger(microseconds),
|
||||
}));
|
||||
|
||||
UIDartState::Current()->FlushMicrotasksNow();
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(), "_drawFrame", {}));
|
||||
}
|
||||
|
||||
void PlatformConfiguration::ReportTimings(std::vector<int64_t> timings) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
Dart_Handle data_handle =
|
||||
Dart_NewTypedData(Dart_TypedData_kInt64, timings.size());
|
||||
|
||||
Dart_TypedData_Type type;
|
||||
void* data = nullptr;
|
||||
intptr_t num_acquired = 0;
|
||||
FML_CHECK(!Dart_IsError(
|
||||
Dart_TypedDataAcquireData(data_handle, &type, &data, &num_acquired)));
|
||||
FML_DCHECK(num_acquired == static_cast<int>(timings.size()));
|
||||
|
||||
memcpy(data, timings.data(), sizeof(int64_t) * timings.size());
|
||||
FML_CHECK(Dart_TypedDataReleaseData(data_handle));
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(), "_reportTimings",
|
||||
{
|
||||
data_handle,
|
||||
}));
|
||||
}
|
||||
|
||||
void PlatformConfiguration::CompletePlatformMessageEmptyResponse(
|
||||
int response_id) {
|
||||
if (!response_id) {
|
||||
return;
|
||||
}
|
||||
auto it = pending_responses_.find(response_id);
|
||||
if (it == pending_responses_.end()) {
|
||||
return;
|
||||
}
|
||||
auto response = std::move(it->second);
|
||||
pending_responses_.erase(it);
|
||||
response->CompleteEmpty();
|
||||
}
|
||||
|
||||
void PlatformConfiguration::CompletePlatformMessageResponse(
|
||||
int response_id,
|
||||
std::vector<uint8_t> data) {
|
||||
if (!response_id) {
|
||||
return;
|
||||
}
|
||||
auto it = pending_responses_.find(response_id);
|
||||
if (it == pending_responses_.end()) {
|
||||
return;
|
||||
}
|
||||
auto response = std::move(it->second);
|
||||
pending_responses_.erase(it);
|
||||
response->Complete(std::make_unique<fml::DataMapping>(std::move(data)));
|
||||
}
|
||||
|
||||
Dart_Handle ComputePlatformResolvedLocale(Dart_Handle supportedLocalesHandle) {
|
||||
std::vector<std::string> supportedLocales =
|
||||
tonic::DartConverter<std::vector<std::string>>::FromDart(
|
||||
supportedLocalesHandle);
|
||||
|
||||
std::vector<std::string> results =
|
||||
*UIDartState::Current()
|
||||
->platform_configuration()
|
||||
->client()
|
||||
->ComputePlatformResolvedLocale(supportedLocales);
|
||||
|
||||
return tonic::DartConverter<std::vector<std::string>>::ToDart(results);
|
||||
}
|
||||
|
||||
static void _ComputePlatformResolvedLocale(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
Dart_Handle result =
|
||||
ComputePlatformResolvedLocale(Dart_GetNativeArgument(args, 1));
|
||||
Dart_SetReturnValue(args, result);
|
||||
}
|
||||
|
||||
void PlatformConfiguration::RegisterNatives(
|
||||
tonic::DartLibraryNatives* natives) {
|
||||
natives->Register({
|
||||
{"PlatformConfiguration_defaultRouteName", DefaultRouteName, 1, true},
|
||||
{"PlatformConfiguration_scheduleFrame", ScheduleFrame, 1, true},
|
||||
{"PlatformConfiguration_sendPlatformMessage", _SendPlatformMessage, 4,
|
||||
true},
|
||||
{"PlatformConfiguration_respondToPlatformMessage",
|
||||
_RespondToPlatformMessage, 3, true},
|
||||
{"PlatformConfiguration_render", Render, 2, true},
|
||||
{"PlatformConfiguration_updateSemantics", UpdateSemantics, 2, true},
|
||||
{"PlatformConfiguration_setIsolateDebugName", SetIsolateDebugName, 2,
|
||||
true},
|
||||
{"PlatformConfiguration_reportUnhandledException",
|
||||
ReportUnhandledException, 2, true},
|
||||
{"PlatformConfiguration_setNeedsReportTimings", SetNeedsReportTimings, 2,
|
||||
true},
|
||||
{"PlatformConfiguration_getPersistentIsolateData",
|
||||
GetPersistentIsolateData, 1, true},
|
||||
{"PlatformConfiguration_computePlatformResolvedLocale",
|
||||
_ComputePlatformResolvedLocale, 2, true},
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
421
lib/ui/window/platform_configuration.h
Normal file
421
lib/ui/window/platform_configuration.h
Normal file
@ -0,0 +1,421 @@
|
||||
// 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.
|
||||
|
||||
#ifndef FLUTTER_LIB_UI_WINDOW_PLATFORM_CONFIGURATION_H_
|
||||
#define FLUTTER_LIB_UI_WINDOW_PLATFORM_CONFIGURATION_H_
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/fml/time/time_point.h"
|
||||
#include "flutter/lib/ui/semantics/semantics_update.h"
|
||||
#include "flutter/lib/ui/window/platform_message.h"
|
||||
#include "flutter/lib/ui/window/pointer_data_packet.h"
|
||||
#include "flutter/lib/ui/window/viewport_metrics.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "third_party/tonic/dart_persistent_value.h"
|
||||
|
||||
namespace tonic {
|
||||
class DartLibraryNatives;
|
||||
|
||||
// So tonic::ToDart<std::vector<int64_t>> returns List<int> instead of
|
||||
// List<dynamic>.
|
||||
template <>
|
||||
struct DartListFactory<int64_t> {
|
||||
static Dart_Handle NewList(intptr_t length) {
|
||||
return Dart_NewListOf(Dart_CoreType_Int, length);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace tonic
|
||||
|
||||
namespace flutter {
|
||||
class FontCollection;
|
||||
class PlatformMessage;
|
||||
class Scene;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief An enum for defining the different kinds of accessibility features
|
||||
/// that can be enabled by the platform.
|
||||
///
|
||||
/// Must match the `AccessibilityFeatureFlag` enum in framework.
|
||||
enum class AccessibilityFeatureFlag : int32_t {
|
||||
kAccessibleNavigation = 1 << 0,
|
||||
kInvertColors = 1 << 1,
|
||||
kDisableAnimations = 1 << 2,
|
||||
kBoldText = 1 << 3,
|
||||
kReduceMotion = 1 << 4,
|
||||
kHighContrast = 1 << 5,
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief A client interface that the `RuntimeController` uses to define
|
||||
/// handlers for `PlatformConfiguration` requests.
|
||||
///
|
||||
/// @see `PlatformConfiguration`
|
||||
///
|
||||
class PlatformConfigurationClient {
|
||||
public:
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief The route or path that the embedder requested when the
|
||||
/// application was launched.
|
||||
///
|
||||
/// This will be the string "`/`" if no particular route was
|
||||
/// requested.
|
||||
///
|
||||
virtual std::string DefaultRouteName() = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Requests that, at the next appropriate opportunity, a new
|
||||
/// frame be scheduled for rendering.
|
||||
///
|
||||
virtual void ScheduleFrame() = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Updates the client's rendering on the GPU with the newly
|
||||
/// provided Scene.
|
||||
///
|
||||
virtual void Render(Scene* scene) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Receives a updated semantics tree from the Framework.
|
||||
///
|
||||
/// @param[in] update The updated semantic tree to apply.
|
||||
///
|
||||
virtual void UpdateSemantics(SemanticsUpdate* update) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief When the Flutter application has a message to send to the
|
||||
/// underlying platform, the message needs to be forwarded to
|
||||
/// the platform on the appropriate thread (via the platform
|
||||
/// task runner). The PlatformConfiguration delegates this task
|
||||
/// to the engine via this method.
|
||||
///
|
||||
/// @see `PlatformView::HandlePlatformMessage`
|
||||
///
|
||||
/// @param[in] message The message from the Flutter application to send to
|
||||
/// the underlying platform.
|
||||
///
|
||||
virtual void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Returns the current collection of fonts available on the
|
||||
/// platform.
|
||||
///
|
||||
/// This function reads an XML file and makes font families and
|
||||
/// collections of them. MinikinFontForTest is used for FontFamily
|
||||
/// creation.
|
||||
virtual FontCollection& GetFontCollection() = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Notifies this client of the name of the root isolate and its
|
||||
/// port when that isolate is launched, restarted (in the
|
||||
/// cold-restart scenario) or the application itself updates the
|
||||
/// name of the root isolate (via `Window.setIsolateDebugName`
|
||||
/// in `window.dart`). The name of the isolate is meaningless to
|
||||
/// the engine but is used in instrumentation and tooling.
|
||||
/// Currently, this information is to update the service
|
||||
/// protocol list of available root isolates running in the VM
|
||||
/// and their names so that the appropriate isolate can be
|
||||
/// selected in the tools for debugging and instrumentation.
|
||||
///
|
||||
/// @param[in] isolate_name The isolate name
|
||||
/// @param[in] isolate_port The isolate port
|
||||
///
|
||||
virtual void UpdateIsolateDescription(const std::string isolate_name,
|
||||
int64_t isolate_port) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Notifies this client that the application has an opinion about
|
||||
/// whether its frame timings need to be reported backed to it.
|
||||
/// Due to the asynchronous nature of rendering in Flutter, it is
|
||||
/// not possible for the application to determine the total time
|
||||
/// it took to render a specific frame. While the layer-tree is
|
||||
/// constructed on the UI thread, it needs to be rendering on the
|
||||
/// raster thread. Dart code cannot execute on this thread. So any
|
||||
/// instrumentation about the frame times gathered on this thread
|
||||
/// needs to be aggregated and sent back to the UI thread for
|
||||
/// processing in Dart.
|
||||
///
|
||||
/// When the application indicates that frame times need to be
|
||||
/// reported, it collects this information till a specified number
|
||||
/// of data points are gathered. Then this information is sent
|
||||
/// back to Dart code via `Engine::ReportTimings`.
|
||||
///
|
||||
/// This option is engine counterpart of the
|
||||
/// `Window._setNeedsReportTimings` in `window.dart`.
|
||||
///
|
||||
/// @param[in] needs_reporting If reporting information should be collected
|
||||
/// and send back to Dart.
|
||||
///
|
||||
virtual void SetNeedsReportTimings(bool value) = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief The embedder can specify data that the isolate can request
|
||||
/// synchronously on launch. This accessor fetches that data.
|
||||
///
|
||||
/// This data is persistent for the duration of the Flutter
|
||||
/// application and is available even after isolate restarts.
|
||||
/// Because of this lifecycle, the size of this data must be kept
|
||||
/// to a minimum.
|
||||
///
|
||||
/// For asynchronous communication between the embedder and
|
||||
/// isolate, a platform channel may be used.
|
||||
///
|
||||
/// @return A map of the isolate data that the framework can request upon
|
||||
/// launch.
|
||||
///
|
||||
virtual std::shared_ptr<const fml::Mapping> GetPersistentIsolateData() = 0;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
/// @brief Directly invokes platform-specific APIs to compute the
|
||||
/// locale the platform would have natively resolved to.
|
||||
///
|
||||
/// @param[in] supported_locale_data The vector of strings that represents
|
||||
/// the locales supported by the app.
|
||||
/// Each locale consists of three
|
||||
/// strings: languageCode, countryCode,
|
||||
/// and scriptCode in that order.
|
||||
///
|
||||
/// @return A vector of 3 strings languageCode, countryCode, and
|
||||
/// scriptCode that represents the locale selected by the
|
||||
/// platform. Empty strings mean the value was unassigned. Empty
|
||||
/// vector represents a null locale.
|
||||
///
|
||||
virtual std::unique_ptr<std::vector<std::string>>
|
||||
ComputePlatformResolvedLocale(
|
||||
const std::vector<std::string>& supported_locale_data) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~PlatformConfigurationClient();
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief A class for holding and distributing platform-level information
|
||||
/// to and from the Dart code in Flutter's framework.
|
||||
///
|
||||
/// It handles communication between the engine and the framework,
|
||||
/// and owns the main window.
|
||||
///
|
||||
/// It communicates with the RuntimeController through the use of a
|
||||
/// PlatformConfigurationClient interface, which the
|
||||
/// RuntimeController defines.
|
||||
///
|
||||
class PlatformConfiguration final {
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Creates a new PlatformConfiguration, typically created by the
|
||||
/// RuntimeController.
|
||||
///
|
||||
/// @param[in] client The `PlatformConfigurationClient` to be injected into
|
||||
/// the PlatformConfiguration. This client is used to
|
||||
/// forward requests to the RuntimeController.
|
||||
///
|
||||
explicit PlatformConfiguration(PlatformConfigurationClient* client);
|
||||
|
||||
// PlatformConfiguration is not copyable.
|
||||
PlatformConfiguration(const PlatformConfiguration&) = delete;
|
||||
PlatformConfiguration& operator=(const PlatformConfiguration&) = delete;
|
||||
|
||||
~PlatformConfiguration();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Access to the platform configuration client (which typically
|
||||
/// is implemented by the RuntimeController).
|
||||
///
|
||||
/// @return Returns the client used to construct this
|
||||
/// PlatformConfiguration.
|
||||
///
|
||||
PlatformConfigurationClient* client() const { return client_; }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Called by the RuntimeController once it has created the root
|
||||
/// isolate, so that the PlatformController can get a handle to
|
||||
/// the 'dart:ui' library.
|
||||
///
|
||||
/// It uses the handle to call the hooks in hooks.dart.
|
||||
///
|
||||
void DidCreateIsolate();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Update the specified locale data in the framework.
|
||||
///
|
||||
/// @deprecated The persistent isolate data must be used for this purpose
|
||||
/// instead.
|
||||
///
|
||||
/// @param[in] locale_data The locale data. This should consist of groups of
|
||||
/// 4 strings, each group representing a single locale.
|
||||
///
|
||||
void UpdateLocales(const std::vector<std::string>& locales);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Update the user settings data in the framework.
|
||||
///
|
||||
/// @deprecated The persistent isolate data must be used for this purpose
|
||||
/// instead.
|
||||
///
|
||||
/// @param[in] data The user settings data.
|
||||
///
|
||||
void UpdateUserSettingsData(const std::string& data);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Updates the lifecycle state data in the framework.
|
||||
///
|
||||
/// @deprecated The persistent isolate data must be used for this purpose
|
||||
/// instead.
|
||||
///
|
||||
/// @param[in] data The lifecycle state data.
|
||||
///
|
||||
void UpdateLifecycleState(const std::string& data);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Notifies the PlatformConfiguration that the embedder has
|
||||
/// expressed an opinion about whether the accessibility tree
|
||||
/// should be generated or not. This call originates in the
|
||||
/// platform view and is forwarded to the PlatformConfiguration
|
||||
/// here by the engine.
|
||||
///
|
||||
/// @param[in] enabled Whether the accessibility tree is enabled or
|
||||
/// disabled.
|
||||
///
|
||||
void UpdateSemanticsEnabled(bool enabled);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Forward the preference of accessibility features that must be
|
||||
/// enabled in the semantics tree to the framwork.
|
||||
///
|
||||
/// @param[in] flags The accessibility features that must be generated in
|
||||
/// the semantics tree.
|
||||
///
|
||||
void UpdateAccessibilityFeatures(int32_t flags);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Notifies the PlatformConfiguration that the client has sent
|
||||
/// it a message. This call originates in the platform view and
|
||||
/// has been forwarded through the engine to here.
|
||||
///
|
||||
/// @param[in] message The message sent from the embedder to the Dart
|
||||
/// application.
|
||||
///
|
||||
void DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Notifies the framework that the embedder encountered an
|
||||
/// accessibility related action on the specified node. This call
|
||||
/// originates on the platform view and has been forwarded to the
|
||||
/// platform configuration here by the engine.
|
||||
///
|
||||
/// @param[in] id The identifier of the accessibility node.
|
||||
/// @param[in] action The accessibility related action performed on the
|
||||
/// node of the specified ID.
|
||||
/// @param[in] args Optional data that applies to the specified action.
|
||||
///
|
||||
void DispatchSemanticsAction(int32_t id,
|
||||
SemanticsAction action,
|
||||
std::vector<uint8_t> args);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Notifies the framework that it is time to begin working on a
|
||||
/// new
|
||||
/// frame previously scheduled via a call to
|
||||
/// `PlatformConfigurationClient::ScheduleFrame`. This call
|
||||
/// originates in the animator.
|
||||
///
|
||||
/// The frame time given as the argument indicates the point at
|
||||
/// which the current frame interval began. It is very slightly
|
||||
/// (because of scheduling overhead) in the past. If a new layer
|
||||
/// tree is not produced and given to the GPU task runner within
|
||||
/// one frame interval from this point, the Flutter application
|
||||
/// will jank.
|
||||
///
|
||||
/// This method calls the `::_beginFrame` method in `hooks.dart`.
|
||||
///
|
||||
/// @param[in] frame_time The point at which the current frame interval
|
||||
/// began. May be used by animation interpolators,
|
||||
/// physics simulations, etc..
|
||||
///
|
||||
void BeginFrame(fml::TimePoint frame_time);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Dart code cannot fully measure the time it takes for a
|
||||
/// specific frame to be rendered. This is because Dart code only
|
||||
/// runs on the UI task runner. That is only a small part of the
|
||||
/// overall frame workload. The GPU task runner frame workload is
|
||||
/// executed on a thread where Dart code cannot run (and hence
|
||||
/// instrument). Besides, due to the pipelined nature of rendering
|
||||
/// in Flutter, there may be multiple frame workloads being
|
||||
/// processed at any given time. However, for non-Timeline based
|
||||
/// profiling, it is useful for trace collection and processing to
|
||||
/// happen in Dart. To do this, the GPU task runner frame
|
||||
/// workloads need to be instrumented separately. After a set
|
||||
/// number of these profiles have been gathered, they need to be
|
||||
/// reported back to Dart code. The engine reports this extra
|
||||
/// instrumentation information back to the framework by invoking
|
||||
/// this method at predefined intervals.
|
||||
///
|
||||
/// @see `FrameTiming`
|
||||
///
|
||||
/// @param[in] timings Collection of `FrameTiming::kCount` * `n` timestamps
|
||||
/// for `n` frames whose timings have not been reported
|
||||
/// yet. A collection of integers is reported here for
|
||||
/// easier conversions to Dart objects. The timestamps
|
||||
/// are measured against the system monotonic clock
|
||||
/// measured in microseconds.
|
||||
///
|
||||
void ReportTimings(std::vector<int64_t> timings);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Registers the native handlers for Dart functions that this
|
||||
/// class handles.
|
||||
///
|
||||
/// @param[in] natives The natives registry that the functions will be
|
||||
/// registered with.
|
||||
///
|
||||
static void RegisterNatives(tonic::DartLibraryNatives* natives);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Retrieves the Window managed by the PlatformConfiguration.
|
||||
///
|
||||
/// @return a pointer to the Window.
|
||||
///
|
||||
Window* window() const { return window_.get(); }
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Responds to a previous platform message to the engine from the
|
||||
/// framework.
|
||||
///
|
||||
/// @param[in] response_id The unique id that identifies the original platform
|
||||
/// message to respond to.
|
||||
/// @param[in] data The data to send back in the response.
|
||||
///
|
||||
void CompletePlatformMessageResponse(int response_id,
|
||||
std::vector<uint8_t> data);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Responds to a previous platform message to the engine from the
|
||||
/// framework with an empty response.
|
||||
///
|
||||
/// @param[in] response_id The unique id that identifies the original platform
|
||||
/// message to respond to.
|
||||
///
|
||||
void CompletePlatformMessageEmptyResponse(int response_id);
|
||||
|
||||
private:
|
||||
PlatformConfigurationClient* client_;
|
||||
tonic::DartPersistentValue library_;
|
||||
|
||||
std::unique_ptr<Window> window_;
|
||||
|
||||
// We use id 0 to mean that no response is expected.
|
||||
int next_response_id_ = 1;
|
||||
std::unordered_map<int, fml::RefPtr<PlatformMessageResponse>>
|
||||
pending_responses_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_LIB_UI_WINDOW_PLATFORM_CONFIGURATION_H_
|
||||
139
lib/ui/window/platform_configuration_unittests.cc
Normal file
139
lib/ui/window/platform_configuration_unittests.cc
Normal file
@ -0,0 +1,139 @@
|
||||
// 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.
|
||||
|
||||
#define FML_USED_ON_EMBEDDER
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
|
||||
#include "flutter/common/task_runners.h"
|
||||
#include "flutter/fml/synchronization/waitable_event.h"
|
||||
#include "flutter/lib/ui/painting/vertices.h"
|
||||
#include "flutter/runtime/dart_vm.h"
|
||||
#include "flutter/shell/common/shell_test.h"
|
||||
#include "flutter/shell/common/thread_host.h"
|
||||
#include "flutter/testing/testing.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
class DummyPlatformConfigurationClient : public PlatformConfigurationClient {
|
||||
public:
|
||||
DummyPlatformConfigurationClient() {
|
||||
std::vector<uint8_t> data;
|
||||
isolate_data_.reset(new ::fml::DataMapping(data));
|
||||
}
|
||||
std::string DefaultRouteName() override { return "TestRoute"; }
|
||||
void ScheduleFrame() override {}
|
||||
void Render(Scene* scene) override {}
|
||||
void UpdateSemantics(SemanticsUpdate* update) override {}
|
||||
void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) override {}
|
||||
FontCollection& GetFontCollection() override { return font_collection_; }
|
||||
void UpdateIsolateDescription(const std::string isolate_name,
|
||||
int64_t isolate_port) override {}
|
||||
void SetNeedsReportTimings(bool value) override {}
|
||||
std::shared_ptr<const fml::Mapping> GetPersistentIsolateData() override {
|
||||
return isolate_data_;
|
||||
}
|
||||
std::unique_ptr<std::vector<std::string>> ComputePlatformResolvedLocale(
|
||||
const std::vector<std::string>& supported_locale_data) override {
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
private:
|
||||
FontCollection font_collection_;
|
||||
std::shared_ptr<const fml::Mapping> isolate_data_;
|
||||
};
|
||||
|
||||
TEST_F(ShellTest, PlatformConfigurationInitialization) {
|
||||
auto message_latch = std::make_shared<fml::AutoResetWaitableEvent>();
|
||||
|
||||
auto nativeValidateConfiguration = [message_latch](
|
||||
Dart_NativeArguments args) {
|
||||
PlatformConfiguration* configuration =
|
||||
UIDartState::Current()->platform_configuration();
|
||||
ASSERT_NE(configuration->window(), nullptr);
|
||||
ASSERT_EQ(configuration->window()->viewport_metrics().device_pixel_ratio,
|
||||
1.0);
|
||||
ASSERT_EQ(configuration->window()->viewport_metrics().physical_width, 0.0);
|
||||
ASSERT_EQ(configuration->window()->viewport_metrics().physical_height, 0.0);
|
||||
|
||||
message_latch->Signal();
|
||||
};
|
||||
|
||||
Settings settings = CreateSettingsForFixture();
|
||||
TaskRunners task_runners("test", // label
|
||||
GetCurrentTaskRunner(), // platform
|
||||
CreateNewThread(), // raster
|
||||
CreateNewThread(), // ui
|
||||
CreateNewThread() // io
|
||||
);
|
||||
|
||||
AddNativeCallback("ValidateConfiguration",
|
||||
CREATE_NATIVE_ENTRY(nativeValidateConfiguration));
|
||||
|
||||
std::unique_ptr<Shell> shell =
|
||||
CreateShell(std::move(settings), std::move(task_runners));
|
||||
|
||||
ASSERT_TRUE(shell->IsSetup());
|
||||
auto run_configuration = RunConfiguration::InferFromSettings(settings);
|
||||
run_configuration.SetEntrypoint("validateConfiguration");
|
||||
|
||||
shell->RunEngine(std::move(run_configuration), [&](auto result) {
|
||||
ASSERT_EQ(result, Engine::RunStatus::Success);
|
||||
});
|
||||
|
||||
message_latch->Wait();
|
||||
DestroyShell(std::move(shell), std::move(task_runners));
|
||||
}
|
||||
|
||||
TEST_F(ShellTest, PlatformConfigurationWindowMetricsUpdate) {
|
||||
auto message_latch = std::make_shared<fml::AutoResetWaitableEvent>();
|
||||
|
||||
auto nativeValidateConfiguration = [message_latch](
|
||||
Dart_NativeArguments args) {
|
||||
PlatformConfiguration* configuration =
|
||||
UIDartState::Current()->platform_configuration();
|
||||
|
||||
ASSERT_NE(configuration->window(), nullptr);
|
||||
configuration->window()->UpdateWindowMetrics(
|
||||
ViewportMetrics{2.0, 10.0, 20.0});
|
||||
ASSERT_EQ(configuration->window()->viewport_metrics().device_pixel_ratio,
|
||||
2.0);
|
||||
ASSERT_EQ(configuration->window()->viewport_metrics().physical_width, 10.0);
|
||||
ASSERT_EQ(configuration->window()->viewport_metrics().physical_height,
|
||||
20.0);
|
||||
|
||||
message_latch->Signal();
|
||||
};
|
||||
|
||||
Settings settings = CreateSettingsForFixture();
|
||||
TaskRunners task_runners("test", // label
|
||||
GetCurrentTaskRunner(), // platform
|
||||
CreateNewThread(), // raster
|
||||
CreateNewThread(), // ui
|
||||
CreateNewThread() // io
|
||||
);
|
||||
|
||||
AddNativeCallback("ValidateConfiguration",
|
||||
CREATE_NATIVE_ENTRY(nativeValidateConfiguration));
|
||||
|
||||
std::unique_ptr<Shell> shell =
|
||||
CreateShell(std::move(settings), std::move(task_runners));
|
||||
|
||||
ASSERT_TRUE(shell->IsSetup());
|
||||
auto run_configuration = RunConfiguration::InferFromSettings(settings);
|
||||
run_configuration.SetEntrypoint("validateConfiguration");
|
||||
|
||||
shell->RunEngine(std::move(run_configuration), [&](auto result) {
|
||||
ASSERT_EQ(result, Engine::RunStatus::Success);
|
||||
});
|
||||
|
||||
message_latch->Wait();
|
||||
DestroyShell(std::move(shell), std::move(task_runners));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
@ -80,4 +80,16 @@ ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
FML_DCHECK(device_pixel_ratio > 0);
|
||||
}
|
||||
|
||||
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height)
|
||||
: device_pixel_ratio(p_device_pixel_ratio),
|
||||
physical_width(p_physical_width),
|
||||
physical_height(p_physical_height) {
|
||||
// Ensure we don't have nonsensical dimensions.
|
||||
FML_DCHECK(physical_width >= 0);
|
||||
FML_DCHECK(physical_height >= 0);
|
||||
FML_DCHECK(device_pixel_ratio > 0);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -52,6 +52,12 @@ struct ViewportMetrics {
|
||||
double p_physical_view_inset_bottom,
|
||||
double p_physical_view_inset_left);
|
||||
|
||||
// Create a ViewportMetrics instance that doesn't include depth, padding, or
|
||||
// insets.
|
||||
ViewportMetrics(double p_device_pixel_ratio,
|
||||
double p_physical_width,
|
||||
double p_physical_height);
|
||||
|
||||
double device_pixel_ratio = 1.0;
|
||||
double physical_width = 0;
|
||||
double physical_height = 0;
|
||||
|
||||
@ -4,183 +4,35 @@
|
||||
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
|
||||
#include "flutter/lib/ui/compositing/scene.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/platform_message_response_dart.h"
|
||||
#include "third_party/tonic/converter/dart_converter.h"
|
||||
#include "third_party/tonic/dart_args.h"
|
||||
#include "third_party/tonic/dart_library_natives.h"
|
||||
#include "third_party/tonic/dart_microtask_queue.h"
|
||||
#include "third_party/tonic/logging/dart_invoke.h"
|
||||
#include "third_party/tonic/typed_data/dart_byte_data.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace {
|
||||
|
||||
void DefaultRouteName(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
std::string routeName =
|
||||
UIDartState::Current()->window()->client()->DefaultRouteName();
|
||||
Dart_SetReturnValue(args, tonic::StdStringToDart(routeName));
|
||||
Window::Window(ViewportMetrics metrics) : viewport_metrics_(metrics) {
|
||||
library_.Set(tonic::DartState::Current(),
|
||||
Dart_LookupLibrary(tonic::ToDart("dart:ui")));
|
||||
}
|
||||
|
||||
void ScheduleFrame(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
UIDartState::Current()->window()->client()->ScheduleFrame();
|
||||
}
|
||||
|
||||
void Render(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
Dart_Handle exception = nullptr;
|
||||
Scene* scene =
|
||||
tonic::DartConverter<Scene*>::FromArguments(args, 1, exception);
|
||||
if (exception) {
|
||||
Dart_ThrowException(exception);
|
||||
return;
|
||||
}
|
||||
UIDartState::Current()->window()->client()->Render(scene);
|
||||
}
|
||||
|
||||
void UpdateSemantics(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
Dart_Handle exception = nullptr;
|
||||
SemanticsUpdate* update =
|
||||
tonic::DartConverter<SemanticsUpdate*>::FromArguments(args, 1, exception);
|
||||
if (exception) {
|
||||
Dart_ThrowException(exception);
|
||||
return;
|
||||
}
|
||||
UIDartState::Current()->window()->client()->UpdateSemantics(update);
|
||||
}
|
||||
|
||||
void SetIsolateDebugName(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
Dart_Handle exception = nullptr;
|
||||
const std::string name =
|
||||
tonic::DartConverter<std::string>::FromArguments(args, 1, exception);
|
||||
if (exception) {
|
||||
Dart_ThrowException(exception);
|
||||
return;
|
||||
}
|
||||
UIDartState::Current()->SetDebugName(name);
|
||||
}
|
||||
|
||||
void SetNeedsReportTimings(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
Dart_Handle exception = nullptr;
|
||||
bool value = tonic::DartConverter<bool>::FromArguments(args, 1, exception);
|
||||
UIDartState::Current()->window()->client()->SetNeedsReportTimings(value);
|
||||
}
|
||||
|
||||
void ReportUnhandledException(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
|
||||
Dart_Handle exception = nullptr;
|
||||
|
||||
auto error_name =
|
||||
tonic::DartConverter<std::string>::FromArguments(args, 0, exception);
|
||||
if (exception) {
|
||||
Dart_ThrowException(exception);
|
||||
return;
|
||||
}
|
||||
|
||||
auto stack_trace =
|
||||
tonic::DartConverter<std::string>::FromArguments(args, 1, exception);
|
||||
if (exception) {
|
||||
Dart_ThrowException(exception);
|
||||
return;
|
||||
}
|
||||
|
||||
UIDartState::Current()->ReportUnhandledException(std::move(error_name),
|
||||
std::move(stack_trace));
|
||||
}
|
||||
|
||||
Dart_Handle SendPlatformMessage(Dart_Handle window,
|
||||
const std::string& name,
|
||||
Dart_Handle callback,
|
||||
Dart_Handle data_handle) {
|
||||
UIDartState* dart_state = UIDartState::Current();
|
||||
|
||||
if (!dart_state->window()) {
|
||||
return tonic::ToDart(
|
||||
"Platform messages can only be sent from the main isolate");
|
||||
}
|
||||
|
||||
fml::RefPtr<PlatformMessageResponse> response;
|
||||
if (!Dart_IsNull(callback)) {
|
||||
response = fml::MakeRefCounted<PlatformMessageResponseDart>(
|
||||
tonic::DartPersistentValue(dart_state, callback),
|
||||
dart_state->GetTaskRunners().GetUITaskRunner());
|
||||
}
|
||||
if (Dart_IsNull(data_handle)) {
|
||||
dart_state->window()->client()->HandlePlatformMessage(
|
||||
fml::MakeRefCounted<PlatformMessage>(name, response));
|
||||
} else {
|
||||
tonic::DartByteData data(data_handle);
|
||||
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
|
||||
dart_state->window()->client()->HandlePlatformMessage(
|
||||
fml::MakeRefCounted<PlatformMessage>(
|
||||
name, std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()),
|
||||
response));
|
||||
}
|
||||
|
||||
return Dart_Null();
|
||||
}
|
||||
|
||||
void _SendPlatformMessage(Dart_NativeArguments args) {
|
||||
tonic::DartCallStatic(&SendPlatformMessage, args);
|
||||
}
|
||||
|
||||
void RespondToPlatformMessage(Dart_Handle window,
|
||||
int response_id,
|
||||
const tonic::DartByteData& data) {
|
||||
if (Dart_IsNull(data.dart_handle())) {
|
||||
UIDartState::Current()->window()->CompletePlatformMessageEmptyResponse(
|
||||
response_id);
|
||||
} else {
|
||||
// TODO(engine): Avoid this copy.
|
||||
const uint8_t* buffer = static_cast<const uint8_t*>(data.data());
|
||||
UIDartState::Current()->window()->CompletePlatformMessageResponse(
|
||||
response_id,
|
||||
std::vector<uint8_t>(buffer, buffer + data.length_in_bytes()));
|
||||
}
|
||||
}
|
||||
|
||||
void _RespondToPlatformMessage(Dart_NativeArguments args) {
|
||||
tonic::DartCallStatic(&RespondToPlatformMessage, args);
|
||||
}
|
||||
|
||||
void GetPersistentIsolateData(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
|
||||
auto persistent_isolate_data =
|
||||
UIDartState::Current()->window()->client()->GetPersistentIsolateData();
|
||||
|
||||
if (!persistent_isolate_data) {
|
||||
Dart_SetReturnValue(args, Dart_Null());
|
||||
return;
|
||||
}
|
||||
|
||||
Dart_SetReturnValue(
|
||||
args, tonic::DartByteData::Create(persistent_isolate_data->GetMapping(),
|
||||
persistent_isolate_data->GetSize()));
|
||||
}
|
||||
|
||||
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer) {
|
||||
return tonic::DartByteData::Create(buffer.data(), buffer.size());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WindowClient::~WindowClient() {}
|
||||
|
||||
Window::Window(WindowClient* client) : client_(client) {}
|
||||
|
||||
Window::~Window() {}
|
||||
|
||||
void Window::DidCreateIsolate() {
|
||||
library_.Set(tonic::DartState::Current(),
|
||||
Dart_LookupLibrary(tonic::ToDart("dart:ui")));
|
||||
void Window::DispatchPointerDataPacket(const PointerDataPacket& packet) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
const std::vector<uint8_t>& buffer = packet.data();
|
||||
Dart_Handle data_handle =
|
||||
tonic::DartByteData::Create(buffer.data(), buffer.size());
|
||||
if (Dart_IsError(data_handle)) {
|
||||
return;
|
||||
}
|
||||
tonic::LogIfError(tonic::DartInvokeField(
|
||||
library_.value(), "_dispatchPointerDataPacket", {data_handle}));
|
||||
}
|
||||
|
||||
void Window::UpdateWindowMetrics(const ViewportMetrics& metrics) {
|
||||
@ -213,244 +65,4 @@ void Window::UpdateWindowMetrics(const ViewportMetrics& metrics) {
|
||||
}));
|
||||
}
|
||||
|
||||
void Window::UpdateLocales(const std::vector<std::string>& locales) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
tonic::LogIfError(tonic::DartInvokeField(
|
||||
library_.value(), "_updateLocales",
|
||||
{
|
||||
tonic::ToDart<std::vector<std::string>>(locales),
|
||||
}));
|
||||
}
|
||||
|
||||
void Window::UpdateUserSettingsData(const std::string& data) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(),
|
||||
"_updateUserSettingsData",
|
||||
{
|
||||
tonic::StdStringToDart(data),
|
||||
}));
|
||||
}
|
||||
|
||||
void Window::UpdateLifecycleState(const std::string& data) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(),
|
||||
"_updateLifecycleState",
|
||||
{
|
||||
tonic::StdStringToDart(data),
|
||||
}));
|
||||
}
|
||||
|
||||
void Window::UpdateSemanticsEnabled(bool enabled) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(
|
||||
library_.value(), "_updateSemanticsEnabled", {tonic::ToDart(enabled)}));
|
||||
}
|
||||
|
||||
void Window::UpdateAccessibilityFeatures(int32_t values) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(),
|
||||
"_updateAccessibilityFeatures",
|
||||
{tonic::ToDart(values)}));
|
||||
}
|
||||
|
||||
void Window::DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
FML_DLOG(WARNING)
|
||||
<< "Dropping platform message for lack of DartState on channel: "
|
||||
<< message->channel();
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
Dart_Handle data_handle =
|
||||
(message->hasData()) ? ToByteData(message->data()) : Dart_Null();
|
||||
if (Dart_IsError(data_handle)) {
|
||||
FML_DLOG(WARNING)
|
||||
<< "Dropping platform message because of a Dart error on channel: "
|
||||
<< message->channel();
|
||||
return;
|
||||
}
|
||||
|
||||
int response_id = 0;
|
||||
if (auto response = message->response()) {
|
||||
response_id = next_response_id_++;
|
||||
pending_responses_[response_id] = response;
|
||||
}
|
||||
|
||||
tonic::LogIfError(
|
||||
tonic::DartInvokeField(library_.value(), "_dispatchPlatformMessage",
|
||||
{tonic::ToDart(message->channel()), data_handle,
|
||||
tonic::ToDart(response_id)}));
|
||||
}
|
||||
|
||||
void Window::DispatchPointerDataPacket(const PointerDataPacket& packet) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
Dart_Handle data_handle = ToByteData(packet.data());
|
||||
if (Dart_IsError(data_handle)) {
|
||||
return;
|
||||
}
|
||||
tonic::LogIfError(tonic::DartInvokeField(
|
||||
library_.value(), "_dispatchPointerDataPacket", {data_handle}));
|
||||
}
|
||||
|
||||
void Window::DispatchSemanticsAction(int32_t id,
|
||||
SemanticsAction action,
|
||||
std::vector<uint8_t> args) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
Dart_Handle args_handle = (args.empty()) ? Dart_Null() : ToByteData(args);
|
||||
|
||||
if (Dart_IsError(args_handle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(
|
||||
library_.value(), "_dispatchSemanticsAction",
|
||||
{tonic::ToDart(id), tonic::ToDart(static_cast<int32_t>(action)),
|
||||
args_handle}));
|
||||
}
|
||||
|
||||
void Window::BeginFrame(fml::TimePoint frameTime) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
int64_t microseconds = (frameTime - fml::TimePoint()).ToMicroseconds();
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(), "_beginFrame",
|
||||
{
|
||||
Dart_NewInteger(microseconds),
|
||||
}));
|
||||
|
||||
UIDartState::Current()->FlushMicrotasksNow();
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(), "_drawFrame", {}));
|
||||
}
|
||||
|
||||
void Window::ReportTimings(std::vector<int64_t> timings) {
|
||||
std::shared_ptr<tonic::DartState> dart_state = library_.dart_state().lock();
|
||||
if (!dart_state) {
|
||||
return;
|
||||
}
|
||||
tonic::DartState::Scope scope(dart_state);
|
||||
|
||||
Dart_Handle data_handle =
|
||||
Dart_NewTypedData(Dart_TypedData_kInt64, timings.size());
|
||||
|
||||
Dart_TypedData_Type type;
|
||||
void* data = nullptr;
|
||||
intptr_t num_acquired = 0;
|
||||
FML_CHECK(!Dart_IsError(
|
||||
Dart_TypedDataAcquireData(data_handle, &type, &data, &num_acquired)));
|
||||
FML_DCHECK(num_acquired == static_cast<int>(timings.size()));
|
||||
|
||||
memcpy(data, timings.data(), sizeof(int64_t) * timings.size());
|
||||
FML_CHECK(Dart_TypedDataReleaseData(data_handle));
|
||||
|
||||
tonic::LogIfError(tonic::DartInvokeField(library_.value(), "_reportTimings",
|
||||
{
|
||||
data_handle,
|
||||
}));
|
||||
}
|
||||
|
||||
void Window::CompletePlatformMessageEmptyResponse(int response_id) {
|
||||
if (!response_id) {
|
||||
return;
|
||||
}
|
||||
auto it = pending_responses_.find(response_id);
|
||||
if (it == pending_responses_.end()) {
|
||||
return;
|
||||
}
|
||||
auto response = std::move(it->second);
|
||||
pending_responses_.erase(it);
|
||||
response->CompleteEmpty();
|
||||
}
|
||||
|
||||
void Window::CompletePlatformMessageResponse(int response_id,
|
||||
std::vector<uint8_t> data) {
|
||||
if (!response_id) {
|
||||
return;
|
||||
}
|
||||
auto it = pending_responses_.find(response_id);
|
||||
if (it == pending_responses_.end()) {
|
||||
return;
|
||||
}
|
||||
auto response = std::move(it->second);
|
||||
pending_responses_.erase(it);
|
||||
response->Complete(std::make_unique<fml::DataMapping>(std::move(data)));
|
||||
}
|
||||
|
||||
Dart_Handle ComputePlatformResolvedLocale(Dart_Handle supportedLocalesHandle) {
|
||||
std::vector<std::string> supportedLocales =
|
||||
tonic::DartConverter<std::vector<std::string>>::FromDart(
|
||||
supportedLocalesHandle);
|
||||
|
||||
std::vector<std::string> results =
|
||||
*UIDartState::Current()
|
||||
->window()
|
||||
->client()
|
||||
->ComputePlatformResolvedLocale(supportedLocales);
|
||||
|
||||
return tonic::DartConverter<std::vector<std::string>>::ToDart(results);
|
||||
}
|
||||
|
||||
static void _ComputePlatformResolvedLocale(Dart_NativeArguments args) {
|
||||
UIDartState::ThrowIfUIOperationsProhibited();
|
||||
Dart_Handle result =
|
||||
ComputePlatformResolvedLocale(Dart_GetNativeArgument(args, 1));
|
||||
Dart_SetReturnValue(args, result);
|
||||
}
|
||||
|
||||
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
|
||||
natives->Register({
|
||||
{"Window_defaultRouteName", DefaultRouteName, 1, true},
|
||||
{"Window_scheduleFrame", ScheduleFrame, 1, true},
|
||||
{"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
|
||||
{"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true},
|
||||
{"Window_render", Render, 2, true},
|
||||
{"Window_updateSemantics", UpdateSemantics, 2, true},
|
||||
{"Window_setIsolateDebugName", SetIsolateDebugName, 2, true},
|
||||
{"Window_reportUnhandledException", ReportUnhandledException, 2, true},
|
||||
{"Window_setNeedsReportTimings", SetNeedsReportTimings, 2, true},
|
||||
{"Window_getPersistentIsolateData", GetPersistentIsolateData, 1, true},
|
||||
{"Window_computePlatformResolvedLocale", _ComputePlatformResolvedLocale,
|
||||
2, true},
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -9,102 +9,27 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/fml/time/time_point.h"
|
||||
#include "flutter/lib/ui/semantics/semantics_update.h"
|
||||
#include "flutter/lib/ui/window/platform_message.h"
|
||||
#include "flutter/lib/ui/window/pointer_data_packet.h"
|
||||
#include "flutter/lib/ui/window/viewport_metrics.h"
|
||||
#include "third_party/skia/include/gpu/GrDirectContext.h"
|
||||
#include "third_party/tonic/dart_persistent_value.h"
|
||||
|
||||
namespace tonic {
|
||||
class DartLibraryNatives;
|
||||
|
||||
// So tonice::ToDart<std::vector<int64_t>> returns List<int> instead of
|
||||
// List<dynamic>.
|
||||
template <>
|
||||
struct DartListFactory<int64_t> {
|
||||
static Dart_Handle NewList(intptr_t length) {
|
||||
return Dart_NewListOf(Dart_CoreType_Int, length);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace tonic
|
||||
|
||||
namespace flutter {
|
||||
class FontCollection;
|
||||
class Scene;
|
||||
|
||||
// Must match the AccessibilityFeatureFlag enum in window.dart.
|
||||
enum class AccessibilityFeatureFlag : int32_t {
|
||||
kAccessibleNavigation = 1 << 0,
|
||||
kInvertColors = 1 << 1,
|
||||
kDisableAnimations = 1 << 2,
|
||||
kBoldText = 1 << 3,
|
||||
kReduceMotion = 1 << 4,
|
||||
kHighContrast = 1 << 5,
|
||||
};
|
||||
|
||||
class WindowClient {
|
||||
public:
|
||||
virtual std::string DefaultRouteName() = 0;
|
||||
virtual void ScheduleFrame() = 0;
|
||||
virtual void Render(Scene* scene) = 0;
|
||||
virtual void UpdateSemantics(SemanticsUpdate* update) = 0;
|
||||
virtual void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) = 0;
|
||||
virtual FontCollection& GetFontCollection() = 0;
|
||||
virtual void UpdateIsolateDescription(const std::string isolate_name,
|
||||
int64_t isolate_port) = 0;
|
||||
virtual void SetNeedsReportTimings(bool value) = 0;
|
||||
virtual std::shared_ptr<const fml::Mapping> GetPersistentIsolateData() = 0;
|
||||
virtual std::unique_ptr<std::vector<std::string>>
|
||||
ComputePlatformResolvedLocale(
|
||||
const std::vector<std::string>& supported_locale_data) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~WindowClient();
|
||||
};
|
||||
|
||||
class Window final {
|
||||
public:
|
||||
explicit Window(WindowClient* client);
|
||||
explicit Window(ViewportMetrics metrics);
|
||||
|
||||
~Window();
|
||||
|
||||
WindowClient* client() const { return client_; }
|
||||
const ViewportMetrics& viewport_metrics() const { return viewport_metrics_; }
|
||||
|
||||
const ViewportMetrics& viewport_metrics() { return viewport_metrics_; }
|
||||
|
||||
void DidCreateIsolate();
|
||||
void UpdateWindowMetrics(const ViewportMetrics& metrics);
|
||||
void UpdateLocales(const std::vector<std::string>& locales);
|
||||
void UpdateUserSettingsData(const std::string& data);
|
||||
void UpdateLifecycleState(const std::string& data);
|
||||
void UpdateSemanticsEnabled(bool enabled);
|
||||
void UpdateAccessibilityFeatures(int32_t flags);
|
||||
void DispatchPlatformMessage(fml::RefPtr<PlatformMessage> message);
|
||||
void DispatchPointerDataPacket(const PointerDataPacket& packet);
|
||||
void DispatchSemanticsAction(int32_t id,
|
||||
SemanticsAction action,
|
||||
std::vector<uint8_t> args);
|
||||
void BeginFrame(fml::TimePoint frameTime);
|
||||
void ReportTimings(std::vector<int64_t> timings);
|
||||
|
||||
void CompletePlatformMessageResponse(int response_id,
|
||||
std::vector<uint8_t> data);
|
||||
void CompletePlatformMessageEmptyResponse(int response_id);
|
||||
|
||||
static void RegisterNatives(tonic::DartLibraryNatives* natives);
|
||||
void UpdateWindowMetrics(const ViewportMetrics& metrics);
|
||||
|
||||
private:
|
||||
WindowClient* client_;
|
||||
tonic::DartPersistentValue library_;
|
||||
ViewportMetrics viewport_metrics_;
|
||||
|
||||
// We use id 0 to mean that no response is expected.
|
||||
int next_response_id_ = 1;
|
||||
std::unordered_map<int, fml::RefPtr<PlatformMessageResponse>>
|
||||
pending_responses_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -53,6 +53,8 @@ source_set_maybe_fuchsia_legacy("runtime") {
|
||||
"dart_vm_lifecycle.h",
|
||||
"embedder_resources.cc",
|
||||
"embedder_resources.h",
|
||||
"platform_data.cc",
|
||||
"platform_data.h",
|
||||
"ptrace_ios.cc",
|
||||
"ptrace_ios.h",
|
||||
"runtime_controller.cc",
|
||||
@ -63,8 +65,6 @@ source_set_maybe_fuchsia_legacy("runtime") {
|
||||
"service_protocol.h",
|
||||
"skia_concurrent_executor.cc",
|
||||
"skia_concurrent_executor.h",
|
||||
"window_data.cc",
|
||||
"window_data.h",
|
||||
]
|
||||
|
||||
public_deps = [ "//third_party/rapidjson" ]
|
||||
|
||||
@ -57,7 +57,7 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
|
||||
const Settings& settings,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
TaskRunners task_runners,
|
||||
std::unique_ptr<Window> window,
|
||||
std::unique_ptr<PlatformConfiguration> platform_configuration,
|
||||
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
fml::RefPtr<SkiaUnrefQueue> unref_queue,
|
||||
@ -112,7 +112,8 @@ std::weak_ptr<DartIsolate> DartIsolate::CreateRootIsolate(
|
||||
std::shared_ptr<DartIsolate>* root_isolate_data =
|
||||
static_cast<std::shared_ptr<DartIsolate>*>(Dart_IsolateData(vm_isolate));
|
||||
|
||||
(*root_isolate_data)->SetWindow(std::move(window));
|
||||
(*root_isolate_data)
|
||||
->SetPlatformConfiguration(std::move(platform_configuration));
|
||||
|
||||
return (*root_isolate_data)->GetWeakIsolatePtr();
|
||||
}
|
||||
@ -598,7 +599,7 @@ Dart_Isolate DartIsolate::DartCreateAndStartServiceIsolate(
|
||||
vm_data->GetSettings(), // settings
|
||||
vm_data->GetIsolateSnapshot(), // isolate snapshot
|
||||
null_task_runners, // task runners
|
||||
nullptr, // window
|
||||
nullptr, // platform_configuration
|
||||
{}, // snapshot delegate
|
||||
{}, // IO Manager
|
||||
{}, // Skia unref queue
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
#include "flutter/lib/ui/io_manager.h"
|
||||
#include "flutter/lib/ui/snapshot_delegate.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
#include "flutter/runtime/dart_snapshot.h"
|
||||
#include "third_party/dart/runtime/include/dart_api.h"
|
||||
#include "third_party/tonic/dart_state.h"
|
||||
@ -192,7 +192,7 @@ class DartIsolate : public UIDartState {
|
||||
const Settings& settings,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
TaskRunners task_runners,
|
||||
std::unique_ptr<Window> window,
|
||||
std::unique_ptr<PlatformConfiguration> platform_configuration,
|
||||
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
fml::RefPtr<SkiaUnrefQueue> skia_unref_queue,
|
||||
|
||||
@ -2,11 +2,11 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/runtime/window_data.h"
|
||||
#include "flutter/runtime/platform_data.h"
|
||||
|
||||
namespace flutter {
|
||||
WindowData::WindowData() = default;
|
||||
PlatformData::PlatformData() = default;
|
||||
|
||||
WindowData::~WindowData() = default;
|
||||
PlatformData::~PlatformData() = default;
|
||||
|
||||
} // namespace flutter
|
||||
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_RUNTIME_WINDOW_DATA_H_
|
||||
#define FLUTTER_RUNTIME_WINDOW_DATA_H_
|
||||
#ifndef FLUTTER_RUNTIME_PLATFORM_DATA_H_
|
||||
#define FLUTTER_RUNTIME_PLATFORM_DATA_H_
|
||||
|
||||
#include "flutter/lib/ui/window/viewport_metrics.h"
|
||||
|
||||
@ -23,12 +23,12 @@ namespace flutter {
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * flutter::Shell::Create, which takes a window_data to initialize the
|
||||
/// * flutter::Shell::Create, which takes a platform_data to initialize the
|
||||
/// ui.Window attached to it.
|
||||
struct WindowData {
|
||||
WindowData();
|
||||
struct PlatformData {
|
||||
PlatformData();
|
||||
|
||||
~WindowData();
|
||||
~PlatformData();
|
||||
|
||||
ViewportMetrics viewport_metrics;
|
||||
std::string language_code;
|
||||
@ -45,4 +45,4 @@ struct WindowData {
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_RUNTIME_WINDOW_DATA_H_
|
||||
#endif // FLUTTER_RUNTIME_PLATFORM_DATA_H_
|
||||
@ -8,8 +8,10 @@
|
||||
#include "flutter/fml/trace_event.h"
|
||||
#include "flutter/lib/ui/compositing/scene.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "flutter/runtime/runtime_delegate.h"
|
||||
#include "lib/ui/window/viewport_metrics.h"
|
||||
#include "third_party/tonic/dart_message_handler.h"
|
||||
|
||||
namespace flutter {
|
||||
@ -26,7 +28,7 @@ RuntimeController::RuntimeController(
|
||||
std::string p_advisory_script_uri,
|
||||
std::string p_advisory_script_entrypoint,
|
||||
const std::function<void(int64_t)>& idle_notification_callback,
|
||||
const WindowData& p_window_data,
|
||||
const PlatformData& p_platform_data,
|
||||
const fml::closure& p_isolate_create_callback,
|
||||
const fml::closure& p_isolate_shutdown_callback,
|
||||
std::shared_ptr<const fml::Mapping> p_persistent_isolate_data)
|
||||
@ -41,7 +43,7 @@ RuntimeController::RuntimeController(
|
||||
advisory_script_uri_(p_advisory_script_uri),
|
||||
advisory_script_entrypoint_(p_advisory_script_entrypoint),
|
||||
idle_notification_callback_(idle_notification_callback),
|
||||
window_data_(std::move(p_window_data)),
|
||||
platform_data_(std::move(p_platform_data)),
|
||||
isolate_create_callback_(p_isolate_create_callback),
|
||||
isolate_shutdown_callback_(p_isolate_shutdown_callback),
|
||||
persistent_isolate_data_(std::move(p_persistent_isolate_data)) {
|
||||
@ -49,20 +51,21 @@ RuntimeController::RuntimeController(
|
||||
// It will be run at a later point when the engine provides a run
|
||||
// configuration and then runs the isolate.
|
||||
auto strong_root_isolate =
|
||||
DartIsolate::CreateRootIsolate(vm_->GetVMData()->GetSettings(), //
|
||||
isolate_snapshot_, //
|
||||
task_runners_, //
|
||||
std::make_unique<Window>(this), //
|
||||
snapshot_delegate_, //
|
||||
io_manager_, //
|
||||
unref_queue_, //
|
||||
image_decoder_, //
|
||||
p_advisory_script_uri, //
|
||||
p_advisory_script_entrypoint, //
|
||||
nullptr, //
|
||||
isolate_create_callback_, //
|
||||
isolate_shutdown_callback_ //
|
||||
)
|
||||
DartIsolate::CreateRootIsolate(
|
||||
vm_->GetVMData()->GetSettings(), //
|
||||
isolate_snapshot_, //
|
||||
task_runners_, //
|
||||
std::make_unique<PlatformConfiguration>(this), //
|
||||
snapshot_delegate_, //
|
||||
io_manager_, //
|
||||
unref_queue_, //
|
||||
image_decoder_, //
|
||||
p_advisory_script_uri, //
|
||||
p_advisory_script_entrypoint, //
|
||||
nullptr, //
|
||||
isolate_create_callback_, //
|
||||
isolate_shutdown_callback_ //
|
||||
)
|
||||
.lock();
|
||||
|
||||
FML_CHECK(strong_root_isolate) << "Could not create root isolate.";
|
||||
@ -74,9 +77,9 @@ RuntimeController::RuntimeController(
|
||||
root_isolate_return_code_ = {true, code};
|
||||
});
|
||||
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
tonic::DartState::Scope scope(strong_root_isolate);
|
||||
window->DidCreateIsolate();
|
||||
platform_configuration->DidCreateIsolate();
|
||||
if (!FlushRuntimeStateToIsolate()) {
|
||||
FML_DLOG(ERROR) << "Could not setup initial isolate state.";
|
||||
}
|
||||
@ -121,7 +124,7 @@ std::unique_ptr<RuntimeController> RuntimeController::Clone() const {
|
||||
advisory_script_uri_, //
|
||||
advisory_script_entrypoint_, //
|
||||
idle_notification_callback_, //
|
||||
window_data_, //
|
||||
platform_data_, //
|
||||
isolate_create_callback_, //
|
||||
isolate_shutdown_callback_, //
|
||||
persistent_isolate_data_ //
|
||||
@ -129,30 +132,32 @@ std::unique_ptr<RuntimeController> RuntimeController::Clone() const {
|
||||
}
|
||||
|
||||
bool RuntimeController::FlushRuntimeStateToIsolate() {
|
||||
return SetViewportMetrics(window_data_.viewport_metrics) &&
|
||||
SetLocales(window_data_.locale_data) &&
|
||||
SetSemanticsEnabled(window_data_.semantics_enabled) &&
|
||||
SetAccessibilityFeatures(window_data_.accessibility_feature_flags_) &&
|
||||
SetUserSettingsData(window_data_.user_settings_data) &&
|
||||
SetLifecycleState(window_data_.lifecycle_state);
|
||||
return SetViewportMetrics(platform_data_.viewport_metrics) &&
|
||||
SetLocales(platform_data_.locale_data) &&
|
||||
SetSemanticsEnabled(platform_data_.semantics_enabled) &&
|
||||
SetAccessibilityFeatures(
|
||||
platform_data_.accessibility_feature_flags_) &&
|
||||
SetUserSettingsData(platform_data_.user_settings_data) &&
|
||||
SetLifecycleState(platform_data_.lifecycle_state);
|
||||
}
|
||||
|
||||
bool RuntimeController::SetViewportMetrics(const ViewportMetrics& metrics) {
|
||||
window_data_.viewport_metrics = metrics;
|
||||
platform_data_.viewport_metrics = metrics;
|
||||
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
window->UpdateWindowMetrics(metrics);
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
platform_configuration->window()->UpdateWindowMetrics(metrics);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RuntimeController::SetLocales(
|
||||
const std::vector<std::string>& locale_data) {
|
||||
window_data_.locale_data = locale_data;
|
||||
platform_data_.locale_data = locale_data;
|
||||
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
window->UpdateLocales(locale_data);
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
platform_configuration->UpdateLocales(locale_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -160,10 +165,11 @@ bool RuntimeController::SetLocales(
|
||||
}
|
||||
|
||||
bool RuntimeController::SetUserSettingsData(const std::string& data) {
|
||||
window_data_.user_settings_data = data;
|
||||
platform_data_.user_settings_data = data;
|
||||
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
window->UpdateUserSettingsData(window_data_.user_settings_data);
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
platform_configuration->UpdateUserSettingsData(
|
||||
platform_data_.user_settings_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -171,10 +177,11 @@ bool RuntimeController::SetUserSettingsData(const std::string& data) {
|
||||
}
|
||||
|
||||
bool RuntimeController::SetLifecycleState(const std::string& data) {
|
||||
window_data_.lifecycle_state = data;
|
||||
platform_data_.lifecycle_state = data;
|
||||
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
window->UpdateLifecycleState(window_data_.lifecycle_state);
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
platform_configuration->UpdateLifecycleState(
|
||||
platform_data_.lifecycle_state);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -182,10 +189,11 @@ bool RuntimeController::SetLifecycleState(const std::string& data) {
|
||||
}
|
||||
|
||||
bool RuntimeController::SetSemanticsEnabled(bool enabled) {
|
||||
window_data_.semantics_enabled = enabled;
|
||||
platform_data_.semantics_enabled = enabled;
|
||||
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
window->UpdateSemanticsEnabled(window_data_.semantics_enabled);
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
platform_configuration->UpdateSemanticsEnabled(
|
||||
platform_data_.semantics_enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -193,10 +201,10 @@ bool RuntimeController::SetSemanticsEnabled(bool enabled) {
|
||||
}
|
||||
|
||||
bool RuntimeController::SetAccessibilityFeatures(int32_t flags) {
|
||||
window_data_.accessibility_feature_flags_ = flags;
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
window->UpdateAccessibilityFeatures(
|
||||
window_data_.accessibility_feature_flags_);
|
||||
platform_data_.accessibility_feature_flags_ = flags;
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
platform_configuration->UpdateAccessibilityFeatures(
|
||||
platform_data_.accessibility_feature_flags_);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -204,18 +212,20 @@ bool RuntimeController::SetAccessibilityFeatures(int32_t flags) {
|
||||
}
|
||||
|
||||
bool RuntimeController::BeginFrame(fml::TimePoint frame_time) {
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
window->BeginFrame(frame_time);
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
platform_configuration->BeginFrame(frame_time);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RuntimeController::ReportTimings(std::vector<int64_t> timings) {
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
window->ReportTimings(std::move(timings));
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
platform_configuration->ReportTimings(std::move(timings));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -239,23 +249,25 @@ bool RuntimeController::NotifyIdle(int64_t deadline) {
|
||||
|
||||
bool RuntimeController::DispatchPlatformMessage(
|
||||
fml::RefPtr<PlatformMessage> message) {
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
TRACE_EVENT1("flutter", "RuntimeController::DispatchPlatformMessage",
|
||||
"mode", "basic");
|
||||
window->DispatchPlatformMessage(std::move(message));
|
||||
platform_configuration->DispatchPlatformMessage(std::move(message));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RuntimeController::DispatchPointerDataPacket(
|
||||
const PointerDataPacket& packet) {
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
TRACE_EVENT1("flutter", "RuntimeController::DispatchPointerDataPacket",
|
||||
"mode", "basic");
|
||||
window->DispatchPointerDataPacket(packet);
|
||||
platform_configuration->window()->DispatchPointerDataPacket(packet);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -264,69 +276,72 @@ bool RuntimeController::DispatchSemanticsAction(int32_t id,
|
||||
std::vector<uint8_t> args) {
|
||||
TRACE_EVENT1("flutter", "RuntimeController::DispatchSemanticsAction", "mode",
|
||||
"basic");
|
||||
if (auto* window = GetWindowIfAvailable()) {
|
||||
window->DispatchSemanticsAction(id, action, std::move(args));
|
||||
if (auto* platform_configuration = GetPlatformConfigurationIfAvailable()) {
|
||||
platform_configuration->DispatchSemanticsAction(id, action,
|
||||
std::move(args));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Window* RuntimeController::GetWindowIfAvailable() {
|
||||
PlatformConfiguration*
|
||||
RuntimeController::GetPlatformConfigurationIfAvailable() {
|
||||
std::shared_ptr<DartIsolate> root_isolate = root_isolate_.lock();
|
||||
return root_isolate ? root_isolate->window() : nullptr;
|
||||
return root_isolate ? root_isolate->platform_configuration() : nullptr;
|
||||
}
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
std::string RuntimeController::DefaultRouteName() {
|
||||
return client_.DefaultRouteName();
|
||||
}
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void RuntimeController::ScheduleFrame() {
|
||||
client_.ScheduleFrame();
|
||||
}
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void RuntimeController::Render(Scene* scene) {
|
||||
client_.Render(scene->takeLayerTree());
|
||||
}
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void RuntimeController::UpdateSemantics(SemanticsUpdate* update) {
|
||||
if (window_data_.semantics_enabled) {
|
||||
if (platform_data_.semantics_enabled) {
|
||||
client_.UpdateSemantics(update->takeNodes(), update->takeActions());
|
||||
}
|
||||
}
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void RuntimeController::HandlePlatformMessage(
|
||||
fml::RefPtr<PlatformMessage> message) {
|
||||
client_.HandlePlatformMessage(std::move(message));
|
||||
}
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
FontCollection& RuntimeController::GetFontCollection() {
|
||||
return client_.GetFontCollection();
|
||||
}
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void RuntimeController::UpdateIsolateDescription(const std::string isolate_name,
|
||||
int64_t isolate_port) {
|
||||
client_.UpdateIsolateDescription(isolate_name, isolate_port);
|
||||
}
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void RuntimeController::SetNeedsReportTimings(bool value) {
|
||||
client_.SetNeedsReportTimings(value);
|
||||
}
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
std::shared_ptr<const fml::Mapping>
|
||||
RuntimeController::GetPersistentIsolateData() {
|
||||
return persistent_isolate_data_;
|
||||
}
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
std::unique_ptr<std::vector<std::string>>
|
||||
RuntimeController::ComputePlatformResolvedLocale(
|
||||
const std::vector<std::string>& supported_locale_data) {
|
||||
|
||||
@ -14,10 +14,10 @@
|
||||
#include "flutter/lib/ui/io_manager.h"
|
||||
#include "flutter/lib/ui/text/font_collection.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
#include "flutter/lib/ui/window/platform_configuration.h"
|
||||
#include "flutter/lib/ui/window/pointer_data_packet.h"
|
||||
#include "flutter/lib/ui/window/window.h"
|
||||
#include "flutter/runtime/dart_vm.h"
|
||||
#include "flutter/runtime/window_data.h"
|
||||
#include "flutter/runtime/platform_data.h"
|
||||
#include "rapidjson/document.h"
|
||||
#include "rapidjson/stringbuffer.h"
|
||||
|
||||
@ -38,7 +38,7 @@ class Window;
|
||||
/// used by the engine to copy the currently accumulated window state so it can
|
||||
/// be referenced by the new runtime controller.
|
||||
///
|
||||
class RuntimeController final : public WindowClient {
|
||||
class RuntimeController final : public PlatformConfigurationClient {
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Creates a new instance of a runtime controller. This is
|
||||
@ -90,7 +90,7 @@ class RuntimeController final : public WindowClient {
|
||||
/// code in isolate scope when the VM
|
||||
/// is about to be notified that the
|
||||
/// engine is going to be idle.
|
||||
/// @param[in] window_data The window data (if exists).
|
||||
/// @param[in] platform_data The window data (if exists).
|
||||
/// @param[in] isolate_create_callback The isolate create callback. This
|
||||
/// allows callers to run native code
|
||||
/// in isolate scope on the UI task
|
||||
@ -117,12 +117,12 @@ class RuntimeController final : public WindowClient {
|
||||
std::string advisory_script_uri,
|
||||
std::string advisory_script_entrypoint,
|
||||
const std::function<void(int64_t)>& idle_notification_callback,
|
||||
const WindowData& window_data,
|
||||
const PlatformData& platform_data,
|
||||
const fml::closure& isolate_create_callback,
|
||||
const fml::closure& isolate_shutdown_callback,
|
||||
std::shared_ptr<const fml::Mapping> persistent_isolate_data);
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
~RuntimeController() override;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -136,11 +136,11 @@ class RuntimeController final : public WindowClient {
|
||||
std::unique_ptr<RuntimeController> Clone() const;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Forward the specified window metrics to the running isolate.
|
||||
/// @brief Forward the specified viewport metrics to the running isolate.
|
||||
/// If the isolate is not running, these metrics will be saved and
|
||||
/// flushed to the isolate when it starts.
|
||||
///
|
||||
/// @param[in] metrics The metrics.
|
||||
/// @param[in] metrics The viewport metrics.
|
||||
///
|
||||
/// @return If the window metrics were forwarded to the running isolate.
|
||||
///
|
||||
@ -466,46 +466,46 @@ class RuntimeController final : public WindowClient {
|
||||
std::string advisory_script_uri_;
|
||||
std::string advisory_script_entrypoint_;
|
||||
std::function<void(int64_t)> idle_notification_callback_;
|
||||
WindowData window_data_;
|
||||
PlatformData platform_data_;
|
||||
std::weak_ptr<DartIsolate> root_isolate_;
|
||||
std::pair<bool, uint32_t> root_isolate_return_code_ = {false, 0};
|
||||
const fml::closure isolate_create_callback_;
|
||||
const fml::closure isolate_shutdown_callback_;
|
||||
std::shared_ptr<const fml::Mapping> persistent_isolate_data_;
|
||||
|
||||
Window* GetWindowIfAvailable();
|
||||
PlatformConfiguration* GetPlatformConfigurationIfAvailable();
|
||||
|
||||
bool FlushRuntimeStateToIsolate();
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
std::string DefaultRouteName() override;
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void ScheduleFrame() override;
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void Render(Scene* scene) override;
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void UpdateSemantics(SemanticsUpdate* update) override;
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void HandlePlatformMessage(fml::RefPtr<PlatformMessage> message) override;
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
FontCollection& GetFontCollection() override;
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void UpdateIsolateDescription(const std::string isolate_name,
|
||||
int64_t isolate_port) override;
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
void SetNeedsReportTimings(bool value) override;
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
std::shared_ptr<const fml::Mapping> GetPersistentIsolateData() override;
|
||||
|
||||
// |WindowClient|
|
||||
// |PlatformConfigurationClient|
|
||||
std::unique_ptr<std::vector<std::string>> ComputePlatformResolvedLocale(
|
||||
const std::vector<std::string>& supported_locale_data) override;
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ Engine::Engine(Delegate& delegate,
|
||||
DartVM& vm,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
TaskRunners task_runners,
|
||||
const WindowData window_data,
|
||||
const PlatformData platform_data,
|
||||
Settings settings,
|
||||
std::unique_ptr<Animator> animator,
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
@ -71,7 +71,7 @@ Engine::Engine(Delegate& delegate,
|
||||
settings_.advisory_script_uri, // advisory script uri
|
||||
settings_.advisory_script_entrypoint, // advisory script entrypoint
|
||||
settings_.idle_notification_callback, // idle notification callback
|
||||
window_data, // window data
|
||||
platform_data, // platform data
|
||||
settings_.isolate_create_callback, // isolate create callback
|
||||
settings_.isolate_shutdown_callback, // isolate shutdown callback
|
||||
settings_.persistent_isolate_data // persistent isolate data
|
||||
@ -276,7 +276,8 @@ void Engine::SetViewportMetrics(const ViewportMetrics& metrics) {
|
||||
bool dimensions_changed =
|
||||
viewport_metrics_.physical_height != metrics.physical_height ||
|
||||
viewport_metrics_.physical_width != metrics.physical_width ||
|
||||
viewport_metrics_.physical_depth != metrics.physical_depth;
|
||||
viewport_metrics_.physical_depth != metrics.physical_depth ||
|
||||
viewport_metrics_.device_pixel_ratio != metrics.device_pixel_ratio;
|
||||
viewport_metrics_ = metrics;
|
||||
runtime_controller_->SetViewportMetrics(viewport_metrics_);
|
||||
if (animator_) {
|
||||
|
||||
@ -295,7 +295,7 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
|
||||
DartVM& vm,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
TaskRunners task_runners,
|
||||
const WindowData window_data,
|
||||
const PlatformData platform_data,
|
||||
Settings settings,
|
||||
std::unique_ptr<Animator> animator,
|
||||
fml::WeakPtr<IOManager> io_manager,
|
||||
@ -421,7 +421,7 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
|
||||
/// one frame interval from this point, the Flutter application
|
||||
/// will jank.
|
||||
///
|
||||
/// If an root isolate is running, this method calls the
|
||||
/// If a root isolate is running, this method calls the
|
||||
/// `::_beginFrame` method in `hooks.dart`. If a root isolate is
|
||||
/// not running, this call does nothing.
|
||||
///
|
||||
@ -701,9 +701,10 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Notifies the engine that the embedder has expressed an opinion
|
||||
/// about where the accessibility tree should be generated or not.
|
||||
/// This call originates in the platform view and is forwarded to
|
||||
/// the engine here on the UI task runner by the shell.
|
||||
/// about whether the accessibility tree should be generated or
|
||||
/// not. This call originates in the platform view and is
|
||||
/// forwarded to the engine here on the UI task runner by the
|
||||
/// shell.
|
||||
///
|
||||
/// @param[in] enabled Whether the accessibility tree is enabled or
|
||||
/// disabled.
|
||||
|
||||
@ -23,7 +23,7 @@ class PointerDataDispatcher;
|
||||
/// delivered packets, and dispatches them in sync with the VSYNC signal.
|
||||
///
|
||||
/// This object will be owned by the engine because it relies on the engine's
|
||||
/// `Animator` (which owns `VsyncWaiter`) and `RuntomeController` to do the
|
||||
/// `Animator` (which owns `VsyncWaiter`) and `RuntimeController` to do the
|
||||
/// filtering. This object is currently designed to be only called from the UI
|
||||
/// thread (no thread safety is guaranteed).
|
||||
///
|
||||
|
||||
@ -43,7 +43,7 @@ constexpr char kFontChange[] = "fontsChange";
|
||||
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
|
||||
DartVMRef vm,
|
||||
TaskRunners task_runners,
|
||||
const WindowData window_data,
|
||||
const PlatformData platform_data,
|
||||
Settings settings,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
|
||||
@ -134,7 +134,7 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
|
||||
fml::MakeCopyable([&engine_promise, //
|
||||
shell = shell.get(), //
|
||||
&dispatcher_maker, //
|
||||
&window_data, //
|
||||
&platform_data, //
|
||||
isolate_snapshot = std::move(isolate_snapshot), //
|
||||
vsync_waiter = std::move(vsync_waiter), //
|
||||
&weak_io_manager_future, //
|
||||
@ -155,7 +155,7 @@ std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
|
||||
*shell->GetDartVM(), //
|
||||
std::move(isolate_snapshot), //
|
||||
task_runners, //
|
||||
window_data, //
|
||||
platform_data, //
|
||||
shell->GetSettings(), //
|
||||
std::move(animator), //
|
||||
weak_io_manager_future.get(), //
|
||||
@ -242,17 +242,17 @@ std::unique_ptr<Shell> Shell::Create(
|
||||
Settings settings,
|
||||
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
|
||||
const Shell::CreateCallback<Rasterizer>& on_create_rasterizer) {
|
||||
return Shell::Create(std::move(task_runners), //
|
||||
WindowData{/* default window data */}, //
|
||||
std::move(settings), //
|
||||
std::move(on_create_platform_view), //
|
||||
std::move(on_create_rasterizer) //
|
||||
return Shell::Create(std::move(task_runners), //
|
||||
PlatformData{/* default platform data */}, //
|
||||
std::move(settings), //
|
||||
std::move(on_create_platform_view), //
|
||||
std::move(on_create_rasterizer) //
|
||||
);
|
||||
}
|
||||
|
||||
std::unique_ptr<Shell> Shell::Create(
|
||||
TaskRunners task_runners,
|
||||
const WindowData window_data,
|
||||
const PlatformData platform_data,
|
||||
Settings settings,
|
||||
Shell::CreateCallback<PlatformView> on_create_platform_view,
|
||||
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
|
||||
@ -267,7 +267,7 @@ std::unique_ptr<Shell> Shell::Create(
|
||||
auto vm_data = vm->GetVMData();
|
||||
|
||||
return Shell::Create(std::move(task_runners), //
|
||||
std::move(window_data), //
|
||||
std::move(platform_data), //
|
||||
std::move(settings), //
|
||||
vm_data->GetIsolateSnapshot(), // isolate snapshot
|
||||
on_create_platform_view, //
|
||||
@ -278,7 +278,7 @@ std::unique_ptr<Shell> Shell::Create(
|
||||
|
||||
std::unique_ptr<Shell> Shell::Create(
|
||||
TaskRunners task_runners,
|
||||
const WindowData window_data,
|
||||
const PlatformData platform_data,
|
||||
Settings settings,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
|
||||
@ -302,7 +302,7 @@ std::unique_ptr<Shell> Shell::Create(
|
||||
vm = std::move(vm), //
|
||||
&shell, //
|
||||
task_runners = std::move(task_runners), //
|
||||
window_data, //
|
||||
platform_data, //
|
||||
settings, //
|
||||
isolate_snapshot = std::move(isolate_snapshot), //
|
||||
on_create_platform_view, //
|
||||
@ -310,7 +310,7 @@ std::unique_ptr<Shell> Shell::Create(
|
||||
]() mutable {
|
||||
shell = CreateShellOnPlatformThread(std::move(vm),
|
||||
std::move(task_runners), //
|
||||
window_data, //
|
||||
platform_data, //
|
||||
settings, //
|
||||
std::move(isolate_snapshot), //
|
||||
on_create_platform_view, //
|
||||
|
||||
@ -138,7 +138,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
/// the Dart VM.
|
||||
///
|
||||
/// @param[in] task_runners The task runners
|
||||
/// @param[in] window_data The default data for setting up
|
||||
/// @param[in] platform_data The default data for setting up
|
||||
/// ui.Window that attached to this
|
||||
/// intance.
|
||||
/// @param[in] settings The settings
|
||||
@ -161,7 +161,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
///
|
||||
static std::unique_ptr<Shell> Create(
|
||||
TaskRunners task_runners,
|
||||
const WindowData window_data,
|
||||
const PlatformData platform_data,
|
||||
Settings settings,
|
||||
CreateCallback<PlatformView> on_create_platform_view,
|
||||
CreateCallback<Rasterizer> on_create_rasterizer);
|
||||
@ -176,7 +176,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
/// requires the specification of a running VM instance.
|
||||
///
|
||||
/// @param[in] task_runners The task runners
|
||||
/// @param[in] window_data The default data for setting up
|
||||
/// @param[in] platform_data The default data for setting up
|
||||
/// ui.Window that attached to this
|
||||
/// intance.
|
||||
/// @param[in] settings The settings
|
||||
@ -203,7 +203,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
///
|
||||
static std::unique_ptr<Shell> Create(
|
||||
TaskRunners task_runners,
|
||||
const WindowData window_data,
|
||||
const PlatformData platform_data,
|
||||
Settings settings,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
const CreateCallback<PlatformView>& on_create_platform_view,
|
||||
@ -426,7 +426,7 @@ class Shell final : public PlatformView::Delegate,
|
||||
static std::unique_ptr<Shell> CreateShellOnPlatformThread(
|
||||
DartVMRef vm,
|
||||
TaskRunners task_runners,
|
||||
const WindowData window_data,
|
||||
const PlatformData platform_data,
|
||||
Settings settings,
|
||||
fml::RefPtr<const DartSnapshot> isolate_snapshot,
|
||||
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
|
||||
|
||||
@ -100,10 +100,7 @@ void ShellTest::PumpOneFrame(Shell* shell,
|
||||
double width,
|
||||
double height,
|
||||
LayerTreeBuilder builder) {
|
||||
PumpOneFrame(shell,
|
||||
flutter::ViewportMetrics{1, width, height, flutter::kUnsetDepth,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
std::move(builder));
|
||||
PumpOneFrame(shell, {1.0, width, height}, std::move(builder));
|
||||
}
|
||||
|
||||
void ShellTest::PumpOneFrame(Shell* shell,
|
||||
|
||||
@ -684,7 +684,7 @@ TEST_F(ShellTest, WaitForFirstFrameZeroSizeFrame) {
|
||||
configuration.SetEntrypoint("emptyMain");
|
||||
|
||||
RunEngine(shell.get(), std::move(configuration));
|
||||
PumpOneFrame(shell.get(), {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
PumpOneFrame(shell.get(), {1.0, 0.0, 0.0});
|
||||
fml::Status result =
|
||||
shell->WaitForFirstFrame(fml::TimeDelta::FromMilliseconds(1000));
|
||||
ASSERT_FALSE(result.ok());
|
||||
@ -802,8 +802,7 @@ TEST_F(ShellTest, SetResourceCacheSize) {
|
||||
|
||||
fml::TaskRunner::RunNowOrPostTask(
|
||||
shell->GetTaskRunners().GetPlatformTaskRunner(), [&shell]() {
|
||||
shell->GetPlatformView()->SetViewportMetrics(
|
||||
{1.0, 400, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
shell->GetPlatformView()->SetViewportMetrics({1.0, 400, 200});
|
||||
});
|
||||
PumpOneFrame(shell.get());
|
||||
|
||||
@ -822,8 +821,7 @@ TEST_F(ShellTest, SetResourceCacheSize) {
|
||||
|
||||
fml::TaskRunner::RunNowOrPostTask(
|
||||
shell->GetTaskRunners().GetPlatformTaskRunner(), [&shell]() {
|
||||
shell->GetPlatformView()->SetViewportMetrics(
|
||||
{1.0, 800, 400, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
shell->GetPlatformView()->SetViewportMetrics({1.0, 800, 400});
|
||||
});
|
||||
PumpOneFrame(shell.get());
|
||||
|
||||
@ -841,8 +839,7 @@ TEST_F(ShellTest, SetResourceCacheSizeEarly) {
|
||||
|
||||
fml::TaskRunner::RunNowOrPostTask(
|
||||
shell->GetTaskRunners().GetPlatformTaskRunner(), [&shell]() {
|
||||
shell->GetPlatformView()->SetViewportMetrics(
|
||||
{1.0, 400, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
shell->GetPlatformView()->SetViewportMetrics({1.0, 400, 200});
|
||||
});
|
||||
PumpOneFrame(shell.get());
|
||||
|
||||
@ -870,8 +867,7 @@ TEST_F(ShellTest, SetResourceCacheSizeNotifiesDart) {
|
||||
|
||||
fml::TaskRunner::RunNowOrPostTask(
|
||||
shell->GetTaskRunners().GetPlatformTaskRunner(), [&shell]() {
|
||||
shell->GetPlatformView()->SetViewportMetrics(
|
||||
{1.0, 400, 200, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
|
||||
shell->GetPlatformView()->SetViewportMetrics({1.0, 400, 200});
|
||||
});
|
||||
PumpOneFrame(shell.get());
|
||||
|
||||
@ -1235,7 +1231,7 @@ TEST_F(ShellTest, CanDecompressImageFromAsset) {
|
||||
}
|
||||
|
||||
TEST_F(ShellTest, OnServiceProtocolGetSkSLsWorks) {
|
||||
// Create 2 dummpy SkSL cache file IE (base32 encoding of A), II (base32
|
||||
// Create 2 dummy SkSL cache file IE (base32 encoding of A), II (base32
|
||||
// encoding of B) with content x and y.
|
||||
fml::ScopedTemporaryDirectory temp_dir;
|
||||
PersistentCache::SetCacheDirectoryPath(temp_dir.path());
|
||||
|
||||
@ -22,10 +22,10 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
static WindowData GetDefaultWindowData() {
|
||||
WindowData window_data;
|
||||
window_data.lifecycle_state = "AppLifecycleState.detached";
|
||||
return window_data;
|
||||
static PlatformData GetDefaultPlatformData() {
|
||||
PlatformData platform_data;
|
||||
platform_data.lifecycle_state = "AppLifecycleState.detached";
|
||||
return platform_data;
|
||||
}
|
||||
|
||||
bool AndroidShellHolder::use_embedded_view;
|
||||
@ -121,9 +121,9 @@ AndroidShellHolder::AndroidShellHolder(
|
||||
);
|
||||
|
||||
shell_ =
|
||||
Shell::Create(task_runners, // task runners
|
||||
GetDefaultWindowData(), // window data
|
||||
settings_, // settings
|
||||
Shell::Create(task_runners, // task runners
|
||||
GetDefaultPlatformData(), // window data
|
||||
settings_, // settings
|
||||
on_create_platform_view, // platform view create callback
|
||||
on_create_rasterizer // rasterizer create callback
|
||||
);
|
||||
@ -137,9 +137,9 @@ AndroidShellHolder::AndroidShellHolder(
|
||||
);
|
||||
|
||||
shell_ =
|
||||
Shell::Create(task_runners, // task runners
|
||||
GetDefaultWindowData(), // window data
|
||||
settings_, // settings
|
||||
Shell::Create(task_runners, // task runners
|
||||
GetDefaultPlatformData(), // window data
|
||||
settings_, // settings
|
||||
on_create_platform_view, // platform view create callback
|
||||
on_create_rasterizer // rasterizer create callback
|
||||
);
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/fml/unique_fd.h"
|
||||
#include "flutter/lib/ui/window/viewport_metrics.h"
|
||||
#include "flutter/runtime/window_data.h"
|
||||
#include "flutter/runtime/platform_data.h"
|
||||
#include "flutter/shell/common/run_configuration.h"
|
||||
#include "flutter/shell/common/shell.h"
|
||||
#include "flutter/shell/common/thread_host.h"
|
||||
|
||||
@ -1063,7 +1063,7 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link FlutterEngineAttachmentListener}, which is notifed whenever this {@code
|
||||
* Adds a {@link FlutterEngineAttachmentListener}, which is notified whenever this {@code
|
||||
* FlutterView} attached to/detaches from a {@link FlutterEngine}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
|
||||
@ -168,12 +168,12 @@ static flutter::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) {
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - WindowData accessors
|
||||
#pragma mark - PlatformData accessors
|
||||
|
||||
- (const flutter::WindowData)defaultWindowData {
|
||||
flutter::WindowData windowData;
|
||||
windowData.lifecycle_state = std::string("AppLifecycleState.detached");
|
||||
return windowData;
|
||||
- (const flutter::PlatformData)defaultPlatformData {
|
||||
flutter::PlatformData PlatformData;
|
||||
PlatformData.lifecycle_state = std::string("AppLifecycleState.detached");
|
||||
return PlatformData;
|
||||
}
|
||||
|
||||
#pragma mark - Settings accessors
|
||||
@ -261,6 +261,6 @@ static flutter::Settings DefaultSettingsForProcess(NSBundle* bundle = nil) {
|
||||
);
|
||||
}
|
||||
|
||||
#pragma mark - windowData utilities
|
||||
#pragma mark - PlatformData utilities
|
||||
|
||||
@end
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
#define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_FLUTTERDARTPROJECT_INTERNAL_H_
|
||||
|
||||
#include "flutter/common/settings.h"
|
||||
#include "flutter/runtime/window_data.h"
|
||||
#include "flutter/runtime/platform_data.h"
|
||||
#include "flutter/shell/common/engine.h"
|
||||
#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterDartProject.h"
|
||||
|
||||
@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@interface FlutterDartProject ()
|
||||
|
||||
- (const flutter::Settings&)settings;
|
||||
- (const flutter::WindowData)defaultWindowData;
|
||||
- (const flutter::PlatformData)defaultPlatformData;
|
||||
|
||||
- (flutter::RunConfiguration)runConfiguration;
|
||||
- (flutter::RunConfiguration)runConfigurationForEntrypoint:(nullable NSString*)entrypointOrNil;
|
||||
|
||||
@ -17,6 +17,9 @@
|
||||
#include "flutter/shell/common/switches.h"
|
||||
#include "flutter/shell/common/thread_host.h"
|
||||
#include "flutter/shell/platform/darwin/common/command_line.h"
|
||||
#include "flutter/shell/platform/darwin/ios/rendering_api_selection.h"
|
||||
#include "flutter/shell/profiling/sampling_profiler.h"
|
||||
|
||||
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h"
|
||||
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject_Internal.h"
|
||||
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.h"
|
||||
@ -28,8 +31,6 @@
|
||||
#import "flutter/shell/platform/darwin/ios/framework/Source/profiler_metrics_ios.h"
|
||||
#import "flutter/shell/platform/darwin/ios/ios_surface.h"
|
||||
#import "flutter/shell/platform/darwin/ios/platform_view_ios.h"
|
||||
#include "flutter/shell/platform/darwin/ios/rendering_api_selection.h"
|
||||
#include "flutter/shell/profiling/sampling_profiler.h"
|
||||
|
||||
NSString* const FlutterDefaultDartEntrypoint = nil;
|
||||
static constexpr int kNumProfilerSamplesPerSec = 5;
|
||||
@ -445,7 +446,7 @@ static constexpr int kNumProfilerSamplesPerSec = 5;
|
||||
static size_t shellCount = 1;
|
||||
|
||||
auto settings = [_dartProject.get() settings];
|
||||
auto windowData = [_dartProject.get() defaultWindowData];
|
||||
auto platformData = [_dartProject.get() defaultPlatformData];
|
||||
|
||||
if (libraryURI) {
|
||||
FML_DCHECK(entrypoint) << "Must specify entrypoint if specifying library";
|
||||
@ -510,10 +511,10 @@ static constexpr int kNumProfilerSamplesPerSec = 5;
|
||||
);
|
||||
// Create the shell. This is a blocking operation.
|
||||
_shell = flutter::Shell::Create(std::move(task_runners), // task runners
|
||||
std::move(windowData), // window data
|
||||
std::move(platformData), // platform data
|
||||
std::move(settings), // settings
|
||||
on_create_platform_view, // platform view creation
|
||||
on_create_rasterizer // rasterzier creation
|
||||
on_create_rasterizer // rasterizer creation
|
||||
);
|
||||
} else {
|
||||
flutter::TaskRunners task_runners(threadLabel.UTF8String, // label
|
||||
@ -524,10 +525,10 @@ static constexpr int kNumProfilerSamplesPerSec = 5;
|
||||
);
|
||||
// Create the shell. This is a blocking operation.
|
||||
_shell = flutter::Shell::Create(std::move(task_runners), // task runners
|
||||
std::move(windowData), // window data
|
||||
std::move(platformData), // platform data
|
||||
std::move(settings), // settings
|
||||
on_create_platform_view, // platform view creation
|
||||
on_create_rasterizer // rasterzier creation
|
||||
on_create_rasterizer // rasterizer creation
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -9,6 +9,39 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// This file defines an Application Binary Interface (ABI), which requires more
|
||||
// stability than regular code to remain functional for exchanging messages
|
||||
// between different versions of the embedding and the engine, to allow for both
|
||||
// forward and backward compatibility.
|
||||
//
|
||||
// Specifically,
|
||||
// - The order, type, and size of the struct members below must remain the same,
|
||||
// and members should not be removed.
|
||||
// - New structures that are part of the ABI must be defined with "size_t
|
||||
// struct_size;" as their first member, which should be initialized using
|
||||
// "sizeof(Type)".
|
||||
// - Enum values must not change or be removed.
|
||||
// - Enum members without explicit values must not be reordered.
|
||||
// - Function signatures (names, argument counts, argument order, and argument
|
||||
// type) cannot change.
|
||||
// - The core behavior of existing functions cannot change.
|
||||
//
|
||||
// These changes are allowed:
|
||||
// - Adding new struct members at the end of a structure.
|
||||
// - Adding new enum members with a new value.
|
||||
// - Renaming a struct member as long as its type, size, and intent remain the
|
||||
// same.
|
||||
// - Renaming an enum member as long as its value and intent remains the same.
|
||||
//
|
||||
// It is expected that struct members and implicitly-valued enums will not
|
||||
// always be declared in an order that is optimal for the reader, since members
|
||||
// will be added over time, and they can't be reordered.
|
||||
//
|
||||
// Existing functions should continue to appear from the caller's point of view
|
||||
// to operate as they did when they were first introduced, so introduce a new
|
||||
// function instead of modifying the core behavior of a function (and continue
|
||||
// to support the existing function with the previous behavior).
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
#include "flutter/shell/common/shell.h"
|
||||
#include "flutter/shell/common/thread_host.h"
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
#include "flutter/shell/platform/embedder/embedder_engine.h"
|
||||
#include "flutter/shell/platform/embedder/embedder_external_texture_gl.h"
|
||||
#include "flutter/shell/platform/embedder/embedder_thread_host.h"
|
||||
|
||||
|
||||
@ -257,7 +257,7 @@ Engine::Engine(Delegate& delegate,
|
||||
TRACE_EVENT0("flutter", "CreateShell");
|
||||
shell_ = flutter::Shell::Create(
|
||||
task_runners, // host task runners
|
||||
flutter::WindowData(), // default window data
|
||||
flutter::PlatformData(), // default window data
|
||||
settings_, // shell launch settings
|
||||
std::move(isolate_snapshot), // isolate snapshot
|
||||
on_create_platform_view, // platform view create callback
|
||||
|
||||
@ -235,10 +235,10 @@ int RunTester(const flutter::Settings& settings,
|
||||
}
|
||||
});
|
||||
|
||||
flutter::ViewportMetrics metrics;
|
||||
flutter::ViewportMetrics metrics{};
|
||||
metrics.device_pixel_ratio = 3.0;
|
||||
metrics.physical_width = 2400; // 800 at 3x resolution
|
||||
metrics.physical_height = 1800; // 600 at 3x resolution
|
||||
metrics.physical_width = 2400.0; // 800 at 3x resolution.
|
||||
metrics.physical_height = 1800.0; // 600 at 3x resolution.
|
||||
shell->GetPlatformView()->SetViewportMetrics(metrics);
|
||||
|
||||
// Run the message loop and wait for the script to do its thing.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user