fix(desktop): taskbar badge transparent circle + larger size

The Windows overlay badge rendered as a black square because GDI drawing
functions do not write the alpha channel — all pixels stay at A=0, causing
Windows to fall back to the opaque monochrome mask and draw corner pixels
as solid black.

Fix: after all GDI calls, iterate the pixel buffer and set alpha=0xFF for
every non-zero pixel; corner pixels (zero) retain A=0 and composite as
transparent, giving a proper circular badge.

Also increased bitmap size 16→20 and font height 11→14 for better
legibility, especially for two-digit mention counts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-14 13:19:20 -04:00
parent 0306842284
commit 524fa61c01
+15 -2
View File
@@ -162,7 +162,7 @@ fn set_badge_count(count: u32, window: tauri::Window) -> Result<(), String> {
let mut label_wide: Vec<u16> = label.encode_utf16().chain(std::iter::once(0)).collect();
unsafe {
let size = 16i32;
let size = 20i32;
let hdc_screen = windows::Win32::Graphics::Gdi::GetDC(None);
let hdc = CreateCompatibleDC(Some(hdc_screen));
@@ -191,7 +191,7 @@ fn set_badge_count(count: u32, window: tauri::Window) -> Result<(), String> {
let _ = Ellipse(hdc, 0, 0, size, size);
let hfont = CreateFontW(
11,
14,
0,
0,
0,
@@ -226,6 +226,19 @@ fn set_badge_count(count: u32, window: tauri::Window) -> Result<(), String> {
let _ = DeleteObject(hpen.into());
let _ = DeleteObject(hfont.into());
// GDI drawing leaves the alpha channel at 0 for all pixels.
// Set alpha=255 for every painted pixel so Windows uses per-pixel
// alpha compositing instead of falling back to the opaque mask,
// which would render unpainted corner pixels as a black square.
let pixel_count = (size * size) as usize;
let pixels =
std::slice::from_raw_parts_mut(bits as *mut u32, pixel_count);
for pixel in pixels.iter_mut() {
if *pixel != 0 {
*pixel |= 0xFF00_0000u32;
}
}
let hbm_mask = CreateBitmap(size, size, 1, 1, None);
if hbm_mask.0 as usize == 0 {
let _ = DeleteObject(hbm_color.into());