Unverified Commit b3bde1d9 authored by Jason Simmons's avatar Jason Simmons Committed by GitHub

Update the Windows runner for Gallery (#84020)

parent 190a1a4a
...@@ -23,6 +23,7 @@ list(APPEND FLUTTER_LIBRARY_HEADERS ...@@ -23,6 +23,7 @@ list(APPEND FLUTTER_LIBRARY_HEADERS
"flutter_windows.h" "flutter_windows.h"
"flutter_messenger.h" "flutter_messenger.h"
"flutter_plugin_registrar.h" "flutter_plugin_registrar.h"
"flutter_texture_registrar.h"
) )
list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/")
add_library(flutter INTERFACE) add_library(flutter INTERFACE)
...@@ -91,6 +92,7 @@ add_custom_command( ...@@ -91,6 +92,7 @@ add_custom_command(
${FLUTTER_TOOL_ENVIRONMENT} ${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat"
windows-x64 $<CONFIG> windows-x64 $<CONFIG>
VERBATIM
) )
add_custom_target(flutter_assemble DEPENDS add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}" "${FLUTTER_LIBRARY}"
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Generated file. Do not edit. // Generated file. Do not edit.
// //
// clang-format off
#include "generated_plugin_registrant.h" #include "generated_plugin_registrant.h"
#include <url_launcher_windows/url_launcher_plugin.h> #include <url_launcher_windows/url_launcher_plugin.h>
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
// Generated file. Do not edit. // Generated file. Do not edit.
// //
// clang-format off
#ifndef GENERATED_PLUGIN_REGISTRANT_ #ifndef GENERATED_PLUGIN_REGISTRANT_
#define GENERATED_PLUGIN_REGISTRANT_ #define GENERATED_PLUGIN_REGISTRANT_
......
...@@ -4,7 +4,6 @@ project(runner LANGUAGES CXX) ...@@ -4,7 +4,6 @@ project(runner LANGUAGES CXX)
add_executable(${BINARY_NAME} WIN32 add_executable(${BINARY_NAME} WIN32
"flutter_window.cpp" "flutter_window.cpp"
"main.cpp" "main.cpp"
"run_loop.cpp"
"utils.cpp" "utils.cpp"
"win32_window.cpp" "win32_window.cpp"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
......
...@@ -45,6 +45,16 @@ END ...@@ -45,6 +45,16 @@ END
#endif // APSTUDIO_INVOKED #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 // Version
...@@ -79,11 +89,11 @@ BEGIN ...@@ -79,11 +89,11 @@ BEGIN
BEGIN BEGIN
BLOCK "040904e4" BLOCK "040904e4"
BEGIN BEGIN
VALUE "CompanyName", "io.flutter.demo" "\0" VALUE "CompanyName", "com.example" "\0"
VALUE "FileDescription", "A new Flutter project." "\0" VALUE "FileDescription", "A new Flutter project." "\0"
VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "FileVersion", VERSION_AS_STRING "\0"
VALUE "InternalName", "flutter_gallery" "\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 "OriginalFilename", "flutter_gallery.exe" "\0"
VALUE "ProductName", "flutter_gallery" "\0" VALUE "ProductName", "flutter_gallery" "\0"
VALUE "ProductVersion", VERSION_AS_STRING "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0"
......
...@@ -4,9 +4,8 @@ ...@@ -4,9 +4,8 @@
#include "flutter/generated_plugin_registrant.h" #include "flutter/generated_plugin_registrant.h"
FlutterWindow::FlutterWindow(RunLoop* run_loop, FlutterWindow::FlutterWindow(const flutter::DartProject& project)
const flutter::DartProject& project) : project_(project) {}
: run_loop_(run_loop), project_(project) {}
FlutterWindow::~FlutterWindow() {} FlutterWindow::~FlutterWindow() {}
...@@ -26,14 +25,12 @@ bool FlutterWindow::OnCreate() { ...@@ -26,14 +25,12 @@ bool FlutterWindow::OnCreate() {
return false; return false;
} }
RegisterPlugins(flutter_controller_->engine()); RegisterPlugins(flutter_controller_->engine());
run_loop_->RegisterFlutterInstance(flutter_controller_->engine());
SetChildContent(flutter_controller_->view()->GetNativeWindow()); SetChildContent(flutter_controller_->view()->GetNativeWindow());
return true; return true;
} }
void FlutterWindow::OnDestroy() { void FlutterWindow::OnDestroy() {
if (flutter_controller_) { if (flutter_controller_) {
run_loop_->UnregisterFlutterInstance(flutter_controller_->engine());
flutter_controller_ = nullptr; flutter_controller_ = nullptr;
} }
...@@ -44,7 +41,7 @@ LRESULT ...@@ -44,7 +41,7 @@ LRESULT
FlutterWindow::MessageHandler(HWND hwnd, UINT const message, FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
WPARAM const wparam, WPARAM const wparam,
LPARAM const lparam) noexcept { 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_) { if (flutter_controller_) {
std::optional<LRESULT> result = std::optional<LRESULT> result =
flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
......
...@@ -10,16 +10,13 @@ ...@@ -10,16 +10,13 @@
#include <memory> #include <memory>
#include "run_loop.h"
#include "win32_window.h" #include "win32_window.h"
// A window that does nothing but host a Flutter view. // A window that does nothing but host a Flutter view.
class FlutterWindow : public Win32Window { class FlutterWindow : public Win32Window {
public: public:
// Creates a new FlutterWindow driven by the |run_loop|, hosting a // Creates a new FlutterWindow hosting a Flutter view running |project|.
// Flutter view running |project|. explicit FlutterWindow(const flutter::DartProject& project);
explicit FlutterWindow(RunLoop* run_loop,
const flutter::DartProject& project);
virtual ~FlutterWindow(); virtual ~FlutterWindow();
protected: protected:
...@@ -30,9 +27,6 @@ class FlutterWindow : public Win32Window { ...@@ -30,9 +27,6 @@ class FlutterWindow : public Win32Window {
LPARAM const lparam) noexcept override; LPARAM const lparam) noexcept override;
private: private:
// The run loop driving events for this window.
RunLoop* run_loop_;
// The project to run. // The project to run.
flutter::DartProject project_; flutter::DartProject project_;
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
#include <windows.h> #include <windows.h>
#include "flutter_window.h" #include "flutter_window.h"
#include "run_loop.h"
#include "utils.h" #include "utils.h"
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
...@@ -18,10 +17,14 @@ 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. // plugins.
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
RunLoop run_loop;
flutter::DartProject project(L"data"); flutter::DartProject project(L"data");
FlutterWindow window(&run_loop, project);
std::vector<std::string> command_line_arguments =
GetCommandLineArguments();
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
FlutterWindow window(project);
Win32Window::Point origin(10, 10); Win32Window::Point origin(10, 10);
Win32Window::Size size(1280, 720); Win32Window::Size size(1280, 720);
if (!window.CreateAndShow(L"flutter_gallery", origin, size)) { if (!window.CreateAndShow(L"flutter_gallery", origin, size)) {
...@@ -29,7 +32,11 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, ...@@ -29,7 +32,11 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
} }
window.SetQuitOnClose(true); window.SetQuitOnClose(true);
run_loop.Run(); ::MSG msg;
while (::GetMessage(&msg, nullptr, 0, 0)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
::CoUninitialize(); ::CoUninitialize();
return EXIT_SUCCESS; return EXIT_SUCCESS;
......
#include "run_loop.h"
#include <windows.h>
#include <algorithm>
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<DWORD>(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;
}
// 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 <flutter/flutter_engine.h>
#include <chrono>
#include <set>
// 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::FlutterEngine*> flutter_instances_;
};
#endif // RUNNER_RUN_LOOP_H_
...@@ -20,3 +20,45 @@ void CreateAndAttachConsole() { ...@@ -20,3 +20,45 @@ void CreateAndAttachConsole() {
FlutterDesktopResyncOutputStreams(); FlutterDesktopResyncOutputStreams();
} }
} }
std::vector<std::string> 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::string>();
}
std::vector<std::string> 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;
}
...@@ -5,8 +5,19 @@ ...@@ -5,8 +5,19 @@
#ifndef RUNNER_UTILS_H_ #ifndef RUNNER_UTILS_H_
#define RUNNER_UTILS_H_ #define RUNNER_UTILS_H_
#include <string>
#include <vector>
// Creates a console for the process, and redirects stdout and stderr to // Creates a console for the process, and redirects stdout and stderr to
// it for both the runner and the Flutter library. // it for both the runner and the Flutter library.
void CreateAndAttachConsole(); 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<std::string>,
// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
std::vector<std::string> GetCommandLineArguments();
#endif // RUNNER_UTILS_H_ #endif // RUNNER_UTILS_H_
...@@ -173,7 +173,7 @@ Win32Window::MessageHandler(HWND hwnd, ...@@ -173,7 +173,7 @@ Win32Window::MessageHandler(HWND hwnd,
return 0; return 0;
} }
case WM_SIZE: case WM_SIZE: {
RECT rect = GetClientArea(); RECT rect = GetClientArea();
if (child_content_ != nullptr) { if (child_content_ != nullptr) {
// Size and position the child window. // Size and position the child window.
...@@ -181,6 +181,7 @@ Win32Window::MessageHandler(HWND hwnd, ...@@ -181,6 +181,7 @@ Win32Window::MessageHandler(HWND hwnd,
rect.bottom - rect.top, TRUE); rect.bottom - rect.top, TRUE);
} }
return 0; return 0;
}
case WM_ACTIVATE: case WM_ACTIVATE:
if (child_content_ != nullptr) { if (child_content_ != nullptr) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment