Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 28 additions & 10 deletions platforms/macos/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ use objc2::{
};
use objc2_app_kit::*;
use objc2_foundation::{
ns_string, NSArray, NSCopying, NSInteger, NSNumber, NSObject, NSPoint, NSRange, NSRect,
NSString,
ns_string, NSArray, NSCopying, NSInteger, NSNumber, NSObject, NSObjectProtocol, NSPoint,
NSRange, NSRect, NSString,
};
use std::rc::{Rc, Weak};

Expand Down Expand Up @@ -357,6 +357,13 @@ impl NodeWrapper<'_> {
}
}

// derived from objc2 0.6 `AnyObject::downcast_ref`
// TODO: can be removed after updating objc2 to 0.6 which has `AnyObject::downcast_ref`
fn downcast_ref<T: ClassType>(obj: &NSObject) -> Option<&T> {
obj.is_kind_of::<T>()
.then(|| unsafe { &*(obj as *const NSObject).cast::<T>() })
}

pub(crate) struct PlatformNodeIvars {
context: Weak<Context>,
node_id: NodeId,
Expand Down Expand Up @@ -548,9 +555,24 @@ declare_class!(
}

#[method(setAccessibilityValue:)]
fn set_value(&self, _value: &NSObject) {
// This isn't yet implemented. See the comment on this selector
// in `is_selector_allowed`.
fn set_value(&self, value: &NSObject) {
if let Some(string) = downcast_ref::<NSString>(value) {
self.resolve_with_context(|node, context| {
context.do_action(ActionRequest {
action: Action::SetValue,
target: node.id(),
data: Some(ActionData::Value(string.to_string().into())),
});
});
} else if let Some(number) = downcast_ref::<NSNumber>(value) {
self.resolve_with_context(|node, context| {
context.do_action(ActionRequest {
action: Action::SetValue,
target: node.id(),
data: Some(ActionData::NumericValue(number.doubleValue())),
});
});
}
}

#[method_id(accessibilityMinValue)]
Expand Down Expand Up @@ -1024,11 +1046,7 @@ declare_class!(
return node.supports_text_ranges();
}
if selector == sel!(setAccessibilityValue:) {
// Our implementation of this currently does nothing,
// and it's not clear if VoiceOver ever actually uses it,
// but it must be allowed for editable text in order to get
// the expected VoiceOver behavior.
return node.supports_text_ranges() && !node.is_read_only();
return node.supports_action(Action::SetValue, &filter);
}
if selector == sel!(isAccessibilitySelected) {
let wrapper = NodeWrapper(node);
Expand Down