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 25, 2024
1 parent b66ee5a commit 465eca9
Show file tree
Hide file tree
Showing 13 changed files with 441 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
99 changes: 89 additions & 10 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 Down Expand Up @@ -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;
Expand All @@ -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()
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -430,7 +468,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 486 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 487 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 491 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 mimetyps;
if (resbits == 32 && ressize > 0) {
Atom *atoms = reinterpret_cast<Atom*>(result);
for (int i = 0; i < static_cast<int>(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);
}
9 changes: 8 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,23 @@ 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);
private:
ClipboardMonitor * clipMonitor{nullptr};
std::atomic_bool isX11{ false };
};
} // namespace dfmbase
Q_DECLARE_METATYPE(DFMBASE_NAMESPACE::ClipBoard::ClipboardAction)
Expand Down
Loading

0 comments on commit 465eca9

Please sign in to comment.