From 3ededae5745761d23907d65bbaebb283f6f8e3f2 Mon Sep 17 00:00:00 2001 From: JACK Date: Thu, 16 Feb 2023 05:44:58 +0800 Subject: [PATCH] Add grim-based wayland universal screenshot adapter (#3018) * Add grim-based wayland universal screenshot adapter In the past, flameshot used a special and superfluous method to call the wayland screenshot component - dbus protocol communication. Although this method is supported by a large number of distributions, it does not take into account the actual situation of wayland (including WM custom desktop environment users). Now, we can enable the wayland universal screenshot adapter with the help of grim, just add the following compilation flags in cmake: ``` -DUSE_WAYLAND_GRIM=true ``` In addition, the patch also adds HYPRLAND type and OTHER type support * grim outputs to standard streams instead of files * Automatically enable wayland clipboard support when USE_WAYLAND_GRIM is enabled * Cancel USE_WAYLAND_GRIM Activate USE_WAYLAND_CLIPBOARD by default Due to the dependency problem of USE_WAYLAND_CLIPBOARD, cancel USE_WAYLAND_GRIM to activate USE_WAYLAND_CLIPBOARD by default, Add a warning prompt to activate USE_WAYLAND_GRIM when USE_WAYLAND_CLIPBOARD is activated * perform formatting * modify cmake message The grim adapter cannot be used in gnome and similar environments, modify the cmake message to express it * remove generic screenshot adapter for gnome Generic screenshot adapter is only supported on compositors that support wlroots * Update format --- src/CMakeLists.txt | 7 ++++++ src/utils/desktopinfo.cpp | 3 +++ src/utils/desktopinfo.h | 3 ++- src/utils/screengrabber.cpp | 44 ++++++++++++++++++++++++++++++++++++- src/utils/screengrabber.h | 1 + 5 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d6c6d69de6..f1f30f1d9b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -216,10 +216,17 @@ target_link_libraries( ) if (USE_WAYLAND_CLIPBOARD) + if(!USE_WAYLAND_GRIM) + message(WARNING "You activated the USE_WAYLAND_CLIPBOARD option, but did not activate the USE_WAYLAND_GRIM option. Flameshot will use the dbus protocol to support wayland. If you use wlroots-based wayland, it is recommended to enable USE_WAYLAND_GRIM") + endif() target_compile_definitions(flameshot PRIVATE USE_WAYLAND_CLIPBOARD=1) target_link_libraries(flameshot KF5::GuiAddons) endif() +if (USE_WAYLAND_GRIM) + target_compile_definitions(flameshot PRIVATE USE_WAYLAND_GRIM=1) +endif() + if (APPLE) set(MACOSX_BUNDLE_IDENTIFIER "org.flameshot") set_target_properties( diff --git a/src/utils/desktopinfo.cpp b/src/utils/desktopinfo.cpp index 4833f5ac8b..393cad751a 100644 --- a/src/utils/desktopinfo.cpp +++ b/src/utils/desktopinfo.cpp @@ -37,6 +37,9 @@ DesktopInfo::WM DesktopInfo::windowManager() if (desktop.contains(QLatin1String("sway"), Qt::CaseInsensitive)) { return DesktopInfo::SWAY; } + if (desktop.contains(QLatin1String("Hyprland"), Qt::CaseInsensitive)) { + return DesktopInfo::HYPRLAND; + } if (desktop.contains(QLatin1String("kde-plasma"))) { return DesktopInfo::KDE; } diff --git a/src/utils/desktopinfo.h b/src/utils/desktopinfo.h index b84708c6a8..03f29086a6 100644 --- a/src/utils/desktopinfo.h +++ b/src/utils/desktopinfo.h @@ -16,7 +16,8 @@ class DesktopInfo KDE, OTHER, QTILE, - SWAY + SWAY, + HYPRLAND }; bool waylandDetected(); diff --git a/src/utils/screengrabber.cpp b/src/utils/screengrabber.cpp index 0605b60567..062c4bdeea 100644 --- a/src/utils/screengrabber.cpp +++ b/src/utils/screengrabber.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) @@ -25,6 +26,29 @@ ScreenGrabber::ScreenGrabber(QObject* parent) : QObject(parent) {} +void ScreenGrabber::generalGrimScreenshot(bool& ok, QPixmap& res) +{ +#ifdef USE_WAYLAND_GRIM +#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) + QProcess Process; + QString program = "grim"; + QStringList arguments; + arguments << "-"; + Process.start(program, arguments); + if (Process.waitForFinished()) { + res.loadFromData(Process.readAll()); + ok = true; + } else { + ok = false; + AbstractLogger::error() + << tr("The universal wayland screen capture adapter requires Grim as " + "the screen capture component of wayland. If the screen " + "capture component is missing, please install it!"); + } +#endif +#endif +} + void ScreenGrabber::freeDesktopPortal(bool& ok, QPixmap& res) { @@ -102,9 +126,27 @@ QPixmap ScreenGrabber::grabEntireDesktop(bool& ok) switch (m_info.windowManager()) { case DesktopInfo::GNOME: case DesktopInfo::KDE: + freeDesktopPortal(ok, res); + break; case DesktopInfo::QTILE: - case DesktopInfo::SWAY: { + case DesktopInfo::SWAY: + case DesktopInfo::HYPRLAND: + case DesktopInfo::OTHER: { +#ifndef USE_WAYLAND_GRIM + AbstractLogger::warning() << tr( + "If the USE_WAYLAND_GRIM option is not activated, the dbus " + "protocol will be used. It should be noted that using the " + "dbus protocol under wayland is not recommended. It is " + "recommended to recompile with the USE_WAYLAND_GRIM flag to " + "activate the grim-based general wayland screenshot adapter"); freeDesktopPortal(ok, res); +#else + AbstractLogger::warning() + << tr("grim's screenshot component is implemented based on " + "wlroots, it may not be used in GNOME or similar " + "desktop environments"); + generalGrimScreenshot(ok, res); +#endif break; } default: diff --git a/src/utils/screengrabber.h b/src/utils/screengrabber.h index c565e3f4bc..39be6d5ac2 100644 --- a/src/utils/screengrabber.h +++ b/src/utils/screengrabber.h @@ -16,6 +16,7 @@ class ScreenGrabber : public QObject QRect screenGeometry(QScreen* screen); QPixmap grabScreen(QScreen* screenNumber, bool& ok); void freeDesktopPortal(bool& ok, QPixmap& res); + void generalGrimScreenshot(bool& ok, QPixmap& res); QRect desktopGeometry(); private: