From 524fa61c01e7898c82fe6e5c716b84213240f503 Mon Sep 17 00:00:00 2001 From: Jared Vititoe Date: Sun, 14 Jun 2026 13:19:20 -0400 Subject: [PATCH] fix(desktop): taskbar badge transparent circle + larger size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src-tauri/src/lib.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 0efaa5e..38c35f6 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -162,7 +162,7 @@ fn set_badge_count(count: u32, window: tauri::Window) -> Result<(), String> { let mut label_wide: Vec = 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());