From 8eb78e2baadf33e242981414858abc425b00c8a0 Mon Sep 17 00:00:00 2001 From: Francisco Magdaleno Date: Tue, 18 Jun 2019 16:57:01 -0700 Subject: [PATCH] [glfw] Implement clipboard support from GLFW api (flutter/engine#9361) --- .../ci/licenses_golden/licenses_flutter | 2 + .../src/flutter/shell/platform/glfw/BUILD.gn | 2 + .../shell/platform/glfw/flutter_glfw.cc | 6 ++ .../shell/platform/glfw/platform_handler.cc | 80 +++++++++++++++++++ .../shell/platform/glfw/platform_handler.h | 38 +++++++++ 5 files changed, 128 insertions(+) create mode 100644 engine/src/flutter/shell/platform/glfw/platform_handler.cc create mode 100644 engine/src/flutter/shell/platform/glfw/platform_handler.h diff --git a/engine/src/flutter/ci/licenses_golden/licenses_flutter b/engine/src/flutter/ci/licenses_golden/licenses_flutter index 5d162e74d7..9d18645670 100644 --- a/engine/src/flutter/ci/licenses_golden/licenses_flutter +++ b/engine/src/flutter/ci/licenses_golden/licenses_flutter @@ -917,6 +917,8 @@ FILE: ../../../flutter/shell/platform/glfw/flutter_glfw.cc FILE: ../../../flutter/shell/platform/glfw/key_event_handler.cc FILE: ../../../flutter/shell/platform/glfw/key_event_handler.h FILE: ../../../flutter/shell/platform/glfw/keyboard_hook_handler.h +FILE: ../../../flutter/shell/platform/glfw/platform_handler.cc +FILE: ../../../flutter/shell/platform/glfw/platform_handler.h FILE: ../../../flutter/shell/platform/glfw/public/flutter_glfw.h FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.cc FILE: ../../../flutter/shell/platform/glfw/text_input_plugin.h diff --git a/engine/src/flutter/shell/platform/glfw/BUILD.gn b/engine/src/flutter/shell/platform/glfw/BUILD.gn index 478d2e80e3..defb5b707c 100644 --- a/engine/src/flutter/shell/platform/glfw/BUILD.gn +++ b/engine/src/flutter/shell/platform/glfw/BUILD.gn @@ -36,6 +36,8 @@ source_set("flutter_glfw") { "key_event_handler.cc", "key_event_handler.h", "keyboard_hook_handler.h", + "platform_handler.cc", + "platform_handler.h", "text_input_plugin.cc", "text_input_plugin.h", ] diff --git a/engine/src/flutter/shell/platform/glfw/flutter_glfw.cc b/engine/src/flutter/shell/platform/glfw/flutter_glfw.cc index 24caf6af1b..05cef2990e 100644 --- a/engine/src/flutter/shell/platform/glfw/flutter_glfw.cc +++ b/engine/src/flutter/shell/platform/glfw/flutter_glfw.cc @@ -17,6 +17,7 @@ #include "flutter/shell/platform/embedder/embedder.h" #include "flutter/shell/platform/glfw/key_event_handler.h" #include "flutter/shell/platform/glfw/keyboard_hook_handler.h" +#include "flutter/shell/platform/glfw/platform_handler.h" #include "flutter/shell/platform/glfw/text_input_plugin.h" // For compatibility with GTK-based plugins, special message loop setup is @@ -75,6 +76,9 @@ struct FlutterDesktopWindowControllerState { std::vector> keyboard_hook_handlers; + // Handler for the flutter/platform channel. + std::unique_ptr platform_handler; + // Whether or not the pointer has been added (or if tracking is enabled, has // been added since it was last removed). bool pointer_currently_added = false; @@ -606,6 +610,8 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow( std::make_unique(internal_plugin_messenger)); state->keyboard_hook_handlers.push_back( std::make_unique(internal_plugin_messenger)); + state->platform_handler = std::make_unique( + internal_plugin_messenger, state->window.get()); // Trigger an initial size callback to send size information to Flutter. state->monitor_screen_coordinates_per_inch = GetScreenCoordinatesPerInch(); diff --git a/engine/src/flutter/shell/platform/glfw/platform_handler.cc b/engine/src/flutter/shell/platform/glfw/platform_handler.cc new file mode 100644 index 0000000000..5e9f41ed21 --- /dev/null +++ b/engine/src/flutter/shell/platform/glfw/platform_handler.cc @@ -0,0 +1,80 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/glfw/platform_handler.h" + +#include + +#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/json_method_codec.h" + +static constexpr char kChannelName[] = "flutter/platform"; + +static constexpr char kGetClipboardDataMethod[] = "Clipboard.getData"; +static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData"; + +static constexpr char kTextPlainFormat[] = "text/plain"; +static constexpr char kTextKey[] = "text"; + +static constexpr char kUnknownClipboardFormatError[] = + "Unknown clipboard format error"; + +namespace flutter { + +PlatformHandler::PlatformHandler(flutter::BinaryMessenger* messenger, + GLFWwindow* window) + : channel_(std::make_unique>( + messenger, + kChannelName, + &flutter::JsonMethodCodec::GetInstance())), + window_(window) { + channel_->SetMethodCallHandler( + [this]( + const flutter::MethodCall& call, + std::unique_ptr> result) { + HandleMethodCall(call, std::move(result)); + }); +} + +void PlatformHandler::HandleMethodCall( + const flutter::MethodCall& method_call, + std::unique_ptr> result) { + const std::string& method = method_call.method_name(); + + if (method.compare(kGetClipboardDataMethod) == 0) { + // Only one string argument is expected. + const rapidjson::Value& format = method_call.arguments()[0]; + + if (strcmp(format.GetString(), kTextPlainFormat) != 0) { + result->Error(kUnknownClipboardFormatError, + "GLFW clipboard API only supports text."); + return; + } + + const char* clipboardData = glfwGetClipboardString(window_); + if (clipboardData == nullptr) { + result->Error(kUnknownClipboardFormatError, + "Failed to retrieve clipboard data from GLFW api."); + return; + } + rapidjson::Document document; + document.SetObject(); + rapidjson::Document::AllocatorType& allocator = document.GetAllocator(); + document.AddMember(rapidjson::Value(kTextKey, allocator), + rapidjson::Value(clipboardData, allocator), allocator); + result->Success(&document); + } else if (method.compare(kSetClipboardDataMethod) == 0) { + const rapidjson::Value& document = *method_call.arguments(); + rapidjson::Value::ConstMemberIterator itr = document.FindMember(kTextKey); + if (itr == document.MemberEnd()) { + result->Error(kUnknownClipboardFormatError, + "Missing text to store on clipboard."); + return; + } + glfwSetClipboardString(window_, itr->value.GetString()); + result->Success(); + } else { + result->NotImplemented(); + } +} +} // namespace flutter diff --git a/engine/src/flutter/shell/platform/glfw/platform_handler.h b/engine/src/flutter/shell/platform/glfw/platform_handler.h new file mode 100644 index 0000000000..99ab782c90 --- /dev/null +++ b/engine/src/flutter/shell/platform/glfw/platform_handler.h @@ -0,0 +1,38 @@ +// 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_PLATFORM_HANDLER_H_ +#define FLUTTER_SHELL_PLATFORM_GLFW_PLATFORM_HANDLER_H_ + +#include + +#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/binary_messenger.h" +#include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/method_channel.h" +#include "flutter/shell/platform/glfw/public/flutter_glfw.h" +#include "rapidjson/document.h" + +namespace flutter { + +// Handler for internal system channels. +class PlatformHandler { + public: + explicit PlatformHandler(flutter::BinaryMessenger* messenger, + GLFWwindow* window); + + private: + // Called when a method is called on |channel_|; + void HandleMethodCall( + const flutter::MethodCall& method_call, + std::unique_ptr> result); + + // The MethodChannel used for communication with the Flutter engine. + std::unique_ptr> channel_; + + // A reference to the GLFW window. + GLFWwindow* window_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_GLFW_PLATFORM_HANDLER_H_