diff --git a/app/fonts/Roboto/LICENSE.txt b/app/fonts/Roboto/LICENSE.txt new file mode 100644 index 0000000..75b5248 --- /dev/null +++ b/app/fonts/Roboto/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/app/fonts/Roboto/Roboto-Black.ttf b/app/fonts/Roboto/Roboto-Black.ttf new file mode 100644 index 0000000..51c71bb Binary files /dev/null and b/app/fonts/Roboto/Roboto-Black.ttf differ diff --git a/app/fonts/Roboto/Roboto-BlackItalic.ttf b/app/fonts/Roboto/Roboto-BlackItalic.ttf new file mode 100644 index 0000000..ca20ca3 Binary files /dev/null and b/app/fonts/Roboto/Roboto-BlackItalic.ttf differ diff --git a/app/fonts/Roboto/Roboto-Bold.ttf b/app/fonts/Roboto/Roboto-Bold.ttf new file mode 100644 index 0000000..e612852 Binary files /dev/null and b/app/fonts/Roboto/Roboto-Bold.ttf differ diff --git a/app/fonts/Roboto/Roboto-BoldItalic.ttf b/app/fonts/Roboto/Roboto-BoldItalic.ttf new file mode 100644 index 0000000..677bc04 Binary files /dev/null and b/app/fonts/Roboto/Roboto-BoldItalic.ttf differ diff --git a/app/fonts/Roboto/Roboto-Italic.ttf b/app/fonts/Roboto/Roboto-Italic.ttf new file mode 100644 index 0000000..5fd05c3 Binary files /dev/null and b/app/fonts/Roboto/Roboto-Italic.ttf differ diff --git a/app/fonts/Roboto/Roboto-Light.ttf b/app/fonts/Roboto/Roboto-Light.ttf new file mode 100644 index 0000000..4f1fb58 Binary files /dev/null and b/app/fonts/Roboto/Roboto-Light.ttf differ diff --git a/app/fonts/Roboto/Roboto-LightItalic.ttf b/app/fonts/Roboto/Roboto-LightItalic.ttf new file mode 100644 index 0000000..eec0ae9 Binary files /dev/null and b/app/fonts/Roboto/Roboto-LightItalic.ttf differ diff --git a/app/fonts/Roboto/Roboto-Medium.ttf b/app/fonts/Roboto/Roboto-Medium.ttf new file mode 100644 index 0000000..86d1c52 Binary files /dev/null and b/app/fonts/Roboto/Roboto-Medium.ttf differ diff --git a/app/fonts/Roboto/Roboto-MediumItalic.ttf b/app/fonts/Roboto/Roboto-MediumItalic.ttf new file mode 100644 index 0000000..66aa174 Binary files /dev/null and b/app/fonts/Roboto/Roboto-MediumItalic.ttf differ diff --git a/app/fonts/Roboto/Roboto-Regular.ttf b/app/fonts/Roboto/Roboto-Regular.ttf new file mode 100644 index 0000000..cb8ffcf Binary files /dev/null and b/app/fonts/Roboto/Roboto-Regular.ttf differ diff --git a/app/fonts/Roboto/Roboto-Thin.ttf b/app/fonts/Roboto/Roboto-Thin.ttf new file mode 100644 index 0000000..a85eb7c Binary files /dev/null and b/app/fonts/Roboto/Roboto-Thin.ttf differ diff --git a/app/fonts/Roboto/Roboto-ThinItalic.ttf b/app/fonts/Roboto/Roboto-ThinItalic.ttf new file mode 100644 index 0000000..ac77951 Binary files /dev/null and b/app/fonts/Roboto/Roboto-ThinItalic.ttf differ diff --git a/app/lib/main_desktop.dart b/app/lib/main_desktop.dart new file mode 100644 index 0000000..2b3724f --- /dev/null +++ b/app/lib/main_desktop.dart @@ -0,0 +1,10 @@ +import 'package:flutter/foundation.dart' + show debugDefaultTargetPlatformOverride; +import 'package:flutter/material.dart'; +import 'package:stashall/src/app.dart'; + +void main() { + debugDefaultTargetPlatformOverride = TargetPlatform.fuchsia; + + runApp(MyApp()); +} diff --git a/app/linux/Makefile b/app/linux/Makefile new file mode 100644 index 0000000..8eaf803 --- /dev/null +++ b/app/linux/Makefile @@ -0,0 +1,127 @@ +# Copyright 2018 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Example-specific variables. +# To modify this Makefile for a different application, these are the values +# that are mostly likely to need to be changed. + +# Executable name. +BINARY_NAME=flutter_desktop_example +# The C++ code for the embedder application. +SOURCES=flutter_embedder_example.cc + +# Default build type. For a release build, set BUILD=release. +# Currently this only sets NDEBUG, which is used to control the flags passed +# to the Flutter engine in the example shell, and not the complation settings +# (e.g., optimization level) of the C++ code. +BUILD=debug + +# Configuration provided via flutter tool. +include flutter/generated_config + +# Dependency locations +FLUTTER_APP_CACHE_DIR=flutter/ +FLUTTER_APP_DIR=$(CURDIR)/.. +FLUTTER_APP_BUILD_DIR=$(FLUTTER_APP_DIR)/build + +OUT_DIR=$(FLUTTER_APP_BUILD_DIR)/linux + +# Libraries +FLUTTER_LIB_NAME=flutter_linux +FLUTTER_LIB=$(FLUTTER_APP_CACHE_DIR)/lib$(FLUTTER_LIB_NAME).so + +# Tools +FLUTTER_BIN=$(FLUTTER_ROOT)/bin/flutter +LINUX_BUILD=$(FLUTTER_ROOT)/packages/flutter_tools/bin/linux_backend.sh + +# Resources +ICU_DATA_NAME=icudtl.dat +ICU_DATA_SOURCE=$(FLUTTER_APP_CACHE_DIR)/$(ICU_DATA_NAME) +FLUTTER_ASSETS_NAME=flutter_assets +FLUTTER_ASSETS_SOURCE=$(FLUTTER_APP_BUILD_DIR)/$(FLUTTER_ASSETS_NAME) + +# Bundle structure +BUNDLE_OUT_DIR=$(OUT_DIR)/$(BUILD) +BUNDLE_DATA_DIR=$(BUNDLE_OUT_DIR)/data +BUNDLE_LIB_DIR=$(BUNDLE_OUT_DIR)/lib + +BIN_OUT=$(BUNDLE_OUT_DIR)/$(BINARY_NAME) +ICU_DATA_OUT=$(BUNDLE_DATA_DIR)/$(ICU_DATA_NAME) +FLUTTER_LIB_OUT=$(BUNDLE_LIB_DIR)/$(notdir $(FLUTTER_LIB)) + +# Add relevant code from the wrapper library, which is intended to be statically +# built into the client. +WRAPPER_ROOT=$(FLUTTER_APP_CACHE_DIR)/cpp_client_wrapper +WRAPPER_SOURCES= \ + $(WRAPPER_ROOT)/flutter_window_controller.cc \ + $(WRAPPER_ROOT)/plugin_registrar.cc \ + $(WRAPPER_ROOT)/engine_method_result.cc +SOURCES+=$(WRAPPER_SOURCES) + +# Headers +WRAPPER_INCLUDE_DIR=$(WRAPPER_ROOT)/include +INCLUDE_DIRS=$(FLUTTER_APP_CACHE_DIR) $(WRAPPER_INCLUDE_DIR) + +# Build settings +CXX=g++ -std=c++14 +CXXFLAGS.release=-DNDEBUG +CXXFLAGS=-Wall -Werror $(CXXFLAGS.$(BUILD)) +CPPFLAGS=$(patsubst %,-I%,$(INCLUDE_DIRS)) +LDFLAGS=-L$(BUNDLE_LIB_DIR) \ + -l$(FLUTTER_LIB_NAME) \ + -Wl,-rpath=\$$ORIGIN/lib + +# Targets + +.PHONY: all +all: $(BIN_OUT) bundle + +# This is a phony target because the flutter tool cannot describe +# its inputs and outputs yet. +.PHONY: sync +sync: flutter/generated_config + $(FLUTTER_ROOT)/packages/flutter_tools/bin/tool_backend.sh linux-x64 $(BUILD) + +.PHONY: bundle +bundle: $(ICU_DATA_OUT) $(FLUTTER_LIB_OUT) bundleflutterassets + +$(BIN_OUT): $(SOURCES) $(FLUTTER_LIB_OUT) + mkdir -p $(@D) + $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(SOURCES) $(LDFLAGS) -o $@ + +$(WRAPPER_SOURCES) $(FLUTTER_LIB) $(ICU_DATA_SOURCE) $(FLUTTER_ASSETS_SOURCE): \ + | sync + +$(FLUTTER_LIB_OUT): $(FLUTTER_LIB) + mkdir -p $(BUNDLE_LIB_DIR) + cp $(FLUTTER_LIB) $(BUNDLE_LIB_DIR) + +$(ICU_DATA_OUT): $(ICU_DATA_SOURCE) + mkdir -p $(dir $(ICU_DATA_OUT)) + cp $(ICU_DATA_SOURCE) $(ICU_DATA_OUT) + +# Fully re-copy the assets directory on each build to avoid having to keep a +# comprehensive list of all asset files here, which would be fragile to changes +# in the Flutter example (e.g., adding a new font to pubspec.yaml would require +# changes here). +.PHONY: bundleflutterassets +bundleflutterassets: $(FLUTTER_ASSETS_SOURCE) + mkdir -p $(BUNDLE_DATA_DIR) + rsync -rpu --delete $(FLUTTER_ASSETS_SOURCE) $(BUNDLE_DATA_DIR) + +.PHONY: clean +clean: + rm -rf $(OUT_DIR); \ + cd $(FLUTTER_APP_DIR); \ + $(FLUTTER_BIN) clean diff --git a/app/linux/flutter/.last_artifact_version b/app/linux/flutter/.last_artifact_version new file mode 100644 index 0000000..f768b9e --- /dev/null +++ b/app/linux/flutter/.last_artifact_version @@ -0,0 +1 @@ +8dc3a4cde2075a4f5458fd0eb199627f5124508d \ No newline at end of file diff --git a/app/linux/flutter/cpp_client_wrapper/README b/app/linux/flutter/cpp_client_wrapper/README new file mode 100644 index 0000000..a7f8764 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/README @@ -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 libary 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). diff --git a/app/linux/flutter/cpp_client_wrapper/byte_stream_wrappers.h b/app/linux/flutter/cpp_client_wrapper/byte_stream_wrappers.h new file mode 100644 index 0000000..96ab0b0 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/byte_stream_wrappers.h @@ -0,0 +1,105 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BYTE_STREAM_WRAPPERS_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BYTE_STREAM_WRAPPERS_H_ + +// Utility classes for interacting with a buffer of bytes as a stream, for use +// in message channel codecs. + +#include +#include +#include +#include + +namespace flutter { + +// Wraps an array of bytes with utility methods for treating it as a readable +// stream. +class ByteBufferStreamReader { + 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) {} + + // Reads and returns the next byte from the stream. + uint8_t ReadByte() { + if (location_ >= size_) { + std::cerr << "Invalid read in StandardCodecByteStreamReader" << std::endl; + return 0; + } + return bytes_[location_++]; + } + + // Reads the next |length| bytes from the stream into |buffer|. The caller + // is responsible for ensuring that |buffer| is large enough. + void ReadBytes(uint8_t* buffer, size_t length) { + if (location_ + length > size_) { + std::cerr << "Invalid read in StandardCodecByteStreamReader" << std::endl; + return; + } + std::memcpy(buffer, &bytes_[location_], length); + location_ += length; + } + + // Advances the read cursor to the next multiple of |alignment| relative to + // the start of the wrapped byte buffer, unless it is already aligned. + void ReadAlignment(uint8_t alignment) { + 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; +}; + +// Wraps an array of bytes with utility methods for treating it as a writable +// stream. +class ByteBufferStreamWriter { + public: + // Createa a writter that writes into |buffer|. + // |buffer| must remain valid for the lifetime of this object. + explicit ByteBufferStreamWriter(std::vector* buffer) + : bytes_(buffer) { + assert(buffer); + } + + // Writes |byte| to the wrapped buffer. + void WriteByte(uint8_t byte) { bytes_->push_back(byte); } + + // Writes the next |length| bytes from |bytes| into the wrapped buffer. + // The caller is responsible for ensuring that |buffer| is large enough. + void WriteBytes(const uint8_t* bytes, size_t length) { + assert(length > 0); + bytes_->insert(bytes_->end(), bytes, bytes + length); + } + + // Writes 0s until the next multiple of |alignment| relative to + // the start of the wrapped byte buffer, unless the write positition is + // already aligned. + 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* bytes_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_BYTE_STREAM_WRAPPERS_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/engine_method_result.cc b/app/linux/flutter/cpp_client_wrapper/engine_method_result.cc new file mode 100644 index 0000000..03e17a8 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/engine_method_result.cc @@ -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. + +#include "include/flutter/engine_method_result.h" + +#include +#include + +namespace flutter { +namespace internal { + +ReplyManager::ReplyManager(BinaryReply reply_handler) + : reply_handler_(std::move(reply_handler)) { + assert(reply_handler_); +} + +ReplyManager::~ReplyManager() { + if (reply_handler_) { + // Warn, rather than send a not-implemented response, since the engine may + // no longer be valid at this point. + std::cerr + << "Warning: Failed to respond to a message. This is a memory leak." + << std::endl; + } +} + +void ReplyManager::SendResponseData(const std::vector* data) { + if (!reply_handler_) { + std::cerr + << "Error: Only one of Success, Error, or NotImplemented can be " + "called," + << " and it can be called exactly once. Ignoring duplicate result." + << std::endl; + return; + } + + const uint8_t* message = data && !data->empty() ? data->data() : nullptr; + size_t message_size = data ? data->size() : 0; + reply_handler_(message, message_size); + reply_handler_ = nullptr; +} + +} // namespace internal +} // namespace flutter diff --git a/app/linux/flutter/cpp_client_wrapper/flutter_window_controller.cc b/app/linux/flutter/cpp_client_wrapper/flutter_window_controller.cc new file mode 100644 index 0000000..4253597 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/flutter_window_controller.cc @@ -0,0 +1,81 @@ +// 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_window_controller.h" + +#include +#include + +namespace flutter { + +FlutterWindowController::FlutterWindowController( + const std::string& icu_data_path) + : icu_data_path_(icu_data_path) { + init_succeeded_ = FlutterDesktopInit(); +} + +FlutterWindowController::~FlutterWindowController() { + if (controller_) { + FlutterDesktopDestroyWindow(controller_); + } + if (init_succeeded_) { + FlutterDesktopTerminate(); + } +} + +bool FlutterWindowController::CreateWindow( + int width, + int height, + const std::string& title, + const std::string& assets_path, + const std::vector& arguments) { + if (!init_succeeded_) { + std::cerr << "Could not create window; FlutterDesktopInit failed." + << std::endl; + return false; + } + + if (controller_) { + std::cerr << "Only one Flutter window can exist at a time." << std::endl; + return false; + } + + std::vector engine_arguments; + std::transform( + arguments.begin(), arguments.end(), std::back_inserter(engine_arguments), + [](const std::string& arg) -> const char* { return arg.c_str(); }); + size_t arg_count = engine_arguments.size(); + + controller_ = FlutterDesktopCreateWindow( + width, height, title.c_str(), assets_path.c_str(), icu_data_path_.c_str(), + arg_count > 0 ? &engine_arguments[0] : nullptr, arg_count); + if (!controller_) { + std::cerr << "Failed to create window." << std::endl; + return false; + } + window_ = + std::make_unique(FlutterDesktopGetWindow(controller_)); + return true; +} + +FlutterDesktopPluginRegistrarRef FlutterWindowController::GetRegistrarForPlugin( + const std::string& plugin_name) { + if (!controller_) { + std::cerr << "Cannot get plugin registrar without a window; call " + "CreateWindow first." + << std::endl; + return nullptr; + } + return FlutterDesktopGetPluginRegistrar(controller_, plugin_name.c_str()); +} + +void FlutterWindowController::RunEventLoop() { + if (controller_) { + FlutterDesktopRunWindowLoop(controller_); + } + window_ = nullptr; + controller_ = nullptr; +} + +} // namespace flutter diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/basic_message_channel.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/basic_message_channel.h new file mode 100644 index 0000000..df03714 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/basic_message_channel.h @@ -0,0 +1,96 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_BASIC_MESSAGE_CHANNEL_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_BASIC_MESSAGE_CHANNEL_H_ + +#include +#include + +#include "binary_messenger.h" +#include "message_codec.h" + +namespace flutter { + +// A message reply callback. +// +// Used for submitting a reply back to a Flutter message sender. +template +using MessageReply = std::function; + +// A handler for receiving a message from the Flutter engine. +// +// Implementations must asynchronously call reply exactly once with the reply +// to the message. +template +using MessageHandler = + std::function reply)>; + +// A channel for communicating with the Flutter engine by sending asynchronous +// messages. +template +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* 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> raw_message = + codec_->EncodeMessage(message); + messenger_->Send(name_, raw_message->data(), raw_message->size()); + } + + // TODO: Add support for a version of Send expecting a reply once + // https://github.com/flutter/flutter/issues/18852 is fixed. + + // Registers a handler that should be called any time a message is + // received on this channel. + void SetMessageHandler(MessageHandler handler) const { + 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, + BinaryReply binary_reply) { + // Use this channel's codec to decode the message and build a reply + // handler. + std::unique_ptr 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 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)); + } + + private: + BinaryMessenger* messenger_; + std::string name_; + const MessageCodec* codec_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_BASIC_MESSAGE_CHANNEL_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/binary_messenger.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/binary_messenger.h new file mode 100644 index 0000000..ae91941 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/binary_messenger.h @@ -0,0 +1,56 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_BINARY_MESSENGER_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_BINARY_MESSENGER_H_ + +#include +#include + +// TODO: Consider adding absl as a dependency and using absl::Span for all of +// the message/message_size pairs. +namespace flutter { + +// A binary message reply callback. +// +// Used for submitting a binary reply back to a Flutter message sender. +typedef std::function + BinaryReply; + +// A message handler callback. +// +// Used for receiving messages from Flutter and providing an asynchronous reply. +typedef std::function< + void(const uint8_t* message, const 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 side on the specified channel, + // expecting no reply. + // + // TODO: Consider adding absl as a dependency and using absl::Span. + virtual void Send(const std::string& channel, + const uint8_t* message, + const size_t message_size) const = 0; + + // TODO: Add support for a version of Send expecting a reply once + // https://github.com/flutter/flutter/issues/18852 is fixed. + + // 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_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_BINARY_MESSENGER_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/encodable_value.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/encodable_value.h new file mode 100644 index 0000000..03d9803 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/encodable_value.h @@ -0,0 +1,569 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_ + +#include +#include +#include +#include +#include +#include + +namespace flutter { + +static_assert(sizeof(double) == 8, "EncodableValue requires a 64-bit double"); + +class EncodableValue; +// Convenience type aliases for list and map EncodableValue types. +using EncodableList = std::vector; +using EncodableMap = std::map; + +// 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), +// })}, +// }) +class EncodableValue { + public: + // Possible types for an EncodableValue to reperesent. + enum class Type { + kNull, // A null value. + kBool, // A boolean value. + kInt, // A 32-bit integer. + kLong, // A 64-bit integer. + kDouble, // A 64-bit floating point number. + kString, // A string. + kByteList, // A list of bytes. + kIntList, // A list of 32-bit integers. + kLongList, // A list of 64-bit integers. + kDoubleList, // A list of 64-bit floating point numbers. + kList, // A list of EncodableValues. + kMap, // A mapping from EncodableValues to EncodableValues. + }; + + // Creates an instance representing a null value. + EncodableValue() {} + + // Creates an instance representing a bool value. + explicit EncodableValue(bool value) : bool_(value), type_(Type::kBool) {} + + // Creates an instance representing a 32-bit integer value. + explicit EncodableValue(int32_t value) : int_(value), type_(Type::kInt) {} + + // Creates an instance representing a 64-bit integer value. + explicit EncodableValue(int64_t value) : long_(value), type_(Type::kLong) {} + + // Creates an instance representing a 64-bit floating point value. + explicit EncodableValue(double value) + : double_(value), type_(Type::kDouble) {} + + // Creates an instance representing a string value. + explicit EncodableValue(const char* value) + : string_(new std::string(value)), type_(Type::kString) {} + + // Creates an instance representing a string value. + explicit EncodableValue(const std::string& value) + : string_(new std::string(value)), type_(Type::kString) {} + + // Creates an instance representing a list of bytes. + explicit EncodableValue(std::vector list) + : byte_list_(new std::vector(std::move(list))), + type_(Type::kByteList) {} + + // Creates an instance representing a list of 32-bit integers. + explicit EncodableValue(std::vector list) + : int_list_(new std::vector(std::move(list))), + type_(Type::kIntList) {} + + // Creates an instance representing a list of 64-bit integers. + explicit EncodableValue(std::vector list) + : long_list_(new std::vector(std::move(list))), + type_(Type::kLongList) {} + + // Creates an instance representing a list of 64-bit floating point values. + explicit EncodableValue(std::vector list) + : double_list_(new std::vector(std::move(list))), + type_(Type::kDoubleList) {} + + // Creates an instance representing a list of EncodableValues. + explicit EncodableValue(EncodableList list) + : list_(new EncodableList(std::move(list))), type_(Type::kList) {} + + // Creates an instance representing a map from EncodableValues to + // EncodableValues. + explicit EncodableValue(EncodableMap map) + : map_(new EncodableMap(std::move(map))), type_(Type::kMap) {} + + // Convience constructor for creating default value of the given type. + // + // Collections types will be empty, numeric types will be 0, strings will be + // empty, and booleans will be false. For non-collection types, prefer using + // the value-based constructor with an explicit value for clarity. + explicit EncodableValue(Type type) : type_(type) { + switch (type_) { + case Type::kNull: + break; + case Type::kBool: + bool_ = false; + break; + case Type::kInt: + int_ = 0; + break; + case Type::kLong: + long_ = 0; + break; + case Type::kDouble: + double_ = 0.0; + break; + case Type::kString: + string_ = new std::string(); + break; + case Type::kByteList: + byte_list_ = new std::vector(); + break; + case Type::kIntList: + int_list_ = new std::vector(); + break; + case Type::kLongList: + long_list_ = new std::vector(); + break; + case Type::kDoubleList: + double_list_ = new std::vector(); + break; + case Type::kList: + list_ = new std::vector(); + break; + case Type::kMap: + map_ = new std::map(); + break; + } + } + + ~EncodableValue() { DestroyValue(); } + + EncodableValue(const EncodableValue& other) { + DestroyValue(); + + type_ = other.type_; + switch (type_) { + case Type::kNull: + break; + case Type::kBool: + bool_ = other.bool_; + break; + case Type::kInt: + int_ = other.int_; + break; + case Type::kLong: + long_ = other.long_; + break; + case Type::kDouble: + double_ = other.double_; + break; + case Type::kString: + string_ = new std::string(*other.string_); + break; + case Type::kByteList: + byte_list_ = new std::vector(*other.byte_list_); + break; + case Type::kIntList: + int_list_ = new std::vector(*other.int_list_); + break; + case Type::kLongList: + long_list_ = new std::vector(*other.long_list_); + break; + case Type::kDoubleList: + double_list_ = new std::vector(*other.double_list_); + break; + case Type::kList: + list_ = new std::vector(*other.list_); + break; + case Type::kMap: + map_ = new std::map(*other.map_); + break; + } + } + + EncodableValue(EncodableValue&& other) { *this = std::move(other); } + + EncodableValue& operator=(const EncodableValue& other) { + if (&other == this) { + return *this; + } + using std::swap; + EncodableValue temp(other); + swap(*this, temp); + return *this; + } + + EncodableValue& operator=(EncodableValue&& other) { + if (&other == this) { + return *this; + } + DestroyValue(); + + type_ = other.type_; + switch (type_) { + case Type::kNull: + break; + case Type::kBool: + bool_ = other.bool_; + break; + case Type::kInt: + int_ = other.int_; + break; + case Type::kLong: + long_ = other.long_; + break; + case Type::kDouble: + double_ = other.double_; + break; + case Type::kString: + string_ = other.string_; + break; + case Type::kByteList: + byte_list_ = other.byte_list_; + break; + case Type::kIntList: + int_list_ = other.int_list_; + break; + case Type::kLongList: + long_list_ = other.long_list_; + break; + case Type::kDoubleList: + double_list_ = other.double_list_; + break; + case Type::kList: + list_ = other.list_; + break; + case Type::kMap: + map_ = other.map_; + break; + } + // Ensure that destruction doesn't run on the source of the move. + other.type_ = Type::kNull; + return *this; + } + + // Allow assigning any value type that can be used for a constructor. + template + EncodableValue& operator=(const T& value) { + *this = EncodableValue(value); + return *this; + } + + // This operator exists only to provide a stable ordering for use as a + // std::map key. It does not attempt to provide useful ordering semantics. + // Notably: + // - Numeric values are not guaranteed any ordering across numeric types. + // E.g., 1 as a Long may sort after 100 as an Int. + // - Collection types use pointer equality, rather than value. This means that + // multiple collections with the same values will end up as separate keys + // in a map (consistent with default Dart Map behavior). + bool operator<(const EncodableValue& other) const { + if (type_ != other.type_) { + return type_ < other.type_; + } + switch (type_) { + case Type::kNull: + return false; + case Type::kBool: + return bool_ < other.bool_; + case Type::kInt: + return int_ < other.int_; + case Type::kLong: + return long_ < other.long_; + case Type::kDouble: + return double_ < other.double_; + case Type::kString: + return *string_ < *other.string_; + case Type::kByteList: + case Type::kIntList: + case Type::kLongList: + case Type::kDoubleList: + case Type::kList: + case Type::kMap: + return this < &other; + } + assert(false); + return false; + } + + // Returns the bool value this object represents. + // + // It is a programming error to call this unless IsBool() is true. + bool BoolValue() const { + assert(IsBool()); + return bool_; + } + + // Returns the 32-bit integer value this object represents. + // + // It is a programming error to call this unless IsInt() is true. + int32_t IntValue() const { + assert(IsInt()); + return int_; + } + + // Returns the 64-bit integer value this object represents. + // + // It is a programming error to call this unless IsLong() or IsInt() is true. + // + // Note that calling this function on an Int value is the only case where + // a *Value() function can be called without the corresponding Is*() being + // true. This is 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. + int64_t LongValue() const { + assert(IsLong() || IsInt()); + if (IsLong()) { + return long_; + } + return int_; + } + + // Returns the double value this object represents. + // + // It is a programming error to call this unless IsDouble() is true. + double DoubleValue() const { + assert(IsDouble()); + return double_; + } + + // Returns the string value this object represents. + // + // It is a programming error to call this unless IsString() is true. + const std::string& StringValue() const { + assert(IsString()); + return *string_; + } + + // Returns the byte list this object represents. + // + // It is a programming error to call this unless IsByteList() is true. + const std::vector& ByteListValue() const { + assert(IsByteList()); + return *byte_list_; + } + + // Returns the byte list this object represents. + // + // It is a programming error to call this unless IsByteList() is true. + std::vector& ByteListValue() { + assert(IsByteList()); + return *byte_list_; + } + + // Returns the 32-bit integer list this object represents. + // + // It is a programming error to call this unless IsIntList() is true. + const std::vector& IntListValue() const { + assert(IsIntList()); + return *int_list_; + } + + // Returns the 32-bit integer list this object represents. + // + // It is a programming error to call this unless IsIntList() is true. + std::vector& IntListValue() { + assert(IsIntList()); + return *int_list_; + } + + // Returns the 64-bit integer list this object represents. + // + // It is a programming error to call this unless IsLongList() is true. + const std::vector& LongListValue() const { + assert(IsLongList()); + return *long_list_; + } + + // Returns the 64-bit integer list this object represents. + // + // It is a programming error to call this unless IsLongList() is true. + std::vector& LongListValue() { + assert(IsLongList()); + return *long_list_; + } + + // Returns the double list this object represents. + // + // It is a programming error to call this unless IsDoubleList() is true. + const std::vector& DoubleListValue() const { + assert(IsDoubleList()); + return *double_list_; + } + + // Returns the double list this object represents. + // + // It is a programming error to call this unless IsDoubleList() is true. + std::vector& DoubleListValue() { + assert(IsDoubleList()); + return *double_list_; + } + + // Returns the list of EncodableValues this object represents. + // + // It is a programming error to call this unless IsList() is true. + const EncodableList& ListValue() const { + assert(IsList()); + return *list_; + } + + // Returns the list of EncodableValues this object represents. + // + // It is a programming error to call this unless IsList() is true. + EncodableList& ListValue() { + assert(IsList()); + return *list_; + } + + // Returns the map of EncodableValue : EncodableValue pairs this object + // represent. + // + // It is a programming error to call this unless IsMap() is true. + const EncodableMap& MapValue() const { + assert(IsMap()); + return *map_; + } + + // Returns the map of EncodableValue : EncodableValue pairs this object + // represent. + // + // It is a programming error to call this unless IsMap() is true. + EncodableMap& MapValue() { + assert(IsMap()); + return *map_; + } + + // Returns true if this represents a null value. + bool IsNull() const { return type_ == Type::kNull; } + + // Returns true if this represents a bool value. + bool IsBool() const { return type_ == Type::kBool; } + + // Returns true if this represents a 32-bit integer value. + bool IsInt() const { return type_ == Type::kInt; } + + // Returns true if this represents a 64-bit integer value. + bool IsLong() const { return type_ == Type::kLong; } + + // Returns true if this represents a double value. + bool IsDouble() const { return type_ == Type::kDouble; } + + // Returns true if this represents a string value. + bool IsString() const { return type_ == Type::kString; } + + // Returns true if this represents a list of bytes. + bool IsByteList() const { return type_ == Type::kByteList; } + + // Returns true if this represents a list of 32-bit integers. + bool IsIntList() const { return type_ == Type::kIntList; } + + // Returns true if this represents a list of 64-bit integers. + bool IsLongList() const { return type_ == Type::kLongList; } + + // Returns true if this represents a list of doubles. + bool IsDoubleList() const { return type_ == Type::kDoubleList; } + + // Returns true if this represents a list of EncodableValues. + bool IsList() const { return type_ == Type::kList; } + + // Returns true if this represents a map of EncodableValue : EncodableValue + // pairs. + bool IsMap() const { return type_ == Type::kMap; } + + // Returns the type this value represents. + // + // This is primarily intended for use with switch(); for individual checks, + // prefer an Is*() call. + Type type() const { return type_; } + + private: + // Performs any cleanup necessary for the active union value. This must be + // called before assigning a new value, and on object destruction. + // + // After calling this, type_ will alway be kNull. + void DestroyValue() { + switch (type_) { + case Type::kNull: + case Type::kBool: + case Type::kInt: + case Type::kLong: + case Type::kDouble: + break; + case Type::kString: + delete string_; + break; + case Type::kByteList: + delete byte_list_; + break; + case Type::kIntList: + delete int_list_; + break; + case Type::kLongList: + delete long_list_; + break; + case Type::kDoubleList: + delete double_list_; + break; + case Type::kList: + delete list_; + break; + case Type::kMap: + delete map_; + break; + } + + type_ = Type::kNull; + } + + // The anonymous union that stores the represented value. Accessing any of + // these entries other than the one that corresponds to the current value of + // |type_| has undefined behavior. + // + // Pointers are used for the non-POD types to avoid making the overall size + // of the union unnecessarily large. + // + // TODO: Replace this with std::variant once c++17 is available. + union { + bool bool_; + int32_t int_; + int64_t long_; + double double_; + std::string* string_; + std::vector* byte_list_; + std::vector* int_list_; + std::vector* long_list_; + std::vector* double_list_; + std::vector* list_; + std::map* map_; + }; + + // The currently active union entry. + Type type_ = Type::kNull; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENCODABLE_VALUE_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/engine_method_result.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/engine_method_result.h new file mode 100644 index 0000000..9c28a85 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/engine_method_result.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_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENGINE_METHOD_RESULT_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENGINE_METHOD_RESULT_H_ + +#include +#include +#include + +#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: + 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* 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 +class EngineMethodResult : public MethodResult { + 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* codec) + : reply_manager_( + std::make_unique(std::move(reply_handler))), + codec_(codec) {} + + ~EngineMethodResult() = default; + + protected: + // |flutter::MethodResult| + void SuccessInternal(const T* result) override { + std::unique_ptr> 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> 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 reply_manager_; + + const MethodCodec* codec_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_ENGINE_METHOD_RESULT_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/flutter_window.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/flutter_window.h new file mode 100644 index 0000000..a788bc7 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/flutter_window.h @@ -0,0 +1,92 @@ +// 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_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_WINDOW_H_ +#define FLUTTER_SHELL_PLATFORM_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "plugin_registrar.h" + +namespace flutter { + +// A data type for window position and size. +struct WindowFrame { + int left; + int top; + int width; + int height; +}; + +// A window displaying Flutter content. +class FlutterWindow { + public: + explicit FlutterWindow(FlutterDesktopWindowRef window) : window_(window) {} + + ~FlutterWindow() = default; + + // Prevent copying. + FlutterWindow(FlutterWindow const&) = delete; + FlutterWindow& operator=(FlutterWindow const&) = delete; + + // Enables or disables hover tracking. + // + // If hover is enabled, mouse movement will send hover events to the Flutter + // engine, rather than only tracking the mouse while the button is pressed. + // Defaults to off. + void SetHoverEnabled(bool enabled) { + FlutterDesktopWindowSetHoverEnabled(window_, enabled); + } + + // Sets the displayed title of the window. + void SetTitle(const std::string& title) { + FlutterDesktopWindowSetTitle(window_, title.c_str()); + } + + // Sets the displayed icon for the window. + // + // The pixel format is 32-bit RGBA. The provided image data only needs to be + // valid for the duration of the call to this method. Pass a nullptr to revert + // to the default icon. + void SetIcon(uint8_t* pixel_data, int width, int height) { + FlutterDesktopWindowSetIcon(window_, pixel_data, width, height); + } + + // Returns the frame of the window, including any decoration (e.g., title + // bar), in screen coordinates. + WindowFrame GetFrame() { + WindowFrame frame = {}; + FlutterDesktopWindowGetFrame(window_, &frame.left, &frame.top, &frame.width, + &frame.height); + return frame; + } + + // Set the frame of the window, including any decoration (e.g., title + // bar), in screen coordinates. + void SetFrame(const WindowFrame& frame) { + FlutterDesktopWindowSetFrame(window_, frame.left, frame.top, frame.width, + frame.height); + } + + // Returns the number of pixels per screen coordinate for the window. + // + // Flutter uses pixel coordinates, so this is the ratio of positions and sizes + // seen by Flutter as compared to the screen. + double GetScaleFactor() { + return FlutterDesktopWindowGetScaleFactor(window_); + } + + private: + // Handle for interacting with the C API's window. + // + // Note: window_ is conceptually owned by the controller, not this object. + FlutterDesktopWindowRef window_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_WINDOW_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/flutter_window_controller.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/flutter_window_controller.h new file mode 100644 index 0000000..5c54b42 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/flutter_window_controller.h @@ -0,0 +1,90 @@ +// 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_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_WINDOW_CONTROLLER_H_ +#define FLUTTER_SHELL_PLATFORM_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_WINDOW_CONTROLLER_H_ + +#include +#include +#include + +#include + +#include "flutter_window.h" +#include "plugin_registrar.h" + +namespace flutter { + +// A controller for a window 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. +// +// Note: This is an early implementation (using GLFW internally) which +// requires control of the application's event loop, and is thus useful +// primarily for building a simple one-window shell hosting a Flutter +// application. The final implementation and API will be very different. +class FlutterWindowController { + public: + // There must be only one instance of this class in an application at any + // given time, as Flutter does not support multiple engines in one process, + // or multiple views in one engine. + explicit FlutterWindowController(const std::string& icu_data_path); + + ~FlutterWindowController(); + + // Prevent copying. + FlutterWindowController(FlutterWindowController const&) = delete; + FlutterWindowController& operator=(FlutterWindowController const&) = delete; + + // Creates and displays a window for displaying Flutter content. + // + // The |assets_path| is the path to the flutter_assets folder for the Flutter + // application to be run. |icu_data_path| is the path to the icudtl.dat file + // for the version of Flutter you are using. + // + // The |arguments| are passed to the Flutter engine. See: + // https://github.com/flutter/engine/blob/master/shell/common/switches.h for + // for details. Not all arguments will apply to desktop. + // + // Only one Flutter window can exist at a time; see constructor comment. + bool CreateWindow(int width, + int height, + const std::string& title, + const std::string& assets_path, + const std::vector& arguments); + + // Returns the FlutterDesktopPluginRegistrarRef to register a plugin with the + // given name. + // + // The name must be unique across the application. + FlutterDesktopPluginRegistrarRef GetRegistrarForPlugin( + const std::string& plugin_name); + + // The FlutterWindow managed by this controller, if any. Returns nullptr + // before CreateWindow is called, and after RunEventLoop returns; + FlutterWindow* window() { return window_.get(); } + + // Loops on Flutter window events until the window closes. + void RunEventLoop(); + + private: + // The path to the ICU data file. Set at creation time since it is the same + // for any window created. + std::string icu_data_path_; + + // Whether or not FlutterDesktopInit succeeded at creation time. + bool init_succeeded_ = false; + + // The owned FlutterWindow, if any. + std::unique_ptr window_; + + // Handle for interacting with the C API's window controller, if any. + FlutterDesktopWindowControllerRef controller_ = nullptr; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_FLUTTER_WINDOW_CONTROLLER_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/json_message_codec.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/json_message_codec.h new file mode 100644 index 0000000..ba1aa2f --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/json_message_codec.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_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_JSON_MESSAGE_CODEC_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_JSON_MESSAGE_CODEC_H_ + +#include "json_type.h" +#include "message_codec.h" + +namespace flutter { + +// A message encoding/decoding mechanism for communications to/from the +// Flutter engine via JSON channels. +class JsonMessageCodec : public MessageCodec { + public: + // Returns the shared instance of the codec. + static const JsonMessageCodec& GetInstance(); + + ~JsonMessageCodec() = default; + + // Prevent copying. + JsonMessageCodec(JsonMessageCodec const&) = delete; + JsonMessageCodec& operator=(JsonMessageCodec const&) = delete; + + protected: + // Instances should be obtained via GetInstance. + JsonMessageCodec() = default; + + // |flutter::MessageCodec| + std::unique_ptr DecodeMessageInternal( + const uint8_t* binary_message, + const size_t message_size) const override; + + // |flutter::MessageCodec| + std::unique_ptr> EncodeMessageInternal( + const JsonValueType& message) const override; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_JSON_MESSAGE_CODEC_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/json_method_codec.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/json_method_codec.h new file mode 100644 index 0000000..92af820 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/json_method_codec.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_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_JSON_METHOD_CODEC_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_JSON_METHOD_CODEC_H_ + +#include "json_type.h" +#include "method_call.h" +#include "method_codec.h" + +namespace flutter { + +// An implementation of MethodCodec that uses JSON strings as the serialization. +class JsonMethodCodec : public MethodCodec { + public: + // Returns the shared instance of the codec. + static const JsonMethodCodec& GetInstance(); + + ~JsonMethodCodec() = default; + + // Prevent copying. + JsonMethodCodec(JsonMethodCodec const&) = delete; + JsonMethodCodec& operator=(JsonMethodCodec const&) = delete; + + protected: + // Instances should be obtained via GetInstance. + JsonMethodCodec() = default; + + // |flutter::MethodCodec| + std::unique_ptr> DecodeMethodCallInternal( + const uint8_t* message, + const size_t message_size) const override; + + // |flutter::MethodCodec| + std::unique_ptr> EncodeMethodCallInternal( + const MethodCall& method_call) const override; + + // |flutter::MethodCodec| + std::unique_ptr> EncodeSuccessEnvelopeInternal( + const JsonValueType* result) const override; + + // |flutter::MethodCodec| + std::unique_ptr> EncodeErrorEnvelopeInternal( + const std::string& error_code, + const std::string& error_message, + const JsonValueType* error_details) const override; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_JSON_METHOD_CODEC_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/json_type.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/json_type.h new file mode 100644 index 0000000..476cee7 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/json_type.h @@ -0,0 +1,26 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_JSON_TYPE_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_JSON_TYPE_H_ + +// By default, the Json codecs use jsoncpp, but a version using RapidJSON is +// implemented as well. To use the latter, set USE_RAPID_JSON. +// +// When writing code using the JSON codec classes, do not use JsonValueType; +// instead use the underlying type for the library you have selected directly. + +#ifdef USE_RAPID_JSON +#include + +// The APIs often pass owning references, which in RapidJSON must include the +// allocator, so the value type for the APIs is Document rather than Value. +using JsonValueType = rapidjson::Document; +#else +#include + +using JsonValueType = Json::Value; +#endif + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_JSON_TYPE_H_ \ No newline at end of file diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/message_codec.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/message_codec.h new file mode 100644 index 0000000..386d0d0 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/message_codec.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_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_MESSAGE_CODEC_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_MESSAGE_CODEC_H_ + +#include +#include +#include + +namespace flutter { + +// Translates between a binary message and higher-level method call and +// response/error objects. +template +class MessageCodec { + public: + MessageCodec() = default; + + virtual ~MessageCodec() = default; + + // Prevent copying. + MessageCodec(MessageCodec const&) = delete; + MessageCodec& operator=(MessageCodec const&) = delete; + + // Returns the message encoded in |binary_message|, or nullptr if it cannot be + // decoded by this codec. + std::unique_ptr 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 DecodeMessage( + const std::vector& 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> 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 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> EncodeMessageInternal( + const T& message) const = 0; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_MESSAGE_CODEC_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/method_call.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/method_call.h new file mode 100644 index 0000000..80274e7 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/method_call.h @@ -0,0 +1,41 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_TYPED_METHOD_CALL_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_TYPED_METHOD_CALL_H_ + +#include +#include + +namespace flutter { + +// An object encapsulating a method call from Flutter whose arguments are of +// type T. +template +class MethodCall { + public: + // Creates a MethodCall with the given name and arguments. + MethodCall(const std::string& method_name, std::unique_ptr arguments) + : method_name_(method_name), arguments_(std::move(arguments)) {} + + virtual ~MethodCall() = default; + + // Prevent copying. + MethodCall(MethodCall const&) = delete; + MethodCall& operator=(MethodCall 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 arguments_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_TYPED_METHOD_CALL_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/method_channel.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/method_channel.h new file mode 100644 index 0000000..e1f1640 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/method_channel.h @@ -0,0 +1,90 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CHANNEL_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CHANNEL_H_ + +#include +#include + +#include "binary_messenger.h" +#include "engine_method_result.h" +#include "method_call.h" +#include "method_codec.h" +#include "method_result.h" + +namespace flutter { + +// 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 +using MethodCallHandler = + std::function& call, + std::unique_ptr> result)>; + +// A channel for communicating with the Flutter engine using invocation of +// asynchronous methods. +template +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* 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. + void InvokeMethod(const std::string& method, std::unique_ptr arguments) { + MethodCall method_call(method, std::move(arguments)); + std::unique_ptr> message = + codec_->EncodeMethodCall(method_call); + messenger_->Send(name_, message->data(), message->size()); + } + + // TODO: Add support for a version of InvokeMethod expecting a reply once + // https://github.com/flutter/flutter/issues/18852 is fixed. + + // Registers a handler that should be called any time a method call is + // received on this channel. + void SetMethodCallHandler(MethodCallHandler handler) const { + const auto* codec = codec_; + std::string channel_name = name_; + BinaryMessageHandler binary_handler = [handler, codec, channel_name]( + const uint8_t* message, + const 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>(std::move(reply), codec); + std::unique_ptr> 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)); + } + + private: + BinaryMessenger* messenger_; + std::string name_; + const MethodCodec* codec_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CHANNEL_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/method_codec.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/method_codec.h new file mode 100644 index 0000000..6f9e09a --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/method_codec.h @@ -0,0 +1,93 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CODEC_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CODEC_H_ + +#include +#include +#include + +#include "method_call.h" + +namespace flutter { + +// Translates between a binary message and higher-level method call and +// response/error objects. +template +class MethodCodec { + public: + MethodCodec() = default; + + virtual ~MethodCodec() = default; + + // Prevent copying. + MethodCodec(MethodCodec const&) = delete; + MethodCodec& operator=(MethodCodec const&) = delete; + + // Returns the MethodCall encoded in |message|, or nullptr if it cannot be + // decoded. + std::unique_ptr> DecodeMethodCall( + const uint8_t* message, + const 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> DecodeMethodCall( + const std::vector& 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> EncodeMethodCall( + const MethodCall& 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> 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> 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)); + } + + protected: + // Implementation of the public interface, to be provided by subclasses. + virtual std::unique_ptr> DecodeMethodCallInternal( + const uint8_t* message, + const size_t message_size) const = 0; + + // Implementation of the public interface, to be provided by subclasses. + virtual std::unique_ptr> EncodeMethodCallInternal( + const MethodCall& method_call) const = 0; + + // Implementation of the public interface, to be provided by subclasses. + virtual std::unique_ptr> EncodeSuccessEnvelopeInternal( + const T* result) const = 0; + + // Implementation of the public interface, to be provided by subclasses. + virtual std::unique_ptr> EncodeErrorEnvelopeInternal( + const std::string& error_code, + const std::string& error_message, + const T* error_details) const = 0; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_CODEC_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/method_result.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/method_result.h new file mode 100644 index 0000000..e3bf572 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/method_result.h @@ -0,0 +1,58 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_RESULT_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_RESULT_H_ + +#include + +namespace flutter { + +// Encapsulates a result sent back to the Flutter engine in response to a +// MethodCall. Only one method should be called on any given instance. +template +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. + // An optional value can be provided as part of the success message. + void Success(const T* result = nullptr) { SuccessInternal(result); } + + // Sends an error response, indicating that the call was understood but + // handling failed in some way. A string error code must be provided, and in + // addition an optional user-readable error_message and/or details object can + // be included. + void Error(const std::string& error_code, + const std::string& error_message = "", + const T* error_details = nullptr) { + ErrorInternal(error_code, error_message, error_details); + } + + // 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_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_METHOD_RESULT_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/plugin_registrar.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/plugin_registrar.h new file mode 100644 index 0000000..5fbe1b5 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/plugin_registrar.h @@ -0,0 +1,74 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_H_ + +#include +#include +#include + +#include + +#include "binary_messenger.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(); } + + // Takes ownership of |plugin|. + // + // Plugins are not required to call this method if they have other lifetime + // management, but this is a convient place for plugins to be owned to ensure + // that they stay valid for any registered callbacks. + void AddPlugin(std::unique_ptr plugin); + + // Enables input blocking on the given channel name. + // + // If set, then the parent window should disable input callbacks + // while waiting for the handler for messages on that channel to run. + void EnableInputBlockingForChannel(const std::string& channel); + + private: + // Handle for interacting with the C API's registrar. + FlutterDesktopPluginRegistrarRef registrar_; + + std::unique_ptr messenger_; + + // Plugins registered for ownership. + std::set> plugins_; +}; + +// A plugin that can be registered for ownership by a PluginRegistrar. +class Plugin { + public: + virtual ~Plugin() = default; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/plugin_registrar_glfw.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/plugin_registrar_glfw.h new file mode 100644 index 0000000..a2a9da9 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/plugin_registrar_glfw.h @@ -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_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_GLFW_H_ +#define FLUTTER_SHELL_PLATFORM_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_GLFW_H_ + +#include + +#include + +#include "flutter_window.h" +#include "plugin_registrar.h" + +namespace flutter { + +// An extension to PluginRegistrar providing access to GLFW-shell-specific +// functionality. +class PluginRegistrarGlfw : public PluginRegistrar { + public: + // Creates a new PluginRegistrar. |core_registrar| and the messenger it + // provides must remain valid as long as this object exists. + explicit PluginRegistrarGlfw(FlutterDesktopPluginRegistrarRef core_registrar) + : PluginRegistrar(core_registrar) { + window_ = std::make_unique( + FlutterDesktopRegistrarGetWindow(core_registrar)); + } + + virtual ~PluginRegistrarGlfw() = default; + + // Prevent copying. + PluginRegistrarGlfw(PluginRegistrarGlfw const&) = delete; + PluginRegistrarGlfw& operator=(PluginRegistrarGlfw const&) = delete; + + FlutterWindow* window() { return window_.get(); } + + private: + // The owned FlutterWindow, if any. + std::unique_ptr window_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_GLFW_CLIENT_WRAPPER_INCLUDE_FLUTTER_PLUGIN_REGISTRAR_GLFW_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/standard_message_codec.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/standard_message_codec.h new file mode 100644 index 0000000..75644c7 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/standard_message_codec.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_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_MESSAGE_CODEC_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_MESSAGE_CODEC_H_ + +#include "encodable_value.h" +#include "message_codec.h" + +namespace flutter { + +// A binary message encoding/decoding mechanism for communications to/from the +// Flutter engine via message channels. +class StandardMessageCodec : public MessageCodec { + public: + // Returns the shared instance of the codec. + static const StandardMessageCodec& GetInstance(); + + ~StandardMessageCodec(); + + // Prevent copying. + StandardMessageCodec(StandardMessageCodec const&) = delete; + StandardMessageCodec& operator=(StandardMessageCodec const&) = delete; + + protected: + // Instances should be obtained via GetInstance. + StandardMessageCodec(); + + // |flutter::MessageCodec| + std::unique_ptr DecodeMessageInternal( + const uint8_t* binary_message, + const size_t message_size) const override; + + // |flutter::MessageCodec| + std::unique_ptr> EncodeMessageInternal( + const EncodableValue& message) const override; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_MESSAGE_CODEC_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/include/flutter/standard_method_codec.h b/app/linux/flutter/cpp_client_wrapper/include/flutter/standard_method_codec.h new file mode 100644 index 0000000..3b47411 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/include/flutter/standard_method_codec.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_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_METHOD_CODEC_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_METHOD_CODEC_H_ + +#include "encodable_value.h" +#include "method_call.h" +#include "method_codec.h" + +namespace flutter { + +// An implementation of MethodCodec that uses a binary serialization. +class StandardMethodCodec : public MethodCodec { + public: + // Returns the shared instance of the codec. + static const StandardMethodCodec& GetInstance(); + + ~StandardMethodCodec() = default; + + // Prevent copying. + StandardMethodCodec(StandardMethodCodec const&) = delete; + StandardMethodCodec& operator=(StandardMethodCodec const&) = delete; + + protected: + // Instances should be obtained via GetInstance. + StandardMethodCodec() = default; + + // |flutter::MethodCodec| + std::unique_ptr> DecodeMethodCallInternal( + const uint8_t* message, + const size_t message_size) const override; + + // |flutter::MethodCodec| + std::unique_ptr> EncodeMethodCallInternal( + const MethodCall& method_call) const override; + + // |flutter::MethodCodec| + std::unique_ptr> EncodeSuccessEnvelopeInternal( + const EncodableValue* result) const override; + + // |flutter::MethodCodec| + std::unique_ptr> EncodeErrorEnvelopeInternal( + const std::string& error_code, + const std::string& error_message, + const EncodableValue* error_details) const override; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_INCLUDE_FLUTTER_STANDARD_METHOD_CODEC_H_ diff --git a/app/linux/flutter/cpp_client_wrapper/json_message_codec.cc b/app/linux/flutter/cpp_client_wrapper/json_message_codec.cc new file mode 100644 index 0000000..5610c47 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/json_message_codec.cc @@ -0,0 +1,70 @@ +// 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/json_message_codec.h" + +#include +#include + +#ifdef USE_RAPID_JSON +#include "rapidjson/error/en.h" +#include "rapidjson/stringbuffer.h" +#include "rapidjson/writer.h" +#endif + +namespace flutter { + +// static +const JsonMessageCodec& JsonMessageCodec::GetInstance() { + static JsonMessageCodec sInstance; + return sInstance; +} + +std::unique_ptr> JsonMessageCodec::EncodeMessageInternal( + const JsonValueType& message) const { +#ifdef USE_RAPID_JSON + // TODO: Look into alternate writers that would avoid the buffer copy. + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + message.Accept(writer); + const char* buffer_start = buffer.GetString(); + return std::make_unique>( + buffer_start, buffer_start + buffer.GetSize()); +#else + Json::StreamWriterBuilder writer_builder; + std::string serialization = Json::writeString(writer_builder, message); + return std::make_unique>(serialization.begin(), + serialization.end()); +#endif +} + +std::unique_ptr JsonMessageCodec::DecodeMessageInternal( + const uint8_t* binary_message, + const size_t message_size) const { + auto raw_message = reinterpret_cast(binary_message); + auto json_message = std::make_unique(); + std::string parse_errors; + bool parsing_successful = false; +#ifdef USE_RAPID_JSON + rapidjson::ParseResult result = + json_message->Parse(raw_message, message_size); + parsing_successful = result == rapidjson::ParseErrorCode::kParseErrorNone; + if (!parsing_successful) { + parse_errors = rapidjson::GetParseError_En(result.Code()); + } +#else + Json::CharReaderBuilder reader_builder; + std::unique_ptr parser(reader_builder.newCharReader()); + parsing_successful = parser->parse(raw_message, raw_message + message_size, + json_message.get(), &parse_errors); +#endif + if (!parsing_successful) { + std::cerr << "Unable to parse JSON message:" << std::endl + << parse_errors << std::endl; + return nullptr; + } + return json_message; +} + +} // namespace flutter diff --git a/app/linux/flutter/cpp_client_wrapper/json_method_codec.cc b/app/linux/flutter/cpp_client_wrapper/json_method_codec.cc new file mode 100644 index 0000000..6c9528f --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/json_method_codec.cc @@ -0,0 +1,140 @@ +// 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/json_method_codec.h" + +#include "include/flutter/json_message_codec.h" + +namespace flutter { + +namespace { +// Keys used in MethodCall encoding. +constexpr char kMessageMethodKey[] = "method"; +constexpr char kMessageArgumentsKey[] = "args"; +} // namespace + +// static +const JsonMethodCodec& JsonMethodCodec::GetInstance() { + static JsonMethodCodec sInstance; + return sInstance; +} + +std::unique_ptr> +JsonMethodCodec::DecodeMethodCallInternal(const uint8_t* message, + const size_t message_size) const { + std::unique_ptr json_message = + JsonMessageCodec::GetInstance().DecodeMessage(message, message_size); + if (!json_message) { + return nullptr; + } + +#if USE_RAPID_JSON + auto method_name_iter = json_message->FindMember(kMessageMethodKey); + if (method_name_iter == json_message->MemberEnd()) { + return nullptr; + } + if (!method_name_iter->value.IsString()) { + return nullptr; + } + std::string method_name(method_name_iter->value.GetString()); + auto arguments_iter = json_message->FindMember(kMessageArgumentsKey); + std::unique_ptr arguments; + if (arguments_iter != json_message->MemberEnd()) { + // Pull the arguments subtree up to the root of json_message. This is + // destructive to json_message, but the full value is no longer needed, and + // this avoids a subtree copy. + // Note: The static_cast is for compatibility with RapidJSON 1.1; master + // already allows swapping a Document with a Value directly. Once there is + // a new RapidJSON release (at which point clients can be expected to have + // that change in the version they depend on) remove the cast. + static_cast(json_message.get()) + ->Swap(arguments_iter->value); + // Swap it into |arguments|. This moves the allocator ownership, so that + // the data won't be deleted when json_message goes out of scope. + arguments = std::make_unique(); + arguments->Swap(*json_message); + } + return std::make_unique>( + method_name, std::move(arguments)); +#else + Json::Value method = (*json_message)[kMessageMethodKey]; + if (method.isNull()) { + return nullptr; + } + return std::make_unique>( + method.asString(), + std::make_unique((*json_message)[kMessageArgumentsKey])); +#endif +} + +std::unique_ptr> JsonMethodCodec::EncodeMethodCallInternal( + const MethodCall& method_call) const { +#if USE_RAPID_JSON + // TODO: Consider revisiting the codec APIs to avoid the need to copy + // everything when doing encoding (e.g., by having a version that takes + // owership of the object to encode, so that it can be moved instead). + rapidjson::Document message(rapidjson::kObjectType); + auto& allocator = message.GetAllocator(); + rapidjson::Value name(method_call.method_name(), allocator); + rapidjson::Value arguments; + if (method_call.arguments()) { + arguments.CopyFrom(*method_call.arguments(), allocator); + } + message.AddMember(kMessageMethodKey, name, allocator); + message.AddMember(kMessageArgumentsKey, arguments, allocator); +#else + Json::Value message(Json::objectValue); + message[kMessageMethodKey] = method_call.method_name(); + const Json::Value* arguments = method_call.arguments(); + message[kMessageArgumentsKey] = arguments ? *arguments : Json::Value(); +#endif + + return JsonMessageCodec::GetInstance().EncodeMessage(message); +} + +std::unique_ptr> +JsonMethodCodec::EncodeSuccessEnvelopeInternal( + const JsonValueType* result) const { +#if USE_RAPID_JSON + rapidjson::Document envelope; + envelope.SetArray(); + rapidjson::Value result_value; + if (result) { + result_value.CopyFrom(*result, envelope.GetAllocator()); + } + envelope.PushBack(result_value, envelope.GetAllocator()); +#else + Json::Value envelope(Json::arrayValue); + envelope.append(result == nullptr ? Json::Value() : *result); +#endif + + return JsonMessageCodec::GetInstance().EncodeMessage(envelope); +} + +std::unique_ptr> +JsonMethodCodec::EncodeErrorEnvelopeInternal( + const std::string& error_code, + const std::string& error_message, + const JsonValueType* error_details) const { +#if USE_RAPID_JSON + rapidjson::Document envelope(rapidjson::kArrayType); + auto& allocator = envelope.GetAllocator(); + envelope.PushBack(rapidjson::Value(error_code, allocator), allocator); + envelope.PushBack(rapidjson::Value(error_message, allocator), allocator); + rapidjson::Value details_value; + if (error_details) { + details_value.CopyFrom(*error_details, allocator); + } + envelope.PushBack(details_value, allocator); +#else + Json::Value envelope(Json::arrayValue); + envelope.append(error_code); + envelope.append(error_message.empty() ? Json::Value() : error_message); + envelope.append(error_details == nullptr ? Json::Value() : *error_details); +#endif + + return JsonMessageCodec::GetInstance().EncodeMessage(envelope); +} + +} // namespace flutter diff --git a/app/linux/flutter/cpp_client_wrapper/plugin_registrar.cc b/app/linux/flutter/cpp_client_wrapper/plugin_registrar.cc new file mode 100644 index 0000000..46c1173 --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/plugin_registrar.cc @@ -0,0 +1,125 @@ +// 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 "include/flutter/engine_method_result.h" +#include "include/flutter/method_channel.h" + +#include +#include + +namespace flutter { + +namespace { + +// Passes |message| to |user_data|, which must be a BinaryMessageHandler, along +// with a BinaryReply that will send a response on |message|'s response handle. +// +// This serves as an adaptor between the function-pointer-based message callback +// interface provided by the C API and the std::function-based message handler +// interface of BinaryMessenger. +void ForwardToHandler(FlutterDesktopMessengerRef messenger, + const FlutterDesktopMessage* message, + void* user_data) { + auto* response_handle = message->response_handle; + BinaryReply reply_handler = [messenger, response_handle]( + const uint8_t* reply, + const size_t reply_size) mutable { + if (!response_handle) { + std::cerr << "Error: Response can be set only once. Ignoring " + "duplicate response." + << std::endl; + return; + } + FlutterDesktopMessengerSendResponse(messenger, response_handle, reply, + reply_size); + // The engine frees the response handle once + // FlutterDesktopSendMessageResponse is called. + response_handle = nullptr; + }; + + const BinaryMessageHandler& message_handler = + *static_cast(user_data); + + message_handler(message->message, message->message_size, + std::move(reply_handler)); +} + +} // namespace + +// Wrapper around a FlutterDesktopMessengerRef that implements the +// BinaryMessenger API. +class BinaryMessengerImpl : public BinaryMessenger { + public: + explicit BinaryMessengerImpl(FlutterDesktopMessengerRef core_messenger) + : messenger_(core_messenger) {} + + virtual ~BinaryMessengerImpl() = default; + + // Prevent copying. + BinaryMessengerImpl(BinaryMessengerImpl const&) = delete; + BinaryMessengerImpl& operator=(BinaryMessengerImpl const&) = delete; + + // |flutter::BinaryMessenger| + void Send(const std::string& channel, + const uint8_t* message, + const size_t message_size) const override; + + // |flutter::BinaryMessenger| + void SetMessageHandler(const std::string& channel, + BinaryMessageHandler handler) override; + + private: + // Handle for interacting with the C API. + FlutterDesktopMessengerRef messenger_; + + // A map from channel names to the BinaryMessageHandler that should be called + // for incoming messages on that channel. + std::map handlers_; +}; + +void BinaryMessengerImpl::Send(const std::string& channel, + const uint8_t* message, + const size_t message_size) const { + FlutterDesktopMessengerSend(messenger_, channel.c_str(), message, + message_size); +} + +void BinaryMessengerImpl::SetMessageHandler(const std::string& channel, + BinaryMessageHandler handler) { + if (!handler) { + handlers_.erase(channel); + FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(), nullptr, + nullptr); + return; + } + // Save the handler, to keep it alive. + handlers_[channel] = std::move(handler); + BinaryMessageHandler* message_handler = &handlers_[channel]; + // Set an adaptor callback that will invoke the handler. + FlutterDesktopMessengerSetCallback(messenger_, channel.c_str(), + ForwardToHandler, message_handler); +} + +// PluginRegistrar: + +PluginRegistrar::PluginRegistrar(FlutterDesktopPluginRegistrarRef registrar) + : registrar_(registrar) { + auto core_messenger = FlutterDesktopRegistrarGetMessenger(registrar_); + messenger_ = std::make_unique(core_messenger); +} + +PluginRegistrar::~PluginRegistrar() {} + +void PluginRegistrar::AddPlugin(std::unique_ptr plugin) { + plugins_.insert(std::move(plugin)); +} + +void PluginRegistrar::EnableInputBlockingForChannel( + const std::string& channel) { + FlutterDesktopRegistrarEnableInputBlocking(registrar_, channel.c_str()); +} + +} // namespace flutter diff --git a/app/linux/flutter/cpp_client_wrapper/standard_codec.cc b/app/linux/flutter/cpp_client_wrapper/standard_codec.cc new file mode 100644 index 0000000..6fbb63e --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/standard_codec.cc @@ -0,0 +1,378 @@ +// 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 "include/flutter/standard_message_codec.h" +#include "include/flutter/standard_method_codec.h" +#include "standard_codec_serializer.h" + +#include +#include +#include +#include +#include +#include + +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, +}; + +// Returns the encoded type that should be written when serializing |value|. +EncodedType EncodedTypeForValue(const EncodableValue& value) { + switch (value.type()) { + case EncodableValue::Type::kNull: + return EncodedType::kNull; + case EncodableValue::Type::kBool: + return value.BoolValue() ? EncodedType::kTrue : EncodedType::kFalse; + case EncodableValue::Type::kInt: + return EncodedType::kInt32; + case EncodableValue::Type::kLong: + return EncodedType::kInt64; + case EncodableValue::Type::kDouble: + return EncodedType::kFloat64; + case EncodableValue::Type::kString: + return EncodedType::kString; + case EncodableValue::Type::kByteList: + return EncodedType::kUInt8List; + case EncodableValue::Type::kIntList: + return EncodedType::kInt32List; + case EncodableValue::Type::kLongList: + return EncodedType::kInt64List; + case EncodableValue::Type::kDoubleList: + return EncodedType::kFloat64List; + case EncodableValue::Type::kList: + return EncodedType::kList; + case EncodableValue::Type::kMap: + return EncodedType::kMap; + } + assert(false); + return EncodedType::kNull; +} + +} // namespace + +StandardCodecSerializer::StandardCodecSerializer() = default; + +StandardCodecSerializer::~StandardCodecSerializer() = default; + +EncodableValue StandardCodecSerializer::ReadValue( + ByteBufferStreamReader* stream) const { + EncodedType type = static_cast(stream->ReadByte()); + ; + switch (type) { + case EncodedType::kNull: + return EncodableValue(); + case EncodedType::kTrue: + return EncodableValue(true); + case EncodedType::kFalse: + return EncodableValue(false); + case EncodedType::kInt32: { + int32_t int_value = 0; + stream->ReadBytes(reinterpret_cast(&int_value), 4); + return EncodableValue(int_value); + } + case EncodedType::kInt64: { + int64_t long_value = 0; + stream->ReadBytes(reinterpret_cast(&long_value), 8); + return EncodableValue(long_value); + } + case EncodedType::kFloat64: { + double double_value = 0; + stream->ReadAlignment(8); + stream->ReadBytes(reinterpret_cast(&double_value), 8); + return EncodableValue(double_value); + } + case EncodedType::kLargeInt: + case EncodedType::kString: { + int32_t size = ReadSize(stream); + std::string string_value; + string_value.resize(size); + stream->ReadBytes(reinterpret_cast(&string_value[0]), size); + return EncodableValue(string_value); + } + case EncodedType::kUInt8List: + return ReadVector(stream); + case EncodedType::kInt32List: + return ReadVector(stream); + case EncodedType::kInt64List: + return ReadVector(stream); + case EncodedType::kFloat64List: + return ReadVector(stream); + case EncodedType::kList: { + int32_t length = ReadSize(stream); + EncodableList list_value; + list_value.reserve(length); + for (int32_t i = 0; i < length; ++i) { + list_value.push_back(ReadValue(stream)); + } + return EncodableValue(list_value); + } + case EncodedType::kMap: { + int32_t length = ReadSize(stream); + EncodableMap map_value; + for (int32_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); + } + } + std::cerr << "Unknown type in StandardCodecSerializer::ReadValue: " + << static_cast(type) << std::endl; + return EncodableValue(); +} + +void StandardCodecSerializer::WriteValue(const EncodableValue& value, + ByteBufferStreamWriter* stream) const { + stream->WriteByte(static_cast(EncodedTypeForValue(value))); + switch (value.type()) { + case EncodableValue::Type::kNull: + case EncodableValue::Type::kBool: + // Null and bool are encoded directly in the type. + break; + case EncodableValue::Type::kInt: { + int32_t int_value = value.IntValue(); + stream->WriteBytes(reinterpret_cast(&int_value), 4); + break; + } + case EncodableValue::Type::kLong: { + int64_t long_value = value.LongValue(); + stream->WriteBytes(reinterpret_cast(&long_value), 8); + break; + } + case EncodableValue::Type::kDouble: { + stream->WriteAlignment(8); + double double_value = value.DoubleValue(); + stream->WriteBytes(reinterpret_cast(&double_value), 8); + break; + } + case EncodableValue::Type::kString: { + const auto& string_value = value.StringValue(); + size_t size = string_value.size(); + WriteSize(size, stream); + stream->WriteBytes(reinterpret_cast(string_value.data()), + size); + break; + } + case EncodableValue::Type::kByteList: + WriteVector(value.ByteListValue(), stream); + break; + case EncodableValue::Type::kIntList: + WriteVector(value.IntListValue(), stream); + break; + case EncodableValue::Type::kLongList: + WriteVector(value.LongListValue(), stream); + break; + case EncodableValue::Type::kDoubleList: + WriteVector(value.DoubleListValue(), stream); + break; + case EncodableValue::Type::kList: + WriteSize(value.ListValue().size(), stream); + for (const auto& item : value.ListValue()) { + WriteValue(item, stream); + } + break; + case EncodableValue::Type::kMap: + WriteSize(value.MapValue().size(), stream); + for (const auto& pair : value.MapValue()) { + WriteValue(pair.first, stream); + WriteValue(pair.second, stream); + } + break; + } +} + +uint32_t StandardCodecSerializer::ReadSize( + ByteBufferStreamReader* stream) const { + uint8_t byte = stream->ReadByte(); + if (byte < 254) { + return byte; + } else if (byte == 254) { + uint16_t value; + stream->ReadBytes(reinterpret_cast(&value), 2); + return value; + } else { + uint32_t value; + stream->ReadBytes(reinterpret_cast(&value), 4); + return value; + } +} + +void StandardCodecSerializer::WriteSize(uint32_t size, + ByteBufferStreamWriter* stream) const { + if (size < 254) { + stream->WriteByte(static_cast(size)); + } else if (size <= 0xffff) { + stream->WriteByte(254); + uint16_t value = static_cast(size); + stream->WriteBytes(reinterpret_cast(&value), 2); + } else { + stream->WriteByte(255); + stream->WriteBytes(reinterpret_cast(&size), 4); + } +} + +template +EncodableValue StandardCodecSerializer::ReadVector( + ByteBufferStreamReader* stream) const { + int32_t count = ReadSize(stream); + std::vector vector; + vector.resize(count); + size_t type_size = sizeof(T); + if (type_size > 1) { + stream->ReadAlignment(type_size); + } + stream->ReadBytes(reinterpret_cast(vector.data()), + count * type_size); + return EncodableValue(vector); +} + +template +void StandardCodecSerializer::WriteVector( + const std::vector vector, + ByteBufferStreamWriter* stream) const { + size_t count = vector.size(); + WriteSize(count, stream); + size_t type_size = sizeof(T); + if (type_size > 1) { + stream->WriteAlignment(type_size); + } + stream->WriteBytes(reinterpret_cast(vector.data()), + count * type_size); +} + +// ===== standard_message_codec.h ===== + +// static +const StandardMessageCodec& StandardMessageCodec::GetInstance() { + static StandardMessageCodec sInstance; + return sInstance; +} + +StandardMessageCodec::StandardMessageCodec() = default; + +StandardMessageCodec::~StandardMessageCodec() = default; + +std::unique_ptr StandardMessageCodec::DecodeMessageInternal( + const uint8_t* binary_message, + const size_t message_size) const { + StandardCodecSerializer serializer; + ByteBufferStreamReader stream(binary_message, message_size); + return std::make_unique(serializer.ReadValue(&stream)); +} + +std::unique_ptr> +StandardMessageCodec::EncodeMessageInternal( + const EncodableValue& message) const { + StandardCodecSerializer serializer; + auto encoded = std::make_unique>(); + ByteBufferStreamWriter stream(encoded.get()); + serializer.WriteValue(message, &stream); + return encoded; +} + +// ===== standard_method_codec.h ===== + +// static +const StandardMethodCodec& StandardMethodCodec::GetInstance() { + static StandardMethodCodec sInstance; + return sInstance; +} + +std::unique_ptr> +StandardMethodCodec::DecodeMethodCallInternal(const uint8_t* message, + const size_t message_size) const { + StandardCodecSerializer serializer; + ByteBufferStreamReader stream(message, message_size); + EncodableValue method_name = serializer.ReadValue(&stream); + if (!method_name.IsString()) { + std::cerr << "Invalid method call; method name is not a string." + << std::endl; + return nullptr; + } + auto arguments = + std::make_unique(serializer.ReadValue(&stream)); + return std::make_unique>(method_name.StringValue(), + std::move(arguments)); +} + +std::unique_ptr> +StandardMethodCodec::EncodeMethodCallInternal( + const MethodCall& method_call) const { + StandardCodecSerializer serializer; + auto encoded = std::make_unique>(); + 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> +StandardMethodCodec::EncodeSuccessEnvelopeInternal( + const EncodableValue* result) const { + StandardCodecSerializer serializer; + auto encoded = std::make_unique>(); + ByteBufferStreamWriter stream(encoded.get()); + stream.WriteByte(0); + if (result) { + serializer.WriteValue(*result, &stream); + } else { + serializer.WriteValue(EncodableValue(), &stream); + } + return encoded; +} + +std::unique_ptr> +StandardMethodCodec::EncodeErrorEnvelopeInternal( + const std::string& error_code, + const std::string& error_message, + const EncodableValue* error_details) const { + StandardCodecSerializer serializer; + auto encoded = std::make_unique>(); + 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; +} + +} // namespace flutter diff --git a/app/linux/flutter/cpp_client_wrapper/standard_codec_serializer.h b/app/linux/flutter/cpp_client_wrapper/standard_codec_serializer.h new file mode 100644 index 0000000..07499fd --- /dev/null +++ b/app/linux/flutter/cpp_client_wrapper/standard_codec_serializer.h @@ -0,0 +1,54 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_ENCODABLE_VALUE_SERIALIZER_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_ENCODABLE_VALUE_SERIALIZER_H_ + +#include "byte_stream_wrappers.h" +#include "include/flutter/encodable_value.h" + +namespace flutter { + +// Encapsulates the logic for encoding/decoding EncodableValues to/from the +// standard codec binary representation. +class StandardCodecSerializer { + public: + StandardCodecSerializer(); + ~StandardCodecSerializer(); + + // Prevent copying. + StandardCodecSerializer(StandardCodecSerializer const&) = delete; + StandardCodecSerializer& operator=(StandardCodecSerializer const&) = delete; + + // Reads and returns the next value from |stream|. + EncodableValue ReadValue(ByteBufferStreamReader* stream) const; + + // Writes the encoding of |value| to |stream|. + void WriteValue(const EncodableValue& value, + ByteBufferStreamWriter* stream) const; + + protected: + // Reads the variable-length size from the current position in |stream|. + uint32_t ReadSize(ByteBufferStreamReader* stream) const; + + // Writes the variable-length size encoding to |stream|. + void WriteSize(uint32_t size, ByteBufferStreamWriter* stream) const; + + // 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 support list value types of + // EncodableValue. + template + EncodableValue ReadVector(ByteBufferStreamReader* stream) const; + + // Writes |vector| to |stream| as a fixed-type list. |T| must correspond to + // one of the support list value types of EncodableValue. + template + void WriteVector(const std::vector vector, + ByteBufferStreamWriter* stream) const; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_CLIENT_WRAPPER_ENCODABLE_VALUE_SERIALIZER_H_ diff --git a/app/linux/flutter/flutter_export.h b/app/linux/flutter/flutter_export.h new file mode 100644 index 0000000..2f38091 --- /dev/null +++ b/app/linux/flutter/flutter_export.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_CPP_PUBLIC_FLUTTER_EXPORT_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_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_CPP_PUBLIC_FLUTTER_EXPORT_H_ \ No newline at end of file diff --git a/app/linux/flutter/flutter_glfw.h b/app/linux/flutter/flutter_glfw.h new file mode 100644 index 0000000..f4c718f --- /dev/null +++ b/app/linux/flutter/flutter_glfw.h @@ -0,0 +1,174 @@ +// 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_GLFW_PUBLIC_FLUTTER_GLFW_H_ +#define FLUTTER_SHELL_PLATFORM_GLFW_PUBLIC_FLUTTER_GLFW_H_ + +#include +#include + +#include "flutter_export.h" +#include "flutter_messenger.h" +#include "flutter_plugin_registrar.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Opaque reference to a Flutter window controller. +typedef struct FlutterDesktopWindowControllerState* + FlutterDesktopWindowControllerRef; + +// Opaque reference to a Flutter window. +typedef struct FlutterDesktopWindow* FlutterDesktopWindowRef; + +// Opaque reference to a Flutter engine instance. +typedef struct FlutterDesktopEngineState* FlutterDesktopEngineRef; + +// Sets up the library's graphic context. Must be called before any other +// methods. +// +// Note: Internally, this library uses GLFW, which does not support multiple +// copies within the same process. Internally this calls glfwInit, which will +// fail if you have called glfwInit elsewhere in the process. +FLUTTER_EXPORT bool FlutterDesktopInit(); + +// Tears down library state. Must be called before the process terminates. +FLUTTER_EXPORT void FlutterDesktopTerminate(); + +// Creates a Window running a Flutter Application. +// +// FlutterDesktopInit() must be called prior to this function. +// +// The |assets_path| is the path to the flutter_assets folder for the Flutter +// application to be run. |icu_data_path| is the path to the icudtl.dat file +// for the version of Flutter you are using. +// +// The |arguments| are passed to the Flutter engine. See: +// https://github.com/flutter/engine/blob/master/shell/common/switches.h for +// for details. Not all arguments will apply to desktop. +// +// Returns a null pointer in the event of an error. Otherwise, the pointer is +// valid until FlutterDesktopRunWindowLoop has been called and returned, or +// FlutterDesktopDestroyWindow is called. +// Note that calling FlutterDesktopCreateWindow without later calling +// one of those two methods on the returned reference is a memory leak. +FLUTTER_EXPORT FlutterDesktopWindowControllerRef +FlutterDesktopCreateWindow(int initial_width, + int initial_height, + const char* title, + const char* assets_path, + const char* icu_data_path, + const char** arguments, + size_t argument_count); + +// Shuts down the engine instance associated with |controller|, and cleans up +// associated state. +// +// |controller| is no longer valid after this call. +FLUTTER_EXPORT void FlutterDesktopDestroyWindow( + FlutterDesktopWindowControllerRef controller); + +// Loops on Flutter window events until the window is closed. +// +// Once this function returns, |controller| is no longer valid, and must not be +// be used again, as it calls FlutterDesktopDestroyWindow internally. +// +// TODO: Replace this with a method that allows running the runloop +// incrementally. +FLUTTER_EXPORT void FlutterDesktopRunWindowLoop( + FlutterDesktopWindowControllerRef controller); + +// Returns the window handle for the window associated with +// FlutterDesktopWindowControllerRef. +// +// Its lifetime is the same as the |controller|'s. +FLUTTER_EXPORT FlutterDesktopWindowRef +FlutterDesktopGetWindow(FlutterDesktopWindowControllerRef controller); + +// Returns the plugin registrar handle for the plugin with the given name. +// +// The name must be unique across the application. +FLUTTER_EXPORT FlutterDesktopPluginRegistrarRef +FlutterDesktopGetPluginRegistrar(FlutterDesktopWindowControllerRef controller, + const char* plugin_name); + +// Enables or disables hover tracking. +// +// If hover is enabled, mouse movement will send hover events to the Flutter +// engine, rather than only tracking the mouse while the button is pressed. +// Defaults to on. +FLUTTER_EXPORT void FlutterDesktopWindowSetHoverEnabled( + FlutterDesktopWindowRef flutter_window, + bool enabled); + +// Sets the displayed title for |flutter_window|. +FLUTTER_EXPORT void FlutterDesktopWindowSetTitle( + FlutterDesktopWindowRef flutter_window, + const char* title); + +// Sets the displayed icon for |flutter_window|. +// +// The pixel format is 32-bit RGBA. The provided image data only needs to be +// valid for the duration of the call to this method. Pass a nullptr to revert +// to the default icon. +FLUTTER_EXPORT void FlutterDesktopWindowSetIcon( + FlutterDesktopWindowRef flutter_window, + uint8_t* pixel_data, + int width, + int height); + +// Gets the position and size of |flutter_window| in screen coordinates. +FLUTTER_EXPORT void FlutterDesktopWindowGetFrame( + FlutterDesktopWindowRef flutter_window, + int* x, + int* y, + int* width, + int* height); + +// Sets the position and size of |flutter_window| in screen coordinates. +FLUTTER_EXPORT void FlutterDesktopWindowSetFrame( + FlutterDesktopWindowRef flutter_window, + int x, + int y, + int width, + int height); + +// Returns the scale factor--the number of pixels per screen coordinate--for +// |flutter_window|. +FLUTTER_EXPORT double FlutterDesktopWindowGetScaleFactor( + FlutterDesktopWindowRef flutter_window); + +// Runs an instance of a headless Flutter engine. +// +// The |assets_path| is the path to the flutter_assets folder for the Flutter +// application to be run. |icu_data_path| is the path to the icudtl.dat file +// for the version of Flutter you are using. +// +// The |arguments| are passed to the Flutter engine. See: +// https://github.com/flutter/engine/blob/master/shell/common/switches.h for +// for details. Not all arguments will apply to desktop. +// +// Returns a null pointer in the event of an error. +FLUTTER_EXPORT FlutterDesktopEngineRef +FlutterDesktopRunEngine(const char* assets_path, + const char* icu_data_path, + const char** arguments, + size_t argument_count); + +// Shuts down the given engine instance. Returns true if the shutdown was +// successful. |engine_ref| is no longer valid after this call. +FLUTTER_EXPORT bool FlutterDesktopShutDownEngine( + FlutterDesktopEngineRef engine_ref); + +// Returns the window associated with this registrar's engine instance. +// This is a GLFW shell-specific extension to flutter_plugin_registrar.h +FLUTTER_EXPORT FlutterDesktopWindowRef +FlutterDesktopRegistrarGetWindow(FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // FLUTTER_SHELL_PLATFORM_GLFW_PUBLIC_FLUTTER_GLFW_H_ diff --git a/app/linux/flutter/flutter_messenger.h b/app/linux/flutter/flutter_messenger.h new file mode 100644 index 0000000..ff9f434 --- /dev/null +++ b/app/linux/flutter/flutter_messenger.h @@ -0,0 +1,81 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_COMMON_CPP_PUBLIC_FLUTTER_MESSENGER_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_PUBLIC_FLUTTER_MESSENGER_H_ + +#include +#include + +#include "flutter_export.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Opaque reference to a Flutter engine messenger. +typedef struct FlutterDesktopMessenger* FlutterDesktopMessengerRef; + +// Opaque handle for tracking responses to messages. +typedef struct _FlutterPlatformMessageResponseHandle + FlutterDesktopMessageResponseHandle; + +// 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 void FlutterDesktopMessengerSend( + FlutterDesktopMessengerRef messenger, + const char* channel, + const uint8_t* message, + const size_t message_size); + +// 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); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_PUBLIC_FLUTTER_MESSENGER_H_ diff --git a/app/linux/flutter/flutter_plugin_registrar.h b/app/linux/flutter/flutter_plugin_registrar.h new file mode 100644 index 0000000..1caa3ce --- /dev/null +++ b/app/linux/flutter/flutter_plugin_registrar.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_COMMON_CPP_PUBLIC_FLUTTER_PLUGIN_REGISTRAR_H_ +#define FLUTTER_SHELL_PLATFORM_COMMON_CPP_PUBLIC_FLUTTER_PLUGIN_REGISTRAR_H_ + +#include +#include + +#include "flutter_export.h" +#include "flutter_messenger.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// Opaque reference to a plugin registrar. +typedef struct FlutterDesktopPluginRegistrar* FlutterDesktopPluginRegistrarRef; + +// Returns the engine messenger associated with this registrar. +FLUTTER_EXPORT FlutterDesktopMessengerRef +FlutterDesktopRegistrarGetMessenger(FlutterDesktopPluginRegistrarRef registrar); + +// Enables input blocking on the given channel. +// +// If set, then the Flutter window will disable input callbacks +// while waiting for the handler for messages on that channel to run. This is +// useful if handling the message involves showing a modal window, for instance. +// +// This must be called after FlutterDesktopSetMessageHandler, as setting a +// handler on a channel will reset the input blocking state back to the +// default of disabled. +FLUTTER_EXPORT void FlutterDesktopRegistrarEnableInputBlocking( + FlutterDesktopPluginRegistrarRef registrar, + const char* channel); + +#if defined(__cplusplus) +} // extern "C" +#endif + +#endif // FLUTTER_SHELL_PLATFORM_COMMON_CPP_PUBLIC_FLUTTER_PLUGIN_REGISTRAR_H_ diff --git a/app/linux/flutter/generated_config b/app/linux/flutter/generated_config new file mode 100644 index 0000000..5438e1d --- /dev/null +++ b/app/linux/flutter/generated_config @@ -0,0 +1,6 @@ +# Generated code do not commit. +export FLUTTER_ROOT=/home/kevin/Work/github.com/flutter/flutter +export BUILD=debug +export TRACK_WIDGET_CREATION=true +export FLUTTER_TARGET=lib/main.dart +export PROJECT_DIR=/home/kevin/Work/github.com/rushio-consulting/stashall/app diff --git a/app/linux/flutter/icudtl.dat b/app/linux/flutter/icudtl.dat new file mode 100644 index 0000000..d9677ab Binary files /dev/null and b/app/linux/flutter/icudtl.dat differ diff --git a/app/linux/flutter/libflutter_linux.so b/app/linux/flutter/libflutter_linux.so new file mode 100755 index 0000000..317bd90 Binary files /dev/null and b/app/linux/flutter/libflutter_linux.so differ diff --git a/app/linux/flutter_embedder_example.cc b/app/linux/flutter_embedder_example.cc new file mode 100644 index 0000000..d87734f --- /dev/null +++ b/app/linux/flutter_embedder_example.cc @@ -0,0 +1,71 @@ +// Copyright 2018 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include + +#include +#include +#include +#include + +#include + +namespace { + +// Returns the path of the directory containing this executable, or an empty +// string if the directory cannot be found. +std::string GetExecutableDirectory() { + char buffer[PATH_MAX + 1]; + ssize_t length = readlink("/proc/self/exe", buffer, sizeof(buffer)); + if (length > PATH_MAX) { + std::cerr << "Couldn't locate executable" << std::endl; + return ""; + } + std::string executable_path(buffer, length); + size_t last_separator_position = executable_path.find_last_of('/'); + if (last_separator_position == std::string::npos) { + std::cerr << "Unabled to find parent directory of " << executable_path + << std::endl; + return ""; + } + return executable_path.substr(0, last_separator_position); +} + +} // namespace + +int main(int argc, char **argv) { + // Resources are located relative to the executable. + std::string base_directory = GetExecutableDirectory(); + if (base_directory.empty()) { + base_directory = "."; + } + std::string data_directory = base_directory + "/data"; + std::string assets_path = data_directory + "/flutter_assets"; + std::string icu_data_path = data_directory + "/icudtl.dat"; + + // Arguments for the Flutter Engine. + std::vector arguments; + + flutter::FlutterWindowController flutter_controller(icu_data_path); + + // Start the engine. + if (!flutter_controller.CreateWindow(800, 600, "Flutter Desktop Example", + assets_path, arguments)) { + return EXIT_FAILURE; + } + + // Run until the window is closed. + flutter_controller.RunEventLoop(); + return EXIT_SUCCESS; +} diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 9fc80d5..7f6f3fb 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -20,3 +20,19 @@ dev_dependencies: flutter: uses-material-design: true + + fonts: + - family: Roboto + fonts: + - asset: fonts/Roboto/Roboto-Thin.ttf + weight: 100 + - asset: fonts/Roboto/Roboto-Light.ttf + weight: 300 + - asset: fonts/Roboto/Roboto-Regular.ttf + weight: 400 + - asset: fonts/Roboto/Roboto-Medium.ttf + weight: 500 + - asset: fonts/Roboto/Roboto-Bold.ttf + weight: 700 + - asset: fonts/Roboto/Roboto-Black.ttf + weight: 900