Skip to content

Commit

Permalink
Stick PNGs on the clipboard on Wayland
Browse files Browse the repository at this point in the history
Because using Qt's image data breaks transparency when copying between
canvases.
  • Loading branch information
askmeaboutlo0m committed Nov 22, 2024
1 parent 3d6ddd2 commit 4828cf1
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 9 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Unreleased Version 2.2.2-pre
* Server Fix: Don't pointlessly reload server certificates if they didn't change. Thanks Liz for reporting.
* Server Fix: Work around too many authenticated users in a session, which could cause a crash. Thanks Liz for reporting.
* Fix: Don't crash when filling with feathering and a canvas-filling selection. Thanks Meru for reporting.
* Fix: Work around broken transparency when copying images between canvases on Wayland. Thanks Absolute Goober for reporting.

2024-11-06 Version 2.2.2-beta.4
* Fix: Solve rendering glitches with selection outlines that happen on some systems. Thanks xxxx for reporting.
Expand Down
22 changes: 13 additions & 9 deletions src/desktop/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3593,11 +3593,13 @@ void MainWindow::copyText()
textedit->copy();
}

// clang-format on
void MainWindow::paste()
{
utils::ScopedOverrideCursor waitCursor;
const QMimeData *mimeData = Document::getClipboardData();
if(mimeData && mimeData->hasImage()) {
QImage img = Document::getClipboardImageData(mimeData);
if(!img.isNull()) {
QPoint pastepos;
bool pasteAtPos = false;

Expand All @@ -3611,25 +3613,27 @@ void MainWindow::paste()
qint64 pid = pos.at(2).toLongLong(&ok3);
qulonglong doc = pos.at(3).toULongLong(&ok4);
pasteAtPos = ok1 && ok2 && ok3 && ok4 &&
pid == qApp->applicationPid() && doc == m_doc->pasteId();
pid == qApp->applicationPid() &&
doc == m_doc->pasteId();
}
}

// Paste-in-place if we're the source (same process, same document)
if(pasteAtPos && m_canvasView->isPointVisible(pastepos))
pasteImage(mimeData->imageData().value<QImage>(), &pastepos, true);
else
pasteImage(mimeData->imageData().value<QImage>());
if(pasteAtPos && m_canvasView->isPointVisible(pastepos)) {
pasteImage(img, &pastepos, true);
} else {
pasteImage(img);
}
}
}

// clang-format on
void MainWindow::pasteCentered()
{
utils::ScopedOverrideCursor waitCursor;
const QMimeData *mimeData = Document::getClipboardData();
if(mimeData && mimeData->hasImage()) {
pasteImage(mimeData->imageData().value<QImage>(), nullptr, true);
QImage img = Document::getClipboardImageData(mimeData);
if(!img.isNull()) {
pasteImage(img, nullptr, true);
}
}

Expand Down
33 changes: 33 additions & 0 deletions src/libclient/document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1443,7 +1443,24 @@ bool Document::copyFromLayer(int layer)
if(!img.isNull() && layer == 0) {
fillBackground(img);
}

#ifdef Q_OS_LINUX
// Copying image data from one Drawpile canvas to another is busted on
// Wayland, obliterating transparency. We store a PNG directly instead.
if(QGuiApplication::platformName() == QStringLiteral("wayland")) {
QByteArray bytes;
{
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
img.save(&buffer, "PNG");
}
data->setData(QStringLiteral("image/png"), bytes);
} else {
data->setImageData(img);
}
#else
data->setImageData(img);
#endif

// Store also original coordinates
QRect bounds = m_canvas->selection()->bounds();
Expand Down Expand Up @@ -1684,6 +1701,22 @@ const QMimeData *Document::getClipboardData()
#endif
}

QImage Document::getClipboardImageData(const QMimeData *mimeData)
{
if(mimeData) {
if(mimeData->hasImage()) {
return mimeData->imageData().value<QImage>();
} else if(mimeData->hasFormat(QStringLiteral("image/png"))) {
QImage img;
if(img.loadFromData(
mimeData->data(QStringLiteral("image/png")), "PNG")) {
return img;
}
}
}
return QImage();
}

#ifdef HAVE_CLIPBOARD_EMULATION
QMimeData Document::clipboardData;
#endif
1 change: 1 addition & 0 deletions src/libclient/document.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ public slots:
void addServerLogEntry(const QString &log);

static const QMimeData *getClipboardData();
static QImage getClipboardImageData(const QMimeData *mimeData);

private slots:
void onServerLogin(
Expand Down

0 comments on commit 4828cf1

Please sign in to comment.