Skip to content

Commit 9a06db4

Browse files
authored
Fix pin size on Windows for scaled screen (#4907)
Pinning a capture on a display with 150% scaling produces a pin window half again as large as the region that was selected. #4614 fixed the position of that window for v14.0.0; this is the size. A capture started from the tray icon is fine, because the tray lives in the daemon and createPin() hands the pixmap straight to attachPin(). Any invocation that runs in its own process instead -- `flameshot gui` from a shell, a desktop or AutoHotkey shortcut, D-Bus -- finds FlameshotDaemon::instance() null and serializes the capture to the daemon. QDataStream writes a QPixmap as a plain image, which carries no device pixel ratio, so the daemon reconstructs a pixmap that claims a ratio of 1. PinWidget then lays out device pixels as if they were logical ones and the window comes out too large by the scale factor. The built-in PrintScreen hook is not affected; it runs inside the daemon and takes the in-process path. Send the ratio next to the pixmap so the serialized path ends up with the same pixmap the in-process path already gets. Both transports share the reading half, since the D-Bus adapter and the KDSingleApplication handler each deserialize the message themselves. A message from an older flameshot has no ratio appended; the read runs past the end, the stream reports it, and the pixmap keeps the ratio it already had. Checked on Windows 11, 1024x768 screen, QT_SCALE_FACTOR=1.5, pinning a 400x300 region. The pin window measured 621x471 before and 422x321 after. The capture is 400x300 device pixels either way, so the pin should be that plus the 7pt margin on each side, and the patched size matches the 414x314 measured on an unscaled screen to within the scaled margin. Unscaled displays measured 414x314 both before and after.
1 parent 3e80710 commit 9a06db4

2 files changed

Lines changed: 28 additions & 6 deletions

File tree

data/dbus/org.flameshot.Flameshot.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
<!--
1313
attachPin:
14-
@data: Byte array containing the screenshot and geometry information.
14+
@data: Byte array containing the screenshot, geometry information and
15+
the screenshot's device pixel ratio.
1516
1617
Attach a pinned screenshot widget to the daemon.
1718
-->

src/core/flameshotdaemon.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,26 @@
3939
#include "core/globalshortcutfilter.h"
4040
#endif
4141

42+
namespace {
43+
/**
44+
* @brief Read a pin message written by FlameshotDaemon::createPin.
45+
*
46+
* A QPixmap loses its device pixel ratio when it goes through a QDataStream,
47+
* so it travels next to the pixmap and is restored here. Without it the pin is
48+
* laid out in device pixels and comes out too big on a scaled screen. Messages
49+
* from an older flameshot don't carry it, in which case the pixmap keeps the
50+
* ratio it was created with.
51+
*/
52+
void readPin(QDataStream& stream, QPixmap& pixmap, QRect& geometry)
53+
{
54+
qreal devicePixelRatio = 0;
55+
stream >> pixmap >> geometry >> devicePixelRatio;
56+
if (stream.status() == QDataStream::Ok && devicePixelRatio > 0) {
57+
pixmap.setDevicePixelRatio(devicePixelRatio);
58+
}
59+
}
60+
}
61+
4262
/**
4363
* @brief A way of accessing the flameshot daemon both from the daemon itself,
4464
* and from subcommands.
@@ -121,13 +141,15 @@ void FlameshotDaemon::createPin(const QPixmap& capture, QRect geometry)
121141
QByteArray data;
122142
QDataStream stream(&data, QIODevice::WriteOnly);
123143

144+
// A QPixmap loses its device pixel ratio when streamed, so send it along.
124145
#if defined(USE_KDSINGLEAPPLICATION) && \
125146
(defined(Q_OS_MACOS) || defined(Q_OS_WIN))
126147
auto kdsa = KDSingleApplication(QStringLiteral("org.flameshot.Flameshot"));
127-
stream << QStringLiteral("attachPin") << capture << geometry;
148+
stream << QStringLiteral("attachPin") << capture << geometry
149+
<< capture.devicePixelRatio();
128150
kdsa.sendMessage(data);
129151
#else
130-
stream << capture << geometry;
152+
stream << capture << geometry << capture.devicePixelRatio();
131153
QDBusMessage m = createMethodCall(QStringLiteral("attachPin"));
132154
m << data;
133155
call(m);
@@ -330,8 +352,7 @@ void FlameshotDaemon::attachPin(const QByteArray& data)
330352
QPixmap pixmap;
331353
QRect geometry;
332354

333-
stream >> pixmap;
334-
stream >> geometry;
355+
readPin(stream, pixmap, geometry);
335356

336357
attachPin(pixmap, geometry);
337358
}
@@ -474,7 +495,7 @@ void FlameshotDaemon::messageReceivedFromSecondaryInstance(
474495
if (methodCall == QStringLiteral("attachPin")) {
475496
QPixmap capture;
476497
QRect geometry;
477-
stream >> capture >> geometry;
498+
readPin(stream, capture, geometry);
478499
// qDebug() << "Pixmap:" << capture;
479500
// qDebug() << "Geometry:" << geometry;
480501
if (!capture.isNull()) {

0 commit comments

Comments
 (0)