mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-11 17:30:00 +02:00
feat: Add streaming handlers for live TV proxying and VOD HLS transcoding using FFmpeg.
This commit is contained in:
1 parent
887bfad433
commit
89bd5bd7cb
51 files changed
+4568
No files matched your search
@@ -0,0 +1 @@
|
||||
C:/Users/Jacques/AppData/Local/Pub/Cache/hosted/pub.dev/package_info_plus-9.0.0/
|
||||
@@ -0,0 +1 @@
|
||||
C:/Users/Jacques/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_windows-2.3.0/
|
||||
@@ -0,0 +1 @@
|
||||
C:/Users/Jacques/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_windows-2.4.1/
|
||||
@@ -0,0 +1 @@
|
||||
C:/Users/Jacques/AppData/Local/Pub/Cache/hosted/pub.dev/video_player_win-3.2.2/
|
||||
@@ -0,0 +1 @@
|
||||
C:/Users/Jacques/AppData/Local/Pub/Cache/hosted/pub.dev/wakelock_plus-1.4.0/
|
||||
@@ -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_CLIENT_WRAPPER_BINARY_MESSENGER_IMPL_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_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_CLIENT_WRAPPER_BINARY_MESSENGER_IMPL_H_
|
||||
@@ -0,0 +1,102 @@
|
||||
// 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_CLIENT_WRAPPER_BYTE_BUFFER_STREAMS_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_BYTE_BUFFER_STREAMS_H_
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "include/flutter/byte_streams.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// Implementation of ByteStreamReader base on a byte array.
|
||||
class ByteBufferStreamReader : public ByteStreamReader {
|
||||
public:
|
||||
// Createa a reader reading from |bytes|, which must have a length of |size|.
|
||||
// |bytes| must remain valid for the lifetime of this object.
|
||||
explicit ByteBufferStreamReader(const uint8_t* bytes, size_t size)
|
||||
: bytes_(bytes), size_(size) {}
|
||||
|
||||
virtual ~ByteBufferStreamReader() = default;
|
||||
|
||||
// |ByteStreamReader|
|
||||
uint8_t ReadByte() override {
|
||||
if (location_ >= size_) {
|
||||
std::cerr << "Invalid read in StandardCodecByteStreamReader" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
return bytes_[location_++];
|
||||
}
|
||||
|
||||
// |ByteStreamReader|
|
||||
void ReadBytes(uint8_t* buffer, size_t length) override {
|
||||
if (location_ + length > size_) {
|
||||
std::cerr << "Invalid read in StandardCodecByteStreamReader" << std::endl;
|
||||
return;
|
||||
}
|
||||
std::memcpy(buffer, &bytes_[location_], length);
|
||||
location_ += length;
|
||||
}
|
||||
|
||||
// |ByteStreamReader|
|
||||
void ReadAlignment(uint8_t alignment) override {
|
||||
uint8_t mod = location_ % alignment;
|
||||
if (mod) {
|
||||
location_ += alignment - mod;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// The buffer to read from.
|
||||
const uint8_t* bytes_;
|
||||
// The total size of the buffer.
|
||||
size_t size_;
|
||||
// The current read location.
|
||||
size_t location_ = 0;
|
||||
};
|
||||
|
||||
// Implementation of ByteStreamWriter based on a byte array.
|
||||
class ByteBufferStreamWriter : public ByteStreamWriter {
|
||||
public:
|
||||
// Creates a writer that writes into |buffer|.
|
||||
// |buffer| must remain valid for the lifetime of this object.
|
||||
explicit ByteBufferStreamWriter(std::vector<uint8_t>* buffer)
|
||||
: bytes_(buffer) {
|
||||
assert(buffer);
|
||||
}
|
||||
|
||||
virtual ~ByteBufferStreamWriter() = default;
|
||||
|
||||
// |ByteStreamWriter|
|
||||
void WriteByte(uint8_t byte) { bytes_->push_back(byte); }
|
||||
|
||||
// |ByteStreamWriter|
|
||||
void WriteBytes(const uint8_t* bytes, size_t length) {
|
||||
assert(length > 0);
|
||||
bytes_->insert(bytes_->end(), bytes, bytes + length);
|
||||
}
|
||||
|
||||
// |ByteStreamWriter|
|
||||
void WriteAlignment(uint8_t alignment) {
|
||||
uint8_t mod = bytes_->size() % alignment;
|
||||
if (mod) {
|
||||
for (int i = 0; i < alignment - mod; ++i) {
|
||||
WriteByte(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// The buffer to write to.
|
||||
std::vector<uint8_t>* bytes_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_BYTE_BUFFER_STREAMS_H_
|
||||
@@ -0,0 +1,284 @@
|
||||
// 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 <cassert>
|
||||
#include <iostream>
|
||||
#include <variant>
|
||||
|
||||
#include "binary_messenger_impl.h"
|
||||
#include "include/flutter/engine_method_result.h"
|
||||
#include "include/flutter/method_channel.h"
|
||||
#include "include/flutter/standard_method_codec.h"
|
||||
#include "texture_registrar_impl.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// ========== binary_messenger_impl.h ==========
|
||||
|
||||
namespace {
|
||||
|
||||
using FlutterDesktopMessengerScopedLock =
|
||||
std::unique_ptr<FlutterDesktopMessenger,
|
||||
decltype(&FlutterDesktopMessengerUnlock)>;
|
||||
|
||||
// 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;
|
||||
auto messenger_ptr = std::shared_ptr<FlutterDesktopMessenger>(
|
||||
FlutterDesktopMessengerAddRef(messenger),
|
||||
&FlutterDesktopMessengerRelease);
|
||||
BinaryReply reply_handler = [messenger_ptr, response_handle](
|
||||
const uint8_t* reply,
|
||||
size_t reply_size) mutable {
|
||||
// Note: This lambda can be called on any thread.
|
||||
auto lock = FlutterDesktopMessengerScopedLock(
|
||||
FlutterDesktopMessengerLock(messenger_ptr.get()),
|
||||
&FlutterDesktopMessengerUnlock);
|
||||
if (!FlutterDesktopMessengerIsAvailable(messenger_ptr.get())) {
|
||||
// Drop reply if it comes in after the engine is destroyed.
|
||||
return;
|
||||
}
|
||||
if (!response_handle) {
|
||||
std::cerr << "Error: Response can be set only once. Ignoring "
|
||||
"duplicate response."
|
||||
<< std::endl;
|
||||
return;
|
||||
}
|
||||
FlutterDesktopMessengerSendResponse(messenger_ptr.get(), 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
|
||||
|
||||
// ========== method_channel.h ==========
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr char kControlChannelName[] = "dev.flutter/channel-buffers";
|
||||
constexpr char kResizeMethod[] = "resize";
|
||||
constexpr char kOverflowMethod[] = "overflow";
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace internal {
|
||||
|
||||
void ResizeChannel(BinaryMessenger* messenger, std::string name, int new_size) {
|
||||
auto control_channel = std::make_unique<MethodChannel<EncodableValue>>(
|
||||
messenger, kControlChannelName, &StandardMethodCodec::GetInstance());
|
||||
|
||||
// The deserialization logic handles only 32 bits values, see
|
||||
// https://github.com/flutter/engine/blob/93e8901490e78c7ba7e319cce4470d9c6478c6dc/lib/ui/channel_buffers.dart#L495.
|
||||
control_channel->InvokeMethod(
|
||||
kResizeMethod, std::make_unique<EncodableValue>(EncodableList{
|
||||
EncodableValue(name),
|
||||
EncodableValue(static_cast<int32_t>(new_size)),
|
||||
}));
|
||||
}
|
||||
|
||||
void SetChannelWarnsOnOverflow(BinaryMessenger* messenger,
|
||||
std::string name,
|
||||
bool warns) {
|
||||
auto control_channel = std::make_unique<MethodChannel<EncodableValue>>(
|
||||
messenger, kControlChannelName, &StandardMethodCodec::GetInstance());
|
||||
|
||||
control_channel->InvokeMethod(kOverflowMethod,
|
||||
std::make_unique<EncodableValue>(EncodableList{
|
||||
EncodableValue(name),
|
||||
EncodableValue(!warns),
|
||||
}));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// ========== texture_registrar_impl.h ==========
|
||||
|
||||
TextureRegistrarImpl::TextureRegistrarImpl(
|
||||
FlutterDesktopTextureRegistrarRef texture_registrar_ref)
|
||||
: texture_registrar_ref_(texture_registrar_ref) {}
|
||||
|
||||
TextureRegistrarImpl::~TextureRegistrarImpl() = default;
|
||||
|
||||
int64_t TextureRegistrarImpl::RegisterTexture(TextureVariant* texture) {
|
||||
FlutterDesktopTextureInfo info = {};
|
||||
if (auto pixel_buffer_texture = std::get_if<PixelBufferTexture>(texture)) {
|
||||
info.type = kFlutterDesktopPixelBufferTexture;
|
||||
info.pixel_buffer_config.user_data = pixel_buffer_texture;
|
||||
info.pixel_buffer_config.callback =
|
||||
[](size_t width, size_t height,
|
||||
void* user_data) -> const FlutterDesktopPixelBuffer* {
|
||||
auto texture = static_cast<PixelBufferTexture*>(user_data);
|
||||
return texture->CopyPixelBuffer(width, height);
|
||||
};
|
||||
} else if (auto gpu_surface_texture =
|
||||
std::get_if<GpuSurfaceTexture>(texture)) {
|
||||
info.type = kFlutterDesktopGpuSurfaceTexture;
|
||||
info.gpu_surface_config.struct_size =
|
||||
sizeof(FlutterDesktopGpuSurfaceTextureConfig);
|
||||
info.gpu_surface_config.type = gpu_surface_texture->surface_type();
|
||||
info.gpu_surface_config.user_data = gpu_surface_texture;
|
||||
info.gpu_surface_config.callback =
|
||||
[](size_t width, size_t height,
|
||||
void* user_data) -> const FlutterDesktopGpuSurfaceDescriptor* {
|
||||
auto texture = static_cast<GpuSurfaceTexture*>(user_data);
|
||||
return texture->ObtainDescriptor(width, height);
|
||||
};
|
||||
} else {
|
||||
std::cerr << "Attempting to register unknown texture variant." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int64_t texture_id = FlutterDesktopTextureRegistrarRegisterExternalTexture(
|
||||
texture_registrar_ref_, &info);
|
||||
return texture_id;
|
||||
} // namespace flutter
|
||||
|
||||
bool TextureRegistrarImpl::MarkTextureFrameAvailable(int64_t texture_id) {
|
||||
return FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable(
|
||||
texture_registrar_ref_, texture_id);
|
||||
}
|
||||
|
||||
void TextureRegistrarImpl::UnregisterTexture(int64_t texture_id,
|
||||
std::function<void()> callback) {
|
||||
if (callback == nullptr) {
|
||||
FlutterDesktopTextureRegistrarUnregisterExternalTexture(
|
||||
texture_registrar_ref_, texture_id, nullptr, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
struct Captures {
|
||||
std::function<void()> callback;
|
||||
};
|
||||
auto captures = new Captures();
|
||||
captures->callback = std::move(callback);
|
||||
FlutterDesktopTextureRegistrarUnregisterExternalTexture(
|
||||
texture_registrar_ref_, texture_id,
|
||||
[](void* opaque) {
|
||||
auto captures = reinterpret_cast<Captures*>(opaque);
|
||||
captures->callback();
|
||||
delete captures;
|
||||
},
|
||||
captures);
|
||||
}
|
||||
|
||||
bool TextureRegistrarImpl::UnregisterTexture(int64_t texture_id) {
|
||||
UnregisterTexture(texture_id, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@@ -0,0 +1,11 @@
|
||||
// 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 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 "core_implementations.cc"
|
||||
@@ -0,0 +1,126 @@
|
||||
// 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 "include/flutter/flutter_engine.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
#include "binary_messenger_impl.h"
|
||||
#include "flutter_windows.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
FlutterEngine::FlutterEngine(const DartProject& project) {
|
||||
FlutterDesktopEngineProperties c_engine_properties = {};
|
||||
c_engine_properties.assets_path = project.assets_path().c_str();
|
||||
c_engine_properties.icu_data_path = project.icu_data_path().c_str();
|
||||
c_engine_properties.aot_library_path = project.aot_library_path().c_str();
|
||||
c_engine_properties.dart_entrypoint = project.dart_entrypoint().c_str();
|
||||
c_engine_properties.gpu_preference =
|
||||
static_cast<FlutterDesktopGpuPreference>(project.gpu_preference());
|
||||
c_engine_properties.ui_thread_policy =
|
||||
static_cast<FlutterDesktopUIThreadPolicy>(project.ui_thread_policy());
|
||||
|
||||
const std::vector<std::string>& entrypoint_args =
|
||||
project.dart_entrypoint_arguments();
|
||||
std::vector<const char*> entrypoint_argv;
|
||||
std::transform(
|
||||
entrypoint_args.begin(), entrypoint_args.end(),
|
||||
std::back_inserter(entrypoint_argv),
|
||||
[](const std::string& arg) -> const char* { return arg.c_str(); });
|
||||
|
||||
c_engine_properties.dart_entrypoint_argc =
|
||||
static_cast<int>(entrypoint_argv.size());
|
||||
c_engine_properties.dart_entrypoint_argv =
|
||||
entrypoint_argv.empty() ? nullptr : entrypoint_argv.data();
|
||||
|
||||
engine_ = FlutterDesktopEngineCreate(&c_engine_properties);
|
||||
|
||||
auto core_messenger = FlutterDesktopEngineGetMessenger(engine_);
|
||||
messenger_ = std::make_unique<BinaryMessengerImpl>(core_messenger);
|
||||
}
|
||||
|
||||
FlutterEngine::~FlutterEngine() {
|
||||
ShutDown();
|
||||
}
|
||||
|
||||
bool FlutterEngine::Run() {
|
||||
return Run(nullptr);
|
||||
}
|
||||
|
||||
bool FlutterEngine::Run(const char* entry_point) {
|
||||
if (!engine_) {
|
||||
std::cerr << "Cannot run an engine that failed creation." << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (run_succeeded_) {
|
||||
std::cerr << "Cannot run an engine more than once." << std::endl;
|
||||
return false;
|
||||
}
|
||||
bool run_succeeded = FlutterDesktopEngineRun(engine_, entry_point);
|
||||
if (!run_succeeded) {
|
||||
std::cerr << "Failed to start engine." << std::endl;
|
||||
}
|
||||
run_succeeded_ = true;
|
||||
return run_succeeded;
|
||||
}
|
||||
|
||||
void FlutterEngine::ShutDown() {
|
||||
if (engine_ && owns_engine_) {
|
||||
FlutterDesktopEngineDestroy(engine_);
|
||||
}
|
||||
engine_ = nullptr;
|
||||
}
|
||||
|
||||
std::chrono::nanoseconds FlutterEngine::ProcessMessages() {
|
||||
return std::chrono::nanoseconds(FlutterDesktopEngineProcessMessages(engine_));
|
||||
}
|
||||
|
||||
void FlutterEngine::ReloadSystemFonts() {
|
||||
FlutterDesktopEngineReloadSystemFonts(engine_);
|
||||
}
|
||||
|
||||
FlutterDesktopPluginRegistrarRef FlutterEngine::GetRegistrarForPlugin(
|
||||
const std::string& plugin_name) {
|
||||
if (!engine_) {
|
||||
std::cerr << "Cannot get plugin registrar on an engine that isn't running; "
|
||||
"call Run first."
|
||||
<< std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
return FlutterDesktopEngineGetPluginRegistrar(engine_, plugin_name.c_str());
|
||||
}
|
||||
|
||||
void FlutterEngine::SetNextFrameCallback(std::function<void()> callback) {
|
||||
next_frame_callback_ = std::move(callback);
|
||||
FlutterDesktopEngineSetNextFrameCallback(
|
||||
engine_,
|
||||
[](void* user_data) {
|
||||
FlutterEngine* self = static_cast<FlutterEngine*>(user_data);
|
||||
self->next_frame_callback_();
|
||||
self->next_frame_callback_ = nullptr;
|
||||
},
|
||||
this);
|
||||
}
|
||||
|
||||
std::optional<LRESULT> FlutterEngine::ProcessExternalWindowMessage(
|
||||
HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
LRESULT result;
|
||||
if (FlutterDesktopEngineProcessExternalWindowMessage(
|
||||
engine_, hwnd, message, wparam, lparam, &result)) {
|
||||
return result;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
FlutterDesktopEngineRef FlutterEngine::RelinquishEngine() {
|
||||
owns_engine_ = false;
|
||||
return engine_;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@@ -0,0 +1,53 @@
|
||||
// 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 "include/flutter/flutter_view_controller.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
FlutterViewController::FlutterViewController(int width,
|
||||
int height,
|
||||
const DartProject& project) {
|
||||
engine_ = std::make_shared<FlutterEngine>(project);
|
||||
controller_ = FlutterDesktopViewControllerCreate(width, height,
|
||||
engine_->RelinquishEngine());
|
||||
if (!controller_) {
|
||||
std::cerr << "Failed to create view controller." << std::endl;
|
||||
return;
|
||||
}
|
||||
view_ = std::make_unique<FlutterView>(
|
||||
FlutterDesktopViewControllerGetView(controller_));
|
||||
}
|
||||
|
||||
FlutterViewController::~FlutterViewController() {
|
||||
if (controller_) {
|
||||
FlutterDesktopViewControllerDestroy(controller_);
|
||||
}
|
||||
}
|
||||
|
||||
FlutterViewId FlutterViewController::view_id() const {
|
||||
auto view_id = FlutterDesktopViewControllerGetViewId(controller_);
|
||||
|
||||
return static_cast<FlutterViewId>(view_id);
|
||||
}
|
||||
|
||||
void FlutterViewController::ForceRedraw() {
|
||||
FlutterDesktopViewControllerForceRedraw(controller_);
|
||||
}
|
||||
|
||||
std::optional<LRESULT> FlutterViewController::HandleTopLevelWindowProc(
|
||||
HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
LRESULT result;
|
||||
bool handled = FlutterDesktopViewControllerHandleTopLevelWindowProc(
|
||||
controller_, hwnd, message, wparam, lparam, &result);
|
||||
return handled ? result : std::optional<LRESULT>(std::nullopt);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@@ -0,0 +1,149 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_BASIC_MESSAGE_CHANNEL_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_BASIC_MESSAGE_CHANNEL_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "binary_messenger.h"
|
||||
#include "message_codec.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
namespace internal {
|
||||
// Internal helper functions used by BasicMessageChannel and MethodChannel.
|
||||
|
||||
// Adjusts the number of messages that will get buffered when sending messages
|
||||
// to channels that aren't fully set up yet. For example, the engine isn't
|
||||
// running yet or the channel's message handler isn't set up on the Dart side
|
||||
// yet.
|
||||
void ResizeChannel(BinaryMessenger* messenger, std::string name, int new_size);
|
||||
|
||||
// Defines whether the channel should show warning messages when discarding
|
||||
// messages due to overflow.
|
||||
//
|
||||
// When |warns| is false, the channel is expected to overflow and warning
|
||||
// messages will not be shown.
|
||||
void SetChannelWarnsOnOverflow(BinaryMessenger* messenger,
|
||||
std::string name,
|
||||
bool warns);
|
||||
|
||||
} // namespace internal
|
||||
|
||||
class EncodableValue;
|
||||
|
||||
// A message reply callback.
|
||||
//
|
||||
// Used for submitting a reply back to a Flutter message sender.
|
||||
template <typename T>
|
||||
using MessageReply = std::function<void(const T& reply)>;
|
||||
|
||||
// A handler for receiving a message from the Flutter engine.
|
||||
//
|
||||
// Implementations must asynchronously call reply exactly once with the reply
|
||||
// to the message.
|
||||
template <typename T>
|
||||
using MessageHandler =
|
||||
std::function<void(const T& message, const MessageReply<T>& reply)>;
|
||||
|
||||
// A channel for communicating with the Flutter engine by sending asynchronous
|
||||
// messages.
|
||||
template <typename T = EncodableValue>
|
||||
class BasicMessageChannel {
|
||||
public:
|
||||
// Creates an instance that sends and receives method calls on the channel
|
||||
// named |name|, encoded with |codec| and dispatched via |messenger|.
|
||||
BasicMessageChannel(BinaryMessenger* messenger,
|
||||
const std::string& name,
|
||||
const MessageCodec<T>* codec)
|
||||
: messenger_(messenger), name_(name), codec_(codec) {}
|
||||
|
||||
~BasicMessageChannel() = default;
|
||||
|
||||
// Prevent copying.
|
||||
BasicMessageChannel(BasicMessageChannel const&) = delete;
|
||||
BasicMessageChannel& operator=(BasicMessageChannel const&) = delete;
|
||||
|
||||
// Sends a message to the Flutter engine on this channel.
|
||||
void Send(const T& message) {
|
||||
std::unique_ptr<std::vector<uint8_t>> raw_message =
|
||||
codec_->EncodeMessage(message);
|
||||
messenger_->Send(name_, raw_message->data(), raw_message->size());
|
||||
}
|
||||
|
||||
// Sends a message to the Flutter engine on this channel expecting a reply.
|
||||
void Send(const T& message, BinaryReply reply) {
|
||||
std::unique_ptr<std::vector<uint8_t>> raw_message =
|
||||
codec_->EncodeMessage(message);
|
||||
messenger_->Send(name_, raw_message->data(), raw_message->size(),
|
||||
std::move(reply));
|
||||
}
|
||||
|
||||
// Registers a handler that should be called any time a message is
|
||||
// received on this channel. A null handler will remove any previous handler.
|
||||
//
|
||||
// Note that the BasicMessageChannel does not own the handler, and will not
|
||||
// unregister it on destruction, so the caller is responsible for
|
||||
// unregistering explicitly if it should no longer be called.
|
||||
void SetMessageHandler(const MessageHandler<T>& handler) const {
|
||||
if (!handler) {
|
||||
messenger_->SetMessageHandler(name_, nullptr);
|
||||
return;
|
||||
}
|
||||
const auto* codec = codec_;
|
||||
std::string channel_name = name_;
|
||||
BinaryMessageHandler binary_handler = [handler, codec, channel_name](
|
||||
const uint8_t* binary_message,
|
||||
const size_t binary_message_size,
|
||||
const BinaryReply& binary_reply) {
|
||||
// Use this channel's codec to decode the message and build a reply
|
||||
// handler.
|
||||
std::unique_ptr<T> message =
|
||||
codec->DecodeMessage(binary_message, binary_message_size);
|
||||
if (!message) {
|
||||
std::cerr << "Unable to decode message on channel " << channel_name
|
||||
<< std::endl;
|
||||
binary_reply(nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
MessageReply<T> unencoded_reply = [binary_reply,
|
||||
codec](const T& unencoded_response) {
|
||||
auto binary_response = codec->EncodeMessage(unencoded_response);
|
||||
binary_reply(binary_response->data(), binary_response->size());
|
||||
};
|
||||
handler(*message, std::move(unencoded_reply));
|
||||
};
|
||||
messenger_->SetMessageHandler(name_, std::move(binary_handler));
|
||||
}
|
||||
|
||||
// Adjusts the number of messages that will get buffered when sending messages
|
||||
// to channels that aren't fully set up yet. For example, the engine isn't
|
||||
// running yet or the channel's message handler isn't set up on the Dart side
|
||||
// yet.
|
||||
void Resize(int new_size) {
|
||||
internal::ResizeChannel(messenger_, name_, new_size);
|
||||
}
|
||||
|
||||
// Defines whether the channel should show warning messages when discarding
|
||||
// messages due to overflow.
|
||||
//
|
||||
// When |warns| is false, the channel is expected to overflow and warning
|
||||
// messages will not be shown.
|
||||
void SetWarnsOnOverflow(bool warns) {
|
||||
internal::SetChannelWarnsOnOverflow(messenger_, name_, warns);
|
||||
}
|
||||
|
||||
private:
|
||||
BinaryMessenger* messenger_;
|
||||
std::string name_;
|
||||
const MessageCodec<T>* codec_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_BASIC_MESSAGE_CHANNEL_H_
|
||||
@@ -0,0 +1,52 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_BINARY_MESSENGER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_BINARY_MESSENGER_H_
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// A binary message reply callback.
|
||||
//
|
||||
// Used for submitting a binary reply back to a Flutter message sender.
|
||||
typedef std::function<void(const uint8_t* reply, size_t reply_size)>
|
||||
BinaryReply;
|
||||
|
||||
// A message handler callback.
|
||||
//
|
||||
// Used for receiving messages from Flutter and providing an asynchronous reply.
|
||||
typedef std::function<
|
||||
void(const uint8_t* message, size_t message_size, BinaryReply reply)>
|
||||
BinaryMessageHandler;
|
||||
|
||||
// A protocol for a class that handles communication of binary data on named
|
||||
// channels to and from the Flutter engine.
|
||||
class BinaryMessenger {
|
||||
public:
|
||||
virtual ~BinaryMessenger() = default;
|
||||
|
||||
// Sends a binary message to the Flutter engine on the specified channel.
|
||||
//
|
||||
// If |reply| is provided, it will be called back with the response from the
|
||||
// engine.
|
||||
virtual void Send(const std::string& channel,
|
||||
const uint8_t* message,
|
||||
size_t message_size,
|
||||
BinaryReply reply = nullptr) const = 0;
|
||||
|
||||
// Registers a message handler for incoming binary messages from the Flutter
|
||||
// side on the specified channel.
|
||||
//
|
||||
// Replaces any existing handler. Provide a null handler to unregister the
|
||||
// existing handler.
|
||||
virtual void SetMessageHandler(const std::string& channel,
|
||||
BinaryMessageHandler handler) = 0;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_BINARY_MESSENGER_H_
|
||||
@@ -0,0 +1,85 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_BYTE_STREAMS_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_BYTE_STREAMS_H_
|
||||
|
||||
// Interfaces for interacting with a stream of bytes, for use in codecs.
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// An interface for a class that reads from a byte stream.
|
||||
class ByteStreamReader {
|
||||
public:
|
||||
explicit ByteStreamReader() = default;
|
||||
virtual ~ByteStreamReader() = default;
|
||||
|
||||
// Reads and returns the next byte from the stream.
|
||||
virtual uint8_t ReadByte() = 0;
|
||||
|
||||
// Reads the next |length| bytes from the stream into |buffer|. The caller
|
||||
// is responsible for ensuring that |buffer| is large enough.
|
||||
virtual void ReadBytes(uint8_t* buffer, size_t length) = 0;
|
||||
|
||||
// Advances the read cursor to the next multiple of |alignment| relative to
|
||||
// the start of the stream, unless it is already aligned.
|
||||
virtual void ReadAlignment(uint8_t alignment) = 0;
|
||||
|
||||
// Reads and returns the next 32-bit integer from the stream.
|
||||
int32_t ReadInt32() {
|
||||
int32_t value = 0;
|
||||
ReadBytes(reinterpret_cast<uint8_t*>(&value), 4);
|
||||
return value;
|
||||
}
|
||||
|
||||
// Reads and returns the next 64-bit integer from the stream.
|
||||
int64_t ReadInt64() {
|
||||
int64_t value = 0;
|
||||
ReadBytes(reinterpret_cast<uint8_t*>(&value), 8);
|
||||
return value;
|
||||
}
|
||||
|
||||
// Reads and returns the next 64-bit floating point number from the stream.
|
||||
double ReadDouble() {
|
||||
double value = 0;
|
||||
ReadBytes(reinterpret_cast<uint8_t*>(&value), 8);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
// An interface for a class that writes to a byte stream.
|
||||
class ByteStreamWriter {
|
||||
public:
|
||||
explicit ByteStreamWriter() = default;
|
||||
virtual ~ByteStreamWriter() = default;
|
||||
|
||||
// Writes |byte| to the stream.
|
||||
virtual void WriteByte(uint8_t byte) = 0;
|
||||
|
||||
// Writes the next |length| bytes from |bytes| to the stream
|
||||
virtual void WriteBytes(const uint8_t* bytes, size_t length) = 0;
|
||||
|
||||
// Writes 0s until the next multiple of |alignment| relative to the start
|
||||
// of the stream, unless the write positition is already aligned.
|
||||
virtual void WriteAlignment(uint8_t alignment) = 0;
|
||||
|
||||
// Writes the given 32-bit int to the stream.
|
||||
void WriteInt32(int32_t value) {
|
||||
WriteBytes(reinterpret_cast<const uint8_t*>(&value), 4);
|
||||
}
|
||||
|
||||
// Writes the given 64-bit int to the stream.
|
||||
void WriteInt64(int64_t value) {
|
||||
WriteBytes(reinterpret_cast<const uint8_t*>(&value), 8);
|
||||
}
|
||||
|
||||
// Writes the given 36-bit double to the stream.
|
||||
void WriteDouble(double value) {
|
||||
WriteBytes(reinterpret_cast<const uint8_t*>(&value), 8);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_BYTE_STREAMS_H_
|
||||
@@ -0,0 +1,145 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_DART_PROJECT_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_DART_PROJECT_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// Configures how the Flutter engine selects a GPU.
|
||||
enum class GpuPreference {
|
||||
// No preference.
|
||||
NoPreference,
|
||||
// Prefer energy efficiency over performance, such as an integrated GPU.
|
||||
// This falls back to a high performance GPU if no low power GPU is
|
||||
// available.
|
||||
LowPowerPreference,
|
||||
};
|
||||
|
||||
// Configures the thread policy for running the UI isolate.
|
||||
enum class UIThreadPolicy {
|
||||
// Default value. Currently will run the UI isolate on separate thread,
|
||||
// later will be changed to running the UI isolate on platform thread.
|
||||
Default,
|
||||
// Run the UI isolate on platform thread.
|
||||
RunOnPlatformThread,
|
||||
// Run the UI isolate on a separate thread.
|
||||
RunOnSeparateThread,
|
||||
};
|
||||
|
||||
// A set of Flutter and Dart assets used to initialize a Flutter engine.
|
||||
class DartProject {
|
||||
public:
|
||||
// Creates a DartProject from a series of absolute paths.
|
||||
// The three paths are:
|
||||
// - assets_path: Path to the assets directory as built by the Flutter tool.
|
||||
// - icu_data_path: Path to the icudtl.dat file.
|
||||
// - aot_library_path: Path to the AOT snapshot file.
|
||||
//
|
||||
// The paths may either be absolute or relative to the directory containing
|
||||
// the running executable.
|
||||
explicit DartProject(const std::wstring& assets_path,
|
||||
const std::wstring& icu_data_path,
|
||||
const std::wstring& aot_library_path) {
|
||||
assets_path_ = assets_path;
|
||||
icu_data_path_ = icu_data_path;
|
||||
aot_library_path_ = aot_library_path;
|
||||
}
|
||||
|
||||
// Creates a DartProject from a directory path. The directory should contain
|
||||
// the following top-level items:
|
||||
// - icudtl.dat (provided as a resource by the Flutter tool)
|
||||
// - flutter_assets (as built by the Flutter tool)
|
||||
// - app.so, for an AOT build (as built by the Flutter tool)
|
||||
//
|
||||
// The path can either be absolute, or relative to the directory containing
|
||||
// the running executable.
|
||||
explicit DartProject(const std::wstring& path) {
|
||||
assets_path_ = path + L"\\flutter_assets";
|
||||
icu_data_path_ = path + L"\\icudtl.dat";
|
||||
aot_library_path_ = path + L"\\app.so";
|
||||
}
|
||||
|
||||
~DartProject() = default;
|
||||
|
||||
// Sets the Dart entrypoint to the specified value.
|
||||
//
|
||||
// If not set, the default entrypoint (main) is used. Custom Dart entrypoints
|
||||
// must be decorated with `@pragma('vm:entry-point')`.
|
||||
void set_dart_entrypoint(const std::string& entrypoint) {
|
||||
if (entrypoint.empty()) {
|
||||
return;
|
||||
}
|
||||
dart_entrypoint_ = entrypoint;
|
||||
}
|
||||
|
||||
// Returns the Dart entrypoint.
|
||||
const std::string& dart_entrypoint() const { return dart_entrypoint_; }
|
||||
|
||||
// Sets the command line arguments that should be passed to the Dart
|
||||
// entrypoint.
|
||||
void set_dart_entrypoint_arguments(std::vector<std::string> arguments) {
|
||||
dart_entrypoint_arguments_ = std::move(arguments);
|
||||
}
|
||||
|
||||
// Returns any command line arguments that should be passed to the Dart
|
||||
// entrypoint.
|
||||
const std::vector<std::string>& dart_entrypoint_arguments() const {
|
||||
return dart_entrypoint_arguments_;
|
||||
}
|
||||
|
||||
// Sets the GPU usage preference for flutter engine.
|
||||
void set_gpu_preference(GpuPreference gpu_preference) {
|
||||
gpu_preference_ = gpu_preference;
|
||||
}
|
||||
|
||||
// Returns the project's GPU preference.
|
||||
// Defaults to NoPreference.
|
||||
GpuPreference gpu_preference() const { return gpu_preference_; }
|
||||
|
||||
// Sets the thread policy for UI isolate.
|
||||
void set_ui_thread_policy(UIThreadPolicy policy) {
|
||||
ui_thread_policy_ = policy;
|
||||
}
|
||||
|
||||
// Returns the policy for UI isolate.
|
||||
// Defaults to UIThreadPolicy::Default.
|
||||
UIThreadPolicy ui_thread_policy() const { return ui_thread_policy_; }
|
||||
|
||||
private:
|
||||
// Accessors for internals are private, so that they can be changed if more
|
||||
// flexible options for project structures are needed later without it
|
||||
// being a breaking change. Provide access to internal classes that need
|
||||
// them.
|
||||
friend class FlutterEngine;
|
||||
friend class FlutterViewController;
|
||||
friend class DartProjectTest;
|
||||
|
||||
const std::wstring& assets_path() const { return assets_path_; }
|
||||
const std::wstring& icu_data_path() const { return icu_data_path_; }
|
||||
const std::wstring& aot_library_path() const { return aot_library_path_; }
|
||||
|
||||
// The path to the assets directory.
|
||||
std::wstring assets_path_;
|
||||
// The path to the ICU data.
|
||||
std::wstring icu_data_path_;
|
||||
// The path to the AOT library. This will always return a path, but non-AOT
|
||||
// builds will not be expected to actually have a library at that path.
|
||||
std::wstring aot_library_path_;
|
||||
// The Dart entrypoint to launch.
|
||||
std::string dart_entrypoint_;
|
||||
// The list of arguments to pass through to the Dart entrypoint.
|
||||
std::vector<std::string> dart_entrypoint_arguments_;
|
||||
// The preference for GPU to be used by flutter engine.
|
||||
GpuPreference gpu_preference_ = GpuPreference::NoPreference;
|
||||
// Thread policy for UI isolate.
|
||||
UIThreadPolicy ui_thread_policy_ = UIThreadPolicy::Default;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_DART_PROJECT_H_
|
||||
@@ -0,0 +1,274 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_
|
||||
|
||||
#include <any>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
// Unless overridden, attempt to detect the RTTI state from the compiler.
|
||||
#ifndef FLUTTER_ENABLE_RTTI
|
||||
#if defined(_MSC_VER)
|
||||
#ifdef _CPPRTTI
|
||||
#define FLUTTER_ENABLE_RTTI 1
|
||||
#endif
|
||||
#elif defined(__clang__)
|
||||
#if __has_feature(cxx_rtti)
|
||||
#define FLUTTER_ENABLE_RTTI 1
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#ifdef __GXX_RTTI
|
||||
#define FLUTTER_ENABLE_RTTI 1
|
||||
#endif
|
||||
#endif
|
||||
#endif // #ifndef FLUTTER_ENABLE_RTTI
|
||||
|
||||
namespace flutter {
|
||||
|
||||
static_assert(sizeof(double) == 8, "EncodableValue requires a 64-bit double");
|
||||
|
||||
// A container for arbitrary types in EncodableValue.
|
||||
//
|
||||
// This is used in conjunction with StandardCodecExtension to allow using other
|
||||
// types with a StandardMethodCodec/StandardMessageCodec. It is implicitly
|
||||
// convertible to EncodableValue, so constructing an EncodableValue from a
|
||||
// custom type can generally be written as:
|
||||
// CustomEncodableValue(MyType(...))
|
||||
// rather than:
|
||||
// EncodableValue(CustomEncodableValue(MyType(...)))
|
||||
//
|
||||
// For extracting received custom types, it is implicitly convertible to
|
||||
// std::any. For example:
|
||||
// const MyType& my_type_value =
|
||||
// std::any_cast<MyType>(std::get<CustomEncodableValue>(value));
|
||||
//
|
||||
// If RTTI is enabled, different extension types can be checked with type():
|
||||
// if (custom_value->type() == typeid(SomeData)) { ... }
|
||||
// Clients that wish to disable RTTI would need to decide on another approach
|
||||
// for distinguishing types (e.g., in StandardCodecExtension::WriteValueOfType)
|
||||
// if multiple custom types are needed. For instance, wrapping all of the
|
||||
// extension types in an EncodableValue-style variant, and only ever storing
|
||||
// that variant in CustomEncodableValue.
|
||||
class CustomEncodableValue {
|
||||
public:
|
||||
explicit CustomEncodableValue(const std::any& value) : value_(value) {}
|
||||
~CustomEncodableValue() = default;
|
||||
|
||||
// Allow implicit conversion to std::any to allow direct use of any_cast.
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator std::any&() { return value_; }
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator const std::any&() const { return value_; }
|
||||
|
||||
#if defined(FLUTTER_ENABLE_RTTI) && FLUTTER_ENABLE_RTTI
|
||||
// Passthrough to std::any's type().
|
||||
const std::type_info& type() const noexcept { return value_.type(); }
|
||||
#endif
|
||||
|
||||
// This operator exists only to provide a stable ordering for use as a
|
||||
// std::map key, to satisfy the compiler requirements for EncodableValue.
|
||||
// It does not attempt to provide useful ordering semantics, and using a
|
||||
// custom value as a map key is not recommended.
|
||||
bool operator<(const CustomEncodableValue& other) const {
|
||||
return this < &other;
|
||||
}
|
||||
bool operator==(const CustomEncodableValue& other) const {
|
||||
return this == &other;
|
||||
}
|
||||
|
||||
private:
|
||||
std::any value_;
|
||||
};
|
||||
|
||||
class EncodableValue;
|
||||
|
||||
// Convenience type aliases.
|
||||
using EncodableList = std::vector<EncodableValue>;
|
||||
using EncodableMap = std::map<EncodableValue, EncodableValue>;
|
||||
|
||||
namespace internal {
|
||||
// The base class for EncodableValue. Do not use this directly; it exists only
|
||||
// for EncodableValue to inherit from.
|
||||
//
|
||||
// Do not change the order or indexes of the items here; see the comment on
|
||||
// EncodableValue
|
||||
using EncodableValueVariant = std::variant<std::monostate,
|
||||
bool,
|
||||
int32_t,
|
||||
int64_t,
|
||||
double,
|
||||
std::string,
|
||||
std::vector<uint8_t>,
|
||||
std::vector<int32_t>,
|
||||
std::vector<int64_t>,
|
||||
std::vector<double>,
|
||||
EncodableList,
|
||||
EncodableMap,
|
||||
CustomEncodableValue,
|
||||
std::vector<float>>;
|
||||
} // namespace internal
|
||||
|
||||
// An object that can contain any value or collection type supported by
|
||||
// Flutter's standard method codec.
|
||||
//
|
||||
// For details, see:
|
||||
// https://api.flutter.dev/flutter/services/StandardMessageCodec-class.html
|
||||
//
|
||||
// As an example, the following Dart structure:
|
||||
// {
|
||||
// 'flag': true,
|
||||
// 'name': 'Thing',
|
||||
// 'values': [1, 2.0, 4],
|
||||
// }
|
||||
// would correspond to:
|
||||
// EncodableValue(EncodableMap{
|
||||
// {EncodableValue("flag"), EncodableValue(true)},
|
||||
// {EncodableValue("name"), EncodableValue("Thing")},
|
||||
// {EncodableValue("values"), EncodableValue(EncodableList{
|
||||
// EncodableValue(1),
|
||||
// EncodableValue(2.0),
|
||||
// EncodableValue(4),
|
||||
// })},
|
||||
// })
|
||||
//
|
||||
// The primary API surface for this object is std::variant. For instance,
|
||||
// getting a string value from an EncodableValue, with type checking:
|
||||
// if (std::holds_alternative<std::string>(value)) {
|
||||
// std::string some_string = std::get<std::string>(value);
|
||||
// }
|
||||
//
|
||||
// The order/indexes of the variant types is part of the API surface, and is
|
||||
// guaranteed not to change.
|
||||
//
|
||||
// The variant types are mapped with Dart types in following ways:
|
||||
// std::monostate -> null
|
||||
// bool -> bool
|
||||
// int32_t -> int
|
||||
// int64_t -> int
|
||||
// double -> double
|
||||
// std::string -> String
|
||||
// std::vector<uint8_t> -> Uint8List
|
||||
// std::vector<int32_t> -> Int32List
|
||||
// std::vector<int64_t> -> Int64List
|
||||
// std::vector<float> -> Float32List
|
||||
// std::vector<double> -> Float64List
|
||||
// EncodableList -> List
|
||||
// EncodableMap -> Map
|
||||
class EncodableValue : public internal::EncodableValueVariant {
|
||||
public:
|
||||
// Rely on std::variant for most of the constructors/operators.
|
||||
using super = internal::EncodableValueVariant;
|
||||
using super::super;
|
||||
using super::operator=;
|
||||
|
||||
explicit EncodableValue() = default;
|
||||
|
||||
// Avoid the C++17 pitfall of conversion from char* to bool. Should not be
|
||||
// needed for C++20.
|
||||
explicit EncodableValue(const char* string) : super(std::string(string)) {}
|
||||
EncodableValue& operator=(const char* other) {
|
||||
*this = std::string(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Allow implicit conversion from CustomEncodableValue; the only reason to
|
||||
// make a CustomEncodableValue (which can only be constructed explicitly) is
|
||||
// to use it with EncodableValue, so the risk of unintended conversions is
|
||||
// minimal, and it avoids the need for the verbose:
|
||||
// EncodableValue(CustomEncodableValue(...)).
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
EncodableValue(const CustomEncodableValue& v) : super(v) {}
|
||||
|
||||
// Override the conversion constructors from std::variant to make them
|
||||
// explicit, to avoid implicit conversion.
|
||||
//
|
||||
// While implicit conversion can be convenient in some cases, it can have very
|
||||
// surprising effects. E.g., calling a function that takes an EncodableValue
|
||||
// but accidentally passing an EncodableValue* would, instead of failing to
|
||||
// compile, go through a pointer->bool->EncodableValue(bool) chain and
|
||||
// silently call the function with a temp-constructed EncodableValue(true).
|
||||
template <class T>
|
||||
constexpr explicit EncodableValue(T&& t) noexcept : super(t) {}
|
||||
|
||||
// Returns true if the value is null. Convenience wrapper since unlike the
|
||||
// other types, std::monostate uses aren't self-documenting.
|
||||
bool IsNull() const { return std::holds_alternative<std::monostate>(*this); }
|
||||
|
||||
// Convenience method to simplify handling objects received from Flutter
|
||||
// where the values may be larger than 32-bit, since they have the same type
|
||||
// on the Dart side, but will be either 32-bit or 64-bit here depending on
|
||||
// the value.
|
||||
//
|
||||
// Calling this method if the value doesn't contain either an int32_t or an
|
||||
// int64_t will throw an exception.
|
||||
int64_t LongValue() const {
|
||||
if (std::holds_alternative<int32_t>(*this)) {
|
||||
return std::get<int32_t>(*this);
|
||||
}
|
||||
return std::get<int64_t>(*this);
|
||||
}
|
||||
|
||||
// The C++ Standard Library implementations can get into issues with recursive
|
||||
// constraint satisfaction when (among other things) objects of this type (which
|
||||
// is an `std::variant` subclass) are put into containers like `std::vector`.
|
||||
//
|
||||
// A definition of `operator<` is provided to break that recursion. However, in
|
||||
// C++20 with the latest compilers (Clang compilers newer than 20 and the latest
|
||||
// GCC variants, see https://gcc.godbolt.org/z/KM6n6qane) requiring that that
|
||||
// the `std::three_way_comparable` constraint be satisfied requires the
|
||||
// provision of `operator<=>` to do the same thing.
|
||||
//
|
||||
// The code below makes this translation unit be safe to include from both C++17
|
||||
// and C++20 translation units while also using the newest compilers.
|
||||
//
|
||||
// The correctness of the compiler's gripes with this code and the subsequent
|
||||
// need for these workarounds is not fully understood or explored. If you run
|
||||
// into issues with this code again, the following breadcrumbs may prove
|
||||
// useful. If you cannot access some or all of these links, the compiler
|
||||
// explorer link above should serve a reduced test case to base an investigation
|
||||
// off of.
|
||||
//
|
||||
// * b/423885648#comment8
|
||||
// * b/423885648#comment19
|
||||
// * cl/542631351
|
||||
// * cl/542541552
|
||||
// * https://github.com/flutter/engine/pull/43091
|
||||
//
|
||||
#if __cplusplus >= 202002L
|
||||
friend std::partial_ordering operator<=>(const EncodableValue& lhs,
|
||||
const EncodableValue& rhs) {
|
||||
auto& lv = static_cast<const super&>(lhs);
|
||||
auto& rv = static_cast<const super&>(rhs);
|
||||
|
||||
if (lv < rv) {
|
||||
return std::partial_ordering::less;
|
||||
}
|
||||
|
||||
if (rv < lv) {
|
||||
return std::partial_ordering::greater;
|
||||
}
|
||||
|
||||
if (lv == rv) {
|
||||
return std::partial_ordering::equivalent;
|
||||
}
|
||||
|
||||
return std::partial_ordering::unordered;
|
||||
}
|
||||
#else // __cplusplus >= 202002L
|
||||
friend bool operator<(const EncodableValue& lhs, const EncodableValue& rhs) {
|
||||
return static_cast<const super&>(lhs) < static_cast<const super&>(rhs);
|
||||
}
|
||||
#endif // __cplusplus >= 202002L
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_
|
||||
@@ -0,0 +1,86 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENGINE_METHOD_RESULT_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENGINE_METHOD_RESULT_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "binary_messenger.h"
|
||||
#include "method_codec.h"
|
||||
#include "method_result.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
namespace internal {
|
||||
// Manages the one-time sending of response data. This is an internal helper
|
||||
// class for EngineMethodResult, separated out since the implementation doesn't
|
||||
// vary based on the template type.
|
||||
class ReplyManager {
|
||||
public:
|
||||
explicit ReplyManager(BinaryReply reply_handler_);
|
||||
~ReplyManager();
|
||||
|
||||
// Prevent copying.
|
||||
ReplyManager(ReplyManager const&) = delete;
|
||||
ReplyManager& operator=(ReplyManager const&) = delete;
|
||||
|
||||
// Sends the given response data (which must either be nullptr, which
|
||||
// indicates an unhandled method, or a response serialized with |codec_|) to
|
||||
// the engine.
|
||||
void SendResponseData(const std::vector<uint8_t>* data);
|
||||
|
||||
private:
|
||||
BinaryReply reply_handler_;
|
||||
};
|
||||
} // namespace internal
|
||||
|
||||
// Implemention of MethodResult that sends a response to the Flutter engine
|
||||
// exactly once, encoded using a given codec.
|
||||
template <typename T>
|
||||
class EngineMethodResult : public MethodResult<T> {
|
||||
public:
|
||||
// Creates a result object that will send results to |reply_handler|, encoded
|
||||
// using |codec|. The |codec| pointer must remain valid for as long as this
|
||||
// object exists.
|
||||
EngineMethodResult(BinaryReply reply_handler, const MethodCodec<T>* codec)
|
||||
: reply_manager_(
|
||||
std::make_unique<internal::ReplyManager>(std::move(reply_handler))),
|
||||
codec_(codec) {}
|
||||
|
||||
~EngineMethodResult() = default;
|
||||
|
||||
protected:
|
||||
// |flutter::MethodResult|
|
||||
void SuccessInternal(const T* result) override {
|
||||
std::unique_ptr<std::vector<uint8_t>> data =
|
||||
codec_->EncodeSuccessEnvelope(result);
|
||||
reply_manager_->SendResponseData(data.get());
|
||||
}
|
||||
|
||||
// |flutter::MethodResult|
|
||||
void ErrorInternal(const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const T* error_details) override {
|
||||
std::unique_ptr<std::vector<uint8_t>> data =
|
||||
codec_->EncodeErrorEnvelope(error_code, error_message, error_details);
|
||||
reply_manager_->SendResponseData(data.get());
|
||||
}
|
||||
|
||||
// |flutter::MethodResult|
|
||||
void NotImplementedInternal() override {
|
||||
reply_manager_->SendResponseData(nullptr);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<internal::ReplyManager> reply_manager_;
|
||||
|
||||
const MethodCodec<T>* codec_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENGINE_METHOD_RESULT_H_
|
||||
@@ -0,0 +1,181 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_CHANNEL_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_CHANNEL_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "binary_messenger.h"
|
||||
#include "engine_method_result.h"
|
||||
#include "event_sink.h"
|
||||
#include "event_stream_handler.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class EncodableValue;
|
||||
|
||||
// A named channel for communicating with the Flutter application using
|
||||
// asynchronous event streams. Incoming requests for event stream setup are
|
||||
// decoded from binary on receipt, and C++ responses and events are encoded into
|
||||
// binary before being transmitted back to Flutter. The MethodCodec used must be
|
||||
// compatible with the one used by the Flutter application. This can be achieved
|
||||
// by creating an EventChannel
|
||||
// ("https://api.flutter.dev/flutter/services/EventChannel-class.html")
|
||||
// counterpart of this channel on the Dart side.
|
||||
// The C++ type of stream configuration arguments, events, and error details are
|
||||
// templated, but only values supported by the specified MethodCodec can be
|
||||
// used.
|
||||
template <typename T = EncodableValue>
|
||||
class EventChannel {
|
||||
public:
|
||||
// Creates an instance that sends and receives event handler on the channel
|
||||
// named |name|, encoded with |codec| and dispatched via |messenger|.
|
||||
EventChannel(BinaryMessenger* messenger,
|
||||
const std::string& name,
|
||||
const MethodCodec<T>* codec)
|
||||
: messenger_(messenger), name_(name), codec_(codec) {}
|
||||
~EventChannel() = default;
|
||||
|
||||
// Prevent copying.
|
||||
EventChannel(EventChannel const&) = delete;
|
||||
EventChannel& operator=(EventChannel const&) = delete;
|
||||
|
||||
// Registers a stream handler on this channel.
|
||||
// If no handler has been registered, any incoming stream setup requests will
|
||||
// be handled silently by providing an empty stream.
|
||||
//
|
||||
// Note that the EventChannel does not own the handler and will not
|
||||
// unregister it on destruction. The caller is responsible for unregistering
|
||||
// the handler if it should no longer be called.
|
||||
void SetStreamHandler(std::unique_ptr<StreamHandler<T>> handler) {
|
||||
if (!handler) {
|
||||
messenger_->SetMessageHandler(name_, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// std::function requires a copyable lambda, so convert to a shared pointer.
|
||||
// This is safe since only one copy of the shared_pointer will ever be
|
||||
// accessed.
|
||||
std::shared_ptr<StreamHandler<T>> shared_handler(handler.release());
|
||||
const MethodCodec<T>* codec = codec_;
|
||||
const std::string channel_name = name_;
|
||||
const BinaryMessenger* messenger = messenger_;
|
||||
BinaryMessageHandler binary_handler =
|
||||
[shared_handler, codec, channel_name, messenger,
|
||||
// Mutable state to track the handler's listening status.
|
||||
is_listening = false](const uint8_t* message,
|
||||
const size_t message_size,
|
||||
const BinaryReply& reply) mutable {
|
||||
constexpr char kOnListenMethod[] = "listen";
|
||||
constexpr char kOnCancelMethod[] = "cancel";
|
||||
|
||||
std::unique_ptr<MethodCall<T>> method_call =
|
||||
codec->DecodeMethodCall(message, message_size);
|
||||
if (!method_call) {
|
||||
std::cerr
|
||||
<< "Unable to construct method call from message on channel: "
|
||||
<< channel_name << std::endl;
|
||||
reply(nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string& method = method_call->method_name();
|
||||
if (method.compare(kOnListenMethod) == 0) {
|
||||
if (is_listening) {
|
||||
std::unique_ptr<StreamHandlerError<T>> error =
|
||||
shared_handler->OnCancel(nullptr);
|
||||
if (error) {
|
||||
std::cerr << "Failed to cancel existing stream: "
|
||||
<< (error->error_code) << ", "
|
||||
<< (error->error_message) << ", "
|
||||
<< (error->error_details);
|
||||
}
|
||||
}
|
||||
is_listening = true;
|
||||
|
||||
std::unique_ptr<std::vector<uint8_t>> result;
|
||||
auto sink = std::make_unique<EventSinkImplementation>(
|
||||
messenger, channel_name, codec);
|
||||
std::unique_ptr<StreamHandlerError<T>> error =
|
||||
shared_handler->OnListen(method_call->arguments(),
|
||||
std::move(sink));
|
||||
if (error) {
|
||||
result = codec->EncodeErrorEnvelope(error->error_code,
|
||||
error->error_message,
|
||||
error->error_details.get());
|
||||
} else {
|
||||
result = codec->EncodeSuccessEnvelope();
|
||||
}
|
||||
reply(result->data(), result->size());
|
||||
} else if (method.compare(kOnCancelMethod) == 0) {
|
||||
std::unique_ptr<std::vector<uint8_t>> result;
|
||||
if (is_listening) {
|
||||
std::unique_ptr<StreamHandlerError<T>> error =
|
||||
shared_handler->OnCancel(method_call->arguments());
|
||||
if (error) {
|
||||
result = codec->EncodeErrorEnvelope(error->error_code,
|
||||
error->error_message,
|
||||
error->error_details.get());
|
||||
} else {
|
||||
result = codec->EncodeSuccessEnvelope();
|
||||
}
|
||||
is_listening = false;
|
||||
} else {
|
||||
result = codec->EncodeErrorEnvelope(
|
||||
"error", "No active stream to cancel", nullptr);
|
||||
}
|
||||
reply(result->data(), result->size());
|
||||
} else {
|
||||
reply(nullptr, 0);
|
||||
}
|
||||
};
|
||||
messenger_->SetMessageHandler(name_, std::move(binary_handler));
|
||||
}
|
||||
|
||||
private:
|
||||
class EventSinkImplementation : public EventSink<T> {
|
||||
public:
|
||||
EventSinkImplementation(const BinaryMessenger* messenger,
|
||||
const std::string& name,
|
||||
const MethodCodec<T>* codec)
|
||||
: messenger_(messenger), name_(name), codec_(codec) {}
|
||||
~EventSinkImplementation() = default;
|
||||
|
||||
// Prevent copying.
|
||||
EventSinkImplementation(EventSinkImplementation const&) = delete;
|
||||
EventSinkImplementation& operator=(EventSinkImplementation const&) = delete;
|
||||
|
||||
private:
|
||||
const BinaryMessenger* messenger_;
|
||||
const std::string name_;
|
||||
const MethodCodec<T>* codec_;
|
||||
|
||||
protected:
|
||||
void SuccessInternal(const T* event = nullptr) override {
|
||||
auto result = codec_->EncodeSuccessEnvelope(event);
|
||||
messenger_->Send(name_, result->data(), result->size());
|
||||
}
|
||||
|
||||
void ErrorInternal(const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const T* error_details) override {
|
||||
auto result =
|
||||
codec_->EncodeErrorEnvelope(error_code, error_message, error_details);
|
||||
messenger_->Send(name_, result->data(), result->size());
|
||||
}
|
||||
|
||||
void EndOfStreamInternal() override { messenger_->Send(name_, nullptr, 0); }
|
||||
};
|
||||
|
||||
BinaryMessenger* messenger_;
|
||||
const std::string name_;
|
||||
const MethodCodec<T>* codec_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_CHANNEL_H_
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_SINK_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_SINK_H_
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class EncodableValue;
|
||||
|
||||
// Event callback. Events to be sent to Flutter application
|
||||
// act as clients of this interface for sending events.
|
||||
template <typename T = EncodableValue>
|
||||
class EventSink {
|
||||
public:
|
||||
EventSink() = default;
|
||||
virtual ~EventSink() = default;
|
||||
|
||||
// Prevent copying.
|
||||
EventSink(EventSink const&) = delete;
|
||||
EventSink& operator=(EventSink const&) = delete;
|
||||
|
||||
// Consumes a successful event
|
||||
void Success(const T& event) { SuccessInternal(&event); }
|
||||
|
||||
// Consumes a successful event.
|
||||
void Success() { SuccessInternal(nullptr); }
|
||||
|
||||
// Consumes an error event.
|
||||
void Error(const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const T& error_details) {
|
||||
ErrorInternal(error_code, error_message, &error_details);
|
||||
}
|
||||
|
||||
// Consumes an error event.
|
||||
void Error(const std::string& error_code,
|
||||
const std::string& error_message = "") {
|
||||
ErrorInternal(error_code, error_message, nullptr);
|
||||
}
|
||||
|
||||
// Consumes end of stream. Ensuing calls to Success() or
|
||||
// Error(), if any, are ignored.
|
||||
void EndOfStream() { EndOfStreamInternal(); }
|
||||
|
||||
protected:
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual void SuccessInternal(const T* event = nullptr) = 0;
|
||||
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual void ErrorInternal(const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const T* error_details) = 0;
|
||||
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual void EndOfStreamInternal() = 0;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_SINK_H_
|
||||
@@ -0,0 +1,77 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_STREAM_HANDLER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_STREAM_HANDLER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "event_sink.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class EncodableValue;
|
||||
|
||||
template <typename T = EncodableValue>
|
||||
struct StreamHandlerError {
|
||||
const std::string error_code;
|
||||
const std::string error_message;
|
||||
const std::unique_ptr<T> error_details;
|
||||
|
||||
StreamHandlerError(const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
std::unique_ptr<T>&& error_details)
|
||||
: error_code(error_code),
|
||||
error_message(error_message),
|
||||
error_details(std::move(error_details)) {}
|
||||
};
|
||||
|
||||
// Handler for stream setup and teardown requests.
|
||||
// Implementations must be prepared to accept sequences of alternating calls to
|
||||
// OnListen() and OnCancel(). Implementations should ideally consume no
|
||||
// resources when the last such call is not OnListen(). In typical situations,
|
||||
// this means that the implementation should register itself with
|
||||
// platform-specific event sources OnListen() and deregister again OnCancel().
|
||||
template <typename T = EncodableValue>
|
||||
class StreamHandler {
|
||||
public:
|
||||
StreamHandler() = default;
|
||||
virtual ~StreamHandler() = default;
|
||||
|
||||
// Prevent copying.
|
||||
StreamHandler(StreamHandler const&) = delete;
|
||||
StreamHandler& operator=(StreamHandler const&) = delete;
|
||||
|
||||
// Handles a request to set up an event stream. Returns nullptr on success,
|
||||
// or an error on failure.
|
||||
// |arguments| is stream configuration arguments and
|
||||
// |events| is an EventSink for emitting events to the Flutter receiver.
|
||||
std::unique_ptr<StreamHandlerError<T>> OnListen(
|
||||
const T* arguments,
|
||||
std::unique_ptr<EventSink<T>>&& events) {
|
||||
return OnListenInternal(arguments, std::move(events));
|
||||
}
|
||||
|
||||
// Handles a request to tear down the most recently created event stream.
|
||||
// Returns nullptr on success, or an error on failure.
|
||||
// |arguments| is stream configuration arguments.
|
||||
std::unique_ptr<StreamHandlerError<T>> OnCancel(const T* arguments) {
|
||||
return OnCancelInternal(arguments);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual std::unique_ptr<StreamHandlerError<T>> OnListenInternal(
|
||||
const T* arguments,
|
||||
std::unique_ptr<EventSink<T>>&& events) = 0;
|
||||
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual std::unique_ptr<StreamHandlerError<T>> OnCancelInternal(
|
||||
const T* arguments) = 0;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_STREAM_HANDLER_H_
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_STREAM_HANDLER_FUNCTIONS_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_STREAM_HANDLER_FUNCTIONS_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "event_sink.h"
|
||||
#include "event_stream_handler.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class EncodableValue;
|
||||
|
||||
// Handler types for each of the StreamHandler setup and teardown
|
||||
// requests.
|
||||
template <typename T>
|
||||
using StreamHandlerListen =
|
||||
std::function<std::unique_ptr<StreamHandlerError<T>>(
|
||||
const T* arguments,
|
||||
std::unique_ptr<EventSink<T>>&& events)>;
|
||||
|
||||
template <typename T>
|
||||
using StreamHandlerCancel =
|
||||
std::function<std::unique_ptr<StreamHandlerError<T>>(const T* arguments)>;
|
||||
|
||||
// An implementation of StreamHandler that pass calls through to
|
||||
// provided function objects.
|
||||
template <typename T = EncodableValue>
|
||||
class StreamHandlerFunctions : public StreamHandler<T> {
|
||||
public:
|
||||
// Creates a handler object that calls the provided functions
|
||||
// for the corresponding StreamHandler outcomes.
|
||||
StreamHandlerFunctions(StreamHandlerListen<T> on_listen,
|
||||
StreamHandlerCancel<T> on_cancel)
|
||||
: on_listen_(std::move(on_listen)), on_cancel_(std::move(on_cancel)) {}
|
||||
|
||||
virtual ~StreamHandlerFunctions() = default;
|
||||
|
||||
// Prevent copying.
|
||||
StreamHandlerFunctions(StreamHandlerFunctions const&) = delete;
|
||||
StreamHandlerFunctions& operator=(StreamHandlerFunctions const&) = delete;
|
||||
|
||||
protected:
|
||||
// |flutter::StreamHandler|
|
||||
std::unique_ptr<StreamHandlerError<T>> OnListenInternal(
|
||||
const T* arguments,
|
||||
std::unique_ptr<EventSink<T>>&& events) override {
|
||||
if (on_listen_) {
|
||||
return on_listen_(arguments, std::move(events));
|
||||
}
|
||||
|
||||
auto error = std::make_unique<StreamHandlerError<T>>(
|
||||
"error", "No OnListen handler set", nullptr);
|
||||
return std::move(error);
|
||||
}
|
||||
|
||||
// |flutter::StreamHandler|
|
||||
std::unique_ptr<StreamHandlerError<T>> OnCancelInternal(
|
||||
const T* arguments) override {
|
||||
if (on_cancel_) {
|
||||
return on_cancel_(arguments);
|
||||
}
|
||||
|
||||
auto error = std::make_unique<StreamHandlerError<T>>(
|
||||
"error", "No OnCancel handler set", nullptr);
|
||||
return std::move(error);
|
||||
}
|
||||
|
||||
StreamHandlerListen<T> on_listen_;
|
||||
StreamHandlerCancel<T> on_cancel_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_EVENT_STREAM_HANDLER_FUNCTIONS_H_
|
||||
@@ -0,0 +1,128 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_ENGINE_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_ENGINE_H_
|
||||
|
||||
#include <flutter_windows.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "binary_messenger.h"
|
||||
#include "dart_project.h"
|
||||
#include "plugin_registrar.h"
|
||||
#include "plugin_registry.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// An instance of a Flutter engine.
|
||||
//
|
||||
// In the future, this will be the API surface used for all interactions with
|
||||
// the engine, rather than having them duplicated on FlutterViewController.
|
||||
// For now it is only used in the rare case where you need a headless Flutter
|
||||
// engine.
|
||||
class FlutterEngine : public PluginRegistry {
|
||||
public:
|
||||
// Creates a new engine for running the given project.
|
||||
explicit FlutterEngine(const DartProject& project);
|
||||
|
||||
virtual ~FlutterEngine();
|
||||
|
||||
// Prevent copying.
|
||||
FlutterEngine(FlutterEngine const&) = delete;
|
||||
FlutterEngine& operator=(FlutterEngine const&) = delete;
|
||||
|
||||
// Starts running the engine at the entrypoint function specified in the
|
||||
// DartProject used to configure the engine, or main() by default.
|
||||
bool Run();
|
||||
|
||||
// Starts running the engine, with an optional entry point.
|
||||
//
|
||||
// If provided, entry_point must be the name of a top-level function from the
|
||||
// same Dart library that contains the app's main() function, and must be
|
||||
// decorated with `@pragma(vm:entry-point)` to ensure the method is not
|
||||
// tree-shaken by the Dart compiler. If not provided, defaults to main().
|
||||
bool Run(const char* entry_point);
|
||||
|
||||
// Terminates the running engine.
|
||||
void ShutDown();
|
||||
|
||||
// Processes any pending events in the Flutter engine, and returns the
|
||||
// nanosecond delay until the next scheduled event (or max, if none).
|
||||
//
|
||||
// This should be called on every run of the application-level runloop, and
|
||||
// a wait for native events in the runloop should never be longer than the
|
||||
// last return value from this function.
|
||||
std::chrono::nanoseconds ProcessMessages();
|
||||
|
||||
// Tells the engine that the system font list has changed. Should be called
|
||||
// by clients when OS-level font changes happen (e.g., WM_FONTCHANGE in a
|
||||
// Win32 application).
|
||||
void ReloadSystemFonts();
|
||||
|
||||
// Tells the engine that the platform brightness value has changed. Should be
|
||||
// called by clients when OS-level theme changes happen (e.g.,
|
||||
// WM_DWMCOLORIZATIONCOLORCHANGED in a Win32 application).
|
||||
void ReloadPlatformBrightness();
|
||||
|
||||
// flutter::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(); }
|
||||
|
||||
// Schedule a callback to be called after the next frame is drawn.
|
||||
//
|
||||
// This must be called from the platform thread. The callback is executed only
|
||||
// once on the platform thread.
|
||||
void SetNextFrameCallback(std::function<void()> callback);
|
||||
|
||||
// Called to pass an external window message to the engine for lifecycle
|
||||
// state updates. Non-Flutter windows must call this method in their WndProc
|
||||
// in order to be included in the logic for application lifecycle state
|
||||
// updates. Returns a result if the message should be consumed.
|
||||
std::optional<LRESULT> ProcessExternalWindowMessage(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
|
||||
private:
|
||||
// For access to the engine handle.
|
||||
friend class FlutterViewController;
|
||||
|
||||
// Gives up ownership of |engine_|, but keeps a weak reference to it.
|
||||
//
|
||||
// This is intended to be used by FlutterViewController, since the underlying
|
||||
// C API for view controllers takes over engine ownership.
|
||||
FlutterDesktopEngineRef RelinquishEngine();
|
||||
|
||||
// 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;
|
||||
|
||||
// Whether |Run| has been called successfully.
|
||||
//
|
||||
// This is used to improve error messages. This can be false while the engine
|
||||
// is running if the engine was started by creating a view.
|
||||
bool run_succeeded_ = false;
|
||||
|
||||
// The callback to execute once the next frame is drawn.
|
||||
std::function<void()> next_frame_callback_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_ENGINE_H_
|
||||
@@ -0,0 +1,42 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_H_
|
||||
|
||||
#include <flutter_windows.h>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// The unique identifier for a view.
|
||||
typedef int64_t FlutterViewId;
|
||||
|
||||
// A view displaying Flutter content.
|
||||
class FlutterView {
|
||||
public:
|
||||
explicit FlutterView(FlutterDesktopViewRef view) : view_(view) {}
|
||||
|
||||
// Destroys this reference to the view. The underlying view is not destroyed.
|
||||
virtual ~FlutterView() = default;
|
||||
|
||||
// Prevent copying.
|
||||
FlutterView(FlutterView const&) = delete;
|
||||
FlutterView& operator=(FlutterView const&) = delete;
|
||||
|
||||
// Returns the backing HWND for the view.
|
||||
HWND GetNativeWindow() { return FlutterDesktopViewGetHWND(view_); }
|
||||
|
||||
// Returns the DXGI adapter used for rendering or nullptr in case of error.
|
||||
IDXGIAdapter* GetGraphicsAdapter() {
|
||||
return FlutterDesktopViewGetGraphicsAdapter(view_);
|
||||
}
|
||||
|
||||
private:
|
||||
// Handle for interacting with the C API's view.
|
||||
FlutterDesktopViewRef view_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_H_
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_CONTROLLER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_CONTROLLER_H_
|
||||
|
||||
#include <flutter_windows.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "dart_project.h"
|
||||
#include "flutter_engine.h"
|
||||
#include "flutter_view.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// A controller for a view displaying Flutter content.
|
||||
//
|
||||
// This is the primary wrapper class for the desktop C API.
|
||||
// If you use this class, you should not call any of the setup or teardown
|
||||
// methods in the C API directly, as this class will do that internally.
|
||||
class FlutterViewController {
|
||||
public:
|
||||
// Creates a FlutterView that can be parented into a Windows View hierarchy
|
||||
// either using HWNDs.
|
||||
//
|
||||
// This also creates a new FlutterEngine.
|
||||
//
|
||||
// |dart_project| will be used to configure the engine backing this view.
|
||||
FlutterViewController(int width, int height, const DartProject& project);
|
||||
|
||||
virtual ~FlutterViewController();
|
||||
|
||||
// Prevent copying.
|
||||
FlutterViewController(FlutterViewController const&) = delete;
|
||||
FlutterViewController& operator=(FlutterViewController const&) = delete;
|
||||
|
||||
// Returns the view controller's view ID.
|
||||
FlutterViewId view_id() const;
|
||||
|
||||
// Returns the engine running Flutter content in this view.
|
||||
FlutterEngine* engine() const { return engine_.get(); }
|
||||
|
||||
// Returns the view managed by this controller.
|
||||
FlutterView* view() const { return view_.get(); }
|
||||
|
||||
// Requests new frame from the engine and repaints the view.
|
||||
void ForceRedraw();
|
||||
|
||||
// Allows the Flutter engine and any interested plugins an opportunity to
|
||||
// handle the given message.
|
||||
//
|
||||
// If a result is returned, then the message was handled in such a way that
|
||||
// further handling should not be done.
|
||||
std::optional<LRESULT> HandleTopLevelWindowProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
|
||||
private:
|
||||
// Handle for interacting with the C API's view controller, if any.
|
||||
FlutterDesktopViewControllerRef controller_ = nullptr;
|
||||
|
||||
// The backing engine
|
||||
std::shared_ptr<FlutterEngine> engine_;
|
||||
|
||||
// The owned FlutterView.
|
||||
std::unique_ptr<FlutterView> view_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_VIEW_CONTROLLER_H_
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_MESSAGE_CODEC_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_MESSAGE_CODEC_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// Translates between a binary message and higher-level method call and
|
||||
// response/error objects.
|
||||
template <typename T>
|
||||
class MessageCodec {
|
||||
public:
|
||||
MessageCodec() = default;
|
||||
|
||||
virtual ~MessageCodec() = default;
|
||||
|
||||
// Prevent copying.
|
||||
MessageCodec(MessageCodec<T> const&) = delete;
|
||||
MessageCodec& operator=(MessageCodec<T> const&) = delete;
|
||||
|
||||
// Returns the message encoded in |binary_message|, or nullptr if it cannot be
|
||||
// decoded by this codec.
|
||||
std::unique_ptr<T> DecodeMessage(const uint8_t* binary_message,
|
||||
const size_t message_size) const {
|
||||
return std::move(DecodeMessageInternal(binary_message, message_size));
|
||||
}
|
||||
|
||||
// Returns the message encoded in |binary_message|, or nullptr if it cannot be
|
||||
// decoded by this codec.
|
||||
std::unique_ptr<T> DecodeMessage(
|
||||
const std::vector<uint8_t>& binary_message) const {
|
||||
size_t size = binary_message.size();
|
||||
const uint8_t* data = size > 0 ? &binary_message[0] : nullptr;
|
||||
return std::move(DecodeMessageInternal(data, size));
|
||||
}
|
||||
|
||||
// Returns a binary encoding of the given |message|, or nullptr if the
|
||||
// message cannot be serialized by this codec.
|
||||
std::unique_ptr<std::vector<uint8_t>> EncodeMessage(const T& message) const {
|
||||
return std::move(EncodeMessageInternal(message));
|
||||
}
|
||||
|
||||
protected:
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual std::unique_ptr<T> DecodeMessageInternal(
|
||||
const uint8_t* binary_message,
|
||||
const size_t message_size) const = 0;
|
||||
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual std::unique_ptr<std::vector<uint8_t>> EncodeMessageInternal(
|
||||
const T& message) const = 0;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_MESSAGE_CODEC_H_
|
||||
@@ -0,0 +1,43 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CALL_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CALL_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class EncodableValue;
|
||||
|
||||
// An object encapsulating a method call from Flutter whose arguments are of
|
||||
// type T.
|
||||
template <typename T = EncodableValue>
|
||||
class MethodCall {
|
||||
public:
|
||||
// Creates a MethodCall with the given name and arguments.
|
||||
MethodCall(const std::string& method_name, std::unique_ptr<T> arguments)
|
||||
: method_name_(method_name), arguments_(std::move(arguments)) {}
|
||||
|
||||
virtual ~MethodCall() = default;
|
||||
|
||||
// Prevent copying.
|
||||
MethodCall(MethodCall<T> const&) = delete;
|
||||
MethodCall& operator=(MethodCall<T> const&) = delete;
|
||||
|
||||
// The name of the method being called.
|
||||
const std::string& method_name() const { return method_name_; }
|
||||
|
||||
// The arguments to the method call, or NULL if there are none.
|
||||
const T* arguments() const { return arguments_.get(); }
|
||||
|
||||
private:
|
||||
std::string method_name_;
|
||||
std::unique_ptr<T> arguments_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CALL_H_
|
||||
@@ -0,0 +1,151 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CHANNEL_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CHANNEL_H_
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "basic_message_channel.h"
|
||||
#include "binary_messenger.h"
|
||||
#include "engine_method_result.h"
|
||||
#include "method_call.h"
|
||||
#include "method_codec.h"
|
||||
#include "method_result.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class EncodableValue;
|
||||
|
||||
// A handler for receiving a method call from the Flutter engine.
|
||||
//
|
||||
// Implementations must asynchronously call exactly one of the methods on
|
||||
// |result| to indicate the result of the method call.
|
||||
template <typename T>
|
||||
using MethodCallHandler =
|
||||
std::function<void(const MethodCall<T>& call,
|
||||
std::unique_ptr<MethodResult<T>> result)>;
|
||||
|
||||
// A channel for communicating with the Flutter engine using invocation of
|
||||
// asynchronous methods.
|
||||
template <typename T = EncodableValue>
|
||||
class MethodChannel {
|
||||
public:
|
||||
// Creates an instance that sends and receives method calls on the channel
|
||||
// named |name|, encoded with |codec| and dispatched via |messenger|.
|
||||
MethodChannel(BinaryMessenger* messenger,
|
||||
const std::string& name,
|
||||
const MethodCodec<T>* codec)
|
||||
: messenger_(messenger), name_(name), codec_(codec) {}
|
||||
|
||||
~MethodChannel() = default;
|
||||
|
||||
// Prevent copying.
|
||||
MethodChannel(MethodChannel const&) = delete;
|
||||
MethodChannel& operator=(MethodChannel const&) = delete;
|
||||
|
||||
// Sends a message to the Flutter engine on this channel.
|
||||
//
|
||||
// If |result| is provided, one of its methods will be invoked with the
|
||||
// response from the engine.
|
||||
void InvokeMethod(const std::string& method,
|
||||
std::unique_ptr<T> arguments,
|
||||
std::unique_ptr<MethodResult<T>> result = nullptr) {
|
||||
MethodCall<T> method_call(method, std::move(arguments));
|
||||
std::unique_ptr<std::vector<uint8_t>> message =
|
||||
codec_->EncodeMethodCall(method_call);
|
||||
if (!result) {
|
||||
messenger_->Send(name_, message->data(), message->size(), nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// std::function requires a copyable lambda, so convert to a shared pointer.
|
||||
// This is safe since only one copy of the shared_pointer will ever be
|
||||
// accessed.
|
||||
std::shared_ptr<MethodResult<T>> shared_result(result.release());
|
||||
const auto* codec = codec_;
|
||||
std::string channel_name = name_;
|
||||
BinaryReply reply_handler = [shared_result, codec, channel_name](
|
||||
const uint8_t* reply, size_t reply_size) {
|
||||
if (reply_size == 0) {
|
||||
shared_result->NotImplemented();
|
||||
return;
|
||||
}
|
||||
// Use this channel's codec to decode and handle the
|
||||
// reply.
|
||||
bool decoded = codec->DecodeAndProcessResponseEnvelope(
|
||||
reply, reply_size, shared_result.get());
|
||||
if (!decoded) {
|
||||
std::cerr << "Unable to decode reply to method "
|
||||
"invocation on channel "
|
||||
<< channel_name << std::endl;
|
||||
shared_result->NotImplemented();
|
||||
}
|
||||
};
|
||||
|
||||
messenger_->Send(name_, message->data(), message->size(),
|
||||
std::move(reply_handler));
|
||||
}
|
||||
|
||||
// Registers a handler that should be called any time a method call is
|
||||
// received on this channel. A null handler will remove any previous handler.
|
||||
//
|
||||
// The handler will be owned by the underlying BinaryMessageHandler.
|
||||
// Destroying the MethodChannel will not unregister the handler, so
|
||||
// the caller is responsible for unregistering explicitly if the handler
|
||||
// stops being valid before the engine is destroyed.
|
||||
void SetMethodCallHandler(const MethodCallHandler<T>& handler) const {
|
||||
if (!handler) {
|
||||
messenger_->SetMessageHandler(name_, nullptr);
|
||||
return;
|
||||
}
|
||||
const auto* codec = codec_;
|
||||
std::string channel_name = name_;
|
||||
BinaryMessageHandler binary_handler = [handler, codec, channel_name](
|
||||
const uint8_t* message,
|
||||
size_t message_size,
|
||||
BinaryReply reply) {
|
||||
// Use this channel's codec to decode the call and build a result handler.
|
||||
auto result =
|
||||
std::make_unique<EngineMethodResult<T>>(std::move(reply), codec);
|
||||
std::unique_ptr<MethodCall<T>> method_call =
|
||||
codec->DecodeMethodCall(message, message_size);
|
||||
if (!method_call) {
|
||||
std::cerr << "Unable to construct method call from message on channel "
|
||||
<< channel_name << std::endl;
|
||||
result->NotImplemented();
|
||||
return;
|
||||
}
|
||||
handler(*method_call, std::move(result));
|
||||
};
|
||||
messenger_->SetMessageHandler(name_, std::move(binary_handler));
|
||||
}
|
||||
|
||||
// Adjusts the number of messages that will get buffered when sending messages
|
||||
// to channels that aren't fully set up yet. For example, the engine isn't
|
||||
// running yet or the channel's message handler isn't set up on the Dart side
|
||||
// yet.
|
||||
void Resize(int new_size) {
|
||||
internal::ResizeChannel(messenger_, name_, new_size);
|
||||
}
|
||||
|
||||
// Defines whether the channel should show warning messages when discarding
|
||||
// messages due to overflow.
|
||||
//
|
||||
// When |warns| is false, the channel is expected to overflow and warning
|
||||
// messages will not be shown.
|
||||
void SetWarnsOnOverflow(bool warns) {
|
||||
internal::SetChannelWarnsOnOverflow(messenger_, name_, warns);
|
||||
}
|
||||
|
||||
private:
|
||||
BinaryMessenger* messenger_;
|
||||
std::string name_;
|
||||
const MethodCodec<T>* codec_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CHANNEL_H_
|
||||
@@ -0,0 +1,111 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CODEC_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CODEC_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "method_call.h"
|
||||
#include "method_result.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// Translates between a binary message and higher-level method call and
|
||||
// response/error objects.
|
||||
template <typename T>
|
||||
class MethodCodec {
|
||||
public:
|
||||
MethodCodec() = default;
|
||||
|
||||
virtual ~MethodCodec() = default;
|
||||
|
||||
// Prevent copying.
|
||||
MethodCodec(MethodCodec<T> const&) = delete;
|
||||
MethodCodec& operator=(MethodCodec<T> const&) = delete;
|
||||
|
||||
// Returns the MethodCall encoded in |message|, or nullptr if it cannot be
|
||||
// decoded.
|
||||
std::unique_ptr<MethodCall<T>> DecodeMethodCall(const uint8_t* message,
|
||||
size_t message_size) const {
|
||||
return std::move(DecodeMethodCallInternal(message, message_size));
|
||||
}
|
||||
|
||||
// Returns the MethodCall encoded in |message|, or nullptr if it cannot be
|
||||
// decoded.
|
||||
std::unique_ptr<MethodCall<T>> DecodeMethodCall(
|
||||
const std::vector<uint8_t>& message) const {
|
||||
size_t size = message.size();
|
||||
const uint8_t* data = size > 0 ? &message[0] : nullptr;
|
||||
return std::move(DecodeMethodCallInternal(data, size));
|
||||
}
|
||||
|
||||
// Returns a binary encoding of the given |method_call|, or nullptr if the
|
||||
// method call cannot be serialized by this codec.
|
||||
std::unique_ptr<std::vector<uint8_t>> EncodeMethodCall(
|
||||
const MethodCall<T>& method_call) const {
|
||||
return std::move(EncodeMethodCallInternal(method_call));
|
||||
}
|
||||
|
||||
// Returns a binary encoding of |result|. |result| must be a type supported
|
||||
// by the codec.
|
||||
std::unique_ptr<std::vector<uint8_t>> EncodeSuccessEnvelope(
|
||||
const T* result = nullptr) const {
|
||||
return std::move(EncodeSuccessEnvelopeInternal(result));
|
||||
}
|
||||
|
||||
// Returns a binary encoding of |error|. The |error_details| must be a type
|
||||
// supported by the codec.
|
||||
std::unique_ptr<std::vector<uint8_t>> EncodeErrorEnvelope(
|
||||
const std::string& error_code,
|
||||
const std::string& error_message = "",
|
||||
const T* error_details = nullptr) const {
|
||||
return std::move(
|
||||
EncodeErrorEnvelopeInternal(error_code, error_message, error_details));
|
||||
}
|
||||
|
||||
// Decodes the response envelope encoded in |response|, calling the
|
||||
// appropriate method on |result|.
|
||||
//
|
||||
// Returns false if |response| cannot be decoded. In that case the caller is
|
||||
// responsible for calling a |result| method.
|
||||
bool DecodeAndProcessResponseEnvelope(const uint8_t* response,
|
||||
size_t response_size,
|
||||
MethodResult<T>* result) const {
|
||||
return DecodeAndProcessResponseEnvelopeInternal(response, response_size,
|
||||
result);
|
||||
}
|
||||
|
||||
protected:
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual std::unique_ptr<MethodCall<T>> DecodeMethodCallInternal(
|
||||
const uint8_t* message,
|
||||
size_t message_size) const = 0;
|
||||
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual std::unique_ptr<std::vector<uint8_t>> EncodeMethodCallInternal(
|
||||
const MethodCall<T>& method_call) const = 0;
|
||||
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual std::unique_ptr<std::vector<uint8_t>> EncodeSuccessEnvelopeInternal(
|
||||
const T* result) const = 0;
|
||||
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual std::unique_ptr<std::vector<uint8_t>> EncodeErrorEnvelopeInternal(
|
||||
const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const T* error_details) const = 0;
|
||||
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual bool DecodeAndProcessResponseEnvelopeInternal(
|
||||
const uint8_t* response,
|
||||
size_t response_size,
|
||||
MethodResult<T>* result) const = 0;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CODEC_H_
|
||||
@@ -0,0 +1,76 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_RESULT_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_RESULT_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class EncodableValue;
|
||||
|
||||
// Encapsulates a result returned from a MethodCall. Only one method should be
|
||||
// called on any given instance.
|
||||
template <typename T = EncodableValue>
|
||||
class MethodResult {
|
||||
public:
|
||||
MethodResult() = default;
|
||||
|
||||
virtual ~MethodResult() = default;
|
||||
|
||||
// Prevent copying.
|
||||
MethodResult(MethodResult const&) = delete;
|
||||
MethodResult& operator=(MethodResult const&) = delete;
|
||||
|
||||
// Sends a success response, indicating that the call completed successfully
|
||||
// with the given result.
|
||||
void Success(const T& result) { SuccessInternal(&result); }
|
||||
|
||||
// Sends a success response, indicating that the call completed successfully
|
||||
// with no result.
|
||||
void Success() { SuccessInternal(nullptr); }
|
||||
|
||||
// Sends an error response, indicating that the call was understood but
|
||||
// handling failed in some way.
|
||||
//
|
||||
// error_code: A string error code describing the error.
|
||||
// error_message: A user-readable error message.
|
||||
// error_details: Arbitrary extra details about the error.
|
||||
void Error(const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const T& error_details) {
|
||||
ErrorInternal(error_code, error_message, &error_details);
|
||||
}
|
||||
|
||||
// Sends an error response, indicating that the call was understood but
|
||||
// handling failed in some way.
|
||||
//
|
||||
// error_code: A string error code describing the error.
|
||||
// error_message: A user-readable error message (optional).
|
||||
void Error(const std::string& error_code,
|
||||
const std::string& error_message = "") {
|
||||
ErrorInternal(error_code, error_message, nullptr);
|
||||
}
|
||||
|
||||
// Sends a not-implemented response, indicating that the method either was not
|
||||
// recognized, or has not been implemented.
|
||||
void NotImplemented() { NotImplementedInternal(); }
|
||||
|
||||
protected:
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual void SuccessInternal(const T* result) = 0;
|
||||
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual void ErrorInternal(const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const T* error_details) = 0;
|
||||
|
||||
// Implementation of the public interface, to be provided by subclasses.
|
||||
virtual void NotImplementedInternal() = 0;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_RESULT_H_
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_RESULT_FUNCTIONS_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_RESULT_FUNCTIONS_H_
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "method_result.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class EncodableValue;
|
||||
|
||||
// Handler types for each of the MethodResult outcomes.
|
||||
template <typename T>
|
||||
using ResultHandlerSuccess = std::function<void(const T* result)>;
|
||||
template <typename T>
|
||||
using ResultHandlerError = std::function<void(const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const T* error_details)>;
|
||||
template <typename T>
|
||||
using ResultHandlerNotImplemented = std::function<void()>;
|
||||
|
||||
// An implementation of MethodResult that pass calls through to provided
|
||||
// function objects, for ease of constructing one-off result handlers.
|
||||
template <typename T = EncodableValue>
|
||||
class MethodResultFunctions : public MethodResult<T> {
|
||||
public:
|
||||
// Creates a result object that calls the provided functions for the
|
||||
// corresponding MethodResult outcomes.
|
||||
MethodResultFunctions(ResultHandlerSuccess<T> on_success,
|
||||
ResultHandlerError<T> on_error,
|
||||
ResultHandlerNotImplemented<T> on_not_implemented)
|
||||
: on_success_(std::move(on_success)),
|
||||
on_error_(std::move(on_error)),
|
||||
on_not_implemented_(std::move(on_not_implemented)) {}
|
||||
|
||||
virtual ~MethodResultFunctions() = default;
|
||||
|
||||
// Prevent copying.
|
||||
MethodResultFunctions(MethodResultFunctions const&) = delete;
|
||||
MethodResultFunctions& operator=(MethodResultFunctions const&) = delete;
|
||||
|
||||
protected:
|
||||
// |flutter::MethodResult|
|
||||
void SuccessInternal(const T* result) override {
|
||||
if (on_success_) {
|
||||
on_success_(result);
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::MethodResult|
|
||||
void ErrorInternal(const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const T* error_details) override {
|
||||
if (on_error_) {
|
||||
on_error_(error_code, error_message, error_details);
|
||||
}
|
||||
}
|
||||
|
||||
// |flutter::MethodResult|
|
||||
void NotImplementedInternal() override {
|
||||
if (on_not_implemented_) {
|
||||
on_not_implemented_();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ResultHandlerSuccess<T> on_success_;
|
||||
ResultHandlerError<T> on_error_;
|
||||
ResultHandlerNotImplemented<T> on_not_implemented_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_RESULT_FUNCTIONS_H_
|
||||
@@ -0,0 +1,131 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_H_
|
||||
|
||||
#include <flutter_plugin_registrar.h>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
#include "binary_messenger.h"
|
||||
#include "texture_registrar.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class Plugin;
|
||||
|
||||
// A object managing the registration of a plugin for various events.
|
||||
//
|
||||
// Currently this class has very limited functionality, but is expected to
|
||||
// expand over time to more closely match the functionality of
|
||||
// the Flutter mobile plugin APIs' plugin registrars.
|
||||
class PluginRegistrar {
|
||||
public:
|
||||
// Creates a new PluginRegistrar. |core_registrar| and the messenger it
|
||||
// provides must remain valid as long as this object exists.
|
||||
explicit PluginRegistrar(FlutterDesktopPluginRegistrarRef core_registrar);
|
||||
|
||||
virtual ~PluginRegistrar();
|
||||
|
||||
// Prevent copying.
|
||||
PluginRegistrar(PluginRegistrar const&) = delete;
|
||||
PluginRegistrar& operator=(PluginRegistrar const&) = delete;
|
||||
|
||||
// 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(); }
|
||||
|
||||
// Returns the texture registrar to use for the plugin to render a pixel
|
||||
// buffer.
|
||||
TextureRegistrar* texture_registrar() { return texture_registrar_.get(); }
|
||||
|
||||
// Takes ownership of |plugin|.
|
||||
//
|
||||
// Plugins are not required to call this method if they have other lifetime
|
||||
// management, but this is a convenient place for plugins to be owned to
|
||||
// ensure that they stay valid for any registered callbacks.
|
||||
void AddPlugin(std::unique_ptr<Plugin> plugin);
|
||||
|
||||
protected:
|
||||
FlutterDesktopPluginRegistrarRef registrar() const { return registrar_; }
|
||||
|
||||
// Destroys all owned plugins. Subclasses should call this at the beginning of
|
||||
// their destructors to prevent the possibility of an owned plugin trying to
|
||||
// access destroyed state during its own destruction.
|
||||
void ClearPlugins();
|
||||
|
||||
private:
|
||||
// Handle for interacting with the C API's registrar.
|
||||
FlutterDesktopPluginRegistrarRef registrar_;
|
||||
|
||||
std::unique_ptr<BinaryMessenger> messenger_;
|
||||
|
||||
std::unique_ptr<TextureRegistrar> texture_registrar_;
|
||||
|
||||
// Plugins registered for ownership.
|
||||
std::set<std::unique_ptr<Plugin>> plugins_;
|
||||
};
|
||||
|
||||
// A plugin that can be registered for ownership by a PluginRegistrar.
|
||||
class Plugin {
|
||||
public:
|
||||
virtual ~Plugin() = default;
|
||||
};
|
||||
|
||||
// A singleton to own PluginRegistrars. This is intended for use in plugins,
|
||||
// where there is no higher-level object to own a PluginRegistrar that can
|
||||
// own plugin instances and ensure that they live as long as the engine they
|
||||
// are registered with.
|
||||
class PluginRegistrarManager {
|
||||
public:
|
||||
static PluginRegistrarManager* GetInstance();
|
||||
|
||||
// Prevent copying.
|
||||
PluginRegistrarManager(PluginRegistrarManager const&) = delete;
|
||||
PluginRegistrarManager& operator=(PluginRegistrarManager const&) = delete;
|
||||
|
||||
// Returns a plugin registrar wrapper of type T, which must be a kind of
|
||||
// PluginRegistrar, creating it if necessary. The returned registrar will
|
||||
// live as long as the underlying FlutterDesktopPluginRegistrarRef, so
|
||||
// can be used to own plugin instances.
|
||||
//
|
||||
// Calling this multiple times for the same registrar_ref with different
|
||||
// template types results in undefined behavior.
|
||||
template <class T>
|
||||
T* GetRegistrar(FlutterDesktopPluginRegistrarRef registrar_ref) {
|
||||
auto insert_result =
|
||||
registrars_.emplace(registrar_ref, std::make_unique<T>(registrar_ref));
|
||||
auto& registrar_pair = *(insert_result.first);
|
||||
FlutterDesktopPluginRegistrarSetDestructionHandler(registrar_pair.first,
|
||||
OnRegistrarDestroyed);
|
||||
return static_cast<T*>(registrar_pair.second.get());
|
||||
}
|
||||
|
||||
// Destroys all registrar wrappers created by the manager.
|
||||
//
|
||||
// This is intended primarily for use in tests.
|
||||
void Reset() { registrars_.clear(); }
|
||||
|
||||
private:
|
||||
PluginRegistrarManager();
|
||||
|
||||
using WrapperMap = std::map<FlutterDesktopPluginRegistrarRef,
|
||||
std::unique_ptr<PluginRegistrar>>;
|
||||
|
||||
static void OnRegistrarDestroyed(FlutterDesktopPluginRegistrarRef registrar);
|
||||
|
||||
WrapperMap* registrars() { return ®istrars_; }
|
||||
|
||||
WrapperMap registrars_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_H_
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_WINDOWS_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_WINDOWS_H_
|
||||
|
||||
#include <flutter_windows.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "flutter_view.h"
|
||||
#include "plugin_registrar.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// A delegate callback for WindowProc delegation.
|
||||
//
|
||||
// Implementations should return a value only if they have handled the message
|
||||
// and want to stop all further handling.
|
||||
using WindowProcDelegate = std::function<std::optional<
|
||||
LRESULT>(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)>;
|
||||
|
||||
// An extension to PluginRegistrar providing access to Windows-specific
|
||||
// functionality.
|
||||
class PluginRegistrarWindows : public PluginRegistrar {
|
||||
public:
|
||||
// Creates a new PluginRegistrar. |core_registrar| and the messenger it
|
||||
// provides must remain valid as long as this object exists.
|
||||
explicit PluginRegistrarWindows(
|
||||
FlutterDesktopPluginRegistrarRef core_registrar)
|
||||
: PluginRegistrar(core_registrar) {
|
||||
FlutterDesktopViewRef implicit_view =
|
||||
FlutterDesktopPluginRegistrarGetView(core_registrar);
|
||||
if (implicit_view) {
|
||||
implicit_view_ = std::make_unique<FlutterView>(implicit_view);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~PluginRegistrarWindows() {
|
||||
// Must be the first call.
|
||||
ClearPlugins();
|
||||
// Explicitly cleared to facilitate destruction order testing.
|
||||
implicit_view_.reset();
|
||||
}
|
||||
|
||||
// Prevent copying.
|
||||
PluginRegistrarWindows(PluginRegistrarWindows const&) = delete;
|
||||
PluginRegistrarWindows& operator=(PluginRegistrarWindows const&) = delete;
|
||||
|
||||
// Returns the implicit view, or nullptr if there is no implicit view.
|
||||
//
|
||||
// See:
|
||||
// https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/implicitView.html
|
||||
//
|
||||
// DEPRECATED: Use |GetViewById| instead.
|
||||
FlutterView* GetView() { return implicit_view_.get(); }
|
||||
|
||||
// Returns the view with the given ID, or nullptr if the view does not exist.
|
||||
//
|
||||
// Destroying the shared pointer destroys the reference to the view; it does
|
||||
// not destroy the underlying view.
|
||||
std::shared_ptr<FlutterView> GetViewById(FlutterViewId view_id) const {
|
||||
FlutterDesktopViewRef view =
|
||||
FlutterDesktopPluginRegistrarGetViewById(registrar(), view_id);
|
||||
if (!view) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_shared<FlutterView>(view);
|
||||
}
|
||||
|
||||
// Registers |delegate| to receive WindowProc callbacks for the top-level
|
||||
// window containing this Flutter instance. Returns an ID that can be used to
|
||||
// unregister the handler.
|
||||
//
|
||||
// Delegates are not guaranteed to be called:
|
||||
// - The application may choose not to delegate WindowProc calls.
|
||||
// - If multiple plugins are registered, the first one that returns a value
|
||||
// from the delegate message will "win", and others will not be called.
|
||||
// The order of delegate calls is not defined.
|
||||
//
|
||||
// Delegates should be implemented as narrowly as possible, only returning
|
||||
// a value in cases where it's important that other delegates not run, to
|
||||
// minimize the chances of conflicts between plugins.
|
||||
int RegisterTopLevelWindowProcDelegate(WindowProcDelegate delegate) {
|
||||
if (window_proc_delegates_.empty()) {
|
||||
FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(
|
||||
registrar(), PluginRegistrarWindows::OnTopLevelWindowProc, this);
|
||||
}
|
||||
int delegate_id = next_window_proc_delegate_id_++;
|
||||
window_proc_delegates_.emplace(delegate_id, std::move(delegate));
|
||||
return delegate_id;
|
||||
}
|
||||
|
||||
// Unregisters a previously registered delegate.
|
||||
void UnregisterTopLevelWindowProcDelegate(int proc_id) {
|
||||
window_proc_delegates_.erase(proc_id);
|
||||
if (window_proc_delegates_.empty()) {
|
||||
FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate(
|
||||
registrar(), PluginRegistrarWindows::OnTopLevelWindowProc);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// A FlutterDesktopWindowProcCallback implementation that forwards back to
|
||||
// a PluginRegistarWindows instance provided as |user_data|.
|
||||
static bool OnTopLevelWindowProc(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam,
|
||||
void* user_data,
|
||||
LRESULT* result) {
|
||||
const auto* registrar = static_cast<PluginRegistrarWindows*>(user_data);
|
||||
std::optional optional_result = registrar->CallTopLevelWindowProcDelegates(
|
||||
hwnd, message, wparam, lparam);
|
||||
if (optional_result) {
|
||||
*result = *optional_result;
|
||||
}
|
||||
return optional_result.has_value();
|
||||
}
|
||||
|
||||
std::optional<LRESULT> CallTopLevelWindowProcDelegates(HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) const {
|
||||
std::optional<LRESULT> result;
|
||||
for (const auto& pair : window_proc_delegates_) {
|
||||
result = pair.second(hwnd, message, wparam, lparam);
|
||||
// Stop as soon as any delegate indicates that it has handled the message.
|
||||
if (result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// The associated FlutterView, if any.
|
||||
std::unique_ptr<FlutterView> implicit_view_;
|
||||
|
||||
// The next ID to return from RegisterWindowProcDelegate.
|
||||
int next_window_proc_delegate_id_ = 1;
|
||||
|
||||
std::map<int, WindowProcDelegate> window_proc_delegates_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_WINDOWS_H_
|
||||
@@ -0,0 +1,37 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRY_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRY_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <flutter_plugin_registrar.h>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// Vends PluginRegistrars for named plugins.
|
||||
//
|
||||
// Plugins are identified by unique string keys, typically the name of the
|
||||
// plugin's main class.
|
||||
class PluginRegistry {
|
||||
public:
|
||||
PluginRegistry() = default;
|
||||
virtual ~PluginRegistry() = default;
|
||||
|
||||
// Prevent copying.
|
||||
PluginRegistry(PluginRegistry const&) = delete;
|
||||
PluginRegistry& operator=(PluginRegistry const&) = delete;
|
||||
|
||||
// Returns the FlutterDesktopPluginRegistrarRef to register a plugin with the
|
||||
// given name.
|
||||
//
|
||||
// The name must be unique across the application.
|
||||
virtual FlutterDesktopPluginRegistrarRef GetRegistrarForPlugin(
|
||||
const std::string& plugin_name) = 0;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRY_H_
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_CODEC_SERIALIZER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_CODEC_SERIALIZER_H_
|
||||
|
||||
#include "byte_streams.h"
|
||||
#include "encodable_value.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// Encapsulates the logic for encoding/decoding EncodableValues to/from the
|
||||
// standard codec binary representation.
|
||||
//
|
||||
// This can be subclassed to extend the standard codec with support for new
|
||||
// types.
|
||||
class StandardCodecSerializer {
|
||||
public:
|
||||
virtual ~StandardCodecSerializer();
|
||||
|
||||
// Returns the shared serializer instance.
|
||||
static const StandardCodecSerializer& GetInstance();
|
||||
|
||||
// Prevent copying.
|
||||
StandardCodecSerializer(StandardCodecSerializer const&) = delete;
|
||||
StandardCodecSerializer& operator=(StandardCodecSerializer const&) = delete;
|
||||
|
||||
// Reads and returns the next value from |stream|.
|
||||
EncodableValue ReadValue(ByteStreamReader* stream) const;
|
||||
|
||||
// Writes the encoding of |value| to |stream|, including the initial type
|
||||
// discrimination byte.
|
||||
//
|
||||
// Can be overridden by a subclass to extend the codec.
|
||||
virtual void WriteValue(const EncodableValue& value,
|
||||
ByteStreamWriter* stream) const;
|
||||
|
||||
protected:
|
||||
// Codecs require long-lived serializers, so clients should always use
|
||||
// GetInstance().
|
||||
StandardCodecSerializer();
|
||||
|
||||
// Reads and returns the next value from |stream|, whose discrimination byte
|
||||
// was |type|.
|
||||
//
|
||||
// The discrimination byte will already have been read from the stream when
|
||||
// this is called.
|
||||
//
|
||||
// Can be overridden by a subclass to extend the codec.
|
||||
virtual EncodableValue ReadValueOfType(uint8_t type,
|
||||
ByteStreamReader* stream) const;
|
||||
|
||||
// Reads the variable-length size from the current position in |stream|.
|
||||
size_t ReadSize(ByteStreamReader* stream) const;
|
||||
|
||||
// Writes the variable-length size encoding to |stream|.
|
||||
void WriteSize(size_t size, ByteStreamWriter* stream) const;
|
||||
|
||||
private:
|
||||
// Reads a fixed-type list whose values are of type T from the current
|
||||
// position in |stream|, and returns it as the corresponding EncodableValue.
|
||||
// |T| must correspond to one of the supported list value types of
|
||||
// EncodableValue.
|
||||
template <typename T>
|
||||
EncodableValue ReadVector(ByteStreamReader* stream) const;
|
||||
|
||||
// Writes |vector| to |stream| as a fixed-type list. |T| must correspond to
|
||||
// one of the supported list value types of EncodableValue.
|
||||
template <typename T>
|
||||
void WriteVector(const std::vector<T> vector, ByteStreamWriter* stream) const;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_CODEC_SERIALIZER_H_
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_MESSAGE_CODEC_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_MESSAGE_CODEC_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "encodable_value.h"
|
||||
#include "message_codec.h"
|
||||
#include "standard_codec_serializer.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// A binary message encoding/decoding mechanism for communications to/from the
|
||||
// Flutter engine via message channels.
|
||||
class StandardMessageCodec : public MessageCodec<EncodableValue> {
|
||||
public:
|
||||
// Returns an instance of the codec, optionally using a custom serializer to
|
||||
// add support for more types.
|
||||
//
|
||||
// If provided, |serializer| must be long-lived. If no serializer is provided,
|
||||
// the default will be used.
|
||||
//
|
||||
// The instance returned for a given |serializer| will be shared, and
|
||||
// any instance returned from this will be long-lived, and can be safely
|
||||
// passed to, e.g., channel constructors.
|
||||
static const StandardMessageCodec& GetInstance(
|
||||
const StandardCodecSerializer* serializer = nullptr);
|
||||
|
||||
~StandardMessageCodec();
|
||||
|
||||
// Prevent copying.
|
||||
StandardMessageCodec(StandardMessageCodec const&) = delete;
|
||||
StandardMessageCodec& operator=(StandardMessageCodec const&) = delete;
|
||||
|
||||
protected:
|
||||
// |flutter::MessageCodec|
|
||||
std::unique_ptr<EncodableValue> DecodeMessageInternal(
|
||||
const uint8_t* binary_message,
|
||||
const size_t message_size) const override;
|
||||
|
||||
// |flutter::MessageCodec|
|
||||
std::unique_ptr<std::vector<uint8_t>> EncodeMessageInternal(
|
||||
const EncodableValue& message) const override;
|
||||
|
||||
private:
|
||||
// Instances should be obtained via GetInstance.
|
||||
explicit StandardMessageCodec(const StandardCodecSerializer* serializer);
|
||||
|
||||
const StandardCodecSerializer* serializer_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_MESSAGE_CODEC_H_
|
||||
@@ -0,0 +1,73 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_METHOD_CODEC_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_METHOD_CODEC_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "encodable_value.h"
|
||||
#include "method_call.h"
|
||||
#include "method_codec.h"
|
||||
#include "standard_codec_serializer.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// An implementation of MethodCodec that uses a binary serialization.
|
||||
class StandardMethodCodec : public MethodCodec<EncodableValue> {
|
||||
public:
|
||||
// Returns an instance of the codec, optionally using a custom serializer to
|
||||
// add support for more types.
|
||||
//
|
||||
// If provided, |serializer| must be long-lived. If no serializer is provided,
|
||||
// the default will be used.
|
||||
//
|
||||
// The instance returned for a given |extension| will be shared, and
|
||||
// any instance returned from this will be long-lived, and can be safely
|
||||
// passed to, e.g., channel constructors.
|
||||
static const StandardMethodCodec& GetInstance(
|
||||
const StandardCodecSerializer* serializer = nullptr);
|
||||
|
||||
~StandardMethodCodec();
|
||||
|
||||
// Prevent copying.
|
||||
StandardMethodCodec(StandardMethodCodec const&) = delete;
|
||||
StandardMethodCodec& operator=(StandardMethodCodec const&) = delete;
|
||||
|
||||
protected:
|
||||
// |flutter::MethodCodec|
|
||||
std::unique_ptr<MethodCall<EncodableValue>> DecodeMethodCallInternal(
|
||||
const uint8_t* message,
|
||||
size_t message_size) const override;
|
||||
|
||||
// |flutter::MethodCodec|
|
||||
std::unique_ptr<std::vector<uint8_t>> EncodeMethodCallInternal(
|
||||
const MethodCall<EncodableValue>& method_call) const override;
|
||||
|
||||
// |flutter::MethodCodec|
|
||||
std::unique_ptr<std::vector<uint8_t>> EncodeSuccessEnvelopeInternal(
|
||||
const EncodableValue* result) const override;
|
||||
|
||||
// |flutter::MethodCodec|
|
||||
std::unique_ptr<std::vector<uint8_t>> EncodeErrorEnvelopeInternal(
|
||||
const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const EncodableValue* error_details) const override;
|
||||
|
||||
// |flutter::MethodCodec|
|
||||
bool DecodeAndProcessResponseEnvelopeInternal(
|
||||
const uint8_t* response,
|
||||
size_t response_size,
|
||||
MethodResult<EncodableValue>* result) const override;
|
||||
|
||||
private:
|
||||
// Instances should be obtained via GetInstance.
|
||||
explicit StandardMethodCodec(const StandardCodecSerializer* serializer);
|
||||
|
||||
const StandardCodecSerializer* serializer_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_METHOD_CODEC_H_
|
||||
@@ -0,0 +1,111 @@
|
||||
// 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_CLIENT_WRAPPER_INCLUDE_FLUTTER_TEXTURE_REGISTRAR_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_TEXTURE_REGISTRAR_H_
|
||||
|
||||
#include <flutter_texture_registrar.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// A pixel buffer texture.
|
||||
class PixelBufferTexture {
|
||||
public:
|
||||
// A callback used for retrieving pixel buffers.
|
||||
typedef std::function<const FlutterDesktopPixelBuffer*(size_t width,
|
||||
size_t height)>
|
||||
CopyBufferCallback;
|
||||
|
||||
// Creates a pixel buffer texture that uses the provided |copy_buffer_cb| to
|
||||
// retrieve the buffer.
|
||||
// As the callback is usually invoked from the render thread, the callee must
|
||||
// take care of proper synchronization. It also needs to be ensured that the
|
||||
// returned buffer isn't released prior to unregistering this texture.
|
||||
explicit PixelBufferTexture(CopyBufferCallback copy_buffer_callback)
|
||||
: copy_buffer_callback_(std::move(copy_buffer_callback)) {}
|
||||
|
||||
// Returns the callback-provided FlutterDesktopPixelBuffer that contains the
|
||||
// actual pixel data. The intended surface size is specified by |width| and
|
||||
// |height|.
|
||||
const FlutterDesktopPixelBuffer* CopyPixelBuffer(size_t width,
|
||||
size_t height) const {
|
||||
return copy_buffer_callback_(width, height);
|
||||
}
|
||||
|
||||
private:
|
||||
const CopyBufferCallback copy_buffer_callback_;
|
||||
};
|
||||
|
||||
// A GPU surface-based texture.
|
||||
class GpuSurfaceTexture {
|
||||
public:
|
||||
// A callback used for retrieving surface descriptors.
|
||||
typedef std::function<
|
||||
const FlutterDesktopGpuSurfaceDescriptor*(size_t width, size_t height)>
|
||||
ObtainDescriptorCallback;
|
||||
|
||||
GpuSurfaceTexture(FlutterDesktopGpuSurfaceType surface_type,
|
||||
ObtainDescriptorCallback obtain_descriptor_callback)
|
||||
: surface_type_(surface_type),
|
||||
obtain_descriptor_callback_(std::move(obtain_descriptor_callback)) {}
|
||||
|
||||
// Returns the callback-provided FlutterDesktopGpuSurfaceDescriptor that
|
||||
// contains the surface handle. The intended surface size is specified by
|
||||
// |width| and |height|.
|
||||
const FlutterDesktopGpuSurfaceDescriptor* ObtainDescriptor(
|
||||
size_t width,
|
||||
size_t height) const {
|
||||
return obtain_descriptor_callback_(width, height);
|
||||
}
|
||||
|
||||
// Gets the surface type.
|
||||
FlutterDesktopGpuSurfaceType surface_type() const { return surface_type_; }
|
||||
|
||||
private:
|
||||
const FlutterDesktopGpuSurfaceType surface_type_;
|
||||
const ObtainDescriptorCallback obtain_descriptor_callback_;
|
||||
};
|
||||
|
||||
// The available texture variants.
|
||||
// Only PixelBufferTexture is currently implemented.
|
||||
// Other variants are expected to be added in the future.
|
||||
typedef std::variant<PixelBufferTexture, GpuSurfaceTexture> TextureVariant;
|
||||
|
||||
// An object keeping track of external textures.
|
||||
//
|
||||
// Thread safety:
|
||||
// It's safe to call the member methods from any thread.
|
||||
class TextureRegistrar {
|
||||
public:
|
||||
virtual ~TextureRegistrar() = default;
|
||||
|
||||
// Registers a |texture| object and returns the ID for that texture.
|
||||
virtual int64_t RegisterTexture(TextureVariant* texture) = 0;
|
||||
|
||||
// Notifies the flutter engine that the texture object corresponding
|
||||
// to |texure_id| needs to render a new frame.
|
||||
//
|
||||
// For PixelBufferTextures, this will effectively make the engine invoke
|
||||
// the callback that was provided upon creating the texture.
|
||||
virtual bool MarkTextureFrameAvailable(int64_t texture_id) = 0;
|
||||
|
||||
// Asynchronously unregisters an existing texture object.
|
||||
// Upon completion, the optional |callback| gets invoked.
|
||||
virtual void UnregisterTexture(int64_t texture_id,
|
||||
std::function<void()> callback) = 0;
|
||||
|
||||
// Unregisters an existing texture object.
|
||||
// DEPRECATED: Use UnregisterTexture(texture_id, optional_callback) instead.
|
||||
virtual bool UnregisterTexture(int64_t texture_id) = 0;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_INCLUDE_FLUTTER_TEXTURE_REGISTRAR_H_
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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 "include/flutter/plugin_registrar.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
||||
#include "binary_messenger_impl.h"
|
||||
#include "include/flutter/engine_method_result.h"
|
||||
#include "include/flutter/method_channel.h"
|
||||
#include "texture_registrar_impl.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// ===== PluginRegistrar =====
|
||||
|
||||
PluginRegistrar::PluginRegistrar(FlutterDesktopPluginRegistrarRef registrar)
|
||||
: registrar_(registrar) {
|
||||
auto core_messenger = FlutterDesktopPluginRegistrarGetMessenger(registrar_);
|
||||
messenger_ = std::make_unique<BinaryMessengerImpl>(core_messenger);
|
||||
|
||||
auto texture_registrar =
|
||||
FlutterDesktopRegistrarGetTextureRegistrar(registrar_);
|
||||
texture_registrar_ =
|
||||
std::make_unique<TextureRegistrarImpl>(texture_registrar);
|
||||
}
|
||||
|
||||
PluginRegistrar::~PluginRegistrar() {
|
||||
// This must always be the first call.
|
||||
ClearPlugins();
|
||||
|
||||
// Explicitly cleared to facilitate testing of destruction order.
|
||||
messenger_.reset();
|
||||
}
|
||||
|
||||
void PluginRegistrar::AddPlugin(std::unique_ptr<Plugin> plugin) {
|
||||
plugins_.insert(std::move(plugin));
|
||||
}
|
||||
|
||||
void PluginRegistrar::ClearPlugins() {
|
||||
plugins_.clear();
|
||||
}
|
||||
|
||||
// ===== PluginRegistrarManager =====
|
||||
|
||||
// static
|
||||
PluginRegistrarManager* PluginRegistrarManager::GetInstance() {
|
||||
static PluginRegistrarManager* instance = new PluginRegistrarManager();
|
||||
return instance;
|
||||
}
|
||||
|
||||
PluginRegistrarManager::PluginRegistrarManager() = default;
|
||||
|
||||
// static
|
||||
void PluginRegistrarManager::OnRegistrarDestroyed(
|
||||
FlutterDesktopPluginRegistrarRef registrar) {
|
||||
GetInstance()->registrars()->erase(registrar);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@@ -0,0 +1,9 @@
|
||||
This code is intended to be built into plugins and applications to provide
|
||||
higher-level, C++ abstractions for interacting with the Flutter library.
|
||||
|
||||
Over time, the goal is to move more of this code into the library in a way that
|
||||
provides a usable ABI (e.g., does not use standard library in the interfaces).
|
||||
|
||||
Note that this wrapper is still in early stages. Expect significant churn in
|
||||
both the APIs and the structure of the wrapper (e.g., the exact set of files
|
||||
that need to be built).
|
||||
@@ -0,0 +1,468 @@
|
||||
// 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 what would normally be standard_codec_serializer.cc,
|
||||
// standard_message_codec.cc, and standard_method_codec.cc. They are grouped
|
||||
// together to simplify use of the client wrapper, since the common case is
|
||||
// that any client that needs one of these files needs all three.
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "byte_buffer_streams.h"
|
||||
#include "include/flutter/standard_codec_serializer.h"
|
||||
#include "include/flutter/standard_message_codec.h"
|
||||
#include "include/flutter/standard_method_codec.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// ===== standard_codec_serializer.h =====
|
||||
|
||||
namespace {
|
||||
|
||||
// The order/values here must match the constants in message_codecs.dart.
|
||||
enum class EncodedType {
|
||||
kNull = 0,
|
||||
kTrue,
|
||||
kFalse,
|
||||
kInt32,
|
||||
kInt64,
|
||||
kLargeInt, // No longer used. If encountered, treat as kString.
|
||||
kFloat64,
|
||||
kString,
|
||||
kUInt8List,
|
||||
kInt32List,
|
||||
kInt64List,
|
||||
kFloat64List,
|
||||
kList,
|
||||
kMap,
|
||||
kFloat32List,
|
||||
};
|
||||
|
||||
// Returns the encoded type that should be written when serializing |value|.
|
||||
EncodedType EncodedTypeForValue(const EncodableValue& value) {
|
||||
switch (value.index()) {
|
||||
case 0:
|
||||
return EncodedType::kNull;
|
||||
case 1:
|
||||
return std::get<bool>(value) ? EncodedType::kTrue : EncodedType::kFalse;
|
||||
case 2:
|
||||
return EncodedType::kInt32;
|
||||
case 3:
|
||||
return EncodedType::kInt64;
|
||||
case 4:
|
||||
return EncodedType::kFloat64;
|
||||
case 5:
|
||||
return EncodedType::kString;
|
||||
case 6:
|
||||
return EncodedType::kUInt8List;
|
||||
case 7:
|
||||
return EncodedType::kInt32List;
|
||||
case 8:
|
||||
return EncodedType::kInt64List;
|
||||
case 9:
|
||||
return EncodedType::kFloat64List;
|
||||
case 10:
|
||||
return EncodedType::kList;
|
||||
case 11:
|
||||
return EncodedType::kMap;
|
||||
case 13:
|
||||
return EncodedType::kFloat32List;
|
||||
}
|
||||
assert(false);
|
||||
return EncodedType::kNull;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
StandardCodecSerializer::StandardCodecSerializer() = default;
|
||||
|
||||
StandardCodecSerializer::~StandardCodecSerializer() = default;
|
||||
|
||||
const StandardCodecSerializer& StandardCodecSerializer::GetInstance() {
|
||||
static StandardCodecSerializer sInstance;
|
||||
return sInstance;
|
||||
};
|
||||
|
||||
EncodableValue StandardCodecSerializer::ReadValue(
|
||||
ByteStreamReader* stream) const {
|
||||
uint8_t type = stream->ReadByte();
|
||||
return ReadValueOfType(type, stream);
|
||||
}
|
||||
|
||||
void StandardCodecSerializer::WriteValue(const EncodableValue& value,
|
||||
ByteStreamWriter* stream) const {
|
||||
stream->WriteByte(static_cast<uint8_t>(EncodedTypeForValue(value)));
|
||||
// TODO(cbracken): Consider replacing this with std::visit.
|
||||
switch (value.index()) {
|
||||
case 0:
|
||||
case 1:
|
||||
// Null and bool are encoded directly in the type.
|
||||
break;
|
||||
case 2:
|
||||
stream->WriteInt32(std::get<int32_t>(value));
|
||||
break;
|
||||
case 3:
|
||||
stream->WriteInt64(std::get<int64_t>(value));
|
||||
break;
|
||||
case 4:
|
||||
stream->WriteAlignment(8);
|
||||
stream->WriteDouble(std::get<double>(value));
|
||||
break;
|
||||
case 5: {
|
||||
const auto& string_value = std::get<std::string>(value);
|
||||
size_t size = string_value.size();
|
||||
WriteSize(size, stream);
|
||||
if (size > 0) {
|
||||
stream->WriteBytes(
|
||||
reinterpret_cast<const uint8_t*>(string_value.data()), size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
WriteVector(std::get<std::vector<uint8_t>>(value), stream);
|
||||
break;
|
||||
case 7:
|
||||
WriteVector(std::get<std::vector<int32_t>>(value), stream);
|
||||
break;
|
||||
case 8:
|
||||
WriteVector(std::get<std::vector<int64_t>>(value), stream);
|
||||
break;
|
||||
case 9:
|
||||
WriteVector(std::get<std::vector<double>>(value), stream);
|
||||
break;
|
||||
case 10: {
|
||||
const auto& list = std::get<EncodableList>(value);
|
||||
WriteSize(list.size(), stream);
|
||||
for (const auto& item : list) {
|
||||
WriteValue(item, stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 11: {
|
||||
const auto& map = std::get<EncodableMap>(value);
|
||||
WriteSize(map.size(), stream);
|
||||
for (const auto& pair : map) {
|
||||
WriteValue(pair.first, stream);
|
||||
WriteValue(pair.second, stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 12:
|
||||
std::cerr
|
||||
<< "Unhandled custom type in StandardCodecSerializer::WriteValue. "
|
||||
<< "Custom types require codec extensions." << std::endl;
|
||||
break;
|
||||
case 13: {
|
||||
WriteVector(std::get<std::vector<float>>(value), stream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EncodableValue StandardCodecSerializer::ReadValueOfType(
|
||||
uint8_t type,
|
||||
ByteStreamReader* stream) const {
|
||||
switch (static_cast<EncodedType>(type)) {
|
||||
case EncodedType::kNull:
|
||||
return EncodableValue();
|
||||
case EncodedType::kTrue:
|
||||
return EncodableValue(true);
|
||||
case EncodedType::kFalse:
|
||||
return EncodableValue(false);
|
||||
case EncodedType::kInt32:
|
||||
return EncodableValue(stream->ReadInt32());
|
||||
case EncodedType::kInt64:
|
||||
return EncodableValue(stream->ReadInt64());
|
||||
case EncodedType::kFloat64:
|
||||
stream->ReadAlignment(8);
|
||||
return EncodableValue(stream->ReadDouble());
|
||||
case EncodedType::kLargeInt:
|
||||
case EncodedType::kString: {
|
||||
size_t size = ReadSize(stream);
|
||||
std::string string_value;
|
||||
string_value.resize(size);
|
||||
stream->ReadBytes(reinterpret_cast<uint8_t*>(&string_value[0]), size);
|
||||
return EncodableValue(string_value);
|
||||
}
|
||||
case EncodedType::kUInt8List:
|
||||
return ReadVector<uint8_t>(stream);
|
||||
case EncodedType::kInt32List:
|
||||
return ReadVector<int32_t>(stream);
|
||||
case EncodedType::kInt64List:
|
||||
return ReadVector<int64_t>(stream);
|
||||
case EncodedType::kFloat64List:
|
||||
return ReadVector<double>(stream);
|
||||
case EncodedType::kList: {
|
||||
size_t length = ReadSize(stream);
|
||||
EncodableList list_value;
|
||||
list_value.reserve(length);
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
list_value.push_back(ReadValue(stream));
|
||||
}
|
||||
return EncodableValue(list_value);
|
||||
}
|
||||
case EncodedType::kMap: {
|
||||
size_t length = ReadSize(stream);
|
||||
EncodableMap map_value;
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
EncodableValue key = ReadValue(stream);
|
||||
EncodableValue value = ReadValue(stream);
|
||||
map_value.emplace(std::move(key), std::move(value));
|
||||
}
|
||||
return EncodableValue(map_value);
|
||||
}
|
||||
case EncodedType::kFloat32List: {
|
||||
return ReadVector<float>(stream);
|
||||
}
|
||||
}
|
||||
std::cerr << "Unknown type in StandardCodecSerializer::ReadValueOfType: "
|
||||
<< static_cast<int>(type) << std::endl;
|
||||
return EncodableValue();
|
||||
}
|
||||
|
||||
size_t StandardCodecSerializer::ReadSize(ByteStreamReader* stream) const {
|
||||
uint8_t byte = stream->ReadByte();
|
||||
if (byte < 254) {
|
||||
return byte;
|
||||
} else if (byte == 254) {
|
||||
uint16_t value = 0;
|
||||
stream->ReadBytes(reinterpret_cast<uint8_t*>(&value), 2);
|
||||
return value;
|
||||
} else {
|
||||
uint32_t value = 0;
|
||||
stream->ReadBytes(reinterpret_cast<uint8_t*>(&value), 4);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
void StandardCodecSerializer::WriteSize(size_t size,
|
||||
ByteStreamWriter* stream) const {
|
||||
if (size < 254) {
|
||||
stream->WriteByte(static_cast<uint8_t>(size));
|
||||
} else if (size <= 0xffff) {
|
||||
stream->WriteByte(254);
|
||||
uint16_t value = static_cast<uint16_t>(size);
|
||||
stream->WriteBytes(reinterpret_cast<uint8_t*>(&value), 2);
|
||||
} else {
|
||||
stream->WriteByte(255);
|
||||
uint32_t value = static_cast<uint32_t>(size);
|
||||
stream->WriteBytes(reinterpret_cast<uint8_t*>(&value), 4);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
EncodableValue StandardCodecSerializer::ReadVector(
|
||||
ByteStreamReader* stream) const {
|
||||
size_t count = ReadSize(stream);
|
||||
std::vector<T> vector;
|
||||
vector.resize(count);
|
||||
uint8_t type_size = static_cast<uint8_t>(sizeof(T));
|
||||
if (type_size > 1) {
|
||||
stream->ReadAlignment(type_size);
|
||||
}
|
||||
stream->ReadBytes(reinterpret_cast<uint8_t*>(vector.data()),
|
||||
count * type_size);
|
||||
return EncodableValue(vector);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void StandardCodecSerializer::WriteVector(const std::vector<T> vector,
|
||||
ByteStreamWriter* stream) const {
|
||||
size_t count = vector.size();
|
||||
WriteSize(count, stream);
|
||||
if (count == 0) {
|
||||
return;
|
||||
}
|
||||
uint8_t type_size = static_cast<uint8_t>(sizeof(T));
|
||||
if (type_size > 1) {
|
||||
stream->WriteAlignment(type_size);
|
||||
}
|
||||
stream->WriteBytes(reinterpret_cast<const uint8_t*>(vector.data()),
|
||||
count * type_size);
|
||||
}
|
||||
|
||||
// ===== standard_message_codec.h =====
|
||||
|
||||
// static
|
||||
const StandardMessageCodec& StandardMessageCodec::GetInstance(
|
||||
const StandardCodecSerializer* serializer) {
|
||||
if (!serializer) {
|
||||
serializer = &StandardCodecSerializer::GetInstance();
|
||||
}
|
||||
static auto* sInstances = new std::map<const StandardCodecSerializer*,
|
||||
std::unique_ptr<StandardMessageCodec>>;
|
||||
auto it = sInstances->find(serializer);
|
||||
if (it == sInstances->end()) {
|
||||
// Uses new due to private constructor (to prevent API clients from
|
||||
// accidentally passing temporary codec instances to channels).
|
||||
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
auto emplace_result = sInstances->emplace(
|
||||
serializer, std::unique_ptr<StandardMessageCodec>(
|
||||
new StandardMessageCodec(serializer)));
|
||||
it = emplace_result.first;
|
||||
}
|
||||
return *(it->second);
|
||||
}
|
||||
|
||||
StandardMessageCodec::StandardMessageCodec(
|
||||
const StandardCodecSerializer* serializer)
|
||||
: serializer_(serializer) {}
|
||||
|
||||
StandardMessageCodec::~StandardMessageCodec() = default;
|
||||
|
||||
std::unique_ptr<EncodableValue> StandardMessageCodec::DecodeMessageInternal(
|
||||
const uint8_t* binary_message,
|
||||
size_t message_size) const {
|
||||
if (!binary_message) {
|
||||
return std::make_unique<EncodableValue>();
|
||||
}
|
||||
ByteBufferStreamReader stream(binary_message, message_size);
|
||||
return std::make_unique<EncodableValue>(serializer_->ReadValue(&stream));
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<uint8_t>>
|
||||
StandardMessageCodec::EncodeMessageInternal(
|
||||
const EncodableValue& message) const {
|
||||
auto encoded = std::make_unique<std::vector<uint8_t>>();
|
||||
ByteBufferStreamWriter stream(encoded.get());
|
||||
serializer_->WriteValue(message, &stream);
|
||||
return encoded;
|
||||
}
|
||||
|
||||
// ===== standard_method_codec.h =====
|
||||
|
||||
// static
|
||||
const StandardMethodCodec& StandardMethodCodec::GetInstance(
|
||||
const StandardCodecSerializer* serializer) {
|
||||
if (!serializer) {
|
||||
serializer = &StandardCodecSerializer::GetInstance();
|
||||
}
|
||||
static auto* sInstances = new std::map<const StandardCodecSerializer*,
|
||||
std::unique_ptr<StandardMethodCodec>>;
|
||||
auto it = sInstances->find(serializer);
|
||||
if (it == sInstances->end()) {
|
||||
// Uses new due to private constructor (to prevent API clients from
|
||||
// accidentally passing temporary codec instances to channels).
|
||||
// NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
|
||||
auto emplace_result = sInstances->emplace(
|
||||
serializer, std::unique_ptr<StandardMethodCodec>(
|
||||
new StandardMethodCodec(serializer)));
|
||||
it = emplace_result.first;
|
||||
}
|
||||
return *(it->second);
|
||||
}
|
||||
|
||||
StandardMethodCodec::StandardMethodCodec(
|
||||
const StandardCodecSerializer* serializer)
|
||||
: serializer_(serializer) {}
|
||||
|
||||
StandardMethodCodec::~StandardMethodCodec() = default;
|
||||
|
||||
std::unique_ptr<MethodCall<EncodableValue>>
|
||||
StandardMethodCodec::DecodeMethodCallInternal(const uint8_t* message,
|
||||
size_t message_size) const {
|
||||
ByteBufferStreamReader stream(message, message_size);
|
||||
EncodableValue method_name_value = serializer_->ReadValue(&stream);
|
||||
const auto* method_name = std::get_if<std::string>(&method_name_value);
|
||||
if (!method_name) {
|
||||
std::cerr << "Invalid method call; method name is not a string."
|
||||
<< std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
auto arguments =
|
||||
std::make_unique<EncodableValue>(serializer_->ReadValue(&stream));
|
||||
return std::make_unique<MethodCall<EncodableValue>>(*method_name,
|
||||
std::move(arguments));
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<uint8_t>>
|
||||
StandardMethodCodec::EncodeMethodCallInternal(
|
||||
const MethodCall<EncodableValue>& method_call) const {
|
||||
auto encoded = std::make_unique<std::vector<uint8_t>>();
|
||||
ByteBufferStreamWriter stream(encoded.get());
|
||||
serializer_->WriteValue(EncodableValue(method_call.method_name()), &stream);
|
||||
if (method_call.arguments()) {
|
||||
serializer_->WriteValue(*method_call.arguments(), &stream);
|
||||
} else {
|
||||
serializer_->WriteValue(EncodableValue(), &stream);
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<uint8_t>>
|
||||
StandardMethodCodec::EncodeSuccessEnvelopeInternal(
|
||||
const EncodableValue* result) const {
|
||||
auto encoded = std::make_unique<std::vector<uint8_t>>();
|
||||
ByteBufferStreamWriter stream(encoded.get());
|
||||
stream.WriteByte(0);
|
||||
if (result) {
|
||||
serializer_->WriteValue(*result, &stream);
|
||||
} else {
|
||||
serializer_->WriteValue(EncodableValue(), &stream);
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
std::unique_ptr<std::vector<uint8_t>>
|
||||
StandardMethodCodec::EncodeErrorEnvelopeInternal(
|
||||
const std::string& error_code,
|
||||
const std::string& error_message,
|
||||
const EncodableValue* error_details) const {
|
||||
auto encoded = std::make_unique<std::vector<uint8_t>>();
|
||||
ByteBufferStreamWriter stream(encoded.get());
|
||||
stream.WriteByte(1);
|
||||
serializer_->WriteValue(EncodableValue(error_code), &stream);
|
||||
if (error_message.empty()) {
|
||||
serializer_->WriteValue(EncodableValue(), &stream);
|
||||
} else {
|
||||
serializer_->WriteValue(EncodableValue(error_message), &stream);
|
||||
}
|
||||
if (error_details) {
|
||||
serializer_->WriteValue(*error_details, &stream);
|
||||
} else {
|
||||
serializer_->WriteValue(EncodableValue(), &stream);
|
||||
}
|
||||
return encoded;
|
||||
}
|
||||
|
||||
bool StandardMethodCodec::DecodeAndProcessResponseEnvelopeInternal(
|
||||
const uint8_t* response,
|
||||
size_t response_size,
|
||||
MethodResult<EncodableValue>* result) const {
|
||||
ByteBufferStreamReader stream(response, response_size);
|
||||
uint8_t flag = stream.ReadByte();
|
||||
switch (flag) {
|
||||
case 0: {
|
||||
EncodableValue value = serializer_->ReadValue(&stream);
|
||||
if (value.IsNull()) {
|
||||
result->Success();
|
||||
} else {
|
||||
result->Success(value);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case 1: {
|
||||
EncodableValue code = serializer_->ReadValue(&stream);
|
||||
EncodableValue message = serializer_->ReadValue(&stream);
|
||||
EncodableValue details = serializer_->ReadValue(&stream);
|
||||
const std::string& message_string =
|
||||
message.IsNull() ? "" : std::get<std::string>(message);
|
||||
if (details.IsNull()) {
|
||||
result->Error(std::get<std::string>(code), message_string);
|
||||
} else {
|
||||
result->Error(std::get<std::string>(code), message_string, details);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@@ -0,0 +1,44 @@
|
||||
// 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_CLIENT_WRAPPER_TEXTURE_REGISTRAR_IMPL_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_TEXTURE_REGISTRAR_IMPL_H_
|
||||
|
||||
#include "include/flutter/texture_registrar.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// Wrapper around a FlutterDesktopTextureRegistrarRef that implements the
|
||||
// TextureRegistrar API.
|
||||
class TextureRegistrarImpl : public TextureRegistrar {
|
||||
public:
|
||||
explicit TextureRegistrarImpl(
|
||||
FlutterDesktopTextureRegistrarRef texture_registrar_ref);
|
||||
virtual ~TextureRegistrarImpl();
|
||||
|
||||
// Prevent copying.
|
||||
TextureRegistrarImpl(TextureRegistrarImpl const&) = delete;
|
||||
TextureRegistrarImpl& operator=(TextureRegistrarImpl const&) = delete;
|
||||
|
||||
// |flutter::TextureRegistrar|
|
||||
int64_t RegisterTexture(TextureVariant* texture) override;
|
||||
|
||||
// |flutter::TextureRegistrar|
|
||||
bool MarkTextureFrameAvailable(int64_t texture_id) override;
|
||||
|
||||
// |flutter::TextureRegistrar|
|
||||
void UnregisterTexture(int64_t texture_id,
|
||||
std::function<void()> callback) override;
|
||||
|
||||
// |flutter::TextureRegistrar|
|
||||
bool UnregisterTexture(int64_t texture_id) override;
|
||||
|
||||
private:
|
||||
// Handle for interacting with the C API.
|
||||
FlutterDesktopTextureRegistrarRef texture_registrar_ref_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_CLIENT_WRAPPER_TEXTURE_REGISTRAR_IMPL_H_
|
||||
@@ -0,0 +1,28 @@
|
||||
// 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_PUBLIC_FLUTTER_EXPORT_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_EXPORT_H_
|
||||
|
||||
#ifdef FLUTTER_DESKTOP_LIBRARY
|
||||
|
||||
// Add visibility/export annotations when building the library.
|
||||
#ifdef _WIN32
|
||||
#define FLUTTER_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define FLUTTER_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#else // FLUTTER_DESKTOP_LIBRARY
|
||||
|
||||
// Add import annotations when consuming the library.
|
||||
#ifdef _WIN32
|
||||
#define FLUTTER_EXPORT __declspec(dllimport)
|
||||
#else
|
||||
#define FLUTTER_EXPORT
|
||||
#endif
|
||||
|
||||
#endif // FLUTTER_DESKTOP_LIBRARY
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_EXPORT_H_
|
||||
@@ -0,0 +1,144 @@
|
||||
// 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_PUBLIC_FLUTTER_MESSENGER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_MESSENGER_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "flutter_export.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif // defined(__cplusplus)
|
||||
|
||||
// Opaque reference to a Flutter engine messenger.
|
||||
typedef struct FlutterDesktopMessenger* FlutterDesktopMessengerRef;
|
||||
|
||||
// Opaque handle for tracking responses to messages.
|
||||
typedef struct _FlutterPlatformMessageResponseHandle
|
||||
FlutterDesktopMessageResponseHandle;
|
||||
|
||||
// The callback expected as a response of a binary message.
|
||||
typedef void (*FlutterDesktopBinaryReply)(const uint8_t* data,
|
||||
size_t data_size,
|
||||
void* user_data);
|
||||
|
||||
// A message received from Flutter.
|
||||
typedef struct {
|
||||
// Size of this struct as created by Flutter.
|
||||
size_t struct_size;
|
||||
// The name of the channel used for this message.
|
||||
const char* channel;
|
||||
// The raw message data.
|
||||
const uint8_t* message;
|
||||
// The length of |message|.
|
||||
size_t message_size;
|
||||
// The response handle. If non-null, the receiver of this message must call
|
||||
// FlutterDesktopSendMessageResponse exactly once with this handle.
|
||||
const FlutterDesktopMessageResponseHandle* response_handle;
|
||||
} FlutterDesktopMessage;
|
||||
|
||||
// Function pointer type for message handler callback registration.
|
||||
//
|
||||
// The user data will be whatever was passed to FlutterDesktopSetMessageHandler
|
||||
// for the channel the message is received on.
|
||||
typedef void (*FlutterDesktopMessageCallback)(
|
||||
FlutterDesktopMessengerRef /* messenger */,
|
||||
const FlutterDesktopMessage* /* message*/,
|
||||
void* /* user data */);
|
||||
|
||||
// Sends a binary message to the Flutter side on the specified channel.
|
||||
FLUTTER_EXPORT bool FlutterDesktopMessengerSend(
|
||||
FlutterDesktopMessengerRef messenger,
|
||||
const char* channel,
|
||||
const uint8_t* message,
|
||||
const size_t message_size);
|
||||
|
||||
// Sends a binary message to the Flutter side on the specified channel.
|
||||
// The |reply| callback will be executed when a response is received.
|
||||
FLUTTER_EXPORT bool FlutterDesktopMessengerSendWithReply(
|
||||
FlutterDesktopMessengerRef messenger,
|
||||
const char* channel,
|
||||
const uint8_t* message,
|
||||
const size_t message_size,
|
||||
const FlutterDesktopBinaryReply reply,
|
||||
void* user_data);
|
||||
|
||||
// Sends a reply to a FlutterDesktopMessage for the given response handle.
|
||||
//
|
||||
// Once this has been called, |handle| is invalid and must not be used again.
|
||||
FLUTTER_EXPORT void FlutterDesktopMessengerSendResponse(
|
||||
FlutterDesktopMessengerRef messenger,
|
||||
const FlutterDesktopMessageResponseHandle* handle,
|
||||
const uint8_t* data,
|
||||
size_t data_length);
|
||||
|
||||
// Registers a callback function for incoming binary messages from the Flutter
|
||||
// side on the specified channel.
|
||||
//
|
||||
// Replaces any existing callback. Provide a null handler to unregister the
|
||||
// existing callback.
|
||||
//
|
||||
// If |user_data| is provided, it will be passed in |callback| calls.
|
||||
FLUTTER_EXPORT void FlutterDesktopMessengerSetCallback(
|
||||
FlutterDesktopMessengerRef messenger,
|
||||
const char* channel,
|
||||
FlutterDesktopMessageCallback callback,
|
||||
void* user_data);
|
||||
|
||||
// Increments the reference count for the |messenger|.
|
||||
//
|
||||
// Operation is thread-safe.
|
||||
//
|
||||
// See also: |FlutterDesktopMessengerRelease|
|
||||
FLUTTER_EXPORT FlutterDesktopMessengerRef
|
||||
FlutterDesktopMessengerAddRef(FlutterDesktopMessengerRef messenger);
|
||||
|
||||
// Decrements the reference count for the |messenger|.
|
||||
//
|
||||
// Operation is thread-safe.
|
||||
//
|
||||
// See also: |FlutterDesktopMessengerAddRef|
|
||||
FLUTTER_EXPORT void FlutterDesktopMessengerRelease(
|
||||
FlutterDesktopMessengerRef messenger);
|
||||
|
||||
// Returns `true` if the |FlutterDesktopMessengerRef| still references a running
|
||||
// engine.
|
||||
//
|
||||
// This check should be made inside of a |FlutterDesktopMessengerLock| and
|
||||
// before any other calls are made to the FlutterDesktopMessengerRef when using
|
||||
// it from a thread other than the platform thread.
|
||||
FLUTTER_EXPORT bool FlutterDesktopMessengerIsAvailable(
|
||||
FlutterDesktopMessengerRef messenger);
|
||||
|
||||
// Locks the `FlutterDesktopMessengerRef` ensuring that
|
||||
// |FlutterDesktopMessengerIsAvailable| does not change while locked.
|
||||
//
|
||||
// All calls to the FlutterDesktopMessengerRef from threads other than the
|
||||
// platform thread should happen inside of a lock.
|
||||
//
|
||||
// Operation is thread-safe.
|
||||
//
|
||||
// Returns the |messenger| value.
|
||||
//
|
||||
// See also: |FlutterDesktopMessengerUnlock|
|
||||
FLUTTER_EXPORT FlutterDesktopMessengerRef
|
||||
FlutterDesktopMessengerLock(FlutterDesktopMessengerRef messenger);
|
||||
|
||||
// Unlocks the `FlutterDesktopMessengerRef`.
|
||||
//
|
||||
// Operation is thread-safe.
|
||||
//
|
||||
// See also: |FlutterDesktopMessengerLock|
|
||||
FLUTTER_EXPORT void FlutterDesktopMessengerUnlock(
|
||||
FlutterDesktopMessengerRef messenger);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_MESSENGER_H_
|
||||
@@ -0,0 +1,45 @@
|
||||
// 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_PUBLIC_FLUTTER_PLUGIN_REGISTRAR_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_PLUGIN_REGISTRAR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "flutter_export.h"
|
||||
#include "flutter_messenger.h"
|
||||
#include "flutter_texture_registrar.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif // defined(__cplusplus)
|
||||
|
||||
// Opaque reference to a plugin registrar.
|
||||
typedef struct FlutterDesktopPluginRegistrar* FlutterDesktopPluginRegistrarRef;
|
||||
|
||||
// Function pointer type for registrar destruction callback.
|
||||
typedef void (*FlutterDesktopOnPluginRegistrarDestroyed)(
|
||||
FlutterDesktopPluginRegistrarRef);
|
||||
|
||||
// Returns the engine messenger associated with this registrar.
|
||||
FLUTTER_EXPORT FlutterDesktopMessengerRef
|
||||
FlutterDesktopPluginRegistrarGetMessenger(
|
||||
FlutterDesktopPluginRegistrarRef registrar);
|
||||
|
||||
// Returns the texture registrar associated with this registrar.
|
||||
FLUTTER_EXPORT FlutterDesktopTextureRegistrarRef
|
||||
FlutterDesktopRegistrarGetTextureRegistrar(
|
||||
FlutterDesktopPluginRegistrarRef registrar);
|
||||
|
||||
// Registers a callback to be called when the plugin registrar is destroyed.
|
||||
FLUTTER_EXPORT void FlutterDesktopPluginRegistrarSetDestructionHandler(
|
||||
FlutterDesktopPluginRegistrarRef registrar,
|
||||
FlutterDesktopOnPluginRegistrarDestroyed callback);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_PLUGIN_REGISTRAR_H_
|
||||
@@ -0,0 +1,187 @@
|
||||
// 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_PUBLIC_FLUTTER_TEXTURE_REGISTRAR_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_TEXTURE_REGISTRAR_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "flutter_export.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct FlutterDesktopTextureRegistrar;
|
||||
// Opaque reference to a texture registrar.
|
||||
typedef struct FlutterDesktopTextureRegistrar*
|
||||
FlutterDesktopTextureRegistrarRef;
|
||||
|
||||
// Possible values for the type specified in FlutterDesktopTextureInfo.
|
||||
// Additional types may be added in the future.
|
||||
typedef enum {
|
||||
// A Pixel buffer-based texture.
|
||||
kFlutterDesktopPixelBufferTexture,
|
||||
// A platform-specific GPU surface-backed texture.
|
||||
kFlutterDesktopGpuSurfaceTexture
|
||||
} FlutterDesktopTextureType;
|
||||
|
||||
// Supported GPU surface types.
|
||||
typedef enum {
|
||||
// Uninitialized.
|
||||
kFlutterDesktopGpuSurfaceTypeNone,
|
||||
// A DXGI shared texture handle (Windows only).
|
||||
// See
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiresource-getsharedhandle
|
||||
kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle,
|
||||
// A |ID3D11Texture2D| (Windows only).
|
||||
kFlutterDesktopGpuSurfaceTypeD3d11Texture2D
|
||||
} FlutterDesktopGpuSurfaceType;
|
||||
|
||||
// Supported pixel formats.
|
||||
typedef enum {
|
||||
// Uninitialized.
|
||||
kFlutterDesktopPixelFormatNone,
|
||||
// Represents a 32-bit RGBA color format with 8 bits each for red, green, blue
|
||||
// and alpha.
|
||||
kFlutterDesktopPixelFormatRGBA8888,
|
||||
// Represents a 32-bit BGRA color format with 8 bits each for blue, green, red
|
||||
// and alpha.
|
||||
kFlutterDesktopPixelFormatBGRA8888
|
||||
} FlutterDesktopPixelFormat;
|
||||
|
||||
// An image buffer object.
|
||||
typedef struct {
|
||||
// The pixel data buffer.
|
||||
const uint8_t* buffer;
|
||||
// Width of the pixel buffer.
|
||||
size_t width;
|
||||
// Height of the pixel buffer.
|
||||
size_t height;
|
||||
// An optional callback that gets invoked when the |buffer| can be released.
|
||||
void (*release_callback)(void* release_context);
|
||||
// Opaque data passed to |release_callback|.
|
||||
void* release_context;
|
||||
} FlutterDesktopPixelBuffer;
|
||||
|
||||
// A GPU surface descriptor.
|
||||
typedef struct {
|
||||
// The size of this struct. Must be
|
||||
// sizeof(FlutterDesktopGpuSurfaceDescriptor).
|
||||
size_t struct_size;
|
||||
// The surface handle. The expected type depends on the
|
||||
// |FlutterDesktopGpuSurfaceType|.
|
||||
//
|
||||
// Provide a |ID3D11Texture2D*| when using
|
||||
// |kFlutterDesktopGpuSurfaceTypeD3d11Texture2D| or a |HANDLE| when using
|
||||
// |kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle|.
|
||||
//
|
||||
// The referenced resource needs to stay valid until it has been opened by
|
||||
// Flutter. Consider incrementing the resource's reference count in the
|
||||
// |FlutterDesktopGpuSurfaceTextureCallback| and registering a
|
||||
// |release_callback| for decrementing the reference count once it has been
|
||||
// opened.
|
||||
void* handle;
|
||||
// The physical width.
|
||||
size_t width;
|
||||
// The physical height.
|
||||
size_t height;
|
||||
// The visible width.
|
||||
// It might be less or equal to the physical |width|.
|
||||
size_t visible_width;
|
||||
// The visible height.
|
||||
// It might be less or equal to the physical |height|.
|
||||
size_t visible_height;
|
||||
// The pixel format which might be optional depending on the surface type.
|
||||
FlutterDesktopPixelFormat format;
|
||||
// An optional callback that gets invoked when the |handle| has been opened.
|
||||
void (*release_callback)(void* release_context);
|
||||
// Opaque data passed to |release_callback|.
|
||||
void* release_context;
|
||||
} FlutterDesktopGpuSurfaceDescriptor;
|
||||
|
||||
// The pixel buffer copy callback definition provided to
|
||||
// the Flutter engine to copy the texture.
|
||||
// It is invoked with the intended surface size specified by |width| and
|
||||
// |height| and the |user_data| held by
|
||||
// |FlutterDesktopPixelBufferTextureConfig|.
|
||||
//
|
||||
// As this is usually called from the render thread, the callee must take
|
||||
// care of proper synchronization. It also needs to be ensured that the
|
||||
// returned |FlutterDesktopPixelBuffer| isn't released prior to unregistering
|
||||
// the corresponding texture.
|
||||
typedef const FlutterDesktopPixelBuffer* (
|
||||
*FlutterDesktopPixelBufferTextureCallback)(size_t width,
|
||||
size_t height,
|
||||
void* user_data);
|
||||
|
||||
// The GPU surface callback definition provided to the Flutter engine to obtain
|
||||
// the surface. It is invoked with the intended surface size specified by
|
||||
// |width| and |height| and the |user_data| held by
|
||||
// |FlutterDesktopGpuSurfaceTextureConfig|.
|
||||
typedef const FlutterDesktopGpuSurfaceDescriptor* (
|
||||
*FlutterDesktopGpuSurfaceTextureCallback)(size_t width,
|
||||
size_t height,
|
||||
void* user_data);
|
||||
|
||||
// An object used to configure pixel buffer textures.
|
||||
typedef struct {
|
||||
// The callback used by the engine to copy the pixel buffer object.
|
||||
FlutterDesktopPixelBufferTextureCallback callback;
|
||||
// Opaque data that will get passed to the provided |callback|.
|
||||
void* user_data;
|
||||
} FlutterDesktopPixelBufferTextureConfig;
|
||||
|
||||
// An object used to configure GPU-surface textures.
|
||||
typedef struct {
|
||||
// The size of this struct. Must be
|
||||
// sizeof(FlutterDesktopGpuSurfaceTextureConfig).
|
||||
size_t struct_size;
|
||||
// The concrete surface type (e.g.
|
||||
// |kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle|)
|
||||
FlutterDesktopGpuSurfaceType type;
|
||||
// The callback used by the engine to obtain the surface descriptor.
|
||||
FlutterDesktopGpuSurfaceTextureCallback callback;
|
||||
// Opaque data that will get passed to the provided |callback|.
|
||||
void* user_data;
|
||||
} FlutterDesktopGpuSurfaceTextureConfig;
|
||||
|
||||
typedef struct {
|
||||
FlutterDesktopTextureType type;
|
||||
union {
|
||||
FlutterDesktopPixelBufferTextureConfig pixel_buffer_config;
|
||||
FlutterDesktopGpuSurfaceTextureConfig gpu_surface_config;
|
||||
};
|
||||
} FlutterDesktopTextureInfo;
|
||||
|
||||
// Registers a new texture with the Flutter engine and returns the texture ID.
|
||||
// This function can be called from any thread.
|
||||
FLUTTER_EXPORT int64_t FlutterDesktopTextureRegistrarRegisterExternalTexture(
|
||||
FlutterDesktopTextureRegistrarRef texture_registrar,
|
||||
const FlutterDesktopTextureInfo* info);
|
||||
|
||||
// Asynchronously unregisters the texture identified by |texture_id| from the
|
||||
// Flutter engine.
|
||||
// An optional |callback| gets invoked upon completion.
|
||||
// This function can be called from any thread.
|
||||
FLUTTER_EXPORT void FlutterDesktopTextureRegistrarUnregisterExternalTexture(
|
||||
FlutterDesktopTextureRegistrarRef texture_registrar,
|
||||
int64_t texture_id,
|
||||
void (*callback)(void* user_data),
|
||||
void* user_data);
|
||||
|
||||
// Marks that a new texture frame is available for a given |texture_id|.
|
||||
// Returns true on success or false if the specified texture doesn't exist.
|
||||
// This function can be called from any thread.
|
||||
FLUTTER_EXPORT bool
|
||||
FlutterDesktopTextureRegistrarMarkExternalTextureFrameAvailable(
|
||||
FlutterDesktopTextureRegistrarRef texture_registrar,
|
||||
int64_t texture_id);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_COMMON_PUBLIC_FLUTTER_TEXTURE_REGISTRAR_H_
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,332 @@
|
||||
// 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_PUBLIC_FLUTTER_WINDOWS_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_PUBLIC_FLUTTER_WINDOWS_H_
|
||||
|
||||
#include <dxgi.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "flutter_export.h"
|
||||
#include "flutter_messenger.h"
|
||||
#include "flutter_plugin_registrar.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*VoidCallback)(void* /* user data */);
|
||||
|
||||
// Opaque reference to a Flutter view controller.
|
||||
struct FlutterDesktopViewController;
|
||||
typedef struct FlutterDesktopViewController* FlutterDesktopViewControllerRef;
|
||||
|
||||
// Opaque reference to a Flutter window.
|
||||
struct FlutterDesktopView;
|
||||
typedef struct FlutterDesktopView* FlutterDesktopViewRef;
|
||||
|
||||
// Opaque reference to a Flutter engine instance.
|
||||
struct FlutterDesktopEngine;
|
||||
typedef struct FlutterDesktopEngine* FlutterDesktopEngineRef;
|
||||
|
||||
// The unique identifier for a view.
|
||||
typedef int64_t FlutterDesktopViewId;
|
||||
|
||||
// Configures how the Flutter engine selects a GPU.
|
||||
typedef enum {
|
||||
// No preference.
|
||||
NoPreference,
|
||||
// Prefer energy efficiency over performance, such as an integrated GPU.
|
||||
// This falls back to a high performance GPU if no low power GPU is
|
||||
// available.
|
||||
LowPowerPreference,
|
||||
} FlutterDesktopGpuPreference;
|
||||
|
||||
// Configures the thread policy for running the UI isolate.
|
||||
typedef enum {
|
||||
// Default value. Currently will run the UI isolate on separate thread,
|
||||
// later will be changed to running the UI isolate on platform thread.
|
||||
Default,
|
||||
// Run the UI isolate on platform thread.
|
||||
RunOnPlatformThread,
|
||||
// Run the UI isolate on a separate thread.
|
||||
RunOnSeparateThread,
|
||||
} FlutterDesktopUIThreadPolicy;
|
||||
|
||||
// Properties for configuring a Flutter engine instance.
|
||||
typedef struct {
|
||||
// The path to the flutter_assets folder for the application to be run.
|
||||
// This can either be an absolute path or a path relative to the directory
|
||||
// containing the executable.
|
||||
const wchar_t* assets_path;
|
||||
|
||||
// The path to the icudtl.dat file for the version of Flutter you are using.
|
||||
// This can either be an absolute path or a path relative to the directory
|
||||
// containing the executable.
|
||||
const wchar_t* icu_data_path;
|
||||
|
||||
// The path to the AOT library file for your application, if any.
|
||||
// This can either be an absolute path or a path relative to the directory
|
||||
// containing the executable. This can be nullptr for a non-AOT build, as
|
||||
// it will be ignored in that case.
|
||||
const wchar_t* aot_library_path;
|
||||
|
||||
// The name of the top-level Dart entrypoint function. If null or the empty
|
||||
// string, 'main' is assumed. If a custom entrypoint is used, this parameter
|
||||
// must specifiy the name of a top-level function in the same Dart library as
|
||||
// the app's main() function. Custom entrypoint functions must be decorated
|
||||
// with `@pragma('vm:entry-point')` to ensure the method is not tree-shaken
|
||||
// by the Dart compiler.
|
||||
const char* dart_entrypoint;
|
||||
|
||||
// Number of elements in the array passed in as dart_entrypoint_argv.
|
||||
int dart_entrypoint_argc;
|
||||
|
||||
// Array of Dart entrypoint arguments. This is deep copied during the call
|
||||
// to FlutterDesktopEngineCreate.
|
||||
const char** dart_entrypoint_argv;
|
||||
|
||||
// GPU choice preference
|
||||
FlutterDesktopGpuPreference gpu_preference;
|
||||
|
||||
// Policy for the thread that runs UI isolate.
|
||||
FlutterDesktopUIThreadPolicy ui_thread_policy;
|
||||
} FlutterDesktopEngineProperties;
|
||||
|
||||
// ========== View Controller ==========
|
||||
|
||||
// Creates a view that hosts and displays the given engine instance.
|
||||
//
|
||||
// This takes ownership of |engine|, so FlutterDesktopEngineDestroy should no
|
||||
// longer be called on it, as it will be called internally when the view
|
||||
// controller is destroyed. If creating the view controller fails, the engine
|
||||
// will be destroyed immediately.
|
||||
//
|
||||
// If |engine| is not already running, the view controller will start running
|
||||
// it automatically before displaying the window.
|
||||
//
|
||||
// The caller owns the returned reference, and is responsible for calling
|
||||
// FlutterDesktopViewControllerDestroy. Returns a null pointer in the event of
|
||||
// an error.
|
||||
//
|
||||
// The Win32 implementation accepts width, height with view hookup explicitly
|
||||
// performed using the caller using HWND parenting.
|
||||
FLUTTER_EXPORT FlutterDesktopViewControllerRef
|
||||
FlutterDesktopViewControllerCreate(int width,
|
||||
int height,
|
||||
FlutterDesktopEngineRef engine);
|
||||
|
||||
// Shuts down the engine instance associated with |controller|, and cleans up
|
||||
// associated state.
|
||||
//
|
||||
// |controller| is no longer valid after this call.
|
||||
FLUTTER_EXPORT void FlutterDesktopViewControllerDestroy(
|
||||
FlutterDesktopViewControllerRef controller);
|
||||
|
||||
// Returns the view controller's view ID.
|
||||
FLUTTER_EXPORT FlutterDesktopViewId FlutterDesktopViewControllerGetViewId(
|
||||
FlutterDesktopViewControllerRef view_controller);
|
||||
|
||||
// Returns the handle for the engine running in FlutterDesktopViewControllerRef.
|
||||
//
|
||||
// Its lifetime is the same as the |controller|'s.
|
||||
FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopViewControllerGetEngine(
|
||||
FlutterDesktopViewControllerRef controller);
|
||||
|
||||
// Returns the view managed by the given controller.
|
||||
FLUTTER_EXPORT FlutterDesktopViewRef
|
||||
FlutterDesktopViewControllerGetView(FlutterDesktopViewControllerRef controller);
|
||||
|
||||
// Requests new frame from the engine and repaints the view.
|
||||
FLUTTER_EXPORT void FlutterDesktopViewControllerForceRedraw(
|
||||
FlutterDesktopViewControllerRef controller);
|
||||
|
||||
// Allows the Flutter engine and any interested plugins an opportunity to
|
||||
// handle the given message.
|
||||
//
|
||||
// If the WindowProc was handled and further handling should stop, this returns
|
||||
// true and |result| will be populated. |result| is not set if returning false.
|
||||
FLUTTER_EXPORT bool FlutterDesktopViewControllerHandleTopLevelWindowProc(
|
||||
FlutterDesktopViewControllerRef controller,
|
||||
HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam,
|
||||
LRESULT* result);
|
||||
|
||||
// ========== Engine ==========
|
||||
|
||||
// Creates a Flutter engine with the given properties.
|
||||
//
|
||||
// The caller owns the returned reference, and is responsible for calling
|
||||
// FlutterDesktopEngineDestroy. The lifetime of |engine_properties| is required
|
||||
// to extend only until the end of this call.
|
||||
FLUTTER_EXPORT FlutterDesktopEngineRef FlutterDesktopEngineCreate(
|
||||
const FlutterDesktopEngineProperties* engine_properties);
|
||||
|
||||
// Shuts down and destroys the given engine instance. Returns true if the
|
||||
// shutdown was successful, or if the engine was not running.
|
||||
//
|
||||
// |engine| is no longer valid after this call.
|
||||
FLUTTER_EXPORT bool FlutterDesktopEngineDestroy(FlutterDesktopEngineRef engine);
|
||||
|
||||
// Starts running the given engine instance.
|
||||
//
|
||||
// The entry_point parameter is deprecated but preserved for
|
||||
// backward-compatibility. If desired, a custom Dart entrypoint function can be
|
||||
// set in the dart_entrypoint field of the FlutterDesktopEngineProperties
|
||||
// struct passed to FlutterDesktopEngineCreate.
|
||||
//
|
||||
// If specified, entry_point must be the name of a top-level function from the
|
||||
// same Dart library that contains the app's main() function, and must be
|
||||
// decorated with `@pragma(vm:entry-point)` to ensure the method is not
|
||||
// tree-shaken by the Dart compiler. If conflicting non-null values are passed
|
||||
// to this function and via the FlutterDesktopEngineProperties struct, the run
|
||||
// will fail.
|
||||
//
|
||||
// Returns false if running the engine failed.
|
||||
FLUTTER_EXPORT bool FlutterDesktopEngineRun(FlutterDesktopEngineRef engine,
|
||||
const char* entry_point);
|
||||
|
||||
// DEPRECATED: This is no longer necessary to call, Flutter will take care of
|
||||
// processing engine messages transparently through DispatchMessage.
|
||||
//
|
||||
// Processes any pending events in the Flutter engine, and returns the
|
||||
// number of nanoseconds until the next scheduled event (or max, if none).
|
||||
//
|
||||
// This should be called on every run of the application-level runloop, and
|
||||
// a wait for native events in the runloop should never be longer than the
|
||||
// last return value from this function.
|
||||
FLUTTER_EXPORT uint64_t
|
||||
FlutterDesktopEngineProcessMessages(FlutterDesktopEngineRef engine);
|
||||
|
||||
FLUTTER_EXPORT void FlutterDesktopEngineReloadSystemFonts(
|
||||
FlutterDesktopEngineRef engine);
|
||||
|
||||
// Returns the plugin registrar handle for the plugin with the given name.
|
||||
//
|
||||
// The name must be unique across the application.
|
||||
FLUTTER_EXPORT FlutterDesktopPluginRegistrarRef
|
||||
FlutterDesktopEngineGetPluginRegistrar(FlutterDesktopEngineRef engine,
|
||||
const char* plugin_name);
|
||||
|
||||
// Returns the messenger associated with the engine.
|
||||
//
|
||||
// This does not provide an owning reference, so should *not* be balanced with a
|
||||
// call to |FlutterDesktopMessengerRelease|.
|
||||
//
|
||||
// Callers should use |FlutterDesktopMessengerAddRef| if the returned pointer
|
||||
// will potentially outlive 'engine', such as when passing it to another thread.
|
||||
FLUTTER_EXPORT FlutterDesktopMessengerRef
|
||||
FlutterDesktopEngineGetMessenger(FlutterDesktopEngineRef engine);
|
||||
|
||||
// Returns the texture registrar associated with the engine.
|
||||
FLUTTER_EXPORT FlutterDesktopTextureRegistrarRef
|
||||
FlutterDesktopEngineGetTextureRegistrar(FlutterDesktopEngineRef engine);
|
||||
|
||||
// Schedule a callback to be called after the next frame is drawn.
|
||||
//
|
||||
// This must be called from the platform thread. The callback is executed only
|
||||
// once on the platform thread.
|
||||
FLUTTER_EXPORT void FlutterDesktopEngineSetNextFrameCallback(
|
||||
FlutterDesktopEngineRef engine,
|
||||
VoidCallback callback,
|
||||
void* user_data);
|
||||
|
||||
// ========== View ==========
|
||||
|
||||
// Returns the backing HWND for manipulation in host application.
|
||||
FLUTTER_EXPORT HWND FlutterDesktopViewGetHWND(FlutterDesktopViewRef view);
|
||||
|
||||
// Returns the DXGI adapter used for rendering or nullptr in case of error.
|
||||
FLUTTER_EXPORT IDXGIAdapter* FlutterDesktopViewGetGraphicsAdapter(
|
||||
FlutterDesktopViewRef view);
|
||||
|
||||
// Called to pass an external window message to the engine for lifecycle
|
||||
// state updates. Non-Flutter windows must call this method in their WndProc
|
||||
// in order to be included in the logic for application lifecycle state
|
||||
// updates. Returns a result if the message should be consumed.
|
||||
FLUTTER_EXPORT bool FlutterDesktopEngineProcessExternalWindowMessage(
|
||||
FlutterDesktopEngineRef engine,
|
||||
HWND hwnd,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam,
|
||||
LRESULT* result);
|
||||
|
||||
// ========== Plugin Registrar (extensions) ==========
|
||||
// These are Windows-specific extensions to flutter_plugin_registrar.h
|
||||
|
||||
// Function pointer type for top level WindowProc delegate registration.
|
||||
//
|
||||
// The user data will be whatever was passed to
|
||||
// FlutterDesktopRegisterTopLevelWindowProcHandler.
|
||||
//
|
||||
// Implementations should populate |result| and return true if the WindowProc
|
||||
// was handled and further handling should stop. |result| is ignored if the
|
||||
// function returns false.
|
||||
typedef bool (*FlutterDesktopWindowProcCallback)(HWND /* hwnd */,
|
||||
UINT /* uMsg */,
|
||||
WPARAM /*wParam*/,
|
||||
LPARAM /* lParam*/,
|
||||
void* /* user data */,
|
||||
LRESULT* result);
|
||||
|
||||
// Returns the implicit view associated with this registrar's engine instance,
|
||||
// or null if there is no implicit view.
|
||||
//
|
||||
// See:
|
||||
// https://api.flutter.dev/flutter/dart-ui/PlatformDispatcher/implicitView.html
|
||||
//
|
||||
// DEPRECATED: Use |FlutterDesktopPluginRegistrarGetViewById| instead.
|
||||
FLUTTER_EXPORT FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetView(
|
||||
FlutterDesktopPluginRegistrarRef registrar);
|
||||
|
||||
// Returns the view associated with the registrar's engine instance, or null if
|
||||
// the view does not exist.
|
||||
FLUTTER_EXPORT FlutterDesktopViewRef FlutterDesktopPluginRegistrarGetViewById(
|
||||
FlutterDesktopPluginRegistrarRef registrar,
|
||||
FlutterDesktopViewId view_id);
|
||||
|
||||
FLUTTER_EXPORT void
|
||||
FlutterDesktopPluginRegistrarRegisterTopLevelWindowProcDelegate(
|
||||
FlutterDesktopPluginRegistrarRef registrar,
|
||||
FlutterDesktopWindowProcCallback delegate,
|
||||
void* user_data);
|
||||
|
||||
FLUTTER_EXPORT void
|
||||
FlutterDesktopPluginRegistrarUnregisterTopLevelWindowProcDelegate(
|
||||
FlutterDesktopPluginRegistrarRef registrar,
|
||||
FlutterDesktopWindowProcCallback delegate);
|
||||
|
||||
// ========== Freestanding Utilities ==========
|
||||
|
||||
// Gets the DPI for a given |hwnd|, depending on the supported APIs per
|
||||
// windows version and DPI awareness mode. If nullptr is passed, returns the DPI
|
||||
// of the primary monitor.
|
||||
//
|
||||
// This uses the same logic and fallback for older Windows versions that is used
|
||||
// internally by Flutter to determine the DPI to use for displaying Flutter
|
||||
// content, so should be used by any code (e.g., in plugins) that translates
|
||||
// between Windows and Dart sizes/offsets.
|
||||
FLUTTER_EXPORT UINT FlutterDesktopGetDpiForHWND(HWND hwnd);
|
||||
|
||||
// Gets the DPI for a given |monitor|. If the API is not available, a default
|
||||
// DPI of 96 is returned.
|
||||
//
|
||||
// See FlutterDesktopGetDpiForHWND for more information.
|
||||
FLUTTER_EXPORT UINT FlutterDesktopGetDpiForMonitor(HMONITOR monitor);
|
||||
|
||||
// Reopens stdout and stderr and resysncs the standard library output streams.
|
||||
// Should be called if output is being directed somewhere in the runner process
|
||||
// (e.g., after an AllocConsole call).
|
||||
FLUTTER_EXPORT void FlutterDesktopResyncOutputStreams();
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_PUBLIC_FLUTTER_WINDOWS_H_
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated code do not commit.
|
||||
file(TO_CMAKE_PATH "C:\\flutter" FLUTTER_ROOT)
|
||||
file(TO_CMAKE_PATH "C:\\Users\\Jacques\\Git\\xtremflow" PROJECT_DIR)
|
||||
|
||||
set(FLUTTER_VERSION "1.0.0+1" PARENT_SCOPE)
|
||||
set(FLUTTER_VERSION_MAJOR 1 PARENT_SCOPE)
|
||||
set(FLUTTER_VERSION_MINOR 0 PARENT_SCOPE)
|
||||
set(FLUTTER_VERSION_PATCH 0 PARENT_SCOPE)
|
||||
set(FLUTTER_VERSION_BUILD 1 PARENT_SCOPE)
|
||||
|
||||
# Environment variables to pass to tool_backend.sh
|
||||
list(APPEND FLUTTER_TOOL_ENVIRONMENT
|
||||
"FLUTTER_ROOT=C:\\flutter"
|
||||
"PROJECT_DIR=C:\\Users\\Jacques\\Git\\xtremflow"
|
||||
"FLUTTER_ROOT=C:\\flutter"
|
||||
"FLUTTER_EPHEMERAL_DIR=C:\\Users\\Jacques\\Git\\xtremflow\\windows\\flutter\\ephemeral"
|
||||
"PROJECT_DIR=C:\\Users\\Jacques\\Git\\xtremflow"
|
||||
"FLUTTER_TARGET=lib\\main.dart"
|
||||
"DART_DEFINES=RkxVVFRFUl9WRVJTSU9OPTMuMzguNQ==,RkxVVFRFUl9DSEFOTkVMPXN0YWJsZQ==,RkxVVFRFUl9HSVRfVVJMPWh0dHBzOi8vZ2l0aHViLmNvbS9mbHV0dGVyL2ZsdXR0ZXIuZ2l0,RkxVVFRFUl9GUkFNRVdPUktfUkVWSVNJT049ZjZmZjE1MjlmZA==,RkxVVFRFUl9FTkdJTkVfUkVWSVNJT049MTUyN2FlMGVjNQ==,RkxVVFRFUl9EQVJUX1ZFUlNJT049My4xMC40"
|
||||
"DART_OBFUSCATION=false"
|
||||
"TRACK_WIDGET_CREATION=true"
|
||||
"TREE_SHAKE_ICONS=true"
|
||||
"PACKAGE_CONFIG=C:\\Users\\Jacques\\Git\\xtremflow\\.dart_tool\\package_config.json"
|
||||
)
|
||||
Binary file not shown.
Reference in new issue
Block a user