Avoid double pixel-ratio scaling of dbus tray icons

QIcon::pixmap does automatic scaling to DPR by default, so
use QIconEngine API to access internal pixmaps directly instead.

Pick-to: 5.15
Task-number: QTBUG-83806
Change-Id: I3ccbed8387811a87bbea3f5d4ad9963e1be28a49
Reviewed-by: Dmitry Shachnev <mitya57@gmail.com>
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Allan Sandfeld Jensen 2020-09-21 14:29:52 +02:00
parent f69144471b
commit e5e89d17b3
2 changed files with 11 additions and 10 deletions

View File

@ -213,10 +213,9 @@ QTemporaryFile *QDBusTrayIcon::tempIcon(const QIcon &icon)
} }
if (!necessary) if (!necessary)
return nullptr; return nullptr;
qreal dpr = qGuiApp->devicePixelRatio();
QTemporaryFile *ret = new QTemporaryFile(tempFileTemplate(), this); QTemporaryFile *ret = new QTemporaryFile(tempFileTemplate(), this);
ret->open(); ret->open();
icon.pixmap(QSize(22 * dpr, 22 * dpr)).save(ret); icon.pixmap(QSize(22, 22)).save(ret);
ret->close(); ret->close();
return ret; return ret;
} }

View File

@ -46,6 +46,7 @@
#include <QDBusMetaType> #include <QDBusMetaType>
#include <QImage> #include <QImage>
#include <QIcon> #include <QIcon>
#include <QIconEngine>
#include <QImage> #include <QImage>
#include <QPixmap> #include <QPixmap>
#include <QDebug> #include <QDebug>
@ -54,6 +55,7 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <qpa/qplatformmenu.h> #include <qpa/qplatformmenu.h>
#include <private/qdbusplatformmenu_p.h> #include <private/qdbusplatformmenu_p.h>
#include <private/qicon_p.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -64,35 +66,35 @@ static const int IconNormalMediumSize = 64;
QXdgDBusImageVector iconToQXdgDBusImageVector(const QIcon &icon) QXdgDBusImageVector iconToQXdgDBusImageVector(const QIcon &icon)
{ {
QXdgDBusImageVector ret; QXdgDBusImageVector ret;
QList<QSize> sizes = icon.availableSizes(); QIconEngine *engine = const_cast<QIcon &>(icon).data_ptr()->engine;
QList<QSize> sizes = engine->availableSizes(QIcon::Normal, QIcon::Off);
// Omit any size larger than 64 px, to save D-Bus bandwidth; // Omit any size larger than 64 px, to save D-Bus bandwidth;
// ensure that 22px or smaller exists, because it's a common size; // ensure that 22px or smaller exists, because it's a common size;
// and ensure that something between 22px and 64px exists, for better scaling to other sizes. // and ensure that something between 22px and 64px exists, for better scaling to other sizes.
bool hasSmallIcon = false; bool hasSmallIcon = false;
bool hasMediumIcon = false; bool hasMediumIcon = false;
qreal dpr = qGuiApp->devicePixelRatio();
QList<QSize> toRemove; QList<QSize> toRemove;
for (const QSize &size : qAsConst(sizes)) { for (const QSize &size : qAsConst(sizes)) {
int maxSize = qMax(size.width(), size.height()); int maxSize = qMax(size.width(), size.height());
if (maxSize <= IconNormalSmallSize * dpr) if (maxSize <= IconNormalSmallSize)
hasSmallIcon = true; hasSmallIcon = true;
else if (maxSize <= IconNormalMediumSize * dpr) else if (maxSize <= IconNormalMediumSize)
hasMediumIcon = true; hasMediumIcon = true;
else if (maxSize > IconSizeLimit * dpr) else if (maxSize > IconSizeLimit)
toRemove << size; toRemove << size;
} }
for (const QSize &size : qAsConst(toRemove)) for (const QSize &size : qAsConst(toRemove))
sizes.removeOne(size); sizes.removeOne(size);
if (!hasSmallIcon) if (!hasSmallIcon)
sizes.append(QSize(IconNormalSmallSize * dpr, IconNormalSmallSize * dpr)); sizes.append(QSize(IconNormalSmallSize, IconNormalSmallSize));
if (!hasMediumIcon) if (!hasMediumIcon)
sizes.append(QSize(IconNormalMediumSize * dpr, IconNormalMediumSize * dpr)); sizes.append(QSize(IconNormalMediumSize, IconNormalMediumSize));
ret.reserve(sizes.size()); ret.reserve(sizes.size());
for (const QSize &size : qAsConst(sizes)) { for (const QSize &size : qAsConst(sizes)) {
// Protocol specifies ARGB32 format in network byte order // Protocol specifies ARGB32 format in network byte order
QImage im = icon.pixmap(size).toImage().convertToFormat(QImage::Format_ARGB32); QImage im = engine->pixmap(size, QIcon::Normal, QIcon::Off).toImage().convertToFormat(QImage::Format_ARGB32);
// letterbox if necessary to make it square // letterbox if necessary to make it square
if (im.height() != im.width()) { if (im.height() != im.width()) {
int maxSize = qMax(im.width(), im.height()); int maxSize = qMax(im.width(), im.height());