diff --git a/src/screenshotdialog.cpp b/src/screenshotdialog.cpp
index 7edb027..6117e21 100644
--- a/src/screenshotdialog.cpp
+++ b/src/screenshotdialog.cpp
@@ -1,147 +1,151 @@
/*
* Copyright © 2018 Red Hat, Inc
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*
* Authors:
* Jan Grulich
*/
#include "screenshotdialog.h"
#include "ui_screenshotdialog.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
Q_LOGGING_CATEGORY(XdgDesktopPortalKdeScreenshotDialog, "xdp-kde-screenshot-dialog")
static int readData(int fd, QByteArray &data)
{
// implementation based on QtWayland file qwaylanddataoffer.cpp
char buf[4096];
int retryCount = 0;
int n;
while (true) {
n = QT_READ(fd, buf, sizeof buf);
// give user 30 sec to click a window, afterwards considered as error
if (n == -1 && (errno == EAGAIN) && ++retryCount < 30000) {
usleep(1000);
} else {
break;
}
}
if (n > 0) {
data.append(buf, n);
n = readData(fd, data);
}
return n;
}
static QImage readImage(int pipeFd)
{
QByteArray content;
if (readData(pipeFd, content) != 0) {
close(pipeFd);
return QImage();
}
close(pipeFd);
QDataStream ds(content);
QImage image;
ds >> image;
return image;
}
ScreenshotDialog::ScreenshotDialog(QDialog *parent, Qt::WindowFlags flags)
: QDialog(parent, flags)
, m_dialog(new Ui::ScreenshotDialog)
{
m_dialog->setupUi(this);
connect(m_dialog->buttonBox, &QDialogButtonBox::accepted, this, &ScreenshotDialog::accept);
connect(m_dialog->buttonBox, &QDialogButtonBox::rejected, this, &ScreenshotDialog::reject);
connect(m_dialog->takeScreenshotButton, &QPushButton::clicked, this, [this] () {
QTimer::singleShot(1000 * m_dialog->delaySpinBox->value(), this, &ScreenshotDialog::takeScreenshot);
});
+#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
connect(m_dialog->areaComboBox, static_cast(&QComboBox::currentIndexChanged), this, [this] (int index) {
+#else
+ connect(m_dialog->areaComboBox, static_cast(&QComboBox::currentIndexChanged) , this, [this] (int index) {
+#endif
m_dialog->includeBordersCheckbox->setEnabled(index == 2);
});
m_dialog->buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
setWindowTitle(i18n("Request screenshot"));
}
ScreenshotDialog::~ScreenshotDialog()
{
delete m_dialog;
}
void ScreenshotDialog::takeScreenshot()
{
int pipeFds[2];
if (pipe2(pipeFds, O_CLOEXEC|O_NONBLOCK) != 0) {
Q_EMIT failed();
return;
}
QDBusInterface interface(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QStringLiteral("org.kde.kwin.Screenshot"));
if (m_dialog->areaComboBox->currentIndex() < 2) {
interface.asyncCall(m_dialog->areaComboBox->currentIndex() ? QStringLiteral("screenshotScreen") : QStringLiteral("screenshotFullscreen"), QVariant::fromValue(QDBusUnixFileDescriptor(pipeFds[1])), m_dialog->includeCursorCheckbox->isChecked());
} else {
interface.asyncCall(QStringLiteral("interactive"), QVariant::fromValue(QDBusUnixFileDescriptor(pipeFds[1])), mask());
}
QFutureWatcher *watcher = new QFutureWatcher(this);
QObject::connect(watcher, &QFutureWatcher::finished, this,
[watcher, this] {
watcher->deleteLater();
m_image = watcher->result();
m_dialog->image->setPixmap(QPixmap::fromImage(m_image).scaled(400, 320, Qt::KeepAspectRatio));
m_dialog->buttonBox->button(QDialogButtonBox::Save)->setEnabled(true);
}
);
watcher->setFuture(QtConcurrent::run(readImage, pipeFds[0]));
::close(pipeFds[1]);
}
QImage ScreenshotDialog::image() const
{
return m_image;
}
int ScreenshotDialog::mask()
{
int mask = 0;
if (m_dialog->includeBordersCheckbox->isChecked()) {
mask = 1;
}
if (m_dialog->includeCursorCheckbox->isChecked()) {
mask |= 1 << 1;
}
return mask;
}