win32: Copy icon pixels to BGRA instead of mutating the shared buffer

This commit is contained in:
Sena
2026-09-03 22:01:35 +08:00
committed by GitHub
parent 98562ae862
commit 729985877a
2 changed files with 9 additions and 24 deletions

View File

@@ -20,7 +20,7 @@ use winit_core::icon::*;
use super::util; use super::util;
use crate::WinIcon; use crate::WinIcon;
pub(crate) const PIXEL_SIZE: usize = mem::size_of::<Pixel>(); pub(crate) const PIXEL_SIZE: usize = mem::size_of::<u32>();
unsafe impl Send for WinIcon {} unsafe impl Send for WinIcon {}
@@ -96,14 +96,11 @@ impl WinIcon {
pub(crate) fn from_rgba(rgba: &RgbaIcon) -> Result<Self, BadIcon> { pub(crate) fn from_rgba(rgba: &RgbaIcon) -> Result<Self, BadIcon> {
let pixel_count = rgba.buffer().len() / PIXEL_SIZE; let pixel_count = rgba.buffer().len() / PIXEL_SIZE;
let mut and_mask = Vec::with_capacity(pixel_count); let mut and_mask = Vec::with_capacity(pixel_count);
let pixels = unsafe { let mut bgra = Vec::with_capacity(rgba.buffer().len());
std::slice::from_raw_parts_mut(rgba.buffer().as_ptr() as *mut Pixel, pixel_count) for pixel in rgba.buffer().chunks_exact(PIXEL_SIZE) {
}; and_mask.push(pixel[3].wrapping_sub(u8::MAX)); // invert alpha channel
for pixel in pixels { bgra.extend_from_slice(&[pixel[2], pixel[1], pixel[0], pixel[3]]);
and_mask.push(pixel.a.wrapping_sub(u8::MAX)); // invert alpha channel
pixel.convert_to_bgra();
} }
assert_eq!(and_mask.len(), pixel_count);
let handle = unsafe { let handle = unsafe {
CreateIcon( CreateIcon(
ptr::null_mut(), ptr::null_mut(),
@@ -112,7 +109,7 @@ impl WinIcon {
1, 1,
(PIXEL_SIZE * 8) as u8, (PIXEL_SIZE * 8) as u8,
and_mask.as_ptr(), and_mask.as_ptr(),
rgba.buffer().as_ptr(), bgra.as_ptr(),
) )
}; };
if !handle.is_null() { 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)] #[derive(Debug, Clone, Copy)]
pub enum IconType { pub enum IconType {
Small = ICON_SMALL as isize, Small = ICON_SMALL as isize,
@@ -252,12 +243,3 @@ impl RaiiCursor {
self.handle 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,
}

View File

@@ -117,6 +117,9 @@ changelog entry.
`DefWindowProc` for normal propagation. `DefWindowProc` for normal propagation.
- On Windows, fix getting the window's DPI internally leaks `HDC` handles. - 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. 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 Redox, handle `EINTR` when reading from `event_socket` instead of panicking.
- On X11, fix all pointer input being dropped for absolute pointing devices - On X11, fix all pointer input being dropped for absolute pointing devices
without pressure or tilt axes, such as the emulated tablets of without pressure or tilt axes, such as the emulated tablets of