-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathmacos.rs
More file actions
100 lines (84 loc) · 3.92 KB
/
Copy pathmacos.rs
File metadata and controls
100 lines (84 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#![allow(unexpected_cfgs)]
#[cfg(target_os = "macos")]
use tauri::{AppHandle, Emitter};
#[cfg(target_os = "macos")]
pub fn hide_dock_icon() {
use cocoa::appkit::{NSApplication, NSApplicationActivationPolicyAccessory};
unsafe {
let app = NSApplication::sharedApplication(cocoa::base::nil);
app.setActivationPolicy_(NSApplicationActivationPolicyAccessory);
}
}
#[cfg(target_os = "macos")]
pub fn force_focus() {
use cocoa::appkit::NSApplication;
unsafe {
let app = NSApplication::sharedApplication(cocoa::base::nil);
app.activateIgnoringOtherApps_(cocoa::base::YES);
}
}
#[cfg(target_os = "macos")]
pub fn setup_power_monitor(app_handle: AppHandle) {
use cocoa::base::{id, nil};
use cocoa::foundation::NSString;
use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel};
use std::ffi::c_void;
unsafe {
let class_name = "PaperCachePowerMonitorDelegate";
let delegate_class = match Class::get(class_name) {
Some(cls) => cls,
None => {
let superclass = class!(NSObject);
let mut decl =
ClassDecl::new(class_name, superclass).expect("Failed to declare class");
decl.add_ivar::<*mut c_void>("app_handle");
extern "C" fn on_sleep(this: &Object, _cmd: Sel, _notification: id) {
unsafe {
let ptr: *mut c_void = *this.get_ivar("app_handle");
let app = &*(ptr as *const AppHandle);
let _ = app.emit("power:suspend", ());
}
}
extern "C" fn on_wake(this: &Object, _cmd: Sel, _notification: id) {
unsafe {
let ptr: *mut c_void = *this.get_ivar("app_handle");
let app = &*(ptr as *const AppHandle);
let _ = app.emit("power:resume", ());
}
}
decl.add_method(sel!(onSleep:), on_sleep as extern "C" fn(&Object, Sel, id));
decl.add_method(sel!(onWake:), on_wake as extern "C" fn(&Object, Sel, id));
decl.register()
}
};
let delegate: id = msg_send![delegate_class, new];
// SAFETY: We intentionally leak the AppHandle here. The NSNotificationCenter
// observer (delegate) is registered for the lifetime of the process and must
// always have a valid pointer to the handle. Freeing the box would invalidate
// the pointer stored in the Objective-C ivar, causing a use-after-free.
// This is a deliberate, bounded leak (one pointer per process lifetime).
let app_box = Box::new(app_handle);
let ptr = Box::into_raw(app_box) as *mut c_void;
(*delegate).set_ivar("app_handle", ptr);
let workspace: id = msg_send![class!(NSWorkspace), sharedWorkspace];
let nc: id = msg_send![workspace, notificationCenter];
let sleep_notification = NSString::alloc(nil).init_str("NSWorkspaceWillSleepNotification");
let wake_notification = NSString::alloc(nil).init_str("NSWorkspaceDidWakeNotification");
let _: () = msg_send![nc, addObserver:delegate selector:sel!(onSleep:) name:sleep_notification object:nil];
let _: () = msg_send![nc, addObserver:delegate selector:sel!(onWake:) name:wake_notification object:nil];
}
}
#[cfg(target_os = "macos")]
pub fn set_move_to_active_space(window: &tauri::WebviewWindow) {
use cocoa::appkit::NSWindow;
use cocoa::appkit::NSWindowCollectionBehavior;
if let Ok(ns_window) = window.ns_window() {
unsafe {
let ns_window = ns_window as cocoa::base::id;
let mut behavior = ns_window.collectionBehavior();
behavior |= NSWindowCollectionBehavior::NSWindowCollectionBehaviorMoveToActiveSpace;
ns_window.setCollectionBehavior_(behavior);
}
}
}