File indexing completed on 2024-02-25 17:31:04

0001 /*
0002  * SPDX-FileCopyrightText: 2018 Red Hat Inc
0003  *
0004  * SPDX-License-Identifier: LGPL-2.0-or-later
0005  *
0006  * SPDX-FileCopyrightText: 2018 Jan Grulich <jgrulich@redhat.com>
0007  * SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org>
0008  */
0009 
0010 #include "screenshot.h"
0011 #include "request.h"
0012 #include "screenshot_debug.h"
0013 #include "screenshotdialog.h"
0014 #include "utils.h"
0015 
0016 #include <QDBusArgument>
0017 #include <QDBusReply>
0018 #include <QDateTime>
0019 #include <QPointer>
0020 #include <QStandardPaths>
0021 #include <QWindow>
0022 #include <QtDBus>
0023 
0024 // Keep in sync with qflatpakcolordialog from Qt flatpak platform theme
0025 Q_DECLARE_METATYPE(ScreenshotPortal::ColorRGB)
0026 
0027 QDBusArgument &operator<<(QDBusArgument &arg, const ScreenshotPortal::ColorRGB &color)
0028 {
0029     arg.beginStructure();
0030     arg << color.red << color.green << color.blue;
0031     arg.endStructure();
0032     return arg;
0033 }
0034 
0035 const QDBusArgument &operator>>(const QDBusArgument &arg, ScreenshotPortal::ColorRGB &color)
0036 {
0037     double red, green, blue;
0038     arg.beginStructure();
0039     arg >> red >> green >> blue;
0040     color.red = red;
0041     color.green = green;
0042     color.blue = blue;
0043     arg.endStructure();
0044 
0045     return arg;
0046 }
0047 
0048 QDBusArgument &operator<<(QDBusArgument &argument, const QColor &color)
0049 {
0050     argument.beginStructure();
0051     argument << color.rgba();
0052     argument.endStructure();
0053     return argument;
0054 }
0055 
0056 const QDBusArgument &operator>>(const QDBusArgument &argument, QColor &color)
0057 {
0058     argument.beginStructure();
0059     QRgb rgba;
0060     argument >> rgba;
0061     argument.endStructure();
0062     color = QColor::fromRgba(rgba);
0063     return argument;
0064 }
0065 
0066 ScreenshotPortal::ScreenshotPortal(QObject *parent)
0067     : QDBusAbstractAdaptor(parent)
0068 {
0069     qDBusRegisterMetaType<QColor>();
0070     qDBusRegisterMetaType<ColorRGB>();
0071 }
0072 
0073 ScreenshotPortal::~ScreenshotPortal()
0074 {
0075 }
0076 
0077 uint ScreenshotPortal::Screenshot(const QDBusObjectPath &handle,
0078                                   const QString &app_id,
0079                                   const QString &parent_window,
0080                                   const QVariantMap &options,
0081                                   QVariantMap &results)
0082 {
0083     qCDebug(XdgDesktopPortalKdeScreenshot) << "Screenshot called with parameters:";
0084     qCDebug(XdgDesktopPortalKdeScreenshot) << "    handle: " << handle.path();
0085     qCDebug(XdgDesktopPortalKdeScreenshot) << "    app_id: " << app_id;
0086     qCDebug(XdgDesktopPortalKdeScreenshot) << "    parent_window: " << parent_window;
0087     qCDebug(XdgDesktopPortalKdeScreenshot) << "    options: " << options;
0088 
0089     QPointer<ScreenshotDialog> screenshotDialog = new ScreenshotDialog;
0090     Utils::setParentWindow(screenshotDialog->windowHandle(), parent_window);
0091     Request::makeClosableDialogRequest(handle, screenshotDialog.data());
0092 
0093     const bool modal = options.value(QStringLiteral("modal"), false).toBool();
0094     screenshotDialog->windowHandle()->setModality(modal ? Qt::WindowModal : Qt::NonModal);
0095 
0096     const bool interactive = options.value(QStringLiteral("interactive"), false).toBool();
0097     if (!interactive) {
0098         screenshotDialog->takeScreenshotNonInteractive();
0099     } else {
0100         screenshotDialog->exec();
0101     }
0102 
0103     const QImage screenshot = screenshotDialog->image();
0104 
0105     if (screenshotDialog) {
0106         screenshotDialog->deleteLater();
0107     }
0108 
0109     if (screenshot.isNull()) {
0110         return 1;
0111     }
0112 
0113     const QString filename =
0114         QStringLiteral("%1/Screenshot_%2.png") //
0115             .arg(QStandardPaths::writableLocation(QStandardPaths::PicturesLocation), QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMdd_hhmmss")));
0116 
0117     if (!screenshot.save(filename, "PNG")) {
0118         return 1;
0119     }
0120 
0121     results.insert(QStringLiteral("uri"), QUrl::fromLocalFile(filename).toString(QUrl::FullyEncoded));
0122 
0123     return 0;
0124 }
0125 
0126 uint ScreenshotPortal::PickColor(const QDBusObjectPath &handle,
0127                                  const QString &app_id,
0128                                  const QString &parent_window,
0129                                  const QVariantMap &options,
0130                                  QVariantMap &results)
0131 {
0132     qCDebug(XdgDesktopPortalKdeScreenshot) << "PickColor called with parameters:";
0133     qCDebug(XdgDesktopPortalKdeScreenshot) << "    handle: " << handle.path();
0134     qCDebug(XdgDesktopPortalKdeScreenshot) << "    app_id: " << app_id;
0135     qCDebug(XdgDesktopPortalKdeScreenshot) << "    parent_window: " << parent_window;
0136     qCDebug(XdgDesktopPortalKdeScreenshot) << "    options: " << options;
0137 
0138     QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KWin"),
0139                                                       QStringLiteral("/ColorPicker"),
0140                                                       QStringLiteral("org.kde.kwin.ColorPicker"),
0141                                                       QStringLiteral("pick"));
0142     QDBusReply<QColor> reply = QDBusConnection::sessionBus().call(msg);
0143     if (reply.isValid() && !reply.error().isValid()) {
0144         QColor selectedColor = reply.value();
0145         ColorRGB color;
0146         color.red = selectedColor.redF();
0147         color.green = selectedColor.greenF();
0148         color.blue = selectedColor.blueF();
0149 
0150         results.insert(QStringLiteral("color"), QVariant::fromValue<ScreenshotPortal::ColorRGB>(color));
0151         return 0;
0152     }
0153 
0154     return 1;
0155 }