From 465eca93aff0272e545c24f25abff42cf1fa6430 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 | 99 ++++++- src/dfm-base/utils/clipboard.h | 9 +- src/dfm-base/utils/clipboardmonitor.cpp | 274 ++++++++++++++++++ src/dfm-base/utils/clipboardmonitor.h | 35 +++ .../fileoperationseventreceiver.cpp | 8 + .../menuscene/clipboardmenuscene.cpp | 3 +- .../view/operator/fileoperatorproxy.cpp | 2 +- .../desktop/core/ddplugin-core/core.cpp | 2 +- .../ddplugin-organizer/utils/fileoperator.cpp | 2 +- .../filemanager/core/dfmplugin-core/core.cpp | 2 +- .../utils/fileoperatorhelper.cpp | 3 +- tests/dfm-base/CMakeLists.txt | 10 + 13 files changed, 441 insertions(+), 18 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 7c5e7e63be..d9f7b76400 100644 --- a/src/dfm-base/utils/clipboard.cpp +++ b/src/dfm-base/utils/clipboard.cpp @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include @@ -38,25 +40,24 @@ 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 & mimeTypes) { - QMutexLocker lk(&clipboardFileUrlsMutex); clipboardFileUrls.clear(); - const QMimeData *mimeData = qApp->clipboard()->mimeData(); - if (!mimeData || mimeData->formats().isEmpty()) { + if (mimeTypes.isEmpty()) { qCWarning(logDFMBase) << "get null mimeData from QClipBoard or remote formats is null!"; return; } - if (mimeData->hasFormat(kRemoteCopyKey)) { + const QMimeData *mimeData = qApp->clipboard()->mimeData(); + if (mimeTypes.contains(kRemoteCopyKey)) { qCInfo(logDFMBase) << "clipboard use other !"; clipboardAction = ClipBoard::kRemoteAction; remoteCurrentCount++; return; } // 远程协助功能 - if (mimeData->hasFormat(kRemoteAssistanceCopyKey)) { + if (mimeTypes.contains(kRemoteAssistanceCopyKey)) { qCInfo(logDFMBase) << "Remote copy: set remote copy action"; clipboardAction = ClipBoard::kRemoteCopiedAction; return; @@ -82,10 +83,31 @@ void onClipboardDataChanged() ClipBoard::ClipBoard(QObject *parent) : QObject(parent) { - connect(qApp->clipboard(), &QClipboard::dataChanged, this, [this]() { - onClipboardDataChanged(); + init(); +} + +void ClipBoard::init() +{ + QLibrary library("libdisplayjack-clipboard.so"); + if (!WindowUtils ::isWayLand() || !library.load()) { + connect(qApp->clipboard(), &QClipboard::dataChanged, this, [this]() { + const QMimeData *data = qApp->clipboard()->mimeData(); + onClipboardDataChanged(data->formats()); + emit clipboardDataChanged(); + }); + return; + } + library.unload(); + isX11 = true; + clipMonitor = new ClipboardMonitor; + QObject::connect(clipMonitor, &ClipboardMonitor::clipboardChanged, this, [this](const QStringList & mimeTypes) { + qWarning() << "Clipboard MIME types changed:" << mimeTypes; + onClipboardDataChanged(mimeTypes); + readFirstClipboard(); emit clipboardDataChanged(); }); + + clipMonitor->start(); } ClipBoard *ClipBoard::instance() @@ -293,6 +315,22 @@ void ClipBoard::replaceClipboardUrl(const QUrl &oldUrl, const QUrl &newUrl) clipboardUrls.replace(index, newUrl); setUrlsToClipboard(clipboardUrls, action); } + +void ClipBoard::readFirstClipboard() +{ + QStringList mime; + if(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 @@ -430,7 +468,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 mimetyps; + if (resbits == 32 && ressize > 0) { + Atom *atoms = reinterpret_cast(result); + for (int i = 0; i < static_cast(ressize); i++) { + printf("Target: %s\n", XGetAtomName(display, atoms[i])); + mimetyps.append(XGetAtomName(display, atoms[i])); + } + } + XFree(result); + XDestroyWindow(display, window); + XCloseDisplay(display); + return mimetyps; +} + +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..1d078f369f 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,23 @@ 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); +private: + ClipboardMonitor * clipMonitor{nullptr}; + std::atomic_bool isX11{ false }; }; } // 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..72d02ec0d4 --- /dev/null +++ b/src/dfm-base/utils/clipboardmonitor.cpp @@ -0,0 +1,274 @@ +#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 7756c993d4..6d13dfc47b 100644 --- a/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.cpp +++ b/src/plugins/common/core/dfmplugin-fileoperations/fileoperationsevent/fileoperationseventreceiver.cpp @@ -448,6 +448,14 @@ bool FileOperationsEventReceiver::doRenameDesktopFiles(QList &urls, const JobHandlePointer FileOperationsEventReceiver::doCopyFile(const quint64 windowId, const QList &sources, const QUrl &target, const AbstractJobHandler::JobFlags flags, DFMBASE_NAMESPACE::AbstractJobHandler::OperatorHandleCallback callbaskHandle) { + // 深信服拷贝 + if (flags.testFlag(AbstractJobHandler::JobFlag::kCopyRemote)) { + JobHandlePointer handle = copyMoveJob->copy(sources, target, flags); + if (callbaskHandle) + callbaskHandle(handle); + return handle; + } + if (sources.isEmpty()) return nullptr; diff --git a/src/plugins/common/core/dfmplugin-menu/menuscene/clipboardmenuscene.cpp b/src/plugins/common/core/dfmplugin-menu/menuscene/clipboardmenuscene.cpp index aaaa01498a..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, nullptr, QVariant(), 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-canvas/view/operator/fileoperatorproxy.cpp b/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.cpp index 3ec2c7c5a3..d5be69338f 100644 --- a/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.cpp +++ b/src/plugins/desktop/core/ddplugin-canvas/view/operator/fileoperatorproxy.cpp @@ -205,7 +205,7 @@ void FileOperatorProxy::pasteFiles(const CanvasView *view, const QPoint pos) if (ClipBoard::kRemoteAction == action) { dpfSignalDispatcher->publish(GlobalEventType::kCopy, view->winId(), urls, view->model()->rootUrl(), - AbstractJobHandler::JobFlag::kCopyRemote, nullptr, nullptr, QVariant(), nullptr); + AbstractJobHandler::JobFlag::kCopyRemote, nullptr); return; } 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/desktop/ddplugin-organizer/utils/fileoperator.cpp b/src/plugins/desktop/ddplugin-organizer/utils/fileoperator.cpp index 1473675470..4fd314a030 100644 --- a/src/plugins/desktop/ddplugin-organizer/utils/fileoperator.cpp +++ b/src/plugins/desktop/ddplugin-organizer/utils/fileoperator.cpp @@ -158,7 +158,7 @@ void FileOperator::pasteFiles(const CollectionView *view, const QString &targetC if (ClipBoard::kRemoteAction == action) { dpfSignalDispatcher->publish(GlobalEventType::kCopy, view->winId(), urls, view->model()->rootUrl(), - AbstractJobHandler::JobFlag::kCopyRemote, nullptr, nullptr, QVariant(), nullptr); + AbstractJobHandler::JobFlag::kCopyRemote, nullptr); return; } 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/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.cpp b/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.cpp index 5462a284c6..6e0eb11bbd 100644 --- a/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.cpp +++ b/src/plugins/filemanager/core/dfmplugin-workspace/utils/fileoperatorhelper.cpp @@ -234,8 +234,7 @@ void FileOperatorHelper::pasteFiles(const FileView *view) sourceUrls, view->rootUrl(), AbstractJobHandler::JobFlag::kCopyRemote, - nullptr, nullptr, - QVariant(), nullptr); + nullptr); } else { fmWarning() << "Unknown clipboard past action:" << action << " urls:" << sourceUrls; } 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(