From 64bb275cc4222ccefeceb28c7821d604bcb28fb3 Mon Sep 17 00:00:00 2001 From: Callum Iddon Date: Wed, 9 Jan 2019 00:16:55 -0500 Subject: [PATCH 1/3] Remove exports.def from GN Build (#221) Missed change from PR #216 --- library/BUILD.gn | 5 ----- 1 file changed, 5 deletions(-) diff --git a/library/BUILD.gn b/library/BUILD.gn index e013036f5..971238ea1 100644 --- a/library/BUILD.gn +++ b/library/BUILD.gn @@ -90,11 +90,6 @@ published_shared_library("flutter_embedder") { } if (is_win) { - dll_exports = rebase_path("windows/exports.def") - ldflags = [ - "/DEF:$dll_exports", - ] - deps += [ "//library/windows:publish_flutter_engine", "//library/windows:fetch_glfw", From 867e99e701d7817061db533cd14a0cc876487e3c Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Wed, 9 Jan 2019 14:23:49 -0800 Subject: [PATCH 2/3] [linux/windows] Add BasicMessageChannel (#219) Implements BasicMessageChannel, adds MessageCodec, and makes JsonMessageCodec public. Converts the key event handler from using BinaryMessenger directly to using a BasicMessageChannel to send events now that it's available. --- library/BUILD.gn | 6 +- library/common/glfw/key_event_handler.cc | 20 ++-- library/common/glfw/key_event_handler.h | 13 ++- .../{internal => }/json_message_codec.cc | 10 +- library/common/json_method_codec.cc | 2 +- .../basic_message_channel.h | 106 ++++++++++++++++++ .../binary_messenger.h | 4 +- .../json_message_codec.h | 35 +++--- .../flutter_desktop_embedding/message_codec.h | 61 ++++++++++ library/windows/GLFW Library.vcxproj | 2 +- library/windows/GLFW Library.vcxproj.filters | 2 +- 11 files changed, 212 insertions(+), 49 deletions(-) rename library/common/{internal => }/json_message_codec.cc (85%) create mode 100644 library/include/flutter_desktop_embedding/basic_message_channel.h rename library/{common/internal => include/flutter_desktop_embedding}/json_message_codec.h (56%) create mode 100644 library/include/flutter_desktop_embedding/message_codec.h diff --git a/library/BUILD.gn b/library/BUILD.gn index 971238ea1..b0b596bce 100644 --- a/library/BUILD.gn +++ b/library/BUILD.gn @@ -36,19 +36,21 @@ published_shared_library("flutter_embedder") { if (is_linux || is_win) { sources += [ "common/engine_method_result.cc", - "common/internal/json_message_codec.cc", - "common/internal/json_message_codec.h", "common/internal/plugin_handler.cc", "common/internal/plugin_handler.h", "common/internal/text_input_model.cc", "common/internal/text_input_model.h", + "common/json_message_codec.cc", "common/json_method_codec.cc", ] public += [ + "include/flutter_desktop_embedding/basic_message_channel.h", "include/flutter_desktop_embedding/binary_messenger.h", "include/flutter_desktop_embedding/engine_method_result.h", "include/flutter_desktop_embedding/fde_export.h", + "include/flutter_desktop_embedding/json_message_codec.h", "include/flutter_desktop_embedding/json_method_codec.h", + "include/flutter_desktop_embedding/message_codec.h", "include/flutter_desktop_embedding/method_call.h", "include/flutter_desktop_embedding/method_channel.h", "include/flutter_desktop_embedding/method_codec.h", diff --git a/library/common/glfw/key_event_handler.cc b/library/common/glfw/key_event_handler.cc index 0b6e4e36d..d2337cd67 100644 --- a/library/common/glfw/key_event_handler.cc +++ b/library/common/glfw/key_event_handler.cc @@ -16,7 +16,7 @@ #include #include -#include "library/common/internal/json_message_codec.h" +#include "library/include/flutter_desktop_embedding/json_message_codec.h" static constexpr char kChannelName[] = "flutter/keyevent"; @@ -32,8 +32,9 @@ static constexpr char kRepeat[] = "repeat"; namespace flutter_desktop_embedding { -KeyEventHandler::KeyEventHandler(const BinaryMessenger *messenger) - : messenger_(messenger), channel_(kChannelName) {} +KeyEventHandler::KeyEventHandler(BinaryMessenger *messenger) + : channel_(std::make_unique>( + messenger, kChannelName, &JsonMessageCodec::GetInstance())) {} KeyEventHandler::~KeyEventHandler() {} @@ -43,23 +44,22 @@ void KeyEventHandler::KeyboardHook(GLFWwindow *window, int key, int scancode, int action, int mods) { // TODO: Translate to a cross-platform key code system rather than passing // the native key code. - Json::Value args; - args[kKeyCodeKey] = key; - args[kKeyMapKey] = kAndroidKeyMap; + Json::Value event; + event[kKeyCodeKey] = key; + event[kKeyMapKey] = kAndroidKeyMap; switch (action) { case GLFW_PRESS: - args[kTypeKey] = kKeyDown; + event[kTypeKey] = kKeyDown; break; case GLFW_RELEASE: - args[kTypeKey] = kKeyUp; + event[kTypeKey] = kKeyUp; break; default: std::cerr << "Unknown key event action: " << action << std::endl; return; } - auto message = JsonMessageCodec::GetInstance().EncodeMessage(args); - messenger_->Send(channel_, message->data(), message->size()); + channel_->Send(event); } } // namespace flutter_desktop_embedding \ No newline at end of file diff --git a/library/common/glfw/key_event_handler.h b/library/common/glfw/key_event_handler.h index ccf86b20d..5e086db93 100644 --- a/library/common/glfw/key_event_handler.h +++ b/library/common/glfw/key_event_handler.h @@ -14,7 +14,12 @@ #ifndef LIBRARY_COMMON_GLFW_KEY_EVENT_HANDLER_H_ #define LIBRARY_COMMON_GLFW_KEY_EVENT_HANDLER_H_ +#include + +#include + #include "library/common/glfw/keyboard_hook_handler.h" +#include "library/include/flutter_desktop_embedding/basic_message_channel.h" #include "library/include/flutter_desktop_embedding/binary_messenger.h" namespace flutter_desktop_embedding { @@ -24,7 +29,7 @@ namespace flutter_desktop_embedding { // Handles key events and forwards them to the Flutter engine. class KeyEventHandler : public KeyboardHookHandler { public: - explicit KeyEventHandler(const BinaryMessenger *messenger); + explicit KeyEventHandler(BinaryMessenger *messenger); virtual ~KeyEventHandler(); // KeyboardHookHandler. @@ -33,10 +38,8 @@ class KeyEventHandler : public KeyboardHookHandler { void CharHook(GLFWwindow *window, unsigned int code_point) override; private: - // Binds this plugin to the given caller-owned binary messenger. It must - // remain valid for the life of the plugin. - const BinaryMessenger *messenger_; - std::string channel_; + // The Flutter system channel for key event messages. + std::unique_ptr> channel_; }; } // namespace flutter_desktop_embedding diff --git a/library/common/internal/json_message_codec.cc b/library/common/json_message_codec.cc similarity index 85% rename from library/common/internal/json_message_codec.cc rename to library/common/json_message_codec.cc index 8cf5dfb64..8eda6714d 100644 --- a/library/common/internal/json_message_codec.cc +++ b/library/common/json_message_codec.cc @@ -11,7 +11,7 @@ // 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 "library/common/internal/json_message_codec.h" +#include "library/include/flutter_desktop_embedding/json_message_codec.h" #include #include @@ -24,7 +24,7 @@ const JsonMessageCodec &JsonMessageCodec::GetInstance() { return sInstance; } -std::unique_ptr> JsonMessageCodec::EncodeMessage( +std::unique_ptr> JsonMessageCodec::EncodeMessageInternal( const Json::Value &message) const { Json::StreamWriterBuilder writer_builder; std::string serialization = Json::writeString(writer_builder, message); @@ -33,12 +33,12 @@ std::unique_ptr> JsonMessageCodec::EncodeMessage( serialization.end()); } -std::unique_ptr JsonMessageCodec::DecodeMessage( - const uint8_t *message, const size_t message_size) const { +std::unique_ptr JsonMessageCodec::DecodeMessageInternal( + const uint8_t *binary_message, const size_t message_size) const { Json::CharReaderBuilder reader_builder; std::unique_ptr parser(reader_builder.newCharReader()); - auto raw_message = reinterpret_cast(message); + auto raw_message = reinterpret_cast(binary_message); auto json_message = std::make_unique(); std::string parse_errors; bool parsing_successful = diff --git a/library/common/json_method_codec.cc b/library/common/json_method_codec.cc index 2538860c4..717f8bc81 100644 --- a/library/common/json_method_codec.cc +++ b/library/common/json_method_codec.cc @@ -13,7 +13,7 @@ // limitations under the License. #include "library/include/flutter_desktop_embedding/json_method_codec.h" -#include "library/common/internal/json_message_codec.h" +#include "library/include/flutter_desktop_embedding/json_message_codec.h" namespace flutter_desktop_embedding { diff --git a/library/include/flutter_desktop_embedding/basic_message_channel.h b/library/include/flutter_desktop_embedding/basic_message_channel.h new file mode 100644 index 000000000..25882e250 --- /dev/null +++ b/library/include/flutter_desktop_embedding/basic_message_channel.h @@ -0,0 +1,106 @@ +// 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. +#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_BASIC_MESSAGE_CHANNEL_H_ +#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_BASIC_MESSAGE_CHANNEL_H_ + +#include +#include + +#include "binary_messenger.h" +#include "fde_export.h" +#include "message_codec.h" + +namespace flutter_desktop_embedding { + +// 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 FDE_EXPORT BasicMessageChannel { + public: + // Creates an instance that sends and receives method calls on the channel + // named |name|, encoded with |codec| and dispatched via |messenger|. + // + // TODO: Make codec optional once the standard codec is supported (Issue #67). + BasicMessageChannel(BinaryMessenger *messenger, const std::string &name, + const MessageCodec *codec) + : messenger_(messenger), name_(name), codec_(codec) {} + ~BasicMessageChannel() {} + + // 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_desktop_embedding + +#endif // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_BASIC_MESSAGE_CHANNEL_H_ diff --git a/library/include/flutter_desktop_embedding/binary_messenger.h b/library/include/flutter_desktop_embedding/binary_messenger.h index 13f18ac33..3252ad596 100644 --- a/library/include/flutter_desktop_embedding/binary_messenger.h +++ b/library/include/flutter_desktop_embedding/binary_messenger.h @@ -23,9 +23,9 @@ // the message/message_size pairs. namespace flutter_desktop_embedding { -// A message reply callback. +// A binary message reply callback. // -// Used for submitting a reply back to a Flutter message sender. +// Used for submitting a binary reply back to a Flutter message sender. typedef std::function BinaryReply; diff --git a/library/common/internal/json_message_codec.h b/library/include/flutter_desktop_embedding/json_message_codec.h similarity index 56% rename from library/common/internal/json_message_codec.h rename to library/include/flutter_desktop_embedding/json_message_codec.h index fbd53e3f9..8a824e67f 100644 --- a/library/common/internal/json_message_codec.h +++ b/library/include/flutter_desktop_embedding/json_message_codec.h @@ -11,23 +11,19 @@ // 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. -#ifndef LIBRARY_COMMON_INTERNAL_JSON_MESSAGE_CODEC_H_ -#define LIBRARY_COMMON_INTERNAL_JSON_MESSAGE_CODEC_H_ - -#include -#include +#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_MESSAGE_CODEC_H_ +#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_MESSAGE_CODEC_H_ #include +#include "fde_export.h" +#include "message_codec.h" + namespace flutter_desktop_embedding { // A message encoding/decoding mechanism for communications to/from the // Flutter engine via JSON channels. -// -// TODO: Make this public, once generalizing a MessageCodec parent interface is -// addressed; this is complicated by the return type of EncodeMessage. -// Part of issue #102. -class JsonMessageCodec { +class JsonMessageCodec : public MessageCodec { public: // Returns the shared instance of the codec. static const JsonMessageCodec &GetInstance(); @@ -38,22 +34,17 @@ class JsonMessageCodec { JsonMessageCodec(JsonMessageCodec const &) = delete; JsonMessageCodec &operator=(JsonMessageCodec const &) = delete; - // Returns a binary encoding of the given message, or nullptr if the - // message cannot be serialized by this codec. - std::unique_ptr> EncodeMessage( - const Json::Value &message) const; - - // Returns the JSON object encoded in |message|, or nullptr if it cannot be - // decoded. - // TODO: Consider adding absl as a dependency and using absl::Span. - std::unique_ptr DecodeMessage(const uint8_t *message, - const size_t message_size) const; - protected: // Instances should be obtained via GetInstance. JsonMessageCodec() = default; + + // MessageCodec: + std::unique_ptr DecodeMessageInternal( + const uint8_t *binary_message, const size_t message_size) const override; + std::unique_ptr> EncodeMessageInternal( + const Json::Value &message) const override; }; } // namespace flutter_desktop_embedding -#endif // LIBRARY_COMMON_INTERNAL_JSON_MESSAGE_CODEC_H_ +#endif // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_JSON_MESSAGE_CODEC_H_ diff --git a/library/include/flutter_desktop_embedding/message_codec.h b/library/include/flutter_desktop_embedding/message_codec.h new file mode 100644 index 000000000..7ad2d518f --- /dev/null +++ b/library/include/flutter_desktop_embedding/message_codec.h @@ -0,0 +1,61 @@ +// Copyright 2019 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. +#ifndef LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_MESSAGE_CODEC_H_ +#define LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_MESSAGE_CODEC_H_ + +#include +#include +#include + +#include "fde_export.h" + +namespace flutter_desktop_embedding { + +// Translates between a binary message and higher-level method call and +// response/error objects. +template +class FDE_EXPORT 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. + // TODO: Consider adding absl as a dependency and using absl::Span. + std::unique_ptr DecodeMessage(const uint8_t *binary_message, + const size_t message_size) const { + return std::move(DecodeMessageInternal(binary_message, message_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: + // Implementations 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; + virtual std::unique_ptr> EncodeMessageInternal( + const T &message) const = 0; +}; + +} // namespace flutter_desktop_embedding + +#endif // LIBRARY_INCLUDE_FLUTTER_DESKTOP_EMBEDDING_MESSAGE_CODEC_H_ diff --git a/library/windows/GLFW Library.vcxproj b/library/windows/GLFW Library.vcxproj index f0dbd4f95..d7dfa8a2f 100644 --- a/library/windows/GLFW Library.vcxproj +++ b/library/windows/GLFW Library.vcxproj @@ -150,9 +150,9 @@ - + diff --git a/library/windows/GLFW Library.vcxproj.filters b/library/windows/GLFW Library.vcxproj.filters index c0b1920c8..bf62d4890 100644 --- a/library/windows/GLFW Library.vcxproj.filters +++ b/library/windows/GLFW Library.vcxproj.filters @@ -24,7 +24,7 @@ Source Files - + Source Files From 181519441377a63b4dead5099d719dadbd8a20f8 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Wed, 9 Jan 2019 19:13:08 -0800 Subject: [PATCH 3/3] [linux] Use pkg-config for libglfw (#220) The makes libglfw added via pkg-config calls, rather than manually, for consistency with other similar dependencies. --- build/linux/config/BUILD.gn | 16 ++++++++++------ example/linux/Makefile | 5 ++--- library/BUILD.gn | 2 +- library/linux/Makefile | 6 +++--- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/build/linux/config/BUILD.gn b/build/linux/config/BUILD.gn index c3af658f1..af00df3e5 100644 --- a/build/linux/config/BUILD.gn +++ b/build/linux/config/BUILD.gn @@ -14,18 +14,22 @@ import("//third_party/chromium/build/config/linux/pkg_config.gni") -pkg_config("gtk3") { - packages = [ "gtk+-3.0" ] -} - pkg_config("epoxy") { packages = [ "epoxy" ] } -pkg_config("x11") { - packages = [ "x11" ] +pkg_config("glfw3") { + packages = [ "glfw3" ] +} + +pkg_config("gtk3") { + packages = [ "gtk+-3.0" ] } pkg_config("jsoncpp") { packages = [ "jsoncpp" ] } + +pkg_config("x11") { + packages = [ "x11" ] +} diff --git a/example/linux/Makefile b/example/linux/Makefile index 5cf7fa045..e09be8d80 100644 --- a/example/linux/Makefile +++ b/example/linux/Makefile @@ -83,14 +83,13 @@ endif # Build settings CXX=g++ -std=c++14 -CXXFLAGS=-Wall -Werror $(shell pkg-config --cflags jsoncpp) +CXXFLAGS=-Wall -Werror $(shell pkg-config --cflags jsoncpp glfw3) CPPFLAGS=$(patsubst %,-I%,$(INCLUDE_DIRS)) ifdef USE_GN CPPFLAGS+=-DUSE_FLATTENED_INCLUDES endif LDFLAGS=-L$(OUT_LIB_DIR) \ - -lglfw \ - $(shell pkg-config --libs jsoncpp) \ + $(shell pkg-config --libs jsoncpp glfw3) \ -l$(FLUTTER_EMBEDDER_LIB_NAME) \ -l$(FLUTTER_ENGINE_LIB_NAME) \ $(patsubst %,-l$(PLUGIN_LIB_NAME_PREFIX)%,$(PLUGIN_NAMES)) \ diff --git a/library/BUILD.gn b/library/BUILD.gn index b0b596bce..5e1873f36 100644 --- a/library/BUILD.gn +++ b/library/BUILD.gn @@ -75,7 +75,6 @@ published_shared_library("flutter_embedder") { if (is_linux) { libs = [ - "glfw", "GL", ] @@ -85,6 +84,7 @@ published_shared_library("flutter_embedder") { configs += [ "//build/linux/config:epoxy", + "//build/linux/config:glfw3", "//build/linux/config:gtk3", "//build/linux/config:jsoncpp", "//build/linux/config:x11", diff --git a/library/linux/Makefile b/library/linux/Makefile index df7b62ebe..ba9b01a0f 100644 --- a/library/linux/Makefile +++ b/library/linux/Makefile @@ -27,10 +27,10 @@ CXXFLAGS= -Wall -Werror -shared -fPIC -fvisibility=hidden \ -I$(PROJECT_ROOT)/library/include \ -I$(FLUTTER_ENGINE_HEADER_DIR) \ -DFLUTTER_DESKTOP_EMBEDDING_IMPL \ - $(shell pkg-config --cflags gtk+-3.0 epoxy x11 jsoncpp) + $(shell pkg-config --cflags gtk+-3.0 epoxy x11 jsoncpp glfw3) LDFLAGS= -L$(CURDIR) \ - $(shell pkg-config --libs gtk+-3.0 epoxy x11 jsoncpp) \ - -lglfw -lGL -l$(FLUTTER_ENGINE_LIB_NAME) \ + $(shell pkg-config --libs gtk+-3.0 epoxy x11 jsoncpp glfw3) \ + -lGL -l$(FLUTTER_ENGINE_LIB_NAME) \ -Wl,-rpath=$(CURDIR)