diff --git a/DeskControler/DeskControler.cpp b/DeskControler/DeskControler.cpp index 882a5eb..3a84ada 100644 --- a/DeskControler/DeskControler.cpp +++ b/DeskControler/DeskControler.cpp @@ -4,6 +4,7 @@ #include #include #include "VideoWidget.h" +#include "RemoteClipboard.h" #include "LogWidget.h" DeskControler::DeskControler(QWidget* parent) @@ -201,6 +202,11 @@ void DeskControler::setupVideoSession(const QString& relayServer, quint16 relayP m_videoReceiver = new VideoReceiver(this); + RemoteClipboard* remoteClipboard = new RemoteClipboard(this); + + connect(remoteClipboard, &RemoteClipboard::clipboardDataReady, + m_videoReceiver, &VideoReceiver::clipboardDataCaptured); + connect(videoWidget, &VideoWidget::mouseEventCaptured, m_videoReceiver, &VideoReceiver::mouseEventCaptured); diff --git a/DeskControler/DeskControler.vcxproj b/DeskControler/DeskControler.vcxproj index 054de3d..2dfa9bd 100644 --- a/DeskControler/DeskControler.vcxproj +++ b/DeskControler/DeskControler.vcxproj @@ -73,6 +73,7 @@ + @@ -104,6 +105,9 @@ + + + diff --git a/DeskControler/NetworkWorker.cpp b/DeskControler/NetworkWorker.cpp index f183aab..e383782 100644 --- a/DeskControler/NetworkWorker.cpp +++ b/DeskControler/NetworkWorker.cpp @@ -228,6 +228,40 @@ void NetworkWorker::sendKeyEventToServer(int key, bool pressed) } } +void NetworkWorker::sendClipboardEventToServer(const ClipboardEvent& clipboardEvent) +{ + if (m_socket->state() != QAbstractSocket::ConnectedState) { + return; // 如果没有连接上 RelayServer,就不发送 + } + + // 组装 ClipboardEvent 消息到 RendezvousMessage 中 + RendezvousMessage msg; + *msg.mutable_clipboardevent() = clipboardEvent; + + std::string serialized; + if (!msg.SerializeToString(&serialized)) { + LogWidget::instance()->addLog("Failed to serialize ClipboardEvent message", LogWidget::Error); + return; + } + + QByteArray protobufData(serialized.data(), serialized.size()); + + // 计算长度头(大端序) + quint32 len = static_cast(protobufData.size()); + quint32 len_be = qToBigEndian(len); // 大端序转换 + + // 构造完整数据 + QByteArray sendData; + sendData.append(reinterpret_cast(&len_be), sizeof(len_be)); + sendData.append(protobufData); + + if (m_socket && m_socket->state() == QAbstractSocket::ConnectedState) { + m_socket->write(sendData); + m_socket->flush(); + } +} + + void NetworkWorker::onSocketError(QAbstractSocket::SocketError socketError) { diff --git a/DeskControler/NetworkWorker.h b/DeskControler/NetworkWorker.h index 5018736..fee59bb 100644 --- a/DeskControler/NetworkWorker.h +++ b/DeskControler/NetworkWorker.h @@ -19,6 +19,7 @@ public slots: void cleanup(); void sendMouseEventToServer(int x, int y, int mask); void sendKeyEventToServer(int key, bool pressed); + void sendClipboardEventToServer(const ClipboardEvent& clipboardEvent); signals: diff --git a/DeskControler/RemoteClipboard.cpp b/DeskControler/RemoteClipboard.cpp new file mode 100644 index 0000000..c2da3d5 --- /dev/null +++ b/DeskControler/RemoteClipboard.cpp @@ -0,0 +1,67 @@ +#include "RemoteClipboard.h" +#include +#include +#include +#include +#include +#include "LogWidget.h" + +RemoteClipboard::RemoteClipboard(QObject* parent) + : QObject(parent) +{ + qApp->installEventFilter(this); +} + + +bool RemoteClipboard::eventFilter(QObject* /*obj*/, QEvent* event) +{ + if (event->type() == QEvent::KeyPress) { + QKeyEvent* keyEvent = static_cast(event); + if ((keyEvent->modifiers() & Qt::ControlModifier) && keyEvent->key() == Qt::Key_C) { + QClipboard* clipboard = QApplication::clipboard(); + const QMimeData* mimeData = clipboard->mimeData(); + if (mimeData) { + LogWidget::instance()->addLog("Control side: Detected Ctrl+C, sending clipboard data", LogWidget::Info); + sendClipboardData(mimeData); + } + else { + LogWidget::instance()->addLog("Control side: Clipboard is empty", LogWidget::Warning); + } + return true; + } + } + return QObject::eventFilter(nullptr, event); +} + +void RemoteClipboard::sendClipboardData(const QMimeData* mimeData) +{ + ClipboardEvent eventMsg; + // 如果剪贴板中包含文件 URL,优先处理文件数据 + if (mimeData->hasUrls() && !mimeData->urls().isEmpty()) { + QString filePath = mimeData->urls().first().toLocalFile(); + QFile file(filePath); + if (file.open(QIODevice::ReadOnly)) { + QByteArray data = file.readAll(); + file.close(); + FileContent* fileContent = eventMsg.mutable_file(); + fileContent->set_file_data(data.toStdString()); + QFileInfo fileInfo(filePath); + fileContent->set_file_name(fileInfo.fileName().toStdString()); + LogWidget::instance()->addLog(QString("Control side: Copied file: %1").arg(filePath), LogWidget::Info); + } + else { + LogWidget::instance()->addLog(QString("Control side: Failed to open file: %1").arg(filePath), LogWidget::Error); + return; + } + } + else if (mimeData->hasText()) { + TextContent* textContent = eventMsg.mutable_text(); + textContent->set_text_data(mimeData->text().toStdString()); + LogWidget::instance()->addLog("Control side: Copied text data", LogWidget::Info); + } + else { + LogWidget::instance()->addLog("Control side: Unsupported clipboard data", LogWidget::Warning); + return; + } + emit clipboardDataReady(eventMsg); +} diff --git a/DeskControler/RemoteClipboard.h b/DeskControler/RemoteClipboard.h new file mode 100644 index 0000000..f172620 --- /dev/null +++ b/DeskControler/RemoteClipboard.h @@ -0,0 +1,25 @@ +#ifndef REMOTECLIPBOARD_H +#define REMOTECLIPBOARD_H + +#include +#include +#include +#include "rendezvous.pb.h" + +class RemoteClipboard : public QObject { + Q_OBJECT +public: + explicit RemoteClipboard(QObject* parent = nullptr); + +protected: + bool eventFilter(QObject* obj, QEvent* event) override; + +private: + void sendClipboardData(const QMimeData* mimeData); + + +signals: + void clipboardDataReady(const ClipboardEvent& clipboardEvent); +}; + +#endif // REMOTECLIPBOARD_H diff --git a/DeskControler/VideoReceiver.cpp b/DeskControler/VideoReceiver.cpp index e69c417..cfda9cc 100644 --- a/DeskControler/VideoReceiver.cpp +++ b/DeskControler/VideoReceiver.cpp @@ -102,4 +102,12 @@ void VideoReceiver::keyEventCaptured(int key, bool pressed) Qt::QueuedConnection, Q_ARG(int, key), Q_ARG(bool, pressed)); -} \ No newline at end of file +} + +void VideoReceiver::clipboardDataCaptured(const ClipboardEvent& clipboardEvent) +{ + QMetaObject::invokeMethod(m_netWorker, + "sendClipboardEventToServer", + Qt::QueuedConnection, + Q_ARG(ClipboardEvent, clipboardEvent)); +} diff --git a/DeskControler/VideoReceiver.h b/DeskControler/VideoReceiver.h index 15e9fd4..8505361 100644 --- a/DeskControler/VideoReceiver.h +++ b/DeskControler/VideoReceiver.h @@ -4,6 +4,7 @@ #include #include #include +#include "rendezvous.pb.h" class NetworkWorker; class VideoDecoderWorker; @@ -28,6 +29,7 @@ class VideoReceiver : public QObject public slots: void mouseEventCaptured(int x, int y, int mask); void keyEventCaptured(int key, bool pressed); + void clipboardDataCaptured(const ClipboardEvent& clipboardEvent); private slots: // 褰撹В鐮佺嚎绋嬪彂鍑 frameDecoded 鏃惰皟鐢 diff --git a/DeskControler/VideoWidget.cpp b/DeskControler/VideoWidget.cpp index f581121..60bb767 100644 --- a/DeskControler/VideoWidget.cpp +++ b/DeskControler/VideoWidget.cpp @@ -20,6 +20,7 @@ void VideoWidget::setFrame(const QImage& image) setMinimumSize(currentFrame.size()); resize(currentFrame.size()); m_firstFrame = false; + } update(); diff --git a/DeskControler/VideoWidget.h b/DeskControler/VideoWidget.h index 03d9948..59c6d35 100644 --- a/DeskControler/VideoWidget.h +++ b/DeskControler/VideoWidget.h @@ -6,6 +6,7 @@ #include #include + enum MouseMask { MouseMove = 0x01, // 鼠标移动 MouseLeftDown = 0x02, // 鼠标左键按下 diff --git a/ReadMe.md b/ReadMe.md index 9e60a57..6b55153 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -28,13 +28,13 @@ SimpleRustDesk 鏄竴涓繙绋嬫闈㈡帶鍒剁郴缁熺ず渚嬮」鐩紝鍙傝 RustDesk ![榧犳爣閿洏鎺у埗 UML](diagrams/output/MouseKeyInput.svg) -## 鏂囦欢浼犺緭-浠庢帶鍒剁澶嶅埗绀烘剰鍥 (ctrlcFromControl.puml) +## 鏂囦欢浼犺緭-浠庢帶鍒剁澶嶅埗 UML 鍥 -![ctrlcFromControl](./diagrams/ctrlcFromControl.png) +![ctrlcFromControl](./diagrams/output/ctrlcFromControl.png) -## 鏂囦欢浼犺緭-浠庤鎺у埗绔鍒剁ず鎰忓浘 (ctrlcFromServer.puml) +## 鏂囦欢浼犺緭-浠庤鎺у埗绔鍒 UML 鍥 -![ctrlcFromServer](./diagrams/ctrlcFromServer.png) +![ctrlcFromServer](./diagrams/output/ctrlcFromServer.png) ## 娉ㄦ剰浜嬮」