Flutter Engine
The Flutter Engine
FlutterEmbedderGLFW.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <cassert>
6#include <chrono>
7#include <iostream>
8
9#include "GLFW/glfw3.h"
10#include "embedder.h"
11
12// This value is calculated after the window is created.
13static double g_pixelRatio = 1.0;
14static const size_t kInitialWindowWidth = 800;
15static const size_t kInitialWindowHeight = 600;
16static constexpr FlutterViewId kImplicitViewId = 0;
17
18static_assert(FLUTTER_ENGINE_VERSION == 1,
19 "This Flutter Embedder was authored against the stable Flutter "
20 "API at version 1. There has been a serious breakage in the "
21 "API. Please read the ChangeLog and take appropriate action "
22 "before updating this assertion");
23
26 double x,
27 double y) {
28 FlutterPointerEvent event = {};
29 event.struct_size = sizeof(event);
30 event.phase = phase;
31 event.x = x * g_pixelRatio;
32 event.y = y * g_pixelRatio;
33 event.timestamp =
34 std::chrono::duration_cast<std::chrono::microseconds>(
35 std::chrono::high_resolution_clock::now().time_since_epoch())
36 .count();
37 // This example only supports a single window, therefore we assume the pointer
38 // event occurred in the only view, the implicit view.
39 event.view_id = kImplicitViewId;
41 reinterpret_cast<FlutterEngine>(glfwGetWindowUserPointer(window)), &event,
42 1);
43}
44
45void GLFWcursorPositionCallback(GLFWwindow* window, double x, double y) {
47}
48
50 int key,
51 int action,
52 int mods) {
53 if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS) {
54 double x, y;
55 glfwGetCursorPos(window, &x, &y);
57 glfwSetCursorPosCallback(window, GLFWcursorPositionCallback);
58 }
59
60 if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_RELEASE) {
61 double x, y;
62 glfwGetCursorPos(window, &x, &y);
64 glfwSetCursorPosCallback(window, nullptr);
65 }
66}
67
68static void GLFWKeyCallback(GLFWwindow* window,
69 int key,
70 int scancode,
71 int action,
72 int mods) {
73 if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
74 glfwSetWindowShouldClose(window, GLFW_TRUE);
75 }
76}
77
78void GLFWwindowSizeCallback(GLFWwindow* window, int width, int height) {
80 event.struct_size = sizeof(event);
81 event.width = width * g_pixelRatio;
82 event.height = height * g_pixelRatio;
83 event.pixel_ratio = g_pixelRatio;
84 // This example only supports a single window, therefore we assume the event
85 // occurred in the only view, the implicit view.
86 event.view_id = kImplicitViewId;
88 reinterpret_cast<FlutterEngine>(glfwGetWindowUserPointer(window)),
89 &event);
90}
91
92bool RunFlutter(GLFWwindow* window,
93 const std::string& project_path,
94 const std::string& icudtl_path) {
95 FlutterRendererConfig config = {};
96 config.type = kOpenGL;
97 config.open_gl.struct_size = sizeof(config.open_gl);
98 config.open_gl.make_current = [](void* userdata) -> bool {
99 glfwMakeContextCurrent(static_cast<GLFWwindow*>(userdata));
100 return true;
101 };
102 config.open_gl.clear_current = [](void*) -> bool {
103 glfwMakeContextCurrent(nullptr); // is this even a thing?
104 return true;
105 };
106 config.open_gl.present = [](void* userdata) -> bool {
107 glfwSwapBuffers(static_cast<GLFWwindow*>(userdata));
108 return true;
109 };
110 config.open_gl.fbo_callback = [](void*) -> uint32_t {
111 return 0; // FBO0
112 };
113 config.open_gl.gl_proc_resolver = [](void*, const char* name) -> void* {
114 return reinterpret_cast<void*>(glfwGetProcAddress(name));
115 };
116
117 // This directory is generated by `flutter build bundle`.
118 std::string assets_path = project_path + "/build/flutter_assets";
120 .struct_size = sizeof(FlutterProjectArgs),
121 .assets_path = assets_path.c_str(),
122 .icu_data_path =
123 icudtl_path.c_str(), // Find this in your bin/cache directory.
124 };
125 FlutterEngine engine = nullptr;
127 FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, // renderer
128 &args, window, &engine);
129 if (result != kSuccess || engine == nullptr) {
130 std::cout << "Could not run the Flutter Engine." << std::endl;
131 return false;
132 }
133
134 glfwSetWindowUserPointer(window, engine);
136
137 return true;
138}
139
141 std::cout << "usage: embedder_example <path to project> <path to icudtl.dat>"
142 << std::endl;
143}
144
145void GLFW_ErrorCallback(int error, const char* description) {
146 std::cout << "GLFW Error: (" << error << ") " << description << std::endl;
147}
148
149int main(int argc, const char* argv[]) {
150 if (argc != 3) {
151 printUsage();
152 return 1;
153 }
154
155 std::string project_path = argv[1];
156 std::string icudtl_path = argv[2];
157
158 glfwSetErrorCallback(GLFW_ErrorCallback);
159
160 int result = glfwInit();
161 if (result != GLFW_TRUE) {
162 std::cout << "Could not initialize GLFW." << std::endl;
163 return EXIT_FAILURE;
164 }
165
166#if defined(__linux__)
167 glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
168#endif
169
170 GLFWwindow* window = glfwCreateWindow(
171 kInitialWindowWidth, kInitialWindowHeight, "Flutter", NULL, NULL);
172 if (window == nullptr) {
173 std::cout << "Could not create GLFW window." << std::endl;
174 return EXIT_FAILURE;
175 }
176
177 int framebuffer_width, framebuffer_height;
178 glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
179 g_pixelRatio = framebuffer_width / kInitialWindowWidth;
180
181 bool run_result = RunFlutter(window, project_path, icudtl_path);
182 if (!run_result) {
183 std::cout << "Could not run the Flutter engine." << std::endl;
184 return EXIT_FAILURE;
185 }
186
187 glfwSetKeyCallback(window, GLFWKeyCallback);
188 glfwSetWindowSizeCallback(window, GLFWwindowSizeCallback);
189 glfwSetMouseButtonCallback(window, GLFWmouseButtonCallback);
190
191 while (!glfwWindowShouldClose(window)) {
192 glfwWaitEvents();
193 }
194
195 glfwDestroyWindow(window);
196 glfwTerminate();
197
198 return EXIT_SUCCESS;
199}
FlutterEngineResult FlutterEngineRun(size_t version, const FlutterRendererConfig *config, const FlutterProjectArgs *args, void *user_data, FLUTTER_API_SYMBOL(FlutterEngine) *engine_out)
Initialize and run a Flutter engine instance and return a handle to it. This is a convenience method ...
Definition: embedder.cc:1715
FlutterEngineResult FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterWindowMetricsEvent *flutter_metrics)
Definition: embedder.cc:2320
FlutterEngineResult FlutterEngineSendPointerEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPointerEvent *pointers, size_t events_count)
Definition: embedder.cc:2429
@ kOpenGL
Definition: embedder.h:80
FlutterPointerPhase
The phase of the pointer event.
Definition: embedder.h:965
@ kUp
Definition: embedder.h:973
@ kDown
Definition: embedder.h:980
@ kMove
Definition: embedder.h:985
FlutterEngineResult
Definition: embedder.h:72
@ kSuccess
Definition: embedder.h:73
int64_t FlutterViewId
Definition: embedder.h:275
#define FLUTTER_ENGINE_VERSION
Definition: embedder.h:70
GLFWwindow * window
Definition: main.cc:45
FlutterEngine engine
Definition: main.cc:68
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent * event
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
#define GLFW_TRUE
Definition: flutter_glfw.cc:33
bool RunFlutter(GLFWwindow *window, const std::string &project_path, const std::string &icudtl_path)
static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
static double g_pixelRatio
static constexpr FlutterViewId kImplicitViewId
void GLFWcursorPositionCallbackAtPhase(GLFWwindow *window, FlutterPointerPhase phase, double x, double y)
static const size_t kInitialWindowHeight
int main(int argc, const char *argv[])
static const size_t kInitialWindowWidth
void GLFWwindowSizeCallback(GLFWwindow *window, int width, int height)
void GLFWcursorPositionCallback(GLFWwindow *window, double x, double y)
void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action, int mods)
void printUsage()
void GLFW_ErrorCallback(int error, const char *description)
char ** argv
Definition: library.h:9
double y
double x
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
int32_t height
int32_t width
ProcResolver gl_proc_resolver
Definition: embedder.h:554
BoolCallback make_current
Definition: embedder.h:516
UIntCallback fbo_callback
Definition: embedder.h:530
size_t struct_size
The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
Definition: embedder.h:515
BoolCallback clear_current
Definition: embedder.h:517
size_t struct_size
The size of this struct. Must be sizeof(FlutterPointerEvent).
Definition: embedder.h:1036
FlutterOpenGLRendererConfig open_gl
Definition: embedder.h:829
FlutterRendererType type
Definition: embedder.h:827
size_t struct_size
The size of this struct. Must be sizeof(FlutterWindowMetricsEvent).
Definition: embedder.h:843