diff options
Diffstat (limited to 'community/plasma-phone-components/0001-Port-to-the-new-org.kde.KWin.ScreenShots2-interface.patch')
-rw-r--r-- | community/plasma-phone-components/0001-Port-to-the-new-org.kde.KWin.ScreenShots2-interface.patch | 449 |
1 files changed, 0 insertions, 449 deletions
diff --git a/community/plasma-phone-components/0001-Port-to-the-new-org.kde.KWin.ScreenShots2-interface.patch b/community/plasma-phone-components/0001-Port-to-the-new-org.kde.KWin.ScreenShots2-interface.patch deleted file mode 100644 index 9b8654a4db1..00000000000 --- a/community/plasma-phone-components/0001-Port-to-the-new-org.kde.KWin.ScreenShots2-interface.patch +++ /dev/null @@ -1,449 +0,0 @@ -From 989d6fdc1dbf399d3daafa3c53327288a9cc7d01 Mon Sep 17 00:00:00 2001 -From: Aleix Pol <aleixpol@kde.org> -Date: Fri, 23 Jul 2021 03:30:16 +0200 -Subject: [PATCH] Port to the new org.kde.KWin.ScreenShots2 interface - -Fixes https://invent.kde.org/plasma/plasma-phone-components/-/issues/85 ---- - containments/panel/CMakeLists.txt | 2 +- - .../panel/dbus/org.kde.KWin.ScreenShot2.xml | 184 ++++++++++++++++++ - containments/panel/phonepanel.cpp | 152 ++++++++------- - containments/panel/phonepanel.h | 5 +- - 4 files changed, 274 insertions(+), 69 deletions(-) - create mode 100644 containments/panel/dbus/org.kde.KWin.ScreenShot2.xml - -diff --git a/containments/panel/CMakeLists.txt b/containments/panel/CMakeLists.txt -index 8758686..b482ac4 100644 ---- a/containments/panel/CMakeLists.txt -+++ b/containments/panel/CMakeLists.txt -@@ -1,4 +1,4 @@ --qt5_add_dbus_interfaces(DBUS_SRCS dbus/org.kde.KWin.Screenshot.xml -+qt5_add_dbus_interfaces(DBUS_SRCS dbus/org.kde.KWin.ScreenShot2.xml - dbus/org.kde.KScreen.xml) - - set(phonepanel_SRCS -diff --git a/containments/panel/dbus/org.kde.KWin.ScreenShot2.xml b/containments/panel/dbus/org.kde.KWin.ScreenShot2.xml -new file mode 100644 -index 0000000..34c03b2 ---- /dev/null -+++ b/containments/panel/dbus/org.kde.KWin.ScreenShot2.xml -@@ -0,0 +1,184 @@ -+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" -+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> -+<!-- -+ SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org> -+ -+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL -+--> -+<node name="/org/kde/KWin/ScreenShot2"> -+ <!-- -+ org.kde.KWin.ScreenShot2: -+ @short_description: Screen shot interface -+ -+ This interface provides a way to request a screenshot of a rectangular area, -+ a screen, or a window. -+ --> -+ <interface name="org.kde.KWin.ScreenShot2"> -+ <!-- -+ CaptureWindow: -+ @handle: The unique handle that identified the window -+ @options: Optional vardict with screenshot options -+ @pipe: The pipe file descriptor where the screenshot will be written -+ -+ Take a screenshot of the specified window. The application that -+ requests the screenshot must have the org.kde.KWin.ScreenShot2 -+ interface listed in the X-KDE-DBUS-Restricted-Interfaces desktop -+ file entry. -+ -+ Available @options include: -+ -+ * "include-cursor" (b): Whether the cursor should be included. -+ Defaults to false -+ * "include-decoration" (b): Whether the decoration should be included. -+ Defaults to false -+ * "native-resolution" (b): Whether the screenshot should be in -+ native size. Defaults to false -+ -+ The following results get returned via the @results vardict: -+ -+ * "type" (s): The type of the image written to the pipe. Currently, -+ the only supported type is "raw" -+ * "width" (u): The width of the image. Available only if the image -+ type is "raw" -+ * "height" (u): The height of the image. Available only if the image -+ type is "raw" -+ * "stride" (u): The number of bytes per row. Available only if the -+ image type is "raw" -+ * "format" (u): The image format, as defined in QImage::Format. -+ Available only if the image type is "raw" -+ --> -+ <method name="CaptureWindow"> -+ <arg name="handle" type="s" direction="in" /> -+ <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap" /> -+ <arg name="options" type="a{sv}" direction="in" /> -+ <arg name="pipe" type="h" direction="in" /> -+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap" /> -+ <arg name="results" type="a{sv}" direction="out" /> -+ </method> -+ -+ <!-- -+ CaptureArea: -+ @x: The x coordinate of the upper left corner of the area -+ @y: The y coordinate of the upper left corner of the area -+ @width: The width of the screenshot area -+ @height: The height of the screenshot area -+ @options: Optional vardict with screenshot options -+ @pipe: The pipe file descriptor where the screenshot will be written -+ -+ Take a screenshot of the specified rectangular area. The application -+ that requests the screenshot must have the org.kde.KWin.ScreenShot2 -+ interface listed in the X-KDE-DBUS-Restricted-Interfaces desktop file -+ entry. -+ -+ Available @options include: -+ -+ * "include-cursor" (b): Whether the cursor should be included. -+ Defaults to false -+ * "native-resolution" (b): Whether the screenshot should be in -+ native size. Defaults to false -+ -+ The following results get returned via the @results vardict: -+ -+ * "type" (s): The type of the image written to the pipe. Currently, -+ the only supported type is "raw" -+ * "width" (u): The width of the image. Available only if the image -+ type is "raw" -+ * "height" (u): The height of the image. Available only if the image -+ type is "raw" -+ * "stride" (u): The number of bytes per row. Available only if the -+ image type is "raw" -+ * "format" (u): The image format, as defined in QImage::Format. -+ Available only if the image type is "raw" -+ --> -+ <method name="CaptureArea"> -+ <arg name="x" type="i" direction="in" /> -+ <arg name="y" type="i" direction="in" /> -+ <arg name="width" type="u" direction="in" /> -+ <arg name="height" type="u" direction="in" /> -+ <annotation name="org.qtproject.QtDBus.QtTypeName.In4" value="QVariantMap" /> -+ <arg name="options" type="a{sv}" direction="in" /> -+ <arg name="pipe" type="h" direction="in" /> -+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap" /> -+ <arg name="results" type="a{sv}" direction="out" /> -+ </method> -+ -+ <!-- -+ CaptureScreen: -+ @name: The name of the screen assigned by the compositor -+ @options: Optional vardict with screenshot options -+ @pipe: The pipe file descriptor where the screenshot will be written -+ -+ Take a screenshot of the specified monitor. The application that -+ requests the screenshot must have the org.kde.KWin.ScreenShot2 -+ interface listed in the X-KDE-DBUS-Restricted-Interfaces desktop file -+ entry. -+ -+ Available @options include: -+ -+ * "include-cursor" (b): Whether the cursor should be included. -+ Defaults to false -+ * "native-resolution" (b): Whether the screenshot should be in -+ native size. Defaults to false -+ -+ The following results get returned via the @results vardict: -+ -+ * "type" (s): The type of the image written to the pipe. Currently, -+ the only supported type is "raw" -+ * "width" (u): The width of the image. Available only if the image -+ type is "raw" -+ * "height" (u): The height of the image. Available only if the image -+ type is "raw" -+ * "stride" (u): The number of bytes per row. Available only if the -+ image type is "raw" -+ * "format" (u): The image format, as defined in QImage::Format. -+ Available only if the image type is "raw" -+ --> -+ <method name="CaptureScreen"> -+ <arg name="name" type="s" direction="in" /> -+ <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap" /> -+ <arg name="options" type="a{sv}" direction="in" /> -+ <arg name="pipe" type="h" direction="in" /> -+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap" /> -+ <arg name="results" type="a{sv}" direction="out" /> -+ </method> -+ -+ <!-- -+ CaptureInteractive: -+ @kind: 0 - window, 1 - screen -+ @options: Optional vardict with screenshot options -+ @pipe: The pipe file descriptor where the screenshot will be written -+ -+ Take a screenshot of a screen or a window as selected by the user. -+ -+ Available @options include: -+ -+ * "include-cursor" (b): Whether the cursor should be included. -+ Defaults to false -+ * "include-decoration" (b): Whether the decoration should be included. -+ Defaults to false -+ * "native-resolution" (b): Whether the screenshot should be in -+ native size. Defaults to false -+ -+ The following results get returned via the @results vardict: -+ -+ * "type" (s): The type of the image written to the pipe. Currently, -+ the only supported type is "raw" -+ * "width" (u): The width of the image. Available only if the image -+ type is "raw" -+ * "height" (u): The height of the image. Available only if the image -+ type is "raw" -+ * "stride" (u): The number of bytes per row. Available only if the -+ image type is "raw" -+ * "format" (u): The image format, as defined in QImage::Format. -+ Available only if the image type is "raw" -+ --> -+ <method name="CaptureInteractive"> -+ <arg name="kind" type="u" direction="in" /> -+ <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap" /> -+ <arg name="options" type="a{sv}" direction="in" /> -+ <arg name="pipe" type="h" direction="in" /> -+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap" /> -+ <arg name="results" type="a{sv}" direction="out" /> -+ </method> -+ </interface> -+</node> -diff --git a/containments/panel/phonepanel.cpp b/containments/panel/phonepanel.cpp -index 06aab12..35a72a8 100644 ---- a/containments/panel/phonepanel.cpp -+++ b/containments/panel/phonepanel.cpp -@@ -19,6 +19,7 @@ - #include <QDateTime> - #include <QDebug> - #include <QFile> -+#include <QGuiApplication> - #include <QProcess> - #include <QScreen> - #include <QStandardPaths> -@@ -30,44 +31,45 @@ constexpr int SCREENSHOT_DELAY = 200; - - /* -- Static Helpers --------------------------------------------------------------------------- */ - --static int readData(int theFile, QByteArray &theDataOut) -+static QImage allocateImage(const QVariantMap &metadata) - { -- // implementation based on QtWayland file qwaylanddataoffer.cpp -- char lBuffer[4096]; -- int lRetryCount = 0; -- ssize_t lBytesRead = 0; -- -- do { -- // give user 30 sec to click a window, afterwards considered as error -- while (true) { -- lBytesRead = QT_READ(theFile, lBuffer, sizeof lBuffer); -- if (lBytesRead == -1 && (errno == EAGAIN) && ++lRetryCount < 30000) { -- usleep(1000); -- } else { -- break; -- } -- } -+ bool ok; - -- if (lBytesRead > 0) { -- theDataOut.append(lBuffer, lBytesRead); -- } -- } while (lBytesRead > 0); -- return lBytesRead; -+ const uint width = metadata.value(QStringLiteral("width")).toUInt(&ok); -+ if (!ok) { -+ return QImage(); -+ } -+ -+ const uint height = metadata.value(QStringLiteral("height")).toUInt(&ok); -+ if (!ok) { -+ return QImage(); -+ } -+ -+ const uint format = metadata.value(QStringLiteral("format")).toUInt(&ok); -+ if (!ok) { -+ return QImage(); -+ } -+ -+ return QImage(width, height, QImage::Format(format)); - } - --static QImage readImage(int thePipeFd) -+static QImage readImage(int fileDescriptor, const QVariantMap &metadata) - { -- QByteArray lContent; -- if (readData(thePipeFd, lContent) != 0) { -- close(thePipeFd); -+ QFile file; -+ if (!file.open(fileDescriptor, QFileDevice::ReadOnly, QFileDevice::AutoCloseHandle)) { -+ close(fileDescriptor); - return QImage(); - } -- close(thePipeFd); - -- QDataStream lDataStream(lContent); -- QImage lImage; -- lDataStream >> lImage; -- return lImage; -+ QImage result = allocateImage(metadata); -+ if (result.isNull()) { -+ return QImage(); -+ } -+ -+ QDataStream stream(&file); -+ stream.readRawData(reinterpret_cast<char *>(result.bits()), result.sizeInBytes()); -+ -+ return result; - } - - PhonePanel::PhonePanel(QObject *parent, const QVariantList &args) -@@ -75,7 +77,10 @@ PhonePanel::PhonePanel(QObject *parent, const QVariantList &args) - { - // setHasConfigurationInterface(true); - m_kscreenInterface = new org::kde::KScreen(QStringLiteral("org.kde.kded5"), QStringLiteral("/modules/kscreen"), QDBusConnection::sessionBus(), this); -- m_screenshotInterface = new org::kde::kwin::Screenshot(QStringLiteral("org.kde.KWin"), QStringLiteral("/Screenshot"), QDBusConnection::sessionBus(), this); -+ m_screenshotInterface = new OrgKdeKWinScreenShot2Interface(QStringLiteral("org.kde.KWin.ScreenShot2"), -+ QStringLiteral("/org/kde/KWin/ScreenShot2"), -+ QDBusConnection::sessionBus(), -+ this); - - m_localeConfig = KSharedConfig::openConfig(QStringLiteral("kdeglobals"), KConfig::SimpleConfig); - m_localeConfigWatcher = KConfigWatcher::create(m_localeConfig); -@@ -142,55 +147,70 @@ void PhonePanel::setAutoRotate(bool value) - } - } - --void PhonePanel::takeScreenshot() -+void PhonePanel::handleMetaDataReceived(const QVariantMap &metadata, int fd) - { -- QString filePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); -- if (filePath.isEmpty()) { -- qWarning() << "Couldn't find a writable location for the screenshot!"; -- return; -- } -- QDir picturesDir(filePath); -- if (!picturesDir.mkpath(QStringLiteral("Screenshots"))) { -- qWarning() << "Couldn't create folder at" << picturesDir.path() + QStringLiteral("/Screenshots") << "to take screenshot."; -+ const QString type = metadata.value(QStringLiteral("type")).toString(); -+ if (type != QLatin1String("raw")) { -+ qWarning() << "Unsupported metadata type:" << type; - return; - } -- filePath += QStringLiteral("/Screenshots/Screenshot_%1.png").arg(QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMdd_hhmmss"))); - -+ auto watcher = new QFutureWatcher<QImage>(this); -+ connect(watcher, &QFutureWatcher<QImage>::finished, this, [watcher]() { -+ watcher->deleteLater(); -+ -+ QString filePath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); -+ if (filePath.isEmpty()) { -+ qWarning() << "Couldn't find a writable location for the screenshot!"; -+ return; -+ } -+ QDir picturesDir(filePath); -+ if (!picturesDir.mkpath(QStringLiteral("Screenshots"))) { -+ qWarning() << "Couldn't create folder at" << picturesDir.path() + QStringLiteral("/Screenshots") << "to take screenshot."; -+ return; -+ } -+ filePath += QStringLiteral("/Screenshots/Screenshot_%1.png").arg(QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMdd_hhmmss"))); -+ const auto m_result = watcher->result(); -+ if (m_result.isNull() || !m_result.save(filePath)) { -+ qWarning() << "Screenshot failed"; -+ } else { -+ KNotification *notif = new KNotification("captured"); -+ notif->setComponentName(QStringLiteral("plasma_phone_components")); -+ notif->setTitle(i18n("New Screenshot")); -+ notif->setUrls({filePath}); -+ notif->setText(i18n("New screenshot saved to %1", filePath)); -+ notif->sendEvent(); -+ } -+ }); -+ watcher->setFuture(QtConcurrent::run(readImage, fd, metadata)); -+} -+ -+void PhonePanel::takeScreenshot() -+{ - // wait ~200 ms to wait for rest of animations - QTimer::singleShot(SCREENSHOT_DELAY, [=]() { - int lPipeFds[2]; -- if (pipe2(lPipeFds, O_CLOEXEC | O_NONBLOCK) != 0) { -+ if (pipe2(lPipeFds, O_CLOEXEC) != 0) { - qWarning() << "Could not take screenshot"; - return; - } -- // Take fullscreen screenshot, and no pointer -- QDBusPendingCall pcall = m_screenshotInterface->screenshotFullscreen(QDBusUnixFileDescriptor(lPipeFds[1]), false, true); -- QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this); -- QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [](QDBusPendingCallWatcher *watcher) { -- if (watcher->isError()) { -- const auto error = watcher->error(); -- qWarning() << "Error calling KWin DBus interface:" << error.name() << error.message(); -- } -+ -+ // We don't have access to the ScreenPool so we'll just take the first screen -+ auto pendingCall = m_screenshotInterface->CaptureScreen(qGuiApp->screens().constFirst()->name(), {}, QDBusUnixFileDescriptor(lPipeFds[1])); -+ close(lPipeFds[1]); -+ auto pipeFileDescriptor = lPipeFds[0]; -+ -+ auto watcher = new QDBusPendingCallWatcher(pendingCall, this); -+ connect(watcher, &QDBusPendingCallWatcher::finished, this, [this, watcher, pipeFileDescriptor]() { - watcher->deleteLater(); -- }); -- const auto lWatcher = new QFutureWatcher<QImage>(this); -- QObject::connect(lWatcher, &QFutureWatcher<QImage>::finished, this, [lWatcher, filePath]() { -- lWatcher->deleteLater(); -- const QImage lImage = lWatcher->result(); -- qDebug() << lImage; -- if (!lImage.save(filePath, "PNG")) { -- qWarning() << "Failed to save screenshot to" << filePath; -+ const QDBusPendingReply<QVariantMap> reply = *watcher; -+ -+ if (reply.isError()) { -+ qWarning() << "Screenshot request failed:" << reply.error().message(); - } else { -- KNotification *notif = new KNotification("captured"); -- notif->setComponentName(QStringLiteral("plasma_phone_components")); -- notif->setTitle(i18n("New Screenshot")); -- notif->setUrls({filePath}); -- notif->setText(i18n("New screenshot saved to %1", filePath)); -- notif->sendEvent(); -+ handleMetaDataReceived(reply, pipeFileDescriptor); - } - }); -- lWatcher->setFuture(QtConcurrent::run(readImage, lPipeFds[0])); -- close(lPipeFds[1]); - }); - } - -diff --git a/containments/panel/phonepanel.h b/containments/panel/phonepanel.h -index 59b9351..6e7e04a 100644 ---- a/containments/panel/phonepanel.h -+++ b/containments/panel/phonepanel.h -@@ -13,7 +13,7 @@ - #include <KSharedConfig> - - #include "kscreeninterface.h" --#include "screenshotinterface.h" -+#include "screenshot2interface.h" - - class PhonePanel : public Plasma::Containment - { -@@ -44,13 +44,14 @@ signals: - void isSystem24HourFormatChanged(); - - private: -+ void handleMetaDataReceived(const QVariantMap &metadata, int fd); - bool m_running = false; - - KConfigWatcher::Ptr m_localeConfigWatcher; - KSharedConfig::Ptr m_localeConfig; - - org::kde::KScreen *m_kscreenInterface; -- org::kde::kwin::Screenshot *m_screenshotInterface; -+ OrgKdeKWinScreenShot2Interface *m_screenshotInterface; - }; - - #endif |