未验证 提交 3295beba 编写于 作者: J James Clarke 提交者: GitHub

Windows: Add UWP target stub [Flutter#14697] (#21754)

上级 1f1c6d25
......@@ -152,10 +152,15 @@ group("flutter") {
}
if (is_win) {
public_deps += [
"//flutter/shell/platform/windows:flutter_windows_unittests",
"//flutter/shell/platform/windows/client_wrapper:client_wrapper_windows_unittests",
]
if (target_os == "winuwp") {
# TODO: Add winnup variant of the unit tests here; see
# https://github.com/flutter/flutter/issues/70197
} else {
public_deps += [
"//flutter/shell/platform/windows:flutter_windows_unittests",
"//flutter/shell/platform/windows/client_wrapper:client_wrapper_windows_unittests",
]
}
}
}
}
......
......@@ -1408,9 +1408,18 @@ FILE: ../../../flutter/shell/platform/windows/flutter_windows_engine.h
FILE: ../../../flutter/shell/platform/windows/flutter_windows_engine_unittests.cc
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.cc
FILE: ../../../flutter/shell/platform/windows/flutter_windows_view.h
FILE: ../../../flutter/shell/platform/windows/flutter_windows_win32.cc
FILE: ../../../flutter/shell/platform/windows/flutter_windows_winuwp.cc
FILE: ../../../flutter/shell/platform/windows/key_event_handler.cc
FILE: ../../../flutter/shell/platform/windows/key_event_handler.h
FILE: ../../../flutter/shell/platform/windows/keyboard_hook_handler.h
FILE: ../../../flutter/shell/platform/windows/platform_handler.cc
FILE: ../../../flutter/shell/platform/windows/platform_handler.h
FILE: ../../../flutter/shell/platform/windows/platform_handler_unittests.cc
FILE: ../../../flutter/shell/platform/windows/platform_handler_win32.cc
FILE: ../../../flutter/shell/platform/windows/platform_handler_win32.h
FILE: ../../../flutter/shell/platform/windows/platform_handler_winuwp.cc
FILE: ../../../flutter/shell/platform/windows/platform_handler_winuwp.h
FILE: ../../../flutter/shell/platform/windows/public/flutter_windows.h
FILE: ../../../flutter/shell/platform/windows/string_conversion.cc
FILE: ../../../flutter/shell/platform/windows/string_conversion.h
......@@ -1418,6 +1427,12 @@ FILE: ../../../flutter/shell/platform/windows/string_conversion_unittests.cc
FILE: ../../../flutter/shell/platform/windows/system_utils.h
FILE: ../../../flutter/shell/platform/windows/system_utils_unittests.cc
FILE: ../../../flutter/shell/platform/windows/system_utils_win32.cc
FILE: ../../../flutter/shell/platform/windows/system_utils_winuwp.cc
FILE: ../../../flutter/shell/platform/windows/task_runner.h
FILE: ../../../flutter/shell/platform/windows/task_runner_win32.cc
FILE: ../../../flutter/shell/platform/windows/task_runner_win32.h
FILE: ../../../flutter/shell/platform/windows/task_runner_winuwp.cc
FILE: ../../../flutter/shell/platform/windows/task_runner_winuwp.h
FILE: ../../../flutter/shell/platform/windows/text_input_plugin.cc
FILE: ../../../flutter/shell/platform/windows/text_input_plugin.h
FILE: ../../../flutter/shell/platform/windows/win32_dpi_utils.cc
......@@ -1426,10 +1441,6 @@ FILE: ../../../flutter/shell/platform/windows/win32_dpi_utils_unittests.cc
FILE: ../../../flutter/shell/platform/windows/win32_flutter_window.cc
FILE: ../../../flutter/shell/platform/windows/win32_flutter_window.h
FILE: ../../../flutter/shell/platform/windows/win32_flutter_window_unittests.cc
FILE: ../../../flutter/shell/platform/windows/win32_platform_handler.cc
FILE: ../../../flutter/shell/platform/windows/win32_platform_handler.h
FILE: ../../../flutter/shell/platform/windows/win32_task_runner.cc
FILE: ../../../flutter/shell/platform/windows/win32_task_runner.h
FILE: ../../../flutter/shell/platform/windows/win32_window.cc
FILE: ../../../flutter/shell/platform/windows/win32_window.h
FILE: ../../../flutter/shell/platform/windows/win32_window_proc_delegate_manager.cc
......
......@@ -29,14 +29,20 @@ source_set("flutter_windows_headers") {
public_deps =
[ "//flutter/shell/platform/common/cpp:common_cpp_library_headers" ]
configs +=
[ "//flutter/shell/platform/common/cpp:desktop_library_implementation" ]
if (target_os == "winuwp") {
configs +=
[ "//flutter/shell/platform/common/cpp:desktop_library_implementation" ]
} else {
configs +=
[ "//flutter/shell/platform/common/cpp:desktop_library_implementation" ]
}
public_configs =
[ "//flutter/shell/platform/common/cpp:relative_flutter_library_headers" ]
}
source_set("flutter_windows_source") {
# Common Windows sources.
sources = [
"angle_surface_manager.cc",
"angle_surface_manager.h",
......@@ -52,29 +58,48 @@ source_set("flutter_windows_source") {
"key_event_handler.cc",
"key_event_handler.h",
"keyboard_hook_handler.h",
"platform_handler.cc",
"platform_handler.h",
"string_conversion.cc",
"string_conversion.h",
"system_utils.h",
"system_utils_win32.cc",
"task_runner.h",
"text_input_plugin.cc",
"text_input_plugin.h",
"win32_dpi_utils.cc",
"win32_dpi_utils.h",
"win32_flutter_window.cc",
"win32_flutter_window.h",
"win32_platform_handler.cc",
"win32_platform_handler.h",
"win32_task_runner.cc",
"win32_task_runner.h",
"win32_window.cc",
"win32_window.h",
"win32_window_proc_delegate_manager.cc",
"win32_window_proc_delegate_manager.h",
"window_binding_handler.h",
"window_binding_handler_delegate.h",
"window_state.h",
]
# Target-specific sources.
if (target_os == "winuwp") {
sources += [
"flutter_windows_winuwp.cc",
"platform_handler_winuwp.cc",
"platform_handler_winuwp.h",
"system_utils_winuwp.cc",
"task_runner_winuwp.cc",
"task_runner_winuwp.h",
]
} else {
sources += [
"flutter_windows_win32.cc",
"platform_handler_win32.cc",
"platform_handler_win32.h",
"system_utils_win32.cc",
"task_runner_win32.cc",
"task_runner_win32.h",
"win32_dpi_utils.cc",
"win32_dpi_utils.h",
"win32_flutter_window.cc",
"win32_flutter_window.h",
"win32_window.cc",
"win32_window.h",
"win32_window_proc_delegate_manager.cc",
"win32_window_proc_delegate_manager.h",
]
}
configs += [
"//flutter/shell/platform/common/cpp:desktop_library_implementation",
"//third_party/angle:gl_prototypes",
......@@ -116,40 +141,51 @@ shared_library("flutter_windows") {
public_configs = [ "//flutter:config" ]
}
shared_library("flutter_windows_winuwp") {
deps = [ ":flutter_windows_source" ]
libs = [ "windowsapp.lib" ]
public_configs = [ "//flutter:config" ]
}
test_fixtures("flutter_windows_fixtures") {
fixtures = []
}
executable("flutter_windows_unittests") {
testonly = true
sources = [
"flutter_project_bundle_unittests.cc",
"flutter_windows_engine_unittests.cc",
"string_conversion_unittests.cc",
"system_utils_unittests.cc",
"testing/engine_embedder_api_modifier.h",
"testing/mock_win32_window.cc",
"testing/mock_win32_window.h",
"testing/win32_flutter_window_test.cc",
"testing/win32_flutter_window_test.h",
"win32_dpi_utils_unittests.cc",
"win32_flutter_window_unittests.cc",
"win32_window_proc_delegate_manager_unittests.cc",
"win32_window_unittests.cc",
]
public_configs = [ "//flutter:config" ]
deps = [
":flutter_windows_fixtures",
":flutter_windows_headers",
":flutter_windows_source",
"//flutter/shell/platform/embedder:embedder_as_internal_library",
"//flutter/shell/platform/embedder:embedder_test_utils",
"//flutter/testing",
"//third_party/rapidjson",
]
if (target_os == "winuwp") {
# disabled until the uwp implementation is present
} else {
executable("flutter_windows_unittests") {
testonly = true
sources = [
"flutter_project_bundle_unittests.cc",
"flutter_windows_engine_unittests.cc",
"string_conversion_unittests.cc",
"system_utils_unittests.cc",
"testing/engine_embedder_api_modifier.h",
"testing/mock_win32_window.cc",
"testing/mock_win32_window.h",
"testing/win32_flutter_window_test.cc",
"testing/win32_flutter_window_test.h",
"win32_dpi_utils_unittests.cc",
"win32_flutter_window_unittests.cc",
"win32_window_proc_delegate_manager_unittests.cc",
"win32_window_unittests.cc",
]
public_configs = [ "//flutter:config" ]
deps = [
":flutter_windows_fixtures",
":flutter_windows_headers",
":flutter_windows_source",
"//flutter/shell/platform/common/cpp:common_cpp",
"//flutter/shell/platform/embedder:embedder_as_internal_library",
"//flutter/shell/platform/embedder:embedder_test_utils",
"//flutter/testing",
"//third_party/rapidjson",
]
}
}
shared_library("flutter_windows_glfw") {
......@@ -168,11 +204,20 @@ group("windows_glfw") {
}
group("windows") {
deps = [
":flutter_windows",
":publish_headers_windows",
"//flutter/shell/platform/windows/client_wrapper:publish_wrapper_windows",
]
if (target_os == "winuwp") {
deps = [
":flutter_windows_winuwp",
":publish_headers_windows",
"//flutter/shell/platform/windows/client_wrapper:publish_wrapper_windows",
]
} else {
deps = [
":flutter_windows",
":publish_headers_windows",
"//flutter/shell/platform/windows/client_wrapper:publish_wrapper_windows",
]
}
if (build_glfw_shell) {
deps += [ ":windows_glfw" ]
}
......
......@@ -64,9 +64,11 @@ void FlutterEngine::ShutDown() {
engine_ = nullptr;
}
#ifndef WINUWP
std::chrono::nanoseconds FlutterEngine::ProcessMessages() {
return std::chrono::nanoseconds(FlutterDesktopEngineProcessMessages(engine_));
}
#endif
void FlutterEngine::ReloadSystemFonts() {
FlutterDesktopEngineReloadSystemFonts(engine_);
......
......@@ -29,6 +29,7 @@ FlutterViewController::~FlutterViewController() {
}
}
#ifndef WINUWP
std::optional<LRESULT> FlutterViewController::HandleTopLevelWindowProc(
HWND hwnd,
UINT message,
......@@ -39,5 +40,6 @@ std::optional<LRESULT> FlutterViewController::HandleTopLevelWindowProc(
controller_, hwnd, message, wparam, lparam, &result);
return handled ? result : std::optional<LRESULT>(std::nullopt);
}
#endif
} // namespace flutter
......@@ -46,6 +46,7 @@ class FlutterViewController {
// Returns the view managed by this controller.
FlutterView* view() { return view_.get(); }
#ifndef WINUWP
// Allows the Flutter engine and any interested plugins an opportunity to
// handle the given message.
//
......@@ -55,6 +56,7 @@ class FlutterViewController {
UINT message,
WPARAM wparam,
LPARAM lparam);
#endif
private:
// Handle for interacting with the C API's view controller, if any.
......
......@@ -7,7 +7,7 @@
#include <filesystem>
#include <iostream>
#include "flutter/shell/platform/common/cpp/engine_switches.h"
#include "flutter/shell/platform/common/cpp/engine_switches.h" // nogncheck
#include "flutter/shell/platform/common/cpp/path_utils.h"
namespace flutter {
......
......@@ -22,9 +22,6 @@
#include "flutter/shell/platform/windows/flutter_project_bundle.h"
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/win32_dpi_utils.h"
#include "flutter/shell/platform/windows/win32_flutter_window.h"
#include "flutter/shell/platform/windows/win32_task_runner.h"
#include "flutter/shell/platform/windows/window_binding_handler.h"
#include "flutter/shell/platform/windows/window_state.h"
......@@ -52,32 +49,6 @@ static FlutterDesktopViewRef HandleForView(flutter::FlutterWindowsView* view) {
return reinterpret_cast<FlutterDesktopViewRef>(view);
}
FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(
int width,
int height,
FlutterDesktopEngineRef engine) {
std::unique_ptr<flutter::WindowBindingHandler> window_wrapper =
std::make_unique<flutter::Win32FlutterWindow>(width, height);
auto state = std::make_unique<FlutterDesktopViewControllerState>();
state->view =
std::make_unique<flutter::FlutterWindowsView>(std::move(window_wrapper));
state->view->CreateRenderSurface();
// Take ownership of the engine, starting it if necessary.
state->view->SetEngine(
std::unique_ptr<flutter::FlutterWindowsEngine>(EngineFromHandle(engine)));
if (!state->view->GetEngine()->running()) {
if (!state->view->GetEngine()->RunWithEntrypoint(nullptr)) {
return nullptr;
}
}
// Must happen after engine is running.
state->view->SendInitialBounds();
return state.release();
}
void FlutterDesktopViewControllerDestroy(
FlutterDesktopViewControllerRef controller) {
delete controller;
......@@ -93,23 +64,6 @@ FlutterDesktopViewRef FlutterDesktopViewControllerGetView(
return HandleForView(controller->view.get());
}
bool FlutterDesktopViewControllerHandleTopLevelWindowProc(
FlutterDesktopViewControllerRef controller,
HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam,
LRESULT* result) {
std::optional<LRESULT> delegate_result =
controller->view->GetEngine()
->window_proc_delegate_manager()
->OnTopLevelWindowProc(hwnd, message, wparam, lparam);
if (delegate_result) {
*result = *delegate_result;
}
return delegate_result.has_value();
}
FlutterDesktopEngineRef FlutterDesktopEngineCreate(
const FlutterDesktopEngineProperties& engine_properties) {
flutter::FlutterProjectBundle project(engine_properties);
......@@ -132,10 +86,6 @@ bool FlutterDesktopEngineRun(FlutterDesktopEngineRef engine,
return EngineFromHandle(engine)->RunWithEntrypoint(entry_point);
}
uint64_t FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine) {
return EngineFromHandle(engine)->task_runner()->ProcessTasks().count();
}
void FlutterDesktopEngineReloadSystemFonts(FlutterDesktopEngineRef engine) {
EngineFromHandle(engine)->ReloadSystemFonts();
}
......@@ -164,29 +114,6 @@ FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(
return HandleForView(registrar->engine->view());
}
void FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(
FlutterDesktopPluginRegistrarRef registrar,
FlutterDesktopWindowProcCallback delegate,
void* user_data) {
registrar->engine->window_proc_delegate_manager()
->RegisterTopLevelWindowProcDelegate(delegate, user_data);
}
void FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate(
FlutterDesktopPluginRegistrarRef registrar,
FlutterDesktopWindowProcCallback delegate) {
registrar->engine->window_proc_delegate_manager()
->UnregisterTopLevelWindowProcDelegate(delegate);
}
UINT FlutterDesktopGetDpiForHWND(HWND hwnd) {
return flutter::GetDpiForHWND(hwnd);
}
UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor) {
return flutter::GetDpiForMonitor(monitor);
}
void FlutterDesktopResyncOutputStreams() {
FILE* unused;
if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
......
......@@ -15,6 +15,7 @@
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/string_conversion.h"
#include "flutter/shell/platform/windows/system_utils.h"
#include "flutter/shell/platform/windows/task_runner.h"
#include "third_party/rapidjson/include/rapidjson/document.h"
namespace flutter {
......@@ -99,7 +100,7 @@ FlutterWindowsEngine::FlutterWindowsEngine(const FlutterProjectBundle& project)
embedder_api_.struct_size = sizeof(FlutterEngineProcTable);
FlutterEngineGetProcAddresses(&embedder_api_);
task_runner_ = std::make_unique<Win32TaskRunner>(
task_runner_ = TaskRunner::Create(
GetCurrentThreadId(), embedder_api_.GetCurrentTime,
[this](const auto* task) {
if (!engine_) {
......@@ -121,8 +122,10 @@ FlutterWindowsEngine::FlutterWindowsEngine(const FlutterProjectBundle& project)
messenger_wrapper_ = std::make_unique<BinaryMessengerImpl>(messenger_.get());
message_dispatcher_ =
std::make_unique<IncomingMessageDispatcher>(messenger_.get());
#ifndef WINUWP
window_proc_delegate_manager_ =
std::make_unique<Win32WindowProcDelegateManager>();
#endif
// Set up internal channels.
// TODO: Replace this with an embedder.h API. See
......@@ -175,12 +178,12 @@ bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) {
platform_task_runner.user_data = task_runner_.get();
platform_task_runner.runs_task_on_current_thread_callback =
[](void* user_data) -> bool {
return static_cast<Win32TaskRunner*>(user_data)->RunsTasksOnCurrentThread();
return static_cast<TaskRunner*>(user_data)->RunsTasksOnCurrentThread();
};
platform_task_runner.post_task_callback = [](FlutterTask task,
uint64_t target_time_nanos,
void* user_data) -> void {
static_cast<Win32TaskRunner*>(user_data)->PostTask(task, target_time_nanos);
static_cast<TaskRunner*>(user_data)->PostTask(task, target_time_nanos);
};
FlutterCustomTaskRunners custom_task_runners = {};
custom_task_runners.struct_size = sizeof(FlutterCustomTaskRunners);
......@@ -201,7 +204,9 @@ bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) {
auto host = static_cast<FlutterWindowsEngine*>(user_data);
return host->HandlePlatformMessage(engine_message);
};
args.custom_task_runners = &custom_task_runners;
if (aot_data_) {
args.aot_data = aot_data_.get();
}
......
......@@ -16,11 +16,14 @@
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/flutter_project_bundle.h"
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include "flutter/shell/platform/windows/win32_task_runner.h"
#include "flutter/shell/platform/windows/win32_window_proc_delegate_manager.h"
#include "flutter/shell/platform/windows/task_runner.h"
#include "flutter/shell/platform/windows/window_state.h"
#include "third_party/rapidjson/include/rapidjson/document.h"
#ifndef WINUWP
#include "flutter/shell/platform/windows/win32_window_proc_delegate_manager.h" // nogncheck
#endif
namespace flutter {
class FlutterWindowsView;
......@@ -75,11 +78,13 @@ class FlutterWindowsEngine {
return message_dispatcher_.get();
}
Win32TaskRunner* task_runner() { return task_runner_.get(); }
TaskRunner* task_runner() { return task_runner_.get(); }
#ifndef WINUWP
Win32WindowProcDelegateManager* window_proc_delegate_manager() {
return window_proc_delegate_manager_.get();
}
#endif
// Informs the engine that the window metrics have changed.
void SendWindowMetricsEvent(const FlutterWindowMetricsEvent& event);
......@@ -132,7 +137,7 @@ class FlutterWindowsEngine {
FlutterWindowsView* view_ = nullptr;
// Task runner for tasks posted from the engine.
std::unique_ptr<Win32TaskRunner> task_runner_;
std::unique_ptr<TaskRunner> task_runner_;
// The plugin messenger handle given to API clients.
std::unique_ptr<FlutterDesktopMessenger> messenger_;
......@@ -154,8 +159,10 @@ class FlutterWindowsEngine {
FlutterDesktopOnPluginRegistrarDestroyed
plugin_registrar_destruction_callback_ = nullptr;
#ifndef WINUWP
// The manager for WindowProc delegate registration and callbacks.
std::unique_ptr<Win32WindowProcDelegateManager> window_proc_delegate_manager_;
#endif
};
} // namespace flutter
......
......@@ -39,8 +39,7 @@ void FlutterWindowsView::SetEngine(
std::make_unique<flutter::KeyEventHandler>(internal_plugin_messenger));
keyboard_hook_handlers_.push_back(
std::make_unique<flutter::TextInputPlugin>(internal_plugin_messenger));
platform_handler_ = std::make_unique<flutter::PlatformHandler>(
internal_plugin_messenger, this);
platform_handler_ = PlatformHandler::Create(internal_plugin_messenger, this);
cursor_handler_ = std::make_unique<flutter::CursorHandler>(
internal_plugin_messenger, binding_handler_.get());
......
......@@ -18,9 +18,9 @@
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
#include "flutter/shell/platform/windows/key_event_handler.h"
#include "flutter/shell/platform/windows/keyboard_hook_handler.h"
#include "flutter/shell/platform/windows/platform_handler.h"
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include "flutter/shell/platform/windows/text_input_plugin.h"
#include "flutter/shell/platform/windows/win32_platform_handler.h"
#include "flutter/shell/platform/windows/window_binding_handler.h"
#include "flutter/shell/platform/windows/window_binding_handler_delegate.h"
#include "flutter/shell/platform/windows/window_state.h"
......
// Copyright 2013 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.
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include <io.h>
#include <algorithm>
#include <cassert>
#include <chrono>
#include <cstdlib>
#include <filesystem>
#include <iostream>
#include <memory>
#include <vector>
#include "flutter/shell/platform/windows/task_runner_win32.h"
#include "flutter/shell/platform/windows/win32_dpi_utils.h"
#include "flutter/shell/platform/windows/win32_flutter_window.h"
// Returns the engine corresponding to the given opaque API handle.
static flutter::FlutterWindowsEngine* EngineFromHandle(
FlutterDesktopEngineRef ref) {
return reinterpret_cast<flutter::FlutterWindowsEngine*>(ref);
}
FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(
int width,
int height,
FlutterDesktopEngineRef engine) {
std::unique_ptr<flutter::WindowBindingHandler> window_wrapper =
std::make_unique<flutter::Win32FlutterWindow>(width, height);
auto state = std::make_unique<FlutterDesktopViewControllerState>();
state->view =
std::make_unique<flutter::FlutterWindowsView>(std::move(window_wrapper));
state->view->CreateRenderSurface();
// Take ownership of the engine, starting it if necessary.
state->view->SetEngine(
std::unique_ptr<flutter::FlutterWindowsEngine>(EngineFromHandle(engine)));
if (!state->view->GetEngine()->running()) {
if (!state->view->GetEngine()->RunWithEntrypoint(nullptr)) {
return nullptr;
}
}
// Must happen after engine is running.
state->view->SendInitialBounds();
return state.release();
}
bool FlutterDesktopViewControllerHandleTopLevelWindowProc(
FlutterDesktopViewControllerRef controller,
HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam,
LRESULT* result) {
std::optional<LRESULT> delegate_result =
controller->view->GetEngine()
->window_proc_delegate_manager()
->OnTopLevelWindowProc(hwnd, message, wparam, lparam);
if (delegate_result) {
*result = *delegate_result;
}
return delegate_result.has_value();
}
uint64_t FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine) {
return static_cast<flutter::TaskRunnerWin32*>(
EngineFromHandle(engine)->task_runner())
->ProcessTasks()
.count();
}
void FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(
FlutterDesktopPluginRegistrarRef registrar,
FlutterDesktopWindowProcCallback delegate,
void* user_data) {
registrar->engine->window_proc_delegate_manager()
->RegisterTopLevelWindowProcDelegate(delegate, user_data);
}
void FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate(
FlutterDesktopPluginRegistrarRef registrar,
FlutterDesktopWindowProcCallback delegate) {
registrar->engine->window_proc_delegate_manager()
->UnregisterTopLevelWindowProcDelegate(delegate);
}
UINT FlutterDesktopGetDpiForHWND(HWND hwnd) {
return flutter::GetDpiForHWND(hwnd);
}
UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor) {
return flutter::GetDpiForMonitor(monitor);
}
// Copyright 2013 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.
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include <io.h>
#include <algorithm>
#include <cassert>
#include <chrono>
#include <cstdlib>
#include <filesystem>
#include <iostream>
#include <memory>
#include <vector>
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/plugin_registrar.h"
#include "flutter/shell/platform/common/cpp/incoming_message_dispatcher.h"
FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate(
int width,
int height,
FlutterDesktopEngineRef engine) {
// TODO add WINUWP implementation.
return nullptr;
}
uint64_t FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine) {
// TODO add WINUWP implementation.
return 0;
}
void FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(
FlutterDesktopPluginRegistrarRef registrar,
FlutterDesktopWindowProcCallback delegate,
void* user_data) {
// TODO add WINUWP implementation.
}
void FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate(
FlutterDesktopPluginRegistrarRef registrar,
FlutterDesktopWindowProcCallback delegate) {
// TODO add WINUWP implementation.
}
// Copyright 2013 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.
#include "flutter/shell/platform/windows/platform_handler.h"
#include "flutter/shell/platform/common/cpp/json_method_codec.h"
static constexpr char kChannelName[] = "flutter/platform";
static constexpr char kGetClipboardDataMethod[] = "Clipboard.getData";
static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData";
static constexpr char kTextPlainFormat[] = "text/plain";
static constexpr char kTextKey[] = "text";
static constexpr char kUnknownClipboardFormatMessage[] =
"Unknown clipboard format";
namespace flutter {
PlatformHandler::PlatformHandler(BinaryMessenger* messenger)
: channel_(std::make_unique<MethodChannel<rapidjson::Document>>(
messenger,
kChannelName,
&JsonMethodCodec::GetInstance())) {
channel_->SetMethodCallHandler(
[this](const MethodCall<rapidjson::Document>& call,
std::unique_ptr<MethodResult<rapidjson::Document>> result) {
HandleMethodCall(call, std::move(result));
});
}
PlatformHandler::~PlatformHandler() = default;
void PlatformHandler::HandleMethodCall(
const MethodCall<rapidjson::Document>& method_call,
std::unique_ptr<MethodResult<rapidjson::Document>> result) {
const std::string& method = method_call.method_name();
if (method.compare(kGetClipboardDataMethod) == 0) {
// Only one string argument is expected.
const rapidjson::Value& format = method_call.arguments()[0];
if (strcmp(format.GetString(), kTextPlainFormat) != 0) {
result->Error(kClipboardError, kUnknownClipboardFormatMessage);
return;
}
GetPlainText(std::move(result), kTextKey);
} else if (method.compare(kSetClipboardDataMethod) == 0) {
const rapidjson::Value& document = *method_call.arguments();
rapidjson::Value::ConstMemberIterator itr = document.FindMember(kTextKey);
if (itr == document.MemberEnd()) {
result->Error(kClipboardError, kUnknownClipboardFormatMessage);
return;
}
SetPlainText(itr->value.GetString(), std::move(result));
} else {
result->NotImplemented();
}
}
} // namespace flutter
......@@ -7,7 +7,6 @@
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/binary_messenger.h"
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/method_channel.h"
#include "flutter/shell/platform/windows/public/flutter_windows.h"
#include "rapidjson/document.h"
namespace flutter {
......@@ -17,20 +16,38 @@ class FlutterWindowsView;
// Handler for internal system channels.
class PlatformHandler {
public:
explicit PlatformHandler(flutter::BinaryMessenger* messenger,
FlutterWindowsView* view);
explicit PlatformHandler(BinaryMessenger* messenger);
virtual ~PlatformHandler();
// Creates a new platform handler using the given messenger and view.
static std::unique_ptr<PlatformHandler> Create(BinaryMessenger* messenger,
FlutterWindowsView* view);
protected:
// Gets plain text from the clipboard and provides it to |result| as the
// value in a dictionary with the given |key|.
virtual void GetPlainText(
std::unique_ptr<MethodResult<rapidjson::Document>> result,
std::string_view key) = 0;
// Sets the clipboard's plain text to |text|, and reports the result (either
// an error, or null for success) to |result|.
virtual void SetPlainText(
const std::string& text,
std::unique_ptr<MethodResult<rapidjson::Document>> result) = 0;
// A error type to use for error responses.
static constexpr char kClipboardError[] = "Clipboard error";
private:
// Called when a method is called on |channel_|;
void HandleMethodCall(
const flutter::MethodCall<rapidjson::Document>& method_call,
std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result);
const MethodCall<rapidjson::Document>& method_call,
std::unique_ptr<MethodResult<rapidjson::Document>> result);
// The MethodChannel used for communication with the Flutter engine.
std::unique_ptr<flutter::MethodChannel<rapidjson::Document>> channel_;
// A reference to the win32 window.
FlutterWindowsView* view_;
std::unique_ptr<MethodChannel<rapidjson::Document>> channel_;
};
} // namespace flutter
......
// Copyright 2013 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.
#include "flutter/shell/platform/windows/platform_handler.h"
#include <memory>
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/binary_messenger.h"
#include "flutter/shell/platform/common/cpp/json_method_codec.h"
#include "flutter/shell/platform/windows/testing/test_binary_messenger.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "rapidjson/document.h"
namespace flutter {
namespace testing {
namespace {
using ::testing::_;
static constexpr char kChannelName[] = "flutter/platform";
static constexpr char kGetClipboardDataMethod[] = "Clipboard.getData";
static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData";
static constexpr char kTextPlainFormat[] = "text/plain";
// Test implementation of PlatformHandler to allow testing the PlatformHandler
// logic.
class TestPlatformHandler : public PlatformHandler {
public:
explicit TestPlatformHandler(BinaryMessenger* messenger)
: PlatformHandler(messenger) {}
virtual ~TestPlatformHandler() {}
// |PlatformHandler|
MOCK_METHOD2(GetPlainText,
void(std::unique_ptr<MethodResult<rapidjson::Document>>,
const char*));
MOCK_METHOD2(SetPlainText,
void(const std::string&,
std::unique_ptr<MethodResult<rapidjson::Document>>));
};
// Mock result to inspect results of PlatformHandler calls.
class MockMethodResult : public MethodResult<rapidjson::Document> {
public:
MOCK_METHOD1(SuccessInternal, void(const rapidjson::Document*));
MOCK_METHOD3(ErrorInternal,
void(const std::string&,
const std::string&,
const rapidjson::Document*));
MOCK_METHOD0(NotImplementedInternal, void());
};
} // namespace
TEST(PlatformHandler, GettingTextCallsThrough) {
TestBinaryMessenger messenger;
TestPlatformHandler platform_handler(&messenger);
auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
auto& allocator = args->GetAllocator();
args->PushBack(kTextPlainFormat, allocator);
auto encoded = JsonMethodCodec::GetInstance().EncodeMethodCall(
MethodCall<rapidjson::Document>(kGetClipboardDataMethod,
std::move(args)));
// Set up a handler to call a response on |result| so that it doesn't log
// on destruction about leaking.
ON_CALL(platform_handler, GetPlainText)
.WillByDefault(
[](std::unique_ptr<MethodResult<rapidjson::Document>> result,
auto key) { result->NotImplemented(); });
EXPECT_CALL(platform_handler, GetPlainText(_, ::testing::StrEq("text")));
EXPECT_TRUE(messenger.SimulateEngineMessage(
kChannelName, encoded->data(), encoded->size(),
[](const uint8_t* reply, size_t reply_size) {}));
}
TEST(PlatformHandler, RejectsGettingUnknownTypes) {
TestBinaryMessenger messenger;
TestPlatformHandler platform_handler(&messenger);
auto args = std::make_unique<rapidjson::Document>(rapidjson::kArrayType);
auto& allocator = args->GetAllocator();
args->PushBack("madeup/contenttype", allocator);
auto encoded = JsonMethodCodec::GetInstance().EncodeMethodCall(
MethodCall<rapidjson::Document>(kGetClipboardDataMethod,
std::move(args)));
MockMethodResult result;
// Requsting an unknow content type is an error.
EXPECT_CALL(result, ErrorInternal(_, _, _));
EXPECT_TRUE(messenger.SimulateEngineMessage(
kChannelName, encoded->data(), encoded->size(),
[&](const uint8_t* reply, size_t reply_size) {
JsonMethodCodec::GetInstance().DecodeAndProcessResponseEnvelope(
reply, reply_size, &result);
}));
}
TEST(PlatformHandler, SettingTextCallsThrough) {
TestBinaryMessenger messenger;
TestPlatformHandler platform_handler(&messenger);
auto args = std::make_unique<rapidjson::Document>(rapidjson::kObjectType);
auto& allocator = args->GetAllocator();
args->AddMember("text", "hello", allocator);
auto encoded = JsonMethodCodec::GetInstance().EncodeMethodCall(
MethodCall<rapidjson::Document>(kSetClipboardDataMethod,
std::move(args)));
// Set up a handler to call a response on |result| so that it doesn't log
// on destruction about leaking.
ON_CALL(platform_handler, SetPlainText)
.WillByDefault(
[](auto value,
std::unique_ptr<MethodResult<rapidjson::Document>> result) {
result->NotImplemented();
});
EXPECT_CALL(platform_handler, SetPlainText(::testing::StrEq("hello"), _));
EXPECT_TRUE(messenger.SimulateEngineMessage(
kChannelName, encoded->data(), encoded->size(),
[](const uint8_t* reply, size_t reply_size) {}));
}
TEST(PlatformHandler, RejectsSettingUnknownTypes) {
TestBinaryMessenger messenger;
TestPlatformHandler platform_handler(&messenger);
auto args = std::make_unique<rapidjson::Document>(rapidjson::kObjectType);
auto& allocator = args->GetAllocator();
args->AddMember("madeuptype", "hello", allocator);
auto encoded = JsonMethodCodec::GetInstance().EncodeMethodCall(
MethodCall<rapidjson::Document>(kSetClipboardDataMethod,
std::move(args)));
MockMethodResult result;
// Requsting an unknow content type is an error.
EXPECT_CALL(result, ErrorInternal(_, _, _));
EXPECT_TRUE(messenger.SimulateEngineMessage(
kChannelName, encoded->data(), encoded->size(),
[&](const uint8_t* reply, size_t reply_size) {
JsonMethodCodec::GetInstance().DecodeAndProcessResponseEnvelope(
reply, reply_size, &result);
}));
}
} // namespace testing
} // namespace flutter
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/platform/windows/win32_platform_handler.h"
#include "flutter/shell/platform/windows/platform_handler_win32.h"
#include <windows.h>
......@@ -10,22 +10,9 @@
#include <iostream>
#include <optional>
#include "flutter/shell/platform/common/cpp/json_method_codec.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/string_conversion.h"
static constexpr char kChannelName[] = "flutter/platform";
static constexpr char kGetClipboardDataMethod[] = "Clipboard.getData";
static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData";
static constexpr char kTextPlainFormat[] = "text/plain";
static constexpr char kTextKey[] = "text";
static constexpr char kClipboardError[] = "Clipboard error";
static constexpr char kUnknownClipboardFormatMessage[] =
"Unknown clipboard format";
namespace flutter {
namespace {
......@@ -198,88 +185,67 @@ bool ScopedClipboard::SetString(const std::wstring string) {
} // namespace
PlatformHandler::PlatformHandler(flutter::BinaryMessenger* messenger,
FlutterWindowsView* view)
: channel_(std::make_unique<flutter::MethodChannel<rapidjson::Document>>(
messenger,
kChannelName,
&flutter::JsonMethodCodec::GetInstance())),
view_(view) {
channel_->SetMethodCallHandler(
[this](
const flutter::MethodCall<rapidjson::Document>& call,
std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result) {
HandleMethodCall(call, std::move(result));
});
// static
std::unique_ptr<PlatformHandler> PlatformHandler::Create(
BinaryMessenger* messenger,
FlutterWindowsView* view) {
return std::make_unique<PlatformHandlerWin32>(messenger, view);
}
void PlatformHandler::HandleMethodCall(
const flutter::MethodCall<rapidjson::Document>& method_call,
std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result) {
const std::string& method = method_call.method_name();
if (method.compare(kGetClipboardDataMethod) == 0) {
// Only one string argument is expected.
const rapidjson::Value& format = method_call.arguments()[0];
if (strcmp(format.GetString(), kTextPlainFormat) != 0) {
result->Error(kClipboardError, kUnknownClipboardFormatMessage);
return;
}
ScopedClipboard clipboard;
if (!clipboard.Open(std::get<HWND>(*view_->GetRenderTarget()))) {
rapidjson::Document error_code;
error_code.SetInt(::GetLastError());
result->Error(kClipboardError, "Unable to open clipboard", error_code);
return;
}
if (!clipboard.HasString()) {
result->Success(rapidjson::Document());
return;
}
std::optional<std::wstring> clipboard_string = clipboard.GetString();
if (!clipboard_string) {
rapidjson::Document error_code;
error_code.SetInt(::GetLastError());
result->Error(kClipboardError, "Unable to get clipboard data",
error_code);
return;
}
rapidjson::Document document;
document.SetObject();
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
document.AddMember(
rapidjson::Value(kTextKey, allocator),
rapidjson::Value(Utf8FromUtf16(*clipboard_string), allocator),
allocator);
result->Success(document);
} else if (method.compare(kSetClipboardDataMethod) == 0) {
const rapidjson::Value& document = *method_call.arguments();
rapidjson::Value::ConstMemberIterator itr = document.FindMember(kTextKey);
if (itr == document.MemberEnd()) {
result->Error(kClipboardError, kUnknownClipboardFormatMessage);
return;
}
PlatformHandlerWin32::PlatformHandlerWin32(BinaryMessenger* messenger,
FlutterWindowsView* view)
: PlatformHandler(messenger), view_(view) {}
PlatformHandlerWin32::~PlatformHandlerWin32() = default;
void PlatformHandlerWin32::GetPlainText(
std::unique_ptr<MethodResult<rapidjson::Document>> result,
std::string_view key) {
ScopedClipboard clipboard;
if (!clipboard.Open(std::get<HWND>(*view_->GetRenderTarget()))) {
rapidjson::Document error_code;
error_code.SetInt(::GetLastError());
result->Error(kClipboardError, "Unable to open clipboard", error_code);
return;
}
if (!clipboard.HasString()) {
result->Success(rapidjson::Document());
return;
}
std::optional<std::wstring> clipboard_string = clipboard.GetString();
if (!clipboard_string) {
rapidjson::Document error_code;
error_code.SetInt(::GetLastError());
result->Error(kClipboardError, "Unable to get clipboard data", error_code);
return;
}
ScopedClipboard clipboard;
rapidjson::Document document;
document.SetObject();
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
document.AddMember(
rapidjson::Value(key.data(), allocator),
rapidjson::Value(Utf8FromUtf16(*clipboard_string), allocator), allocator);
result->Success(document);
}
if (!clipboard.Open(std::get<HWND>(*view_->GetRenderTarget()))) {
rapidjson::Document error_code;
error_code.SetInt(::GetLastError());
result->Error(kClipboardError, "Unable to open clipboard", error_code);
return;
}
if (!clipboard.SetString(Utf16FromUtf8(itr->value.GetString()))) {
rapidjson::Document error_code;
error_code.SetInt(::GetLastError());
result->Error(kClipboardError, "Unable to set clipboard data",
error_code);
return;
}
result->Success();
} else {
result->NotImplemented();
void PlatformHandlerWin32::SetPlainText(
const std::string& text,
std::unique_ptr<MethodResult<rapidjson::Document>> result) {
ScopedClipboard clipboard;
if (!clipboard.Open(std::get<HWND>(*view_->GetRenderTarget()))) {
rapidjson::Document error_code;
error_code.SetInt(::GetLastError());
result->Error(kClipboardError, "Unable to open clipboard", error_code);
return;
}
if (!clipboard.SetString(Utf16FromUtf8(text))) {
rapidjson::Document error_code;
error_code.SetInt(::GetLastError());
result->Error(kClipboardError, "Unable to set clipboard data", error_code);
return;
}
result->Success();
}
} // namespace flutter
// Copyright 2013 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 FLUTTER_SHELL_PLATFORM_WINDOWS_PLATFORM_HANDLER_WIN32_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_PLATFORM_HANDLER_WIN32_H_
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/binary_messenger.h"
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/method_channel.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/platform_handler.h"
#include "rapidjson/document.h"
namespace flutter {
class FlutterWindowsView;
// Win32 implementation of PlatformHandler.
class PlatformHandlerWin32 : public PlatformHandler {
public:
explicit PlatformHandlerWin32(BinaryMessenger* messenger,
FlutterWindowsView* view);
virtual ~PlatformHandlerWin32();
protected:
// |PlatformHandler|
void GetPlainText(std::unique_ptr<MethodResult<rapidjson::Document>> result,
std::string_view key) override;
// |PlatformHandler|
void SetPlainText(
const std::string& text,
std::unique_ptr<MethodResult<rapidjson::Document>> result) override;
private:
// A reference to the Flutter view.
FlutterWindowsView* view_;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_PLATFORM_HANDLER_WIN32_H_
// Copyright 2013 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.
#include "flutter/shell/platform/windows/platform_handler_winuwp.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
namespace flutter {
// static
std::unique_ptr<PlatformHandler> PlatformHandler::Create(
BinaryMessenger* messenger,
FlutterWindowsView* view) {
return std::make_unique<PlatformHandlerWinUwp>(messenger, view);
}
PlatformHandlerWinUwp::PlatformHandlerWinUwp(BinaryMessenger* messenger,
FlutterWindowsView* view)
: PlatformHandler(messenger), view_(view) {}
PlatformHandlerWinUwp::~PlatformHandlerWinUwp() = default;
void PlatformHandlerWinUwp::GetPlainText(
std::unique_ptr<MethodResult<rapidjson::Document>> result,
std::string_view key) {
// TODO: Implement. See https://github.com/flutter/flutter/issues/70214.
result->NotImplemented();
}
void PlatformHandlerWinUwp::SetPlainText(
const std::string& text,
std::unique_ptr<MethodResult<rapidjson::Document>> result) {
// TODO: Implement. See https://github.com/flutter/flutter/issues/70214.
result->NotImplemented();
}
} // namespace flutter
// Copyright 2013 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 FLUTTER_SHELL_PLATFORM_WINDOWS_PLATFORM_HANDLER_WINUWP_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_PLATFORM_HANDLER_WINUWP_H_
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/binary_messenger.h"
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/method_channel.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/platform_handler.h"
#include "rapidjson/document.h"
namespace flutter {
class FlutterWindowsView;
// UWP implementation of PlatformHandler.
class PlatformHandlerWinUwp : public PlatformHandler {
public:
explicit PlatformHandlerWinUwp(BinaryMessenger* messenger,
FlutterWindowsView* view);
virtual ~PlatformHandlerWinUwp();
protected:
// |PlatformHandler|
void GetPlainText(std::unique_ptr<MethodResult<rapidjson::Document>> result,
std::string_view key) override;
// |PlatformHandler|
void SetPlainText(
const std::string& text,
std::unique_ptr<MethodResult<rapidjson::Document>> result) override;
private:
// A reference to the Flutter view.
FlutterWindowsView* view_;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_PLATFORM_HANDLER_WINUWP_H_
......@@ -92,6 +92,7 @@ FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopViewControllerGetEngine(
FLUTTER_EXPORT FlutterDesktopViewRef
FlutterDesktopViewControllerGetView(FlutterDesktopViewControllerRef controller);
#ifndef WINUWP
// Allows the Flutter engine and any interested plugins an opportunity to
// handle the given message.
//
......@@ -104,6 +105,7 @@ FLUTTER_EXPORT bool FlutterDesktopViewControllerHandleTopLevelWindowProc(
WPARAM wparam,
LPARAM lparam,
LRESULT* result);
#endif
// ========== Engine ==========
......@@ -132,6 +134,7 @@ FLUTTER_EXPORT bool FlutterDesktopEngineDestroy(FlutterDesktopEngineRef engine);
FLUTTER_EXPORT bool FlutterDesktopEngineRun(FlutterDesktopEngineRef engine,
const char* entry_point);
#ifndef WINUWP
// Processes any pending events in the Flutter engine, and returns the
// number of nanoseconds until the next scheduled event (or max, if none).
//
......@@ -140,6 +143,7 @@ FLUTTER_EXPORT bool FlutterDesktopEngineRun(FlutterDesktopEngineRef engine,
// last return value from this function.
FLUTTER_EXPORT uint64_t
FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine);
#endif
FLUTTER_EXPORT void FlutterDesktopEngineReloadSystemFonts(
FlutterDesktopEngineRef engine);
......
// Copyright 2013 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.
#include "flutter/shell/platform/windows/system_utils.h"
#include <Windows.h>
#include <sstream>
#include "flutter/shell/platform/windows/string_conversion.h"
namespace flutter {
std::vector<LanguageInfo> GetPreferredLanguageInfo() {
std::vector<std::wstring> languages = GetPreferredLanguages();
std::vector<LanguageInfo> language_info;
// TODO populate via WinRT
return language_info;
}
std::vector<std::wstring> GetPreferredLanguages() {
std::vector<std::wstring> languages;
// TODO populate via WinRT
return languages;
}
LanguageInfo ParseLanguageName(std::wstring language_name) {
LanguageInfo info;
// TODO populate via WinRT
return info;
}
std::wstring GetUserTimeFormat() {
// Rather than do the call-allocate-call-free dance, just use a sufficiently
// large buffer to handle any reasonable time format string.
const int kBufferSize = 100;
wchar_t buffer[kBufferSize];
if (::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_STIMEFORMAT, buffer,
kBufferSize) == 0) {
return std::wstring();
}
return std::wstring(buffer, kBufferSize);
}
bool Prefer24HourTime(std::wstring time_format) {
return time_format.find(L"H") != std::wstring::npos;
}
} // namespace flutter
// Copyright 2013 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 FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_H_
#include <windows.h>
#include <chrono>
#include <memory>
#include "flutter/shell/platform/embedder/embedder.h"
namespace flutter {
typedef uint64_t (*CurrentTimeProc)();
// Abstract custom task runner for scheduling custom tasks.
class TaskRunner {
public:
using TaskExpiredCallback = std::function<void(const FlutterTask*)>;
virtual ~TaskRunner() = default;
// Returns if the current thread is the UI thread.
virtual bool RunsTasksOnCurrentThread() const = 0;
// Post a Flutter engine tasks to the event loop for delayed execution.
virtual void PostTask(FlutterTask flutter_task,
uint64_t flutter_target_time_nanos) = 0;
// Creates a new task runner with the given main thread ID, current time
// provider, and callback for tasks that are ready to be run.
static std::unique_ptr<TaskRunner> Create(
DWORD main_thread_id,
CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired);
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_H_
......@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/shell/platform/windows/win32_task_runner.h"
#include "flutter/shell/platform/windows/task_runner_win32.h"
#include <atomic>
#include <iostream>
......@@ -10,20 +10,29 @@
namespace flutter {
Win32TaskRunner::Win32TaskRunner(DWORD main_thread_id,
// static
std::unique_ptr<TaskRunner> TaskRunner::Create(
DWORD main_thread_id,
CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired) {
return std::make_unique<TaskRunnerWin32>(main_thread_id, get_current_time,
on_task_expired);
}
TaskRunnerWin32::TaskRunnerWin32(DWORD main_thread_id,
CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired)
: main_thread_id_(main_thread_id),
get_current_time_(get_current_time),
on_task_expired_(std::move(on_task_expired)) {}
Win32TaskRunner::~Win32TaskRunner() = default;
TaskRunnerWin32::~TaskRunnerWin32() = default;
bool Win32TaskRunner::RunsTasksOnCurrentThread() const {
bool TaskRunnerWin32::RunsTasksOnCurrentThread() const {
return GetCurrentThreadId() == main_thread_id_;
}
std::chrono::nanoseconds Win32TaskRunner::ProcessTasks() {
std::chrono::nanoseconds TaskRunnerWin32::ProcessTasks() {
const TaskTimePoint now = TaskTimePoint::clock::now();
std::vector<FlutterTask> expired_tasks;
......@@ -68,14 +77,14 @@ std::chrono::nanoseconds Win32TaskRunner::ProcessTasks() {
}
}
Win32TaskRunner::TaskTimePoint Win32TaskRunner::TimePointFromFlutterTime(
TaskRunnerWin32::TaskTimePoint TaskRunnerWin32::TimePointFromFlutterTime(
uint64_t flutter_target_time_nanos) const {
const auto now = TaskTimePoint::clock::now();
const auto flutter_duration = flutter_target_time_nanos - get_current_time_();
return now + std::chrono::nanoseconds(flutter_duration);
}
void Win32TaskRunner::PostTask(FlutterTask flutter_task,
void TaskRunnerWin32::PostTask(FlutterTask flutter_task,
uint64_t flutter_target_time_nanos) {
static std::atomic_uint64_t sGlobalTaskOrder(0);
......
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_WIN32_TASK_RUNNER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_WIN32_TASK_RUNNER_H_
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_WIN32_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_WIN32_H_
#include <windows.h>
......@@ -15,31 +15,31 @@
#include <thread>
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/task_runner.h"
namespace flutter {
typedef uint64_t (*CurrentTimeProc)();
// A custom task runner that integrates with user32 GetMessage semantics so that
// host app can own its own message loop and flutter still gets to process
// tasks on a timely basis.
class Win32TaskRunner {
class TaskRunnerWin32 : public TaskRunner {
public:
using TaskExpiredCallback = std::function<void(const FlutterTask*)>;
// Creates a new task runner with the given main thread ID, current time
// provider, and callback for tasks that are ready to be run.
Win32TaskRunner(DWORD main_thread_id,
TaskRunnerWin32(DWORD main_thread_id,
CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired);
~Win32TaskRunner();
virtual ~TaskRunnerWin32();
// Returns if the current thread is the thread used by the win32 event loop.
bool RunsTasksOnCurrentThread() const;
// |TaskRunner|
bool RunsTasksOnCurrentThread() const override;
std::chrono::nanoseconds ProcessTasks();
// |TaskRunner|
void PostTask(FlutterTask flutter_task,
uint64_t flutter_target_time_nanos) override;
// Post a Flutter engine tasks to the event loop for delayed execution.
void PostTask(FlutterTask flutter_task, uint64_t flutter_target_time_nanos);
std::chrono::nanoseconds ProcessTasks();
private:
using TaskTimePoint = std::chrono::steady_clock::time_point;
......@@ -68,11 +68,11 @@ class Win32TaskRunner {
std::mutex task_queue_mutex_;
std::priority_queue<Task, std::deque<Task>, Task::Comparer> task_queue_;
Win32TaskRunner(const Win32TaskRunner&) = delete;
TaskRunnerWin32(const TaskRunnerWin32&) = delete;
Win32TaskRunner& operator=(const Win32TaskRunner&) = delete;
TaskRunnerWin32& operator=(const TaskRunnerWin32&) = delete;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_WIN32_TASK_RUNNER_H_
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TASK_RUNNER_WIN32_H_
// Copyright 2013 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.
#include "flutter/shell/platform/windows/task_runner_winuwp.h"
#include <atomic>
#include <utility>
namespace flutter {
// static
std::unique_ptr<TaskRunner> TaskRunner::Create(
DWORD main_thread_id,
CurrentTimeProc get_current_time,
const TaskExpiredCallback& on_task_expired) {
return std::make_unique<TaskRunnerWinUwp>(main_thread_id, on_task_expired);
}
TaskRunnerWinUwp::TaskRunnerWinUwp(DWORD main_thread_id,
const TaskExpiredCallback& on_task_expired)
: main_thread_id_(main_thread_id),
on_task_expired_(std::move(on_task_expired)) {
dispatcher_ =
winrt::Windows::UI::Core::CoreWindow::GetForCurrentThread().Dispatcher();
}
TaskRunnerWinUwp::~TaskRunnerWinUwp() = default;
bool TaskRunnerWinUwp::RunsTasksOnCurrentThread() const {
return GetCurrentThreadId() == main_thread_id_;
}
void TaskRunnerWinUwp::PostTask(FlutterTask flutter_task,
uint64_t flutter_target_time_nanos) {
// TODO: Handle the target time. See
// https://github.com/flutter/flutter/issues/70890.
dispatcher_.RunAsync(
winrt::Windows::UI::Core::CoreDispatcherPriority::Normal,
[this, flutter_task]() { on_task_expired_(&flutter_task); });
}
} // namespace flutter
// Copyright 2013 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 FLUTTER_SHELL_PLATFORM_WINDOWS_WINRT_TASK_RUNNER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_WINRT_TASK_RUNNER_H_
#include <windows.h>
#include <winrt/Windows.UI.Core.h>
#include <chrono>
#include <functional>
#include <thread>
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/task_runner.h"
namespace flutter {
// A custom task runner that uses a CoreDispatcher to schedule
// flutter tasks.
class TaskRunnerWinUwp : public TaskRunner {
public:
TaskRunnerWinUwp(DWORD main_thread_id,
const TaskExpiredCallback& on_task_expired);
~TaskRunnerWinUwp();
TaskRunnerWinUwp(const TaskRunnerWinUwp&) = delete;
TaskRunnerWinUwp& operator=(const TaskRunnerWinUwp&) = delete;
// |TaskRunner|
bool RunsTasksOnCurrentThread() const override;
// |TaskRunner|
void PostTask(FlutterTask flutter_task,
uint64_t flutter_target_time_nanos) override;
private:
DWORD main_thread_id_;
TaskExpiredCallback on_task_expired_;
winrt::Windows::UI::Core::CoreDispatcher dispatcher_{nullptr};
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_WINRT_TASK_RUNNER_H_
// Copyright 2013 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 FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_TEST_BINARY_MESSENGER_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_TEST_BINARY_MESSENGER_H_
#include <cassert>
#include <functional>
#include <map>
#include <string>
#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/binary_messenger.h"
namespace flutter {
// A trivial BinaryMessenger implementation for use in tests.
class TestBinaryMessenger : public BinaryMessenger {
public:
using SendHandler = std::function<void(const std::string& channel,
const uint8_t* message,
size_t message_size,
BinaryReply reply)>;
// Creates a new messenge that forwards all calls to |send_handler|.
explicit TestBinaryMessenger(SendHandler send_handler = nullptr)
: send_handler_(std::move(send_handler)) {}
virtual ~TestBinaryMessenger() = default;
// Prevent copying.
TestBinaryMessenger(TestBinaryMessenger const&) = delete;
TestBinaryMessenger& operator=(TestBinaryMessenger const&) = delete;
// Simulates a message from the engine on the given channel.
//
// Returns false if no handler is registered on that channel.
bool SimulateEngineMessage(const std::string& channel,
const uint8_t* message,
size_t message_size,
BinaryReply reply) {
auto handler = registered_handlers_.find(channel);
if (handler == registered_handlers_.end()) {
return false;
}
(handler->second)(message, message_size, reply);
return true;
}
// |flutter::BinaryMessenger|
void Send(const std::string& channel,
const uint8_t* message,
size_t message_size,
BinaryReply reply) const override {
// If something under test sends a message, the test should be handling it.
assert(send_handler_);
send_handler_(channel, message, message_size, reply);
}
// |flutter::BinaryMessenger|
void SetMessageHandler(const std::string& channel,
BinaryMessageHandler handler) override {
if (handler) {
registered_handlers_[channel] = handler;
} else {
registered_handlers_.erase(channel);
}
}
private:
// Handler to call for SendMessage.
SendHandler send_handler_;
// Mapping of channel name to registered handlers.
std::map<std::string, BinaryMessageHandler> registered_handlers_;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_TEST_BINARY_MESSENGER_H_
......@@ -143,6 +143,8 @@ def to_gn_args(args):
elif args.target_os == 'fuchsia':
gn_args['target_os'] = 'fuchsia'
gn_args['flutter_enable_legacy_fuchsia_embedder'] = args.fuchsia_legacy
elif args.target_os == 'winuwp':
gn_args['target_os'] = 'winuwp'
elif args.target_os is not None:
gn_args['target_os'] = args.target_os
......@@ -328,6 +330,7 @@ def parse_args(args):
parser.add_argument('--fuchsia', dest='target_os', action='store_const', const='fuchsia')
parser.add_argument('--fuchsia-legacy', default=True, action='store_true')
parser.add_argument('--no-fuchsia-legacy', dest='fuchsia_legacy', action='store_false')
parser.add_argument('--winuwp', dest='target_os', action='store_const', const='winuwp')
parser.add_argument('--linux-cpu', type=str, choices=['x64', 'x86', 'arm64', 'arm'])
parser.add_argument('--fuchsia-cpu', type=str, choices=['x64', 'arm64'], default = 'x64')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册