diff --git a/Cargo.lock b/Cargo.lock index a09c2dd1..6ce24b2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,9 +65,9 @@ dependencies = [ "accesskit", "accesskit_consumer", "hashbrown", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.6.2", + "objc2-app-kit 0.3.1", + "objc2-foundation 0.3.1", ] [[package]] @@ -429,7 +429,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "objc2", + "objc2 0.5.2", +] + +[[package]] +name = "block2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" +dependencies = [ + "objc2 0.6.2", ] [[package]] @@ -596,6 +605,16 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.2", +] + [[package]] name = "dlib" version = "0.5.2" @@ -1121,6 +1140,15 @@ dependencies = [ "objc2-encode", ] +[[package]] +name = "objc2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561f357ba7f3a2a61563a186a163d0a3a5247e1089524a3981d49adb775078bc" +dependencies = [ + "objc2-encode", +] + [[package]] name = "objc2-app-kit" version = "0.2.2" @@ -1128,13 +1156,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ "bitflags 2.8.0", - "block2", + "block2 0.5.1", + "libc", + "objc2 0.5.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", + "objc2-foundation 0.2.2", + "objc2-quartz-core 0.2.2", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" +dependencies = [ + "bitflags 2.8.0", + "block2 0.6.1", "libc", - "objc2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation", - "objc2-quartz-core", + "objc2 0.6.2", + "objc2-cloud-kit 0.3.1", + "objc2-core-data 0.3.1", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-image 0.3.1", + "objc2-foundation 0.3.1", + "objc2-quartz-core 0.3.1", ] [[package]] @@ -1144,10 +1191,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", + "block2 0.5.1", + "objc2 0.5.2", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.2", + "objc2-foundation 0.3.1", ] [[package]] @@ -1156,9 +1214,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" dependencies = [ - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -1168,9 +1226,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "objc2-core-data" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.2", + "objc2-foundation 0.3.1", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" +dependencies = [ + "bitflags 2.8.0", + "dispatch2", + "objc2 0.6.2", +] + +[[package]] +name = "objc2-core-graphics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" +dependencies = [ + "bitflags 2.8.0", + "dispatch2", + "objc2 0.6.2", + "objc2-core-foundation", + "objc2-io-surface", ] [[package]] @@ -1179,22 +1272,32 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", "objc2-metal", ] +[[package]] +name = "objc2-core-image" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e" +dependencies = [ + "objc2 0.6.2", + "objc2-foundation 0.3.1", +] + [[package]] name = "objc2-core-location" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" dependencies = [ - "block2", - "objc2", + "block2 0.5.1", + "objc2 0.5.2", "objc2-contacts", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -1210,10 +1313,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.8.0", - "block2", + "block2 0.5.1", "dispatch", "libc", - "objc2", + "objc2 0.5.2", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" +dependencies = [ + "bitflags 2.8.0", + "block2 0.6.1", + "libc", + "objc2 0.6.2", + "objc2-core-foundation", +] + +[[package]] +name = "objc2-io-surface" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.2", + "objc2-core-foundation", ] [[package]] @@ -1222,10 +1349,10 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" dependencies = [ - "block2", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -1235,9 +1362,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -1247,20 +1374,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", "objc2-metal", ] +[[package]] +name = "objc2-quartz-core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.2", + "objc2-foundation 0.3.1", +] + [[package]] name = "objc2-symbols" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" dependencies = [ - "objc2", - "objc2-foundation", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -1270,15 +1408,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", - "objc2-cloud-kit", - "objc2-core-data", - "objc2-core-image", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-cloud-kit 0.2.2", + "objc2-core-data 0.2.2", + "objc2-core-image 0.2.2", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", "objc2-link-presentation", - "objc2-quartz-core", + "objc2-quartz-core 0.2.2", "objc2-symbols", "objc2-uniform-type-identifiers", "objc2-user-notifications", @@ -1290,9 +1428,9 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" dependencies = [ - "block2", - "objc2", - "objc2-foundation", + "block2 0.5.1", + "objc2 0.5.2", + "objc2-foundation 0.2.2", ] [[package]] @@ -1302,10 +1440,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ "bitflags 2.8.0", - "block2", - "objc2", + "block2 0.5.1", + "objc2 0.5.2", "objc2-core-location", - "objc2-foundation", + "objc2-foundation 0.2.2", ] [[package]] @@ -2609,7 +2747,7 @@ dependencies = [ "android-activity", "atomic-waker", "bitflags 2.8.0", - "block2", + "block2 0.5.1", "bytemuck", "calloop", "cfg_aliases", @@ -2622,9 +2760,9 @@ dependencies = [ "libc", "memmap2", "ndk", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", "objc2-ui-kit", "orbclient", "percent-encoding", diff --git a/platforms/macos/Cargo.toml b/platforms/macos/Cargo.toml index 95b6c25d..71c8b323 100644 --- a/platforms/macos/Cargo.toml +++ b/platforms/macos/Cargo.toml @@ -18,14 +18,14 @@ default-target = "x86_64-apple-darwin" accesskit = { version = "0.21.0", path = "../../common" } accesskit_consumer = { version = "0.30.0", path = "../../consumer" } hashbrown = { version = "0.15", default-features = false, features = ["default-hasher"] } -objc2 = "0.5.1" -objc2-foundation = { version = "0.2.0", features = [ +objc2 = "0.6.2" +objc2-foundation = { version = "0.3.1", features = [ "NSArray", "NSDictionary", "NSValue", "NSThread", ] } -objc2-app-kit = { version = "0.2.0", features = [ +objc2-app-kit = { version = "0.3.1", features = [ "NSAccessibility", "NSAccessibilityConstants", "NSAccessibilityElement", diff --git a/platforms/macos/src/adapter.rs b/platforms/macos/src/adapter.rs index 2de5dbaf..52297d36 100644 --- a/platforms/macos/src/adapter.rs +++ b/platforms/macos/src/adapter.rs @@ -15,7 +15,7 @@ use accesskit::{ Tree as TreeData, TreeUpdate, }; use accesskit_consumer::{FilterResult, Tree}; -use objc2::rc::{Id, WeakId}; +use objc2::rc::{Retained, Weak}; use objc2_app_kit::NSView; use objc2_foundation::{MainThreadMarker, NSArray, NSObject, NSPoint}; use std::fmt::{Debug, Formatter}; @@ -25,7 +25,7 @@ const PLACEHOLDER_ROOT_ID: NodeId = NodeId(0); enum State { Inactive { - view: WeakId, + view: Weak, is_view_focused: bool, action_handler: Rc, mtm: MainThreadMarker, @@ -91,8 +91,8 @@ impl Adapter { is_view_focused: bool, action_handler: impl 'static + ActionHandler, ) -> Self { - let view = unsafe { Id::retain(view as *mut NSView) }.unwrap(); - let view = WeakId::from_id(&view); + let view = unsafe { Retained::retain(view as *mut NSView) }.unwrap(); + let view = Weak::from_retained(&view); let mtm = MainThreadMarker::new().unwrap(); let state = State::Inactive { view, @@ -231,20 +231,20 @@ impl Adapter { let state = tree.state(); let node = state.root(); let platform_nodes = if filter(&node) == FilterResult::Include { - vec![Id::into_super(Id::into_super( + vec![Retained::into_super(Retained::into_super( context.get_or_create_platform_node(node.id()), ))] } else { node.filtered_children(filter) .map(|node| { - Id::into_super(Id::into_super( + Retained::into_super(Retained::into_super( context.get_or_create_platform_node(node.id()), )) }) - .collect::>>() + .collect::>>() }; - let array = NSArray::from_vec(platform_nodes); - Id::autorelease_return(array) + let array = NSArray::from_retained_slice(&platform_nodes); + Retained::autorelease_return(array) } pub fn focus( @@ -256,14 +256,14 @@ impl Adapter { let state = tree.state(); if let Some(node) = state.focus() { if can_be_focused(&node) { - return Id::autorelease_return(context.get_or_create_platform_node(node.id())) + return Retained::autorelease_return(context.get_or_create_platform_node(node.id())) as *mut _; } } null_mut() } - fn weak_view(&self) -> &WeakId { + fn weak_view(&self) -> &Weak { match &self.state { State::Inactive { view, .. } => view, State::Placeholder { @@ -292,6 +292,6 @@ impl Adapter { let root = state.root(); let point = from_ns_point(&view, &root, point); let node = root.node_at_point(point, &filter).unwrap_or(root); - Id::autorelease_return(context.get_or_create_platform_node(node.id())) as *mut _ + Retained::autorelease_return(context.get_or_create_platform_node(node.id())) as *mut _ } } diff --git a/platforms/macos/src/context.rs b/platforms/macos/src/context.rs index b3d51fa2..ee87a4ff 100644 --- a/platforms/macos/src/context.rs +++ b/platforms/macos/src/context.rs @@ -7,7 +7,7 @@ use crate::node::PlatformNode; use accesskit::{ActionHandler, ActionRequest, NodeId}; use accesskit_consumer::Tree; use hashbrown::HashMap; -use objc2::rc::{Id, WeakId}; +use objc2::rc::{Retained, Weak}; use objc2_app_kit::*; use objc2_foundation::MainThreadMarker; use std::fmt::Debug; @@ -32,10 +32,10 @@ impl ActionHandlerNoMut for ActionHandlerWrapper { } pub(crate) struct Context { - pub(crate) view: WeakId, + pub(crate) view: Weak, pub(crate) tree: RefCell, pub(crate) action_handler: Rc, - platform_nodes: RefCell>>, + platform_nodes: RefCell>>, pub(crate) mtm: MainThreadMarker, } @@ -53,7 +53,7 @@ impl Debug for Context { impl Context { pub(crate) fn new( - view: WeakId, + view: Weak, tree: Tree, action_handler: Rc, mtm: MainThreadMarker, @@ -67,7 +67,10 @@ impl Context { }) } - pub(crate) fn get_or_create_platform_node(self: &Rc, id: NodeId) -> Id { + pub(crate) fn get_or_create_platform_node( + self: &Rc, + id: NodeId, + ) -> Retained { let mut platform_nodes = self.platform_nodes.borrow_mut(); if let Some(result) = platform_nodes.get(&id) { return result.clone(); @@ -78,7 +81,7 @@ impl Context { result } - pub(crate) fn remove_platform_node(&self, id: NodeId) -> Option> { + pub(crate) fn remove_platform_node(&self, id: NodeId) -> Option> { let mut platform_nodes = self.platform_nodes.borrow_mut(); platform_nodes.remove(&id) } diff --git a/platforms/macos/src/event.rs b/platforms/macos/src/event.rs index 6758b55e..036cc50e 100644 --- a/platforms/macos/src/event.rs +++ b/platforms/macos/src/event.rs @@ -36,9 +36,9 @@ impl QueuedEvent { Self::Announcement { text: node.value().unwrap(), priority: if node.live() == Live::Assertive { - NSAccessibilityPriorityLevel::NSAccessibilityPriorityHigh + NSAccessibilityPriorityLevel::High } else { - NSAccessibilityPriorityLevel::NSAccessibilityPriorityMedium + NSAccessibilityPriorityLevel::Medium }, } } @@ -77,7 +77,7 @@ impl QueuedEvent { } }; - let mut user_info = NSMutableDictionary::<_, AnyObject>::new(); + let user_info = NSMutableDictionary::<_, AnyObject>::new(); let text = NSString::from_str(&text); unsafe { user_info.setObject_forKey( diff --git a/platforms/macos/src/node.rs b/platforms/macos/src/node.rs index 29cc4fce..45be1c93 100644 --- a/platforms/macos/src/node.rs +++ b/platforms/macos/src/node.rs @@ -15,11 +15,10 @@ use accesskit::{ }; use accesskit_consumer::{FilterResult, Node}; use objc2::{ - declare_class, msg_send_id, - mutability::InteriorMutable, - rc::Id, + define_class, msg_send, + rc::Retained, runtime::{AnyObject, Sel}, - sel, ClassType, DeclaredClass, + sel, AnyThread, DeclaredClass, }; use objc2_app_kit::*; use objc2_foundation::{ @@ -357,32 +356,26 @@ impl NodeWrapper<'_> { } } +#[derive(Debug)] pub(crate) struct PlatformNodeIvars { context: Weak, node_id: NodeId, } -declare_class!( +define_class!( + #[unsafe(super(NSAccessibilityElement))] + #[derive(Debug)] + #[ivars = PlatformNodeIvars] + #[name = "AccessKitNode"] pub(crate) struct PlatformNode; - unsafe impl ClassType for PlatformNode { - #[inherits(NSObject)] - type Super = NSAccessibilityElement; - type Mutability = InteriorMutable; - const NAME: &'static str = "AccessKitNode"; - } - - impl DeclaredClass for PlatformNode { - type Ivars = PlatformNodeIvars; - } - - unsafe impl PlatformNode { - #[method_id(accessibilityParent)] - fn parent(&self) -> Option> { + impl PlatformNode { + #[unsafe(method_id(accessibilityParent))] + fn parent(&self) -> Option> { self.resolve_with_context(|node, context| { if let Some(parent) = node.filtered_parent(&filter) { - Some(Id::into_super(Id::into_super(Id::into_super(context.get_or_create_platform_node(parent.id()))))) + Some(Retained::into_super(Retained::into_super(Retained::into_super(context.get_or_create_platform_node(parent.id()))))) } else { context .view @@ -393,8 +386,8 @@ declare_class!( .flatten() } - #[method_id(accessibilityWindow)] - fn window(&self) -> Option> { + #[unsafe(method_id(accessibilityWindow))] + fn window(&self) -> Option> { self.resolve_with_context(|_, context| { context .view @@ -404,8 +397,8 @@ declare_class!( .flatten() } - #[method_id(accessibilityTopLevelUIElement)] - fn top_level(&self) -> Option> { + #[unsafe(method_id(accessibilityTopLevelUIElement))] + fn top_level(&self) -> Option> { self.resolve_with_context(|_, context| { context .view @@ -415,19 +408,19 @@ declare_class!( .flatten() } - #[method_id(accessibilityChildren)] - fn children(&self) -> Option>> { + #[unsafe(method_id(accessibilityChildren))] + fn children(&self) -> Option>> { self.children_internal() } - #[method_id(accessibilityChildrenInNavigationOrder)] - fn children_in_navigation_order(&self) -> Option>> { + #[unsafe(method_id(accessibilityChildrenInNavigationOrder))] + fn children_in_navigation_order(&self) -> Option>> { // For now, we assume the children are in navigation order. self.children_internal() } - #[method_id(accessibilitySelectedChildren)] - fn selected_children(&self) -> Option>> { + #[unsafe(method_id(accessibilitySelectedChildren))] + fn selected_children(&self) -> Option>> { self.resolve_with_context(|node, context| { let wrapper = NodeWrapper(node); if !wrapper.is_container_with_selectable_children() { @@ -437,13 +430,13 @@ declare_class!( .items(filter) .filter(|item| item.is_selected() == Some(true)) .map(|child| context.get_or_create_platform_node(child.id())) - .collect::>>(); - Some(NSArray::from_vec(platform_nodes)) + .collect::>>(); + Some(NSArray::from_retained_slice(&platform_nodes)) }) .flatten() } - #[method(accessibilityFrame)] + #[unsafe(method(accessibilityFrame))] fn frame(&self) -> NSRect { self.resolve_with_context(|node, context| { let view = match context.view.load() { @@ -467,42 +460,42 @@ declare_class!( .unwrap_or(NSRect::ZERO) } - #[method_id(accessibilityRole)] - fn role(&self) -> Id { + #[unsafe(method_id(accessibilityRole))] + fn role(&self) -> Retained { self.resolve(ns_role) .unwrap_or(unsafe { NSAccessibilityUnknownRole }) .copy() } - #[method_id(accessibilitySubrole)] - fn sub_role(&self) -> Id { + #[unsafe(method_id(accessibilitySubrole))] + fn sub_role(&self) -> Retained { self.resolve(ns_sub_role) .unwrap_or(unsafe { NSAccessibilityUnknownSubrole }) .copy() } - #[method_id(accessibilityRoleDescription)] - fn role_description(&self) -> Option> { + #[unsafe(method_id(accessibilityRoleDescription))] + fn role_description(&self) -> Option> { self.resolve(|node| { if let Some(role_description) = node.role_description() { Some(NSString::from_str(role_description)) } else { - unsafe { msg_send_id![super(self), accessibilityRoleDescription] } + unsafe { msg_send![super(self), accessibilityRoleDescription] } } }) .flatten() } - #[method_id(accessibilityIdentifier)] - fn identifier(&self) -> Option> { + #[unsafe(method_id(accessibilityIdentifier))] + fn identifier(&self) -> Option> { self.resolve(|node| { node.author_id().map(NSString::from_str) }) .flatten() } - #[method_id(accessibilityTitle)] - fn title(&self) -> Option> { + #[unsafe(method_id(accessibilityTitle))] + fn title(&self) -> Option> { self.resolve(|node| { let wrapper = NodeWrapper(node); wrapper.title().map(|title| NSString::from_str(&title)) @@ -510,8 +503,8 @@ declare_class!( .flatten() } - #[method_id(accessibilityHelp)] - fn description(&self) -> Option> { + #[unsafe(method_id(accessibilityHelp))] + fn description(&self) -> Option> { self.resolve(|node| { let wrapper = NodeWrapper(node); wrapper.description().map(|description| NSString::from_str(&description)) @@ -519,8 +512,8 @@ declare_class!( .flatten() } - #[method_id(accessibilityPlaceholderValue)] - fn placeholder(&self) -> Option> { + #[unsafe(method_id(accessibilityPlaceholderValue))] + fn placeholder(&self) -> Option> { self.resolve(|node| { let wrapper = NodeWrapper(node); wrapper.placeholder().map(NSString::from_str) @@ -528,48 +521,48 @@ declare_class!( .flatten() } - #[method_id(accessibilityValue)] - fn value(&self) -> Option> { + #[unsafe(method_id(accessibilityValue))] + fn value(&self) -> Option> { self.resolve(|node| { let wrapper = NodeWrapper(node); wrapper.value().map(|value| match value { Value::Bool(value) => { - Id::into_super(Id::into_super(NSNumber::new_bool(value))) + Retained::into_super(Retained::into_super(NSNumber::new_bool(value))) } Value::Number(value) => { - Id::into_super(Id::into_super(NSNumber::new_f64(value))) + Retained::into_super(Retained::into_super(NSNumber::new_f64(value))) } Value::String(value) => { - Id::into_super(NSString::from_str(&value)) + Retained::into_super(NSString::from_str(&value)) } }) }) .flatten() } - #[method(setAccessibilityValue:)] + #[unsafe(method(setAccessibilityValue:))] fn set_value(&self, _value: &NSObject) { // This isn't yet implemented. See the comment on this selector // in `is_selector_allowed`. } - #[method_id(accessibilityMinValue)] - fn min_value(&self) -> Option> { + #[unsafe(method_id(accessibilityMinValue))] + fn min_value(&self) -> Option> { self.resolve(|node| { node.min_numeric_value().map(NSNumber::new_f64) }) .flatten() } - #[method_id(accessibilityMaxValue)] - fn max_value(&self) -> Option> { + #[unsafe(method_id(accessibilityMaxValue))] + fn max_value(&self) -> Option> { self.resolve(|node| { node.max_numeric_value().map(NSNumber::new_f64) }) .flatten() } - #[method(accessibilityOrientation)] + #[unsafe(method(accessibilityOrientation))] fn orientation(&self) -> NSAccessibilityOrientation { self.resolve(|node| { match node.orientation() { @@ -581,24 +574,24 @@ declare_class!( .unwrap_or(NSAccessibilityOrientation::Unknown) } - #[method(isAccessibilityElement)] + #[unsafe(method(isAccessibilityElement))] fn is_accessibility_element(&self) -> bool { self.resolve(|node| filter(node) == FilterResult::Include) .unwrap_or(false) } - #[method(isAccessibilityFocused)] + #[unsafe(method(isAccessibilityFocused))] fn is_focused(&self) -> bool { self.resolve(|node| node.is_focused() && can_be_focused(node)) .unwrap_or(false) } - #[method(isAccessibilityEnabled)] + #[unsafe(method(isAccessibilityEnabled))] fn is_enabled(&self) -> bool { self.resolve(|node| !node.is_disabled()).unwrap_or(false) } - #[method(setAccessibilityFocused:)] + #[unsafe(method(setAccessibilityFocused:))] fn set_focused(&self, focused: bool) { self.resolve_with_context(|node, context| { if focused { @@ -622,7 +615,7 @@ declare_class!( }); } - #[method(accessibilityPerformPress)] + #[unsafe(method(accessibilityPerformPress))] fn press(&self) -> bool { self.resolve_with_context(|node, context| { let clickable = node.is_clickable(&filter); @@ -638,7 +631,7 @@ declare_class!( .unwrap_or(false) } - #[method(accessibilityPerformIncrement)] + #[unsafe(method(accessibilityPerformIncrement))] fn increment(&self) -> bool { self.resolve_with_context(|node, context| { let supports_increment = node.supports_increment(&filter); @@ -654,7 +647,7 @@ declare_class!( .unwrap_or(false) } - #[method(accessibilityPerformDecrement)] + #[unsafe(method(accessibilityPerformDecrement))] fn decrement(&self) -> bool { self.resolve_with_context(|node, context| { let supports_decrement = node.supports_decrement(&filter); @@ -670,12 +663,12 @@ declare_class!( .unwrap_or(false) } - #[method(accessibilityNotifiesWhenDestroyed)] + #[unsafe(method(accessibilityNotifiesWhenDestroyed))] fn notifies_when_destroyed(&self) -> bool { true } - #[method(accessibilityNumberOfCharacters)] + #[unsafe(method(accessibilityNumberOfCharacters))] fn number_of_characters(&self) -> NSInteger { self.resolve(|node| { if node.supports_text_ranges() { @@ -687,8 +680,8 @@ declare_class!( .unwrap_or(0) } - #[method_id(accessibilitySelectedText)] - fn selected_text(&self) -> Option> { + #[unsafe(method_id(accessibilitySelectedText))] + fn selected_text(&self) -> Option> { self.resolve(|node| { if node.supports_text_ranges() { if let Some(range) = node.text_selection() { @@ -701,7 +694,7 @@ declare_class!( .flatten() } - #[method(accessibilitySelectedTextRange)] + #[unsafe(method(accessibilitySelectedTextRange))] fn selected_text_range(&self) -> NSRange { self.resolve(|node| { if node.supports_text_ranges() { @@ -714,7 +707,7 @@ declare_class!( .unwrap_or_else(|| NSRange::new(0, 0)) } - #[method(accessibilityInsertionPointLineNumber)] + #[unsafe(method(accessibilityInsertionPointLineNumber))] fn insertion_point_line_number(&self) -> NSInteger { self.resolve(|node| { if node.supports_text_ranges() { @@ -727,7 +720,7 @@ declare_class!( .unwrap_or(0) } - #[method(accessibilityRangeForLine:)] + #[unsafe(method(accessibilityRangeForLine:))] fn range_for_line(&self, line_index: NSInteger) -> NSRange { self.resolve(|node| { if node.supports_text_ranges() && line_index >= 0 { @@ -740,7 +733,7 @@ declare_class!( .unwrap_or_else(|| NSRange::new(0, 0)) } - #[method(accessibilityRangeForPosition:)] + #[unsafe(method(accessibilityRangeForPosition:))] fn range_for_position(&self, point: NSPoint) -> NSRange { self.resolve_with_context(|node, context| { let view = match context.view.load() { @@ -760,8 +753,8 @@ declare_class!( .unwrap_or_else(|| NSRange::new(0, 0)) } - #[method_id(accessibilityStringForRange:)] - fn string_for_range(&self, range: NSRange) -> Option> { + #[unsafe(method_id(accessibilityStringForRange:))] + fn string_for_range(&self, range: NSRange) -> Option> { self.resolve(|node| { if node.supports_text_ranges() { if let Some(range) = from_ns_range(node, range) { @@ -774,7 +767,7 @@ declare_class!( .flatten() } - #[method(accessibilityFrameForRange:)] + #[unsafe(method(accessibilityFrameForRange:))] fn frame_for_range(&self, range: NSRange) -> NSRect { self.resolve_with_context(|node, context| { let view = match context.view.load() { @@ -799,7 +792,7 @@ declare_class!( .unwrap_or(NSRect::ZERO) } - #[method(accessibilityLineForIndex:)] + #[unsafe(method(accessibilityLineForIndex:))] fn line_for_index(&self, index: NSInteger) -> NSInteger { self.resolve(|node| { if node.supports_text_ranges() && index >= 0 { @@ -812,7 +805,7 @@ declare_class!( .unwrap_or(0) } - #[method(accessibilityRangeForIndex:)] + #[unsafe(method(accessibilityRangeForIndex:))] fn range_for_index(&self, index: NSInteger) -> NSRange { self.resolve(|node| { if node.supports_text_ranges() && index >= 0 { @@ -825,7 +818,7 @@ declare_class!( .unwrap_or_else(|| NSRange::new(0, 0)) } - #[method(setAccessibilitySelectedTextRange:)] + #[unsafe(method(setAccessibilitySelectedTextRange:))] fn set_selected_text_range(&self, range: NSRange) { self.resolve_with_context(|node, context| { if node.supports_text_ranges() { @@ -840,13 +833,13 @@ declare_class!( }); } - #[method(isAccessibilityRequired)] + #[unsafe(method(isAccessibilityRequired))] fn is_required(&self) -> bool { self.resolve(|node| node.is_required()) .unwrap_or(false) } - #[method(isAccessibilitySelected)] + #[unsafe(method(isAccessibilitySelected))] fn is_selected(&self) -> bool { self.resolve(|node| { let wrapper = NodeWrapper(node); @@ -857,7 +850,7 @@ declare_class!( .unwrap_or(false) } - #[method(setAccessibilitySelected:)] + #[unsafe(method(setAccessibilitySelected:))] fn set_selected(&self, selected: bool) { self.resolve_with_context(|node, context| { let wrapper = NodeWrapper(node); @@ -878,8 +871,8 @@ declare_class!( }); } - #[method_id(accessibilityRows)] - fn rows(&self) -> Option>> { + #[unsafe(method_id(accessibilityRows))] + fn rows(&self) -> Option>> { self.resolve_with_context(|node, context| { let wrapper = NodeWrapper(node); if !wrapper.is_container_with_selectable_children() { @@ -888,14 +881,14 @@ declare_class!( let platform_nodes = node .items(filter) .map(|child| context.get_or_create_platform_node(child.id())) - .collect::>>(); - Some(NSArray::from_vec(platform_nodes)) + .collect::>>(); + Some(NSArray::from_retained_slice(&platform_nodes)) }) .flatten() } - #[method_id(accessibilitySelectedRows)] - fn selected_rows(&self) -> Option>> { + #[unsafe(method_id(accessibilitySelectedRows))] + fn selected_rows(&self) -> Option>> { self.resolve_with_context(|node, context| { let wrapper = NodeWrapper(node); if !wrapper.is_container_with_selectable_children() { @@ -905,13 +898,13 @@ declare_class!( .items(filter) .filter(|item| item.is_selected() == Some(true)) .map(|child| context.get_or_create_platform_node(child.id())) - .collect::>>(); - Some(NSArray::from_vec(platform_nodes)) + .collect::>>(); + Some(NSArray::from_retained_slice(&platform_nodes)) }) .flatten() } - #[method(accessibilityPerformPick)] + #[unsafe(method(accessibilityPerformPick))] fn pick(&self) -> bool { self.resolve_with_context(|node, context| { let wrapper = NodeWrapper(node); @@ -930,10 +923,10 @@ declare_class!( .unwrap_or(false) } - #[method_id(accessibilityLinkedUIElements)] - fn linked_ui_elements(&self) -> Option>> { + #[unsafe(method_id(accessibilityLinkedUIElements))] + fn linked_ui_elements(&self) -> Option>> { self.resolve_with_context(|node, context| { - let platform_nodes: Vec> = node + let platform_nodes: Vec> = node .controls() .filter(|controlled| filter(controlled) == FilterResult::Include) .map(|controlled| context.get_or_create_platform_node(controlled.id())) @@ -941,14 +934,14 @@ declare_class!( if platform_nodes.is_empty() { None } else { - Some(NSArray::from_vec(platform_nodes)) + Some(NSArray::from_retained_slice(&platform_nodes)) } }) .flatten() } - #[method_id(accessibilityTabs)] - fn tabs(&self) -> Option>> { + #[unsafe(method_id(accessibilityTabs))] + fn tabs(&self) -> Option>> { self.resolve_with_context(|node, context| { if node.role() != Role::TabList { return None; @@ -957,8 +950,8 @@ declare_class!( .filtered_children(filter) .filter(|child| child.role() == Role::Tab) .map(|tab| context.get_or_create_platform_node(tab.id())) - .collect::>>(); - Some(NSArray::from_vec(platform_nodes)) + .collect::>>(); + Some(NSArray::from_retained_slice(&platform_nodes)) }) .flatten() } @@ -970,18 +963,18 @@ declare_class!( // of the legacy methods below only needs to cover actions not already // handled by the newer methods. - #[method_id(accessibilityActionNames)] - fn action_names(&self) -> Id> { + #[unsafe(method_id(accessibilityActionNames))] + fn action_names(&self) -> Retained> { let mut result = vec![]; self.resolve(|node| { if node.supports_action(Action::ScrollIntoView, &filter) { result.push(ns_string!(SCROLL_TO_VISIBLE_ACTION).copy()); } }); - NSArray::from_vec(result) + NSArray::from_retained_slice(&result) } - #[method(accessibilityPerformAction:)] + #[unsafe(method(accessibilityPerformAction:))] fn perform_action(&self, action: &NSString) { self.resolve_with_context(|node, context| { if action == ns_string!(SCROLL_TO_VISIBLE_ACTION) { @@ -994,7 +987,7 @@ declare_class!( }); } - #[method(isAccessibilitySelectorAllowed:)] + #[unsafe(method(isAccessibilitySelectorAllowed:))] fn is_selector_allowed(&self, selector: Sel) -> bool { self.resolve(|node| { if selector == sel!(setAccessibilityFocused:) { @@ -1085,10 +1078,10 @@ declare_class!( ); impl PlatformNode { - pub(crate) fn new(context: Weak, node_id: NodeId) -> Id { + pub(crate) fn new(context: Weak, node_id: NodeId) -> Retained { let this = Self::alloc().set_ivars(PlatformNodeIvars { context, node_id }); - unsafe { msg_send_id![super(this), init] } + unsafe { msg_send![super(this), init] } } fn resolve_with_context(&self, f: F) -> Option @@ -1109,13 +1102,13 @@ impl PlatformNode { self.resolve_with_context(|node, _| f(node)) } - fn children_internal(&self) -> Option>> { + fn children_internal(&self) -> Option>> { self.resolve_with_context(|node, context| { let platform_nodes = node .filtered_children(filter) .map(|child| context.get_or_create_platform_node(child.id())) - .collect::>>(); - NSArray::from_vec(platform_nodes) + .collect::>>(); + NSArray::from_retained_slice(&platform_nodes) }) } } diff --git a/platforms/macos/src/patch.rs b/platforms/macos/src/patch.rs index 68ada2a4..7ce926c8 100644 --- a/platforms/macos/src/patch.rs +++ b/platforms/macos/src/patch.rs @@ -7,11 +7,11 @@ use objc2::{ encode::{Encode, EncodeArguments, EncodeReturn, Encoding}, ffi::class_addMethod, msg_send, - runtime::{AnyClass, AnyObject, Bool, MethodImplementation, Sel}, + runtime::{AnyClass, AnyObject, MethodImplementation, Sel}, sel, Message, }; use objc2_app_kit::NSWindow; -use std::{ffi::CString, ptr::null_mut}; +use std::{ffi::CString, ptr::null_mut, str::FromStr}; extern "C" fn focus_forwarder(this: &NSWindow, _cmd: Sel) -> *mut AnyObject { unsafe { @@ -36,7 +36,7 @@ extern "C" fn focus_forwarder(this: &NSWindow, _cmd: Sel) -> *mut AnyObject { /// Also, this function assumes that the specified class is a subclass /// of `NSWindow`. pub unsafe fn add_focus_forwarder_to_window_class(class_name: &str) { - let class = AnyClass::get(class_name).unwrap(); + let class = AnyClass::get(&CString::from_str(class_name).unwrap()).unwrap(); unsafe { add_method( class as *const AnyClass as *mut AnyClass, @@ -66,19 +66,17 @@ where ); let types = method_type_encoding(&F::Return::ENCODING_RETURN, encs); - let success = Bool::from_raw(unsafe { - class_addMethod( - class as *mut _, - sel.as_ptr(), - Some(func.__imp()), - types.as_ptr(), - ) - }); + let success = unsafe { class_addMethod(class as *mut _, sel, func.__imp(), types.as_ptr()) }; assert!(success.as_bool(), "Failed to add method {sel:?}"); } fn count_args(sel: Sel) -> usize { - sel.name().chars().filter(|&c| c == ':').count() + sel.name() + .to_str() + .unwrap() + .chars() + .filter(|&c| c == ':') + .count() } fn method_type_encoding(ret: &Encoding, args: &[Encoding]) -> CString { diff --git a/platforms/macos/src/subclass.rs b/platforms/macos/src/subclass.rs index 9d5b194f..8b847ba5 100644 --- a/platforms/macos/src/subclass.rs +++ b/platforms/macos/src/subclass.rs @@ -6,20 +6,24 @@ use accesskit::{ActionHandler, ActivationHandler, TreeUpdate}; use objc2::{ declare::ClassBuilder, - declare_class, + define_class, ffi::{ objc_getAssociatedObject, objc_setAssociatedObject, object_setClass, OBJC_ASSOCIATION_RETAIN_NONATOMIC, }, - msg_send_id, - mutability::InteriorMutable, - rc::Id, + msg_send, + rc::Retained, runtime::{AnyClass, Sel}, - sel, ClassType, DeclaredClass, + sel, AnyThread, DeclaredClass, }; use objc2_app_kit::{NSView, NSWindow}; use objc2_foundation::{NSArray, NSObject, NSPoint}; -use std::{cell::RefCell, ffi::c_void, sync::Mutex}; +use std::{ + cell::RefCell, + ffi::{c_void, CString}, + str::FromStr, + sync::Mutex, +}; use crate::{event::QueuedEvents, Adapter}; @@ -41,33 +45,26 @@ struct AssociatedObjectIvars { prev_class: &'static AnyClass, } -declare_class!( +define_class! { + #[unsafe(super(NSObject))] + #[name = "AccessKitSubclassAssociatedObject"] + #[ivars = AssociatedObjectIvars] struct AssociatedObject; - - unsafe impl ClassType for AssociatedObject { - type Super = NSObject; - type Mutability = InteriorMutable; - const NAME: &'static str = "AccessKitSubclassAssociatedObject"; - } - - impl DeclaredClass for AssociatedObject { - type Ivars = AssociatedObjectIvars; - } -); +} impl AssociatedObject { fn new( adapter: Adapter, activation_handler: impl 'static + ActivationHandler, prev_class: &'static AnyClass, - ) -> Id { + ) -> Retained { let state = RefCell::new(AssociatedObjectState { adapter, activation_handler: Box::new(activation_handler), }); let this = Self::alloc().set_ivars(AssociatedObjectIvars { state, prev_class }); - unsafe { msg_send_id![super(this), init] } + unsafe { msg_send![super(this), init] } } } @@ -116,8 +113,8 @@ unsafe extern "C" fn hit_test(this: &NSView, _cmd: Sel, point: NSPoint) -> *mut /// Uses dynamic Objective-C subclassing to implement the `NSView` /// accessibility methods when normal subclassing isn't an option. pub struct SubclassingAdapter { - view: Id, - associated: Id, + view: Retained, + associated: Retained, } impl SubclassingAdapter { @@ -136,16 +133,16 @@ impl SubclassingAdapter { action_handler: impl 'static + ActionHandler, ) -> Self { let view = view as *mut NSView; - let retained_view = unsafe { Id::retain(view) }.unwrap(); + let retained_view = unsafe { Retained::retain(view) }.unwrap(); Self::new_internal(retained_view, activation_handler, action_handler) } fn new_internal( - retained_view: Id, + retained_view: Retained, activation_handler: impl 'static + ActivationHandler, action_handler: impl 'static + ActionHandler, ) -> Self { - let view = Id::as_ptr(&retained_view) as *mut NSView; + let view = Retained::as_ptr(&retained_view) as *mut NSView; if !unsafe { objc_getAssociatedObject(view as *const NSView as *const _, associated_object_key()) } @@ -163,7 +160,7 @@ impl SubclassingAdapter { objc_setAssociatedObject( view as *mut _, associated_object_key(), - Id::as_ptr(&associated) as *mut _, + Retained::as_ptr(&associated) as *mut _, OBJC_ASSOCIATION_RETAIN_NONATOMIC, ) }; @@ -171,8 +168,9 @@ impl SubclassingAdapter { let subclass = match subclasses.iter().find(|entry| entry.0 == prev_class) { Some(entry) => entry.1, None => { - let name = format!("AccessKitSubclassOf{}", prev_class.name()); - let mut builder = ClassBuilder::new(&name, prev_class).unwrap(); + let name = format!("AccessKitSubclassOf{}", prev_class.name().to_str().unwrap()); + let mut builder = + ClassBuilder::new(&CString::from_str(&name).unwrap(), prev_class).unwrap(); unsafe { builder.add_method( sel!(superclass), @@ -258,7 +256,7 @@ impl SubclassingAdapter { impl Drop for SubclassingAdapter { fn drop(&mut self) { let prev_class = self.associated.ivars().prev_class; - let view = Id::as_ptr(&self.view) as *mut NSView; + let view = Retained::as_ptr(&self.view) as *mut NSView; unsafe { object_setClass(view as *mut _, (prev_class as *const AnyClass).cast()) }; unsafe { objc_setAssociatedObject(