未验证 提交 32b1b70e 编写于 作者: S stuartmorgan 提交者: GitHub

[windows] Expose the binary messenger from FlutterEngine (#20551)

Relands https://github.com/flutter/engine/pull/20399

Makes BinaryMessenger available from FlutterEngine, rather than just the plugin registrar. This allows for method channels directly in applications without building them as plugins, and matches the other platforms.

Requires some restructuring of code and GN targets in the client wrappers to make the internals in the shared section usable by the implementations of platform-specific parts of the wrappers. Also fixes a latent issue with EnableInputBlocking symbols being declared but not defined for Windows that came up during testing of the restructing.

Fixes https://github.com/flutter/flutter/issues/62871
上级 76d49222
......@@ -836,7 +836,9 @@ FILE: ../../../flutter/shell/platform/android/surface/android_surface_mock.h
FILE: ../../../flutter/shell/platform/android/vsync_waiter_android.cc
FILE: ../../../flutter/shell/platform/android/vsync_waiter_android.h
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/basic_message_channel_unittests.cc
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/binary_messenger_impl.h
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/byte_buffer_streams.h
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/core_implementations.cc
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/encodable_value_unittests.cc
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/engine_method_result.cc
FILE: ../../../flutter/shell/platform/common/cpp/client_wrapper/event_channel_unittests.cc
......
......@@ -8,7 +8,8 @@ import("core_wrapper_files.gni")
# Client library build for internal use by the shell implementation.
source_set("client_wrapper") {
sources = core_cpp_client_wrapper_sources
public = core_cpp_client_wrapper_includes
public = core_cpp_client_wrapper_includes +
core_cpp_client_wrapper_internal_headers
deps = [ "//flutter/shell/platform/common/cpp:common_cpp_library_headers" ]
......@@ -23,7 +24,8 @@ source_set("client_wrapper") {
# legacy version is removed.
source_set("client_wrapper_legacy_encodable_value") {
sources = core_cpp_client_wrapper_sources
public = core_cpp_client_wrapper_includes
public = core_cpp_client_wrapper_includes +
core_cpp_client_wrapper_internal_headers
deps = [ "//flutter/shell/platform/common/cpp:common_cpp_library_headers" ]
......
// 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_COMMON_CPP_CLIENT_WRAPPER_BINARY_MESSENGER_IMPL_H_
#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BINARY_MESSENGER_IMPL_H_
#include <flutter_messenger.h>
#include <map>
#include <string>
#include "include/flutter/binary_messenger.h"
namespace flutter {
// Wrapper around a FlutterDesktopMessengerRef that implements the
// BinaryMessenger API.
class BinaryMessengerImpl : public BinaryMessenger {
public:
explicit BinaryMessengerImpl(FlutterDesktopMessengerRef core_messenger);
virtual ~BinaryMessengerImpl();
// Prevent copying.
BinaryMessengerImpl(BinaryMessengerImpl const&) = delete;
BinaryMessengerImpl& operator=(BinaryMessengerImpl const&) = delete;
// |flutter::BinaryMessenger|
void Send(const std::string& channel,
const uint8_t* message,
size_t message_size,
BinaryReply reply) const override;
// |flutter::BinaryMessenger|
void SetMessageHandler(const std::string& channel,
BinaryMessageHandler handler) override;
private:
// Handle for interacting with the C API.
FlutterDesktopMessengerRef messenger_;
// A map from channel names to the BinaryMessageHandler that should be called
// for incoming messages on that channel.
std::map<std::string, BinaryMessageHandler> handlers_;
};
} // namespace flutter
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BINARY_MESSENGER_IMPL_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.
// This file contains the implementations of any class in the wrapper that
// - is not fully inline, and
// - is necessary for all clients of the wrapper (either app or plugin).
// It exists instead of the usual structure of having some_class_name.cc files
// so that changes to the set of things that need non-header implementations
// are not breaking changes for the template.
//
// If https://github.com/flutter/flutter/issues/57146 is fixed, this can be
// removed in favor of the normal structure since templates will no longer
// manually include files.
#include <assert.h>
#include <iostream>
#include "binary_messenger_impl.h"
#include "include/flutter/engine_method_result.h"
namespace flutter {
// ========== binary_messenger_impl.h ==========
namespace {
// Passes |message| to |user_data|, which must be a BinaryMessageHandler, along
// with a BinaryReply that will send a response on |message|'s response handle.
//
// This serves as an adaptor between the function-pointer-based message callback
// interface provided by the C API and the std::function-based message handler
// interface of BinaryMessenger.
void ForwardToHandler(FlutterDesktopMessengerRef messenger,
const FlutterDesktopMessage* message,
void* user_data) {
auto* response_handle = message->response_handle;
BinaryReply reply_handler = [messenger, response_handle](
const uint8_t* reply,
size_t reply_size) mutable {
if (!response_handle) {
std::cerr << "Error: Response can be set only once. Ignoring "
"duplicate response."
<< std::endl;
return;
}
FlutterDesktopMessengerSendResponse(messenger, response_handle, reply,
reply_size);
// The engine frees the response handle once
// FlutterDesktopSendMessageResponse is called.
response_handle = nullptr;
};
const BinaryMessageHandler& message_handler =
*static_cast<BinaryMessageHandler*>(user_data);
message_handler(message->message, message->message_size,
std::move(reply_handler));
}
} // namespace
BinaryMessengerImpl::BinaryMessengerImpl(
FlutterDesktopMessengerRef core_messenger)
: messenger_(core_messenger) {}
BinaryMessengerImpl::~BinaryMessengerImpl() = default;
void BinaryMessengerImpl::Send(const std::string& channel,
const uint8_t* message,
size_t message_size,
BinaryReply reply) const {
if (reply == nullptr) {
FlutterDesktopMessengerSend(messenger_, channel.c_str(), message,
message_size);
return;
}
struct Captures {
BinaryReply reply;
};
auto captures = new Captures();
captures->reply = reply;
auto message_reply = [](const uint8_t* data, size_t data_size,
void* user_data) {
auto captures = reinterpret_cast<Captures*>(user_data);
captures->reply(data, data_size);
delete captures;
};
bool result = FlutterDesktopMessengerSendWithReply(
messenger_, channel.c_str(), message, message_size, message_reply,
captures);
if (!result) {
delete captures;
}
}
void BinaryMessengerImpl::SetMessageHandler(const std::string& channel,
BinaryMessageHandler handler) {
if (!handler) {
handlers_.erase(channel);
FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(), nullptr,
nullptr);
return;
}
// Save the handler, to keep it alive.
handlers_[channel] = std::move(handler);
BinaryMessageHandler* message_handler = &handlers_[channel];
// Set an adaptor callback that will invoke the handler.
FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(),
ForwardToHandler, message_handler);
}
// ========== engine_method_result.h ==========
namespace internal {
ReplyManager::ReplyManager(BinaryReply reply_handler)
: reply_handler_(std::move(reply_handler)) {
assert(reply_handler_);
}
ReplyManager::~ReplyManager() {
if (reply_handler_) {
// Warn, rather than send a not-implemented response, since the engine may
// no longer be valid at this point.
std::cerr
<< "Warning: Failed to respond to a message. This is a memory leak."
<< std::endl;
}
}
void ReplyManager::SendResponseData(const std::vector<uint8_t>* data) {
if (!reply_handler_) {
std::cerr
<< "Error: Only one of Success, Error, or NotImplemented can be "
"called,"
<< " and it can be called exactly once. Ignoring duplicate result."
<< std::endl;
return;
}
const uint8_t* message = data && !data->empty() ? data->data() : nullptr;
size_t message_size = data ? data->size() : 0;
reply_handler_(message, message_size);
reply_handler_ = nullptr;
}
} // namespace internal
} // namespace flutter
......@@ -27,13 +27,26 @@ core_cpp_client_wrapper_includes =
],
"abspath")
# Headers that aren't public for clients of the wrapper, but are considered
# public for the purpose of BUILD dependencies (e.g., to allow
# windows/client_wrapper implementation files to include them).
core_cpp_client_wrapper_internal_headers =
get_path_info([
"binary_messenger_impl.h",
"byte_buffer_streams.h",
],
"abspath")
# TODO: Once the wrapper API is more stable, consolidate to as few files as is
# reasonable (without forcing different kinds of clients to take unnecessary
# code) to simplify use.
core_cpp_client_wrapper_sources = get_path_info([
"byte_buffer_streams.h",
"engine_method_result.cc",
"core_implementations.cc",
"plugin_registrar.cc",
"standard_codec.cc",
],
"abspath")
# Temporary shim, published for backwards compatibility.
# See comment in the file for more detail.
temporary_shim_files = get_path_info([ "engine_method_result.cc" ], "abspath")
......@@ -2,44 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "include/flutter/engine_method_result.h"
// This file is deprecated in favor of core_implementations.cc. This is a
// temporary forwarding implementation so that the switch to
// core_implementations.cc isn't an immediate breaking change, allowing for the
// template to be updated to include it and update the template version before
// removing this file.
#include <assert.h>
#include <iostream>
namespace flutter {
namespace internal {
ReplyManager::ReplyManager(BinaryReply reply_handler)
: reply_handler_(std::move(reply_handler)) {
assert(reply_handler_);
}
ReplyManager::~ReplyManager() {
if (reply_handler_) {
// Warn, rather than send a not-implemented response, since the engine may
// no longer be valid at this point.
std::cerr
<< "Warning: Failed to respond to a message. This is a memory leak."
<< std::endl;
}
}
void ReplyManager::SendResponseData(const std::vector<uint8_t>* data) {
if (!reply_handler_) {
std::cerr
<< "Error: Only one of Success, Error, or NotImplemented can be "
"called,"
<< " and it can be called exactly once. Ignoring duplicate result."
<< std::endl;
return;
}
const uint8_t* message = data && !data->empty() ? data->data() : nullptr;
size_t message_size = data ? data->size() : 0;
reply_handler_(message, message_size);
reply_handler_ = nullptr;
}
} // namespace internal
} // namespace flutter
#include "core_implementations.cc"
......@@ -7,125 +7,12 @@
#include <iostream>
#include <map>
#include "binary_messenger_impl.h"
#include "include/flutter/engine_method_result.h"
#include "include/flutter/method_channel.h"
namespace flutter {
namespace {
// Passes |message| to |user_data|, which must be a BinaryMessageHandler, along
// with a BinaryReply that will send a response on |message|'s response handle.
//
// This serves as an adaptor between the function-pointer-based message callback
// interface provided by the C API and the std::function-based message handler
// interface of BinaryMessenger.
void ForwardToHandler(FlutterDesktopMessengerRef messenger,
const FlutterDesktopMessage* message,
void* user_data) {
auto* response_handle = message->response_handle;
BinaryReply reply_handler = [messenger, response_handle](
const uint8_t* reply,
size_t reply_size) mutable {
if (!response_handle) {
std::cerr << "Error: Response can be set only once. Ignoring "
"duplicate response."
<< std::endl;
return;
}
FlutterDesktopMessengerSendResponse(messenger, response_handle, reply,
reply_size);
// The engine frees the response handle once
// FlutterDesktopSendMessageResponse is called.
response_handle = nullptr;
};
const BinaryMessageHandler& message_handler =
*static_cast<BinaryMessageHandler*>(user_data);
message_handler(message->message, message->message_size,
std::move(reply_handler));
}
} // namespace
// Wrapper around a FlutterDesktopMessengerRef that implements the
// BinaryMessenger API.
class BinaryMessengerImpl : public BinaryMessenger {
public:
explicit BinaryMessengerImpl(FlutterDesktopMessengerRef core_messenger)
: messenger_(core_messenger) {}
virtual ~BinaryMessengerImpl() = default;
// Prevent copying.
BinaryMessengerImpl(BinaryMessengerImpl const&) = delete;
BinaryMessengerImpl& operator=(BinaryMessengerImpl const&) = delete;
// |flutter::BinaryMessenger|
void Send(const std::string& channel,
const uint8_t* message,
size_t message_size,
BinaryReply reply) const override;
// |flutter::BinaryMessenger|
void SetMessageHandler(const std::string& channel,
BinaryMessageHandler handler) override;
private:
// Handle for interacting with the C API.
FlutterDesktopMessengerRef messenger_;
// A map from channel names to the BinaryMessageHandler that should be called
// for incoming messages on that channel.
std::map<std::string, BinaryMessageHandler> handlers_;
};
void BinaryMessengerImpl::Send(const std::string& channel,
const uint8_t* message,
size_t message_size,
BinaryReply reply) const {
if (reply == nullptr) {
FlutterDesktopMessengerSend(messenger_, channel.c_str(), message,
message_size);
return;
}
struct Captures {
BinaryReply reply;
};
auto captures = new Captures();
captures->reply = reply;
auto message_reply = [](const uint8_t* data, size_t data_size,
void* user_data) {
auto captures = reinterpret_cast<Captures*>(user_data);
captures->reply(data, data_size);
delete captures;
};
bool result = FlutterDesktopMessengerSendWithReply(
messenger_, channel.c_str(), message, message_size, message_reply,
captures);
if (!result) {
delete captures;
}
}
void BinaryMessengerImpl::SetMessageHandler(const std::string& channel,
BinaryMessageHandler handler) {
if (!handler) {
handlers_.erase(channel);
FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(), nullptr,
nullptr);
return;
}
// Save the handler, to keep it alive.
handlers_[channel] = std::move(handler);
BinaryMessageHandler* message_handler = &handlers_[channel];
// Set an adaptor callback that will invoke the handler.
FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(),
ForwardToHandler, message_handler);
}
// ===== PluginRegistrar =====
PluginRegistrar::PluginRegistrar(FlutterDesktopPluginRegistrarRef registrar)
......
......@@ -71,7 +71,9 @@ template("publish_client_wrapper_core") {
"visibility",
])
public = core_cpp_client_wrapper_includes
sources = core_cpp_client_wrapper_sources + [ _wrapper_readme ]
sources = core_cpp_client_wrapper_sources +
core_cpp_client_wrapper_internal_headers + [ _wrapper_readme ] +
temporary_shim_files
}
}
......
......@@ -52,14 +52,6 @@ void FlutterDesktopRegistrarSetDestructionHandler(
}
}
void FlutterDesktopRegistrarEnableInputBlocking(
FlutterDesktopPluginRegistrarRef registrar,
const char* channel) {
if (s_stub_implementation) {
s_stub_implementation->RegistrarEnableInputBlocking(channel);
}
}
bool FlutterDesktopMessengerSend(FlutterDesktopMessengerRef messenger,
const char* channel,
const uint8_t* message,
......
......@@ -38,9 +38,6 @@ class StubFlutterApi {
virtual void RegistrarSetDestructionHandler(
FlutterDesktopOnRegistrarDestroyed callback) {}
// Called for FlutterDesktopRegistrarEnableInputBlocking.
virtual void RegistrarEnableInputBlocking(const char* channel) {}
// Called for FlutterDesktopMessengerSend.
virtual bool MessengerSend(const char* channel,
const uint8_t* message,
......
......@@ -31,19 +31,6 @@ FLUTTER_EXPORT void FlutterDesktopRegistrarSetDestructionHandler(
FlutterDesktopPluginRegistrarRef registrar,
FlutterDesktopOnRegistrarDestroyed callback);
// Enables input blocking on the given channel.
//
// If set, then the Flutter window will disable input callbacks
// while waiting for the handler for messages on that channel to run. This is
// useful if handling the message involves showing a modal window, for instance.
//
// This must be called after FlutterDesktopSetMessageHandler, as setting a
// handler on a channel will reset the input blocking state back to the
// default of disabled.
FLUTTER_EXPORT void FlutterDesktopRegistrarEnableInputBlocking(
FlutterDesktopPluginRegistrarRef registrar,
const char* channel);
#if defined(__cplusplus)
} // extern "C"
#endif
......
......@@ -182,3 +182,11 @@ FlutterDesktopPluginRegistrarRef FlutterDesktopGetPluginRegistrar(
// The stub ignores this, so just return an arbitrary non-zero value.
return reinterpret_cast<FlutterDesktopPluginRegistrarRef>(2);
}
void FlutterDesktopRegistrarEnableInputBlocking(
FlutterDesktopPluginRegistrarRef registrar,
const char* channel) {
if (s_stub_implementation) {
s_stub_implementation->RegistrarEnableInputBlocking(channel);
}
}
......@@ -88,6 +88,9 @@ class StubFlutterGlfwApi {
// Called for FlutterDesktopShutDownEngine.
virtual bool ShutDownEngine() { return true; }
// Called for FlutterDesktopRegistrarEnableInputBlocking.
virtual void RegistrarEnableInputBlocking(const char* channel) {}
};
// A test helper that owns a stub implementation, making it the test stub for
......
......@@ -219,10 +219,26 @@ FLUTTER_EXPORT bool FlutterDesktopShutDownEngine(
FlutterDesktopEngineRef engine);
// Returns the window associated with this registrar's engine instance.
//
// This is a GLFW shell-specific extension to flutter_plugin_registrar.h
FLUTTER_EXPORT FlutterDesktopWindowRef
FlutterDesktopRegistrarGetWindow(FlutterDesktopPluginRegistrarRef registrar);
// Enables input blocking on the given channel.
//
// If set, then the Flutter window will disable input callbacks
// while waiting for the handler for messages on that channel to run. This is
// useful if handling the message involves showing a modal window, for instance.
//
// This must be called after FlutterDesktopSetMessageHandler, as setting a
// handler on a channel will reset the input blocking state back to the
// default of disabled.
//
// This is a GLFW shell-specific extension to flutter_plugin_registrar.h
FLUTTER_EXPORT void FlutterDesktopRegistrarEnableInputBlocking(
FlutterDesktopPluginRegistrarRef registrar,
const char* channel);
#if defined(__cplusplus)
} // extern "C"
#endif
......
......@@ -20,10 +20,12 @@ _wrapper_sources = [
# This code will be merged into .../common/cpp/client_wrapper for client use,
# so uses header paths that assume the merged state. Include the header
# header directory of the core wrapper files so these includes will work.
# directories of the core wrapper files so these includes will work.
config("relative_core_wrapper_headers") {
include_dirs =
[ "//flutter/shell/platform/common/cpp/client_wrapper/include/flutter" ]
include_dirs = [
"//flutter/shell/platform/common/cpp/client_wrapper",
"//flutter/shell/platform/common/cpp/client_wrapper/include/flutter",
]
}
# Windows client wrapper build for internal use by the shell implementation.
......
......@@ -7,6 +7,8 @@
#include <algorithm>
#include <iostream>
#include "binary_messenger_impl.h"
namespace flutter {
FlutterEngine::FlutterEngine(const DartProject& project) {
......@@ -25,6 +27,9 @@ FlutterEngine::FlutterEngine(const DartProject& project) {
}
engine_ = FlutterDesktopEngineCreate(c_engine_properties);
auto core_messenger = FlutterDesktopEngineGetMessenger(engine_);
messenger_ = std::make_unique<BinaryMessengerImpl>(core_messenger);
}
FlutterEngine::~FlutterEngine() {
......
......@@ -93,4 +93,14 @@ TEST(FlutterEngineTest, ProcessMessages) {
EXPECT_EQ(next_event_time.count(), 99);
}
TEST(FlutterEngineTest, GetMessenger) {
DartProject project(L"data");
testing::ScopedStubFlutterWindowsApi scoped_api_stub(
std::make_unique<TestFlutterWindowsApi>());
auto test_api = static_cast<TestFlutterWindowsApi*>(scoped_api_stub.stub());
FlutterEngine engine(DartProject(L"fake/project/path"));
EXPECT_NE(engine.messenger(), nullptr);
}
} // namespace flutter
......@@ -12,6 +12,7 @@
#include <memory>
#include <string>
#include "binary_messenger.h"
#include "dart_project.h"
#include "plugin_registrar.h"
#include "plugin_registry.h"
......@@ -57,6 +58,12 @@ class FlutterEngine : public PluginRegistry {
FlutterDesktopPluginRegistrarRef GetRegistrarForPlugin(
const std::string& plugin_name) override;
// Returns the messenger to use for creating channels to communicate with the
// Flutter engine.
//
// This pointer will remain valid for the lifetime of this instance.
BinaryMessenger* messenger() { return messenger_.get(); }
private:
// For access to RelinquishEngine.
friend class FlutterViewController;
......@@ -70,6 +77,9 @@ class FlutterEngine : public PluginRegistry {
// Handle for interacting with the C API's engine reference.
FlutterDesktopEngineRef engine_ = nullptr;
// Messenger for communicating with the engine.
std::unique_ptr<BinaryMessenger> messenger_;
// Whether or not this wrapper owns |engine_|.
bool owns_engine_ = true;
......
......@@ -101,6 +101,12 @@ FlutterDesktopPluginRegistrarRef FlutterDesktopEngineGetPluginRegistrar(
return reinterpret_cast<FlutterDesktopPluginRegistrarRef>(1);
}
FlutterDesktopMessengerRef FlutterDesktopEngineGetMessenger(
FlutterDesktopEngineRef engine) {
// The stub ignores this, so just return an arbitrary non-zero value.
return reinterpret_cast<FlutterDesktopMessengerRef>(2);
}
HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef controller) {
if (s_stub_implementation) {
return s_stub_implementation->ViewGetHWND();
......
......@@ -119,6 +119,11 @@ FlutterDesktopPluginRegistrarRef FlutterDesktopEngineGetPluginRegistrar(
return EngineFromHandle(engine)->GetRegistrar();
}
FlutterDesktopMessengerRef FlutterDesktopEngineGetMessenger(
FlutterDesktopEngineRef engine) {
return EngineFromHandle(engine)->messenger();
}
HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view_ref) {
return std::get<HWND>(*view_ref->view->GetRenderTarget());
}
......@@ -151,7 +156,7 @@ void FlutterDesktopResyncOutputStreams() {
FlutterDesktopMessengerRef FlutterDesktopRegistrarGetMessenger(
FlutterDesktopPluginRegistrarRef registrar) {
return registrar->messenger.get();
return registrar->messenger;
}
void FlutterDesktopRegistrarSetDestructionHandler(
......
......@@ -85,15 +85,15 @@ FlutterWindowsEngine::FlutterWindowsEngine(const FlutterProjectBundle& project)
}
});
// Set up the structure of the state/handle objects; engine and view paramater
// will be filled in late.
auto messenger = std::make_unique<FlutterDesktopMessenger>();
// Set up the structure of the state/handle objects; engine and view
// paramaters will be filled in later.
messenger_ = std::make_unique<FlutterDesktopMessenger>();
message_dispatcher_ =
std::make_unique<IncomingMessageDispatcher>(messenger.get());
messenger->dispatcher = message_dispatcher_.get();
std::make_unique<IncomingMessageDispatcher>(messenger_.get());
messenger_->dispatcher = message_dispatcher_.get();
plugin_registrar_ = std::make_unique<FlutterDesktopPluginRegistrar>();
plugin_registrar_->messenger = std::move(messenger);
plugin_registrar_->messenger = messenger_.get();
plugin_registrar_->view = std::make_unique<FlutterDesktopView>();
}
......
......@@ -60,6 +60,8 @@ class FlutterWindowsEngine {
FLUTTER_API_SYMBOL(FlutterEngine) engine() { return engine_; }
FlutterDesktopMessengerRef messenger() { return messenger_.get(); }
Win32TaskRunner* task_runner() { return task_runner_.get(); }
// Callback passed to Flutter engine for notifying window of platform
......@@ -81,6 +83,9 @@ class FlutterWindowsEngine {
// Task runner for tasks posted from the engine.
std::unique_ptr<Win32TaskRunner> task_runner_;
// The plugin messenger handle given to API clients.
std::unique_ptr<FlutterDesktopMessenger> messenger_;
// Message dispatch manager for messages from engine_.
std::unique_ptr<IncomingMessageDispatcher> message_dispatcher_;
......
......@@ -136,6 +136,10 @@ FLUTTER_EXPORT FlutterDesktopPluginRegistrarRef
FlutterDesktopEngineGetPluginRegistrar(FlutterDesktopEngineRef engine,
const char* plugin_name);
// Returns the messenger associated with the engine.
FLUTTER_EXPORT FlutterDesktopMessengerRef
FlutterDesktopEngineGetMessenger(FlutterDesktopEngineRef engine);
// ========== View ==========
// Return backing HWND for manipulation in host application.
......
......@@ -35,7 +35,7 @@ struct FlutterDesktopView {
// State associated with the plugin registrar.
struct FlutterDesktopPluginRegistrar {
// The plugin messenger handle given to API clients.
std::unique_ptr<FlutterDesktopMessenger> messenger;
FlutterDesktopMessenger* messenger;
// The handle for the view associated with this registrar.
std::unique_ptr<FlutterDesktopView> view;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册