Skip to content

Commit 899ad65

Browse files
authored
[linux/windows] Add FlutterWindowController (#253)
Creates a simple C++ object as the primary interaction point for the embedder calls. This provides a simpler API surface than embedder.h, and folds in some common code (e.g., error logging). This also serves to insulate clients from the embedder.h API layer, so that future incremental changes done for #230 will cause less churn for embedders.
1 parent ec38f43 commit 899ad65

File tree

8 files changed

+243
-85
lines changed

8 files changed

+243
-85
lines changed

example/linux_fde/flutter_embedder_example.cc

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
#include <menubar/menubar_plugin.h>
2525

2626
#ifdef USE_FLATTENED_INCLUDES
27-
#include <flutter_desktop_embedding/embedder.h>
27+
#include <flutter_desktop_embedding/flutter_window_controller.h>
2828
#else
29-
#include <flutter_desktop_embedding/glfw/embedder.h>
29+
#include <flutter_desktop_embedding/glfw/flutter_window_controller.h>
3030
#endif
3131

3232
namespace {
@@ -53,11 +53,6 @@ std::string GetExecutableDirectory() {
5353
} // namespace
5454

5555
int main(int argc, char **argv) {
56-
if (!flutter_desktop_embedding::FlutterInit()) {
57-
std::cerr << "Unable to init GLFW; exiting." << std::endl;
58-
return EXIT_FAILURE;
59-
}
60-
6156
// Resources are located relative to the executable.
6257
std::string base_directory = GetExecutableDirectory();
6358
if (base_directory.empty()) {
@@ -72,27 +67,27 @@ int main(int argc, char **argv) {
7267
#ifdef NDEBUG
7368
arguments.push_back("--disable-dart-asserts");
7469
#endif
70+
71+
flutter_desktop_embedding::FlutterWindowController flutter_controller(
72+
icu_data_path);
73+
7574
// Start the engine.
76-
auto window = flutter_desktop_embedding::CreateFlutterWindow(
77-
640, 480, assets_path, icu_data_path, arguments);
78-
if (window == nullptr) {
79-
flutter_desktop_embedding::FlutterTerminate();
80-
std::cerr << "Unable to create Flutter window; exiting." << std::endl;
75+
if (!flutter_controller.CreateWindow(640, 480, assets_path, arguments)) {
8176
return EXIT_FAILURE;
8277
}
8378

8479
// Register any native plugins.
8580
plugins_menubar::MenubarPlugin::RegisterWithRegistrar(
86-
flutter_desktop_embedding::GetRegistrarForPlugin(
87-
window, "plugins_menubar::MenubarPlugin"));
81+
flutter_controller.GetRegistrarForPlugin(
82+
"plugins_menubar::MenubarPlugin"));
8883
plugins_color_panel::ColorPanelPlugin::RegisterWithRegistrar(
89-
flutter_desktop_embedding::GetRegistrarForPlugin(
90-
window, "plugins_color_panel::ColorPanelPlugin"));
84+
flutter_controller.GetRegistrarForPlugin(
85+
"plugins_color_panel::ColorPanelPlugin"));
9186
plugins_file_chooser::FileChooserPlugin::RegisterWithRegistrar(
92-
flutter_desktop_embedding::GetRegistrarForPlugin(
93-
window, "plugins_file_chooser::FileChooserPlugin"));
87+
flutter_controller.GetRegistrarForPlugin(
88+
"plugins_file_chooser::FileChooserPlugin"));
9489

95-
flutter_desktop_embedding::FlutterWindowLoop(window);
96-
glfwTerminate();
90+
// Run until the window is closed.
91+
flutter_controller.RunEventLoop();
9792
return EXIT_SUCCESS;
9893
}

example/windows_fde/flutter_embedder_example.cpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,31 @@
1313
// limitations under the License.
1414

1515
#include <iostream>
16+
#include <string>
1617
#include <vector>
1718

18-
#include "flutter_desktop_embedding/glfw/embedder.h"
19+
#include "flutter_desktop_embedding/glfw/flutter_window_controller.h"
1920

2021
int main(int argc, char **argv) {
21-
if (!flutter_desktop_embedding::FlutterInit()) {
22-
std::cerr << "Unable to init GLFW; exiting." << std::endl;
23-
return EXIT_FAILURE;
24-
}
22+
// TODO: Make paths relative to the executable so it can be run from anywhere.
23+
std::string assets_path = "..\\build\\flutter_assets";
24+
std::string icu_data_path =
25+
"..\\..\\library\\windows\\dependencies\\engine\\icudtl.dat";
26+
2527
// Arguments for the Flutter Engine.
2628
std::vector<std::string> arguments;
2729
#ifndef _DEBUG
2830
arguments.push_back("--disable-dart-asserts");
2931
#endif
32+
flutter_desktop_embedding::FlutterWindowController flutter_controller(
33+
icu_data_path);
34+
3035
// Start the engine.
31-
// TODO: Make paths relative to the executable so it can be run from anywhere.
32-
auto window = flutter_desktop_embedding::CreateFlutterWindow(
33-
640, 480, "..\\build\\flutter_assets",
34-
"..\\..\\library\\windows\\dependencies\\engine\\icudtl.dat", arguments);
35-
if (window == nullptr) {
36-
flutter_desktop_embedding::FlutterTerminate();
37-
std::cerr << "Unable to create Flutter window; exiting." << std::endl;
36+
if (!flutter_controller.CreateWindow(640, 480, assets_path, arguments)) {
3837
return EXIT_FAILURE;
3938
}
4039

41-
flutter_desktop_embedding::FlutterWindowLoop(window);
42-
flutter_desktop_embedding::FlutterTerminate();
40+
// Run until the window is closed.
41+
flutter_controller.RunEventLoop();
4342
return EXIT_SUCCESS;
4443
}

library/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ published_shared_library("flutter_embedder") {
2121
if (is_linux || is_win) {
2222
public = [
2323
"include/flutter_desktop_embedding/glfw/embedder.h",
24+
"include/flutter_desktop_embedding/glfw/flutter_window_controller.h",
2425
]
2526
sources = [
2627
"common/glfw/embedder.cc",
28+
"common/glfw/flutter_window_controller.cc",
2729
"common/glfw/key_event_handler.cc",
2830
"common/glfw/key_event_handler.h",
2931
"common/glfw/keyboard_hook_handler.h",

library/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ $ sudo apt-get install libglfw3-dev libepoxy-dev libjsoncpp-dev libgtk-3-dev \
5555
#### Using the Library
5656

5757
Run `make` under `linux/`, then link `libflutter_embedder.so` into your
58-
binary. See [embedder.h](include/flutter_desktop_embedding/glfw/embedder.h)
58+
binary. See
59+
[flutter_window_controller.h](include/flutter_desktop_embedding/glfw/flutter_window_controller.h)
5960
for details on calling into the library.
6061

6162
You will also need to link `libflutter_engine.so` into your binary.
@@ -96,8 +97,8 @@ You must have a copy of Visual Studio installed.
9697

9798
Build the GLFW Library project under `windows/` in Visual Studio into a static
9899
or dynamic library, then link `flutter_embedder.lib` into your binary and make
99-
sure `embedder.h` is in your include paths. Also ensure that the
100-
`flutter_engine.dll`, and if using a dynamic library
100+
sure `flutter_window_controller.h` is in your include paths. Also ensure that
101+
the `flutter_engine.dll`, and if using a dynamic library
101102
`flutter_embedder.dll`, are in valid DLL include paths.
102103

103104
The output files are located in `bin\x64\$(Configuration)\GLFW Library\`.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2019 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "library/include/flutter_desktop_embedding/glfw/flutter_window_controller.h"
16+
17+
#include <iostream>
18+
19+
namespace flutter_desktop_embedding {
20+
21+
FlutterWindowController::FlutterWindowController(std::string &icu_data_path)
22+
: icu_data_path_(icu_data_path) {
23+
init_succeeded_ = FlutterInit();
24+
}
25+
26+
FlutterWindowController::~FlutterWindowController() {
27+
if (init_succeeded_) {
28+
FlutterTerminate();
29+
}
30+
}
31+
32+
bool FlutterWindowController::CreateWindow(
33+
size_t width, size_t height, const std::string &assets_path,
34+
const std::vector<std::string> &arguments) {
35+
if (!init_succeeded_) {
36+
std::cerr << "Could not create window; FlutterInit failed." << std::endl;
37+
return false;
38+
}
39+
40+
if (window_) {
41+
std::cerr << "Only one Flutter window can exist at a time." << std::endl;
42+
return false;
43+
}
44+
45+
window_ = CreateFlutterWindow(width, height, assets_path, icu_data_path_,
46+
arguments);
47+
if (!window_) {
48+
std::cerr << "Failed to create window." << std::endl;
49+
return false;
50+
}
51+
return true;
52+
}
53+
54+
PluginRegistrar *FlutterWindowController::GetRegistrarForPlugin(
55+
const std::string &plugin_name) {
56+
if (!window_) {
57+
return nullptr;
58+
}
59+
return flutter_desktop_embedding::GetRegistrarForPlugin(window_, plugin_name);
60+
}
61+
62+
void FlutterWindowController::RunEventLoop() {
63+
if (window_) {
64+
FlutterWindowLoop(window_);
65+
}
66+
}
67+
68+
} // namespace flutter_desktop_embedding
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2019 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_FLUTTER_WINDOW_CONTROLLER_H_
16+
#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_FLUTTER_WINDOW_CONTROLLER_H_
17+
18+
#include <string>
19+
#include <vector>
20+
21+
#include "embedder.h"
22+
23+
#ifdef USE_FLATTENED_INCLUDES
24+
#include "fde_export.h"
25+
#include "plugin_registrar.h"
26+
#else
27+
#include "../fde_export.h"
28+
#include "../plugin_registrar.h"
29+
#endif
30+
31+
namespace flutter_desktop_embedding {
32+
33+
// A controller for a window displaying Flutter content.
34+
//
35+
// This is the primary wrapper class for the desktop embedding C API.
36+
// If you use this class, you should not call any of the setup or teardown
37+
// methods in embedder.h directly, as this class will do that internally.
38+
//
39+
// Note: This is an early implementation (using GLFW internally) which
40+
// requires control of the application's event loop, and is thus useful
41+
// primarily for building a simple one-window shell hosting a Flutter
42+
// application. The final implementation and API will be very different.
43+
class FDE_EXPORT FlutterWindowController {
44+
public:
45+
// There must be only one instance of this class in an application at any
46+
// given time, as Flutter does not support multiple engines in one process,
47+
// or multiple views in one engine.
48+
explicit FlutterWindowController(std::string &icu_data_path);
49+
50+
~FlutterWindowController();
51+
52+
// Creates and displays a window for displaying Flutter content.
53+
//
54+
// The |assets_path| is the path to the flutter_assets folder for the Flutter
55+
// application to be run. |icu_data_path| is the path to the icudtl.dat file
56+
// for the version of Flutter you are using.
57+
//
58+
// The |arguments| are passed to the Flutter engine. See:
59+
// https://github.com/flutter/engine/blob/master/shell/common/switches.h for
60+
// for details. Not all arguments will apply to embedding mode.
61+
//
62+
// Only one Flutter window can exist at a time; see constructor comment.
63+
bool CreateWindow(size_t width, size_t height, const std::string &assets_path,
64+
const std::vector<std::string> &arguments);
65+
66+
// Returns the PluginRegistrar to register a plugin with the given name.
67+
//
68+
// The name must be unique across the application, so the recommended approach
69+
// is to use the fully namespace-qualified name of the plugin class.
70+
PluginRegistrar *GetRegistrarForPlugin(const std::string &plugin_name);
71+
72+
// Loops on Flutter window events until the window closes.
73+
void RunEventLoop();
74+
75+
private:
76+
// The path to the ICU data file. Set at creation time since it is the same
77+
// for any window created.
78+
std::string icu_data_path_;
79+
80+
// Whether or not FlutterInit succeeded at creation time.
81+
bool init_succeeded_ = false;
82+
83+
// The curent Flutter window, if any.
84+
GLFWwindow *window_ = nullptr;
85+
};
86+
87+
} // namespace flutter_desktop_embedding
88+
89+
#endif // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_FLUTTER_WINDOW_CONTROLLER_H_

library/windows/GLFW Library.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@
148148
<ItemGroup>
149149
<ClCompile Include="..\common\engine_method_result.cc" />
150150
<ClCompile Include="..\common\glfw\embedder.cc" />
151+
<ClCompile Include="..\common\glfw\flutter_window_controller.cc" />
151152
<ClCompile Include="..\common\glfw\key_event_handler.cc" />
152153
<ClCompile Include="..\common\glfw\text_input_plugin.cc" />
153154
<ClCompile Include="..\common\internal\plugin_handler.cc" />

0 commit comments

Comments
 (0)