From 67cf6c312cdeb41d97e77724ec118fba99bc955c Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Mon, 17 Aug 2020 05:44:48 -0700 Subject: [PATCH] [windows] Expose the binary messenger from FlutterEngine (flutter/engine#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 --- .../ci/licenses_golden/licenses_flutter | 2 + .../common/cpp/client_wrapper/BUILD.gn | 6 +- .../client_wrapper/binary_messenger_impl.h | 50 ++++++ .../client_wrapper/core_implementations.cc | 150 ++++++++++++++++++ .../cpp/client_wrapper/core_wrapper_files.gni | 17 +- .../client_wrapper/engine_method_result.cc | 46 +----- .../cpp/client_wrapper/plugin_registrar.cc | 115 +------------- .../common/cpp/client_wrapper/publish.gni | 4 +- .../testing/stub_flutter_api.cc | 8 - .../client_wrapper/testing/stub_flutter_api.h | 3 - .../cpp/public/flutter_plugin_registrar.h | 13 -- .../testing/stub_flutter_glfw_api.cc | 8 + .../testing/stub_flutter_glfw_api.h | 3 + .../shell/platform/glfw/public/flutter_glfw.h | 16 ++ .../platform/windows/client_wrapper/BUILD.gn | 8 +- .../windows/client_wrapper/flutter_engine.cc | 5 + .../flutter_engine_unittests.cc | 10 ++ .../include/flutter/flutter_engine.h | 10 ++ .../testing/stub_flutter_windows_api.cc | 6 + .../shell/platform/windows/flutter_windows.cc | 7 +- .../windows/flutter_windows_engine.cc | 12 +- .../platform/windows/flutter_windows_engine.h | 5 + .../platform/windows/public/flutter_windows.h | 4 + .../shell/platform/windows/window_state.h | 2 +- 24 files changed, 316 insertions(+), 194 deletions(-) create mode 100644 engine/src/flutter/shell/platform/common/cpp/client_wrapper/binary_messenger_impl.h create mode 100644 engine/src/flutter/shell/platform/common/cpp/client_wrapper/core_implementations.cc diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index df47b5db5ed..b4f0b0fbca8 100755 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -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 diff --git a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/BUILD.gn b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/BUILD.gn index e1adbbaf3e5..6c297103d43 100644 --- a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/BUILD.gn +++ b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/BUILD.gn @@ -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" ] diff --git a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/binary_messenger_impl.h b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/binary_messenger_impl.h new file mode 100644 index 00000000000..28fa475c116 --- /dev/null +++ b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/binary_messenger_impl.h @@ -0,0 +1,50 @@ +// 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 + +#include +#include + +#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 handlers_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BINARY_MESSENGER_IMPL_H_ diff --git a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/core_implementations.cc b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/core_implementations.cc new file mode 100644 index 00000000000..2cafc7f9fe3 --- /dev/null +++ b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/core_implementations.cc @@ -0,0 +1,150 @@ +// 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 + +#include + +#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(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(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* 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 diff --git a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni index f86d87e0243..264bf774e61 100644 --- a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni +++ b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/core_wrapper_files.gni @@ -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") diff --git a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/engine_method_result.cc b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/engine_method_result.cc index 03e17a82e6b..65eaf5d4358 100644 --- a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/engine_method_result.cc +++ b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/engine_method_result.cc @@ -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 -#include - -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* 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" diff --git a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc index 7cdd6af903a..a779d6e26df 100644 --- a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc +++ b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/plugin_registrar.cc @@ -7,125 +7,12 @@ #include #include +#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(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 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(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) diff --git a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/publish.gni b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/publish.gni index e52bf6a3193..907197b6cce 100644 --- a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/publish.gni +++ b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/publish.gni @@ -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 } } diff --git a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc index 580df48645a..1f605489522 100644 --- a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc +++ b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.cc @@ -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, diff --git a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h index 284d15e9749..ae55cdc9010 100644 --- a/engine/src/flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h +++ b/engine/src/flutter/shell/platform/common/cpp/client_wrapper/testing/stub_flutter_api.h @@ -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, diff --git a/engine/src/flutter/shell/platform/common/cpp/public/flutter_plugin_registrar.h b/engine/src/flutter/shell/platform/common/cpp/public/flutter_plugin_registrar.h index 95f0abf1396..e27e125530a 100644 --- a/engine/src/flutter/shell/platform/common/cpp/public/flutter_plugin_registrar.h +++ b/engine/src/flutter/shell/platform/common/cpp/public/flutter_plugin_registrar.h @@ -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 diff --git a/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc b/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc index 38614fc15c5..8875a1b51d2 100644 --- a/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc +++ b/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc @@ -182,3 +182,11 @@ FlutterDesktopPluginRegistrarRef FlutterDesktopGetPluginRegistrar( // The stub ignores this, so just return an arbitrary non-zero value. return reinterpret_cast(2); } + +void FlutterDesktopRegistrarEnableInputBlocking( + FlutterDesktopPluginRegistrarRef registrar, + const char* channel) { + if (s_stub_implementation) { + s_stub_implementation->RegistrarEnableInputBlocking(channel); + } +} diff --git a/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h b/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h index 25792e8c14b..765a02e45f7 100644 --- a/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h +++ b/engine/src/flutter/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h @@ -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 diff --git a/engine/src/flutter/shell/platform/glfw/public/flutter_glfw.h b/engine/src/flutter/shell/platform/glfw/public/flutter_glfw.h index 45a6420f93c..e8b45138778 100644 --- a/engine/src/flutter/shell/platform/glfw/public/flutter_glfw.h +++ b/engine/src/flutter/shell/platform/glfw/public/flutter_glfw.h @@ -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 diff --git a/engine/src/flutter/shell/platform/windows/client_wrapper/BUILD.gn b/engine/src/flutter/shell/platform/windows/client_wrapper/BUILD.gn index 27f8fb77a24..fe54c2ba2a4 100644 --- a/engine/src/flutter/shell/platform/windows/client_wrapper/BUILD.gn +++ b/engine/src/flutter/shell/platform/windows/client_wrapper/BUILD.gn @@ -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. diff --git a/engine/src/flutter/shell/platform/windows/client_wrapper/flutter_engine.cc b/engine/src/flutter/shell/platform/windows/client_wrapper/flutter_engine.cc index 1f55ed8077b..8bf94420646 100644 --- a/engine/src/flutter/shell/platform/windows/client_wrapper/flutter_engine.cc +++ b/engine/src/flutter/shell/platform/windows/client_wrapper/flutter_engine.cc @@ -7,6 +7,8 @@ #include #include +#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(core_messenger); } FlutterEngine::~FlutterEngine() { diff --git a/engine/src/flutter/shell/platform/windows/client_wrapper/flutter_engine_unittests.cc b/engine/src/flutter/shell/platform/windows/client_wrapper/flutter_engine_unittests.cc index 05880ebf504..8fe83225b11 100644 --- a/engine/src/flutter/shell/platform/windows/client_wrapper/flutter_engine_unittests.cc +++ b/engine/src/flutter/shell/platform/windows/client_wrapper/flutter_engine_unittests.cc @@ -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()); + auto test_api = static_cast(scoped_api_stub.stub()); + + FlutterEngine engine(DartProject(L"fake/project/path")); + EXPECT_NE(engine.messenger(), nullptr); +} + } // namespace flutter diff --git a/engine/src/flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_engine.h b/engine/src/flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_engine.h index b4e3ee1b0cb..94edb4064dd 100644 --- a/engine/src/flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_engine.h +++ b/engine/src/flutter/shell/platform/windows/client_wrapper/include/flutter/flutter_engine.h @@ -12,6 +12,7 @@ #include #include +#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 messenger_; + // Whether or not this wrapper owns |engine_|. bool owns_engine_ = true; diff --git a/engine/src/flutter/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc b/engine/src/flutter/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc index c8cd7a8299f..de8b54902a6 100644 --- a/engine/src/flutter/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc +++ b/engine/src/flutter/shell/platform/windows/client_wrapper/testing/stub_flutter_windows_api.cc @@ -101,6 +101,12 @@ FlutterDesktopPluginRegistrarRef FlutterDesktopEngineGetPluginRegistrar( return reinterpret_cast(1); } +FlutterDesktopMessengerRef FlutterDesktopEngineGetMessenger( + FlutterDesktopEngineRef engine) { + // The stub ignores this, so just return an arbitrary non-zero value. + return reinterpret_cast(2); +} + HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef controller) { if (s_stub_implementation) { return s_stub_implementation->ViewGetHWND(); diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows.cc b/engine/src/flutter/shell/platform/windows/flutter_windows.cc index ce7b82308ff..57b641e3fc8 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows.cc @@ -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(*view_ref->view->GetRenderTarget()); } @@ -151,7 +156,7 @@ void FlutterDesktopResyncOutputStreams() { FlutterDesktopMessengerRef FlutterDesktopRegistrarGetMessenger( FlutterDesktopPluginRegistrarRef registrar) { - return registrar->messenger.get(); + return registrar->messenger; } void FlutterDesktopRegistrarSetDestructionHandler( diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc index 957c9432d8c..0dca78da269 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.cc @@ -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(); + // Set up the structure of the state/handle objects; engine and view + // paramaters will be filled in later. + messenger_ = std::make_unique(); message_dispatcher_ = - std::make_unique(messenger.get()); - messenger->dispatcher = message_dispatcher_.get(); + std::make_unique(messenger_.get()); + messenger_->dispatcher = message_dispatcher_.get(); plugin_registrar_ = std::make_unique(); - plugin_registrar_->messenger = std::move(messenger); + plugin_registrar_->messenger = messenger_.get(); plugin_registrar_->view = std::make_unique(); } diff --git a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.h b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.h index 61784a76f80..53e65f429e7 100644 --- a/engine/src/flutter/shell/platform/windows/flutter_windows_engine.h +++ b/engine/src/flutter/shell/platform/windows/flutter_windows_engine.h @@ -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 task_runner_; + // The plugin messenger handle given to API clients. + std::unique_ptr messenger_; + // Message dispatch manager for messages from engine_. std::unique_ptr message_dispatcher_; diff --git a/engine/src/flutter/shell/platform/windows/public/flutter_windows.h b/engine/src/flutter/shell/platform/windows/public/flutter_windows.h index 544aa6888f8..7cd0b89f2fb 100644 --- a/engine/src/flutter/shell/platform/windows/public/flutter_windows.h +++ b/engine/src/flutter/shell/platform/windows/public/flutter_windows.h @@ -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. diff --git a/engine/src/flutter/shell/platform/windows/window_state.h b/engine/src/flutter/shell/platform/windows/window_state.h index 58079051097..08fb5385050 100644 --- a/engine/src/flutter/shell/platform/windows/window_state.h +++ b/engine/src/flutter/shell/platform/windows/window_state.h @@ -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 messenger; + FlutterDesktopMessenger* messenger; // The handle for the view associated with this registrar. std::unique_ptr view;