Skip to content
This repository has been archived by the owner on Apr 24, 2024. It is now read-only.

Commit

Permalink
feat(backend): 迁移至 objc2 与 icrate
Browse files Browse the repository at this point in the history
  • Loading branch information
BillGoldenWater committed May 14, 2023
1 parent 43f1376 commit f1409a5
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 199 deletions.
56 changes: 53 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,9 @@ itertools = "0.10.5"
windows = { version = "0.48.0", features = ["Win32_Foundation", "Win32_System_Console"] }

[target.'cfg(target_os = "macos")'.dependencies]
cocoa = "0.24.1"
objc = "0.2.7"
libc = "0.2.144"
objc_id = "0.1.1"
objc2 = "0.3.0-beta.5"
icrate = { version = "0.0.2", features = ["Foundation", "Foundation_NSString", "Foundation_NSProcessInfo", "AppKit", "AppKit_NSWindow", "AppKit_NSButton"] }

[features]
# by default Tauri runs in production mode
Expand Down
2 changes: 1 addition & 1 deletion backend/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ fn print_env_info() {
info!("build info: {}", build_info());
#[cfg(target_os = "macos")]
{
use crate::utils::process_utils::is_running_under_rosetta;
use crate::utils::process_utils::macos::is_running_under_rosetta;
use log::warn;

if std::env::consts::ARCH == "x86_64" {
Expand Down
7 changes: 4 additions & 3 deletions backend/src/app/app_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use tokio::{
use crate::app::config_manager::ConfigManager;
use crate::network::command_broadcast_server::CommandBroadcastServer;
use crate::network::danmu_receiver::DanmuReceiver;
use crate::utils::process_utils::set_nap;

type Sender = UnboundedSender<()>;
type Receiver = UnboundedReceiver<()>;
Expand Down Expand Up @@ -59,7 +58,8 @@ impl AppLoop {
}

async fn run_loop(&mut self) {
set_nap(
#[cfg(target_os = "macos")]
crate::utils::process_utils::macos::set_nap(
false,
"communicating with bilibili server and danmu viewer clients",
);
Expand All @@ -85,7 +85,8 @@ impl AppLoop {
}
}

set_nap(true, "");
#[cfg(target_os = "macos")]
crate::utils::process_utils::macos::set_nap(true, "");

// send stopped signal
let result = self.ret_tx.send(());
Expand Down
25 changes: 9 additions & 16 deletions backend/src/app/internal_api/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ use crate::get_cfg;
use crate::network::command_broadcast_server::CommandBroadcastServer;
use crate::utils::async_utils::run_blocking;
use crate::utils::immutable_utils::Immutable;
use crate::utils::window_utils::set_visible_on_all_workspaces;

#[command]
pub fn show_main_window(app_handle: tauri::AppHandle) {
Expand Down Expand Up @@ -65,14 +64,10 @@ pub fn create_main_window(app_handle: tauri::AppHandle) {

#[cfg(target_os = "macos")]
{
use crate::utils::window_utils::set_collection_behavior;
use cocoa::appkit::NSWindowCollectionBehavior;
use crate::utils::window_utils::macos::set_collection_behavior;
use icrate::AppKit::NSWindowCollectionBehaviorManaged;

set_collection_behavior(
&main_window,
true,
NSWindowCollectionBehavior::NSWindowCollectionBehaviorManaged,
);
set_collection_behavior(&main_window, true, NSWindowCollectionBehaviorManaged);
}
}

Expand Down Expand Up @@ -161,17 +156,15 @@ pub fn create_viewer_window(app_handle: &tauri::AppHandle<Wry>) {
.set_always_on_top(true)
.expect("failed to set always on top of viewer_window");

set_visible_on_all_workspaces(&viewer_window, true, true, false);
#[cfg(target_os = "macos")]
{
use crate::utils::window_utils::set_collection_behavior;
use cocoa::appkit::NSWindowCollectionBehavior;
use crate::utils::window_utils::macos::{
set_collection_behavior, set_visible_on_all_workspaces,
};
use icrate::AppKit::NSWindowCollectionBehaviorStationary;

set_collection_behavior(
&viewer_window,
true,
NSWindowCollectionBehavior::NSWindowCollectionBehaviorStationary,
);
set_visible_on_all_workspaces(&viewer_window, true, true, false);
set_collection_behavior(&viewer_window, true, NSWindowCollectionBehaviorStationary);
}

let _ = window_shadows::set_shadow(viewer_window, false);
Expand Down
100 changes: 1 addition & 99 deletions backend/src/utils/process_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,102 +4,4 @@
*/

#[cfg(target_os = "macos")]
#[allow(non_snake_case)]
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct ProcessSerialNumber {
pub highLongOfPSN: u32,
pub lowLongOfPSN: u32,
}

#[cfg(target_os = "macos")]
pub type ProcessSerialNumberPtr = *mut ProcessSerialNumber;
#[cfg(target_os = "macos")]
pub type OSStatus = i32;

#[cfg(target_os = "macos")]
#[link(name = "ApplicationServices", kind = "framework")]
extern "C" {
pub(crate) fn TransformProcessType(psn: ProcessSerialNumberPtr, transform_state: u32)
-> OSStatus;
}

#[cfg(target_os = "macos")]
pub fn get_psn() -> ProcessSerialNumber {
ProcessSerialNumber {
highLongOfPSN: 0,
lowLongOfPSN: 2,
}
}

#[cfg(target_os = "macos")]
pub fn is_running_under_rosetta() -> std::io::Result<bool> {
unsafe {
let mut ret = 0;

let attr_name = std::ffi::CString::new("sysctl.proc_translated").unwrap();

let error = libc::sysctlbyname(
attr_name.as_ptr(),
&mut ret as *mut std::os::raw::c_int as *mut std::ffi::c_void,
&mut 8,
std::ptr::null_mut(),
0,
);

if error < std::os::raw::c_int::default() {
return Err(std::io::Error::last_os_error());
}

Ok(ret == 1)
}
}

#[allow(unused_variables)]
pub fn set_nap(enable: bool, reason: &str) {
#[allow(non_upper_case_globals)]
#[cfg(target_os = "macos")]
{
use cocoa::base::nil;
use cocoa::foundation::{NSProcessInfo, NSString};
use objc::{runtime::Object, *};
use objc_id::Id;
use once_cell::sync::Lazy;
use std::sync::Mutex;

const NSActivityIdleSystemSleepDisabled: u64 = 1u64 << 20;
const NSActivitySuddenTerminationDisabled: u64 = 1u64 << 14;
const NSActivityAutomaticTerminationDisabled: u64 = 1u64 << 15;
const NSActivityUserInitiated: u64 = 0x00FFFFFFu64 | NSActivityIdleSystemSleepDisabled;
const NSActivityLatencyCritical: u64 = 0xFF00000000u64;

const options: u64 = NSActivityIdleSystemSleepDisabled
| NSActivitySuddenTerminationDisabled
| NSActivityAutomaticTerminationDisabled
| NSActivityUserInitiated
| NSActivityLatencyCritical;

static ACTIVITY_ID: Lazy<Mutex<Option<Id<Object>>>> = Lazy::new(|| Mutex::new(None));

let process_info = unsafe { NSProcessInfo::processInfo(nil) };

if enable {
if let Some(activity_id) = ACTIVITY_ID.lock().unwrap().take() {
unsafe {
let _: () = msg_send![process_info, endActivity: activity_id];
}
}
} else {
if ACTIVITY_ID.lock().unwrap().is_some() {
set_nap(true, "");
}

let activity_id: Id<Object> = unsafe {
let reason = NSString::alloc(nil).init_str(if reason.is_empty() { "none" } else { reason });
msg_send![process_info, beginActivityWithOptions:options reason:reason]
};

*ACTIVITY_ID.lock().unwrap() = Some(activity_id);
}
}
}
pub mod macos;
102 changes: 102 additions & 0 deletions backend/src/utils/process_utils/macos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 2021-2023 Golden_Water
* SPDX-License-Identifier: AGPL-3.0-only
*/

use std::sync::Mutex;
use std::{
ffi::{c_void, CString},
io,
os::raw::c_int,
ptr,
};

use icrate::{
Foundation::NSProcessInfo,
Foundation::{
NSActivityAutomaticTerminationDisabled, NSActivityIdleSystemSleepDisabled,
NSActivityLatencyCritical, NSActivitySuddenTerminationDisabled, NSActivityUserInitiated,
},
Foundation::{NSActivityOptions, NSString},
};
use objc2::{rc::Id, rc::Shared, runtime::NSObject};
use once_cell::sync::Lazy;

#[link(name = "ApplicationServices", kind = "framework")]
extern "C" {
pub(crate) fn TransformProcessType(psn: ProcessSerialNumberPtr, transform_state: u32)
-> OSStatus;
}

#[allow(non_snake_case)]
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct ProcessSerialNumber {
pub highLongOfPSN: u32,
pub lowLongOfPSN: u32,
}

pub type ProcessSerialNumberPtr = *mut ProcessSerialNumber;

pub type OSStatus = i32;

pub fn get_psn() -> ProcessSerialNumber {
ProcessSerialNumber {
highLongOfPSN: 0,
lowLongOfPSN: 2,
}
}

pub fn is_running_under_rosetta() -> io::Result<bool> {
unsafe {
let mut ret = 0;

let attr_name = CString::new("sysctl.proc_translated").unwrap();

let error = libc::sysctlbyname(
attr_name.as_ptr(),
&mut ret as *mut c_int as *mut c_void,
&mut 8,
ptr::null_mut(),
0,
);

if error < c_int::default() {
return Err(io::Error::last_os_error());
}

Ok(ret == 1)
}
}

pub fn set_nap(enable: bool, reason: &str) {
struct ForceSend<T>(T);
unsafe impl<T> Send for ForceSend<T> {}

type ActivityId = Mutex<Option<ForceSend<Id<NSObject, Shared>>>>;

const OPTIONS: NSActivityOptions = NSActivityIdleSystemSleepDisabled
| NSActivitySuddenTerminationDisabled
| NSActivityAutomaticTerminationDisabled
| NSActivityUserInitiated
| NSActivityLatencyCritical;

static ACTIVITY_ID: Lazy<ActivityId> = Lazy::new(|| Mutex::new(None));

let process_info = NSProcessInfo::processInfo();

if enable {
if let Some(activity_id) = ACTIVITY_ID.lock().unwrap().take() {
unsafe { process_info.endActivity(&activity_id.0) }
}
} else {
if ACTIVITY_ID.lock().unwrap().is_some() {
set_nap(true, "");
}

let activity_id =
unsafe { process_info.beginActivityWithOptions_reason(OPTIONS, &NSString::from_str(reason)) };

*ACTIVITY_ID.lock().unwrap() = Some(ForceSend(activity_id));
}
}

0 comments on commit f1409a5

Please sign in to comment.