Skip to content

Commit 8d8a4c9

Browse files
authored
Fix multi monitor offset bug in Qt6 multi-monitor setups for X11 (flameshot-org#4127)
* Fix dual monitor offset bug in Qt6 multi-monitor setups The issue was caused by using QApplication::primaryScreen() to capture the entire desktop, but in Qt6 the primary screen is not necessarily the leftmost screen. This caused coordinate system misalignment in multi-monitor setups where the primary screen is positioned to the right. Additionally, the previous approach failed in edge cases where screens have different heights and the desktop bounding box includes virtual space that doesn't correspond to any physical screen. Changes: - Replace single-screen desktop capture with composite approach - Capture each screen individually and composite them together - Position capture widget to cover entire desktop geometry - Remove devicePixelRatio division that caused coordinate issues - Handle virtual desktop space by filling with black background This solution works with any multi-monitor configuration including: - Primary screen not being leftmost - Screens with different resolutions and alignments - Bottom-aligned or top-aligned screen arrangements - Complex layouts with virtual coordinate space Fixes flameshot-org#4111 * Fix clang-format issue --------- Co-authored-by: ionsquare <[email protected]>
1 parent 8006d79 commit 8d8a4c9

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

src/utils/screengrabber.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,30 @@ QPixmap ScreenGrabber::grabEntireDesktop(bool& ok)
205205
#endif
206206
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX) || defined(Q_OS_WIN)
207207
QRect geometry = desktopGeometry();
208-
QPixmap p(QApplication::primaryScreen()->grabWindow(
209-
wid, geometry.x(), geometry.y(), geometry.width(), geometry.height()));
210-
QScreen* screen = qApp->screenAt(QCursor::pos());
211-
p.setDevicePixelRatio(screen->devicePixelRatio());
212-
return p;
208+
209+
// Qt6 fix: Create a composite image from all screens to handle
210+
// multi-monitor setups where screens have different positions/heights.
211+
// This fixes the dual monitor offset bug and handles edge cases where
212+
// the desktop bounding box includes virtual space.
213+
QPixmap desktop(geometry.size());
214+
desktop.fill(Qt::black); // Fill with black background
215+
216+
QPainter painter(&desktop);
217+
for (QScreen* screen : QGuiApplication::screens()) {
218+
QRect screenGeom = screen->geometry();
219+
QPixmap screenCapture = screen->grabWindow(
220+
wid, 0, 0, screenGeom.width(), screenGeom.height());
221+
222+
// Calculate position relative to desktop top-left
223+
QPoint relativePos = screenGeom.topLeft() - geometry.topLeft();
224+
painter.drawPixmap(relativePos, screenCapture);
225+
}
226+
painter.end();
227+
228+
// Set device pixel ratio based on the primary screen
229+
desktop.setDevicePixelRatio(
230+
QApplication::primaryScreen()->devicePixelRatio());
231+
return desktop;
213232
#endif
214233
}
215234

@@ -259,8 +278,9 @@ QRect ScreenGrabber::desktopGeometry()
259278

260279
for (QScreen* const screen : QGuiApplication::screens()) {
261280
QRect scrRect = screen->geometry();
262-
scrRect.moveTo(scrRect.x() / screen->devicePixelRatio(),
263-
scrRect.y() / screen->devicePixelRatio());
281+
// Qt6 fix: Don't divide by devicePixelRatio for multi-monitor setups
282+
// This was causing coordinate offset issues in dual monitor
283+
// configurations
264284
geometry = geometry.united(scrRect);
265285
}
266286
return geometry;

src/widgets/capture/capturewidget.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,11 @@ CaptureWidget::CaptureWidget(const CaptureRequest& req,
155155
#if !defined(FLAMESHOT_DEBUG_CAPTURE)
156156
setWindowFlags(Qt::BypassWindowManagerHint | Qt::WindowStaysOnTopHint |
157157
Qt::FramelessWindowHint | Qt::Tool);
158-
resize(pixmap().size());
158+
// Fix for Qt6 dual monitor offset: position widget to cover entire
159+
// desktop
160+
QRect desktopGeom = ScreenGrabber().desktopGeometry();
161+
move(desktopGeom.topLeft());
162+
resize(desktopGeom.size());
159163
#endif
160164
#endif
161165
}

0 commit comments

Comments
 (0)