From c53aacf37f8b8afdae03d298d1d6b44a6f0fb33a Mon Sep 17 00:00:00 2001 From: unsecretised Date: Wed, 22 Apr 2026 12:43:49 +0800 Subject: [PATCH 1/5] Fix attempt --- assets/entitlements.plist | 18 ++++++++++++++++++ scripts/sign-macos.sh | 3 +++ 2 files changed, 21 insertions(+) create mode 100644 assets/entitlements.plist diff --git a/assets/entitlements.plist b/assets/entitlements.plist new file mode 100644 index 0000000..a56b251 --- /dev/null +++ b/assets/entitlements.plist @@ -0,0 +1,18 @@ + + + + + + com.apple.security.temporary-exception.accessibility + + + + com.apple.security.app-sandbox + + + + com.apple.security.device.input-monitoring + + + diff --git a/scripts/sign-macos.sh b/scripts/sign-macos.sh index 881f50f..6b99c8e 100755 --- a/scripts/sign-macos.sh +++ b/scripts/sign-macos.sh @@ -1,5 +1,7 @@ #!/usr/bin/env -S bash -e +ENTITLEMENTS_PATH="assets/macos/entitlements.plist" + APP_BUNDLE_PATH="${APP_BUNDLE_PATH:?APP_BUNDLE_PATH not set}" # 1. Create a temporary keychain and import certificate @@ -29,6 +31,7 @@ security set-key-partition-list -S apple-tool:,apple:,codesign: \ # 2. Sign app bundle codesign --deep --force --options runtime --timestamp \ + --entitlements $ENTITLEMENTS_PATH \ --sign "$MACOS_CERTIFICATE_NAME" \ "$APP_BUNDLE_PATH" From b8f006fc0cc7959773d5185be9fc5828b19b10c5 Mon Sep 17 00:00:00 2001 From: unsecretised Date: Wed, 22 Apr 2026 13:09:04 +0800 Subject: [PATCH 2/5] update path --- assets/entitlements.plist | 9 ++------- scripts/sign-macos.sh | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/assets/entitlements.plist b/assets/entitlements.plist index a56b251..cf673fc 100644 --- a/assets/entitlements.plist +++ b/assets/entitlements.plist @@ -3,16 +3,11 @@ "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> - - com.apple.security.temporary-exception.accessibility - - - com.apple.security.app-sandbox - - com.apple.security.device.input-monitoring + com.apple.security.temporary-exception.accessibility + diff --git a/scripts/sign-macos.sh b/scripts/sign-macos.sh index 6b99c8e..3b1c162 100755 --- a/scripts/sign-macos.sh +++ b/scripts/sign-macos.sh @@ -1,6 +1,6 @@ #!/usr/bin/env -S bash -e -ENTITLEMENTS_PATH="assets/macos/entitlements.plist" +ENTITLEMENTS_PATH="assets/entitlements.plist" APP_BUNDLE_PATH="${APP_BUNDLE_PATH:?APP_BUNDLE_PATH not set}" From b182c9e9b1ec7ac2812edd979327ca4af75fe5f4 Mon Sep 17 00:00:00 2001 From: unsecretised Date: Wed, 22 Apr 2026 13:17:55 +0800 Subject: [PATCH 3/5] ensure accessibility --- src/platform/macos/accessibility.rs | 89 +++++++++++++++++++++++++++++ src/platform/macos/launching.rs | 3 +- src/platform/macos/login.rs | 0 src/platform/macos/mod.rs | 1 + 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 src/platform/macos/accessibility.rs delete mode 100644 src/platform/macos/login.rs diff --git a/src/platform/macos/accessibility.rs b/src/platform/macos/accessibility.rs new file mode 100644 index 0000000..f994f84 --- /dev/null +++ b/src/platform/macos/accessibility.rs @@ -0,0 +1,89 @@ +use std::ffi::c_void; +use std::thread; +use std::time::{Duration, Instant}; + +use objc2::rc::autoreleasepool; +use objc2::runtime::AnyObject; +use objc2::{class, msg_send}; +use log::info; + +#[link(name = "ApplicationServices", kind = "framework")] +unsafe extern "C" { + fn AXIsProcessTrustedWithOptions(options: *const c_void) -> bool; + + static kAXTrustedCheckOptionPrompt: *const c_void; +} + +#[link(name = "CoreFoundation", kind = "framework")] +unsafe extern "C" { + static kCFBooleanTrue: *const c_void; + static kCFBooleanFalse: *const c_void; +} + +const AX_POLL_INTERVAL: Duration = Duration::from_millis(250); +const AX_POLL_TIMEOUT: Duration = Duration::from_secs(30); + +#[inline] +fn ax_is_trusted() -> bool { + unsafe { + autoreleasepool(|_| { + let keys: [*mut AnyObject; 1] = [kAXTrustedCheckOptionPrompt as *mut AnyObject]; + let vals: [*mut AnyObject; 1] = [kCFBooleanFalse as *mut AnyObject]; + let dict: *mut AnyObject = msg_send![ + class!(NSDictionary), + dictionaryWithObjects: vals.as_ptr(), + forKeys: keys.as_ptr(), + count: 1usize + ]; + + AXIsProcessTrustedWithOptions(dict.cast()) + }) + } +} + +#[allow(unsafe_op_in_unsafe_fn)] +unsafe fn prompt_ax_trust_dialog() { + autoreleasepool(|_| { + let keys: [*mut AnyObject; 1] = [kAXTrustedCheckOptionPrompt as *mut AnyObject]; + let vals: [*mut AnyObject; 1] = [kCFBooleanTrue as *mut AnyObject]; + + let dict: *mut AnyObject = msg_send![ + class!(NSDictionary), + dictionaryWithObjects: vals.as_ptr(), + forKeys: keys.as_ptr(), + count: 1usize + ]; + + let _ = AXIsProcessTrustedWithOptions(dict.cast()); + }); +} + +pub fn ensure_accessibility_permission() { + if ax_is_trusted() { + return; + } + + info!("Accessibility permission is not granted; prompting user for permission now."); + + unsafe { prompt_ax_trust_dialog() }; + + let start = Instant::now(); + loop { + if ax_is_trusted() { + info!("Accessibility permission granted"); + return; + } + + if start.elapsed() >= AX_POLL_TIMEOUT { + break; + } + + thread::sleep(AX_POLL_INTERVAL); + } + + println!( + "Rift still does not have accessibility permission. Enable it in System Settings > Privacy & Security > Accessibility, then restart Rift." + ); + + std::process::exit(1); +} diff --git a/src/platform/macos/launching.rs b/src/platform/macos/launching.rs index 5ef49b4..087bb02 100644 --- a/src/platform/macos/launching.rs +++ b/src/platform/macos/launching.rs @@ -3,9 +3,10 @@ use std::sync::{Arc, Mutex}; use block2::RcBlock; use objc2_app_kit::{NSEvent, NSEventMask, NSEventModifierFlags, NSEventType}; -use crate::app::{Message, tile::ExtSender}; +use crate::{app::{Message, tile::ExtSender}, platform::macos::accessibility::ensure_accessibility_permission}; pub fn global_handler(sender: ExtSender) { + ensure_accessibility_permission(); local_handler(sender.clone()); let mask = NSEventMask::KeyDown | NSEventMask::FlagsChanged; let sender = Arc::new(Mutex::new(sender.0.clone())); diff --git a/src/platform/macos/login.rs b/src/platform/macos/login.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index eeab128..39cb9c4 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -1,4 +1,5 @@ //! Macos specific logic, such as window settings, etc. +pub mod accessibility; pub mod discovery; pub mod haptics; pub mod launching; From 4a6cbf700bda635ae2b32a6f4b2ecfc2507251d3 Mon Sep 17 00:00:00 2001 From: unsecretised Date: Wed, 22 Apr 2026 13:18:04 +0800 Subject: [PATCH 4/5] format -_- --- src/platform/macos/accessibility.rs | 2 +- src/platform/macos/launching.rs | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/platform/macos/accessibility.rs b/src/platform/macos/accessibility.rs index f994f84..2617a41 100644 --- a/src/platform/macos/accessibility.rs +++ b/src/platform/macos/accessibility.rs @@ -2,10 +2,10 @@ use std::ffi::c_void; use std::thread; use std::time::{Duration, Instant}; +use log::info; use objc2::rc::autoreleasepool; use objc2::runtime::AnyObject; use objc2::{class, msg_send}; -use log::info; #[link(name = "ApplicationServices", kind = "framework")] unsafe extern "C" { diff --git a/src/platform/macos/launching.rs b/src/platform/macos/launching.rs index 087bb02..e6d22a9 100644 --- a/src/platform/macos/launching.rs +++ b/src/platform/macos/launching.rs @@ -3,7 +3,10 @@ use std::sync::{Arc, Mutex}; use block2::RcBlock; use objc2_app_kit::{NSEvent, NSEventMask, NSEventModifierFlags, NSEventType}; -use crate::{app::{Message, tile::ExtSender}, platform::macos::accessibility::ensure_accessibility_permission}; +use crate::{ + app::{Message, tile::ExtSender}, + platform::macos::accessibility::ensure_accessibility_permission, +}; pub fn global_handler(sender: ExtSender) { ensure_accessibility_permission(); From 04927ded43a1b944ca20d1578c73335250b43292 Mon Sep 17 00:00:00 2001 From: unsecretised Date: Wed, 22 Apr 2026 13:18:41 +0800 Subject: [PATCH 5/5] change note and add credits --- src/platform/macos/accessibility.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platform/macos/accessibility.rs b/src/platform/macos/accessibility.rs index 2617a41..38b4b73 100644 --- a/src/platform/macos/accessibility.rs +++ b/src/platform/macos/accessibility.rs @@ -1,3 +1,4 @@ +/// Taken from: use std::ffi::c_void; use std::thread; use std::time::{Duration, Instant}; @@ -82,7 +83,7 @@ pub fn ensure_accessibility_permission() { } println!( - "Rift still does not have accessibility permission. Enable it in System Settings > Privacy & Security > Accessibility, then restart Rift." + "Rustcast still does not have accessibility permission. Enable it in System Settings > Privacy & Security > Accessibility, then restart Rustcast." ); std::process::exit(1);