From b3bde1d9da170ee6577b3292f19fb209ec3a7f45 Mon Sep 17 00:00:00 2001 From: Jason Simmons Date: Mon, 7 Jun 2021 16:04:03 -0700 Subject: [PATCH] Update the Windows runner for Gallery (#84020) --- .../windows/flutter/CMakeLists.txt | 2 + .../flutter/generated_plugin_registrant.cc | 2 + .../flutter/generated_plugin_registrant.h | 2 + .../windows/runner/CMakeLists.txt | 1 - .../flutter_gallery/windows/runner/Runner.rc | 14 +++- .../windows/runner/flutter_window.cpp | 9 +-- .../windows/runner/flutter_window.h | 10 +-- .../flutter_gallery/windows/runner/main.cpp | 17 +++-- .../windows/runner/run_loop.cpp | 66 ------------------- .../flutter_gallery/windows/runner/run_loop.h | 44 ------------- .../flutter_gallery/windows/runner/utils.cpp | 42 ++++++++++++ .../flutter_gallery/windows/runner/utils.h | 11 ++++ .../windows/runner/win32_window.cpp | 3 +- 13 files changed, 90 insertions(+), 133 deletions(-) delete mode 100644 dev/integration_tests/flutter_gallery/windows/runner/run_loop.cpp delete mode 100644 dev/integration_tests/flutter_gallery/windows/runner/run_loop.h diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt b/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt index c7a8c7607d8..b02c5485c95 100644 --- a/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt +++ b/dev/integration_tests/flutter_gallery/windows/flutter/CMakeLists.txt @@ -23,6 +23,7 @@ list(APPEND FLUTTER_LIBRARY_HEADERS "flutter_windows.h" "flutter_messenger.h" "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" ) list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") add_library(flutter INTERFACE) @@ -91,6 +92,7 @@ add_custom_command( ${FLUTTER_TOOL_ENVIRONMENT} "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" windows-x64 $ + VERBATIM ) add_custom_target(flutter_assemble DEPENDS "${FLUTTER_LIBRARY}" diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc index ddfcf7c328e..d9fdd53925c 100644 --- a/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc +++ b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.cc @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #include "generated_plugin_registrant.h" #include diff --git a/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h index 9846246b4da..dc139d85a93 100644 --- a/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h +++ b/dev/integration_tests/flutter_gallery/windows/flutter/generated_plugin_registrant.h @@ -2,6 +2,8 @@ // Generated file. Do not edit. // +// clang-format off + #ifndef GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_ diff --git a/dev/integration_tests/flutter_gallery/windows/runner/CMakeLists.txt b/dev/integration_tests/flutter_gallery/windows/runner/CMakeLists.txt index 977e38b5d1d..0b899a0bcf1 100644 --- a/dev/integration_tests/flutter_gallery/windows/runner/CMakeLists.txt +++ b/dev/integration_tests/flutter_gallery/windows/runner/CMakeLists.txt @@ -4,7 +4,6 @@ project(runner LANGUAGES CXX) add_executable(${BINARY_NAME} WIN32 "flutter_window.cpp" "main.cpp" - "run_loop.cpp" "utils.cpp" "win32_window.cpp" "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" diff --git a/dev/integration_tests/flutter_gallery/windows/runner/Runner.rc b/dev/integration_tests/flutter_gallery/windows/runner/Runner.rc index 089c56cd98a..4ed0d4a2e86 100644 --- a/dev/integration_tests/flutter_gallery/windows/runner/Runner.rc +++ b/dev/integration_tests/flutter_gallery/windows/runner/Runner.rc @@ -45,6 +45,16 @@ END #endif // APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +// IDI_APP_ICON ICON "resources\\app_icon.ico" + + ///////////////////////////////////////////////////////////////////////////// // // Version @@ -79,11 +89,11 @@ BEGIN BEGIN BLOCK "040904e4" BEGIN - VALUE "CompanyName", "io.flutter.demo" "\0" + VALUE "CompanyName", "com.example" "\0" VALUE "FileDescription", "A new Flutter project." "\0" VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "flutter_gallery" "\0" - VALUE "LegalCopyright", "Copyright (C) 2020 io.flutter.demo. All rights reserved." "\0" + VALUE "LegalCopyright", "Copyright (C) 2021 com.example. All rights reserved." "\0" VALUE "OriginalFilename", "flutter_gallery.exe" "\0" VALUE "ProductName", "flutter_gallery" "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" diff --git a/dev/integration_tests/flutter_gallery/windows/runner/flutter_window.cpp b/dev/integration_tests/flutter_gallery/windows/runner/flutter_window.cpp index c422723045c..b43b9095ea3 100644 --- a/dev/integration_tests/flutter_gallery/windows/runner/flutter_window.cpp +++ b/dev/integration_tests/flutter_gallery/windows/runner/flutter_window.cpp @@ -4,9 +4,8 @@ #include "flutter/generated_plugin_registrant.h" -FlutterWindow::FlutterWindow(RunLoop* run_loop, - const flutter::DartProject& project) - : run_loop_(run_loop), project_(project) {} +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} FlutterWindow::~FlutterWindow() {} @@ -26,14 +25,12 @@ bool FlutterWindow::OnCreate() { return false; } RegisterPlugins(flutter_controller_->engine()); - run_loop_->RegisterFlutterInstance(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); return true; } void FlutterWindow::OnDestroy() { if (flutter_controller_) { - run_loop_->UnregisterFlutterInstance(flutter_controller_->engine()); flutter_controller_ = nullptr; } @@ -44,7 +41,7 @@ LRESULT FlutterWindow::MessageHandler(HWND hwnd, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept { - // Give Flutter, including plugins, an opporutunity to handle window messages. + // Give Flutter, including plugins, an opportunity to handle window messages. if (flutter_controller_) { std::optional result = flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, diff --git a/dev/integration_tests/flutter_gallery/windows/runner/flutter_window.h b/dev/integration_tests/flutter_gallery/windows/runner/flutter_window.h index 62c11f15c3d..bbc5836c018 100644 --- a/dev/integration_tests/flutter_gallery/windows/runner/flutter_window.h +++ b/dev/integration_tests/flutter_gallery/windows/runner/flutter_window.h @@ -10,16 +10,13 @@ #include -#include "run_loop.h" #include "win32_window.h" // A window that does nothing but host a Flutter view. class FlutterWindow : public Win32Window { public: - // Creates a new FlutterWindow driven by the |run_loop|, hosting a - // Flutter view running |project|. - explicit FlutterWindow(RunLoop* run_loop, - const flutter::DartProject& project); + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); virtual ~FlutterWindow(); protected: @@ -30,9 +27,6 @@ class FlutterWindow : public Win32Window { LPARAM const lparam) noexcept override; private: - // The run loop driving events for this window. - RunLoop* run_loop_; - // The project to run. flutter::DartProject project_; diff --git a/dev/integration_tests/flutter_gallery/windows/runner/main.cpp b/dev/integration_tests/flutter_gallery/windows/runner/main.cpp index cd684fb0fad..f27ad3cdd5f 100644 --- a/dev/integration_tests/flutter_gallery/windows/runner/main.cpp +++ b/dev/integration_tests/flutter_gallery/windows/runner/main.cpp @@ -3,7 +3,6 @@ #include #include "flutter_window.h" -#include "run_loop.h" #include "utils.h" int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, @@ -18,10 +17,14 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, // plugins. ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - RunLoop run_loop; - flutter::DartProject project(L"data"); - FlutterWindow window(&run_loop, project); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); if (!window.CreateAndShow(L"flutter_gallery", origin, size)) { @@ -29,7 +32,11 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, } window.SetQuitOnClose(true); - run_loop.Run(); + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } ::CoUninitialize(); return EXIT_SUCCESS; diff --git a/dev/integration_tests/flutter_gallery/windows/runner/run_loop.cpp b/dev/integration_tests/flutter_gallery/windows/runner/run_loop.cpp deleted file mode 100644 index 2d6636ab6bc..00000000000 --- a/dev/integration_tests/flutter_gallery/windows/runner/run_loop.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "run_loop.h" - -#include - -#include - -RunLoop::RunLoop() {} - -RunLoop::~RunLoop() {} - -void RunLoop::Run() { - bool keep_running = true; - TimePoint next_flutter_event_time = TimePoint::clock::now(); - while (keep_running) { - std::chrono::nanoseconds wait_duration = - std::max(std::chrono::nanoseconds(0), - next_flutter_event_time - TimePoint::clock::now()); - ::MsgWaitForMultipleObjects( - 0, nullptr, FALSE, static_cast(wait_duration.count() / 1000), - QS_ALLINPUT); - bool processed_events = false; - MSG message; - // All pending Windows messages must be processed; MsgWaitForMultipleObjects - // won't return again for items left in the queue after PeekMessage. - while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { - processed_events = true; - if (message.message == WM_QUIT) { - keep_running = false; - break; - } - ::TranslateMessage(&message); - ::DispatchMessage(&message); - // Allow Flutter to process messages each time a Windows message is - // processed, to prevent starvation. - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - // If the PeekMessage loop didn't run, process Flutter messages. - if (!processed_events) { - next_flutter_event_time = - std::min(next_flutter_event_time, ProcessFlutterMessages()); - } - } -} - -void RunLoop::RegisterFlutterInstance( - flutter::FlutterEngine* flutter_instance) { - flutter_instances_.insert(flutter_instance); -} - -void RunLoop::UnregisterFlutterInstance( - flutter::FlutterEngine* flutter_instance) { - flutter_instances_.erase(flutter_instance); -} - -RunLoop::TimePoint RunLoop::ProcessFlutterMessages() { - TimePoint next_event_time = TimePoint::max(); - for (auto instance : flutter_instances_) { - std::chrono::nanoseconds wait_duration = instance->ProcessMessages(); - if (wait_duration != std::chrono::nanoseconds::max()) { - next_event_time = - std::min(next_event_time, TimePoint::clock::now() + wait_duration); - } - } - return next_event_time; -} diff --git a/dev/integration_tests/flutter_gallery/windows/runner/run_loop.h b/dev/integration_tests/flutter_gallery/windows/runner/run_loop.h deleted file mode 100644 index 441e7b1cd10..00000000000 --- a/dev/integration_tests/flutter_gallery/windows/runner/run_loop.h +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef RUNNER_RUN_LOOP_H_ -#define RUNNER_RUN_LOOP_H_ - -#include - -#include -#include - -// A runloop that will service events for Flutter instances as well -// as native messages. -class RunLoop { - public: - RunLoop(); - ~RunLoop(); - - // Prevent copying - RunLoop(RunLoop const&) = delete; - RunLoop& operator=(RunLoop const&) = delete; - - // Runs the run loop until the application quits. - void Run(); - - // Registers the given Flutter instance for event servicing. - void RegisterFlutterInstance( - flutter::FlutterEngine* flutter_instance); - - // Unregisters the given Flutter instance from event servicing. - void UnregisterFlutterInstance( - flutter::FlutterEngine* flutter_instance); - - private: - using TimePoint = std::chrono::steady_clock::time_point; - - // Processes all currently pending messages for registered Flutter instances. - TimePoint ProcessFlutterMessages(); - - std::set flutter_instances_; -}; - -#endif // RUNNER_RUN_LOOP_H_ diff --git a/dev/integration_tests/flutter_gallery/windows/runner/utils.cpp b/dev/integration_tests/flutter_gallery/windows/runner/utils.cpp index 37501e5db77..d19bdbbcc32 100644 --- a/dev/integration_tests/flutter_gallery/windows/runner/utils.cpp +++ b/dev/integration_tests/flutter_gallery/windows/runner/utils.cpp @@ -20,3 +20,45 @@ void CreateAndAttachConsole() { FlutterDesktopResyncOutputStreams(); } } + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/dev/integration_tests/flutter_gallery/windows/runner/utils.h b/dev/integration_tests/flutter_gallery/windows/runner/utils.h index 23078fcb9cb..54414c989ba 100644 --- a/dev/integration_tests/flutter_gallery/windows/runner/utils.h +++ b/dev/integration_tests/flutter_gallery/windows/runner/utils.h @@ -5,8 +5,19 @@ #ifndef RUNNER_UTILS_H_ #define RUNNER_UTILS_H_ +#include +#include + // Creates a console for the process, and redirects stdout and stderr to // it for both the runner and the Flutter library. void CreateAndAttachConsole(); +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + #endif // RUNNER_UTILS_H_ diff --git a/dev/integration_tests/flutter_gallery/windows/runner/win32_window.cpp b/dev/integration_tests/flutter_gallery/windows/runner/win32_window.cpp index efc3eb9f226..c10f08dc7da 100644 --- a/dev/integration_tests/flutter_gallery/windows/runner/win32_window.cpp +++ b/dev/integration_tests/flutter_gallery/windows/runner/win32_window.cpp @@ -173,7 +173,7 @@ Win32Window::MessageHandler(HWND hwnd, return 0; } - case WM_SIZE: + case WM_SIZE: { RECT rect = GetClientArea(); if (child_content_ != nullptr) { // Size and position the child window. @@ -181,6 +181,7 @@ Win32Window::MessageHandler(HWND hwnd, rect.bottom - rect.top, TRUE); } return 0; + } case WM_ACTIVATE: if (child_content_ != nullptr) {