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
36 lines
1.4 KiB
C++
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);
|
|
}
|