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 <embedder.h>
6 #include <glfw3.h>
7 
8 #include <cassert>
9 #include <chrono>
10 #include <iostream>
11 
12 // This value is calculated after the window is created.
13 static double g_pixelRatio = 1.0;
14 static const size_t kInitialWindowWidth = 800;
15 static const size_t kInitialWindowHeight = 600;
16 
17 static_assert(FLUTTER_ENGINE_VERSION == 1,
18  "This Flutter Embedder was authored against the stable Flutter "
19  "API at version 1. There has been a serious breakage in the "
20  "API. Please read the ChangeLog and take appropriate action "
21  "before updating this assertion");
22 
23 void GLFWcursorPositionCallbackAtPhase(GLFWwindow* window,
25  double x,
26  double y) {
27  FlutterPointerEvent event = {};
28  event.struct_size = sizeof(event);
29  event.phase = phase;
30  event.x = x * g_pixelRatio;
31  event.y = y * g_pixelRatio;
32  event.timestamp =
33  std::chrono::duration_cast<std::chrono::microseconds>(
34  std::chrono::high_resolution_clock::now().time_since_epoch())
35  .count();
37  reinterpret_cast<FlutterEngine>(glfwGetWindowUserPointer(window)), &event,
38  1);
39 }
40 
41 void GLFWcursorPositionCallback(GLFWwindow* window, double x, double y) {
43 }
44 
45 void GLFWmouseButtonCallback(GLFWwindow* window,
46  int key,
47  int action,
48  int mods) {
49  if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS) {
50  double x, y;
51  glfwGetCursorPos(window, &x, &y);
53  glfwSetCursorPosCallback(window, GLFWcursorPositionCallback);
54  }
55 
56  if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_RELEASE) {
57  double x, y;
58  glfwGetCursorPos(window, &x, &y);
60  glfwSetCursorPosCallback(window, nullptr);
61  }
62 }
63 
64 static void GLFWKeyCallback(GLFWwindow* window,
65  int key,
66  int scancode,
67  int action,
68  int mods) {
69  if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
70  glfwSetWindowShouldClose(window, GLFW_TRUE);
71  }
72 }
73 
74 void GLFWwindowSizeCallback(GLFWwindow* window, int width, int height) {
75  FlutterWindowMetricsEvent event = {};
76  event.struct_size = sizeof(event);
77  event.width = width * g_pixelRatio;
78  event.height = height * g_pixelRatio;
79  event.pixel_ratio = g_pixelRatio;
81  reinterpret_cast<FlutterEngine>(glfwGetWindowUserPointer(window)),
82  &event);
83 }
84 
85 bool RunFlutter(GLFWwindow* window,
86  const std::string& project_path,
87  const std::string& icudtl_path) {
88  FlutterRendererConfig config = {};
89  config.type = kOpenGL;
90  config.open_gl.struct_size = sizeof(config.open_gl);
91  config.open_gl.make_current = [](void* userdata) -> bool {
92  glfwMakeContextCurrent((GLFWwindow*)userdata);
93  return true;
94  };
95  config.open_gl.clear_current = [](void*) -> bool {
96  glfwMakeContextCurrent(nullptr); // is this even a thing?
97  return true;
98  };
99  config.open_gl.present = [](void* userdata) -> bool {
100  glfwSwapBuffers((GLFWwindow*)userdata);
101  return true;
102  };
103  config.open_gl.fbo_callback = [](void*) -> uint32_t {
104  return 0; // FBO0
105  };
106 
107  // This directory is generated by `flutter build bundle`.
108  std::string assets_path = project_path + "/build/flutter_assets";
110  .struct_size = sizeof(FlutterProjectArgs),
111  .assets_path = assets_path.c_str(),
112  .icu_data_path =
113  icudtl_path.c_str(), // Find this in your bin/cache directory.
114  };
115  FlutterEngine engine = nullptr;
116  FlutterEngineResult result =
117  FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, // renderer
118  &args, window, &engine);
119  assert(result == kSuccess && engine != nullptr);
120 
121  glfwSetWindowUserPointer(window, engine);
123 
124  return true;
125 }
126 
127 void printUsage() {
128  std::cout << "usage: flutter_glfw <path to project> <path to icudtl.dat>"
129  << std::endl;
130 }
131 
132 void GLFW_ErrorCallback(int error, const char* description) {
133  std::cout << "GLFW Error: (" << error << ") " << description << std::endl;
134 }
135 
136 int main(int argc, const char* argv[]) {
137  if (argc != 3) {
138  printUsage();
139  return 1;
140  }
141 
142  std::string project_path = argv[1];
143  std::string icudtl_path = argv[2];
144 
145  glfwSetErrorCallback(GLFW_ErrorCallback);
146 
147  int result = glfwInit();
148  assert(result == GLFW_TRUE);
149 
150  GLFWwindow* window = glfwCreateWindow(
151  kInitialWindowWidth, kInitialWindowHeight, "Flutter", NULL, NULL);
152  assert(window != nullptr);
153 
154  int framebuffer_width, framebuffer_height;
155  glfwGetFramebufferSize(window, &framebuffer_width, &framebuffer_height);
156  g_pixelRatio = framebuffer_width / kInitialWindowWidth;
157 
158  bool runResult = RunFlutter(window, project_path, icudtl_path);
159  assert(runResult);
160 
161  glfwSetKeyCallback(window, GLFWKeyCallback);
162  glfwSetWindowSizeCallback(window, GLFWwindowSizeCallback);
163  glfwSetMouseButtonCallback(window, GLFWmouseButtonCallback);
164 
165  while (!glfwWindowShouldClose(window)) {
166  std::cout << "Looping..." << std::endl;
167  glfwWaitEvents();
168  }
169 
170  glfwDestroyWindow(window);
171  glfwTerminate();
172 
173  return EXIT_SUCCESS;
174 }
G_BEGIN_DECLS FlValue * args
Definition: embedder.h:479
int main(int argc, const char *argv[])
FlMethodResponse GError ** error
FlutterPointerPhase
The phase of the pointer event.
Definition: embedder.h:471
#define GLFW_TRUE
Definition: flutter_glfw.cc:30
void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action, int mods)
static double g_pixelRatio
void GLFWwindowSizeCallback(GLFWwindow *window, int width, int height)
static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
#define FLUTTER_ENGINE_VERSION
Definition: embedder.h:63
FlutterRendererType type
Definition: embedder.h:448
static const size_t kInitialWindowHeight
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:718
void GLFW_ErrorCallback(int error, const char *description)
size_t struct_size
The size of this struct. Must be sizeof(FlutterPointerEvent).
Definition: embedder.h:532
FlutterPointerPhase phase
Definition: fl_view.cc:78
size_t struct_size
The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
Definition: embedder.h:379
SemanticsAction action
int32_t height
BoolCallback clear_current
Definition: embedder.h:381
int32_t width
static const size_t kInitialWindowWidth
size_t struct_size
The size of this struct. Must be sizeof(FlutterWindowMetricsEvent).
Definition: embedder.h:457
void GLFWcursorPositionCallbackAtPhase(GLFWwindow *window, FlutterPointerPhase phase, double x, double y)
GdkEventButton * event
Definition: fl_view.cc:62
BoolCallback make_current
Definition: embedder.h:380
FlutterOpenGLRendererConfig open_gl
Definition: embedder.h:450
FlutterEngineResult
Definition: embedder.h:65
UIntCallback fbo_callback
Definition: embedder.h:391
void printUsage()
FlutterEngineResult FlutterEngineSendPointerEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPointerEvent *pointers, size_t events_count)
Definition: embedder.cc:1323
void GLFWcursorPositionCallback(GLFWwindow *window, double x, double y)
FlutterEngineResult FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterWindowMetricsEvent *flutter_metrics)
Definition: embedder.cc:1229
bool RunFlutter(GLFWwindow *window, const std::string &project_path, const std::string &icudtl_path)