1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "flutter/shell/platform/windows/platform_handler.h"
6
7 #include <windows.h>
8
9 #include <iostream>
10
11 #include "flutter/shell/platform/common/cpp/client_wrapper/include/flutter/json_method_codec.h"
12
13 static constexpr char kChannelName[] = "flutter/platform";
14
15 static constexpr char kGetClipboardDataMethod[] = "Clipboard.getData";
16 static constexpr char kSetClipboardDataMethod[] = "Clipboard.setData";
17
18 static constexpr char kTextPlainFormat[] = "text/plain";
19 static constexpr char kTextKey[] = "text";
20
21 static constexpr char kUnknownClipboardFormatError[] =
22 "Unknown clipboard format error";
23
24 namespace flutter {
25
PlatformHandler(flutter::BinaryMessenger * messenger,Win32FlutterWindow * window)26 PlatformHandler::PlatformHandler(flutter::BinaryMessenger* messenger,
27 Win32FlutterWindow* window)
28 : channel_(std::make_unique<flutter::MethodChannel<rapidjson::Document>>(
29 messenger,
30 kChannelName,
31 &flutter::JsonMethodCodec::GetInstance())),
32 window_(window) {
33 channel_->SetMethodCallHandler(
34 [this](
35 const flutter::MethodCall<rapidjson::Document>& call,
36 std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result) {
37 HandleMethodCall(call, std::move(result));
38 });
39 }
40
HandleMethodCall(const flutter::MethodCall<rapidjson::Document> & method_call,std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result)41 void PlatformHandler::HandleMethodCall(
42 const flutter::MethodCall<rapidjson::Document>& method_call,
43 std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result) {
44 const std::string& method = method_call.method_name();
45 if (method.compare(kGetClipboardDataMethod) == 0) {
46 // Only one string argument is expected.
47 const rapidjson::Value& format = method_call.arguments()[0];
48
49 if (strcmp(format.GetString(), kTextPlainFormat) != 0) {
50 result->Error(kUnknownClipboardFormatError,
51 "Windows clipboard API only supports text.");
52 return;
53 }
54
55 auto clipboardData = GetClipboardString();
56
57 if (clipboardData.empty()) {
58 result->Error(kUnknownClipboardFormatError,
59 "Failed to retrieve clipboard data from win32 api.");
60 return;
61 }
62 rapidjson::Document document;
63 document.SetObject();
64 rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
65 document.AddMember(rapidjson::Value(kTextKey, allocator),
66 rapidjson::Value(clipboardData, allocator), allocator);
67 result->Success(&document);
68
69 } else if (method.compare(kSetClipboardDataMethod) == 0) {
70 const rapidjson::Value& document = *method_call.arguments();
71 rapidjson::Value::ConstMemberIterator itr = document.FindMember(kTextKey);
72 if (itr == document.MemberEnd()) {
73 result->Error(kUnknownClipboardFormatError,
74 "Missing text to store on clipboard.");
75 return;
76 }
77 SetClipboardString(std::string(itr->value.GetString()));
78 result->Success();
79 } else {
80 result->NotImplemented();
81 }
82 }
83
GetClipboardString()84 std::string PlatformHandler::GetClipboardString() {
85 if (!OpenClipboard(nullptr)) {
86 return nullptr;
87 }
88
89 HANDLE data = GetClipboardData(CF_TEXT);
90 if (data == nullptr) {
91 CloseClipboard();
92 return nullptr;
93 }
94
95 const char* clipboardData = static_cast<char*>(GlobalLock(data));
96
97 if (clipboardData == nullptr) {
98 CloseClipboard();
99 return nullptr;
100 }
101
102 auto result = std::string(clipboardData);
103 GlobalUnlock(data);
104 CloseClipboard();
105 return result;
106 }
107
SetClipboardString(std::string data)108 void PlatformHandler::SetClipboardString(std::string data) {
109 if (!OpenClipboard(nullptr)) {
110 return;
111 }
112
113 auto htext = GlobalAlloc(GMEM_MOVEABLE, data.size());
114
115 memcpy(GlobalLock(htext), data.c_str(), data.size());
116
117 SetClipboardData(CF_TEXT, htext);
118
119 CloseClipboard();
120 }
121
122 } // namespace flutter
123