Skip to content

Commit

Permalink
fix: Copying files from cloud desktop cannot be copied to the local m…
Browse files Browse the repository at this point in the history
…achine

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
  • Loading branch information
liyigang1 committed Jun 26, 2024
1 parent 9d4345d commit d43a253
Show file tree
Hide file tree
Showing 19 changed files with 512 additions and 79 deletions.
2 changes: 1 addition & 1 deletion include/dfm-base/interfaces/abstractjobhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class AbstractJobHandler : public QObject
kRevocation = 0x200, // 拷贝时不处理文件名称
kCopyRemote = 0x400, // 深信服远程拷贝
kRedo = 0x800, // 重新执行(ctrl + Y)
kCountProgressCustomize = 0x800, // 强制使用自己统计进度
kCountProgressCustomize = 0x1000, // 强制使用自己统计进度
};
Q_ENUM(JobFlag)
Q_DECLARE_FLAGS(JobFlags, JobFlag)
Expand Down
10 changes: 10 additions & 0 deletions src/dfm-base/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
111 changes: 100 additions & 11 deletions src/dfm-base/utils/clipboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <dfm-base/file/local/localfileiconprovider.h>
#include <dfm-base/mimetype/mimetypedisplaymanager.h>
#include <dfm-base/utils/fileutils.h>
#include <dfm-base/utils/clipboardmonitor.h>
#include <dfm-base/utils/windowutils.h>

#include <QApplication>
#include <QClipboard>
Expand All @@ -32,43 +34,52 @@ static QList<QUrl> clipboardFileUrls;
static QMutex clipboardFileUrlsMutex;
static QAtomicInt remoteCurrentCount = 0;
static ClipBoard::ClipboardAction clipboardAction = ClipBoard::kUnknownAction;
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)
{

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)) {

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 (!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)) {
clipboardAction = ClipBoard::kCutAction;
} else if (data.contains(regCopy)) {
clipboardAction = ClipBoard::kCopyAction;
} else {
qCWarning(logDFMBase) << "wrang kGnomeCopyKey data = " << data;
qCWarning(logDFMBase) << "wrong kGnomeCopyKey data = " << data << mimeData->formats();
clipboardAction = ClipBoard::kUnknownAction;
}

Expand All @@ -82,10 +93,31 @@ 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();
});

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()
Expand Down Expand Up @@ -293,6 +325,22 @@ void ClipBoard::replaceClipboardUrl(const QUrl &oldUrl, const QUrl &newUrl)
clipboardUrls.replace(index, newUrl);
setUrlsToClipboard(clipboardUrls, action);
}

void ClipBoard::readFirstClipboard()

Check warning on line 329 in src/dfm-base/utils/clipboard.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'readFirstClipboard' is never used.
{
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
Expand Down Expand Up @@ -430,7 +478,48 @@ QList<QUrl> 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<QUrl> urls;

Check warning on line 496 in src/dfm-base/utils/clipboard.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Unused variable: urls
QString results;

Check warning on line 497 in src/dfm-base/utils/clipboard.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Unused variable: results

XSelectInput(display, window, PropertyChangeMask);
XConvertSelection(display, bufid, fmtid, propid, window, CurrentTime);
QList<QUrl> currentClipboardFileUrls;

Check warning on line 501 in src/dfm-base/utils/clipboard.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Unused variable: 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<unsigned char **>(&result));
QStringList formats;
if (resbits == 32 && ressize > 0) {
Atom *atoms = reinterpret_cast<Atom*>(result);
for (int i = 0; i < static_cast<int>(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);
}
6 changes: 5 additions & 1 deletion src/dfm-base/utils/clipboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
class QMimeData;
class QUrl;
namespace dfmbase {
class ClipboardMonitor;
class ClipBoard : public QObject
{
Q_OBJECT
Expand Down Expand Up @@ -40,17 +41,20 @@ class ClipBoard : public QObject
ClipboardAction clipboardAction() const;
void removeUrls(const QList<QUrl> &urls);
void replaceClipboardUrl(const QUrl &oldUrl, const QUrl &newUrl);
void readFirstClipboard();

private:
explicit ClipBoard(QObject *parent = nullptr);
void init();
virtual ~ClipBoard() = default;
static QList<QUrl> 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)
Expand Down
Loading

0 comments on commit d43a253

Please sign in to comment.