From 2ff9dac04be874b6d34ad4c7cc951d5010e66172 Mon Sep 17 00:00:00 2001 From: Jinquan Shi Date: Mon, 23 Mar 2026 17:28:36 +0800 Subject: [PATCH 1/2] feat: use PDF vector icon for crisp menubar rendering - Use PDF icon via systray.SetIcon for sharp 4K display support - Fall back to PNG template icons if PDF unavailable - Add thin space between icon and text in tray display - Add icon_test.go with PDF/PNG validation tests Co-Authored-By: Claude Opus 4.6 --- internal/menubar/companion_darwin.go | 8 +++-- internal/menubar/icon.go | 7 ++++ internal/menubar/icon_template.pdf | Bin 0 -> 2596 bytes internal/menubar/icon_template.png | Bin 195 -> 978 bytes internal/menubar/icon_template@2x.png | Bin 353 -> 683 bytes internal/menubar/icon_test.go | 44 ++++++++++++++++++++++++++ internal/menubar/tray_display.go | 2 +- internal/menubar/tray_display_test.go | 8 ++--- 8 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 internal/menubar/icon_template.pdf create mode 100644 internal/menubar/icon_test.go diff --git a/internal/menubar/companion_darwin.go b/internal/menubar/companion_darwin.go index 140ebde..a76727b 100644 --- a/internal/menubar/companion_darwin.go +++ b/internal/menubar/companion_darwin.go @@ -64,9 +64,13 @@ func (c *trayController) onReady() { logger.Info("Systray initialized, setting icon") templateIcon, regularIcon := trayIcons() - if len(templateIcon) > 0 && len(regularIcon) > 0 { + pdfIcon := trayIconPDF() + if len(pdfIcon) > 0 { + systray.SetIcon(pdfIcon) + logger.Debug("Tray icon set from PDF") + } else if len(templateIcon) > 0 && len(regularIcon) > 0 { systray.SetTemplateIcon(templateIcon, regularIcon) - logger.Debug("Tray icon set successfully") + logger.Debug("Tray icon set from PNG") } systray.SetTooltip("onWatch menubar companion") diff --git a/internal/menubar/icon.go b/internal/menubar/icon.go index fe9b727..f2fb2af 100644 --- a/internal/menubar/icon.go +++ b/internal/menubar/icon.go @@ -8,6 +8,13 @@ var IconTemplate []byte //go:embed icon_template@2x.png var IconTemplate2x []byte +//go:embed icon_template.pdf +var IconPDF []byte + func trayIcons() ([]byte, []byte) { return IconTemplate, IconTemplate2x } + +func trayIconPDF() []byte { + return IconPDF +} diff --git a/internal/menubar/icon_template.pdf b/internal/menubar/icon_template.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0e1042a81b471b6ab4bdb767b022a8771eece8ac GIT binary patch literal 2596 zcmd^BYfuwc6c+JOR#X&~@yWH7Q548#LmnXGgYYmy1QLg#pw%^5LL|wC%|-*Z3QBcQ zP|(s^(HX533$-d^ody*J#G%z0Mtnayw#90JRvN5GEv5F}O@IV5q>Ac;AgD6oAdM%JN+U@Vr3PYqG5`)(5Om`uGPFubvCs+@7e=NmEa1uX zuyj(#J#rr5;|k$TLs zU%u?@n0nm%``_pN?U_GIKI*{PnR)r)I4B=lnV4Fk{;@l3%(z=tlnKQ&GVYC96Z;>5xn!M)&fr zcfB}OdVYTGl~IeIzkfy*VLV@Kt$(-kBTZHsmXj4;RC7J6PSOk%Wwk}j&Ya8(QMkG1 z;s(Q>-qEG)A{ip7W3hd7mALT4&I}j2DdnUob5QjW)L;B~vtDbUO9uQkY952P4BI(C+_1NR~0bAs-2-G6Ec4gV{ScAqh8Y3>E5)*v57*oC&=4oxXUk{=m}axqoyPc}=~rrPX#l)90~A^xdU0 zzaBTsLF(yFYtedMl`x0k^>G>6SZEv|S|YLzXjVV{oh&s_>5wwpEupK%#0O~axVru) zxsy|BEy)QE4kr@89ur6l;lTohjCGtW@cqs7?@j0?r41|$Z33vzE~grj_JK+}Hm`ud z(R!Bw0atL+prJq-4$!&D{kUvi$BPe&YvL{@PPmkCEVZ<9%k*gzHcy&8y!n#sQ0cny zhy1VI3e0ZXR@|`HFRrmRxkc!^Y1M+pmp6}2lpOAr`H~+$8L~S*A~`FlZbt)|oE+K`)cLu5 zM8W#}_n!W_(dY;E`hLmwH`m*>Cr^82#t&{dB^U8T-Z=XO%2^wyUh; zmb@@$icfZLQ=XqjbMC~|p;xPhgYD(*U3t|b+BTdo zpE2~4v$eLG6Va`Plh}>p!IzR#6}jbyts_F4a{rlzv(o0{8$BMjtg3ReDfoy@1HFQj zRGU@sSe;{9ry-2$^gw4(wlGvW2HVBQ(7|ROKqM3jgdlx%KgNfOjs`FcU}6}?72}5r z;f@%D3HWf^xMDb80QoftBk))3_!8ok7`RvnsW`}2B7#ETiV;MplO4;DS{=nWzT}kJ q913L&sjHxA_&LUr9lps7=``TV$8q1pk_^igh#!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDB+SC;hE;^%b*2hb1*Qr zXELw=S&Tp|1;h*t%nKM9n1M7SNNfQUTvlKKGlC6LXcAiZ38-v#W=KRygs+cPa(=E} zVoH8es$NBI0Z0LZO@$SZnVVXYs8ErclUHn2VXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO| zi&7QL^bGV2l1AfjnEKjFOT9D}DX)@^Za$W4-*MbbUihOG|wN zBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o3raHc^AtelCMM;Vme?vOfh>Xph&xj& zG7&cA6+^uR^q@XSM&D4+Kp$>4P^%3{)G8peA~h$%B{MfQuNY{Dow1P(SUH9S!a^jC zk+?J>NkBE)=!2Y(%G)<%F%I2`!5~1C};C)zC9n( zpY7!|uD5$~wrkOZt68dZ{oJK`+nUmk&8RjHVZQw~%;vl>gME`_(W-Ac0&NSgy#6Yl zxcaKlqNoWnMe@s7%XZJT=v(Y^d)xe`j}E{E(~ zewovayWo)8r>4B^+UtkdJB95HQa{oAiqFTVf&wcVm` zq6+6321{d|>E2H&`4%7D>$vpq$IqGE586VjrTN+?rOuoocI104>-iqT@TYEpDjKJQ zZoS>6R&jpzS+_G&SK80?X<5)=`0T_&f8MR~`j`H%F$$mb?PBt-=>oNz_E(;}f8foF U*e#io+d;|S)78&qol`;+0Qz54@&Et; delta 167 zcmV;Y09gOh2g3o7B!7xYL_t(|+GAkA1O`An8;Gw1@qZ}34iz(Czyo-oivAP8v!QA+ zG#|#I_%sxwiyuZe1eeVXP>jnZa6cnU$RN1}*?_}PIb^j4*lY(Wlz`GO1CYfqTyY(T zA3+*CpjZM&7=iSn1Xu$S_CN|F4>URCfTi33ioHN_AW|HS6d)%gsw8EKGZWd_836hR VqTw>Wn$iFO002ovPDHLkV1kmmKl}gy diff --git a/internal/menubar/icon_template@2x.png b/internal/menubar/icon_template@2x.png index 236561e0fd58a85c8045ff266ea58aa3d5f25794..6b9aa60d1d0033a5387c640742a481703ccdd09b 100644 GIT binary patch delta 660 zcmV;F0&D%@0;>g(BYyw^b5ch_0Itp)=>Px#IAvH#W=%~1DgXcg2mk?xX#fNO00031 z000^Q000000-yo_1ONa40RR91AfN*P1ONa40RR91AOHXW0FO>U$p8QXAxT6*R9Fek zmrbrgF&Kt>PcRUP5px^B$O24R29{t;EWp@=ITAAxwjd;iy?^Ja`^mZ0(u$jNzeLK> z?|q;Cp7u+pp#tJ^xv1G}rsngx+H5xJa5$*b>0~mi)v9VV8mirHt8TZedcB^iR4M_g zX%zsT#csFLgTX+T%Vj`=KGY?L+*jcRxL&V%JRa*}u^43Pf+H6Vw0z+N*zfnc*=)XT zY{Q_1rYjx*R)4FNuGi}yGZz>%(YE6k0F*K2%jHrp7K>n5wC$d_129gp-7c+>R)&;# zWaq>kfXU(#C=?1hNfPIO&j83F*QJSc>75V75EA0S)+m{XS^*VlV^66$*2?}i-oxSWB>+h-0|9XTmo@TzAB{#@bvm6O07O{FGQLs* zA>ZvG@)^r>;|;w$2r07=(gOk!t7Yn!N~H$?cDPT6YsbVpNn4$7ywhzm=Gk6~9sjh| zw|ymM5`O|K=2FV|OBvH3NB#RzkM|m2uhYH`@~;e uPQNfo$zMju^}N+;nd^DK-w(c?e*-5sQOfyBTMbtL0000pjaBYy!XNkl2rc0{u>^`Tum}SS zFd*>uW}Y|b@#CU%3o~Ehz`iH23lzoqRuLVciGi4j70mdi(WfeIY%KyWmSBtpW7;di zCD9XxA$-IjM#&X_5aR{mBO_v-YENRiQG8=U?C76!#9x48;(rlZbMCY^fV&*dJ<%sj zYl?vtT0g1g+wBUuZ5Rd&#;8Dc>{3(*+;-@r941@_4Eh!r>x--H3b#aZS$Rwx4TSo- zid7YJ84GM1;E3;LS2L>GQD8HWBK}>5fmvE@p&F!!uh8C|YFra`QwitBN84NBngF%K zKph$5tC;cz#6Xuod=rYNp?Dz@FU8`AQ5MIs_=O~kE1CGEG>dC_77vpwo@QA*PXF>e Ze*@VcowI2XEs_8L002ovPDHLkV1lBTkevVk diff --git a/internal/menubar/icon_test.go b/internal/menubar/icon_test.go new file mode 100644 index 0000000..30d43ae --- /dev/null +++ b/internal/menubar/icon_test.go @@ -0,0 +1,44 @@ +package menubar + +import ( + "testing" +) + +func TestTrayIconsPNGNotEmpty(t *testing.T) { + template, retina := trayIcons() + if len(template) == 0 { + t.Fatal("trayIcons() template is empty") + } + if len(retina) == 0 { + t.Fatal("trayIcons() retina is empty") + } +} + +func TestTrayIconPDFNotEmpty(t *testing.T) { + pdf := trayIconPDF() + if len(pdf) == 0 { + t.Fatal("trayIconPDF() is empty") + } +} + +func TestTrayIconPDFStartsWithPDFHeader(t *testing.T) { + pdf := trayIconPDF() + if len(pdf) < 4 { + t.Fatal("trayIconPDF() too short to be valid") + } + // PDF files start with "%PDF-" + if string(pdf[:5]) != "%PDF-" { + t.Fatalf("trayIconPDF() does not start with %%PDF-, got %q", string(pdf[:5])) + } +} + +func TestTrayIconsPNGLen(t *testing.T) { + template, retina := trayIcons() + // Verify reasonable PNG header + if string(template[:8]) != "\x89PNG\r\n\x1a\n" { + t.Fatal("template icon does not have PNG header") + } + if string(retina[:8]) != "\x89PNG\r\n\x1a\n" { + t.Fatal("retina icon does not have PNG header") + } +} diff --git a/internal/menubar/tray_display.go b/internal/menubar/tray_display.go index a5c3d94..f9ecde8 100644 --- a/internal/menubar/tray_display.go +++ b/internal/menubar/tray_display.go @@ -75,7 +75,7 @@ func joinTrayParts(parts []string) string { if len(parts) == 0 { return "" } - out := parts[0] + out := "\u2009" + parts[0] for i := 1; i < len(parts); i++ { out += " │ " + parts[i] } diff --git a/internal/menubar/tray_display_test.go b/internal/menubar/tray_display_test.go index 8416604..833563b 100644 --- a/internal/menubar/tray_display_test.go +++ b/internal/menubar/tray_display_test.go @@ -41,8 +41,8 @@ func TestTrayTitleProviderSpecific(t *testing.T) { }, } - if got := TrayTitle(snapshot, settings); got != "84%" { - t.Fatalf("TrayTitle(multi_provider) = %q, want %q", got, "84%") + if got := TrayTitle(snapshot, settings); got != "\u200984%" { + t.Fatalf("TrayTitle(multi_provider) = %q, want %q", got, "\u200984%") } } @@ -73,8 +73,8 @@ func TestTrayTitleCriticalCountAndIconOnly(t *testing.T) { {ProviderID: "copilot"}, }, } - if got := TrayTitle(snapshot, settings); got != "84% │ 12%" { - t.Fatalf("TrayTitle(multi_provider multiple) = %q, want %q", got, "84% │ 12%") + if got := TrayTitle(snapshot, settings); got != "\u200984% │ 12%" { + t.Fatalf("TrayTitle(multi_provider multiple) = %q, want %q", got, "\u200984% │ 12%") } settings.StatusDisplay = StatusDisplay{Mode: StatusDisplayIconOnly} From e46c0177497ef521cafbfa541e92665b368ab999 Mon Sep 17 00:00:00 2001 From: Jinquan Shi Date: Sat, 28 Mar 2026 16:00:19 +0800 Subject: [PATCH 2/2] Revert PDF icon, use PNG for macOS menu bar macOS systray works better with PNG template/retina icons than PDF. Remove PDF icon support and associated tests. Co-Authored-By: Claude Opus 4.6 --- internal/menubar/companion_darwin.go | 6 +--- internal/menubar/icon.go | 7 ----- internal/menubar/icon_template.pdf | Bin 2596 -> 0 bytes internal/menubar/icon_template.png | Bin 978 -> 8667 bytes internal/menubar/icon_template@2x.png | Bin 683 -> 20055 bytes internal/menubar/icon_test.go | 38 ++++++++++++++------------ 6 files changed, 21 insertions(+), 30 deletions(-) delete mode 100644 internal/menubar/icon_template.pdf diff --git a/internal/menubar/companion_darwin.go b/internal/menubar/companion_darwin.go index a76727b..467c44d 100644 --- a/internal/menubar/companion_darwin.go +++ b/internal/menubar/companion_darwin.go @@ -64,11 +64,7 @@ func (c *trayController) onReady() { logger.Info("Systray initialized, setting icon") templateIcon, regularIcon := trayIcons() - pdfIcon := trayIconPDF() - if len(pdfIcon) > 0 { - systray.SetIcon(pdfIcon) - logger.Debug("Tray icon set from PDF") - } else if len(templateIcon) > 0 && len(regularIcon) > 0 { + if len(templateIcon) > 0 && len(regularIcon) > 0 { systray.SetTemplateIcon(templateIcon, regularIcon) logger.Debug("Tray icon set from PNG") } diff --git a/internal/menubar/icon.go b/internal/menubar/icon.go index f2fb2af..fe9b727 100644 --- a/internal/menubar/icon.go +++ b/internal/menubar/icon.go @@ -8,13 +8,6 @@ var IconTemplate []byte //go:embed icon_template@2x.png var IconTemplate2x []byte -//go:embed icon_template.pdf -var IconPDF []byte - func trayIcons() ([]byte, []byte) { return IconTemplate, IconTemplate2x } - -func trayIconPDF() []byte { - return IconPDF -} diff --git a/internal/menubar/icon_template.pdf b/internal/menubar/icon_template.pdf deleted file mode 100644 index 0e1042a81b471b6ab4bdb767b022a8771eece8ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2596 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 V#BRxy+zv`4p00kZF6*2UngBsI4U+%> diff --git a/internal/menubar/icon_template@2x.png b/internal/menubar/icon_template@2x.png index 6b9aa60d1d0033a5387c640742a481703ccdd09b..4c33815f19367b6d20171c7548f917004eb9774f 100644 GIT binary patch literal 20055 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 GygvZ&V6{{L literal 683 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}7O4@QX}-P; zT0k}j17mw80}DtA5K93u0|V0nCb)>g0%imoB-!uha1y9Q(bL5-B!ctobl-K3h7xVn z{ssb_g2mDYPB8gIvQ10y);Vya#Zt&vXq$pc+ur9Zf1liW^-|aD;{7hCF21jw|8L$m z@8t`b9u@6eaWiMxv(Gzk<(R!Huvl^VWs1@2tE;k1q*mR{Tb;Lkb=BT^t3tFGS7nMa z%sZO5{c`g`hv}zN9h&W~sJ7n;f5^HcZhe)F-0P%`5-G2ml*M_s)I4Ol@&5a+n>qV( za}FWI+7$V4t=i<1u@3*Xc+W2oI}m>S+NpnL_YOb&pvvH>$IMvpce?4PTKQhLs8XxB z3Jfk0$Bp&{F)7}EtN2Osbn#=}y*3=0n*}a0GYPIveKp-{DLX^i4*&M-<43GLqvz)D zxtweC>}Fh-?EfuSx7Vts2{CCu3p(|~Tk^8P~8tK|Ae@-A|)a?}Q!o zl^N{*TCpj;D&=um$1cQBWIu^<;_HPX3`*CNfAT)OCcIHSWn0*N^;bzs0%thYmc8Ea z%6QZK{k5jT9A48jejkaC_1kaYc{1MZ#MeDnvu3`o+<%{c-@JNeb@RYeKfR*EL5arG L)z4*}Q$iB}Du^AC diff --git a/internal/menubar/icon_test.go b/internal/menubar/icon_test.go index 30d43ae..df30baf 100644 --- a/internal/menubar/icon_test.go +++ b/internal/menubar/icon_test.go @@ -1,9 +1,29 @@ package menubar import ( + "bytes" + "image/png" "testing" ) +func TestTrayIconsDimensions(t *testing.T) { + template, retina := trayIcons() + + checkDim := func(data []byte, name string, expected int) { + img, err := png.Decode(bytes.NewReader(data)) + if err != nil { + t.Fatalf("failed to decode %s: %v", name, err) + } + bounds := img.Bounds() + if bounds.Dx() != expected || bounds.Dy() != expected { + t.Errorf("%s dimensions expected %dx%d, got %dx%d", name, expected, expected, bounds.Dx(), bounds.Dy()) + } + } + + checkDim(template, "template", 256) + checkDim(retina, "retina", 512) +} + func TestTrayIconsPNGNotEmpty(t *testing.T) { template, retina := trayIcons() if len(template) == 0 { @@ -14,24 +34,6 @@ func TestTrayIconsPNGNotEmpty(t *testing.T) { } } -func TestTrayIconPDFNotEmpty(t *testing.T) { - pdf := trayIconPDF() - if len(pdf) == 0 { - t.Fatal("trayIconPDF() is empty") - } -} - -func TestTrayIconPDFStartsWithPDFHeader(t *testing.T) { - pdf := trayIconPDF() - if len(pdf) < 4 { - t.Fatal("trayIconPDF() too short to be valid") - } - // PDF files start with "%PDF-" - if string(pdf[:5]) != "%PDF-" { - t.Fatalf("trayIconPDF() does not start with %%PDF-, got %q", string(pdf[:5])) - } -} - func TestTrayIconsPNGLen(t *testing.T) { template, retina := trayIcons() // Verify reasonable PNG header