Flutter Engine
The 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
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.
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
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.
400 event.view_id = flutter::kFlutterImplicitViewId;
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.
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
475 FlutterPointerEvent event = {};
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 :
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 :
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.
679UniqueAotDataPtr LoadAotData(const std::filesystem::path& aot_data_path) {
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();
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
1086 ? std::chrono::nanoseconds::max()
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
1107
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:1711
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:2998
FlutterEngineResult FlutterEngineSendWindowMetricsEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterWindowMetricsEvent *flutter_metrics)
Definition embedder.cc:2314
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:2303
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:2681
FlutterEngineResult FlutterEngineCollectAOTData(FlutterEngineAOTData data)
Collects the AOT data.
Definition embedder.cc:1476
FlutterEngineResult FlutterEngineSendPlatformMessage(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPlatformMessage *flutter_message)
Definition embedder.cc:2630
bool FlutterEngineRunsAOTCompiledDartCode(void)
Returns if the Flutter engine instance will run AOT compiled Dart code. This call has no threading re...
Definition embedder.cc:3057
FlutterEngineResult FlutterEngineSendPointerEvent(FLUTTER_API_SYMBOL(FlutterEngine) engine, const FlutterPointerEvent *pointers, size_t events_count)
Definition embedder.cc:2423
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:2731
FlutterEngineResult FlutterPlatformMessageReleaseResponseHandle(FLUTTER_API_SYMBOL(FlutterEngine) engine, FlutterPlatformMessageResponseHandle *response)
Collects the handle created using FlutterPlatformMessageCreateResponseHandle.
Definition embedder.cc:2716
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:1422
#define FLUTTER_API_SYMBOL(symbol)
Definition embedder.h:67
@ kFlutterEngineAOTDataSourceTypeElfPath
Definition embedder.h:2108
@ kOpenGL
Definition embedder.h:80
@ kHover
The pointer moved while up.
Definition embedder.h:995
@ kUp
Definition embedder.h:971
@ kRemove
Definition embedder.h:993
@ kDown
Definition embedder.h:978
@ kAdd
Definition embedder.h:988
@ kMove
Definition embedder.h:983
@ kFlutterPointerButtonMousePrimary
Definition embedder.h:1015
@ kFlutterPointerButtonMouseSecondary
Definition embedder.h:1016
FlutterEngineResult
Definition embedder.h:72
@ kSuccess
Definition embedder.h:73
@ kFlutterPointerSignalKindScroll
Definition embedder.h:1027
#define FLUTTER_ENGINE_VERSION
Definition embedder.h:70
@ kFlutterPointerDeviceKindMouse
Definition embedder.h:1006
GLFWwindow * window
Definition main.cc:45
FlutterEngine engine
Definition main.cc:68
sk_sp< SkImage > image
Definition examples.cpp:29
SkBitmap source
Definition examples.cpp:28
AtkStateType state
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
FlKeyEvent * event
GAsyncResult * result
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
const char * name
Definition fuchsia.cc:50
Win32Message message
char ** argv
Definition library.h:9
G_BEGIN_DECLS FlTextureRegistrar * texture_registrar
double y
double x
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:1594
size_t struct_size
The size of this struct. Must be sizeof(FlutterCustomTaskRunners).
Definition embedder.h:1589
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
ProcResolver gl_proc_resolver
Definition embedder.h:552
size_t struct_size
The size of this struct. Must be sizeof(FlutterOpenGLRendererConfig).
Definition embedder.h:513
BoolCallback make_resource_current
Definition embedder.h:535
size_t struct_size
The size of this struct. Must be sizeof(FlutterPlatformMessage).
Definition embedder.h:1162
const FlutterPlatformMessageResponseHandle * response_handle
Definition embedder.h:1172
const char * channel
Definition embedder.h:1163
const uint8_t * message
Definition embedder.h:1164
size_t struct_size
The size of this struct. Must be sizeof(FlutterPointerEvent).
Definition embedder.h:1034
double y
The y coordinate of the pointer event in physical pixels.
Definition embedder.h:1043
double x
The x coordinate of the pointer event in physical pixels.
Definition embedder.h:1041
FlutterPointerPhase phase
Definition embedder.h:1035
size_t struct_size
The size of this struct. Must be sizeof(FlutterProjectArgs).
Definition embedder.h:2138
FlutterOpenGLRendererConfig open_gl
Definition embedder.h:827
FlutterRendererType type
Definition embedder.h:825
size_t struct_size
The size of this struct. Must be sizeof(FlutterTaskRunnerDescription).
Definition embedder.h:1564
BoolCallback runs_task_on_current_thread_callback
Definition embedder.h:1570
FlutterTaskRunnerPostTaskCallback post_task_callback
Definition embedder.h:1581
size_t struct_size
The size of this struct. Must be sizeof(FlutterWindowMetricsEvent).
Definition embedder.h:841
int64_t texture_id