windows wrapper

This commit is contained in:
ekibun
2020-09-21 01:41:52 +08:00
parent 5f9fdac9f4
commit 9175871678
28 changed files with 618 additions and 582 deletions

View File

@@ -0,0 +1,14 @@
// This is a generated file; do not edit or check into version control.
FLUTTER_ROOT=D:\flutter
FLUTTER_APPLICATION_PATH=D:\project\vscode\neko\plugins\flutter_qjs\example
FLUTTER_TARGET=lib\main.dart
FLUTTER_BUILD_DIR=build
SYMROOT=${SOURCE_ROOT}/../build\ios
OTHER_LDFLAGS=$(inherited) -framework Flutter
FLUTTER_FRAMEWORK_DIR=D:\flutter\bin\cache\artifacts\engine\ios
FLUTTER_BUILD_NAME=1.0.0
FLUTTER_BUILD_NUMBER=1
DART_OBFUSCATION=false
TRACK_WIDGET_CREATION=false
TREE_SHAKE_ICONS=false
PACKAGE_CONFIG=.packages

View File

@@ -0,0 +1,15 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=D:\flutter"
export "FLUTTER_APPLICATION_PATH=D:\project\vscode\neko\plugins\flutter_qjs\example"
export "FLUTTER_TARGET=lib\main.dart"
export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build\ios"
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
export "FLUTTER_FRAMEWORK_DIR=D:\flutter\bin\cache\artifacts\engine\ios"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
export "DART_OBFUSCATION=false"
export "TRACK_WIDGET_CREATION=false"
export "TREE_SHAKE_ICONS=false"
export "PACKAGE_CONFIG=.packages"

View File

@@ -0,0 +1,17 @@
//
// Generated file. Do not edit.
//
#ifndef GeneratedPluginRegistrant_h
#define GeneratedPluginRegistrant_h
#import <Flutter/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface GeneratedPluginRegistrant : NSObject
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
@end
NS_ASSUME_NONNULL_END
#endif /* GeneratedPluginRegistrant_h */

View File

@@ -0,0 +1,12 @@
//
// Generated file. Do not edit.
//
#import "GeneratedPluginRegistrant.h"
@implementation GeneratedPluginRegistrant
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
}
@end

View File

@@ -3,7 +3,7 @@
* @Author: ekibun
* @Date: 2020-08-08 08:16:51
* @LastEditors: ekibun
* @LastEditTime: 2020-09-06 19:44:32
* @LastEditTime: 2020-09-21 01:20:17
*/
import 'package:flutter/material.dart';
import 'dart:typed_data';
@@ -53,7 +53,7 @@ class _TestPageState extends State<TestPage> {
_createEngine() async {
if (engine != null) return;
engine = FlutterQjs();
await engine.setMethodHandler((String method, List arg) async {
engine.setMethodHandler((String method, List arg) async {
switch (method) {
case "http":
Response response = await Dio().get(arg[0]);
@@ -72,14 +72,16 @@ class _TestPageState extends State<TestPage> {
Float32List(2)
]);
default:
return JsMethodHandlerNotImplement();
throw Exception("NotImplement");
}
});
await engine.setModuleHandler((String module) async {
engine.setModuleHandler((String module) {
if (module == "test") return "export default '${new DateTime.now()}'";
return await rootBundle.loadString(
"js/" + module.replaceFirst(new RegExp(r".js$"), "") + ".js");
return "";
// return await rootBundle.loadString(
// "js/" + module.replaceFirst(new RegExp(r".js$"), "") + ".js");
});
engine.dispatch();
}
@override
@@ -119,7 +121,7 @@ class _TestPageState extends State<TestPage> {
child: Text("close engine"),
onPressed: () async {
if (engine == null) return;
await engine.destroy();
await engine.close();
engine = null;
}),
],

View File

@@ -1 +0,0 @@
6

View File

@@ -7,12 +7,12 @@ add_executable(${BINARY_NAME} WIN32
"run_loop.cpp"
"utils.cpp"
"win32_window.cpp"
"window_configuration.cpp"
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
"Runner.rc"
"runner.exe.manifest"
)
apply_standard_settings(${BINARY_NAME})
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
add_dependencies(${BINARY_NAME} flutter_assemble)

View File

@@ -54,6 +54,57 @@ END
// remains consistent on all systems.
IDI_APP_ICON ICON "resources\\app_icon.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
#ifdef FLUTTER_BUILD_NUMBER
#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER
#else
#define VERSION_AS_NUMBER 1,0,0
#endif
#ifdef FLUTTER_BUILD_NAME
#define VERSION_AS_STRING #FLUTTER_BUILD_NAME
#else
#define VERSION_AS_STRING "1.0.0"
#endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_AS_NUMBER
PRODUCTVERSION VERSION_AS_NUMBER
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904e4"
BEGIN
VALUE "CompanyName", "soko.ekibun" "\0"
VALUE "FileDescription", "A new Flutter project." "\0"
VALUE "FileVersion", VERSION_AS_STRING "\0"
VALUE "InternalName", "example" "\0"
VALUE "LegalCopyright", "Copyright (C) 2020 soko.ekibun. All rights reserved." "\0"
VALUE "OriginalFilename", "example.exe" "\0"
VALUE "ProductName", "example" "\0"
VALUE "ProductVersion", VERSION_AS_STRING "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
#endif // English (United States) resources
/////////////////////////////////////////////////////////////////////////////

View File

@@ -15,22 +15,25 @@ bool FlutterWindow::OnCreate() {
return false;
}
// The size here is arbitrary since SetChildContent will resize it.
flutter_controller_ =
std::make_unique<flutter::FlutterViewController>(100, 100, project_);
RECT frame = GetClientArea();
// The size here must match the window dimensions to avoid unnecessary surface
// creation / destruction in the startup path.
flutter_controller_ = std::make_unique<flutter::FlutterViewController>(
frame.right - frame.left, frame.bottom - frame.top, project_);
// Ensure that basic setup of the controller was successful.
if (!flutter_controller_->engine() || !flutter_controller_->view()) {
return false;
}
RegisterPlugins(flutter_controller_.get());
run_loop_->RegisterFlutterInstance(flutter_controller_.get());
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_.get());
run_loop_->UnregisterFlutterInstance(flutter_controller_->engine());
flutter_controller_ = nullptr;
}
@@ -50,5 +53,12 @@ FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
return *result;
}
}
switch (message) {
case WM_FONTCHANGE:
flutter_controller_->engine()->ReloadSystemFonts();
break;
}
return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
}

View File

@@ -1,5 +1,5 @@
#ifndef FLUTTER_WINDOW_H_
#define FLUTTER_WINDOW_H_
#ifndef RUNNER_FLUTTER_WINDOW_H_
#define RUNNER_FLUTTER_WINDOW_H_
#include <flutter/dart_project.h>
#include <flutter/flutter_view_controller.h>
@@ -36,4 +36,4 @@ class FlutterWindow : public Win32Window {
std::unique_ptr<flutter::FlutterViewController> flutter_controller_;
};
#endif // FLUTTER_WINDOW_H_
#endif // RUNNER_FLUTTER_WINDOW_H_

View File

@@ -5,7 +5,6 @@
#include "flutter_window.h"
#include "run_loop.h"
#include "utils.h"
#include "window_configuration.h"
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
_In_ wchar_t *command_line, _In_ int show_command) {
@@ -23,9 +22,9 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
flutter::DartProject project(L"data");
FlutterWindow window(&run_loop, project);
Win32Window::Point origin(kFlutterWindowOriginX, kFlutterWindowOriginY);
Win32Window::Size size(kFlutterWindowWidth, kFlutterWindowHeight);
if (!window.CreateAndShow(kFlutterWindowTitle, origin, size)) {
Win32Window::Point origin(10, 10);
Win32Window::Size size(1280, 720);
if (!window.CreateAndShow(L"example", origin, size)) {
return EXIT_FAILURE;
}
window.SetQuitOnClose(true);

View File

@@ -1,9 +1,6 @@
#include "run_loop.h"
#include <Windows.h>
// Don't stomp std::min/std::max
#undef max
#undef min
#include <windows.h>
#include <algorithm>
@@ -47,20 +44,19 @@ void RunLoop::Run() {
}
void RunLoop::RegisterFlutterInstance(
flutter::FlutterViewController* flutter_instance) {
flutter::FlutterEngine* flutter_instance) {
flutter_instances_.insert(flutter_instance);
}
void RunLoop::UnregisterFlutterInstance(
flutter::FlutterViewController* flutter_instance) {
flutter::FlutterEngine* flutter_instance) {
flutter_instances_.erase(flutter_instance);
}
RunLoop::TimePoint RunLoop::ProcessFlutterMessages() {
TimePoint next_event_time = TimePoint::max();
for (auto flutter_controller : flutter_instances_) {
std::chrono::nanoseconds wait_duration =
flutter_controller->ProcessMessages();
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);

View File

@@ -1,7 +1,7 @@
#ifndef RUN_LOOP_H_
#define RUN_LOOP_H_
#ifndef RUNNER_RUN_LOOP_H_
#define RUNNER_RUN_LOOP_H_
#include <flutter/flutter_view_controller.h>
#include <flutter/flutter_engine.h>
#include <chrono>
#include <set>
@@ -22,11 +22,11 @@ class RunLoop {
// Registers the given Flutter instance for event servicing.
void RegisterFlutterInstance(
flutter::FlutterViewController* flutter_instance);
flutter::FlutterEngine* flutter_instance);
// Unregisters the given Flutter instance from event servicing.
void UnregisterFlutterInstance(
flutter::FlutterViewController* flutter_instance);
flutter::FlutterEngine* flutter_instance);
private:
using TimePoint = std::chrono::steady_clock::time_point;
@@ -34,7 +34,7 @@ class RunLoop {
// Processes all currently pending messages for registered Flutter instances.
TimePoint ProcessFlutterMessages();
std::set<flutter::FlutterViewController*> flutter_instances_;
std::set<flutter::FlutterEngine*> flutter_instances_;
};
#endif // RUN_LOOP_H_
#endif // RUNNER_RUN_LOOP_H_

View File

@@ -1,8 +1,8 @@
#ifndef CONSOLE_UTILS_H_
#define CONSOLE_UTILS_H_
#ifndef RUNNER_UTILS_H_
#define RUNNER_UTILS_H_
// Creates a console for the process, and redirects stdout and stderr to
// it for both the runner and the Flutter library.
void CreateAndAttachConsole();
#endif // CONSOLE_UTILS_H_
#endif // RUNNER_UTILS_H_

View File

@@ -174,8 +174,7 @@ Win32Window::MessageHandler(HWND hwnd,
return 0;
}
case WM_SIZE:
RECT rect;
GetClientRect(hwnd, &rect);
RECT rect = GetClientArea();
if (child_content_ != nullptr) {
// Size and position the child window.
MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left,
@@ -188,11 +187,6 @@ Win32Window::MessageHandler(HWND hwnd,
SetFocus(child_content_);
}
return 0;
// Messages that are directly forwarded to embedding.
case WM_FONTCHANGE:
SendMessage(child_content_, WM_FONTCHANGE, NULL, NULL);
return 0;
}
return DefWindowProc(window_handle_, message, wparam, lparam);
@@ -218,8 +212,7 @@ Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept {
void Win32Window::SetChildContent(HWND content) {
child_content_ = content;
SetParent(content, window_handle_);
RECT frame;
GetClientRect(window_handle_, &frame);
RECT frame = GetClientArea();
MoveWindow(content, frame.left, frame.top, frame.right - frame.left,
frame.bottom - frame.top, true);
@@ -227,6 +220,12 @@ void Win32Window::SetChildContent(HWND content) {
SetFocus(child_content_);
}
RECT Win32Window::GetClientArea() {
RECT frame;
GetClientRect(window_handle_, &frame);
return frame;
}
HWND Win32Window::GetHandle() {
return window_handle_;
}

View File

@@ -1,8 +1,7 @@
#ifndef WIN32_WINDOW_H_
#define WIN32_WINDOW_H_
#ifndef RUNNER_WIN32_WINDOW_H_
#define RUNNER_WIN32_WINDOW_H_
#include <Windows.h>
#include <Windowsx.h>
#include <windows.h>
#include <functional>
#include <memory>
@@ -52,6 +51,9 @@ class Win32Window {
// If true, closing this window will quit the application.
void SetQuitOnClose(bool quit_on_close);
// Return a RECT representing the bounds of the current client area.
RECT GetClientArea();
protected:
// Processes and route salient window messages for mouse handling,
// size change and DPI. Delegates handling of these to member overloads that
@@ -93,4 +95,4 @@ class Win32Window {
HWND child_content_ = nullptr;
};
#endif // WIN32_WINDOW_H_
#endif // RUNNER_WIN32_WINDOW_H_

View File

@@ -1,7 +0,0 @@
#include "window_configuration.h"
const wchar_t* kFlutterWindowTitle = L"example";
const unsigned int kFlutterWindowOriginX = 10;
const unsigned int kFlutterWindowOriginY = 10;
const unsigned int kFlutterWindowWidth = 1280;
const unsigned int kFlutterWindowHeight = 720;

View File

@@ -1,18 +0,0 @@
#ifndef WINDOW_CONFIGURATION_
#define WINDOW_CONFIGURATION_
// This is a temporary approach to isolate changes that people are likely to
// make to main.cpp, where the APIs are still in flux. This will reduce the
// need to resolve conflicts or re-create changes slightly differently every
// time the Windows Flutter API surface changes.
//
// Longer term there should be simpler configuration options for common
// customizations like this, without requiring native code changes.
extern const wchar_t* kFlutterWindowTitle;
extern const unsigned int kFlutterWindowOriginX;
extern const unsigned int kFlutterWindowOriginY;
extern const unsigned int kFlutterWindowWidth;
extern const unsigned int kFlutterWindowHeight;
#endif // WINDOW_CONFIGURATION_