fix(macos): resolve build warnings, memory leaks, and thread safety

- Remove deprecated `cocoa` crate in favor of direct `objc` usage to fix future-incompatibilities warning from `block` dependency.
- Fix irrefutable `if let` pattern warning in macOS `SleepPreventer::Drop`.
- Fix memory leaks by properly releasing `alloc`-ed `NSString` and `NSAppleScript` objects.
- Fix AppKit thread safety by routing dock badge updates to the main thread via `run_on_main_thread`.
This commit is contained in:
NimBold
2026-06-26 21:18:58 +03:30
parent eb7be82e71
commit e1e1061511
3 changed files with 45 additions and 90 deletions
+2 -63
View File
@@ -362,12 +362,6 @@ dependencies = [
"wyz",
]
[[package]]
name = "block"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "block-buffer"
version = "0.10.4"
@@ -650,36 +644,6 @@ dependencies = [
"windows-link 0.2.1",
]
[[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 0.9.4",
"core-graphics 0.23.2",
"foreign-types 0.5.0",
"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 0.9.4",
"core-graphics-types 0.1.3",
"libc",
"objc",
]
[[package]]
name = "combine"
version = "4.6.7"
@@ -755,19 +719,6 @@ version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "core-graphics"
version = "0.23.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081"
dependencies = [
"bitflags 1.3.2",
"core-foundation 0.9.4",
"core-graphics-types 0.1.3",
"foreign-types 0.5.0",
"libc",
]
[[package]]
name = "core-graphics"
version = "0.25.0"
@@ -776,22 +727,11 @@ checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97"
dependencies = [
"bitflags 2.13.0",
"core-foundation 0.10.1",
"core-graphics-types 0.2.0",
"core-graphics-types",
"foreign-types 0.5.0",
"libc",
]
[[package]]
name = "core-graphics-types"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf"
dependencies = [
"bitflags 1.3.2",
"core-foundation 0.9.4",
"libc",
]
[[package]]
name = "core-graphics-types"
version = "0.2.0"
@@ -1375,7 +1315,6 @@ dependencies = [
"async-trait",
"axum",
"chrono",
"cocoa",
"futures-util",
"hmac",
"keepawake",
@@ -4711,7 +4650,7 @@ dependencies = [
"bitflags 2.13.0",
"block2",
"core-foundation 0.10.1",
"core-graphics 0.25.0",
"core-graphics",
"crossbeam-channel",
"dbus",
"dispatch2",
-1
View File
@@ -58,7 +58,6 @@ tauri-plugin-log = "2"
trash = "5"
async-trait = "0.1"
[target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.25"
objc = "0.2.7"
keyring = { version = "3", features = ["apple-native"] }
+43 -26
View File
@@ -3070,25 +3070,31 @@ async fn wait_for_aria2_stopped(port: u16, secret: &str, gid: &str) -> Result<()
}
#[tauri::command]
fn update_dock_badge(_app_handle: tauri::AppHandle, count: i32) {
fn update_dock_badge(app_handle: tauri::AppHandle, count: i32) {
#[cfg(target_os = "macos")]
{
use cocoa::appkit::NSApp;
use cocoa::base::{id, nil};
use cocoa::foundation::NSString;
use objc::{msg_send, sel, sel_impl};
use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use std::ffi::CString;
unsafe {
let app = NSApp();
let dock_tile: id = msg_send![app, dockTile];
let label = if count > 0 {
count.to_string()
} else {
"".to_string()
};
let ns_label = NSString::alloc(nil).init_str(&label);
let _: () = msg_send![dock_tile, setBadgeLabel: ns_label];
}
let _ = app_handle.run_on_main_thread(move || {
unsafe {
let app_class = class!(NSApplication);
let app: *mut Object = msg_send![app_class, sharedApplication];
let dock_tile: *mut Object = msg_send![app, dockTile];
let label = if count > 0 {
count.to_string()
} else {
"".to_string()
};
let c_label = CString::new(label).unwrap();
let ns_string_class = class!(NSString);
let ns_label: *mut Object = msg_send![ns_string_class, alloc];
let ns_label: *mut Object = msg_send![ns_label, initWithUTF8String: c_label.as_ptr()];
let _: () = msg_send![dock_tile, setBadgeLabel: ns_label];
let _: () = msg_send![ns_label, release];
}
});
}
}
@@ -3137,7 +3143,8 @@ pub enum SleepPreventer {
impl Drop for SleepPreventer {
fn drop(&mut self) {
#[cfg(target_os = "macos")]
if let SleepPreventer::Mac { system_sleep_id, network_client_id } = self {
{
let SleepPreventer::Mac { system_sleep_id, network_client_id } = self;
unsafe {
macos_sleep::IOPMAssertionRelease(*system_sleep_id);
macos_sleep::IOPMAssertionRelease(*network_client_id);
@@ -3415,19 +3422,29 @@ async fn set_global_speed_limit(
fn check_automation_permission() -> Result<(), String> {
#[cfg(target_os = "macos")]
{
use cocoa::base::{id, nil};
use cocoa::foundation::NSString;
use objc::runtime::Object;
use objc::{class, msg_send, sel, sel_impl};
use std::ffi::CString;
use std::ptr::null_mut;
unsafe {
objc::rc::autoreleasepool(|| {
let script_str =
NSString::alloc(nil).init_str("tell application \"System Events\" to get name");
let ns_apple_script: id = msg_send![class!(NSAppleScript), alloc];
let ns_apple_script: id = msg_send![ns_apple_script, initWithSource: script_str];
let mut error_dict: id = nil;
let result: id = msg_send![ns_apple_script, executeAndReturnError: &mut error_dict];
if result == nil {
let script = "tell application \"System Events\" to get name";
let c_script = CString::new(script).unwrap();
let ns_string_class = class!(NSString);
let script_str: *mut Object = msg_send![ns_string_class, alloc];
let script_str: *mut Object = msg_send![script_str, initWithUTF8String: c_script.as_ptr()];
let ns_apple_script: *mut Object = msg_send![class!(NSAppleScript), alloc];
let ns_apple_script: *mut Object = msg_send![ns_apple_script, initWithSource: script_str];
let mut error_dict: *mut Object = null_mut();
let result: *mut Object = msg_send![ns_apple_script, executeAndReturnError: &mut error_dict];
let _: () = msg_send![script_str, release];
let _: () = msg_send![ns_apple_script, release];
if result.is_null() {
return Err("Automation permission was not granted".to_string());
}
Ok(())