Workaround libpng crash on macos by not creating `NSImage` from png data (#7252)
This commit is contained in:
parent
c8b844cd83
commit
98add13933
|
|
@ -205,13 +205,18 @@ fn set_title_and_icon_mac(title: &str, icon_data: Option<&IconData>) -> AppIconS
|
||||||
|
|
||||||
use objc2::ClassType as _;
|
use objc2::ClassType as _;
|
||||||
use objc2_app_kit::{NSApplication, NSImage};
|
use objc2_app_kit::{NSApplication, NSImage};
|
||||||
use objc2_foundation::{NSData, NSString};
|
use objc2_foundation::NSString;
|
||||||
|
|
||||||
let png_bytes = if let Some(icon_data) = icon_data {
|
// Do NOT use png even though creating `NSImage` from it is much easier than from raw images data!
|
||||||
match icon_data.to_png_bytes() {
|
//
|
||||||
Ok(png_bytes) => Some(png_bytes),
|
// Some MacOS versions have a bug where creating an `NSImage` from a png will cause it to load an arbitrary `libpng.dylib`.
|
||||||
|
// If this dylib isn't the right version, the application will crash with SIGBUS.
|
||||||
|
// For details see https://github.com/emilk/egui/issues/7155
|
||||||
|
let image = if let Some(icon_data) = icon_data {
|
||||||
|
match icon_data.to_image() {
|
||||||
|
Ok(image) => Some(image),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::warn!("Failed to convert IconData to png: {err}");
|
log::warn!("Failed to read icon data: {err}");
|
||||||
return AppIconStatus::NotSetIgnored;
|
return AppIconStatus::NotSetIgnored;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -231,15 +236,39 @@ fn set_title_and_icon_mac(title: &str, icon_data: Option<&IconData>) -> AppIconS
|
||||||
return AppIconStatus::NotSetIgnored;
|
return AppIconStatus::NotSetIgnored;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(png_bytes) = png_bytes {
|
if let Some(image) = image {
|
||||||
let data = NSData::from_vec(png_bytes);
|
use objc2_app_kit::{NSBitmapImageRep, NSDeviceRGBColorSpace};
|
||||||
|
use objc2_foundation::NSSize;
|
||||||
|
|
||||||
log::trace!("NSImage::initWithData…");
|
log::trace!("NSBitmapImageRep::initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel");
|
||||||
let app_icon = NSImage::initWithData(NSImage::alloc(), &data);
|
let Some(image_rep) = NSBitmapImageRep::initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel(
|
||||||
|
NSBitmapImageRep::alloc(),
|
||||||
|
[image.as_raw().as_ptr().cast_mut()].as_mut_ptr(),
|
||||||
|
image.width() as isize,
|
||||||
|
image.height() as isize,
|
||||||
|
8, // bits per sample
|
||||||
|
4, // samples per pixel
|
||||||
|
true, // has alpha
|
||||||
|
false, // is not planar
|
||||||
|
NSDeviceRGBColorSpace,
|
||||||
|
(image.width() * 4) as isize, // bytes per row
|
||||||
|
32 // bits per pixel
|
||||||
|
) else {
|
||||||
|
log::warn!("Failed to create NSBitmapImageRep from app icon data.");
|
||||||
|
return AppIconStatus::NotSetIgnored;
|
||||||
|
};
|
||||||
|
|
||||||
|
log::trace!("NSImage::initWithSize");
|
||||||
|
let app_icon = NSImage::initWithSize(
|
||||||
|
NSImage::alloc(),
|
||||||
|
NSSize::new(image.width() as f64, image.height() as f64),
|
||||||
|
);
|
||||||
|
log::trace!("NSImage::addRepresentation");
|
||||||
|
app_icon.addRepresentation(&image_rep);
|
||||||
|
|
||||||
profiling::scope!("setApplicationIconImage_");
|
profiling::scope!("setApplicationIconImage_");
|
||||||
log::trace!("setApplicationIconImage…");
|
log::trace!("setApplicationIconImage…");
|
||||||
app.setApplicationIconImage(app_icon.as_deref());
|
app.setApplicationIconImage(Some(&app_icon));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the title in the top bar - for python processes this would be again "python" otherwise.
|
// Change the title in the top bar - for python processes this would be again "python" otherwise.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue