Flutter Engine
The Flutter Engine
flutter_glfw.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 "flutter/shell/platform/glfw/public/flutter_glfw.h"
6
7#include <GLFW/glfw3.h>
8
9#include <algorithm>
10#include <cassert>
11#include <chrono>
12#include <cstdlib>
13#include <filesystem>
14#include <iostream>
15#include <string>
16
17#include "flutter/common/constants.h"
18#include "flutter/shell/platform/common/client_wrapper/include/flutter/plugin_registrar.h"
19#include "flutter/shell/platform/common/incoming_message_dispatcher.h"
20#include "flutter/shell/platform/common/path_utils.h"
21#include "flutter/shell/platform/embedder/embedder.h"
22#include "flutter/shell/platform/glfw/glfw_event_loop.h"
23#include "flutter/shell/platform/glfw/headless_event_loop.h"
24#include "flutter/shell/platform/glfw/key_event_handler.h"
25#include "flutter/shell/platform/glfw/keyboard_hook_handler.h"
26#include "flutter/shell/platform/glfw/platform_handler.h"
27#include "flutter/shell/platform/glfw/system_utils.h"
28#include "flutter/shell/platform/glfw/text_input_plugin.h"
29
30// GLFW_TRUE & GLFW_FALSE are introduced since libglfw-3.3,
31// add definitions here to compile under the old versions.
32#ifndef GLFW_TRUE
33#define GLFW_TRUE 1
34#endif
35#ifndef GLFW_FALSE
36#define GLFW_FALSE 0
37#endif
38
39using UniqueGLFWwindowPtr = std::unique_ptr<GLFWwindow, void (*)(GLFWwindow*)>;
40
41static_assert(FLUTTER_ENGINE_VERSION == 1, "");
42
43const int kFlutterDesktopDontCare = GLFW_DONT_CARE;
44
45static constexpr double kDpPerInch = 160.0;
46
47// Struct for storing state within an instance of the GLFW Window.
49 // The GLFW window that is bound to this state object.
50 UniqueGLFWwindowPtr window = UniqueGLFWwindowPtr(nullptr, glfwDestroyWindow);
51
52 // The invisible GLFW window used to upload resources in the background.
54 UniqueGLFWwindowPtr(nullptr, glfwDestroyWindow);
55
56 // The state associated with the engine.
57 std::unique_ptr<FlutterDesktopEngineState> engine;
58
59 // The window handle given to API clients.
60 std::unique_ptr<FlutterDesktopWindow> window_wrapper;
61
62 // Handlers for keyboard events from GLFW.
63 std::vector<std::unique_ptr<flutter::KeyboardHookHandler>>
65
66 // Whether or not the pointer has been added (or if tracking is enabled,
67 // has been added since it was last removed).
69
70 // Whether or not the pointer is down.
72
73 // The currently pressed buttons, as represented in FlutterPointerEvent.
74 int64_t buttons = 0;
75
76 // The screen coordinates per inch on the primary monitor. Defaults to a sane
77 // value based on pixel_ratio 1.0.
79};
80
81// Opaque reference for the GLFW window itself. This is separate from the
82// controller so that it can be provided to plugins without giving them access
83// to all of the controller-based functionality.
85 // The GLFW window that (indirectly) owns this state object.
86 GLFWwindow* window;
87
88 // Whether or not to track mouse movements to send kHover events.
90
91 // The ratio of pixels per screen coordinate for the window.
93
94 // If non-zero, a forced pixel ratio to use instead of one computed based on
95 // screen information.
97
98 // Resizing triggers a window refresh, but the resize already updates Flutter.
99 // To avoid double messages, the refresh after each resize is skipped.
101};
102
103// Custom deleter for FlutterEngineAOTData.
107 }
108};
109
110using UniqueAotDataPtr = std::unique_ptr<_FlutterEngineAOTData, AOTDataDeleter>;
111/// Maintains one ref on the FlutterDesktopMessenger's internal reference count.
113 std::unique_ptr<FlutterDesktopMessenger,
115
116// Struct for storing state of a Flutter engine instance.
118 // The handle to the Flutter engine instance.
120
121 // The event loop for the main thread that allows for delayed task execution.
122 std::unique_ptr<flutter::EventLoop> event_loop;
123
124 // The plugin messenger handle given to API clients.
126 nullptr, [](FlutterDesktopMessengerRef ref) {}};
127
128 // Message dispatch manager for messages from the Flutter engine.
129 std::unique_ptr<flutter::IncomingMessageDispatcher> message_dispatcher;
130
131 // The plugin registrar handle given to API clients.
132 std::unique_ptr<FlutterDesktopPluginRegistrar> plugin_registrar;
133
134 // The plugin registrar managing internal plugins.
135 std::unique_ptr<flutter::PluginRegistrar> internal_plugin_registrar;
136
137 // Handler for the flutter/platform channel.
138 std::unique_ptr<flutter::PlatformHandler> platform_handler;
139
140 // The controller associated with this engine instance, if any.
141 // This will always be null for a headless engine.
143
144 // AOT data for this engine instance, if applicable.
146};
147
148// State associated with the plugin registrar.
150 // The engine that backs this registrar.
152
153 // Callback to be called on registrar destruction.
155};
156
157// State associated with the messenger used to communicate with the engine.
160
161 /// Increments the reference count.
162 ///
163 /// Thread-safe.
164 void AddRef() { ref_count_.fetch_add(1); }
165
166 /// Decrements the reference count and deletes the object if the count has
167 /// gone to zero.
168 ///
169 /// Thread-safe.
170 void Release() {
171 int32_t old_count = ref_count_.fetch_sub(1);
172 if (old_count <= 1) {
173 delete this;
174 }
175 }
176
177 /// Getter for the engine field.
178 FlutterDesktopEngineState* GetEngine() const { return engine_; }
179
180 /// Setter for the engine field.
181 /// Thread-safe.
183 std::scoped_lock lock(mutex_);
184 engine_ = engine;
185 }
186
187 /// Returns the mutex associated with the |FlutterDesktopMessenger|.
188 ///
189 /// This mutex is used to synchronize reading or writing state inside the
190 /// |FlutterDesktopMessenger| (ie |engine_|).
191 std::mutex& GetMutex() { return mutex_; }
192
195 delete;
196
197 private:
198 // The engine that backs this messenger.
200 std::atomic<int32_t> ref_count_ = 0;
201 std::mutex mutex_;
202};
203
205 FlutterDesktopMessengerRef messenger) {
206 messenger->AddRef();
207 return messenger;
208}
209
211 messenger->Release();
212}
213
215 return messenger->GetEngine() != nullptr;
216}
217
219 FlutterDesktopMessengerRef messenger) {
220 messenger->GetMutex().lock();
221 return messenger;
222}
223
225 messenger->GetMutex().unlock();
226}
227
228// Retrieves state bag for the window in question from the GLFWWindow.
230 GLFWwindow* window) {
231 return reinterpret_cast<FlutterDesktopWindowControllerState*>(
232 glfwGetWindowUserPointer(window));
233}
234
235// Creates and returns an invisible GLFW window that shares |window|'s resource
236// context.
238 glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
239 glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
240#if defined(__linux__)
241 glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
242 glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
243 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
244#endif
245 GLFWwindow* share_window = glfwCreateWindow(1, 1, "", NULL, window);
246 glfwDefaultWindowHints();
247 return UniqueGLFWwindowPtr(share_window, glfwDestroyWindow);
248}
249
250// Converts a FlutterPlatformMessage to an equivalent FlutterDesktopMessage.
252 const FlutterPlatformMessage& engine_message) {
254 message.struct_size = sizeof(message);
255 message.channel = engine_message.channel;
256 message.message = engine_message.message;
257 message.message_size = engine_message.message_size;
258 message.response_handle = engine_message.response_handle;
259 return message;
260}
261
262// Returns the number of screen coordinates per inch for the main monitor.
263// If the information is unavailable, returns a default value that assumes
264// that a screen coordinate is one dp.
266 auto* primary_monitor = glfwGetPrimaryMonitor();
267 if (primary_monitor == nullptr) {
268 return kDpPerInch;
269 }
270 auto* primary_monitor_mode = glfwGetVideoMode(primary_monitor);
271 int primary_monitor_width_mm;
272 glfwGetMonitorPhysicalSize(primary_monitor, &primary_monitor_width_mm,
273 nullptr);
274 if (primary_monitor_width_mm == 0) {
275 return kDpPerInch;
276 }
277 return primary_monitor_mode->width / (primary_monitor_width_mm / 25.4);
278}
279
280// Sends a window metrics update to the Flutter engine using the given
281// framebuffer size and the current window information in |state|.
283 int width,
284 int height) {
285 double dpi = controller->window_wrapper->pixels_per_screen_coordinate *
287
288 FlutterWindowMetricsEvent event = {};
289 event.struct_size = sizeof(event);
290 event.width = width;
291 event.height = height;
292 if (controller->window_wrapper->pixel_ratio_override == 0.0) {
293 // The Flutter pixel_ratio is defined as DPI/dp. Limit the ratio to a
294 // minimum of 1 to avoid rendering a smaller UI on standard resolution
295 // monitors.
296 event.pixel_ratio = std::max(dpi / kDpPerInch, 1.0);
297 } else {
298 event.pixel_ratio = controller->window_wrapper->pixel_ratio_override;
299 }
300 // The GLFW embedder doesn't support multiple views. We assume all pointer
301 // events come from the only view, the implicit view.
302 event.view_id = flutter::kFlutterImplicitViewId;
303 FlutterEngineSendWindowMetricsEvent(controller->engine->flutter_engine,
304 &event);
305}
306
307// Populates |task_runner| with a description that uses |engine_state|'s event
308// loop to run tasks.
310 FlutterTaskRunnerDescription* task_runner,
311 FlutterDesktopEngineState* engine_state) {
312 task_runner->struct_size = sizeof(FlutterTaskRunnerDescription);
313 task_runner->user_data = engine_state;
314 task_runner->runs_task_on_current_thread_callback = [](void* state) -> bool {
315 return reinterpret_cast<FlutterDesktopEngineState*>(state)
316 ->event_loop->RunsTasksOnCurrentThread();
317 };
318 task_runner->post_task_callback =
319 [](FlutterTask task, uint64_t target_time_nanos, void* state) -> void {
320 reinterpret_cast<FlutterDesktopEngineState*>(state)->event_loop->PostTask(
321 task, target_time_nanos);
322 };
323}
324
325// When GLFW calls back to the window with a framebuffer size change, notify
326// FlutterEngine about the new window metrics.
327static void GLFWFramebufferSizeCallback(GLFWwindow* window,
328 int width_px,
329 int height_px) {
330 int width;
331 glfwGetWindowSize(window, &width, nullptr);
332 auto* controller = GetWindowController(window);
333 controller->window_wrapper->pixels_per_screen_coordinate =
334 width > 0 ? width_px / width : 1;
335
336 SendWindowMetrics(controller, width_px, height_px);
337 controller->window_wrapper->skip_next_window_refresh = true;
338}
339
340// Indicates that the window needs to be redrawn.
342 auto* controller = GetWindowController(window);
343 if (controller->window_wrapper->skip_next_window_refresh) {
344 controller->window_wrapper->skip_next_window_refresh = false;
345 return;
346 }
347 // There's no engine API to request a redraw explicitly, so instead send a
348 // window metrics event with the current size to trigger it.
349 int width_px, height_px;
350 glfwGetFramebufferSize(window, &width_px, &height_px);
351 if (width_px > 0 && height_px > 0) {
352 SendWindowMetrics(controller, width_px, height_px);
353 }
354}
355
356// Sends a pointer event to the Flutter engine based on the given data.
357//
358// Any coordinate/distance values in |event_data| should be in screen
359// coordinates; they will be adjusted to pixel values before being sent.
360static void SendPointerEventWithData(GLFWwindow* window,
361 const FlutterPointerEvent& event_data) {
362 auto* controller = GetWindowController(window);
363 // If sending anything other than an add, and the pointer isn't already added,
364 // synthesize an add to satisfy Flutter's expectations about events.
365 if (!controller->pointer_currently_added &&
366 event_data.phase != FlutterPointerPhase::kAdd) {
367 FlutterPointerEvent event = {};
369 event.x = event_data.x;
370 event.y = event_data.y;
372 }
373 // Don't double-add (e.g., if events are delivered out of order, so an add has
374 // already been synthesized).
375 if (controller->pointer_currently_added &&
376 event_data.phase == FlutterPointerPhase::kAdd) {
377 return;
378 }
379
380 FlutterPointerEvent event = event_data;
381 // Set metadata that's always the same regardless of the event.
382 event.struct_size = sizeof(event);
383 event.timestamp =
384 std::chrono::duration_cast<std::chrono::microseconds>(
385 std::chrono::high_resolution_clock::now().time_since_epoch())
386 .count();
388 event.buttons =
389 (event.phase == FlutterPointerPhase::kAdd) ? 0 : controller->buttons;
390
391 // Convert all screen coordinates to pixel coordinates.
392 double pixels_per_coordinate =
393 controller->window_wrapper->pixels_per_screen_coordinate;
394 event.x *= pixels_per_coordinate;
395 event.y *= pixels_per_coordinate;
396 event.scroll_delta_x *= pixels_per_coordinate;
397 event.scroll_delta_y *= pixels_per_coordinate;
398 // The GLFW embedder doesn't support multiple views. We assume all pointer
399 // events come from the only view, the implicit view.
401
402 FlutterEngineSendPointerEvent(controller->engine->flutter_engine, &event, 1);
403
404 if (event_data.phase == FlutterPointerPhase::kAdd) {
405 controller->pointer_currently_added = true;
406 } else if (event_data.phase == FlutterPointerPhase::kRemove) {
407 controller->pointer_currently_added = false;
408 } else if (event_data.phase == FlutterPointerPhase::kDown) {
409 controller->pointer_currently_down = true;
410 } else if (event_data.phase == FlutterPointerPhase::kUp) {
411 controller->pointer_currently_down = false;
412 }
413}
414
415// Updates |event_data| with the current location of the mouse cursor.
417 GLFWwindow* window,
418 FlutterPointerEvent* event_data) {
419 glfwGetCursorPos(window, &event_data->x, &event_data->y);
420}
421
422// Set's |event_data|'s phase depending on the current mouse state.
423// If a kUp or kDown event is triggered while the current state is already
424// up/down, a hover/move will be called instead to avoid a crash in the Flutter
425// engine.
427 FlutterPointerEvent* event_data,
428 int64_t buttons) {
429 auto* controller = GetWindowController(window);
430 event_data->phase =
431 (buttons == 0)
432 ? (controller->pointer_currently_down ? FlutterPointerPhase::kUp
434 : (controller->pointer_currently_down ? FlutterPointerPhase::kMove
436}
437
438// Reports the mouse entering or leaving the Flutter view.
439static void GLFWCursorEnterCallback(GLFWwindow* window, int entered) {
440 FlutterPointerEvent event = {};
441 event.phase =
445}
446
447// Reports mouse movement to the Flutter engine.
448static void GLFWCursorPositionCallback(GLFWwindow* window, double x, double y) {
449 FlutterPointerEvent event = {};
450 event.x = x;
451 event.y = y;
452 auto* controller = GetWindowController(window);
453 SetEventPhaseFromCursorButtonState(window, &event, controller->buttons);
455}
456
457// Reports mouse button press to the Flutter engine.
458static void GLFWMouseButtonCallback(GLFWwindow* window,
459 int key,
460 int action,
461 int mods) {
462 int64_t button;
463 if (key == GLFW_MOUSE_BUTTON_LEFT) {
465 } else if (key == GLFW_MOUSE_BUTTON_RIGHT) {
467 } else {
468 return;
469 }
470
471 auto* controller = GetWindowController(window);
472 controller->buttons = (action == GLFW_PRESS) ? controller->buttons | button
473 : controller->buttons & ~button;
474
476 SetEventPhaseFromCursorButtonState(window, &event, controller->buttons);
479
480 // If mouse tracking isn't already enabled, turn it on for the duration of
481 // the drag to generate kMove events.
482 bool hover_enabled =
483 GetWindowController(window)->window_wrapper->hover_tracking_enabled;
484 if (!hover_enabled) {
485 glfwSetCursorPosCallback(window, (controller->buttons != 0)
487 : nullptr);
488 }
489 // Disable enter/exit events while the mouse button is down; GLFW will send
490 // an exit event when the mouse button is released, and the pointer should
491 // stay valid until then.
492 if (hover_enabled) {
493 glfwSetCursorEnterCallback(
494 window, (controller->buttons != 0) ? nullptr : GLFWCursorEnterCallback);
495 }
496}
497
498// Reports scroll wheel events to the Flutter engine.
499static void GLFWScrollCallback(GLFWwindow* window,
500 double delta_x,
501 double delta_y) {
502 FlutterPointerEvent event = {};
504 auto* controller = GetWindowController(window);
505 SetEventPhaseFromCursorButtonState(window, &event, controller->buttons);
507 // TODO(chrome-bot): See if this can be queried from the OS; this value is
508 // chosen arbitrarily to get something that feels reasonable.
509 const int kScrollOffsetMultiplier = 20;
510 event.scroll_delta_x = delta_x * kScrollOffsetMultiplier;
511 event.scroll_delta_y = -delta_y * kScrollOffsetMultiplier;
513}
514
515// Passes character input events to registered handlers.
516static void GLFWCharCallback(GLFWwindow* window, unsigned int code_point) {
517 for (const auto& handler :
518 GetWindowController(window)->keyboard_hook_handlers) {
519 handler->CharHook(window, code_point);
520 }
521}
522
523// Passes raw key events to registered handlers.
524static void GLFWKeyCallback(GLFWwindow* window,
525 int key,
526 int scancode,
527 int action,
528 int mods) {
529 for (const auto& handler :
530 GetWindowController(window)->keyboard_hook_handlers) {
531 handler->KeyboardHook(window, key, scancode, action, mods);
532 }
533}
534
535// Enables/disables the callbacks related to mouse tracking.
536static void SetHoverCallbacksEnabled(GLFWwindow* window, bool enabled) {
537 glfwSetCursorEnterCallback(window,
538 enabled ? GLFWCursorEnterCallback : nullptr);
539 glfwSetCursorPosCallback(window,
540 enabled ? GLFWCursorPositionCallback : nullptr);
541}
542
543// Flushes event queue and then assigns default window callbacks.
544static void GLFWAssignEventCallbacks(GLFWwindow* window) {
545 glfwPollEvents();
546 glfwSetKeyCallback(window, GLFWKeyCallback);
547 glfwSetCharCallback(window, GLFWCharCallback);
548 glfwSetMouseButtonCallback(window, GLFWMouseButtonCallback);
549 glfwSetScrollCallback(window, GLFWScrollCallback);
550 if (GetWindowController(window)->window_wrapper->hover_tracking_enabled) {
552 }
553}
554
555// Clears default window events.
556static void GLFWClearEventCallbacks(GLFWwindow* window) {
557 glfwSetKeyCallback(window, nullptr);
558 glfwSetCharCallback(window, nullptr);
559 glfwSetMouseButtonCallback(window, nullptr);
560 glfwSetScrollCallback(window, nullptr);
562}
563
564// The Flutter Engine calls out to this function when new platform messages are
565// available
567 const FlutterPlatformMessage* engine_message,
568 void* user_data) {
569 if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) {
570 std::cerr << "Invalid message size received. Expected: "
571 << sizeof(FlutterPlatformMessage) << " but received "
572 << engine_message->struct_size << std::endl;
573 return;
574 }
575
576 FlutterDesktopEngineState* engine_state =
578 GLFWwindow* window = engine_state->window_controller == nullptr
579 ? nullptr
580 : engine_state->window_controller->window.get();
581
582 auto message = ConvertToDesktopMessage(*engine_message);
583 engine_state->message_dispatcher->HandleMessage(
584 message,
585 [window] {
586 if (window) {
588 }
589 },
590 [window] {
591 if (window) {
593 }
594 });
595}
596
598 FlutterDesktopEngineState* engine_state =
600 FlutterDesktopWindowControllerState* window_controller =
601 engine_state->window_controller;
602 if (!window_controller) {
603 return false;
604 }
605 glfwMakeContextCurrent(window_controller->window.get());
606 return true;
607}
608
610 FlutterDesktopEngineState* engine_state =
612 FlutterDesktopWindowControllerState* window_controller =
613 engine_state->window_controller;
614 if (!window_controller) {
615 return false;
616 }
617 glfwMakeContextCurrent(window_controller->resource_window.get());
618 return true;
619}
620
621static bool EngineClearContext(void* user_data) {
622 FlutterDesktopEngineState* engine_state =
624 FlutterDesktopWindowControllerState* window_controller =
625 engine_state->window_controller;
626 if (!window_controller) {
627 return false;
628 }
629 glfwMakeContextCurrent(nullptr);
630 return true;
631}
632
633static bool EnginePresent(void* user_data) {
634 FlutterDesktopEngineState* engine_state =
636 FlutterDesktopWindowControllerState* window_controller =
637 engine_state->window_controller;
638 if (!window_controller) {
639 return false;
640 }
641 glfwSwapBuffers(window_controller->window.get());
642 return true;
643}
644
645static uint32_t EngineGetActiveFbo(void* user_data) {
646 return 0;
647}
648
649// Resolves the address of the specified OpenGL or OpenGL ES
650// core or extension function, if it is supported by the current context.
651static void* EngineProcResolver(void* user_data, const char* name) {
652 return reinterpret_cast<void*>(glfwGetProcAddress(name));
653}
654
655// Clears the GLFW window to Material Blue-Grey.
656//
657// This function is primarily to fix an issue when the Flutter Engine is
658// spinning up, wherein artifacts of existing windows are rendered onto the
659// canvas for a few moments.
660//
661// This function isn't necessary, but makes starting the window much easier on
662// the eyes.
663static void GLFWClearCanvas(GLFWwindow* window) {
664 glfwMakeContextCurrent(window);
665 // This color is Material Blue Grey.
666 glClearColor(236.0f / 255.0f, 239.0f / 255.0f, 241.0f / 255.0f, 0.0f);
667 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
668 glFlush();
669 glfwSwapBuffers(window);
670 glfwMakeContextCurrent(nullptr);
671}
672
673static void GLFWErrorCallback(int error_code, const char* description) {
674 std::cerr << "GLFW error " << error_code << ": " << description << std::endl;
675}
676
677// Attempts to load AOT data from the given path, which must be absolute and
678// non-empty. Logs and returns nullptr on failure.
680 if (aot_data_path.empty()) {
681 std::cerr
682 << "Attempted to load AOT data, but no aot_data_path was provided."
683 << std::endl;
684 return nullptr;
685 }
686 std::string path_string = aot_data_path.string();
687 if (!std::filesystem::exists(aot_data_path)) {
688 std::cerr << "Can't load AOT data from " << path_string << "; no such file."
689 << std::endl;
690 return nullptr;
691 }
694 source.elf_path = path_string.c_str();
695 FlutterEngineAOTData data = nullptr;
697 if (result != kSuccess) {
698 std::cerr << "Failed to load AOT data from: " << path_string << std::endl;
699 return nullptr;
700 }
701 return UniqueAotDataPtr(data);
702}
703
704// Starts an instance of the Flutter Engine.
705//
706// Configures the engine according to |engine_propreties| and using |event_loop|
707// to schedule engine tasks.
708//
709// Returns true on success, in which case |engine_state|'s 'engine' field will
710// be updated to point to the started engine.
712 FlutterDesktopEngineState* engine_state,
713 const FlutterDesktopEngineProperties& engine_properties,
714 std::unique_ptr<flutter::EventLoop> event_loop) {
715 // FlutterProjectArgs is expecting a full argv, so when processing it for
716 // flags the first item is treated as the executable and ignored. Add a dummy
717 // value so that all provided arguments are used.
718 std::vector<const char*> argv = {"placeholder"};
719 if (engine_properties.switches_count > 0) {
720 argv.insert(argv.end(), &engine_properties.switches[0],
721 &engine_properties.switches[engine_properties.switches_count]);
722 }
723
724 std::filesystem::path assets_path =
725 std::filesystem::u8path(engine_properties.assets_path);
726 std::filesystem::path icu_path =
727 std::filesystem::u8path(engine_properties.icu_data_path);
728 std::filesystem::path aot_library_path =
729 std::filesystem::u8path(engine_properties.aot_library_path);
730 if (assets_path.is_relative() || icu_path.is_relative() ||
731 (!aot_library_path.empty() && aot_library_path.is_relative())) {
732 // Treat relative paths as relative to the directory of this executable.
733 std::filesystem::path executable_location =
735 if (executable_location.empty()) {
736 std::cerr << "Unable to find executable location to resolve paths."
737 << std::endl;
738 return false;
739 }
740 assets_path = std::filesystem::path(executable_location) / assets_path;
741 icu_path = std::filesystem::path(executable_location) / icu_path;
742 if (!aot_library_path.empty()) {
743 aot_library_path =
744 std::filesystem::path(executable_location) / aot_library_path;
745 }
746 }
747 // Configure a task runner using the event loop.
748 engine_state->event_loop = std::move(event_loop);
749 FlutterTaskRunnerDescription platform_task_runner = {};
750 ConfigurePlatformTaskRunner(&platform_task_runner, engine_state);
751 FlutterCustomTaskRunners task_runners = {};
752 task_runners.struct_size = sizeof(FlutterCustomTaskRunners);
753 task_runners.platform_task_runner = &platform_task_runner;
754
755 FlutterRendererConfig config = {};
756 config.type = kOpenGL;
757 config.open_gl.struct_size = sizeof(config.open_gl);
763 // Don't provide a resolver in headless mode, since headless mode should
764 // work even if GLFW initialization failed.
765 if (engine_state->window_controller != nullptr) {
767 }
768 const std::string assets_path_string = assets_path.string();
769 const std::string icu_path_string = icu_path.string();
771 args.struct_size = sizeof(FlutterProjectArgs);
772 args.assets_path = assets_path_string.c_str();
773 args.icu_data_path = icu_path_string.c_str();
774 args.command_line_argc = static_cast<int>(argv.size());
775 args.command_line_argv = &argv[0];
776 args.platform_message_callback = EngineOnFlutterPlatformMessage;
777 args.custom_task_runners = &task_runners;
778
780 engine_state->aot_data = LoadAotData(aot_library_path);
781 if (!engine_state->aot_data) {
782 std::cerr << "Unable to start engine without AOT data." << std::endl;
783 return false;
784 }
785 args.aot_data = engine_state->aot_data.get();
786 }
787
790 engine_state, &engine);
791 if (result != kSuccess || engine == nullptr) {
792 std::cerr << "Failed to start Flutter engine: error " << result
793 << std::endl;
794 return false;
795 }
796 engine_state->flutter_engine = engine;
797 return true;
798}
799
800// Passes locale information to the Flutter engine.
802 std::vector<flutter::LanguageInfo> languages =
804 std::vector<FlutterLocale> flutter_locales =
806 // Convert the locale list to the locale pointer list that must be provided.
807 std::vector<const FlutterLocale*> flutter_locale_list;
808 flutter_locale_list.reserve(flutter_locales.size());
809 std::transform(flutter_locales.begin(), flutter_locales.end(),
810 std::back_inserter(flutter_locale_list),
811 [](const auto& arg) -> const auto* { return &arg; });
813 state->flutter_engine, flutter_locale_list.data(),
814 flutter_locale_list.size());
815 if (result != kSuccess) {
816 std::cerr << "Failed to set up Flutter locales." << std::endl;
817 }
818}
819
820// Populates |state|'s helper object fields that are common to normal and
821// headless mode.
822//
823// Window is optional; if present it will be provided to the created
824// PlatformHandler.
826 GLFWwindow* window) {
827 // Messaging.
831 state->messenger->SetEngine(state);
832 state->message_dispatcher =
833 std::make_unique<flutter::IncomingMessageDispatcher>(
834 state->messenger.get());
835
836 // Plugins.
837 state->plugin_registrar = std::make_unique<FlutterDesktopPluginRegistrar>();
838 state->plugin_registrar->engine = state;
839 state->internal_plugin_registrar =
840 std::make_unique<flutter::PluginRegistrar>(state->plugin_registrar.get());
841
842 // System channel handler.
843 state->platform_handler = std::make_unique<flutter::PlatformHandler>(
844 state->internal_plugin_registrar->messenger(), window);
845
847}
848
850 // Before making any GLFW calls, set up a logging error handler.
851 glfwSetErrorCallback(GLFWErrorCallback);
852 return glfwInit();
853}
854
856 glfwTerminate();
857}
858
860 const FlutterDesktopWindowProperties& window_properties,
861 const FlutterDesktopEngineProperties& engine_properties) {
862 auto state = std::make_unique<FlutterDesktopWindowControllerState>();
863
864 // Create the window, and set the state as its user data.
865 if (window_properties.prevent_resize) {
866 glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
867 }
868#if defined(__linux__)
869 glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
870#endif
871 state->window = UniqueGLFWwindowPtr(
872 glfwCreateWindow(window_properties.width, window_properties.height,
873 window_properties.title, NULL, NULL),
874 glfwDestroyWindow);
875 glfwDefaultWindowHints();
876 GLFWwindow* window = state->window.get();
877 if (window == nullptr) {
878 return nullptr;
879 }
881 glfwSetWindowUserPointer(window, state.get());
882
883 // Create the share window before starting the engine, since it may call
884 // EngineMakeResourceContextCurrent immediately.
885 state->resource_window = CreateShareWindowForWindow(window);
886
887 state->engine = std::make_unique<FlutterDesktopEngineState>();
888 state->engine->window_controller = state.get();
889
890 // Create an event loop for the window. It is not running yet.
891 auto event_loop = std::make_unique<flutter::GLFWEventLoop>(
892 std::this_thread::get_id(), // main GLFW thread
893 [engine_state = state->engine.get()](const auto* task) {
894 if (FlutterEngineRunTask(engine_state->flutter_engine, task) !=
895 kSuccess) {
896 std::cerr << "Could not post an engine task." << std::endl;
897 }
898 });
899
900 // Start the engine.
901 if (!RunFlutterEngine(state->engine.get(), engine_properties,
902 std::move(event_loop))) {
903 return nullptr;
904 }
905 SetUpCommonEngineState(state->engine.get(), window);
906
907 state->window_wrapper = std::make_unique<FlutterDesktopWindow>();
908 state->window_wrapper->window = window;
909
910 // Set up the keyboard handlers
911 auto internal_plugin_messenger =
912 state->engine->internal_plugin_registrar->messenger();
913 state->keyboard_hook_handlers.push_back(
914 std::make_unique<flutter::KeyEventHandler>(internal_plugin_messenger));
915 state->keyboard_hook_handlers.push_back(
916 std::make_unique<flutter::TextInputPlugin>(internal_plugin_messenger));
917
918 // Trigger an initial size callback to send size information to Flutter.
919 state->monitor_screen_coordinates_per_inch = GetScreenCoordinatesPerInch();
920 int width_px, height_px;
921 glfwGetFramebufferSize(window, &width_px, &height_px);
922 GLFWFramebufferSizeCallback(window, width_px, height_px);
923
924 // Set up GLFW callbacks for the window.
925 glfwSetFramebufferSizeCallback(window, GLFWFramebufferSizeCallback);
926 glfwSetWindowRefreshCallback(window, GLFWWindowRefreshCallback);
928
929 return state.release();
930}
931
933 controller->engine->messenger->SetEngine(nullptr);
935 controller->engine->plugin_registrar.get();
936 if (registrar->destruction_handler) {
937 registrar->destruction_handler(registrar);
938 }
939 FlutterEngineShutdown(controller->engine->flutter_engine);
940 delete controller;
941}
942
944 bool enabled) {
945 flutter_window->hover_tracking_enabled = enabled;
946 SetHoverCallbacksEnabled(flutter_window->window, enabled);
947}
948
950 const char* title) {
951 GLFWwindow* window = flutter_window->window;
952 glfwSetWindowTitle(window, title);
953}
954
956 uint8_t* pixel_data,
957 int width,
958 int height) {
959 GLFWimage image = {width, height, static_cast<unsigned char*>(pixel_data)};
960 glfwSetWindowIcon(flutter_window->window, pixel_data ? 1 : 0, &image);
961}
962
964 int* x,
965 int* y,
966 int* width,
967 int* height) {
968 glfwGetWindowPos(flutter_window->window, x, y);
969 glfwGetWindowSize(flutter_window->window, width, height);
970 // The above gives content area size and position; adjust for the window
971 // decoration to give actual window frame.
972 int frame_left, frame_top, frame_right, frame_bottom;
973 glfwGetWindowFrameSize(flutter_window->window, &frame_left, &frame_top,
974 &frame_right, &frame_bottom);
975 if (x) {
976 *x -= frame_left;
977 }
978 if (y) {
979 *y -= frame_top;
980 }
981 if (width) {
982 *width += frame_left + frame_right;
983 }
984 if (height) {
985 *height += frame_top + frame_bottom;
986 }
987}
988
990 int x,
991 int y,
992 int width,
993 int height) {
994 // Get the window decoration sizes to adjust, since the GLFW setters take
995 // content position and size.
996 int frame_left, frame_top, frame_right, frame_bottom;
997 glfwGetWindowFrameSize(flutter_window->window, &frame_left, &frame_top,
998 &frame_right, &frame_bottom);
999 glfwSetWindowPos(flutter_window->window, x + frame_left, y + frame_top);
1000 glfwSetWindowSize(flutter_window->window, width - frame_left - frame_right,
1001 height - frame_top - frame_bottom);
1002}
1003
1005 FlutterDesktopWindowRef flutter_window) {
1006 return flutter_window->pixels_per_screen_coordinate;
1007}
1008
1010 FlutterDesktopWindowRef flutter_window,
1011 double pixel_ratio) {
1012 flutter_window->pixel_ratio_override = pixel_ratio;
1013 // Send a metrics update using the new pixel ratio.
1014 int width_px, height_px;
1015 glfwGetFramebufferSize(flutter_window->window, &width_px, &height_px);
1016 if (width_px > 0 && height_px > 0) {
1017 auto* controller = GetWindowController(flutter_window->window);
1018 SendWindowMetrics(controller, width_px, height_px);
1019 }
1020}
1021
1023 FlutterDesktopSize minimum_size,
1024 FlutterDesktopSize maximum_size) {
1025 glfwSetWindowSizeLimits(flutter_window->window, minimum_size.width,
1026 minimum_size.height, maximum_size.width,
1027 maximum_size.height);
1028}
1029
1032 uint32_t timeout_milliseconds) {
1034 timeout_milliseconds);
1035 return !glfwWindowShouldClose(controller->window.get());
1036}
1037
1040 // Currently, one registrar acts as the registrar for all plugins, so the
1041 // name is ignored. It is part of the API to reduce churn in the future when
1042 // aligning more closely with the Flutter registrar system.
1043 return controller->window_wrapper.get();
1044}
1045
1048 return controller->engine.get();
1049}
1050
1053 const char* plugin_name) {
1054 // Currently, one registrar acts as the registrar for all plugins, so the
1055 // name is ignored. It is part of the API to reduce churn in the future when
1056 // aligning more closely with the Flutter registrar system.
1057 return engine->plugin_registrar.get();
1058}
1059
1061 const FlutterDesktopEngineProperties& properties) {
1062 auto engine_state = std::make_unique<FlutterDesktopEngineState>();
1063
1064 auto event_loop = std::make_unique<flutter::HeadlessEventLoop>(
1065 std::this_thread::get_id(),
1066 [state = engine_state.get()](const auto* task) {
1067 if (FlutterEngineRunTask(state->flutter_engine, task) != kSuccess) {
1068 std::cerr << "Could not post an engine task." << std::endl;
1069 }
1070 });
1071
1072 if (!RunFlutterEngine(engine_state.get(), properties,
1073 std::move(event_loop))) {
1074 return nullptr;
1075 }
1076 SetUpCommonEngineState(engine_state.get(), nullptr);
1077
1078 return engine_state.release();
1079}
1080
1083 uint32_t timeout_milliseconds) {
1084 std::chrono::nanoseconds wait_duration =
1085 timeout_milliseconds == 0
1087 : std::chrono::milliseconds(timeout_milliseconds);
1088 engine->event_loop->WaitForEvents(wait_duration);
1089}
1090
1092 auto result = FlutterEngineShutdown(engine->flutter_engine);
1093 delete engine;
1094 return (result == kSuccess);
1095}
1096
1099 const char* channel) {
1100 registrar->engine->message_dispatcher->EnableInputBlockingForChannel(channel);
1101}
1102
1105 return registrar->engine->messenger.get();
1106}
1107
1111 registrar->destruction_handler = callback;
1112}
1113
1117 registrar->engine->window_controller;
1118 if (!controller) {
1119 return nullptr;
1120 }
1121 return controller->window_wrapper.get();
1122}
1123
1125 const char* channel,
1126 const uint8_t* message,
1127 const size_t message_size,
1128 const FlutterDesktopBinaryReply reply,
1129 void* user_data) {
1130 FlutterPlatformMessageResponseHandle* response_handle = nullptr;
1131 if (reply != nullptr && user_data != nullptr) {
1133 messenger->GetEngine()->flutter_engine, reply, user_data,
1134 &response_handle);
1135 if (result != kSuccess) {
1136 std::cout << "Failed to create response handle\n";
1137 return false;
1138 }
1139 }
1140
1141 FlutterPlatformMessage platform_message = {
1142 sizeof(FlutterPlatformMessage),
1143 channel,
1144 message,
1145 message_size,
1146 response_handle,
1147 };
1148
1150 messenger->GetEngine()->flutter_engine, &platform_message);
1151
1152 if (response_handle != nullptr) {
1154 messenger->GetEngine()->flutter_engine, response_handle);
1155 }
1156
1157 return message_result == kSuccess;
1158}
1159
1161 const char* channel,
1162 const uint8_t* message,
1163 const size_t message_size) {
1164 return FlutterDesktopMessengerSendWithReply(messenger, channel, message,
1165 message_size, nullptr, nullptr);
1166}
1167
1171 const uint8_t* data,
1172 size_t data_length) {
1174 messenger->GetEngine()->flutter_engine, handle, data, data_length);
1175}
1176
1178 const char* channel,
1180 void* user_data) {
1181 messenger->GetEngine()->message_dispatcher->SetMessageCallback(
1182 channel, callback, user_data);
1183}
1184
1187 std::cerr << "GLFW Texture support is not implemented yet." << std::endl;
1188 return nullptr;
1189}
1190
1193 const FlutterDesktopTextureInfo* texture_info) {
1194 std::cerr << "GLFW Texture support is not implemented yet." << std::endl;
1195 return -1;
1196}
1197
1200 int64_t texture_id,
1201 void (*callback)(void* user_data),
1202 void* user_data) {
1203 std::cerr << "GLFW Texture support is not implemented yet." << std::endl;
1204}
1205
1208 int64_t texture_id) {
1209 std::cerr << "GLFW Texture support is not implemented yet." << std::endl;
1210 return false;
1211}
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 FlutterEngineUpdateLocales(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterLocale **locales, size_t locales_count)
Notify a running engine instance that the locale has been updated. The preferred locale must be the f...
Definition: embedder.cc:3004
FlutterEngineResult FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterWindowMetricsEvent *flutter_metrics)
Definition: embedder.cc:2320
FlutterEngineResult FlutterEngineShutdown(FLUTTER_API_SYMBOL(FlutterEngine) engine)
Shuts down a Flutter engine instance. The engine handle is no longer valid for any calls in the embed...
Definition: embedder.cc:2309
FlutterEngineResult FlutterPlatformMessageCreateResponseHandle(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterDataCallback data_callback, void *user_data, FlutterPlatformMessageResponseHandle **response_out)
Creates a platform message response handle that allows the embedder to set a native callback for a re...
Definition: embedder.cc:2687
FlutterEngineResult FlutterEngineCollectAOTData(FlutterEngineAOTData data)
Collects the AOT data.
Definition: embedder.cc:1480
FlutterEngineResult FlutterEngineSendPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *flutter_message)
Definition: embedder.cc:2636
bool FlutterEngineRunsAOTCompiledDartCode(void)
Returns if the Flutter engine instance will run AOT compiled Dart code. This call has no threading re...
Definition: embedder.cc:3063
FlutterEngineResult FlutterEngineSendPointerEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPointerEvent *pointers, size_t events_count)
Definition: embedder.cc:2429
FlutterEngineResult FlutterEngineSendPlatformMessageResponse(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
Send a response from the native side to a platform message from the Dart Flutter application.
Definition: embedder.cc:2737
FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterPlatformMessageResponseHandle *response)
Collects the handle created using FlutterPlatformMessageCreateResponseHandle.
Definition: embedder.cc:2722
FlutterEngineResult FlutterEngineCreateAOTData(const FlutterEngineAOTDataSource *source, FlutterEngineAOTData *data_out)
Creates the necessary data structures to launch a Flutter Dart application in AOT mode....
Definition: embedder.cc:1426
@ kFlutterEngineAOTDataSourceTypeElfPath
Definition: embedder.h:2110
@ kOpenGL
Definition: embedder.h:80
struct _FlutterEngine * FLUTTER_API_SYMBOL(FlutterEngine)
Definition: embedder.h:269
@ kHover
The pointer moved while up.
Definition: embedder.h:997
@ kUp
Definition: embedder.h:973
@ kRemove
Definition: embedder.h:995
@ kDown
Definition: embedder.h:980
@ kAdd
Definition: embedder.h:990
@ kMove
Definition: embedder.h:985
@ kFlutterPointerButtonMousePrimary
Definition: embedder.h:1017
@ kFlutterPointerButtonMouseSecondary
Definition: embedder.h:1018
FlutterEngineResult
Definition: embedder.h:72
@ kSuccess
Definition: embedder.h:73
@ kFlutterPointerSignalKindScroll
Definition: embedder.h:1029
#define FLUTTER_ENGINE_VERSION
Definition: embedder.h:70
@ kFlutterPointerDeviceKindMouse
Definition: embedder.h:1008
GLFWwindow * window
Definition: main.cc:45
FlutterEngine engine
Definition: main.cc:68
SkBitmap source
Definition: examples.cpp:28
AtkStateType state
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyEvent * event
uint8_t value
GAsyncResult * result
std::unique_ptr< GLFWwindow, void(*)(GLFWwindow *)> UniqueGLFWwindowPtr
Definition: flutter_glfw.cc:39
static void SetUpLocales(FlutterDesktopEngineState *state)
static FlutterDesktopMessage ConvertToDesktopMessage(const FlutterPlatformMessage &engine_message)
FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow(const FlutterDesktopWindowProperties &window_properties, const FlutterDesktopEngineProperties &engine_properties)
void GLFWWindowRefreshCallback(GLFWwindow *window)
void FlutterDesktopMessengerSetCallback(FlutterDesktopMessengerRef messenger, const char *channel, FlutterDesktopMessageCallback callback, void *user_data)
static UniqueGLFWwindowPtr CreateShareWindowForWindow(GLFWwindow *window)
void FlutterDesktopDestroyWindow(FlutterDesktopWindowControllerRef controller)
const int kFlutterDesktopDontCare
Definition: flutter_glfw.cc:43
FlutterDesktopWindowRef FlutterDesktopPluginRegistrarGetWindow(FlutterDesktopPluginRegistrarRef registrar)
bool FlutterDesktopInit()
static void GLFWErrorCallback(int error_code, const char *description)
std::unique_ptr< FlutterDesktopMessenger, decltype(&FlutterDesktopMessengerRelease)> FlutterDesktopMessengerReferenceOwner
Maintains one ref on the FlutterDesktopMessenger's internal reference count.
static void GLFWCursorPositionCallback(GLFWwindow *window, double x, double y)
void FlutterDesktopMessengerSendResponse(FlutterDesktopMessengerRef messenger, const FlutterDesktopMessageResponseHandle *handle, const uint8_t *data, size_t data_length)
double FlutterDesktopWindowGetScaleFactor(FlutterDesktopWindowRef flutter_window)
bool FlutterDesktopMessengerSendWithReply(FlutterDesktopMessengerRef messenger, const char *channel, const uint8_t *message, const size_t message_size, const FlutterDesktopBinaryReply reply, void *user_data)
void FlutterDesktopPluginRegistrarSetDestructionHandler(FlutterDesktopPluginRegistrarRef registrar, FlutterDesktopOnPluginRegistrarDestroyed callback)
void FlutterDesktopWindowSetPixelRatioOverride(FlutterDesktopWindowRef flutter_window, double pixel_ratio)
UniqueAotDataPtr LoadAotData(const std::filesystem::path &aot_data_path)
int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture(FlutterDesktopTextureRegistrarRef texture_registrar, const FlutterDesktopTextureInfo *texture_info)
static void SetHoverCallbacksEnabled(GLFWwindow *window, bool enabled)
bool FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable(FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id)
static bool RunFlutterEngine(FlutterDesktopEngineState *engine_state, const FlutterDesktopEngineProperties &engine_properties, std::unique_ptr< flutter::EventLoop > event_loop)
static FlutterDesktopWindowControllerState * GetWindowController(GLFWwindow *window)
FlutterDesktopMessengerRef FlutterDesktopMessengerLock(FlutterDesktopMessengerRef messenger)
void FlutterDesktopTextureRegistrarUnregisterExternalTexture(FlutterDesktopTextureRegistrarRef texture_registrar, int64_t texture_id, void(*callback)(void *user_data), void *user_data)
static bool EngineClearContext(void *user_data)
static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
void FlutterDesktopWindowSetSizeLimits(FlutterDesktopWindowRef flutter_window, FlutterDesktopSize minimum_size, FlutterDesktopSize maximum_size)
FlutterDesktopWindowRef FlutterDesktopGetWindow(FlutterDesktopWindowControllerRef controller)
static void SendPointerEventWithData(GLFWwindow *window, const FlutterPointerEvent &event_data)
static void GLFWCharCallback(GLFWwindow *window, unsigned int code_point)
void FlutterDesktopWindowGetFrame(FlutterDesktopWindowRef flutter_window, int *x, int *y, int *width, int *height)
void FlutterDesktopPluginRegistrarEnableInputBlocking(FlutterDesktopPluginRegistrarRef registrar, const char *channel)
void FlutterDesktopRunEngineEventLoopWithTimeout(FlutterDesktopEngineRef engine, uint32_t timeout_milliseconds)
static void GLFWFramebufferSizeCallback(GLFWwindow *window, int width_px, int height_px)
bool FlutterDesktopMessengerIsAvailable(FlutterDesktopMessengerRef messenger)
bool FlutterDesktopMessengerSend(FlutterDesktopMessengerRef messenger, const char *channel, const uint8_t *message, const size_t message_size)
bool FlutterDesktopRunWindowEventLoopWithTimeout(FlutterDesktopWindowControllerRef controller, uint32_t timeout_milliseconds)
void FlutterDesktopWindowSetHoverEnabled(FlutterDesktopWindowRef flutter_window, bool enabled)
static void EngineOnFlutterPlatformMessage(const FlutterPlatformMessage *engine_message, void *user_data)
static void GLFWMouseButtonCallback(GLFWwindow *window, int key, int action, int mods)
static bool EngineMakeResourceContextCurrent(void *user_data)
void FlutterDesktopWindowSetFrame(FlutterDesktopWindowRef flutter_window, int x, int y, int width, int height)
void FlutterDesktopMessengerUnlock(FlutterDesktopMessengerRef messenger)
FlutterDesktopEngineRef FlutterDesktopRunEngine(const FlutterDesktopEngineProperties &properties)
static void SetEventPhaseFromCursorButtonState(GLFWwindow *window, FlutterPointerEvent *event_data, int64_t buttons)
static void SetUpCommonEngineState(FlutterDesktopEngineState *state, GLFWwindow *window)
static void GLFWScrollCallback(GLFWwindow *window, double delta_x, double delta_y)
static void ConfigurePlatformTaskRunner(FlutterTaskRunnerDescription *task_runner, FlutterDesktopEngineState *engine_state)
static double GetScreenCoordinatesPerInch()
FlutterDesktopEngineRef FlutterDesktopGetEngine(FlutterDesktopWindowControllerRef controller)
static bool EngineMakeContextCurrent(void *user_data)
static void SendWindowMetrics(FlutterDesktopWindowControllerState *controller, int width, int height)
static void GLFWAssignEventCallbacks(GLFWwindow *window)
static void GLFWCursorEnterCallback(GLFWwindow *window, int entered)
bool FlutterDesktopShutDownEngine(FlutterDesktopEngineRef engine)
#define GLFW_FALSE
Definition: flutter_glfw.cc:36
static uint32_t EngineGetActiveFbo(void *user_data)
static bool EnginePresent(void *user_data)
FlutterDesktopTextureRegistrarRef FlutterDesktopRegistrarGetTextureRegistrar(FlutterDesktopPluginRegistrarRef registrar)
std::unique_ptr< _FlutterEngineAOTData, AOTDataDeleter > UniqueAotDataPtr
FlutterDesktopMessengerRef FlutterDesktopPluginRegistrarGetMessenger(FlutterDesktopPluginRegistrarRef registrar)
static void SetEventLocationFromCursorPosition(GLFWwindow *window, FlutterPointerEvent *event_data)
void FlutterDesktopMessengerRelease(FlutterDesktopMessengerRef messenger)
void FlutterDesktopWindowSetTitle(FlutterDesktopWindowRef flutter_window, const char *title)
static void * EngineProcResolver(void *user_data, const char *name)
void FlutterDesktopTerminate()
FlutterDesktopMessengerRef FlutterDesktopMessengerAddRef(FlutterDesktopMessengerRef messenger)
void FlutterDesktopWindowSetIcon(FlutterDesktopWindowRef flutter_window, uint8_t *pixel_data, int width, int height)
static void GLFWClearCanvas(GLFWwindow *window)
FlutterDesktopPluginRegistrarRef FlutterDesktopGetPluginRegistrar(FlutterDesktopEngineRef engine, const char *plugin_name)
static constexpr double kDpPerInch
Definition: flutter_glfw.cc:45
static void GLFWClearEventCallbacks(GLFWwindow *window)
void(* FlutterDesktopBinaryReply)(const uint8_t *data, size_t data_size, void *user_data)
void(* FlutterDesktopMessageCallback)(FlutterDesktopMessengerRef, const FlutterDesktopMessage *, void *)
void(* FlutterDesktopOnPluginRegistrarDestroyed)(FlutterDesktopPluginRegistrarRef)
struct FlutterDesktopTextureRegistrar * FlutterDesktopTextureRegistrarRef
static float max(float r, float g, float b)
Definition: hsl.cpp:49
Win32Message message
char ** argv
Definition: library.h:9
G_BEGIN_DECLS FlTextureRegistrar * texture_registrar
double y
double x
sk_sp< const SkImage > image
Definition: SkRecords.h:269
constexpr int64_t kFlutterImplicitViewId
Definition: constants.h:35
std::vector< FlutterLocale > ConvertToFlutterLocale(const std::vector< LanguageInfo > &languages)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
std::vector< LanguageInfo > GetPreferredLanguageInfo()
std::filesystem::path GetExecutableDirectory()
Definition: path_utils.cc:16
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition: p3.cpp:47
int32_t height
int32_t width
void operator()(FlutterEngineAOTData aot_data)
const FlutterTaskRunnerDescription * platform_task_runner
Definition: embedder.h:1596
size_t struct_size
The size of this struct. Must be sizeof(FlutterCustomTaskRunners).
Definition: embedder.h:1591
std::unique_ptr< FlutterDesktopPluginRegistrar > plugin_registrar
FLUTTER_API_SYMBOL(FlutterEngine) flutter_engine
UniqueAotDataPtr aot_data
std::unique_ptr< flutter::PluginRegistrar > internal_plugin_registrar
std::unique_ptr< flutter::PlatformHandler > platform_handler
std::unique_ptr< flutter::EventLoop > event_loop
FlutterDesktopMessengerReferenceOwner messenger
std::unique_ptr< flutter::IncomingMessageDispatcher > message_dispatcher
FlutterDesktopWindowControllerState * window_controller
FlutterDesktopMessenger()=default
FlutterDesktopMessenger(const FlutterDesktopMessenger &value)=delete
FlutterDesktopMessenger & operator=(const FlutterDesktopMessenger &value)=delete
std::mutex & GetMutex()
void SetEngine(FlutterDesktopEngineState *engine)
FlutterDesktopEngineState * GetEngine() const
Getter for the engine field.
FlutterDesktopEngineState * engine
FlutterDesktopOnPluginRegistrarDestroyed destruction_handler
std::unique_ptr< FlutterDesktopWindow > window_wrapper
Definition: flutter_glfw.cc:60
std::vector< std::unique_ptr< flutter::KeyboardHookHandler > > keyboard_hook_handlers
Definition: flutter_glfw.cc:64
UniqueGLFWwindowPtr resource_window
Definition: flutter_glfw.cc:53
std::unique_ptr< FlutterDesktopEngineState > engine
Definition: flutter_glfw.cc:57
GLFWwindow * window
Definition: flutter_glfw.cc:86
double pixels_per_screen_coordinate
Definition: flutter_glfw.cc:92
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 make_resource_current
Definition: embedder.h:537
BoolCallback clear_current
Definition: embedder.h:517
size_t struct_size
The size of this struct. Must be sizeof(FlutterPlatformMessage).
Definition: embedder.h:1164
const FlutterPlatformMessageResponseHandle * response_handle
Definition: embedder.h:1174
const char * channel
Definition: embedder.h:1165
const uint8_t * message
Definition: embedder.h:1166
size_t struct_size
The size of this struct. Must be sizeof(FlutterPointerEvent).
Definition: embedder.h:1036
double y
The y coordinate of the pointer event in physical pixels.
Definition: embedder.h:1045
double x
The x coordinate of the pointer event in physical pixels.
Definition: embedder.h:1043
FlutterPointerPhase phase
Definition: embedder.h:1037
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(FlutterTaskRunnerDescription).
Definition: embedder.h:1566
BoolCallback runs_task_on_current_thread_callback
Definition: embedder.h:1572
FlutterTaskRunnerPostTaskCallback post_task_callback
Definition: embedder.h:1583
size_t struct_size
The size of this struct. Must be sizeof(FlutterWindowMetricsEvent).
Definition: embedder.h:843
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
void * user_data
int64_t texture_id