From b17524ac22bbe0ae2d70b1286c62df64b99371f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D0=B5=D0=BC=20=D0=9C=D0=BE=D1=80=D0=BE?= =?UTF-8?q?=D0=B7=D0=BE=D0=B2?= Date: Mon, 25 May 2026 21:05:34 +0300 Subject: [PATCH 1/3] fix: restore multi-monitor screenshot capture in Qt6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Qt6's QScreen::grabWindow(0) captures only the screen it belongs to, unlike Qt5's QDesktopWidget-based approach which grabbed the full X11 virtual desktop. This broke fullscreen and area capture on multi-monitor setups — the image always showed the primary screen content regardless of which monitor the cursor was on. Fix by iterating all QScreens, grabbing each one individually, and compositing them onto a canvas sized to the full virtual desktop. Translate all coordinates relative to the virtual desktop origin so per-monitor crop and selection capture work correctly when monitors are arranged with negative Qt logical coordinates. Co-Authored-By: Claude Sonnet 4.6 --- src/screenshooter.cpp | 46 +++++++++++++++++++++++++++---------------- src/screenshooter.h | 2 ++ 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/screenshooter.cpp b/src/screenshooter.cpp index dcb7e18d..b11a9841 100755 --- a/src/screenshooter.cpp +++ b/src/screenshooter.cpp @@ -27,31 +27,34 @@ #include #endif +static QRect virtualDesktopRect() +{ + QRect r; + for (QScreen *s : QGuiApplication::screens()) + r = r.united(s->geometry()); + return r; +} + const QImage ScreenShooter::captureFullscreen(bool captureMultipleMonitors) { QImage allMonitorsScreenshot = ScreenShooter::captureAllMonitors(); - //If capturing only a single monitor, crop the image if(!captureMultipleMonitors) { - #if QT_VERSION >= QT_VERSION_CHECK(5,10,0) - QScreen* screen = QGuiApplication::screenAt(QCursor::pos()); - #else - int screenNumber = QApplication::desktop()->screenNumber(QCursor::pos()); - QScreen* screen = QApplication::screens().at(screenNumber); - #endif - return allMonitorsScreenshot.copy(screen->geometry()); + QScreen* screen = QGuiApplication::screenAt(QCursor::pos()); + if (!screen) screen = QApplication::primaryScreen(); + QRect virt = virtualDesktopRect(); + return allMonitorsScreenshot.copy(screen->geometry().translated(-virt.topLeft())); } - //Otherwise return the image as is return allMonitorsScreenshot; } const QImage ScreenShooter::captureSelection(const QRect &area) { + QRect virt = virtualDesktopRect(); QImage allMonitorsScreenshot = ScreenShooter::captureAllMonitors(); - QImage areaScreenshot = allMonitorsScreenshot.copy(area); - return areaScreenshot; + return allMonitorsScreenshot.copy(area.translated(-virt.topLeft())); } const QImage ScreenShooter::captureWindow(WId windowID, bool captureWindowBorders) @@ -186,11 +189,20 @@ const QImage ScreenShooter::captureAllMonitors() } } #endif - //If we are on Win/Mac, or not running on Wayland, use the Qt API to take a screenshot + // Qt6: grabWindow(0) captures only "this screen", not the full virtual desktop. + // Grab each screen individually and composite them into one image. INFO(QObject::tr("Capturing the screen using the Qt API")); - QScreen* screen = QApplication::primaryScreen(); - QRect screenGeometry = screen->virtualGeometry(); - QPixmap pixmap = screen->grabWindow(0, screenGeometry.x(), screenGeometry.y(), screenGeometry.width(), screenGeometry.height()); - - return pixmap.toImage(); + QRect virt = virtualDesktopRect(); + QImage result(virt.size(), QImage::Format_RGB32); + result.fill(Qt::black); + QPainter painter(&result); + for (QScreen *s : QGuiApplication::screens()) { + QImage screenImg = s->grabWindow(0).toImage(); + QRect target = s->geometry().translated(-virt.topLeft()); + if (screenImg.size() != target.size()) + screenImg = screenImg.scaled(target.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + painter.drawImage(target.topLeft(), screenImg); + } + painter.end(); + return result; } diff --git a/src/screenshooter.h b/src/screenshooter.h index 3177ea7b..315873b9 100755 --- a/src/screenshooter.h +++ b/src/screenshooter.h @@ -17,9 +17,11 @@ #include #include #include +#include #include #include #include +#include class ScreenShooter { From 4e9cb476b9d1e9983bcc4b5307b2e4a873c2bcd6 Mon Sep 17 00:00:00 2001 From: "Olav S. Thoresen" Date: Sun, 31 May 2026 14:20:53 +0200 Subject: [PATCH 2/3] keep original comments Co-authored-by: Olav S. Thoresen --- src/screenshooter.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/screenshooter.cpp b/src/screenshooter.cpp index b11a9841..15178796 100755 --- a/src/screenshooter.cpp +++ b/src/screenshooter.cpp @@ -39,6 +39,7 @@ const QImage ScreenShooter::captureFullscreen(bool captureMultipleMonitors) { QImage allMonitorsScreenshot = ScreenShooter::captureAllMonitors(); + //If capturing only a single monitor, crop the image if(!captureMultipleMonitors) { QScreen* screen = QGuiApplication::screenAt(QCursor::pos()); @@ -47,6 +48,7 @@ const QImage ScreenShooter::captureFullscreen(bool captureMultipleMonitors) return allMonitorsScreenshot.copy(screen->geometry().translated(-virt.topLeft())); } + //Otherwise return the image as is return allMonitorsScreenshot; } @@ -189,7 +191,8 @@ const QImage ScreenShooter::captureAllMonitors() } } #endif - // Qt6: grabWindow(0) captures only "this screen", not the full virtual desktop. + //If we are on Win/Mac, or not running on Wayland, use the Qt API to take a screenshot + // Grab each screen individually and composite them into one image. // Grab each screen individually and composite them into one image. INFO(QObject::tr("Capturing the screen using the Qt API")); QRect virt = virtualDesktopRect(); From 6422738835a4350cea2dad11c53d3c73d0502e6d Mon Sep 17 00:00:00 2001 From: "Olav S. Thoresen" Date: Sun, 31 May 2026 14:22:08 +0200 Subject: [PATCH 3/3] remove duplicated comment --- src/screenshooter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/screenshooter.cpp b/src/screenshooter.cpp index 15178796..6d36ea72 100755 --- a/src/screenshooter.cpp +++ b/src/screenshooter.cpp @@ -193,7 +193,6 @@ const QImage ScreenShooter::captureAllMonitors() #endif //If we are on Win/Mac, or not running on Wayland, use the Qt API to take a screenshot // Grab each screen individually and composite them into one image. - // Grab each screen individually and composite them into one image. INFO(QObject::tr("Capturing the screen using the Qt API")); QRect virt = virtualDesktopRect(); QImage result(virt.size(), QImage::Format_RGB32);