1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-29 12:50:04 -04:00

eframe: Use objc2 and its framework crates (#4395)

These are a replacement to the `objc` and `cocoa` crates.

This PR prevents:
- An extra copy when creating `NSData`
- A memory leak when creating `NSImage`
- A memory leak when creating `NSString`

And is generally a readability improvement.

Note that we define `NSApp` manually for now, the implementation in
`objc2-app-kit` is currently suboptimal and wouldn't allow you to check
whether the NSApplication has been created or not.

Related: https://github.com/emilk/egui/issues/4219, this should nicely
coincide with the Winit `0.30` release.

---------

Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
Mads Marquart
2024-04-23 17:35:12 +02:00
committed by GitHub
parent 2c590636b5
commit 14194f5d3a
4 changed files with 99 additions and 63 deletions

View File

@@ -203,12 +203,9 @@ fn set_title_and_icon_mac(title: &str, icon_data: Option<&IconData>) -> AppIconS
use crate::icon_data::IconDataExt as _;
crate::profile_function!();
use cocoa::{
appkit::{NSApp, NSApplication, NSImage, NSMenu, NSWindow},
base::{id, nil},
foundation::{NSData, NSString},
};
use objc::{msg_send, sel, sel_impl};
use objc2::ClassType;
use objc2_app_kit::{NSApplication, NSImage};
use objc2_foundation::{NSData, NSString};
let png_bytes = if let Some(icon_data) = icon_data {
match icon_data.to_png_bytes() {
@@ -222,38 +219,36 @@ fn set_title_and_icon_mac(title: &str, icon_data: Option<&IconData>) -> AppIconS
None
};
// SAFETY: Accessing raw data from icon in a read-only manner. Icon data is static!
// TODO(madsmtm): Move this into `objc2-app-kit`
extern "C" {
static NSApp: Option<&'static NSApplication>;
}
unsafe {
let app = NSApp();
if app.is_null() {
let app = if let Some(app) = NSApp {
app
} else {
log::debug!("NSApp is null");
return AppIconStatus::NotSetIgnored;
}
};
if let Some(png_bytes) = png_bytes {
let data = NSData::dataWithBytes_length_(
nil,
png_bytes.as_ptr().cast::<std::ffi::c_void>(),
png_bytes.len() as u64,
);
let data = NSData::from_vec(png_bytes);
log::trace!("NSImage::initWithData…");
let app_icon = NSImage::initWithData_(NSImage::alloc(nil), data);
let app_icon = NSImage::initWithData(NSImage::alloc(), &data);
crate::profile_scope!("setApplicationIconImage_");
log::trace!("setApplicationIconImage…");
app.setApplicationIconImage_(app_icon);
app.setApplicationIconImage(app_icon.as_deref());
}
// Change the title in the top bar - for python processes this would be again "python" otherwise.
let main_menu = app.mainMenu();
if !main_menu.is_null() {
let item = main_menu.itemAtIndex_(0);
if !item.is_null() {
let app_menu: id = msg_send![item, submenu];
if !app_menu.is_null() {
if let Some(main_menu) = app.mainMenu() {
if let Some(item) = main_menu.itemAtIndex(0) {
if let Some(app_menu) = item.submenu() {
crate::profile_scope!("setTitle_");
app_menu.setTitle_(NSString::alloc(nil).init_str(title));
app_menu.setTitle(&NSString::from_str(title));
}
}
}