1515#include " flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h"
1616#include " flutter/shell/platform/common/cpp/incoming_message_dispatcher.h"
1717#include " flutter/shell/platform/embedder/embedder.h"
18+ #include " flutter/shell/platform/glfw/glfw_event_loop.h"
1819#include " flutter/shell/platform/glfw/key_event_handler.h"
1920#include " flutter/shell/platform/glfw/keyboard_hook_handler.h"
2021#include " flutter/shell/platform/glfw/platform_handler.h"
@@ -79,8 +80,11 @@ struct FlutterDesktopWindowControllerState {
7980 // Handler for the flutter/platform channel.
8081 std::unique_ptr<flutter::PlatformHandler> platform_handler;
8182
82- // Whether or not the pointer has been added (or if tracking is enabled, has
83- // been added since it was last removed).
83+ // The event loop for the main thread that allows for delayed task execution.
84+ std::unique_ptr<flutter::GLFWEventLoop> event_loop;
85+
86+ // Whether or not the pointer has been added (or if tracking is enabled,
87+ // has been added since it was last removed).
8488 bool pointer_currently_added = false ;
8589
8690 // The screen coordinates per inch on the primary monitor. Defaults to a sane
@@ -489,11 +493,13 @@ static void GLFWErrorCallback(int error_code, const char* description) {
489493// provided).
490494//
491495// Returns a caller-owned pointer to the engine.
492- static FlutterEngine RunFlutterEngine (GLFWwindow* window,
493- const char * assets_path,
494- const char * icu_data_path,
495- const char ** arguments,
496- size_t arguments_count) {
496+ static FlutterEngine RunFlutterEngine (
497+ GLFWwindow* window,
498+ const char * assets_path,
499+ const char * icu_data_path,
500+ const char ** arguments,
501+ size_t arguments_count,
502+ const FlutterCustomTaskRunners* custom_task_runners) {
497503 // FlutterProjectArgs is expecting a full argv, so when processing it for
498504 // flags the first item is treated as the executable and ignored. Add a dummy
499505 // value so that all provided arguments are used.
@@ -528,6 +534,7 @@ static FlutterEngine RunFlutterEngine(GLFWwindow* window,
528534 args.command_line_argc = static_cast <int >(argv.size ());
529535 args.command_line_argv = &argv[0 ];
530536 args.platform_message_callback = GLFWOnFlutterPlatformMessage;
537+ args.custom_task_runners = custom_task_runners;
531538 FlutterEngine engine = nullptr ;
532539 auto result =
533540 FlutterEngineRun (FLUTTER_ENGINE_VERSION, &config, &args, window, &engine);
@@ -578,9 +585,38 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow(
578585 // GLFWMakeResourceContextCurrent immediately.
579586 state->resource_window = CreateShareWindowForWindow (window);
580587
588+ // Create an event loop for the window. It is not running yet.
589+ state->event_loop = std::make_unique<flutter::GLFWEventLoop>(
590+ std::this_thread::get_id (), // main GLFW thread
591+ [state = state.get ()](const auto * task) {
592+ if (FlutterEngineRunTask (state->engine , task) != kSuccess ) {
593+ std::cerr << " Could not post an engine task." << std::endl;
594+ }
595+ });
596+
597+ // Configure task runner interop.
598+ FlutterTaskRunnerDescription platform_task_runner = {};
599+ platform_task_runner.struct_size = sizeof (FlutterTaskRunnerDescription);
600+ platform_task_runner.user_data = state.get ();
601+ platform_task_runner.runs_task_on_current_thread_callback =
602+ [](void * state) -> bool {
603+ return reinterpret_cast <FlutterDesktopWindowControllerState*>(state)
604+ ->event_loop ->RunsTasksOnCurrentThread ();
605+ };
606+ platform_task_runner.post_task_callback =
607+ [](FlutterTask task, uint64_t target_time_nanos, void * state) -> void {
608+ reinterpret_cast <FlutterDesktopWindowControllerState*>(state)
609+ ->event_loop ->PostTask (task, target_time_nanos);
610+ };
611+
612+ FlutterCustomTaskRunners custom_task_runners = {};
613+ custom_task_runners.struct_size = sizeof (FlutterCustomTaskRunners);
614+ custom_task_runners.platform_task_runner = &platform_task_runner;
615+
581616 // Start the engine.
582- state->engine = RunFlutterEngine (window, assets_path, icu_data_path,
583- arguments, argument_count);
617+ state->engine =
618+ RunFlutterEngine (window, assets_path, icu_data_path, arguments,
619+ argument_count, &custom_task_runners);
584620 if (state->engine == nullptr ) {
585621 return nullptr ;
586622 }
@@ -704,15 +740,17 @@ void FlutterDesktopRunWindowLoop(FlutterDesktopWindowControllerRef controller) {
704740 // Necessary for GTK thread safety.
705741 XInitThreads ();
706742#endif
743+
707744 while (!glfwWindowShouldClose (window)) {
708- glfwPollEvents ();
745+ auto wait_duration = std::chrono::milliseconds::max ();
709746#ifdef FLUTTER_USE_GTK
747+ // If we are not using GTK, there is no point in waking up.
748+ wait_duration = std::chrono::milliseconds (10 );
710749 if (gtk_events_pending ()) {
711750 gtk_main_iteration ();
712751 }
713752#endif
714- // TODO(awdavies): This will be deprecated soon.
715- __FlutterEngineFlushPendingTasksNow ();
753+ controller->event_loop ->WaitForEvents (wait_duration);
716754 }
717755 FlutterDesktopDestroyWindow (controller);
718756}
@@ -738,8 +776,9 @@ FlutterDesktopEngineRef FlutterDesktopRunEngine(const char* assets_path,
738776 const char * icu_data_path,
739777 const char ** arguments,
740778 size_t argument_count) {
741- auto engine = RunFlutterEngine (nullptr , assets_path, icu_data_path, arguments,
742- argument_count);
779+ auto engine =
780+ RunFlutterEngine (nullptr , assets_path, icu_data_path, arguments,
781+ argument_count, nullptr /* custom task runners */ );
743782 if (engine == nullptr ) {
744783 return nullptr ;
745784 }
0 commit comments