-
-
Save pulyaevskiy/3e36ec624521892e82f2126bb90cd71d to your computer and use it in GitHub Desktop.
Flutter Embedder API Example (GLFW with OpenGL)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <chrono> | |
#include <embedder.h> | |
#include <glfw3.h> | |
#include <iostream> | |
static_assert(FLUTTER_ENGINE_VERSION == 1, ""); | |
static const size_t kInitialWindowWidth = 800; | |
static const size_t kInitialWindowHeight = 600; | |
void GLFWcursorPositionCallbackAtPhase(GLFWwindow *window, | |
FlutterPointerPhase phase, double x, | |
double y) { | |
FlutterPointerEvent event = {}; | |
event.struct_size = sizeof(event); | |
event.phase = phase; | |
event.x = x; | |
event.y = y; | |
event.timestamp = | |
std::chrono::duration_cast<std::chrono::microseconds>( | |
std::chrono::high_resolution_clock::now().time_since_epoch()) | |
.count(); | |
FlutterEngineSendPointerEvent( | |
reinterpret_cast<FlutterEngine>(glfwGetWindowUserPointer(window)), &event, | |
1); | |
} | |
void GLFWcursorPositionCallback(GLFWwindow *window, double x, double y) { | |
GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kMove, x, y); | |
} | |
void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action, | |
int mods) { | |
if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS) { | |
double x, y; | |
glfwGetCursorPos(window, &x, &y); | |
GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kDown, x, y); | |
glfwSetCursorPosCallback(window, GLFWcursorPositionCallback); | |
} | |
if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_RELEASE) { | |
double x, y; | |
glfwGetCursorPos(window, &x, &y); | |
GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kUp, x, y); | |
glfwSetCursorPosCallback(window, nullptr); | |
} | |
} | |
static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode, | |
int action, int mods) { | |
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { | |
glfwSetWindowShouldClose(window, GLFW_TRUE); | |
} | |
} | |
void GLFWwindowSizeCallback(GLFWwindow *window, int width, int height) { | |
FlutterWindowMetricsEvent event = {}; | |
event.struct_size = sizeof(event); | |
event.width = width; | |
event.height = height; | |
event.pixel_ratio = 1.0; | |
FlutterEngineSendWindowMetricsEvent( | |
reinterpret_cast<FlutterEngine>(glfwGetWindowUserPointer(window)), | |
&event); | |
} | |
bool RunFlutter(GLFWwindow *window) { | |
FlutterRendererConfig config = {}; | |
config.type = kOpenGL; | |
config.open_gl.struct_size = sizeof(config.open_gl); | |
config.open_gl.make_current = [](void *userdata) -> bool { | |
glfwMakeContextCurrent((GLFWwindow *)userdata); | |
return true; | |
}; | |
config.open_gl.clear_current = [](void *) -> bool { | |
glfwMakeContextCurrent(nullptr); // is this even a thing? | |
return true; | |
}; | |
config.open_gl.present = [](void *userdata) -> bool { | |
glfwSwapBuffers((GLFWwindow *)userdata); | |
return true; | |
}; | |
config.open_gl.fbo_callback = [](void *) -> uint32_t { | |
return 0; // FBO0 | |
}; | |
#define MY_PROJECT "/Volumes/Mojo/flutter/examples/flutter_gallery" | |
FlutterProjectArgs args = { | |
.struct_size = sizeof(FlutterProjectArgs), | |
.assets_path = MY_PROJECT "/build/app.flx", | |
.main_path = MY_PROJECT "/lib/main.dart", | |
.packages_path = MY_PROJECT "/.packages", | |
}; | |
FlutterEngine engine = nullptr; | |
auto result = FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, // renderer | |
&args, window, &engine); | |
assert(result == kSuccess && engine != nullptr); | |
glfwSetWindowUserPointer(window, engine); | |
GLFWwindowSizeCallback(window, kInitialWindowWidth, kInitialWindowHeight); | |
return true; | |
} | |
int main(int argc, const char *argv[]) { | |
auto result = glfwInit(); | |
assert(result == GLFW_TRUE); | |
auto window = glfwCreateWindow(kInitialWindowWidth, kInitialWindowHeight, | |
"Flutter", NULL, NULL); | |
assert(window != nullptr); | |
bool runResult = RunFlutter(window); | |
assert(runResult); | |
glfwSetKeyCallback(window, GLFWKeyCallback); | |
glfwSetWindowSizeCallback(window, GLFWwindowSizeCallback); | |
glfwSetMouseButtonCallback(window, GLFWmouseButtonCallback); | |
while (!glfwWindowShouldClose(window)) { | |
std::cout << "Looping..." << std::endl; | |
glfwWaitEvents(); | |
} | |
glfwDestroyWindow(window); | |
glfwTerminate(); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment