Skip to content

Commit 87749da

Browse files
committed
Add FlutterDesktopWindowProperties to the public API (flutter-tizen#133)
* Refactor using FlutterProjectBundle * Unsupport relative paths * Reland the support for relative paths * Add FlutterDesktopWindowProperties to the public API * Document undocumented public APIs * Rebase and resolve conflicts * Enable FlutterTizenEngineTest.Run_Twice * Add documentation
1 parent ff9c421 commit 87749da

17 files changed

+418
-235
lines changed

shell/platform/tizen/BUILD.gn

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ _flutter_tizen_source = [
3232
"channels/navigation_channel.cc",
3333
"channels/platform_view_channel.cc",
3434
"channels/text_input_channel.cc",
35+
"flutter_project_bundle.cc",
3536
"flutter_tizen.cc",
3637
"flutter_tizen_engine.cc",
3738
"flutter_tizen_texture_registrar.cc",
@@ -139,6 +140,7 @@ template("embedder_for_profile") {
139140
libs += [
140141
"base-utils-i18n",
141142
"capi-appfw-application",
143+
"capi-appfw-app-common",
142144
"capi-base-common",
143145
"capi-system-info",
144146
"capi-system-system-settings",

shell/platform/tizen/external_texture.h

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <atomic>
99
#include <memory>
10+
1011
#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
1112
#include "flutter/shell/platform/embedder/embedder.h"
1213

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2021 Samsung Electronics Co., Ltd. All rights reserved.
2+
// Copyright 2013 The Flutter Authors. All rights reserved.
3+
// Use of this source code is governed by a BSD-style license that can be
4+
// found in the LICENSE file.
5+
6+
#include "flutter_project_bundle.h"
7+
8+
#ifdef __X64_SHELL__
9+
#include "flutter/shell/platform/common/path_utils.h"
10+
#else
11+
#include <app_common.h>
12+
#endif
13+
14+
#include <filesystem>
15+
16+
#include "flutter/shell/platform/tizen/tizen_log.h"
17+
18+
namespace flutter {
19+
20+
#ifndef __X64_SHELL__
21+
namespace {
22+
23+
// Returns the path of the directory containing the app binary, or an empty
24+
// string if the directory cannot be found.
25+
std::filesystem::path GetExecutableDirectory() {
26+
auto res_path = app_get_resource_path();
27+
if (res_path == nullptr) {
28+
return std::filesystem::path();
29+
}
30+
auto bin_path = std::filesystem::path(res_path) / ".." / "bin";
31+
free(res_path);
32+
return bin_path.lexically_normal();
33+
}
34+
35+
} // namespace
36+
#endif
37+
38+
FlutterProjectBundle::FlutterProjectBundle(
39+
const FlutterDesktopEngineProperties& properties)
40+
: assets_path_(properties.assets_path),
41+
icu_path_(properties.icu_data_path) {
42+
if (properties.aot_library_path != nullptr) {
43+
aot_library_path_ = std::filesystem::path(properties.aot_library_path);
44+
}
45+
46+
// Resolve any relative paths.
47+
if (assets_path_.is_relative() || icu_path_.is_relative() ||
48+
(!aot_library_path_.empty() && aot_library_path_.is_relative())) {
49+
std::filesystem::path executable_location = GetExecutableDirectory();
50+
if (executable_location.empty()) {
51+
FT_LOGE("Unable to find executable location to resolve resource paths.");
52+
assets_path_ = std::filesystem::path();
53+
icu_path_ = std::filesystem::path();
54+
} else {
55+
assets_path_ = std::filesystem::path(executable_location) / assets_path_;
56+
icu_path_ = std::filesystem::path(executable_location) / icu_path_;
57+
if (!aot_library_path_.empty()) {
58+
aot_library_path_ =
59+
std::filesystem::path(executable_location) / aot_library_path_;
60+
}
61+
}
62+
}
63+
64+
switches_.insert(switches_.end(), properties.switches,
65+
properties.switches + properties.switches_count);
66+
}
67+
68+
bool FlutterProjectBundle::HasValidPaths() {
69+
return !assets_path_.empty() && !icu_path_.empty();
70+
}
71+
72+
// Attempts to load AOT data from the given path, which must be absolute and
73+
// non-empty. Logs and returns nullptr on failure.
74+
UniqueAotDataPtr FlutterProjectBundle::LoadAotData(
75+
const FlutterEngineProcTable& engine_procs) {
76+
if (aot_library_path_.empty()) {
77+
FT_LOGE(
78+
"Attempted to load AOT data, but no aot_library_path was provided.");
79+
return UniqueAotDataPtr(nullptr, nullptr);
80+
}
81+
if (!std::filesystem::exists(aot_library_path_)) {
82+
FT_LOGE("Can't load AOT data from %s; no such file.",
83+
aot_library_path_.u8string().c_str());
84+
return UniqueAotDataPtr(nullptr, nullptr);
85+
}
86+
std::string path_string = aot_library_path_.u8string();
87+
FlutterEngineAOTDataSource source = {};
88+
source.type = kFlutterEngineAOTDataSourceTypeElfPath;
89+
source.elf_path = path_string.c_str();
90+
FlutterEngineAOTData data = nullptr;
91+
auto result = engine_procs.CreateAOTData(&source, &data);
92+
if (result != kSuccess) {
93+
FT_LOGE("Failed to load AOT data from: %s", path_string.c_str());
94+
return UniqueAotDataPtr(nullptr, nullptr);
95+
}
96+
return UniqueAotDataPtr(data, engine_procs.CollectAOTData);
97+
}
98+
99+
FlutterProjectBundle::~FlutterProjectBundle() {}
100+
101+
} // namespace flutter
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2021 Samsung Electronics Co., Ltd. All rights reserved.
2+
// Copyright 2013 The Flutter Authors. All rights reserved.
3+
// Use of this source code is governed by a BSD-style license that can be
4+
// found in the LICENSE file.
5+
6+
#ifndef EMBEDDER_FLUTTER_PROJECT_BUNDLE_H_
7+
#define EMBEDDER_FLUTTER_PROJECT_BUNDLE_H_
8+
9+
#include <filesystem>
10+
#include <string>
11+
#include <vector>
12+
13+
#include "flutter/shell/platform/embedder/embedder.h"
14+
#include "flutter/shell/platform/tizen/public/flutter_tizen.h"
15+
16+
namespace flutter {
17+
18+
using UniqueAotDataPtr =
19+
std::unique_ptr<_FlutterEngineAOTData, FlutterEngineCollectAOTDataFnPtr>;
20+
21+
// The data associated with a Flutter project needed to run it in an engine.
22+
class FlutterProjectBundle {
23+
public:
24+
// Creates a new project bundle from the given properties.
25+
//
26+
// Treats any relative paths as relative to the directory of the app binary.
27+
explicit FlutterProjectBundle(
28+
const FlutterDesktopEngineProperties& properties);
29+
30+
~FlutterProjectBundle();
31+
32+
// Whether or not the bundle is valid. This does not check that the paths
33+
// exist, or contain valid data, just that paths were able to be constructed.
34+
bool HasValidPaths();
35+
36+
// Returns the path to the assets directory.
37+
const std::filesystem::path& assets_path() { return assets_path_; }
38+
39+
// Returns the path to the ICU data file.
40+
const std::filesystem::path& icu_path() { return icu_path_; }
41+
42+
// Returns any switches that should be passed to the engine.
43+
const std::vector<std::string> switches() { return switches_; }
44+
45+
// Attempts to load AOT data for this bundle. The returned data must be
46+
// retained until any engine instance it is passed to has been shut down.
47+
//
48+
// Logs and returns nullptr on failure.
49+
UniqueAotDataPtr LoadAotData(const FlutterEngineProcTable& engine_procs);
50+
51+
private:
52+
std::filesystem::path assets_path_;
53+
std::filesystem::path icu_path_;
54+
std::vector<std::string> switches_ = {};
55+
56+
// Path to the AOT library file, if any.
57+
std::filesystem::path aot_library_path_;
58+
};
59+
60+
} // namespace flutter
61+
62+
#endif // EMBEDDER_FLUTTER_PROJECT_BUNDLE_H_

shell/platform/tizen/flutter_tizen.cc

+11-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h"
99
#include "flutter/shell/platform/common/client_wrapper/include/flutter/standard_message_codec.h"
1010
#include "flutter/shell/platform/common/incoming_message_dispatcher.h"
11+
#include "flutter/shell/platform/tizen/flutter_project_bundle.h"
1112
#include "flutter/shell/platform/tizen/flutter_tizen_engine.h"
1213
#include "flutter/shell/platform/tizen/public/flutter_platform_view.h"
1314
#include "flutter/shell/platform/tizen/tizen_log.h"
@@ -25,12 +26,18 @@ static FlutterDesktopEngineRef HandleForEngine(
2526
}
2627

2728
FlutterDesktopEngineRef FlutterDesktopRunEngine(
28-
const FlutterDesktopEngineProperties& engine_properties,
29-
bool headed) {
29+
const FlutterDesktopWindowProperties& window_properties,
30+
const FlutterDesktopEngineProperties& engine_properties) {
3031
flutter::StartLogging();
3132

32-
auto engine = std::make_unique<flutter::FlutterTizenEngine>(headed);
33-
if (!engine->RunEngine(engine_properties)) {
33+
flutter::FlutterProjectBundle project(engine_properties);
34+
auto engine = std::make_unique<flutter::FlutterTizenEngine>(project);
35+
if (window_properties.headed) {
36+
engine->InitializeRenderer(window_properties.x, window_properties.y,
37+
window_properties.width,
38+
window_properties.height);
39+
}
40+
if (!engine->RunEngine()) {
3441
FT_LOGE("Failed to run the Flutter engine.");
3542
return nullptr;
3643
}

shell/platform/tizen/flutter_tizen_engine.cc

+42-55
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
#include "flutter_tizen_engine.h"
77

8-
#include <filesystem>
8+
#include <algorithm>
99
#include <string>
1010
#include <vector>
1111

@@ -33,7 +33,9 @@ constexpr double kProfileFactor = 1.0;
3333

3434
} // namespace
3535

36-
FlutterTizenEngine::FlutterTizenEngine(bool headed) {
36+
FlutterTizenEngine::FlutterTizenEngine(const FlutterProjectBundle& project)
37+
: project_(std::make_unique<FlutterProjectBundle>(project)),
38+
aot_data_(nullptr, nullptr) {
3739
embedder_api_.struct_size = sizeof(FlutterEngineProcTable);
3840
FlutterEngineGetProcAddresses(&embedder_api_);
3941

@@ -55,19 +57,20 @@ FlutterTizenEngine::FlutterTizenEngine(bool headed) {
5557

5658
plugin_registrar_ = std::make_unique<FlutterDesktopPluginRegistrar>();
5759
plugin_registrar_->engine = this;
58-
59-
if (headed) {
60-
InitializeRenderer();
61-
}
6260
}
6361

6462
FlutterTizenEngine::~FlutterTizenEngine() {
6563
renderer = nullptr;
6664
}
6765

68-
void FlutterTizenEngine::InitializeRenderer() {
66+
void FlutterTizenEngine::InitializeRenderer(int32_t x,
67+
int32_t y,
68+
int32_t width,
69+
int32_t height) {
70+
TizenRenderer::WindowGeometry geometry = {x, y, width, height};
71+
6972
#ifdef TIZEN_RENDERER_EVAS_GL
70-
renderer = std::make_unique<TizenRendererEvasGL>(*this);
73+
renderer = std::make_unique<TizenRendererEvasGL>(geometry, *this);
7174

7275
render_loop_ = std::make_unique<TizenRenderEventLoop>(
7376
std::this_thread::get_id(), // main thread
@@ -78,7 +81,7 @@ void FlutterTizenEngine::InitializeRenderer() {
7881
},
7982
renderer.get());
8083
#else
81-
renderer = std::make_unique<TizenRendererEcoreWl2>(*this);
84+
renderer = std::make_unique<TizenRendererEcoreWl2>(geometry, *this);
8285

8386
tizen_vsync_waiter_ = std::make_unique<TizenVsyncWaiter>(this);
8487
#endif
@@ -88,52 +91,42 @@ void FlutterTizenEngine::NotifyLowMemoryWarning() {
8891
embedder_api_.NotifyLowMemoryWarning(engine_);
8992
}
9093

91-
// Attempts to load AOT data from the given path, which must be absolute and
92-
// non-empty. Logs and returns nullptr on failure.
93-
UniqueAotDataPtr FlutterTizenEngine::LoadAotData(std::string aot_data_path) {
94-
if (aot_data_path.empty()) {
95-
FT_LOGE(
96-
"Attempted to load AOT data, but no aot_library_path was provided.");
97-
return nullptr;
98-
}
99-
if (!std::filesystem::exists(aot_data_path)) {
100-
FT_LOGE("Can't load AOT data from %s; no such file.",
101-
aot_data_path.c_str());
102-
return nullptr;
103-
}
104-
FlutterEngineAOTDataSource source = {};
105-
source.type = kFlutterEngineAOTDataSourceTypeElfPath;
106-
source.elf_path = aot_data_path.c_str();
107-
FlutterEngineAOTData data = nullptr;
108-
auto result = embedder_api_.CreateAOTData(&source, &data);
109-
if (result != kSuccess) {
110-
FT_LOGE("Failed to load AOT data from: %s", aot_data_path.c_str());
111-
return nullptr;
94+
bool FlutterTizenEngine::RunEngine() {
95+
if (engine_ != nullptr) {
96+
FT_LOGE("The engine has already started.");
97+
return false;
11298
}
113-
return UniqueAotDataPtr(data);
114-
}
115-
116-
bool FlutterTizenEngine::RunEngine(
117-
const FlutterDesktopEngineProperties& engine_properties) {
11899
if (IsHeaded() && !renderer->IsValid()) {
119100
FT_LOGE("The display was not valid.");
120101
return false;
121102
}
122103

104+
if (!project_->HasValidPaths()) {
105+
FT_LOGE("Missing or unresolvable paths to assets.");
106+
return false;
107+
}
108+
std::string assets_path_string = project_->assets_path().u8string();
109+
std::string icu_path_string = project_->icu_path().u8string();
110+
if (embedder_api_.RunsAOTCompiledDartCode()) {
111+
aot_data_ = project_->LoadAotData(embedder_api_);
112+
if (!aot_data_) {
113+
FT_LOGE("Unable to start engine without AOT data.");
114+
return false;
115+
}
116+
}
117+
123118
// FlutterProjectArgs is expecting a full argv, so when processing it for
124119
// flags the first item is treated as the executable and ignored. Add a dummy
125120
// value so that all provided arguments are used.
121+
std::vector<std::string> switches = project_->switches();
126122
std::vector<const char*> argv = {"placeholder"};
127-
if (engine_properties.switches_count > 0) {
128-
argv.insert(argv.end(), &engine_properties.switches[0],
129-
&engine_properties.switches[engine_properties.switches_count]);
130-
}
123+
std::transform(
124+
switches.begin(), switches.end(), std::back_inserter(argv),
125+
[](const std::string& arg) -> const char* { return arg.c_str(); });
131126

132-
for (size_t i = 0; i < engine_properties.switches_count; ++i) {
133-
auto str = std::string{engine_properties.switches[i]};
134-
if (str.find("verbose-logging") != std::string::npos) {
135-
SetMinLoggingLevel(DLOG_INFO);
136-
}
127+
if (std::find(switches.begin(), switches.end(), "verbose-logging") !=
128+
switches.end()) {
129+
SetMinLoggingLevel(DLOG_INFO);
137130
}
138131

139132
// Configure task runners.
@@ -173,10 +166,10 @@ bool FlutterTizenEngine::RunEngine(
173166

174167
FlutterProjectArgs args = {};
175168
args.struct_size = sizeof(FlutterProjectArgs);
176-
args.assets_path = engine_properties.assets_path;
177-
args.icu_data_path = engine_properties.icu_data_path;
169+
args.assets_path = assets_path_string.c_str();
170+
args.icu_data_path = icu_path_string.c_str();
178171
args.command_line_argc = static_cast<int>(argv.size());
179-
args.command_line_argv = &argv[0];
172+
args.command_line_argv = argv.size() > 0 ? argv.data() : nullptr;
180173
args.platform_message_callback =
181174
[](const FlutterPlatformMessage* engine_message, void* user_data) {
182175
if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) {
@@ -198,13 +191,7 @@ bool FlutterTizenEngine::RunEngine(
198191
};
199192
}
200193
#endif
201-
202-
if (embedder_api_.RunsAOTCompiledDartCode()) {
203-
aot_data_ = LoadAotData(engine_properties.aot_library_path);
204-
if (!aot_data_) {
205-
FT_LOGE("Unable to start engine without AOT data.");
206-
return false;
207-
}
194+
if (aot_data_) {
208195
args.aot_data = aot_data_.get();
209196
}
210197

@@ -357,7 +344,7 @@ void FlutterTizenEngine::SetWindowOrientation(int32_t degree) {
357344
renderer->SetRotate(degree);
358345
// Compute renderer transformation based on the angle of rotation.
359346
double rad = (360 - degree) * M_PI / 180;
360-
auto geometry = renderer->GetGeometry();
347+
auto geometry = renderer->GetCurrentGeometry();
361348
double width = geometry.w;
362349
double height = geometry.h;
363350

0 commit comments

Comments
 (0)