From e655eb0d9b1236ae945f59455398e2962c84d764 Mon Sep 17 00:00:00 2001 From: liyigang Date: Mon, 24 Jun 2024 11:52:12 +0800 Subject: [PATCH] fix: Copying files from cloud desktop cannot be copied to the local machine Not listening to QT's clipboard, listening to x11's clipboard, requires colleagues from the clipboard to handle it Log: Copying files from cloud desktop cannot be copied to the local machine Bug: https://pms.uniontech.com/bug-view-259847.html --- src/dfm-base/CMakeLists.txt | 10 + src/dfm-base/utils/clipboard.cpp | 109 ++++++- src/dfm-base/utils/clipboard.h | 6 +- src/dfm-base/utils/clipboardmonitor.cpp | 273 ++++++++++++++++++ src/dfm-base/utils/clipboardmonitor.h | 35 +++ .../fileoperationseventreceiver.cpp | 3 +- .../fileoperationseventreceiver.h | 2 +- .../menuscene/clipboardmenuscene.cpp | 3 +- .../desktop/core/ddplugin-core/core.cpp | 2 +- .../filemanager/core/dfmplugin-core/core.cpp | 2 +- tests/dfm-base/CMakeLists.txt | 10 + 11 files changed, 436 insertions(+), 19 deletions(-) create mode 100644 src/dfm-base/utils/clipboardmonitor.cpp create mode 100644 src/dfm-base/utils/clipboardmonitor.h diff --git a/src/dfm-base/CMakeLists.txt b/src/dfm-base/CMakeLists.txt index 0ad0a9c06c..49f1c6d644 100644 --- a/src/dfm-base/CMakeLists.txt +++ b/src/dfm-base/CMakeLists.txt @@ -55,6 +55,14 @@ pkg_search_module(gsettings REQUIRED gsettings-qt IMPORTED_TARGET) pkg_check_modules(mount REQUIRED mount IMPORTED_TARGET) pkg_search_module(Dtk REQUIRED dtkcore IMPORTED_TARGET) pkg_search_module(X11 REQUIRED x11 IMPORTED_TARGET) +pkg_check_modules(PC_XCB REQUIRED xcb) + +set(XCB_INCLUDE_DIRS ${PC_XCB_INCLUDE_DIRS}) +set(XCB_LIBRARIES ${PC_XCB_LIBRARIES}) +set(XCB_DEFINITIONS ${PC_XCB_CFLAGS_OTHER}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(XCB DEFAULT_MSG XCB_LIBRARIES XCB_INCLUDE_DIRS) # generate dbus interface qt5_add_dbus_interface(SRCS @@ -114,6 +122,8 @@ target_link_libraries(${BIN_NAME} PUBLIC poppler-cpp KF5::Codecs ${DtkWidget_LIBRARIES} + ${XCB_LIBRARIES} + xcb-xfixes ) target_include_directories(${BIN_NAME} PUBLIC diff --git a/src/dfm-base/utils/clipboard.cpp b/src/dfm-base/utils/clipboard.cpp index a9dd15c5fc..d6fc7d1301 100644 --- a/src/dfm-base/utils/clipboard.cpp +++ b/src/dfm-base/utils/clipboard.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include @@ -34,13 +36,16 @@ static QMutex clipboardFileUrlsMutex; static QAtomicInt remoteCurrentCount = 0; static ClipBoard::ClipboardAction clipboardAction = ClipBoard::kUnknownAction; static std::atomic_bool canReadClipboard { true }; +static std::atomic_bool hasUosRemote{ false }; +static ClipboardMonitor * clipMonitor{ nullptr }; +static std::atomic_bool isX11{ false }; static constexpr char kUserIdKey[] = "userId"; static constexpr char kRemoteCopyKey[] = "uos/remote-copy"; static constexpr char kGnomeCopyKey[] = "x-special/gnome-copied-files"; static constexpr char kRemoteAssistanceCopyKey[] = "uos/remote-copied-files"; -void onClipboardDataChanged() +void onClipboardDataChanged(const QStringList & formats) { if (!canReadClipboard) return; @@ -48,29 +53,29 @@ void onClipboardDataChanged() QMutexLocker lk(&clipboardFileUrlsMutex); clipboardFileUrls.clear(); - const QMimeData *mimeData = qApp->clipboard()->mimeData(); - if (!mimeData || mimeData->formats().isEmpty()) { - qCWarning(logDFMBase) << "get null mimeData from QClipBoard or remote formats is null!"; + if (formats.isEmpty()) { + qCWarning(logDFMBase) << "get empty mimeData formats from QClipBoard!"; return; } - if (mimeData->hasFormat(kRemoteCopyKey)) { - qCWarning(logDFMBase) << "clipboard use other !"; + + if (formats.contains(kRemoteCopyKey) || hasUosRemote) { + qCInfo(logDFMBase) << "clipboard use other !"; clipboardAction = ClipBoard::kRemoteAction; remoteCurrentCount++; return; } // 远程协助功能 - if (mimeData->hasFormat(kRemoteAssistanceCopyKey)) { + if (formats.contains(kRemoteAssistanceCopyKey)) { qCInfo(logDFMBase) << "Remote copy: set remote copy action"; clipboardAction = ClipBoard::kRemoteCopiedAction; return; } - // 没有文件拷贝 - if (!mimeData->hasFormat(kGnomeCopyKey)) { + if (!formats.contains(kGnomeCopyKey)) { qCWarning(logDFMBase) << "no kGnomeCopyKey target in mimedata formats!"; clipboardAction = ClipBoard::kUnknownAction; return; } + const QMimeData *mimeData = qApp->clipboard()->mimeData(); const QString &data = mimeData->data(kGnomeCopyKey); const static QRegExp regCut("cut\nfile://"), regCopy("copy\nfile://"); if (data.contains(regCut)) { @@ -78,7 +83,7 @@ void onClipboardDataChanged() } else if (data.contains(regCopy)) { clipboardAction = ClipBoard::kCopyAction; } else { - qCWarning(logDFMBase) << "wrong kGnomeCopyKey data = " << data; + qCWarning(logDFMBase) << "wrong kGnomeCopyKey data = " << data << mimeData->formats(); clipboardAction = ClipBoard::kUnknownAction; } @@ -92,8 +97,15 @@ void onClipboardDataChanged() ClipBoard::ClipBoard(QObject *parent) : QObject(parent) { + init(); +} + +void ClipBoard::init() +{ + QLibrary library("libdisplayjack-clipboard.so"); + qCritical() << library.fileName(); connect(qApp->clipboard(), &QClipboard::dataChanged, this, [this]() { - onClipboardDataChanged(); + onClipboardDataChanged(qApp->clipboard()->mimeData()->formats()); emit clipboardDataChanged(); }); @@ -104,6 +116,20 @@ ClipBoard::ClipBoard(QObject *parent) connect(&FileManagerWindowsManager::instance(), &FileManagerWindowsManager::lastWindowClosed, this, []{ GlobalData::canReadClipboard = false; }); + + if (!WindowUtils ::isWayLand() || !library.load()) + return; + + library.unload(); + qCWarning(logDFMBase()) << "connect x11 clipboard changed single!!!!" ; + GlobalData::isX11 = true; + GlobalData::clipMonitor = new ClipboardMonitor; + connect(GlobalData::clipMonitor, &ClipboardMonitor::clipboardChanged, this, [](const QStringList & formats) { + qInfo() << " * Clipboard formats changed: " << formats; + GlobalData::hasUosRemote = formats.contains(GlobalData::kRemoteCopyKey); + }); + + GlobalData::clipMonitor->start(); } ClipBoard *ClipBoard::instance() @@ -311,6 +337,22 @@ void ClipBoard::replaceClipboardUrl(const QUrl &oldUrl, const QUrl &newUrl) clipboardUrls.replace(index, newUrl); setUrlsToClipboard(clipboardUrls, action); } + +void ClipBoard::readFirstClipboard() +{ + QStringList mime; + if(GlobalData::isX11) { + static bool first = false; + if (first) + return; + first = true; + mime = getFirstMimeTypesByX11(); + } else { + mime = qApp->clipboard()->mimeData()->formats(); + } + + onClipboardDataChanged(mime); +} /*! * \brief ClipBoard::getUrlsByX11 Use X11 to read URLs downloaded * remotely from the clipboard @@ -448,7 +490,48 @@ QList ClipBoard::getUrlsByX11() return clipboardFileUrls; } -void ClipBoard::onClipboardDataChanged() +QStringList ClipBoard::getFirstMimeTypesByX11() +{ + //使用x11创建一个窗口去阻塞获取URl + Display *display = XOpenDisplay(nullptr); + unsigned long color = BlackPixel(display, DefaultScreen(display)); + Window window = XCreateSimpleWindow(display, DefaultRootWindow(display), 0, 0, 1, 1, 0, color, color); + + char *result = nullptr; + unsigned long ressize = 0, restail = 0; + int resbits; + Atom bufid = XInternAtom(display, "CLIPBOARD", False), + fmtid = XInternAtom(display, "TARGETS", False), + propid = XInternAtom(display, "XSEL_DATA", False); + XEvent event; + + QList urls; + QString results; + + XSelectInput(display, window, PropertyChangeMask); + XConvertSelection(display, bufid, fmtid, propid, window, CurrentTime); + QList currentClipboardFileUrls; + do { + XNextEvent(display, &event); + } while (event.type != SelectionNotify || event.xselection.selection != bufid); + + XGetWindowProperty(display, window, propid, 0, LONG_MAX / 4, True, AnyPropertyType, + &fmtid, &resbits, &ressize, &restail, reinterpret_cast(&result)); + QStringList formats; + if (resbits == 32 && ressize > 0) { + Atom *atoms = reinterpret_cast(result); + for (int i = 0; i < static_cast(ressize); i++) { + formats.append(XGetAtomName(display, atoms[i])); + } + qCWarning(logDFMBase) << "first x11 read formats = " << formats; + } + XFree(result); + XDestroyWindow(display, window); + XCloseDisplay(display); + return formats; +} + +void ClipBoard::onClipboardDataChanged(const QStringList &mimeTypes) { - GlobalData::onClipboardDataChanged(); + GlobalData::onClipboardDataChanged(mimeTypes); } diff --git a/src/dfm-base/utils/clipboard.h b/src/dfm-base/utils/clipboard.h index 7a88ac7ea3..d891bc3524 100644 --- a/src/dfm-base/utils/clipboard.h +++ b/src/dfm-base/utils/clipboard.h @@ -11,6 +11,7 @@ class QMimeData; class QUrl; namespace dfmbase { +class ClipboardMonitor; class ClipBoard : public QObject { Q_OBJECT @@ -40,17 +41,20 @@ class ClipBoard : public QObject ClipboardAction clipboardAction() const; void removeUrls(const QList &urls); void replaceClipboardUrl(const QUrl &oldUrl, const QUrl &newUrl); + void readFirstClipboard(); private: explicit ClipBoard(QObject *parent = nullptr); + void init(); virtual ~ClipBoard() = default; static QList getUrlsByX11(); + QStringList getFirstMimeTypesByX11(); Q_SIGNALS: void clipboardDataChanged(); public Q_SLOTS: - void onClipboardDataChanged(); + void onClipboardDataChanged(const QStringList & mimeTypes); }; } // namespace dfmbase Q_DECLARE_METATYPE(DFMBASE_NAMESPACE::ClipBoard::ClipboardAction) diff --git a/src/dfm-base/utils/clipboardmonitor.cpp b/src/dfm-base/utils/clipboardmonitor.cpp new file mode 100644 index 0000000000..d976e3fa16 --- /dev/null +++ b/src/dfm-base/utils/clipboardmonitor.cpp @@ -0,0 +1,273 @@ +#include "clipboardmonitor.h" + +#include +#include + +#include +#include +//#include + + +#include + +using namespace std; + +static xcb_atom_t primaryAtom = XCB_ATOM_NONE; +static xcb_atom_t clipboardAtom = XCB_ATOM_NONE; +static xcb_atom_t utf8StringAtom = XCB_ATOM_NONE; +static xcb_atom_t textAtom = XCB_ATOM_NONE; +static xcb_atom_t uriListAtom = XCB_ATOM_NONE; +static xcb_atom_t targetsAtom = XCB_ATOM_NONE; +static xcb_atom_t wlSelectionAtom = XCB_ATOM_NONE; +static xcb_atom_t timestampAtom = XCB_ATOM_NONE; +static xcb_atom_t incrAtom = XCB_ATOM_NONE; +static xcb_atom_t deleteAtom = XCB_ATOM_NONE; + +xcb_atom_t getAtom(const char *str, xcb_connection_t *xcbConn) +{ + xcb_atom_t atom = XCB_ATOM_NONE; + if (!strcmp(str, "PRIMARY") && primaryAtom != XCB_ATOM_NONE) { + return primaryAtom; + } else if (!strcmp(str, "CLIPBOARD") && clipboardAtom != XCB_ATOM_NONE) { + return clipboardAtom; + } else if (!strcmp(str, "UTF8_STRING") && utf8StringAtom != XCB_ATOM_NONE) { + return utf8StringAtom; + } else if (!strcmp(str, "TEXT") && textAtom != XCB_ATOM_NONE) { + return textAtom; + } else if (!strcmp(str, "text/uri-list") && uriListAtom != XCB_ATOM_NONE) { + return uriListAtom; + } else if (!strcmp(str, "TARGETS") && targetsAtom != XCB_ATOM_NONE) { + return targetsAtom; + } else if (!strcmp(str, "WL_SELECTION") && wlSelectionAtom != XCB_ATOM_NONE) { + return wlSelectionAtom; + } else if (!strcmp(str, "TIMESTAMP") && timestampAtom != XCB_ATOM_NONE) { + return timestampAtom; + } else if (!strcmp(str, "INCR") && incrAtom != XCB_ATOM_NONE) { + return incrAtom; + } else if (!strcmp(str, "DELETE") && deleteAtom != XCB_ATOM_NONE) { + return deleteAtom; + } + + if (xcbConn) { + xcb_intern_atom_reply_t *rep = nullptr; + uint16_t name_len = static_cast(strlen(str)); + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcbConn, 0, name_len, str); + if (!(rep = xcb_intern_atom_reply(xcbConn, cookie, nullptr))) { + return atom; + } + atom = rep->atom; + free(rep); + } + // 记录atom + if (!strcmp(str, "PRIMARY")) { + primaryAtom = atom; + } else if (!strcmp(str, "CLIPBOARD")) { + clipboardAtom = atom; + } else if (!strcmp(str, "UTF8_STRING")) { + utf8StringAtom = atom; + } else if (!strcmp(str, "TEXT")) { + textAtom = atom; + } else if (!strcmp(str, "text/uri-list")) { + uriListAtom = atom; + } else if (!strcmp(str, "TARGETS")) { + targetsAtom = atom; + } else if (!strcmp(str, "WL_SELECTION")) { + wlSelectionAtom = atom; + } else if (!strcmp(str, "TIMESTAMP")) { + timestampAtom = atom; + } else if (!strcmp(str, "INCR")) { + incrAtom = atom; + } else if (!strcmp(str, "DELETE")) { + deleteAtom = atom; + } + + return atom; +} + +using namespace dfmbase; +ClipboardMonitor::ClipboardMonitor(QObject *parent) + : QThread(parent) +{ + // 创建 XCB 连接 + connection = nullptr; + connection = xcb_connect(nullptr, nullptr); + if (xcb_connection_has_error(connection)) { + for (size_t i = 0; i < 100; i++) { + std::string displayStr(":"); + displayStr += std::to_string(i); + // setenv("DISPLAY",displayStr.c_str(),1); + connection = xcb_connect(displayStr.c_str(), nullptr); + if (xcb_connection_has_error(connection) == 0) { + break; + } + } + } + + if (xcb_connection_has_error(connection)) { + return; + } + + + + const xcb_query_extension_reply_t *queryExtension; + queryExtension = xcb_get_extension_data(connection, &xcb_xfixes_id); + if (!queryExtension) { + xcb_disconnect(connection); + } + + m_queryExtension = queryExtension; + xcb_discard_reply(connection, xcb_xfixes_query_version(connection, 1, 0).sequence); + screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data; + connect(qApp, &QApplication::aboutToQuit, this, [this](){ + stop(); + this->wait(100); + }); +} + +ClipboardMonitor::~ClipboardMonitor() +{ + if (connection) { + xcb_disconnect(connection); + } +} + +void ClipboardMonitor::stop() +{ + stoped = true; + if (connection) { + xcb_disconnect(connection); + } +} + +void ClipboardMonitor::run() +{ + xcb_atom_t clipboardAtom = getAtom("CLIPBOARD", connection); + xcb_atom_t targetsAtom = getAtom("TARGETS", connection); + xcb_window_t window = xcb_generate_id(connection); + + const uint32_t clipboardValues[] = {XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE}; + xcb_create_window(connection, + XCB_COPY_FROM_PARENT, + window, + screen->root, + 0, 0, + 10, 10, + 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, + XCB_COPY_FROM_PARENT, + XCB_CW_EVENT_MASK, + clipboardValues); + + const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER + | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY + | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE; + + + // 创建监控剪贴板变化的事件请求 + xcb_xfixes_select_selection_input(connection, window, clipboardAtom, mask); + + + xcb_flush(connection); + + while (true) { + xcb_generic_event_t *event = xcb_wait_for_event(connection); + if (stoped) { + free(event); + break; + } + if (event) { + switch (event->response_type & (0x7f)) { + case XCB_SELECTION_NOTIFY: { + + xcb_get_property_cookie_t cookie = xcb_get_property(connection, + 1, + window, + getAtom("WL_SELECTION", connection), + XCB_GET_PROPERTY_TYPE_ANY, + 0, + 4096); + if (stoped) { + free(event); + xcb_destroy_window(connection, window); + return; + } + auto *reply = xcb_get_property_reply(connection, cookie, nullptr); + if (!reply) { + break; + } + if (reply->type != XCB_ATOM_ATOM) { + + free(reply); + break; + } + if (stoped) { + free(reply); + free(event); + xcb_destroy_window(connection, window); + return; + } + xcb_atom_t *value = static_cast(xcb_get_property_value(reply)); + QStringList mimeTypes; + for (uint32_t i = 0; i < reply->value_len; i++) { + if (value[i] == XCB_ATOM_NONE) { + continue; + } + if (stoped) { + free(reply); + free(event); + xcb_destroy_window(connection, window); + return; + } + xcb_get_atom_name_cookie_t nameCookie = xcb_get_atom_name(connection, value[i]); + xcb_get_atom_name_reply_t *nameReply = xcb_get_atom_name_reply(connection, nameCookie, nullptr); + + if (nameReply) { + mimeTypes.append(QString::fromUtf8(xcb_get_atom_name_name(nameReply), xcb_get_atom_name_name_length(nameReply))); + free(nameReply); + } + } + if (stoped) { + free(reply); + free(event); + xcb_destroy_window(connection, window); + return; + } + + Q_EMIT clipboardChanged(mimeTypes); + free(reply); + } + break; + default: + if (m_queryExtension && event->response_type == m_queryExtension->first_event + XCB_XFIXES_SELECTION_NOTIFY) { + xcb_xfixes_selection_notify_event_t *se = reinterpret_cast(event); + if (se->selection == clipboardAtom) { + if (stoped) { + free(event); + xcb_destroy_window(connection, window); + return; + } + xcb_convert_selection(connection, + window, + clipboardAtom, + targetsAtom, + getAtom("WL_SELECTION", connection), + se->timestamp); + xcb_flush(connection); + if (stoped) { + free(event); + xcb_destroy_window(connection, window); + return; + } + } + } + break; + } + if (stoped) { + free(event); + break; + } + } + free(event); + } + xcb_destroy_window(connection, window); +} diff --git a/src/dfm-base/utils/clipboardmonitor.h b/src/dfm-base/utils/clipboardmonitor.h new file mode 100644 index 0000000000..3a706c060b --- /dev/null +++ b/src/dfm-base/utils/clipboardmonitor.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2022 - 2023 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: GPL-3.0-or-later +#ifndef CLIPBOARDMONITOR_H +#define CLIPBOARDMONITOR_H + +#include +#include +#include + +#include +namespace dfmbase { +class ClipboardMonitor : public QThread +{ + Q_OBJECT + +public: + ClipboardMonitor(QObject *parent = nullptr); + ~ClipboardMonitor() override; + +Q_SIGNALS: + void clipboardChanged(const QStringList &mimeTypes); +private: + void stop(); +protected: + void run() override; + +private: + xcb_connection_t *connection; + xcb_screen_t *screen; + const xcb_query_extension_reply_t *m_queryExtension = nullptr; + std::atomic_bool stoped{false}; +}; +} // namespace dfmbase +#endif // CLIPBOARDMONITOR_H diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.cpp b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.cpp index b59c8c5cd1..9aab7b04cf 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.cpp +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.cpp @@ -38,6 +38,7 @@ namespace dfmplugin_fileoperations { FileOperationsEventReceiver::FileOperationsEventReceiver(QObject *parent) : QObject(parent), dialogManager(DialogManagerInstance) { + qRegisterMetaType(); } QString FileOperationsEventReceiver::newDocmentName(const QUrl &url, @@ -215,7 +216,7 @@ bool FileOperationsEventReceiver::redo(const quint64 windowId, const QVariantMap case kCopy: if (targets.isEmpty()) return true; - handleOperationCopy(windowId, { sources }, targets.first(), AbstractJobHandler::JobFlag::kNoHint, handle); + handleOperationCopy(windowId, { sources }, targets.first(), DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag::kNoHint, handle); break; case kCutFile: if (targets.isEmpty()) diff --git a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.h b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.h index bda68f9b01..a2b0a73042 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.h +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.h @@ -46,7 +46,7 @@ public slots: void handleOperationCopy(const quint64 windowId, const QList sources, const QUrl target, - const DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag flags, + DFMBASE_NAMESPACE::AbstractJobHandler::JobFlag flags, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback handle, const QVariant custom, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorCallback callback); diff --git a/src/plugins/common/core/dfmplugin-menu/menuscene/clipboardmenuscene.cpp b/src/plugins/common/core/dfmplugin-menu/menuscene/clipboardmenuscene.cpp index 5d6145759b..0f686aab4c 100644 --- a/src/plugins/common/core/dfmplugin-menu/menuscene/clipboardmenuscene.cpp +++ b/src/plugins/common/core/dfmplugin-menu/menuscene/clipboardmenuscene.cpp @@ -173,7 +173,8 @@ bool ClipBoardMenuScene::triggered(QAction *action) fmInfo() << "Remote Assistance Copy: set Current Url to Clipboard"; ClipBoard::setCurUrlToClipboardForRemote(d->currentDir); } else if (ClipBoard::kRemoteAction == action) { - dpfSignalDispatcher->publish(GlobalEventType::kCopy, d->windowId, selectedUrlsTemp, d->currentDir, AbstractJobHandler::JobFlag::kCopyRemote, nullptr); + dpfSignalDispatcher->publish(GlobalEventType::kCopy, d->windowId, selectedUrlsTemp, d->currentDir, + AbstractJobHandler::JobFlag::kCopyRemote, nullptr); } else { fmWarning() << "clipboard action:" << action << " urls:" << selectedUrlsTemp; } diff --git a/src/plugins/desktop/core/ddplugin-core/core.cpp b/src/plugins/desktop/core/ddplugin-core/core.cpp index db091fff0b..e7cd1cec1c 100644 --- a/src/plugins/desktop/core/ddplugin-core/core.cpp +++ b/src/plugins/desktop/core/ddplugin-core/core.cpp @@ -161,7 +161,7 @@ void Core::initializeAfterPainted() fmInfo() << "load lazy plugins" << list; dpfSignalDispatcher->publish(GlobalEventType::kLoadPlugins, list); // init clipboard - ClipBoard::instance()->onClipboardDataChanged(); + ClipBoard::instance()->readFirstClipboard(); }); } diff --git a/src/plugins/filemanager/core/dfmplugin-core/core.cpp b/src/plugins/filemanager/core/dfmplugin-core/core.cpp index 29e2556432..464907034e 100644 --- a/src/plugins/filemanager/core/dfmplugin-core/core.cpp +++ b/src/plugins/filemanager/core/dfmplugin-core/core.cpp @@ -155,7 +155,7 @@ void Core::onWindowOpened(quint64 winid) // TODO: freeze 5s, fix it! QTimer::singleShot(2000, []() { // init clipboard - ClipBoard::instance()->onClipboardDataChanged(); + ClipBoard::instance()->readFirstClipboard(); }); }); } diff --git a/tests/dfm-base/CMakeLists.txt b/tests/dfm-base/CMakeLists.txt index d1e04f4cf4..03232d4b08 100644 --- a/tests/dfm-base/CMakeLists.txt +++ b/tests/dfm-base/CMakeLists.txt @@ -32,6 +32,14 @@ pkg_search_module(dfm-io REQUIRED dfm-io IMPORTED_TARGET) pkg_search_module(dfm-mount REQUIRED dfm-mount IMPORTED_TARGET) pkg_search_module(gsettings REQUIRED gsettings-qt IMPORTED_TARGET) pkg_search_module(Dtk REQUIRED dtkcore IMPORTED_TARGET) +pkg_check_modules(PC_XCB REQUIRED xcb) + +set(XCB_INCLUDE_DIRS ${PC_XCB_INCLUDE_DIRS}) +set(XCB_LIBRARIES ${PC_XCB_LIBRARIES}) +set(XCB_DEFINITIONS ${PC_XCB_CFLAGS_OTHER}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(XCB DEFAULT_MSG XCB_LIBRARIES XCB_INCLUDE_DIRS) qt5_add_dbus_interface(SRC_FILES ${DFM_DBUS_XML_DIR}/org.deepin.filemanager.server.DeviceManager.xml devicemanager_interface) @@ -63,6 +71,8 @@ target_link_libraries(${PROJECT_NAME} PRIVATE KF5::Codecs ${DtkWidget_LIBRARIES} ${X11_LIBRARIES} + ${XCB_LIBRARIES} + xcb-xfixes ) add_test(