From 06dac23ffa06f260c4644438f7f8f5750f1f1196 Mon Sep 17 00:00:00 2001 From: Jordan Moore Date: Wed, 27 May 2026 21:15:02 -0500 Subject: [PATCH 1/2] Fix macOS menu bar tray icon rendering at correct size. Tag the 32x32 PNG with scaleFactor 2.0 on darwin so it displays at 16pt instead of appearing roughly twice as large as other menu bar icons. Co-authored-by: Cursor --- main.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/main.js b/main.js index cd41b81..bc6f8bf 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,4 @@ -const { app, BrowserWindow, Tray, Menu } = require("electron"); +const { app, BrowserWindow, Tray, Menu, nativeImage } = require("electron"); if (require('electron-squirrel-startup')) app.quit(); const path = require("path"); const WebSocket = require("ws"); @@ -115,7 +115,26 @@ function createWindow() { // Function to create the system tray function createTray() { - tray = new Tray(path.join(__dirname, "icons", "png", "32x32.png")); + // On macOS, the menu bar icon must be tagged as @2x (scaleFactor: 2.0) so that + // the 32x32 px image renders at 16x16 points — matching the height of other + // system tray icons. Without the scale factor, macOS treats it as a 32-point + // image and it appears roughly twice as large as every other menu bar icon. + let trayIcon; + if (process.platform === "darwin") { + const rawImage = nativeImage.createFromPath( + path.join(__dirname, "icons", "png", "32x32.png") + ); + trayIcon = nativeImage.createFromBuffer(rawImage.toPNG(), { + scaleFactor: 2.0, + }); + // Do not call setTemplateImage — icons/png/32x32.png is full-color (cannon + // on a light background), not a monochrome template. Template mode strips + // color and tints opaque pixels, which makes the branded icon disappear or + // look like a flat blob in the menu bar. + } else { + trayIcon = path.join(__dirname, "icons", "png", "32x32.png"); + } + tray = new Tray(trayIcon); const contextMenu = Menu.buildFromTemplate([ { label: "Show GPG Bridge UI", From 60331e84f941a90e552b391876059035d62388a5 Mon Sep 17 00:00:00 2001 From: Jordan Moore Date: Thu, 28 May 2026 09:38:20 -0500 Subject: [PATCH 2/2] switched to 32x32@2x.png and a direct path to Tray on macOS --- icons/png/32x32@2x.png | Bin 0 -> 5030 bytes main.js | 28 +++++++--------------------- 2 files changed, 7 insertions(+), 21 deletions(-) create mode 100644 icons/png/32x32@2x.png diff --git a/icons/png/32x32@2x.png b/icons/png/32x32@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c0ace13563da8ae5ebcf69a53b4812052a1f6180 GIT binary patch literal 5030 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 literal 0 HcmV?d00001 diff --git a/main.js b/main.js index bc6f8bf..673096a 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,4 @@ -const { app, BrowserWindow, Tray, Menu, nativeImage } = require("electron"); +const { app, BrowserWindow, Tray, Menu } = require("electron"); if (require('electron-squirrel-startup')) app.quit(); const path = require("path"); const WebSocket = require("ws"); @@ -115,26 +115,12 @@ function createWindow() { // Function to create the system tray function createTray() { - // On macOS, the menu bar icon must be tagged as @2x (scaleFactor: 2.0) so that - // the 32x32 px image renders at 16x16 points — matching the height of other - // system tray icons. Without the scale factor, macOS treats it as a 32-point - // image and it appears roughly twice as large as every other menu bar icon. - let trayIcon; - if (process.platform === "darwin") { - const rawImage = nativeImage.createFromPath( - path.join(__dirname, "icons", "png", "32x32.png") - ); - trayIcon = nativeImage.createFromBuffer(rawImage.toPNG(), { - scaleFactor: 2.0, - }); - // Do not call setTemplateImage — icons/png/32x32.png is full-color (cannon - // on a light background), not a monochrome template. Template mode strips - // color and tints opaque pixels, which makes the branded icon disappear or - // look like a flat blob in the menu bar. - } else { - trayIcon = path.join(__dirname, "icons", "png", "32x32.png"); - } - tray = new Tray(trayIcon); + // On macOS, use 32x32@2x.png so Electron treats the 32px asset as @2x (16pt). + // Without the @2x filename, macOS renders it at 32pt and it looks oversized. + // Do not call setTemplateImage — the PNG is full-color, not a menu-bar template. + const trayIconFile = + process.platform === "darwin" ? "32x32@2x.png" : "32x32.png"; + tray = new Tray(path.join(__dirname, "icons", "png", trayIconFile)); const contextMenu = Menu.buildFromTemplate([ { label: "Show GPG Bridge UI",