diff --git a/Cargo.lock b/Cargo.lock index 71a1426d..707f8450 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ "accesskit", "accesskit_consumer", "hashbrown", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.6.0", + "objc2-app-kit 0.3.0", + "objc2-foundation 0.3.0", ] [[package]] @@ -143,7 +143,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.4.1", + "bitflags 2.8.0", "cc", "cesu8", "jni", @@ -410,9 +410,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "block-buffer" @@ -429,7 +429,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43ff7d91d3c1d568065b06c899777d1e48dcf76103a672a0adbc238a7f247f1e" dependencies = [ - "objc2", + "objc2 0.5.1", ] [[package]] @@ -469,7 +469,7 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b50b5a44d59a98c55a9eeb518f39bf7499ba19fd98ee7d22618687f3f10adbf" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "log", "polling", "rustix", @@ -1015,7 +1015,7 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "libc", "redox_syscall 0.4.1", ] @@ -1111,7 +1111,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "jni-sys", "log", "ndk-sys", @@ -1155,7 +1155,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "cfg-if", "cfg_aliases", "libc", @@ -1209,6 +1209,15 @@ dependencies = [ "objc2-encode", ] +[[package]] +name = "objc2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3531f65190d9cff863b77a99857e74c314dd16bf56c538c4b57c7cbc3f3a6e59" +dependencies = [ + "objc2-encode", +] + [[package]] name = "objc2-app-kit" version = "0.2.0" @@ -1216,9 +1225,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb79768a710a9a1798848179edb186d1af7e8a8679f369e4b8d201dd2a034047" dependencies = [ "block2", - "objc2", + "objc2 0.5.1", "objc2-core-data", - "objc2-foundation", + "objc2-foundation 0.2.0", +] + +[[package]] +name = "objc2-app-kit" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5906f93257178e2f7ae069efb89fbd6ee94f0592740b5f8a1512ca498814d0fb" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.0", + "objc2-core-foundation", + "objc2-foundation 0.3.0", ] [[package]] @@ -1228,15 +1249,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e092bc42eaf30a08844e6a076938c60751225ec81431ab89f5d1ccd9f958d6c" dependencies = [ "block2", - "objc2", - "objc2-foundation", + "objc2 0.5.1", + "objc2-foundation 0.2.0", +] + +[[package]] +name = "objc2-core-foundation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daeaf60f25471d26948a1c2f840e3f7d86f4109e3af4e8e4b5cd70c39690d925" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.0", ] [[package]] name = "objc2-encode" -version = "4.0.1" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88658da63e4cc2c8adb1262902cd6af51094df0488b760d6fd27194269c0950a" +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] name = "objc2-foundation" @@ -1246,7 +1277,18 @@ checksum = "cfaefe14254871ea16c7d88968c0ff14ba554712a20d76421eec52f0a7fb8904" dependencies = [ "block2", "dispatch", - "objc2", + "objc2 0.5.1", +] + +[[package]] +name = "objc2-foundation" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a21c6c9014b82c39515db5b396f91645182611c97d24637cf56ac01e5f8d998" +dependencies = [ + "bitflags 2.8.0", + "objc2 0.6.0", + "objc2-core-foundation", ] [[package]] @@ -1572,7 +1614,7 @@ version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "errno", "libc", "linux-raw-sys", @@ -1737,7 +1779,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60e3d9941fa3bacf7c2bf4b065304faa14164151254cd16ce1b1bc8fc381600f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "calloop", "calloop-wayland-source", "cursor-icon", @@ -2099,7 +2141,7 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ca7d52347346f5473bf2f56705f360e8440873052e575e55890c4fa57843ed3" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "nix 0.26.2", "wayland-backend", "wayland-scanner", @@ -2111,7 +2153,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "cursor-icon", "wayland-backend", ] @@ -2133,7 +2175,7 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e253d7107ba913923dc253967f35e8561a3c65f914543e46843c88ddd729e21c" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -2145,7 +2187,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2158,7 +2200,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2526,7 +2568,7 @@ dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.4.1", + "bitflags 2.8.0", "bytemuck", "calloop", "cfg_aliases", @@ -2539,9 +2581,9 @@ dependencies = [ "libc", "memmap2", "ndk", - "objc2", - "objc2-app-kit", - "objc2-foundation", + "objc2 0.5.1", + "objc2-app-kit 0.2.0", + "objc2-foundation 0.2.0", "orbclient", "percent-encoding", "pin-project", @@ -2634,7 +2676,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.8.0", "dlib", "log", "once_cell", diff --git a/platforms/macos/Cargo.toml b/platforms/macos/Cargo.toml index 2af0abf6..2b6e5b21 100644 --- a/platforms/macos/Cargo.toml +++ b/platforms/macos/Cargo.toml @@ -18,14 +18,15 @@ default-target = "x86_64-apple-darwin" accesskit = { version = "0.17.1", path = "../../common" } accesskit_consumer = { version = "0.26.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 = { version = "0.6", default-features = false } +objc2-foundation = { version = "0.3", default-features = false, features = [ "NSArray", "NSDictionary", "NSValue", "NSThread", ] } -objc2-app-kit = { version = "0.2.0", features = [ +objc2-app-kit = { version = "0.3", default-features = false, features = [ + "objc2-core-foundation", "NSAccessibility", "NSAccessibilityConstants", "NSAccessibilityElement", diff --git a/platforms/macos/src/adapter.rs b/platforms/macos/src/adapter.rs index 2bd942bb..54971890 100644 --- a/platforms/macos/src/adapter.rs +++ b/platforms/macos/src/adapter.rs @@ -8,7 +8,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::{ffi::c_void, ptr::null_mut, rc::Rc}; @@ -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, @@ -62,8 +62,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, @@ -202,20 +202,22 @@ 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( - context.get_or_create_platform_node(node.id()), - ))] + vec![context + .get_or_create_platform_node(node.id()) + .into_super() + .into_super()] } else { node.filtered_children(filter) .map(|node| { - Id::into_super(Id::into_super( - context.get_or_create_platform_node(node.id()), - )) + context + .get_or_create_platform_node(node.id()) + .into_super() + .into_super() }) - .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( @@ -227,14 +229,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 { @@ -263,6 +265,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 ad4c3251..833fb776 100644 --- a/platforms/macos/src/context.rs +++ b/platforms/macos/src/context.rs @@ -6,7 +6,7 @@ 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::{cell::RefCell, rc::Rc}; @@ -32,16 +32,16 @@ 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, } impl Context { pub(crate) fn new( - view: WeakId, + view: Weak, tree: Tree, action_handler: Rc, mtm: MainThreadMarker, @@ -55,7 +55,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(); @@ -66,7 +69,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 2bb851ea..15e0df2d 100644 --- a/platforms/macos/src/event.rs +++ b/platforms/macos/src/event.rs @@ -32,9 +32,9 @@ impl QueuedEvent { Self::Announcement { text: node.value().unwrap(), priority: if node.live() == Live::Assertive { - NSAccessibilityPriorityLevel::NSAccessibilityPriorityHigh + NSAccessibilityPriorityLevel::High } else { - NSAccessibilityPriorityLevel::NSAccessibilityPriorityMedium + NSAccessibilityPriorityLevel::Medium }, } } @@ -73,7 +73,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 6c336432..a20d6873 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, AllocAnyThread, DeclaredClass, }; use objc2_app_kit::*; use objc2_foundation::{ @@ -347,26 +346,18 @@ pub(crate) struct PlatformNodeIvars { node_id: NodeId, } -declare_class!( +define_class!( + #[unsafe(super(NSAccessibilityElement))] + #[name = "AccessKitNode"] + #[ivars = PlatformNodeIvars] 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(context.get_or_create_platform_node(parent.id()).into_super().into_super().into_super()) } else { context .view @@ -377,8 +368,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 @@ -388,8 +379,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 @@ -399,18 +390,18 @@ 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(accessibilityFrame)] + #[unsafe(method(accessibilityFrame))] fn frame(&self) -> NSRect { self.resolve_with_context(|node, context| { let view = match context.view.load() { @@ -434,42 +425,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)) @@ -477,8 +468,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)) @@ -486,8 +477,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) @@ -495,48 +486,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))) + NSNumber::new_bool(value).into_super().into_super() } Value::Number(value) => { - Id::into_super(Id::into_super(NSNumber::new_f64(value))) + NSNumber::new_f64(value).into_super().into_super() } Value::String(value) => { - Id::into_super(NSString::from_str(&value)) + NSString::from_str(&value).into_super() } }) }) .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() { @@ -548,24 +539,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 { @@ -589,7 +580,7 @@ declare_class!( }); } - #[method(accessibilityPerformPress)] + #[unsafe(method(accessibilityPerformPress))] fn press(&self) -> bool { self.resolve_with_context(|node, context| { let clickable = node.is_clickable(); @@ -605,7 +596,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(); @@ -621,7 +612,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(); @@ -637,12 +628,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() { @@ -654,8 +645,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() { @@ -668,7 +659,7 @@ declare_class!( .flatten() } - #[method(accessibilitySelectedTextRange)] + #[unsafe(method(accessibilitySelectedTextRange))] fn selected_text_range(&self) -> NSRange { self.resolve(|node| { if node.supports_text_ranges() { @@ -681,7 +672,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() { @@ -694,7 +685,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 { @@ -707,7 +698,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() { @@ -727,8 +718,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) { @@ -741,7 +732,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() { @@ -766,7 +757,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 { @@ -779,7 +770,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 { @@ -792,7 +783,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() { @@ -807,13 +798,13 @@ declare_class!( }); } - #[method(isAccessibilityRequired)] + #[unsafe(method(isAccessibilityRequired))] fn is_required(&self) -> bool { self.resolve(|node| node.is_required()) .unwrap_or(false) } - #[method(isAccessibilitySelectorAllowed:)] + #[unsafe(method(isAccessibilitySelectorAllowed:))] fn is_selector_allowed(&self, selector: Sel) -> bool { self.resolve(|node| { if selector == sel!(setAccessibilityFocused:) { @@ -879,10 +870,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 @@ -903,13 +894,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 2dab00f2..e1f99d2c 100644 --- a/platforms/macos/src/patch.rs +++ b/platforms/macos/src/patch.rs @@ -7,7 +7,7 @@ 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; @@ -36,7 +36,8 @@ 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_name = CString::new(class_name).unwrap(); + let class = AnyClass::get(&class_name).unwrap(); unsafe { add_method( class as *const AnyClass as *mut AnyClass, @@ -66,19 +67,12 @@ 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_bytes().iter().filter(|&&b| b == b':').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 0b9a2d53..2e5d608b 100644 --- a/platforms/macos/src/subclass.rs +++ b/platforms/macos/src/subclass.rs @@ -6,20 +6,23 @@ 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, AllocAnyThread, 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, CStr}, + sync::Mutex, +}; use crate::{event::QueuedEvents, Adapter}; @@ -41,18 +44,11 @@ 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 { @@ -60,14 +56,14 @@ impl AssociatedObject { 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 +112,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 +132,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; let adapter = unsafe { Adapter::new(view as *mut c_void, false, action_handler) }; // Cast to a pointer and back to force the lifetime to 'static // SAFETY: We know the class will live as long as the instance, @@ -156,7 +152,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, ) }; @@ -164,8 +160,10 @@ 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 mut name_bytes = Vec::from("AccessKitSubclassOf".as_bytes()); + name_bytes.extend_from_slice(prev_class.name().to_bytes_with_nul()); + let name = CStr::from_bytes_with_nul(&name_bytes).unwrap(); + let mut builder = ClassBuilder::new(name, prev_class).unwrap(); unsafe { builder.add_method( sel!(superclass), @@ -251,7 +249,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(