[feat] support clipboard sharing, refs #35

This commit is contained in:
dijunkun
2025-12-29 00:45:17 +08:00
parent c70ebdfe15
commit 17b7ba6b72
8 changed files with 724 additions and 0 deletions

View File

@@ -209,6 +209,7 @@ int Render::ConnectTo(const std::string& remote_id, const char* password,
AddDataStream(props->peer_, props->data_label_.c_str(), false);
AddDataStream(props->peer_, props->file_label_.c_str(), true);
AddDataStream(props->peer_, props->file_feedback_label_.c_str(), true);
AddDataStream(props->peer_, props->clipboard_label_.c_str(), true);
props->connection_status_ = ConnectionStatus::Connecting;

View File

@@ -9,6 +9,7 @@
#include <thread>
#include "OPPOSans_Regular.h"
#include "clipboard.h"
#include "device_controller_factory.h"
#include "fa_regular_400.h"
#include "fa_solid_900.h"
@@ -717,6 +718,7 @@ int Render::CreateConnectionPeer() {
AddDataStream(peer_, data_label_.c_str(), false);
AddDataStream(peer_, file_label_.c_str(), true);
AddDataStream(peer_, file_feedback_label_.c_str(), true);
AddDataStream(peer_, clipboard_label_.c_str(), true);
return 0;
} else {
return -1;
@@ -1267,6 +1269,26 @@ void Render::InitializeModules() {
keyboard_capturer_ = (KeyboardCapturer*)device_controller_factory_->Create(
DeviceControllerFactory::Device::Keyboard);
CreateConnectionPeer();
// start clipboard monitoring with callback to send data to peers
Clipboard::StartMonitoring(
100, [this](const char* data, size_t size) -> int {
// send clipboard data to all connected peers
std::shared_lock lock(client_properties_mutex_);
int ret = -1;
for (const auto& [remote_id, props] : client_properties_) {
if (props && props->peer_ && props->connection_established_) {
ret = SendReliableDataFrame(props->peer_, data, size,
props->clipboard_label_.c_str());
if (ret != 0) {
LOG_WARN("Failed to send clipboard data to peer [{}], ret={}",
remote_id.c_str(), ret);
}
}
}
return ret;
});
modules_inited_ = true;
}
}
@@ -1398,6 +1420,8 @@ void Render::HandleStreamWindow() {
}
void Render::Cleanup() {
Clipboard::StopMonitoring();
if (screen_capturer_) {
screen_capturer_->Destroy();
delete screen_capturer_;

View File

@@ -49,6 +49,7 @@ class Render {
std::string data_label_ = "control_data";
std::string file_label_ = "file";
std::string file_feedback_label_ = "file_feedback";
std::string clipboard_label_ = "clipboard";
std::string local_id_ = "";
std::string remote_id_ = "";
bool exit_ = false;
@@ -515,6 +516,7 @@ class Render {
std::string control_data_label_ = "control_data";
std::string file_label_ = "file";
std::string file_feedback_label_ = "file_feedback";
std::string clipboard_label_ = "clipboard";
Params params_;
// Map file_id to props for tracking file transfer progress via ACK
std::unordered_map<uint32_t, std::weak_ptr<SubStreamWindowProperties>>

View File

@@ -6,6 +6,7 @@
#include <fstream>
#include <unordered_map>
#include "clipboard.h"
#include "device_controller.h"
#include "file_transfer.h"
#include "localization.h"
@@ -327,6 +328,14 @@ void Render::OnReceiveDataBufferCb(const char* data, size_t size,
receiver.OnData(data, size);
return;
} else if (source_id == render->clipboard_label_) {
if (size > 0) {
std::string clipboard_text(data, size);
if (!Clipboard::SetText(clipboard_text)) {
LOG_ERROR("Failed to set clipboard content from remote");
}
}
return;
} else if (source_id == render->file_feedback_label_) {
if (size < sizeof(FileTransferAck)) {
LOG_ERROR("FileTransferAck: buffer too small, size={}", size);