33
44#include " source/tray/StatusNotifierTrayIcon.h"
55
6- #include " Util/Endian .h"
6+ #include " source/tray/SniIcon .h"
77
8- #include < QColor>
98#include < QCoreApplication>
109#include < QDBusAbstractAdaptor>
1110#include < QDBusConnectionInterface>
1817#include < QDBusVariant>
1918#include < QGuiApplication>
2019#include < QIcon>
21- #include < QImage>
2220#include < QLoggingCategory>
23- #include < QPainter>
24- #include < QPen>
25- #include < QPointF>
26- #include < QRectF>
27- #include < QSize>
2821#include < QStringLiteral>
2922
30- #include < cstdint>
31-
3223namespace dish ::source {
3324
3425namespace {
@@ -40,7 +31,6 @@ constexpr auto kWatcherPath = "/StatusNotifierWatcher";
4031constexpr auto kItemInterface = " org.kde.StatusNotifierItem" ;
4132constexpr auto kItemPath = " /StatusNotifierItem" ;
4233constexpr auto kMenuPath = " /MenuBar" ;
43- constexpr auto kIconName = " com.tinkernorth.Dish" ;
4434constexpr auto kNewIconSignal = " NewIcon" ;
4535constexpr auto kNewToolTipSignal = " NewToolTip" ;
4636
@@ -87,73 +77,6 @@ QVariantMap filterProperties(const QVariantMap& properties, const QStringList& n
8777 return filtered;
8878}
8979
90- // a(iiay) carries raw 32-bit ARGB in network byte order, so the source has to
91- // be unpremultiplied ARGB32 and every pixel goes out through putU32Be —
92- // casting the scan line to a uint32_t* would raise alignment and trip
93- // -Wcast-align.
94- SniIconPixmap toSniPixmap (const QImage& source) {
95- const QImage image = source.convertToFormat (QImage::Format_ARGB32);
96- SniIconPixmap pixmap;
97- pixmap.width = image.width ();
98- pixmap.height = image.height ();
99- const qsizetype byteCount =
100- static_cast <qsizetype>(pixmap.width ) * static_cast <qsizetype>(pixmap.height ) * 4 ;
101- pixmap.data = QByteArray (byteCount, ' \0 ' );
102- auto * out = reinterpret_cast <std::uint8_t *>(pixmap.data .data ());
103- qsizetype offset = 0 ;
104- for (int y = 0 ; y < pixmap.height ; ++y) {
105- for (int x = 0 ; x < pixmap.width ; ++x) {
106- util::putU32Be (out + offset, static_cast <std::uint32_t >(image.pixel (x, y)));
107- offset += 4 ;
108- }
109- }
110- return pixmap;
111- }
112-
113- // :/icons/dish.svg belongs to the exe's resource bundle, not to dish_core, so
114- // the fallback is drawn rather than loaded.
115- QImage renderFallbackIcon (int size) {
116- QImage image (size, size, QImage::Format_ARGB32);
117- image.fill (Qt::transparent);
118- const auto extent = static_cast <qreal>(size);
119- const QPointF origin (extent * 0.24 , extent * 0.78 );
120- const QColor ink (0xF5 , 0xF6 , 0xF8 );
121-
122- QPainter painter (&image);
123- painter.setRenderHint (QPainter::Antialiasing, true );
124- QPen pen (ink);
125- pen.setWidthF (qMax (1.0 , extent * 0.11 ));
126- pen.setCapStyle (Qt::RoundCap);
127- painter.setPen (pen);
128- painter.setBrush (Qt::NoBrush);
129- for (int ring = 1 ; ring <= 3 ; ++ring) {
130- const qreal radius = extent * 0.18 * static_cast <qreal>(ring);
131- painter.drawArc (
132- QRectF (origin.x () - radius, origin.y () - radius, radius * 2.0 , radius * 2.0 ), 5 * 16 ,
133- 80 * 16 );
134- }
135- painter.setPen (Qt::NoPen);
136- painter.setBrush (ink);
137- painter.drawEllipse (origin, extent * 0.09 , extent * 0.09 );
138- painter.end ();
139- return image;
140- }
141-
142- // Theme lookup misses entirely under Flatpak, Snap and AppImage, so IconPixmap
143- // always ships alongside IconName instead of only when the theme fails.
144- SniIconPixmapList buildIconPixmaps () {
145- const QIcon themed = QIcon::fromTheme (QLatin1String (kIconName ));
146- SniIconPixmapList pixmaps;
147- for (const int size : {22 , 48 }) {
148- QImage image;
149- if (!themed.isNull ()) { image = themed.pixmap (QSize (size, size)).toImage (); }
150- if (image.isNull ()) { image = renderFallbackIcon (size); }
151- if (image.isNull ()) { continue ; }
152- pixmaps.append (toSniPixmap (image));
153- }
154- return pixmaps;
155- }
156-
15780} // namespace
15881
15982// Returning the const reference parameter is the signature QtDBus REQUIRES of a
@@ -258,7 +181,7 @@ class StatusNotifierItemAdaptor final : public QDBusAbstractAdaptor {
258181 : QDBusAbstractAdaptor(host), owner_(owner) {}
259182
260183 QString category () const { return QStringLiteral (" ApplicationStatus" ); }
261- QString id () const { return QLatin1String (kIconName ); }
184+ QString id () const { return QLatin1String (kSniIconName ); }
262185 QString title () const { return QStringLiteral (" Dish" ); }
263186 // Pinned Active: a Passive item may be hidden by the host, and a hidden
264187 // item is a running Dish the user can neither reach nor quit.
@@ -350,7 +273,7 @@ StatusNotifierTrayIcon::~StatusNotifierTrayIcon() { teardown(); }
350273
351274bool StatusNotifierTrayIcon::isAvailable () const { return available_; }
352275
353- QString StatusNotifierTrayIcon::iconName () const { return QLatin1String ( kIconName ); }
276+ QString StatusNotifierTrayIcon::iconName () const { return sniIconName (themeHasIcon_ ); }
354277
355278SniIconPixmapList StatusNotifierTrayIcon::iconPixmap () const { return iconPixmap_; }
356279
@@ -360,7 +283,8 @@ uint StatusNotifierTrayIcon::menuRevision() const { return 1; }
360283
361284SniToolTip StatusNotifierTrayIcon::toolTip () const {
362285 SniToolTip tip;
363- tip.iconName = QLatin1String (kIconName );
286+ tip.iconName = sniIconName (themeHasIcon_);
287+ tip.iconPixmap = iconPixmap_;
364288 tip.title = QStringLiteral (" Dish" );
365289 switch (presentation_.activity ) {
366290 case reducer::TrayActivity::Idle:
@@ -547,8 +471,11 @@ void StatusNotifierTrayIcon::refreshAvailability() {
547471 emit availabilityChanged (available_);
548472}
549473
474+ // Theme lookup misses entirely under Flatpak, Snap and AppImage, so IconPixmap
475+ // always ships alongside IconName instead of only when the theme fails.
550476void StatusNotifierTrayIcon::updateIcon () {
551- SniIconPixmapList pixmaps = buildIconPixmaps ();
477+ themeHasIcon_ = QIcon::hasThemeIcon (QLatin1String (kSniIconName ));
478+ SniIconPixmapList pixmaps = sniTrayPixmaps ();
552479 if (pixmaps == iconPixmap_) { return ; }
553480 iconPixmap_ = pixmaps;
554481 if (exported_) { emitItemSignal (kNewIconSignal ); }
0 commit comments