Flutter Engine
 
Loading...
Searching...
No Matches
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
6
7#include <GLFW/glfw3.h>
8
9#include <algorithm>
10#include <atomic>
11#include <cassert>
12#include <chrono>
13#include <cstdlib>
14#include <filesystem>
15#include <iostream>
16#include <string>
17
30
31// GLFW_TRUE & GLFW_FALSE are introduced since libglfw-3.3,
32// add definitions here to compile under the old versions.
33#ifndef GLFW_TRUE
34#define GLFW_TRUE 1
35#endif
36#ifndef GLFW_FALSE
37#define GLFW_FALSE 0
38#endif
39
40using UniqueGLFWwindowPtr = std::unique_ptr<GLFWwindow, void (*)(GLFWwindow*)>;
41
42static_assert(FLUTTER_ENGINE_VERSION == 1, "");
43
44const int kFlutterDesktopDontCare = GLFW_DONT_CARE;
45
46static constexpr double kDpPerInch = 160.0;
47
48// Struct for storing state within an instance of the GLFW Window.
50 // The GLFW window that is bound to this state object.
51 UniqueGLFWwindowPtr window = UniqueGLFWwindowPtr(nullptr, glfwDestroyWindow);
52
53 // The invisible GLFW window used to upload resources in the background.
55 UniqueGLFWwindowPtr(nullptr, glfwDestroyWindow);
56
57 // The state associated with the engine.
58 std::unique_ptr<FlutterDesktopEngineState> engine;
59
60 // The window handle given to API clients.
61 std::unique_ptr<FlutterDesktopWindow> window_wrapper;
62
63 // Handlers for keyboard events from GLFW.
64 std::vector<std::unique_ptr<flutter::KeyboardHookHandler>>
66
67 // Whether or not the pointer has been added (or if tracking is enabled,
68 // has been added since it was last removed).
70
71 // Whether or not the pointer is down.
73
74 // The currently pressed buttons, as represented in FlutterPointerEvent.
75 int64_t buttons = 0;
76
77 // The screen coordinates per inch on the primary monitor. Defaults to a sane
78 // value based on pixel_ratio 1.0.
80};
81
82// Opaque reference for the GLFW window itself. This is separate from the
83// controller so that it can be provided to plugins without giving them access
84// to all of the controller-based functionality.
86 // The GLFW window that (indirectly) owns this state object.
87 GLFWwindow* window;
88
89 // Whether or not to track mouse movements to send kHover events.
91
92 // The ratio of pixels per screen coordinate for the window.
94
95 // If non-zero, a forced pixel ratio to use instead of one computed based on
96 // screen information.
98
99 // Resizing triggers a window refresh, but the resize already updates Flutter.
100 // To avoid double messages, the refresh after each resize is skipped.
102};
103
104// Custom deleter for FlutterEngineAOTData.
108 }
109};
110
111using UniqueAotDataPtr = std::unique_ptr<_FlutterEngineAOTData, AOTDataDeleter>;
112/// Maintains one ref on the FlutterDesktopMessenger's internal reference count.
114 std::unique_ptr<FlutterDesktopMessenger,
116
117// Struct for storing state of a Flutter engine instance.
119 // The handle to the Flutter engine instance.
121
122 // The event loop for the main thread that allows for delayed task execution.
123 std::unique_ptr<flutter::EventLoop> event_loop;
124
125 // The plugin messenger handle given to API clients.
128
129 // Message dispatch manager for messages from the Flutter engine.
130 std::unique_ptr<flutter::IncomingMessageDispatcher> message_dispatcher;
131
132 // The plugin registrar handle given to API clients.
133 std::unique_ptr<FlutterDesktopPluginRegistrar> plugin_registrar;
134
135 // The plugin registrar managing internal plugins.
136 std::unique_ptr<flutter::PluginRegistrar> internal_plugin_registrar;
137
138 // Handler for the flutter/platform channel.
139 std::unique_ptr<flutter::PlatformHandler> platform_handler;
140
141 // The controller associated with this engine instance, if any.
142 // This will always be null for a headless engine.
144
145 // AOT data for this engine instance, if applicable.
147};
148
149// State associated with the plugin registrar.
151 // The engine that backs this registrar.
153
154 // Callback to be called on registrar destruction.
156};
157
158// State associated with the messenger used to communicate with the engine.
161
162 /// Increments the reference count.
163 ///
164 /// Thread-safe.
165 void AddRef() { ref_count_.fetch_add(1); }
166
167 /// Decrements the reference count and deletes the object if the count has
168 /// gone to zero.
169 ///
170 /// Thread-safe.
171 void Release() {
172 int32_t old_count = ref_count_.fetch_sub(1);
173 if (old_count <= 1) {
174 delete this;
175 }
176 }
177
178 /// Getter for the engine field.
179 FlutterDesktopEngineState* GetEngine() const { return engine_; }
180
181 /// Setter for the engine field.
182 /// Thread-safe.
184 std::scoped_lock lock(mutex_);
185 engine_ = engine;
186 }
187
188 /// Returns the mutex associated with the |FlutterDesktopMessenger|.
189 ///
190 /// This mutex is used to synchronize reading or writing state inside the
191 /// |FlutterDesktopMessenger| (ie |engine_|).
192 std::mutex& GetMutex() { return mutex_; }
193
196 delete;
197
198 private:
199 // The engine that backs this messenger.
201 std::atomic<int32_t> ref_count_ = 0;
202 std::mutex mutex_;
203};
204
206 FlutterDesktopMessengerRef messenger) {
207 messenger->AddRef();
208 return messenger;
209}
210
214
216 return messenger->GetEngine() != nullptr;
217}
218
220 FlutterDesktopMessengerRef messenger) {
221 messenger->GetMutex().lock();
222 return messenger;
223}
224
226 messenger->GetMutex().unlock();
227}
228
229// Retrieves state bag for the window in question from the GLFWWindow.
231 GLFWwindow* window) {
232 return reinterpret_cast<FlutterDesktopWindowControllerState*>(
233 glfwGetWindowUserPointer(window));
234}
235
236// Creates and returns an invisible GLFW window that shares |window|'s resource
237// context.
239 glfwWindowHint(GLFW_DECORATED, GLFW_FALSE);
240 glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
241#if defined(__linux__)
242 glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
243 glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
244 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
245#endif
246 GLFWwindow* share_window = glfwCreateWindow(1, 1, "", NULL, window);
247 glfwDefaultWindowHints();
248 return UniqueGLFWwindowPtr(share_window, glfwDestroyWindow);
249}
250
251// Converts a FlutterPlatformMessage to an equivalent FlutterDesktopMessage.
253 const FlutterPlatformMessage& engine_message) {
255 message.struct_size = sizeof(message);
256 message.channel = engine_message.channel;
257 message.message = engine_message.message;
258 message.message_size = engine_message.message_size;
259 message.response_handle = engine_message.response_handle;
260 return message;
261}
262
263// Returns the number of screen coordinates per inch for the main monitor.
264// If the information is unavailable, returns a default value that assumes
265// that a screen coordinate is one dp.
267 auto* primary_monitor = glfwGetPrimaryMonitor();
268 if (primary_monitor == nullptr) {
269 return kDpPerInch;
270 }
271 auto* primary_monitor_mode = glfwGetVideoMode(primary_monitor);
272 int primary_monitor_width_mm;
273 glfwGetMonitorPhysicalSize(primary_monitor, &primary_monitor_width_mm,
274 nullptr);
275 if (primary_monitor_width_mm == 0) {
276 return kDpPerInch;
277 }
278 return primary_monitor_mode->width / (primary_monitor_width_mm / 25.4);
279}
280
281// Sends a window metrics update to the Flutter engine using the given
282// framebuffer size and the current window information in |state|.
284 int width,
285 int height) {
286 double dpi = controller->window_wrapper->pixels_per_screen_coordinate *
288
289 FlutterWindowMetricsEvent event = {};
290 event.struct_size = sizeof(event);
291 event.width = width;
292 event.height = height;
293 if (controller->window_wrapper->pixel_ratio_override == 0.0) {
294 // The Flutter pixel_ratio is defined as DPI/dp. Limit the ratio to a
295 // minimum of 1 to avoid rendering a smaller UI on standard resolution
296 // monitors.
297 event.pixel_ratio = std::max(dpi / kDpPerInch, 1.0);
298 } else {
299 event.pixel_ratio = controller->window_wrapper->pixel_ratio_override;
300 }
301 // The GLFW embedder doesn't support multiple views. We assume all pointer
302 // events come from the only view, the implicit view.
303 event.view_id = flutter::kFlutterImplicitViewId;
304 FlutterEngineSendWindowMetricsEvent(controller->engine->flutter_engine,
305 &event);
306}
307
308// Populates |task_runner| with a description that uses |engine_state|'s event
309// loop to run tasks.
311 FlutterTaskRunnerDescription* task_runner,
312 FlutterDesktopEngineState* engine_state) {
313 task_runner->struct_size = sizeof(FlutterTaskRunnerDescription);
314 task_runner->user_data = engine_state;
315 task_runner->runs_task_on_current_thread_callback = [](void* state) -> bool {
316 return reinterpret_cast<FlutterDesktopEngineState*>(state)
317 ->event_loop->RunsTasksOnCurrentThread();
318 };
319 task_runner->post_task_callback =
320 [](FlutterTask task, uint64_t target_time_nanos, void* state) -> void {
321 reinterpret_cast<FlutterDesktopEngineState*>(state)->event_loop->PostTask(
322 task, target_time_nanos);
323 };
324}
325
326// When GLFW calls back to the window with a framebuffer size change, notify
327// FlutterEngine about the new window metrics.
328static void GLFWFramebufferSizeCallback(GLFWwindow* window,
329 int width_px,
330 int height_px) {
331 int width;
332 glfwGetWindowSize(window, &width, nullptr);
333 auto* controller = GetWindowController(window);
334 controller->window_wrapper->pixels_per_screen_coordinate =
335 width > 0 ? width_px / width : 1;
336
337 SendWindowMetrics(controller, width_px, height_px);
338 controller->window_wrapper->skip_next_window_refresh = true;
339}
340
341// Indicates that the window needs to be redrawn.
343 auto* controller = GetWindowController(window);
344 if (controller->window_wrapper->skip_next_window_refresh) {
345 controller->window_wrapper->skip_next_window_refresh = false;
346 return;
347 }
348 // There's no engine API to request a redraw explicitly, so instead send a
349 // window metrics event with the current size to trigger it.
350 int width_px, height_px;
351 glfwGetFramebufferSize(window, &width_px, &height_px);
352 if (width_px > 0 && height_px > 0) {
353 SendWindowMetrics(controller, width_px, height_px);
354 }
355}
356
357// Sends a pointer event to the Flutter engine based on the given data.
358//
359// Any coordinate/distance values in |event_data| should be in screen
360// coordinates; they will be adjusted to pixel values before being sent.
361static void SendPointerEventWithData(GLFWwindow* window,
362 const FlutterPointerEvent& event_data) {
363 auto* controller = GetWindowController(window);
364 // If sending anything other than an add, and the pointer isn't already added,
365 // synthesize an add to satisfy Flutter's expectations about events.
366 if (!controller->pointer_currently_added &&
367 event_data.phase != FlutterPointerPhase::kAdd) {
368 FlutterPointerEvent event = {};
370 event.x = event_data.x;
371 event.y = event_data.y;
373 }
374 // Don't double-add (e.g., if events are delivered out of order, so an add has
375 // already been synthesized).
376 if (controller->pointer_currently_added &&
377 event_data.phase == FlutterPointerPhase::kAdd) {
378 return;
379 }
380
381 FlutterPointerEvent event = event_data;
382 // Set metadata that's always the same regardless of the event.
383 event.struct_size = sizeof(event);
384 event.timestamp =
385 std::chrono::duration_cast<std::chrono::microseconds>(
386 std::chrono::high_resolution_clock::now().time_since_epoch())
387 .count();
389 event.buttons =
390 (event.phase == FlutterPointerPhase::kAdd) ? 0 : controller->buttons;
391
392 // Convert all screen coordinates to pixel coordinates.
393 double pixels_per_coordinate =
394 controller->window_wrapper->pixels_per_screen_coordinate;
395 event.x *= pixels_per_coordinate;
396 event.y *= pixels_per_coordinate;
397 event.scroll_delta_x *= pixels_per_coordinate;
398 event.scroll_delta_y *= pixels_per_coordinate;
399 // The GLFW embedder doesn't support multiple views. We assume all pointer
400 // events come from the only view, the implicit view.
401 event.view_id = flutter::kFlutterImplicitViewId;
402
403 FlutterEngineSendPointerEvent(controller->engine->flutter_engine, &event, 1);
404
405 if (event_data.phase == FlutterPointerPhase::kAdd) {
406 controller->pointer_currently_added = true;
407 } else if (event_data.phase == FlutterPointerPhase::kRemove) {
408 controller->pointer_currently_added = false;
409 } else if (event_data.phase == FlutterPointerPhase::kDown) {
410 controller->pointer_currently_down = true;
411 } else if (event_data.phase == FlutterPointerPhase::kUp) {
412 controller->pointer_currently_down = false;
413 }
414}
415
416// Updates |event_data| with the current location of the mouse cursor.
418 GLFWwindow* window,
419 FlutterPointerEvent* event_data) {
420 glfwGetCursorPos(window, &event_data->x, &event_data->y);
421}
422
423// Set's |event_data|'s phase depending on the current mouse state.
424// If a kUp or kDown event is triggered while the current state is already
425// up/down, a hover/move will be called instead to avoid a crash in the Flutter
426// engine.
428 FlutterPointerEvent* event_data,
429 int64_t buttons) {
430 auto* controller = GetWindowController(window);
431 event_data->phase =
432 (buttons == 0)
433 ? (controller->pointer_currently_down ? FlutterPointerPhase::kUp
435 : (controller->pointer_currently_down ? FlutterPointerPhase::kMove
437}
438
439// Reports the mouse entering or leaving the Flutter view.
440static void GLFWCursorEnterCallback(GLFWwindow* window, int entered) {
441 FlutterPointerEvent event = {};
442 event.phase =
446}
447
448// Reports mouse movement to the Flutter engine.
449static void GLFWCursorPositionCallback(GLFWwindow* window, double x, double y) {
450 FlutterPointerEvent event = {};
451 event.x = x;
452 event.y = y;
453 auto* controller = GetWindowController(window);
454 SetEventPhaseFromCursorButtonState(window, &event, controller->buttons);
456}
457
458// Reports mouse button press to the Flutter engine.
459static void GLFWMouseButtonCallback(GLFWwindow* window,
460 int key,
461 int action,
462 int mods) {
463 int64_t button;
464 if (key == GLFW_MOUSE_BUTTON_LEFT) {
466 } else if (key == GLFW_MOUSE_BUTTON_RIGHT) {
468 } else {
469 return;
470 }
471
472 auto* controller = GetWindowController(window);
473 controller->buttons = (action == GLFW_PRESS) ? controller->buttons | button
474 : controller->buttons & ~button;
475
476 FlutterPointerEvent event = {};
477 SetEventPhaseFromCursorButtonState(window, &event, controller->buttons);
480
481 // If mouse tracking isn't already enabled, turn it on for the duration of
482 // the drag to generate kMove events.
483 bool hover_enabled =
484 GetWindowController(window)->window_wrapper->hover_tracking_enabled;
485 if (!hover_enabled) {
486 glfwSetCursorPosCallback(window, (controller->buttons != 0)
488 : nullptr);
489 }
490 // Disable enter/exit events while the mouse button is down; GLFW will send
491 // an exit event when the mouse button is released, and the pointer should
492 // stay valid until then.
493 if (hover_enabled) {
494 glfwSetCursorEnterCallback(
495 window, (controller->buttons != 0) ? nullptr : GLFWCursorEnterCallback);
496 }
497}
498
499// Reports scroll wheel events to the Flutter engine.
500static void GLFWScrollCallback(GLFWwindow* window,
501 double delta_x,
502 double delta_y) {
503 FlutterPointerEvent event = {};
505 auto* controller = GetWindowController(window);
506 SetEventPhaseFromCursorButtonState(window, &event, controller->buttons);
508 // TODO(chrome-bot): See if this can be queried from the OS; this value is
509 // chosen arbitrarily to get something that feels reasonable.
510 const int kScrollOffsetMultiplier = 20;
511 event.scroll_delta_x = delta_x * kScrollOffsetMultiplier;
512 event.scroll_delta_y = -delta_y * kScrollOffsetMultiplier;
514}
515
516// Passes character input events to registered handlers.
517static void GLFWCharCallback(GLFWwindow* window, unsigned int code_point) {
518 for (const auto& handler :
520 handler->CharHook(window, code_point);
521 }
522}
523
524// Passes raw key events to registered handlers.
525static void GLFWKeyCallback(GLFWwindow* window,
526 int key,
527 int scancode,
528 int action,
529 int mods) {
530 for (const auto& handler :
532 handler->KeyboardHook(window, key, scancode, action, mods);
533 }
534}
535
536// Enables/disables the callbacks related to mouse tracking.
537static void SetHoverCallbacksEnabled(GLFWwindow* window, bool enabled) {
538 glfwSetCursorEnterCallback(window,
539 enabled ? GLFWCursorEnterCallback : nullptr);
540 glfwSetCursorPosCallback(window,
541 enabled ? GLFWCursorPositionCallback : nullptr);
542}
543
544// Flushes event queue and then assigns default window callbacks.
545static void GLFWAssignEventCallbacks(GLFWwindow* window) {
546 glfwPollEvents();
547 glfwSetKeyCallback(window, GLFWKeyCallback);
548 glfwSetCharCallback(window, GLFWCharCallback);
549 glfwSetMouseButtonCallback(window, GLFWMouseButtonCallback);
550 glfwSetScrollCallback(window, GLFWScrollCallback);
551 if (GetWindowController(window)->window_wrapper->hover_tracking_enabled) {
553 }
554}
555
556// Clears default window events.
557static void GLFWClearEventCallbacks(GLFWwindow* window) {
558 glfwSetKeyCallback(window, nullptr);
559 glfwSetCharCallback(window, nullptr);
560 glfwSetMouseButtonCallback(window, nullptr);
561 glfwSetScrollCallback(window, nullptr);
563}
564
565// The Flutter Engine calls out to this function when new platform messages are
566// available
568 const FlutterPlatformMessage* engine_message,
569 void* user_data) {
570 if (engine_message->struct_size != sizeof(FlutterPlatformMessage)) {
571 std::cerr << "Invalid message size received. Expected: "
572 << sizeof(FlutterPlatformMessage) << " but received "
573 << engine_message->struct_size << std::endl;
574 return;
575 }
576
577 FlutterDesktopEngineState* engine_state =
579 GLFWwindow* window = engine_state->window_controller == nullptr
580 ? nullptr
581 : engine_state->window_controller->window.get();
582
583 auto message = ConvertToDesktopMessage(*engine_message);
584 engine_state->message_dispatcher->HandleMessage(
585 message,
586 [window] {
587 if (window) {
589 }
590 },
591 [window] {
592 if (window) {
594 }
595 });
596}
597
599 FlutterDesktopEngineState* engine_state =
601 FlutterDesktopWindowControllerState* window_controller =
602 engine_state->window_controller;
603 if (!window_controller) {
604 return false;
605 }
606 glfwMakeContextCurrent(window_controller->window.get());
607 return true;
608}
609
611 FlutterDesktopEngineState* engine_state =
613 FlutterDesktopWindowControllerState* window_controller =
614 engine_state->window_controller;
615 if (!window_controller) {
616 return false;
617 }
618 glfwMakeContextCurrent(window_controller->resource_window.get());
619 return true;
620}
621
622static bool EngineClearContext(void* user_data) {
623 FlutterDesktopEngineState* engine_state =
625 FlutterDesktopWindowControllerState* window_controller =
626 engine_state->window_controller;
627 if (!window_controller) {
628 return false;
629 }
630 glfwMakeContextCurrent(nullptr);
631 return true;
632}
633
634static bool EnginePresent(void* user_data) {
635 FlutterDesktopEngineState* engine_state =
637 FlutterDesktopWindowControllerState* window_controller =
638 engine_state->window_controller;
639 if (!window_controller) {
640 return false;
641 }
642 glfwSwapBuffers(window_controller->window.get());
643 return true;
644}
645
646static uint32_t EngineGetActiveFbo(void* user_data) {
647 return 0;
648}
649
650// Resolves the address of the specified OpenGL or OpenGL ES
651// core or extension function, if it is supported by the current context.
652static void* EngineProcResolver(void* user_data, const char* name) {
653 return reinterpret_cast<void*>(glfwGetProcAddress(name));
654}
655
656// Clears the GLFW window to Material Blue-Grey.
657//
658// This function is primarily to fix an issue when the Flutter Engine is
659// spinning up, wherein artifacts of existing windows are rendered onto the
660// canvas for a few moments.
661//
662// This function isn't necessary, but makes starting the window much easier on
663// the eyes.
664static void GLFWClearCanvas(GLFWwindow* window) {
665 glfwMakeContextCurrent(window);
666 // This color is Material Blue Grey.
667 glClearColor(236.0f / 255.0f, 239.0f / 255.0f, 241.0f / 255.0f, 0.0f);
668 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
669 glFlush();
670 glfwSwapBuffers(window);
671 glfwMakeContextCurrent(nullptr);
672}
673
674static void GLFWErrorCallback(int error_code, const char* description) {
675 std::cerr << "GLFW error " << error_code << ": " << description << std::endl;
676}
677
678// Attempts to load AOT data from the given path, which must be absolute and
679// non-empty. Logs and returns nullptr on failure.
680UniqueAotDataPtr LoadAotData(const std::filesystem::path& aot_data_path) {
681 if (aot_data_path.empty()) {
682 std::cerr
683 << "Attempted to load AOT data, but no aot_data_path was provided."
684 << std::endl;
685 return nullptr;
686 }
687 std::string path_string = aot_data_path.string();
688 if (!std::filesystem::exists(aot_data_path)) {
689 std::cerr << "Can't load AOT data from " << path_string << "; no such file."
690 << std::endl;
691 return nullptr;
692 }
693 FlutterEngineAOTDataSource source = {};
695 source.elf_path = path_string.c_str();
696 FlutterEngineAOTData data = nullptr;
697 auto result = FlutterEngineCreateAOTData(&source, &data);
698 if (result != kSuccess) {
699 std::cerr << "Failed to load AOT data from: " << path_string << std::endl;
700 return nullptr;
701 }
702 return UniqueAotDataPtr(data);
703}
704
705// Starts an instance of the Flutter Engine.
706//
707// Configures the engine according to |engine_propreties| and using |event_loop|
708// to schedule engine tasks.
709//
710// Returns true on success, in which case |engine_state|'s 'engine' field will
711// be updated to point to the started engine.
713 FlutterDesktopEngineState* engine_state,
714 const FlutterDesktopEngineProperties& engine_properties,
715 std::unique_ptr<flutter::EventLoop> event_loop) {
716 // FlutterProjectArgs is expecting a full argv, so when processing it for
717 // flags the first item is treated as the executable and ignored. Add a dummy
718 // value so that all provided arguments are used.
719 std::vector<const char*> argv = {"placeholder"};
720 if (engine_properties.switches_count > 0) {
721 argv.insert(argv.end(), &engine_properties.switches[0],
722 &engine_properties.switches[engine_properties.switches_count]);
723 }
724
725 std::filesystem::path assets_path =
726 std::filesystem::u8path(engine_properties.assets_path);
727 std::filesystem::path icu_path =
728 std::filesystem::u8path(engine_properties.icu_data_path);
729 std::filesystem::path aot_library_path =
730 std::filesystem::u8path(engine_properties.aot_library_path);
731 if (assets_path.is_relative() || icu_path.is_relative() ||
732 (!aot_library_path.empty() && aot_library_path.is_relative())) {
733 // Treat relative paths as relative to the directory of this executable.
734 std::filesystem::path executable_location =
736 if (executable_location.empty()) {
737 std::cerr << "Unable to find executable location to resolve paths."
738 << std::endl;
739 return false;
740 }
741 assets_path = std::filesystem::path(executable_location) / assets_path;
742 icu_path = std::filesystem::path(executable_location) / icu_path;
743 if (!aot_library_path.empty()) {
744 aot_library_path =
745 std::filesystem::path(executable_location) / aot_library_path;
746 }
747 }
748 // Configure a task runner using the event loop.
749 engine_state->event_loop = std::move(event_loop);
750 FlutterTaskRunnerDescription platform_task_runner = {};
751 ConfigurePlatformTaskRunner(&platform_task_runner, engine_state);
752 FlutterCustomTaskRunners task_runners = {};
753 task_runners.struct_size = sizeof(FlutterCustomTaskRunners);
754 task_runners.platform_task_runner = &platform_task_runner;
755
756 FlutterRendererConfig config = {};
757 config.type = kOpenGL;
758 config.open_gl.struct_size = sizeof(config.open_gl);
764 // Don't provide a resolver in headless mode, since headless mode should
765 // work even if GLFW initialization failed.
766 if (engine_state->window_controller != nullptr) {
768 }
769 const std::string assets_path_string = assets_path.string();
770 const std::string icu_path_string = icu_path.string();
773 args.assets_path = assets_path_string.c_str();
774 args.icu_data_path = icu_path_string.c_str();
775 args.command_line_argc = static_cast<int>(argv.size());
776 args.command_line_argv = &argv[0];
777 args.platform_message_callback = EngineOnFlutterPlatformMessage;
778 args.custom_task_runners = &task_runners;
779
781 engine_state->aot_data = LoadAotData(aot_library_path);
782 if (!engine_state->aot_data) {
783 std::cerr << "Unable to start engine without AOT data." << std::endl;
784 return false;
785 }
786 args.aot_data = engine_state->aot_data.get();
787 }
788
790 auto result = FlutterEngineRun(FLUTTER_ENGINE_VERSION, &config, &args,
791 engine_state, &engine);
792 if (result != kSuccess || engine == nullptr) {
793 std::cerr << "Failed to start Flutter engine: error " << result
794 << std::endl;
795 return false;
796 }
797 engine_state->flutter_engine = engine;
798 return true;
799}
800
801// Passes locale information to the Flutter engine.
803 std::vector<flutter::LanguageInfo> languages =
805 std::vector<FlutterLocale> flutter_locales =
807 // Convert the locale list to the locale pointer list that must be provided.
808 std::vector<const FlutterLocale*> flutter_locale_list;
809 flutter_locale_list.reserve(flutter_locales.size());
810 std::transform(flutter_locales.begin(), flutter_locales.end(),
811 std::back_inserter(flutter_locale_list),
812 [](const auto& arg) -> const auto* { return &arg; });
814 state->flutter_engine, flutter_locale_list.data(),
815 flutter_locale_list.size());
816 if (result != kSuccess) {
817 std::cerr << "Failed to set up Flutter locales." << std::endl;
818 }
819}
820
821// Populates |state|'s helper object fields that are common to normal and
822// headless mode.
823//
824// Window is optional; if present it will be provided to the created
825// PlatformHandler.
827 GLFWwindow* window) {
828 // Messaging.
832 state->messenger->SetEngine(state);
833 state->message_dispatcher =
834 std::make_unique<flutter::IncomingMessageDispatcher>(
835 state->messenger.get());
836
837 // Plugins.
838 state->plugin_registrar = std::make_unique<FlutterDesktopPluginRegistrar>();
839 state->plugin_registrar->engine = state;
841 std::make_unique<flutter::PluginRegistrar>(state->plugin_registrar.get());
842
843 // System channel handler.
844 state->platform_handler = std::make_unique<flutter::PlatformHandler>(
845 state->internal_plugin_registrar->messenger(), window);
846
847 SetUpLocales(state);
848}
849
851 // Before making any GLFW calls, set up a logging error handler.
852 glfwSetErrorCallback(GLFWErrorCallback);
853 return glfwInit();
854}
855
857 glfwTerminate();
858}
859
861 const FlutterDesktopWindowProperties& window_properties,
862 const FlutterDesktopEngineProperties& engine_properties) {
863 auto state = std::make_unique<FlutterDesktopWindowControllerState>();
864
865 // Create the window, and set the state as its user data.
866 if (window_properties.prevent_resize) {
867 glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
868 }
869#if defined(__linux__)
870 glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
871#endif
872 state->window = UniqueGLFWwindowPtr(
873 glfwCreateWindow(window_properties.width, window_properties.height,
874 window_properties.title, NULL, NULL),
875 glfwDestroyWindow);
876 glfwDefaultWindowHints();
877 GLFWwindow* window = state->window.get();
878 if (window == nullptr) {
879 return nullptr;
880 }
882 glfwSetWindowUserPointer(window, state.get());
883
884 // Create the share window before starting the engine, since it may call
885 // EngineMakeResourceContextCurrent immediately.
886 state->resource_window = CreateShareWindowForWindow(window);
887
888 state->engine = std::make_unique<FlutterDesktopEngineState>();
889 state->engine->window_controller = state.get();
890
891 // Create an event loop for the window. It is not running yet.
892 auto event_loop = std::make_unique<flutter::GLFWEventLoop>(
893 std::this_thread::get_id(), // main GLFW thread
894 [engine_state = state->engine.get()](const auto* task) {
895 if (FlutterEngineRunTask(engine_state->flutter_engine, task) !=
896 kSuccess) {
897 std::cerr << "Could not post an engine task." << std::endl;
898 }
899 });
900
901 // Start the engine.
902 if (!RunFlutterEngine(state->engine.get(), engine_properties,
903 std::move(event_loop))) {
904 return nullptr;
905 }
906 SetUpCommonEngineState(state->engine.get(), window);
907
908 state->window_wrapper = std::make_unique<FlutterDesktopWindow>();
909 state->window_wrapper->window = window;
910
911 // Set up the keyboard handlers
912 auto internal_plugin_messenger =
913 state->engine->internal_plugin_registrar->messenger();
914 state->keyboard_hook_handlers.push_back(
915 std::make_unique<flutter::KeyEventHandler>(internal_plugin_messenger));
916 state->keyboard_hook_handlers.push_back(
917 std::make_unique<flutter::TextInputPlugin>(internal_plugin_messenger));
918
919 // Trigger an initial size callback to send size information to Flutter.
920 state->monitor_screen_coordinates_per_inch = GetScreenCoordinatesPerInch();
921 int width_px, height_px;
922 glfwGetFramebufferSize(window, &width_px, &height_px);
923 GLFWFramebufferSizeCallback(window, width_px, height_px);
924
925 // Set up GLFW callbacks for the window.
926 glfwSetFramebufferSizeCallback(window, GLFWFramebufferSizeCallback);
927 glfwSetWindowRefreshCallback(window, GLFWWindowRefreshCallback);
929
930 return state.release();
931}
932
934 controller->engine->messenger->SetEngine(nullptr);
936 controller->engine->plugin_registrar.get();
937 if (registrar->destruction_handler) {
938 registrar->destruction_handler(registrar);
939 }
940 FlutterEngineShutdown(controller->engine->flutter_engine);
941 delete controller;
942}
943
945 bool enabled) {
946 flutter_window->hover_tracking_enabled = enabled;
947 SetHoverCallbacksEnabled(flutter_window->window, enabled);
948}
949
951 const char* title) {
952 GLFWwindow* window = flutter_window->window;
953 glfwSetWindowTitle(window, title);
954}
955
957 uint8_t* pixel_data,
958 int width,
959 int height) {
960 GLFWimage image = {width, height, static_cast<unsigned char*>(pixel_data)};
961 glfwSetWindowIcon(flutter_window->window, pixel_data ? 1 : 0, &image);
962}
963
965 int* x,
966 int* y,
967 int* width,
968 int* height) {
969 glfwGetWindowPos(flutter_window->window, x, y);
970 glfwGetWindowSize(flutter_window->window, width, height);
971 // The above gives content area size and position; adjust for the window
972 // decoration to give actual window frame.
973 int frame_left, frame_top, frame_right, frame_bottom;
974 glfwGetWindowFrameSize(flutter_window->window, &frame_left, &frame_top,
975 &frame_right, &frame_bottom);
976 if (x) {
977 *x -= frame_left;
978 }
979 if (y) {
980 *y -= frame_top;
981 }
982 if (width) {
983 *width += frame_left + frame_right;
984 }
985 if (height) {
986 *height += frame_top + frame_bottom;
987 }
988}
989
991 int x,
992 int y,
993 int width,
994 int height) {
995 // Get the window decoration sizes to adjust, since the GLFW setters take
996 // content position and size.
997 int frame_left, frame_top, frame_right, frame_bottom;
998 glfwGetWindowFrameSize(flutter_window->window, &frame_left, &frame_top,
999 &frame_right, &frame_bottom);
1000 glfwSetWindowPos(flutter_window->window, x + frame_left, y + frame_top);
1001 glfwSetWindowSize(flutter_window->window, width - frame_left - frame_right,
1002 height - frame_top - frame_bottom);
1003}
1004
1006 FlutterDesktopWindowRef flutter_window) {
1007 return flutter_window->pixels_per_screen_coordinate;
1008}
1009
1011 FlutterDesktopWindowRef flutter_window,
1012 double pixel_ratio) {
1013 flutter_window->pixel_ratio_override = pixel_ratio;
1014 // Send a metrics update using the new pixel ratio.
1015 int width_px, height_px;
1016 glfwGetFramebufferSize(flutter_window->window, &width_px, &height_px);
1017 if (width_px > 0 && height_px > 0) {
1018 auto* controller = GetWindowController(flutter_window->window);
1019 SendWindowMetrics(controller, width_px, height_px);
1020 }
1021}
1022
1024 FlutterDesktopSize minimum_size,
1025 FlutterDesktopSize maximum_size) {
1026 glfwSetWindowSizeLimits(flutter_window->window, minimum_size.width,
1027 minimum_size.height, maximum_size.width,
1028 maximum_size.height);
1029}
1030
1033 uint32_t timeout_milliseconds) {
1035 timeout_milliseconds);
1036 return !glfwWindowShouldClose(controller->window.get());
1037}
1038
1041 // Currently, one registrar acts as the registrar for all plugins, so the
1042 // name is ignored. It is part of the API to reduce churn in the future when
1043 // aligning more closely with the Flutter registrar system.
1044 return controller->window_wrapper.get();
1045}
1046
1049 return controller->engine.get();
1050}
1051
1054 const char* plugin_name) {
1055 // Currently, one registrar acts as the registrar for all plugins, so the
1056 // name is ignored. It is part of the API to reduce churn in the future when
1057 // aligning more closely with the Flutter registrar system.
1058 return engine->plugin_registrar.get();
1059}
1060
1062 const FlutterDesktopEngineProperties& properties) {
1063 auto engine_state = std::make_unique<FlutterDesktopEngineState>();
1064
1065 auto event_loop = std::make_unique<flutter::HeadlessEventLoop>(
1066 std::this_thread::get_id(),
1067 [state = engine_state.get()](const auto* task) {
1068 if (FlutterEngineRunTask(state->flutter_engine, task) != kSuccess) {
1069 std::cerr << "Could not post an engine task." << std::endl;
1070 }
1071 });
1072
1073 if (!RunFlutterEngine(engine_state.get(), properties,
1074 std::move(event_loop))) {
1075 return nullptr;
1076 }
1077 SetUpCommonEngineState(engine_state.get(), nullptr);
1078
1079 return engine_state.release();
1080}
1081
1084 uint32_t timeout_milliseconds) {
1085 std::chrono::nanoseconds wait_duration =
1086 timeout_milliseconds == 0
1087 ? std::chrono::nanoseconds::max()
1088 : std::chrono::milliseconds(timeout_milliseconds);
1089 engine->event_loop->WaitForEvents(wait_duration);
1090}
1091
1093 auto result = FlutterEngineShutdown(engine->flutter_engine);
1094 delete engine;
1095 return (result == kSuccess);
1096}
1097
1100 const char* channel) {
1101 registrar->engine->message_dispatcher->EnableInputBlockingForChannel(channel);
1102}
1103
1108
1114
1118 registrar->engine->window_controller;
1119 if (!controller) {
1120 return nullptr;
1121 }
1122 return controller->window_wrapper.get();
1123}
1124
1126 const char* channel,
1127 const uint8_t* message,
1128 const size_t message_size,
1129 const FlutterDesktopBinaryReply reply,
1130 void* user_data) {
1131 FlutterPlatformMessageResponseHandle* response_handle = nullptr;
1132 if (reply != nullptr && user_data != nullptr) {
1134 messenger->GetEngine()->flutter_engine, reply, user_data,
1135 &response_handle);
1136 if (result != kSuccess) {
1137 std::cout << "Failed to create response handle\n";
1138 return false;
1139 }
1140 }
1141
1142 FlutterPlatformMessage platform_message = {
1143 sizeof(FlutterPlatformMessage),
1144 channel,
1145 message,
1146 message_size,
1147 response_handle,
1148 };
1149
1151 messenger->GetEngine()->flutter_engine, &platform_message);
1152
1153 if (response_handle != nullptr) {
1155 messenger->GetEngine()->flutter_engine, response_handle);
1156 }
1157
1158 return message_result == kSuccess;
1159}
1160
1162 const char* channel,
1163 const uint8_t* message,
1164 const size_t message_size) {
1166 message_size, nullptr, nullptr);
1167}
1168
1172 const uint8_t* data,
1173 size_t data_length) {
1175 messenger->GetEngine()->flutter_engine, handle, data, data_length);
1176}
1177
1179 const char* channel,
1181 void* user_data) {
1182 messenger->GetEngine()->message_dispatcher->SetMessageCallback(
1184}
1185
1188 std::cerr << "GLFW Texture support is not implemented yet." << std::endl;
1189 return nullptr;
1190}
1191
1194 const FlutterDesktopTextureInfo* texture_info) {
1195 std::cerr << "GLFW Texture support is not implemented yet." << std::endl;
1196 return -1;
1197}
1198
1201 int64_t texture_id,
1202 void (*callback)(void* user_data),
1203 void* user_data) {
1204 std::cerr << "GLFW Texture support is not implemented yet." << std::endl;
1205}
1206
1209 int64_t texture_id) {
1210 std::cerr << "GLFW Texture support is not implemented yet." << std::endl;
1211 return false;
1212}
int32_t x
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:1971
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:3365
FlutterEngineResult FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterWindowMetricsEvent *flutter_metrics)
Definition embedder.cc:2660
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:2649
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:3028
FlutterEngineResult FlutterEngineCollectAOTData(FlutterEngineAOTData data)
Collects the AOT data.
Definition embedder.cc:1736
FlutterEngineResult FlutterEngineSendPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *flutter_message)
Definition embedder.cc:2977
bool FlutterEngineRunsAOTCompiledDartCode(void)
Returns if the Flutter engine instance will run AOT compiled Dart code. This call has no threading re...
Definition embedder.cc:3424
FlutterEngineResult FlutterEngineSendPointerEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPointerEvent *pointers, size_t events_count)
Definition embedder.cc:2769
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:3078
FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterPlatformMessageResponseHandle *response)
Collects the handle created using FlutterPlatformMessageCreateResponseHandle.
Definition embedder.cc:3063
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:1682
#define FLUTTER_API_SYMBOL(symbol)
Definition embedder.h:67
@ kFlutterEngineAOTDataSourceTypeElfPath
Definition embedder.h:2428
@ kOpenGL
Definition embedder.h:80
@ kHover
The pointer moved while up.
Definition embedder.h:1269
@ kUp
Definition embedder.h:1245
@ kRemove
Definition embedder.h:1267
@ kDown
Definition embedder.h:1252
@ kAdd
Definition embedder.h:1262
@ kMove
Definition embedder.h:1257
@ kFlutterPointerButtonMousePrimary
Definition embedder.h:1289
@ kFlutterPointerButtonMouseSecondary
Definition embedder.h:1290
FlutterEngineResult
Definition embedder.h:72
@ kSuccess
Definition embedder.h:73
@ kFlutterPointerSignalKindScroll
Definition embedder.h:1301
#define FLUTTER_ENGINE_VERSION
Definition embedder.h:70
@ kFlutterPointerDeviceKindMouse
Definition embedder.h:1280
FlutterVulkanImage * image
GLFWwindow * window
Definition main.cc:60
FlutterEngine engine
Definition main.cc:84
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
const gchar * channel
const gchar FlBinaryMessengerMessageHandler handler
G_BEGIN_DECLS GBytes * message
std::unique_ptr< GLFWwindow, void(*)(GLFWwindow *)> UniqueGLFWwindowPtr
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
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
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
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
FlutterDesktopBinaryReply callback
const char * name
Definition fuchsia.cc:49
char ** argv
Definition library.h:9
G_BEGIN_DECLS FlTextureRegistrar * texture_registrar
double y
constexpr int64_t kFlutterImplicitViewId
Definition constants.h:35
std::vector< FlutterLocale > ConvertToFlutterLocale(const std::vector< LanguageInfo > &languages)
std::vector< LanguageInfo > GetPreferredLanguageInfo()
std::filesystem::path GetExecutableDirectory()
Definition path_utils.cc:16
int32_t height
int32_t width
void operator()(FlutterEngineAOTData aot_data)
const FlutterTaskRunnerDescription * platform_task_runner
Definition embedder.h:1896
size_t struct_size
The size of this struct. Must be sizeof(FlutterCustomTaskRunners).
Definition embedder.h:1891
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
void SetEngine(FlutterDesktopEngineState *engine)
FlutterDesktopEngineState * GetEngine() const
Getter for the engine field.
FlutterDesktopEngineState * engine
FlutterDesktopOnPluginRegistrarDestroyed destruction_handler
std::unique_ptr< FlutterDesktopWindow > window_wrapper
std::vector< std::unique_ptr< flutter::KeyboardHookHandler > > keyboard_hook_handlers
std::unique_ptr< FlutterDesktopEngineState > engine
double pixels_per_screen_coordinate
FlutterEngineAOTDataSourceType type
Definition embedder.h:2434
const char * elf_path
Absolute path to an ELF library file.
Definition embedder.h:2437
ProcResolver gl_proc_resolver
Definition embedder.h:758
size_t struct_size
The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
Definition embedder.h:719
BoolCallback make_resource_current
Definition embedder.h:741
size_t struct_size
The size of this struct. Must be sizeof(FlutterPlatformMessage).
Definition embedder.h:1436
const FlutterPlatformMessageResponseHandle * response_handle
Definition embedder.h:1446
const char * channel
Definition embedder.h:1437
const uint8_t * message
Definition embedder.h:1438
size_t struct_size
The size of this struct. Must be sizeof(FlutterPointerEvent).
Definition embedder.h:1308
double y
The y coordinate of the pointer event in physical pixels.
Definition embedder.h:1317
double x
The x coordinate of the pointer event in physical pixels.
Definition embedder.h:1315
FlutterPointerPhase phase
Definition embedder.h:1309
size_t struct_size
The size of this struct. Must be sizeof(FlutterProjectArgs).
Definition embedder.h:2458
FlutterOpenGLRendererConfig open_gl
Definition embedder.h:1033
FlutterRendererType type
Definition embedder.h:1031
size_t struct_size
The size of this struct. Must be sizeof(FlutterTaskRunnerDescription).
Definition embedder.h:1864
BoolCallback runs_task_on_current_thread_callback
Definition embedder.h:1870
FlutterTaskRunnerPostTaskCallback post_task_callback
Definition embedder.h:1881
size_t struct_size
The size of this struct. Must be sizeof(FlutterWindowMetricsEvent).
Definition embedder.h:1047
std::shared_ptr< const fml::Mapping > data
int64_t texture_id