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 Aug 30, 2024
1 parent e07205a commit 07ca59f
Show file tree
Hide file tree
Showing 10 changed files with 434 additions and 18 deletions.
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
109 changes: 96 additions & 13 deletions src/dfm-base/utils/clipboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include <dfm-base/mimetype/mimetypedisplaymanager.h>
#include <dfm-base/utils/fileutils.h>
#include <dfm-base/widgets/filemanagerwindowsmanager.h>
#include <dfm-base/utils/clipboardmonitor.h>
#include <dfm-base/utils/windowutils.h>

#include <QApplication>
#include <QClipboard>
Expand All @@ -34,51 +36,54 @@ 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;

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)) {
clipboardAction = ClipBoard::kCutAction;
} 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;
}

Expand All @@ -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();
});

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

void ClipBoard::readFirstClipboard()

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

View workflow job for this annotation

GitHub Actions / cppcheck

The function 'readFirstClipboard' is never used.

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

View workflow job for this annotation

GitHub Actions / static-check / Call-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 @@ -448,7 +490,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 508 in src/dfm-base/utils/clipboard.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Unused variable: urls

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

View workflow job for this annotation

GitHub Actions / static-check / Call-CppCheck

Unused variable: urls
QString results;

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

View workflow job for this annotation

GitHub Actions / cppcheck

Unused variable: results

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

View workflow job for this annotation

GitHub Actions / static-check / Call-CppCheck

Unused variable: results

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

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

View workflow job for this annotation

GitHub Actions / cppcheck

Unused variable: currentClipboardFileUrls

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

View workflow job for this annotation

GitHub Actions / static-check / Call-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 07ca59f

Please sign in to comment.