Files
qbz/crates/qbz-qt/cxx/clipboard.cpp
T
vicrodh 6b81cfa84d fix(share): copy links through QClipboard, not arboard (#684)
Copy link failed on GNOME + Flatpak: arboard's Wayland path needs the
wlr/ext-data-control protocol, which Mutter does not implement, so it fell
back to X11 — reachable natively through XWayland, unreachable inside the
sandbox ("clipboard unavailable: X11 server connection timed out"). KWin
has the protocol, which is why the failure never reproduced on Plasma.

Replace it with a C++ shim (cxx/clipboard.cpp) that queues the write onto
the GUI thread and hands it to QClipboard: the base wl_data_device protocol
every compositor implements, no extra sandbox permission, and the offer
lives as long as the application (the #514 lifetime rule, without the
long-lived arboard instance). arboard is dropped from the crate.

Verified on Plasma/Wayland and on an Ubuntu GNOME/Wayland VM with DISPLAY
unset (the sandbox condition), where the copy now lands.

cc
2026-09-11 13:53:27 -06:00

36 lines
1.4 KiB
C++

// System clipboard through Qt (#684).
//
// The Rust side used arboard, whose Wayland path needs the wlr/ext-data-control
// protocol. KWin has it; Mutter (GNOME) does not, so arboard fell back to X11
// there — which works natively through XWayland and FAILS inside the Flatpak
// sandbox (no X11 socket): "clipboard unavailable: X11 server connection timed
// out". QClipboard speaks the base wl_data_device protocol every compositor
// implements, needs no extra sandbox permission, and the offer stays alive for
// as long as the application does (the #514 lifetime rule, for free).
//
// The clipboard is a GUI-thread object; the call is queued onto the
// application's thread so any caller (a cxx-qt invokable already on it, or a
// tokio worker) is fine.
#include <QtCore/QCoreApplication>
#include <QtCore/QMetaObject>
#include <QtCore/QString>
#include <QtGui/QClipboard>
#include <QtGui/QGuiApplication>
extern "C" void qbz_clipboard_set_text(const char *utf8, int len) {
QCoreApplication *core = QCoreApplication::instance();
if (!core || !qobject_cast<QGuiApplication *>(core)) {
return;
}
const QString text = QString::fromUtf8(utf8, len);
QMetaObject::invokeMethod(
core,
[text]() {
if (QClipboard *clipboard = QGuiApplication::clipboard()) {
clipboard->setText(text, QClipboard::Clipboard);
}
},
Qt::QueuedConnection);
}