Skip to content

Commit 6079c1c

Browse files
committed
[Clipboard] getData implementation added
[Before] Clipboard.getData feature was not implemented [After] Dart code below is able to gather system clipboard data: Future<ClipboardData?> d = Clipboard.getData(Clipboard.kTextPlain); void dataCallback(ClipboardData? d) { if (d != null) { String? text = d.text; if(text != null) { print("Clipboard data $text"); } } } d.then(dataCallback); [TODO] Need to consider adding some mechanism of synchronization of access to native cbhm API to provide proper behaviour in case of multiple calls
1 parent e629333 commit 6079c1c

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

shell/platform/tizen/BUILD.gn

+3-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ source_set("flutter_tizen") {
8787
"$custom_sysroot/usr/include/eo-1",
8888
"$custom_sysroot/usr/include/evas-1",
8989
"$custom_sysroot/usr/include/system",
90-
"$custom_sysroot/usr/include/wayland-extension"
90+
"$custom_sysroot/usr/include/wayland-extension",
91+
"$custom_sysroot/usr/include/cbhm",
9192
]
9293

9394
lib_dirs = [ root_out_dir, "$custom_sysroot/usr/lib" ]
@@ -114,6 +115,7 @@ source_set("flutter_tizen") {
114115
"tbm",
115116
"tdm-client",
116117
"wayland-client",
118+
"cbhm",
117119
]
118120

119121
if (tizen_sdk_4) {

shell/platform/tizen/channels/platform_channel.cc

+83-1
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,25 @@
44

55
#include "platform_channel.h"
66

7+
#include <mutex>
78
#include <app.h>
9+
#include <cbhm.h>
810

911
#include "flutter/shell/platform/common/cpp/json_method_codec.h"
1012
#include "flutter/shell/platform/tizen/tizen_log.h"
1113

1214
static constexpr char kChannelName[] = "flutter/platform";
1315

16+
// Clipboard.getData constants and variables
17+
std::mutex is_processing_mutex;
18+
static bool is_processing = false;
19+
static constexpr char kTextKey[] = "text";
20+
static constexpr char kTextPlainFormat[] = "text/plain";
21+
static constexpr char kUnknownClipboardFormatError[] =
22+
"Unknown clipboard format error";
23+
static constexpr char kUnknownClipboardError[] =
24+
"Unknown error during clipboard data retrieval";
25+
1426
PlatformChannel::PlatformChannel(flutter::BinaryMessenger* messenger)
1527
: channel_(std::make_unique<flutter::MethodChannel<rapidjson::Document>>(
1628
messenger, kChannelName, &flutter::JsonMethodCodec::GetInstance())) {
@@ -37,7 +49,77 @@ void PlatformChannel::HandleMethodCall(
3749
} else if (method == "HapticFeedback.vibrate") {
3850
result->NotImplemented();
3951
} else if (method == "Clipboard.getData") {
40-
result->NotImplemented();
52+
const rapidjson::Value& format = call.arguments()[0];
53+
54+
// https://api.flutter.dev/flutter/services/Clipboard/kTextPlain-constant.html
55+
// API supports only kTextPlain format, hovewer cbhm API supports also other formats
56+
if (strcmp(format.GetString(), kTextPlainFormat) != 0) {
57+
result->Error(kUnknownClipboardFormatError,
58+
"Clipboard API only supports text.");
59+
return;
60+
}
61+
62+
cbhm_sel_type_e selection_type = CBHM_SEL_TYPE_TEXT;
63+
64+
cbhm_h cbhm_handle = nullptr;
65+
int ret = cbhm_open_service (&cbhm_handle);
66+
if (CBHM_ERROR_NONE != ret) {
67+
result->Error(kUnknownClipboardError, "Failed to initialize cbhm service.");
68+
return;
69+
}
70+
71+
// Report error on next calls until current will be finished.
72+
// Native API - cbhm_selection_get works on static struct, so accessing clipboard parallelly will end
73+
// with race regarding returning values - cbhm_selection_data_cb will be triggered only for latest call.
74+
// TODO consider some queuing mechnism instead of returning error for next calls
75+
{
76+
std::lock_guard<std::mutex> lock(is_processing_mutex);
77+
if (is_processing) {
78+
result->Error(kUnknownClipboardError, "Already processing by other thread.");
79+
return;
80+
}
81+
is_processing = true;
82+
}
83+
struct method_data_t {
84+
std::unique_ptr<flutter::MethodResult<rapidjson::Document>> result;
85+
cbhm_h cbhm_handle;
86+
};
87+
// invalidates the result pointer
88+
method_data_t* data = new method_data_t{};
89+
data->result = std::move(result);
90+
data->cbhm_handle = cbhm_handle;
91+
92+
auto cbhm_selection_data_cb = [](cbhm_h cbhm_handle, const char *buf, size_t len, void *user_data) -> int {
93+
auto data = static_cast<method_data_t*>(user_data);
94+
// move unique_ptr from method_data_t and then release memory
95+
auto result = std::move(data->result);
96+
delete data;
97+
cbhm_close_service (data->cbhm_handle);
98+
99+
FT_LOGD("cbhm_selection_get SUCCESS (%d) %s", len, buf);
100+
{
101+
std::lock_guard<std::mutex> lock(is_processing_mutex);
102+
is_processing = false;
103+
}
104+
if (buf) {
105+
rapidjson::Document document;
106+
document.SetObject();
107+
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
108+
document.AddMember(rapidjson::Value(kTextKey, allocator),
109+
rapidjson::Value(std::string{buf, len}, allocator), allocator);
110+
result->Success(document);
111+
return CBHM_ERROR_NONE;
112+
} else {
113+
result->Error(kUnknownClipboardError, "Data buffer is null.");
114+
return CBHM_ERROR_NO_DATA;
115+
}
116+
};
117+
118+
ret = cbhm_selection_get(cbhm_handle, selection_type, cbhm_selection_data_cb, data);
119+
if (CBHM_ERROR_NONE != ret) {
120+
result->Error(kUnknownClipboardError, "Failed to gather data.");
121+
return;
122+
}
41123
} else if (method == "Clipboard.setData") {
42124
result->NotImplemented();
43125
} else if (method == "Clipboard.hasStrings") {

0 commit comments

Comments
 (0)