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:
parent
2c590636b5
commit
14194f5d3a
|
|
@ -548,7 +548,7 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dd7cf50912cddc06dc5ea7c08c5e81c1b2c842a70d19def1848d54c586fed92"
|
||||
dependencies = [
|
||||
"objc-sys 0.3.1",
|
||||
"objc-sys 0.3.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -571,6 +571,15 @@ dependencies = [
|
|||
"objc2 0.4.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block2"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43ff7d91d3c1d568065b06c899777d1e48dcf76103a672a0adbc238a7f247f1e"
|
||||
dependencies = [
|
||||
"objc2 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blocking"
|
||||
version = "1.4.0"
|
||||
|
|
@ -795,36 +804,6 @@ dependencies = [
|
|||
"error-code",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"block",
|
||||
"cocoa-foundation",
|
||||
"core-foundation",
|
||||
"core-graphics",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cocoa-foundation"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"block",
|
||||
"core-foundation",
|
||||
"core-graphics-types",
|
||||
"libc",
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
|
|
@ -1201,7 +1180,6 @@ name = "eframe"
|
|||
version = "0.27.2"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"cocoa",
|
||||
"directories-next",
|
||||
"document-features",
|
||||
"egui",
|
||||
|
|
@ -1214,7 +1192,9 @@ dependencies = [
|
|||
"image",
|
||||
"js-sys",
|
||||
"log",
|
||||
"objc",
|
||||
"objc2 0.5.1",
|
||||
"objc2-app-kit",
|
||||
"objc2-foundation",
|
||||
"parking_lot",
|
||||
"percent-encoding",
|
||||
"pollster",
|
||||
|
|
@ -2599,9 +2579,9 @@ checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7"
|
|||
|
||||
[[package]]
|
||||
name = "objc-sys"
|
||||
version = "0.3.1"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99e1d07c6eab1ce8b6382b8e3c7246fe117ff3f8b34be065f5ebace6749fe845"
|
||||
checksum = "da284c198fb9b7b0603f8635185e85fbd5b64ee154b1ed406d489077de2d6d60"
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
|
|
@ -2620,10 +2600,43 @@ version = "0.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d"
|
||||
dependencies = [
|
||||
"objc-sys 0.3.1",
|
||||
"objc-sys 0.3.3",
|
||||
"objc2-encode 3.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4b25e1034d0e636cd84707ccdaa9f81243d399196b8a773946dcffec0401659"
|
||||
dependencies = [
|
||||
"objc-sys 0.3.3",
|
||||
"objc2-encode 4.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-app-kit"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fb79768a710a9a1798848179edb186d1af7e8a8679f369e4b8d201dd2a034047"
|
||||
dependencies = [
|
||||
"block2 0.5.0",
|
||||
"objc2 0.5.1",
|
||||
"objc2-core-data",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-core-data"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e092bc42eaf30a08844e6a076938c60751225ec81431ab89f5d1ccd9f958d6c"
|
||||
dependencies = [
|
||||
"block2 0.5.0",
|
||||
"objc2 0.5.1",
|
||||
"objc2-foundation",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "2.0.0-pre.2"
|
||||
|
|
@ -2639,6 +2652,22 @@ version = "3.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-encode"
|
||||
version = "4.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88658da63e4cc2c8adb1262902cd6af51094df0488b760d6fd27194269c0950a"
|
||||
|
||||
[[package]]
|
||||
name = "objc2-foundation"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cfaefe14254871ea16c7d88968c0ff14ba554712a20d76421eec52f0a7fb8904"
|
||||
dependencies = [
|
||||
"block2 0.5.0",
|
||||
"objc2 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_exception"
|
||||
version = "0.1.2"
|
||||
|
|
|
|||
|
|
@ -178,8 +178,19 @@ wgpu = { workspace = true, optional = true, features = [
|
|||
|
||||
# mac:
|
||||
[target.'cfg(any(target_os = "macos"))'.dependencies]
|
||||
cocoa = "0.25.0"
|
||||
objc = "0.2.7"
|
||||
objc2 = "0.5.1"
|
||||
objc2-foundation = { version = "0.2.0", features = [
|
||||
"block2",
|
||||
"NSData",
|
||||
"NSString",
|
||||
] }
|
||||
objc2-app-kit = { version = "0.2.0", features = [
|
||||
"NSApplication",
|
||||
"NSImage",
|
||||
"NSMenu",
|
||||
"NSMenuItem",
|
||||
"NSResponder",
|
||||
] }
|
||||
|
||||
# windows:
|
||||
[target.'cfg(any(target_os = "windows"))'.dependencies]
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ deny = [
|
|||
|
||||
skip = [
|
||||
{ name = "bitflags" }, # old 1.0 version via glutin, png, spirv, …
|
||||
{ name = "block2" }, # old version via glutin->icrate
|
||||
{ name = "event-listener" }, # TODO(emilk): rustls pulls in two versions of this 😭
|
||||
{ name = "libloading" }, # wgpu-hal itself depends on 0.8 while some of its dependencies, like ash and d3d12, depend on 0.7
|
||||
{ name = "memoffset" }, # tiny dependency
|
||||
|
|
@ -61,7 +62,7 @@ skip = [
|
|||
skip-tree = [
|
||||
{ name = "criterion" }, # dev-dependency
|
||||
{ name = "fastrand" }, # old version via accesskit_unix
|
||||
{ name = "foreign-types" }, # small crate. Old version via cocoa and core-graphics (winit).
|
||||
{ name = "foreign-types" }, # small crate. Old version via core-graphics (winit).
|
||||
{ name = "objc2" }, # old version via accesskit_macos
|
||||
{ name = "polling" }, # old version via accesskit_unix
|
||||
{ name = "rfd" }, # example dependency
|
||||
|
|
|
|||
Loading…
Reference in New Issue