diff --git a/client/images/images.qrc b/client/images/images.qrc
index 51574688d..c00cebd59 100644
--- a/client/images/images.qrc
+++ b/client/images/images.qrc
@@ -65,10 +65,11 @@
controls/text-cursor.svg
controls/trash.svg
controls/x-circle.svg
- tray/active.png
- tray/default.png
- tray/error.png
- tray/icon.svg
+ tray/off-black.svg
+ tray/off-light.svg
+ tray/on-black.svg
+ tray/on-white.svg
+ tray/error.svg
controls/monitor.svg
diff --git a/client/images/tray/active.png b/client/images/tray/active.png
deleted file mode 100644
index 7ceac4b4e..000000000
Binary files a/client/images/tray/active.png and /dev/null differ
diff --git a/client/images/tray/default.png b/client/images/tray/default.png
deleted file mode 100644
index 254ac14a7..000000000
Binary files a/client/images/tray/default.png and /dev/null differ
diff --git a/client/images/tray/error.png b/client/images/tray/error.png
deleted file mode 100644
index a24a32df9..000000000
Binary files a/client/images/tray/error.png and /dev/null differ
diff --git a/client/images/tray/error.svg b/client/images/tray/error.svg
new file mode 100644
index 000000000..ffa1e7dd4
--- /dev/null
+++ b/client/images/tray/error.svg
@@ -0,0 +1,3 @@
+
diff --git a/client/images/tray/icon.svg b/client/images/tray/icon.svg
deleted file mode 100644
index c96c97d98..000000000
--- a/client/images/tray/icon.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/client/images/tray/off-black.svg b/client/images/tray/off-black.svg
new file mode 100644
index 000000000..fe9cfbb33
--- /dev/null
+++ b/client/images/tray/off-black.svg
@@ -0,0 +1,10 @@
+
diff --git a/client/images/tray/off-light.svg b/client/images/tray/off-light.svg
new file mode 100644
index 000000000..7aa8194ef
--- /dev/null
+++ b/client/images/tray/off-light.svg
@@ -0,0 +1,3 @@
+
diff --git a/client/images/tray/on-black.svg b/client/images/tray/on-black.svg
new file mode 100644
index 000000000..f84defbe9
--- /dev/null
+++ b/client/images/tray/on-black.svg
@@ -0,0 +1,11 @@
+
diff --git a/client/images/tray/on-white.svg b/client/images/tray/on-white.svg
new file mode 100644
index 000000000..79d876650
--- /dev/null
+++ b/client/images/tray/on-white.svg
@@ -0,0 +1,11 @@
+
diff --git a/client/platforms/linux/linuxtrayiconbackend.cpp b/client/platforms/linux/linuxtrayiconbackend.cpp
index 7bf326d02..ec9e3b104 100644
--- a/client/platforms/linux/linuxtrayiconbackend.cpp
+++ b/client/platforms/linux/linuxtrayiconbackend.cpp
@@ -32,9 +32,7 @@ void LinuxTrayIconBackend::show()
void LinuxTrayIconBackend::applyVisual(const TrayIconVisual &visual)
{
- const qreal opacity = TrayIconCommon::opacityForState(visual.connectionState);
- const QColor indicatorColor = TrayIconCommon::indicatorColorForState(visual.connectionState);
- const QIcon icon = buildTrayIcon(opacity, visual.darkTheme, indicatorColor);
+ const QIcon icon = buildTrayIcon(visual.connectionState, visual.darkTheme);
// Some tray implementations cache the first icon; clear before applying an update.
if (m_trayIcon.isVisible()) {
@@ -47,8 +45,7 @@ void LinuxTrayIconBackend::showMessage(const QString &title, const QString &mess
int timerMsec)
{
m_trayIcon.showMessage(title, message,
- buildTrayIcon(TrayIconCommon::kConnectedOpacity, visual.darkTheme,
- TrayIconCommon::indicatorColorForState(Vpn::ConnectionState::Connected)),
+ buildTrayIcon(Vpn::ConnectionState::Connected, visual.darkTheme),
timerMsec);
}
@@ -66,11 +63,11 @@ void LinuxTrayIconBackend::setActivatedHandler(std::function handler) override;
private:
- QIcon buildTrayIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor) const;
+ QIcon buildTrayIcon(Vpn::ConnectionState state, bool darkTheme) const;
QSystemTrayIcon m_trayIcon;
};
diff --git a/client/platforms/macos/macosstatusicon.h b/client/platforms/macos/macosstatusicon.h
index e67c3d98b..d77dda037 100644
--- a/client/platforms/macos/macosstatusicon.h
+++ b/client/platforms/macos/macosstatusicon.h
@@ -23,7 +23,6 @@ class MacOSStatusIcon final : public QObject {
public:
void setIcon(const QString& iconUrl);
void setIconFromData(const QByteArray& imageData);
- void setIndicatorColor(const QColor& indicatorColor);
void setMenu(QMenu* menu);
void rebuildNativeMenu();
void setToolTip(const QString& tooltip);
diff --git a/client/platforms/macos/macosstatusicon.mm b/client/platforms/macos/macosstatusicon.mm
index 0edb13b44..483db3c7a 100644
--- a/client/platforms/macos/macosstatusicon.mm
+++ b/client/platforms/macos/macosstatusicon.mm
@@ -29,21 +29,17 @@
@end
/**
- * Creates a NSStatusItem with that can hold an icon. Additionally a NSView is
- * set as a subview to the button item of the status item. The view serves as
- * an indicator that can be displayed in color eventhough the icon is set as a
- * template. In that way we give the system control over it’s effective
- * appearance.
+ * Creates a NSStatusItem that holds the tray icon. The icon is set as a
+ * template image, so the system controls its effective appearance for the
+ * current menu bar theme. The connection status is baked into the artwork, so
+ * no separate colored indicator is drawn.
*/
@interface MacOSStatusIconDelegate : NSObject
@property(assign) NSStatusItem* statusItem;
-@property(assign) NSView* statusIndicator;
@property(retain) NSMenu* nativeMenu;
@property(retain) NSMutableArray* menuActionTargets;
- (void)setIcon:(NSData*)imageData;
-- (void)setIndicator;
-- (void)setIndicatorColor:(NSColor*)color;
- (void)setToolTip:(NSString*)tooltip;
- (void)rebuildMenuFromQMenu:(QMenu*)menu;
@end
@@ -62,8 +58,6 @@
self.statusItem =
[[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
self.statusItem.visible = true;
- // Add the indicator as a subview
- [self setIndicator];
return self;
}
@@ -87,34 +81,6 @@
[image release];
}
-/**
- * Adds status indicator as a subview to the status item button.
- */
-- (void)setIndicator {
- float viewHeight = NSHeight([self.statusItem.button bounds]);
- float dotSize = viewHeight * 0.35;
- float dotOrigin = (viewHeight - dotSize) * 0.8;
-
- NSView* dot = [[NSView alloc] initWithFrame:NSMakeRect(dotOrigin, dotOrigin, dotSize, dotSize)];
- self.statusIndicator = dot;
- self.statusIndicator.wantsLayer = true;
- self.statusIndicator.layer.cornerRadius = dotSize * 0.5;
-
- [self.statusItem.button addSubview:self.statusIndicator];
- [dot release];
-}
-
-/**
- * Sets the color if the indicator.
- *
- * @param color The indicator background color.
- */
-- (void)setIndicatorColor:(NSColor*)color {
- if (self.statusIndicator) {
- self.statusIndicator.layer.backgroundColor = color.CGColor;
- }
-}
-
/**
* Sets the status bar menu to the status item.
*
@@ -217,21 +183,6 @@ void MacOSStatusIcon::setIconFromData(const QByteArray& imageData) {
[m_statusBarIcon setIcon:data];
}
-void MacOSStatusIcon::setIndicatorColor(const QColor& indicatorColor) {
- logger.debug() << "Set indicator color";
-
- if (!indicatorColor.isValid()) {
- [m_statusBarIcon setIndicatorColor:[NSColor clearColor]];
- return;
- }
-
- NSColor* color = [NSColor colorWithCalibratedRed:indicatorColor.red() / 255.0f
- green:indicatorColor.green() / 255.0f
- blue:indicatorColor.blue() / 255.0f
- alpha:indicatorColor.alpha() / 255.0f];
- [m_statusBarIcon setIndicatorColor:color];
-}
-
void MacOSStatusIcon::setMenu(QMenu* menu) {
m_qtMenu = menu;
rebuildNativeMenu();
diff --git a/client/platforms/macos/mactrayiconbackend.mm b/client/platforms/macos/mactrayiconbackend.mm
index 17d5b23d4..6a8e8663a 100644
--- a/client/platforms/macos/mactrayiconbackend.mm
+++ b/client/platforms/macos/mactrayiconbackend.mm
@@ -23,9 +23,7 @@ void MacTrayIconBackend::show()
void MacTrayIconBackend::applyVisual(const TrayIconVisual &visual)
{
- const qreal opacity = TrayIconCommon::opacityForState(visual.connectionState);
- m_statusIcon.setIconFromData(TrayIconCommon::buildTemplatePng(opacity));
- m_statusIcon.setIndicatorColor(TrayIconCommon::indicatorColorForState(visual.connectionState));
+ m_statusIcon.setIconFromData(TrayIconCommon::buildTemplatePng(visual.connectionState));
}
void MacTrayIconBackend::showMessage(const QString &title, const QString &message, const TrayIconVisual &visual, int timerMsec)
diff --git a/client/platforms/windows/wintrayicon.cpp b/client/platforms/windows/wintrayicon.cpp
index 1e1121aec..0562d7bb9 100644
--- a/client/platforms/windows/wintrayicon.cpp
+++ b/client/platforms/windows/wintrayicon.cpp
@@ -6,22 +6,19 @@
namespace WinTrayIcon
{
-QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor)
+QIcon buildIcon(Vpn::ConnectionState state, bool darkTheme)
{
- return TrayIconCommon::buildIcon(opacity, darkTheme, indicatorColor);
+ return TrayIconCommon::buildIcon(state, darkTheme);
}
void applyTo(QSystemTrayIcon &trayIcon, Vpn::ConnectionState state, bool darkTheme)
{
- const qreal opacity = TrayIconCommon::opacityForState(state);
- const QColor indicatorColor = TrayIconCommon::indicatorColorForState(state);
- trayIcon.setIcon(buildIcon(opacity, darkTheme, indicatorColor));
+ trayIcon.setIcon(buildIcon(state, darkTheme));
}
QIcon buildNotifyIcon(bool darkTheme)
{
- return buildIcon(TrayIconCommon::kConnectedOpacity, darkTheme,
- TrayIconCommon::indicatorColorForState(Vpn::ConnectionState::Connected));
+ return buildIcon(Vpn::ConnectionState::Connected, darkTheme);
}
void configure(QSystemTrayIcon &trayIcon, QMenu *menu, const QString &tooltip)
diff --git a/client/platforms/windows/wintrayicon.h b/client/platforms/windows/wintrayicon.h
index 5d734025c..39225149e 100644
--- a/client/platforms/windows/wintrayicon.h
+++ b/client/platforms/windows/wintrayicon.h
@@ -12,7 +12,7 @@ class QString;
namespace WinTrayIcon
{
-QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor);
+QIcon buildIcon(Vpn::ConnectionState state, bool darkTheme);
void applyTo(QSystemTrayIcon &trayIcon, Vpn::ConnectionState state, bool darkTheme);
QIcon buildNotifyIcon(bool darkTheme);
diff --git a/client/ui/utils/trayIconCommon.cpp b/client/ui/utils/trayIconCommon.cpp
index 91458a36c..2ab098855 100644
--- a/client/ui/utils/trayIconCommon.cpp
+++ b/client/ui/utils/trayIconCommon.cpp
@@ -7,93 +7,55 @@
namespace TrayIconCommon
{
-qreal opacityForState(Vpn::ConnectionState state)
+QString resourcePathForState(Vpn::ConnectionState state, bool darkTheme)
{
switch (state) {
+ case Vpn::ConnectionState::Error:
+ return QString::fromLatin1(kIconError);
case Vpn::ConnectionState::Connected:
- case Vpn::ConnectionState::Error: return kConnectedOpacity;
+ return QString::fromLatin1(darkTheme ? kIconOnWhite : kIconOnBlack);
case Vpn::ConnectionState::Disconnected:
case Vpn::ConnectionState::Preparing:
case Vpn::ConnectionState::Connecting:
case Vpn::ConnectionState::Disconnecting:
case Vpn::ConnectionState::Reconnecting:
case Vpn::ConnectionState::Unknown:
- default: return kDisconnectedOpacity;
+ default:
+ return QString::fromLatin1(darkTheme ? kIconOffLight : kIconOffBlack);
}
}
-QColor indicatorColorForState(Vpn::ConnectionState state)
-{
- switch (state) {
- case Vpn::ConnectionState::Connected: return QColor(52, 199, 89);
- case Vpn::ConnectionState::Error: return QColor(235, 87, 87);
- default: return QColor();
- }
-}
-
-QPixmap renderTemplate(const QString &resourcePath, qreal opacity, int size)
+QPixmap renderIcon(const QString &resourcePath, int size)
{
QSvgRenderer renderer(resourcePath);
QPixmap pixmap(size, size);
pixmap.fill(Qt::transparent);
if (!renderer.isValid()) {
- qWarning() << "Failed to load tray icon template:" << resourcePath;
+ qWarning() << "Failed to load tray icon:" << resourcePath;
return pixmap;
}
QPainter painter(&pixmap);
- painter.setOpacity(opacity);
renderer.render(&painter, QRectF(0, 0, size, size));
return pixmap;
}
-QPixmap colorizeTemplate(const QPixmap &mask, const QColor &foreground, int size)
+QPixmap buildPixmap(int size, Vpn::ConnectionState state, bool darkTheme)
{
- QPixmap result(size, size);
- result.fill(Qt::transparent);
-
- QPainter painter(&result);
- painter.fillRect(result.rect(), foreground);
- painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
- painter.drawPixmap(0, 0, mask);
- return result;
+ return renderIcon(resourcePathForState(state, darkTheme), size);
}
-void drawStatusIndicator(QPainter &painter, const QColor &color, int size)
-{
- const qreal dotSize = size * 0.35;
- const qreal dotOrigin = (size - dotSize) * 0.8;
-
- painter.setPen(Qt::NoPen);
- painter.setBrush(color);
- painter.drawEllipse(QRectF(dotOrigin, dotOrigin, dotSize, dotSize));
-}
-
-QPixmap buildPixmap(int size, qreal opacity, bool darkTheme, const QColor &indicatorColor)
-{
- const QPixmap mask = renderTemplate(QString::fromLatin1(kTrayTemplateIconPath), opacity, size);
- const QColor foreground = darkTheme ? Qt::white : Qt::black;
- QPixmap pixmap = colorizeTemplate(mask, foreground, size);
-
- if (indicatorColor.isValid()) {
- QPainter painter(&pixmap);
- drawStatusIndicator(painter, indicatorColor, size);
- }
-
- return pixmap;
-}
-
-QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor)
+QIcon buildIcon(Vpn::ConnectionState state, bool darkTheme)
{
QIcon icon;
- icon.addPixmap(buildPixmap(kDefaultTrayIconSize, opacity, darkTheme, indicatorColor));
+ icon.addPixmap(buildPixmap(kDefaultTrayIconSize, state, darkTheme));
return icon;
}
-QByteArray buildTemplatePng(qreal opacity)
+QByteArray buildTemplatePng(Vpn::ConnectionState state)
{
- const QPixmap pixmap = renderTemplate(QString::fromLatin1(kTrayTemplateIconPath), opacity, kDefaultTrayIconSize);
+ const QPixmap pixmap = renderIcon(resourcePathForState(state, /*darkTheme*/ true), kDefaultTrayIconSize);
QByteArray bytes;
QBuffer buffer(&bytes);
diff --git a/client/ui/utils/trayIconCommon.h b/client/ui/utils/trayIconCommon.h
index a47d24a7d..27657d8b8 100644
--- a/client/ui/utils/trayIconCommon.h
+++ b/client/ui/utils/trayIconCommon.h
@@ -2,31 +2,29 @@
#define TRAYICONCOMMON_H
#include
-#include
#include
-#include
#include
+#include
#include "core/protocols/vpnProtocol.h"
namespace TrayIconCommon
{
constexpr int kDefaultTrayIconSize = 128;
- constexpr char kTrayTemplateIconPath[] = ":/images/tray/icon.svg";
- constexpr qreal kDisconnectedOpacity = 0.5;
- constexpr qreal kConnectedOpacity = 1.0;
+ constexpr char kIconOffBlack[] = ":/images/tray/off-black.svg";
+ constexpr char kIconOffLight[] = ":/images/tray/off-light.svg";
+ constexpr char kIconOnBlack[] = ":/images/tray/on-black.svg";
+ constexpr char kIconOnWhite[] = ":/images/tray/on-white.svg";
+ constexpr char kIconError[] = ":/images/tray/error.svg";
- qreal opacityForState(Vpn::ConnectionState state);
- QColor indicatorColorForState(Vpn::ConnectionState state);
+ QString resourcePathForState(Vpn::ConnectionState state, bool darkTheme);
- QPixmap renderTemplate(const QString &resourcePath, qreal opacity, int size);
- QPixmap colorizeTemplate(const QPixmap &mask, const QColor &foreground, int size);
- void drawStatusIndicator(QPainter &painter, const QColor &color, int size);
+ QPixmap renderIcon(const QString &resourcePath, int size);
- QPixmap buildPixmap(int size, qreal opacity, bool darkTheme, const QColor &indicatorColor);
- QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor);
- QByteArray buildTemplatePng(qreal opacity);
+ QPixmap buildPixmap(int size, Vpn::ConnectionState state, bool darkTheme);
+ QIcon buildIcon(Vpn::ConnectionState state, bool darkTheme);
+ QByteArray buildTemplatePng(Vpn::ConnectionState state);
} // namespace TrayIconCommon