From 729985877af86ea3d851658f48a756a7d8e68d1d Mon Sep 17 00:00:00 2001 From: Sena <34237511+sena-nana@users.noreply.github.com> Date: Thu, 3 Sep 2026 22:01:35 +0800 Subject: [PATCH] win32: Copy icon pixels to BGRA instead of mutating the shared buffer --- winit-win32/src/icon.rs | 30 ++++++------------------------ winit/src/changelog/unreleased.md | 3 +++ 2 files changed, 9 insertions(+), 24 deletions(-) diff --git a/winit-win32/src/icon.rs b/winit-win32/src/icon.rs index 8fdf95bea..88fa9588f 100644 --- a/winit-win32/src/icon.rs +++ b/winit-win32/src/icon.rs @@ -20,7 +20,7 @@ use winit_core::icon::*; use super::util; use crate::WinIcon; -pub(crate) const PIXEL_SIZE: usize = mem::size_of::(); +pub(crate) const PIXEL_SIZE: usize = mem::size_of::(); unsafe impl Send for WinIcon {} @@ -96,14 +96,11 @@ impl WinIcon { pub(crate) fn from_rgba(rgba: &RgbaIcon) -> Result { let pixel_count = rgba.buffer().len() / PIXEL_SIZE; let mut and_mask = Vec::with_capacity(pixel_count); - let pixels = unsafe { - std::slice::from_raw_parts_mut(rgba.buffer().as_ptr() as *mut Pixel, pixel_count) - }; - for pixel in pixels { - and_mask.push(pixel.a.wrapping_sub(u8::MAX)); // invert alpha channel - pixel.convert_to_bgra(); + let mut bgra = Vec::with_capacity(rgba.buffer().len()); + for pixel in rgba.buffer().chunks_exact(PIXEL_SIZE) { + and_mask.push(pixel[3].wrapping_sub(u8::MAX)); // invert alpha channel + bgra.extend_from_slice(&[pixel[2], pixel[1], pixel[0], pixel[3]]); } - assert_eq!(and_mask.len(), pixel_count); let handle = unsafe { CreateIcon( ptr::null_mut(), @@ -112,7 +109,7 @@ impl WinIcon { 1, (PIXEL_SIZE * 8) as u8, and_mask.as_ptr(), - rgba.buffer().as_ptr(), + bgra.as_ptr(), ) }; if !handle.is_null() { @@ -135,12 +132,6 @@ impl fmt::Debug for WinIcon { } } -impl Pixel { - fn convert_to_bgra(&mut self) { - mem::swap(&mut self.r, &mut self.b); - } -} - #[derive(Debug, Clone, Copy)] pub enum IconType { Small = ICON_SMALL as isize, @@ -252,12 +243,3 @@ impl RaiiCursor { self.handle } } - -#[repr(C)] -#[derive(Debug)] -pub(crate) struct Pixel { - pub(crate) r: u8, - pub(crate) g: u8, - pub(crate) b: u8, - pub(crate) a: u8, -} diff --git a/winit/src/changelog/unreleased.md b/winit/src/changelog/unreleased.md index f99d149f4..5381bd83e 100644 --- a/winit/src/changelog/unreleased.md +++ b/winit/src/changelog/unreleased.md @@ -117,6 +117,9 @@ changelog entry. `DefWindowProc` for normal propagation. - On Windows, fix getting the window's DPI internally leaks `HDC` handles. Also only call `GetDC` when on < Windows 8.1 which improves its performance. +- On Windows, fix window icons rendering with red and blue swapped when the same `Icon` is + applied more than once (e.g. sharing one icon between the window and the taskbar). The RGBA + to BGRA conversion no longer mutates the shared pixel buffer. - On Redox, handle `EINTR` when reading from `event_socket` instead of panicking. - On X11, fix all pointer input being dropped for absolute pointing devices without pressure or tilt axes, such as the emulated tablets of