From 8da5fe80767b7b053a465aac41348e1e432e23d2 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 2 Jan 2019 08:57:46 -0800 Subject: [PATCH 1/4] Move Windows embedder to shared --- example/windows/GLFW Example.vcxproj | 2 +- example/windows/flutter_embedder_example.cpp | 2 +- library/{windows/embedder.cpp => common/glfw/embedder.cc} | 2 +- .../flutter_desktop_embedding/glfw}/embedder.h | 8 ++++---- library/windows/GLFW Library.vcxproj | 4 ++-- library/windows/GLFW Library.vcxproj.filters | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) rename library/{windows/embedder.cpp => common/glfw/embedder.cc} (99%) rename library/{windows => include/flutter_desktop_embedding/glfw}/embedder.h (93%) diff --git a/example/windows/GLFW Example.vcxproj b/example/windows/GLFW Example.vcxproj index e15a6eda7..c61b451f0 100644 --- a/example/windows/GLFW Example.vcxproj +++ b/example/windows/GLFW Example.vcxproj @@ -72,7 +72,7 @@ $(SolutionDir)bin\$(Platform)\$(Configuration)\$(ProjectName)\ $(SolutionDir)bin\intermediates\$(Platform)\$(Configuration)\$(ProjectName)\ - $(ProjectDir)..\..\library\windows\dependencies\;$(ProjectDir)..\..\;$(IncludePath);$(ProjectDir)..\..\library\windows\ + $(ProjectDir)..\..\library\windows\dependencies\;$(ProjectDir)..\..\;$(IncludePath);$(ProjectDir)..\..\library\windows\;$(ProjectDir)..\..\library\include\ $(ProjectDir)..\..\library\windows\dependencies\GLFW\;$(SolutionDir)bin\$(Platform)\$(Configuration)\GLFW Library\;$(LibraryPath) diff --git a/example/windows/flutter_embedder_example.cpp b/example/windows/flutter_embedder_example.cpp index 165bbd55e..94d4a2d57 100644 --- a/example/windows/flutter_embedder_example.cpp +++ b/example/windows/flutter_embedder_example.cpp @@ -15,7 +15,7 @@ #include #include -#include "embedder.h" +#include "flutter_desktop_embedding/glfw/embedder.h" int main(int argc, char **argv) { if (!flutter_desktop_embedding::FlutterInit()) { diff --git a/library/windows/embedder.cpp b/library/common/glfw/embedder.cc similarity index 99% rename from library/windows/embedder.cpp rename to library/common/glfw/embedder.cc index f6522ca3f..1746c58c6 100644 --- a/library/windows/embedder.cpp +++ b/library/common/glfw/embedder.cc @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "embedder.h" +#include "library/include/flutter_desktop_embedding/glfw/embedder.h" #include #include diff --git a/library/windows/embedder.h b/library/include/flutter_desktop_embedding/glfw/embedder.h similarity index 93% rename from library/windows/embedder.h rename to library/include/flutter_desktop_embedding/glfw/embedder.h index 028d418fb..712512be2 100644 --- a/library/windows/embedder.h +++ b/library/include/flutter_desktop_embedding/glfw/embedder.h @@ -12,15 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef WINDOWS_LIBRARY_EMBEDDER_H_ -#define WINDOWS_LIBRARY_EMBEDDER_H_ +#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_EMBEDDER_H_ +#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_EMBEDDER_H_ #include #include #include -#include "library/include/flutter_desktop_embedding/plugin.h" +#include "../plugin.h" namespace flutter_desktop_embedding { @@ -86,4 +86,4 @@ void FlutterWindowLoop(GLFWwindow *flutter_window); } // namespace flutter_desktop_embedding -#endif // WINDOWS_LIBRARY_EMBEDDER_H_ +#endif // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_EMBEDDER_H_ diff --git a/library/windows/GLFW Library.vcxproj b/library/windows/GLFW Library.vcxproj index 8ea8c4899..f1628bc2d 100644 --- a/library/windows/GLFW Library.vcxproj +++ b/library/windows/GLFW Library.vcxproj @@ -263,6 +263,7 @@ + @@ -277,7 +278,6 @@ - @@ -288,4 +288,4 @@ - \ No newline at end of file + diff --git a/library/windows/GLFW Library.vcxproj.filters b/library/windows/GLFW Library.vcxproj.filters index bf7b4fad3..03dd85a33 100644 --- a/library/windows/GLFW Library.vcxproj.filters +++ b/library/windows/GLFW Library.vcxproj.filters @@ -15,7 +15,7 @@ - + Source Files @@ -71,4 +71,4 @@ Source Files - \ No newline at end of file + From 52ddcf927615f4eacd8cf9af4c434e923a02fbdd Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 2 Jan 2019 09:41:31 -0800 Subject: [PATCH 2/4] Reconcile shared header with Linux header --- library/common/glfw/embedder.cc | 48 +++++++++++++++---- .../flutter_desktop_embedding/glfw/embedder.h | 10 ++++ 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/library/common/glfw/embedder.cc b/library/common/glfw/embedder.cc index 1746c58c6..c1d757625 100644 --- a/library/common/glfw/embedder.cc +++ b/library/common/glfw/embedder.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,20 @@ #include "library/common/glfw/text_input_plugin.h" #include "library/common/internal/plugin_handler.h" +#ifdef __linux__ +#include +#include +#endif + +// GLFW_TRUE & GLFW_FALSE are introduced since libglfw-3.3, +// add definitions here to compile under the old versions. +#ifndef GLFW_TRUE +#define GLFW_TRUE 1 +#endif +#ifndef GLFW_FALSE +#define GLFW_FALSE 0 +#endif + static_assert(FLUTTER_ENGINE_VERSION == 1, ""); // Struct for storing state within an instance of the GLFW Window. @@ -45,14 +60,14 @@ struct FlutterEmbedderState { static constexpr char kDefaultWindowTitle[] = "Flutter"; -// Retreaves state bag for the window in question from the GLFWWindow +// Retrieves state bag for the window in question from the GLFWWindow. static FlutterEmbedderState *GetSavedEmbedderState(GLFWwindow *window) { return reinterpret_cast( glfwGetWindowUserPointer(window)); } -// When GLFW calls back to the window with a cursor position move, forward to -// FlutterEngine as a pointer event with appropriate phase +// When GLFW calls back to the window with a cursor position move, forwards to +// FlutterEngine as a pointer event with appropriate phase. static void GLFWcursorPositionCallbackAtPhase(GLFWwindow *window, FlutterPointerPhase phase, double x, double y) { @@ -69,11 +84,12 @@ static void GLFWcursorPositionCallbackAtPhase(GLFWwindow *window, 1); } -// Report cursor move to engine +// Reports cursor move to the Flutter engine. static void GLFWcursorPositionCallback(GLFWwindow *window, double x, double y) { GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kMove, x, y); } +// Reports mouse button press to the Flutter engine. static void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action, int mods) { double x, y; @@ -89,6 +105,7 @@ static void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action, } } +// Passes character input events to registered handlers. static void GLFWCharCallback(GLFWwindow *window, unsigned int code_point) { for (flutter_desktop_embedding::KeyboardHookHandler *handler : GetSavedEmbedderState(window)->keyboard_hook_handlers) { @@ -96,17 +113,16 @@ static void GLFWCharCallback(GLFWwindow *window, unsigned int code_point) { } } +// Passes raw key events to registered handlers. static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) { for (flutter_desktop_embedding::KeyboardHookHandler *handler : GetSavedEmbedderState(window)->keyboard_hook_handlers) { handler->KeyboardHook(window, key, scancode, action, mods); } - if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { - glfwSetWindowShouldClose(window, GLFW_TRUE); - } } +// Reports window size changes to the Flutter engine. static void GLFWwindowSizeCallback(GLFWwindow *window, int width, int height) { FlutterWindowMetricsEvent event = {}; event.struct_size = sizeof(event); @@ -181,7 +197,7 @@ static uint32_t GLFWGetActiveFbo(void *user_data) { return 0; } static void GLFWClearCanvas(GLFWwindow *window) { glfwMakeContextCurrent(window); // This color is Material Blue Grey. - glClearColor(236, 239, 241, 0); + glClearColor(236.0 / 255.0, 239.0 / 255.0, 241.0 / 255.0, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glFlush(); glfwSwapBuffers(window); @@ -257,6 +273,9 @@ GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height, const std::string &packages_path, const std::string &icu_data_path, const std::vector &arguments) { +#ifdef __linux__ + gtk_init(0, nullptr); +#endif auto window = glfwCreateWindow(initial_width, initial_height, kDefaultWindowTitle, NULL, NULL); if (window == nullptr) { @@ -287,16 +306,25 @@ GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height, int width, height; glfwGetWindowSize(window, &width, &height); GLFWwindowSizeCallback(window, width, height); - glfwSetKeyCallback(window, GLFWKeyCallback); glfwSetWindowSizeCallback(window, GLFWwindowSizeCallback); - glfwSetMouseButtonCallback(window, GLFWmouseButtonCallback); GLFWAssignEventCallbacks(window); return window; } void FlutterWindowLoop(GLFWwindow *flutter_window) { +#ifdef __linux__ + // Necessary for GTK thread safety. + XInitThreads(); +#endif while (!glfwWindowShouldClose(flutter_window)) { +#ifdef __linux__ + glfwPollEvents(); + if (gtk_events_pending()) { + gtk_main_iteration(); + } +#else glfwWaitEvents(); +#endif // TODO(awdavies): This will be deprecated soon. __FlutterEngineFlushPendingTasksNow(); } diff --git a/library/include/flutter_desktop_embedding/glfw/embedder.h b/library/include/flutter_desktop_embedding/glfw/embedder.h index 712512be2..62b8bba4d 100644 --- a/library/include/flutter_desktop_embedding/glfw/embedder.h +++ b/library/include/flutter_desktop_embedding/glfw/embedder.h @@ -15,12 +15,22 @@ #ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_EMBEDDER_H_ #define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_GLFW_EMBEDDER_H_ +#include #include #include +#ifdef __linux__ +// Epoxy must be included before any graphics-related code. +#include +#endif + #include +#ifdef USE_FLATTENED_INCLUDES +#include "plugin.h" +#else #include "../plugin.h" +#endif namespace flutter_desktop_embedding { From 49ef5172f8fefda21d2d647e2b6a298757ddab60 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 2 Jan 2019 13:03:42 -0500 Subject: [PATCH 3/4] Switch Linux over to shared version (with fixes) --- example/linux/flutter_embedder_example.cc | 6 +- library/BUILD.gn | 28 +- library/README.md | 2 +- library/common/glfw/embedder.cc | 2 +- .../flutter_desktop_embedding/glfw/embedder.h | 2 +- .../linux/embedder.h | 85 ----- library/linux/Makefile | 2 +- library/linux/src/embedder.cc | 316 ------------------ 8 files changed, 20 insertions(+), 423 deletions(-) delete mode 100644 library/include/flutter_desktop_embedding/linux/embedder.h delete mode 100644 library/linux/src/embedder.cc diff --git a/example/linux/flutter_embedder_example.cc b/example/linux/flutter_embedder_example.cc index 1a030828e..003ecd989 100644 --- a/example/linux/flutter_embedder_example.cc +++ b/example/linux/flutter_embedder_example.cc @@ -26,7 +26,7 @@ #ifdef USE_FLATTENED_INCLUDES #include #else -#include +#include #endif namespace { @@ -53,7 +53,7 @@ std::string GetExecutableDirectory() { } // namespace int main(int argc, char **argv) { - if (!glfwInit()) { + if (!flutter_desktop_embedding::FlutterInit()) { std::cerr << "Couldn't init GLFW" << std::endl; } @@ -78,7 +78,7 @@ int main(int argc, char **argv) { auto window = flutter_desktop_embedding::CreateFlutterWindowInSnapshotMode( 640, 480, assets_path, icu_data_path, arguments); if (window == nullptr) { - glfwTerminate(); + flutter_desktop_embedding::FlutterTerminate(); return EXIT_FAILURE; } diff --git a/library/BUILD.gn b/library/BUILD.gn index 6b31ae428..605deddc5 100644 --- a/library/BUILD.gn +++ b/library/BUILD.gn @@ -17,14 +17,22 @@ import("//build/packaging.gni") import("//library/engine.gni") published_shared_library("flutter_embedder") { - if (is_linux) { - sources = [ - "linux/src/embedder.cc", - ] + # GLFW embedding implementation. + if (is_linux || is_win) { public = [ - "include/flutter_desktop_embedding/linux/embedder.h", + "include/flutter_desktop_embedding/glfw/embedder.h", + ] + sources = [ + "common/glfw/embedder.cc", + "common/glfw/key_event_handler.cc", + "common/glfw/key_event_handler.h", + "common/glfw/keyboard_hook_handler.h", + "common/glfw/text_input_plugin.cc", + "common/glfw/text_input_plugin.h", ] } + + # Embedding-agnostic shared C++. if (is_linux || is_win) { sources += [ "common/internal/engine_method_result.cc", @@ -56,16 +64,6 @@ published_shared_library("flutter_embedder") { "include/flutter_desktop_embedding/plugin.h", ] } - # GLFW-specific code. - if (is_linux || is_win) { - sources += [ - "common/glfw/key_event_handler.cc", - "common/glfw/key_event_handler.h", - "common/glfw/keyboard_hook_handler.h", - "common/glfw/text_input_plugin.cc", - "common/glfw/text_input_plugin.h", - ] - } deps = [ ":fetch_flutter_engine", diff --git a/library/README.md b/library/README.md index e325a41d6..79329f705 100644 --- a/library/README.md +++ b/library/README.md @@ -49,7 +49,7 @@ $ sudo apt-get install libglfw3-dev libepoxy-dev libjsoncpp-dev libgtk-3-dev \ #### Using the Library Run `make` under `linux/`, then link `libflutter_embedder.so` into your -binary. See [embedder.h](linux/include/flutter_desktop_embedding/embedder.h) +binary. See [embedder.h](include/flutter_desktop_embedding/glfw/embedder.h) for details on calling into the library. You will also need to link `libflutter_engine.so` into your binary. diff --git a/library/common/glfw/embedder.cc b/library/common/glfw/embedder.cc index c1d757625..c9a7c867c 100644 --- a/library/common/glfw/embedder.cc +++ b/library/common/glfw/embedder.cc @@ -28,7 +28,7 @@ #include "library/common/internal/plugin_handler.h" #ifdef __linux__ -#include +#include #include #endif diff --git a/library/include/flutter_desktop_embedding/glfw/embedder.h b/library/include/flutter_desktop_embedding/glfw/embedder.h index 62b8bba4d..669ea9d50 100644 --- a/library/include/flutter_desktop_embedding/glfw/embedder.h +++ b/library/include/flutter_desktop_embedding/glfw/embedder.h @@ -21,7 +21,7 @@ #ifdef __linux__ // Epoxy must be included before any graphics-related code. -#include +#include #endif #include diff --git a/library/include/flutter_desktop_embedding/linux/embedder.h b/library/include/flutter_desktop_embedding/linux/embedder.h deleted file mode 100644 index 3fc973595..000000000 --- a/library/include/flutter_desktop_embedding/linux/embedder.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_LINUX_EMBEDDER_H_ -#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_LINUX_EMBEDDER_H_ - -// Epoxy must be included before any graphics-related code. -#include - -#include - -#include -#include - -#ifdef USE_FLATTENED_INCLUDES -#include "plugin.h" -#else -#include "../plugin.h" -#endif - -namespace flutter_desktop_embedding { - -// Creates a GLFW Window running a Flutter Application. -// -// glfwInit() must be called prior to this function. -// -// The arguments are to configure the paths when launching the engine. See: -// https://github.com/flutter/engine/wiki/Custom-Flutter-Engine-Embedders for -// more details on Flutter Engine embedding. -// -// Returns a null pointer in the event of an error. The caller owns the pointer -// when it is non-null. -GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height, - const std::string &main_path, - const std::string &assets_path, - const std::string &packages_path, - const std::string &icu_data_path, - const std::vector &arguments); - -// Creates a GLFW Window running a Flutter Application in snapshot mode. -// -// glfwInit() must be called prior to this function. -// -// In snapshot mode the assets directory snapshot is used to run the application -// instead of the sources. -// -// The arguments are to configure the paths when launching the engine. See: -// https://github.com/flutter/engine/wiki/Custom-Flutter-Engine-Embedders for -// more details on Flutter Engine embedding. -// -// Returns a null pointer in the event of an error. The caller owns the pointer -// when it is non-null. -GLFWwindow *CreateFlutterWindowInSnapshotMode( - size_t initial_width, size_t initial_height, const std::string &assets_path, - const std::string &icu_data_path, - const std::vector &arguments); - -// Adds a plugin to the flutter_window. -// -// If a plugin already exists for this plugin's channel, returns false. -// Otherwise returns true. -bool AddPlugin(GLFWwindow *flutter_window, std::unique_ptr plugin); - -// Loops on flutter window events until termination. -// -// Must be used instead of glfwWindowShouldClose as it cleans up engine state -// after termination. -// -// After this function the user must eventually call glfwTerminate() if doing -// cleanup. -void FlutterWindowLoop(GLFWwindow *flutter_window); - -} // namespace flutter_desktop_embedding - -#endif // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_LINUX_EMBEDDER_H_ diff --git a/library/linux/Makefile b/library/linux/Makefile index 7c7f4db47..6a5810892 100644 --- a/library/linux/Makefile +++ b/library/linux/Makefile @@ -36,7 +36,7 @@ LDFLAGS= -L$(CURDIR) \ LIBRARIES=$(FLUTTER_ENGINE_LIB_FILE) HEADERS=$(shell find $(PROJECT_ROOT)/library/include/ -type f -name '*.h') \ $(FLUTTER_ENGINE_HEADER_DIR)/$(FLUTTER_ENGINE_HEADER) -SOURCES=$(shell find src/ $(PROJECT_ROOT)/library/common/ -type f -name '*.cc') +SOURCES=$(shell find $(PROJECT_ROOT)/library/common/ -type f -name '*.cc') .PHONY: all all: $(LIBRARY_OUT) diff --git a/library/linux/src/embedder.cc b/library/linux/src/embedder.cc deleted file mode 100644 index b793464a2..000000000 --- a/library/linux/src/embedder.cc +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2018 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include "library/common/glfw/key_event_handler.h" -#include "library/common/glfw/keyboard_hook_handler.h" -#include "library/common/glfw/text_input_plugin.h" -#include "library/common/internal/plugin_handler.h" - -// GLFW_TRUE & GLFW_FALSE are introduced since libglfw-3.3, -// add definitions here to compile under the old versions. -#ifndef GLFW_TRUE -#define GLFW_TRUE 1 -#endif -#ifndef GLFW_FALSE -#define GLFW_FALSE 0 -#endif - -static_assert(FLUTTER_ENGINE_VERSION == 1, ""); - -// Struct for storing state within an instance of the GLFW Window. -struct FlutterEmbedderState { - FlutterEngine engine; - std::unique_ptr plugin_handler; - - // plugin_handler owns these pointers. Destruction happens when this struct is - // deleted from the heap. - std::vector - keyboard_hook_handlers; - // Handles raw key interactions from GLFW. - // TODO: Move key_event_handler once - // https://github.com/google/flutter-desktop-embedding/issues/102 is resolved. - std::unique_ptr key_event_handler; -}; - -static constexpr char kDefaultWindowTitle[] = "Flutter"; - -// Callback forward declarations. -static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode, - int action, int mods); -static void GLFWCharCallback(GLFWwindow *window, unsigned int code_point); -static void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action, - int mods); - -static FlutterEmbedderState *GetSavedEmbedderState(GLFWwindow *window) { - return reinterpret_cast( - glfwGetWindowUserPointer(window)); -} - -// Flushes event queue and then assigns default window callbacks. -static void GLFWAssignEventCallbacks(GLFWwindow *window) { - glfwPollEvents(); - glfwSetKeyCallback(window, GLFWKeyCallback); - glfwSetCharCallback(window, GLFWCharCallback); - glfwSetMouseButtonCallback(window, GLFWmouseButtonCallback); -} - -// Clears default window events. -static void GLFWClearEventCallbacks(GLFWwindow *window) { - glfwSetKeyCallback(window, nullptr); - glfwSetCharCallback(window, nullptr); - glfwSetMouseButtonCallback(window, nullptr); -} - -static 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; - auto state = GetSavedEmbedderState(window); - FlutterEngineSendWindowMetricsEvent(state->engine, &event); -} - -static void GLFWOnFlutterPlatformMessage(const FlutterPlatformMessage *message, - void *user_data) { - if (message->struct_size != sizeof(FlutterPlatformMessage)) { - std::cerr << "Invalid message size received. Expected: " - << sizeof(FlutterPlatformMessage) << " but received " - << message->struct_size << std::endl; - return; - } - - GLFWwindow *window = reinterpret_cast(user_data); - auto state = GetSavedEmbedderState(window); - state->plugin_handler->HandleMethodCallMessage( - message, [window] { GLFWClearEventCallbacks(window); }, - [window] { GLFWAssignEventCallbacks(window); }); -} - -static 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::high_resolution_clock::now().time_since_epoch()) - .count(); - auto state = GetSavedEmbedderState(window); - FlutterEngineSendPointerEvent(state->engine, &event, 1); -} - -static void GLFWcursorPositionCallback(GLFWwindow *window, double x, double y) { - GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kMove, x, y); -} - -static void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action, - int mods) { - double x, y; - if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS) { - glfwGetCursorPos(window, &x, &y); - GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kDown, x, y); - glfwSetCursorPosCallback(window, GLFWcursorPositionCallback); - } - if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_RELEASE) { - glfwGetCursorPos(window, &x, &y); - GLFWcursorPositionCallbackAtPhase(window, FlutterPointerPhase::kUp, x, y); - glfwSetCursorPosCallback(window, nullptr); - } -} - -static void GLFWCharCallback(GLFWwindow *window, unsigned int code_point) { - for (flutter_desktop_embedding::KeyboardHookHandler *handler : - GetSavedEmbedderState(window)->keyboard_hook_handlers) { - handler->CharHook(window, code_point); - } -} - -static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode, - int action, int mods) { - for (flutter_desktop_embedding::KeyboardHookHandler *handler : - GetSavedEmbedderState(window)->keyboard_hook_handlers) { - handler->KeyboardHook(window, key, scancode, action, mods); - } -} - -static bool GLFWMakeContextCurrent(void *user_data) { - GLFWwindow *window = reinterpret_cast(user_data); - glfwMakeContextCurrent(window); - return true; -} - -static bool GLFWClearContext(void *user_data) { - glfwMakeContextCurrent(nullptr); - return true; -} - -static bool GLFWPresent(void *user_data) { - GLFWwindow *window = reinterpret_cast(user_data); - glfwSwapBuffers(window); - return true; -} - -static uint32_t GLFWGetActiveFbo(void *user_data) { return 0; } - -// Clears the GLFW window to Material Blue-Grey. -// -// This function is primarily to fix an issue when the Flutter Engine is -// spinning up, wherein artifacts of existing windows are rendered onto the -// canvas for a few moments. -// -// This function isn't necessary, but makes starting the window much easier on -// the eyes. -static void GLFWClearCanvas(GLFWwindow *window) { - glfwMakeContextCurrent(window); - // This color is Material Blue Grey. - glClearColor(0.92549, 0.93725, 0.9451, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glFlush(); - glfwSwapBuffers(window); - glfwMakeContextCurrent(nullptr); -} - -// Spins up an instance of the Flutter Engine. -// -// This function launches the Flutter Engine in a background thread, supplying -// the necessary callbacks for rendering within a GLFWwindow. -// -// Returns a caller-owned pointer to the engine. -static FlutterEngine RunFlutterEngine( - GLFWwindow *window, const std::string &main_path, - const std::string &assets_path, const std::string &packages_path, - const std::string &icu_data_path, - const std::vector &arguments) { - std::vector argv; - std::transform( - arguments.begin(), arguments.end(), std::back_inserter(argv), - [](const std::string &arg) -> const char * { return arg.c_str(); }); - - FlutterRendererConfig config = {}; - config.type = kOpenGL; - config.open_gl.struct_size = sizeof(config.open_gl); - config.open_gl.make_current = GLFWMakeContextCurrent; - config.open_gl.clear_current = GLFWClearContext; - config.open_gl.present = GLFWPresent; - config.open_gl.fbo_callback = GLFWGetActiveFbo; - FlutterProjectArgs args = {}; - args.struct_size = sizeof(FlutterProjectArgs); - args.assets_path = assets_path.c_str(); - args.main_path = main_path.c_str(); - args.packages_path = packages_path.c_str(); - args.icu_data_path = icu_data_path.c_str(); - args.command_line_argc = argv.size(); - args.command_line_argv = &argv[0]; - args.platform_message_callback = GLFWOnFlutterPlatformMessage; - FlutterEngine engine = nullptr; - auto result = - FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, &args, window, &engine); - if (result != kSuccess || engine == nullptr) { - return nullptr; - } - return engine; -} - -namespace flutter_desktop_embedding { - -bool AddPlugin(GLFWwindow *flutter_window, std::unique_ptr plugin) { - auto state = GetSavedEmbedderState(flutter_window); - return state->plugin_handler->AddPlugin(std::move(plugin)); -} - -GLFWwindow *CreateFlutterWindowInSnapshotMode( - size_t initial_width, size_t initial_height, const std::string &assets_path, - const std::string &icu_data_path, - const std::vector &arguments) { - return CreateFlutterWindow(initial_width, initial_height, "", assets_path, "", - icu_data_path, arguments); -} - -GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height, - const std::string &main_path, - const std::string &assets_path, - const std::string &packages_path, - const std::string &icu_data_path, - const std::vector &arguments) { - gtk_init(0, nullptr); - auto window = glfwCreateWindow(initial_width, initial_height, - kDefaultWindowTitle, NULL, NULL); - if (window == nullptr) { - return nullptr; - } - GLFWClearCanvas(window); - auto engine = RunFlutterEngine(window, main_path, assets_path, packages_path, - icu_data_path, arguments); - if (engine == nullptr) { - glfwDestroyWindow(window); - return nullptr; - } - FlutterEmbedderState *state = new FlutterEmbedderState(); - state->plugin_handler = std::make_unique(engine); - state->engine = engine; - - state->key_event_handler = - std::make_unique(state->plugin_handler.get()); - state->keyboard_hook_handlers.push_back(state->key_event_handler.get()); - auto input_plugin = std::make_unique(); - state->keyboard_hook_handlers.push_back(input_plugin.get()); - - glfwSetWindowUserPointer(window, state); - - AddPlugin(window, std::move(input_plugin)); - - int width, height; - glfwGetWindowSize(window, &width, &height); - GLFWwindowSizeCallback(window, width, height); - glfwSetWindowSizeCallback(window, GLFWwindowSizeCallback); - GLFWAssignEventCallbacks(window); - return window; -} - -void FlutterWindowLoop(GLFWwindow *flutter_window) { - // Necessary for GTK thread safety. - XInitThreads(); - while (!glfwWindowShouldClose(flutter_window)) { - glfwPollEvents(); - if (gtk_events_pending()) { - gtk_main_iteration(); - } - // TODO(awdavies): This will be deprecated soon. - __FlutterEngineFlushPendingTasksNow(); - } - auto state = GetSavedEmbedderState(flutter_window); - FlutterEngineShutdown(state->engine); - delete state; - glfwDestroyWindow(flutter_window); -} - -} // namespace flutter_desktop_embedding From d5326588962f7ae569345e66834a3a500ce83ccd Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 2 Jan 2019 14:06:51 -0500 Subject: [PATCH 4/4] Add comment about Linux includes --- library/common/glfw/embedder.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/library/common/glfw/embedder.cc b/library/common/glfw/embedder.cc index c9a7c867c..c2a0b6460 100644 --- a/library/common/glfw/embedder.cc +++ b/library/common/glfw/embedder.cc @@ -28,6 +28,7 @@ #include "library/common/internal/plugin_handler.h" #ifdef __linux__ +// For plugin-compatible event handling (e.g., modal windows). #include #include #endif