mirror of
https://github.com/R0m1k3/xtremflow.git
synced 2026-10-17 12:19:16 +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