From bed309bb99249120f89f58ce789ff6d3f9a7d210 Mon Sep 17 00:00:00 2001 From: RubenKelevra Date: Sun, 15 Feb 2026 07:48:44 +0100 Subject: [PATCH] tray: use available status menu icons for current scale --- src/tray.js | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/tray.js b/src/tray.js index 11a566bd4..b3cb4066e 100644 --- a/src/tray.js +++ b/src/tray.js @@ -1,4 +1,4 @@ -const { Menu, Tray, shell, app, ipcMain, nativeTheme } = require('electron') +const { Menu, Tray, shell, app, ipcMain, nativeTheme, screen } = require('electron') const i18n = require('i18next') const path = require('path') const os = require('os') @@ -30,6 +30,42 @@ function buildCheckbox (key, label) { } } +const STATUS_ICON_SCALES = [1, 1.5, 2, 2.5, 3, 4, 5] + +function asScaleSuffix (value) { + return `${Number.isInteger(value) ? value.toFixed(0) : value}x` +} + +function getDisplayScaleFactor () { + const scaleFactor = screen.getPrimaryDisplay()?.scaleFactor + if (typeof scaleFactor === 'number' && Number.isFinite(scaleFactor) && scaleFactor > 0) { + return scaleFactor + } + return 1 +} + +function getStatusMenuIconPath (color) { + const statusIconDir = path.resolve(path.join(__dirname, '../assets/icons/status')) + const plainIconPath = path.join(statusIconDir, `${color}.png`) + if (fs.existsSync(plainIconPath)) { + return plainIconPath + } + + const scaleFactor = getDisplayScaleFactor() + const scalesByDistance = [...STATUS_ICON_SCALES].sort((a, b) => { + return Math.abs(a - scaleFactor) - Math.abs(b - scaleFactor) + }) + + for (const scale of scalesByDistance) { + const scaledIconPath = path.join(statusIconDir, `${color}@${asScaleSuffix(scale)}.png`) + if (fs.existsSync(scaledIconPath)) { + return scaledIconPath + } + } + + return path.join(statusIconDir, `${color}@1x.png`) +} + // Notes on this: we are only supporting accelerators on macOS for now because // they natively work as soon as the menu opens. They don't work like that on Windows // or other OSes and must be registered globally. They still collide with global @@ -67,7 +103,7 @@ async function buildMenu () { label: i18n.t(status), visible: false, enabled: false, - icon: path.resolve(path.join(__dirname, `../assets/icons/status/${color}.png`)) + icon: getStatusMenuIconPath(color) })), // @ts-ignore {