| Index: ui/accessibility/platform/ax_platform_node_mac.mm
|
| diff --git a/ui/accessibility/platform/ax_platform_node_mac.mm b/ui/accessibility/platform/ax_platform_node_mac.mm
|
| index 240240e6180bc11f40e56de4fa36fdafd9e65b81..7532f158966fa8cada5cc1043385cccc1791cb2b 100644
|
| --- a/ui/accessibility/platform/ax_platform_node_mac.mm
|
| +++ b/ui/accessibility/platform/ax_platform_node_mac.mm
|
| @@ -8,12 +8,16 @@
|
| #include <stddef.h>
|
|
|
| #include "base/macros.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "base/strings/sys_string_conversions.h"
|
| #include "ui/accessibility/ax_action_data.h"
|
| #include "ui/accessibility/ax_node_data.h"
|
| +#include "ui/accessibility/ax_node_position.h"
|
| +#include "ui/accessibility/ax_range.h"
|
| #include "ui/accessibility/ax_role_properties.h"
|
| #include "ui/accessibility/platform/ax_platform_node.h"
|
| #include "ui/accessibility/platform/ax_platform_node_delegate.h"
|
| +#import "ui/accessibility/platform/text_marker_helper_mac.h"
|
| #include "ui/base/l10n/l10n_util.h"
|
| #import "ui/gfx/mac/coordinate_conversion.h"
|
| #include "ui/strings/grit/ui_strings.h"
|
| @@ -221,21 +225,70 @@ EventMap BuildEventMap() {
|
| }
|
|
|
| void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
|
| + NSLog(@"Notify: %@, %@", target,
|
| + [AXPlatformNodeCocoa nativeNotificationFromAXEvent:event_type]);
|
| NSAccessibilityPostNotification(
|
| target, [AXPlatformNodeCocoa nativeNotificationFromAXEvent:event_type]);
|
| }
|
|
|
| } // namespace
|
|
|
| +namespace ui {
|
| +namespace {
|
| +
|
| +using AXNodePositionInstance = AXNodePosition::AXPositionInstance;
|
| +using AXNodeRange = AXRange<AXNodePositionInstance::element_type>;
|
| +
|
| +class NodePositionFactory : public ui::PositionFactory {
|
| + public:
|
| + explicit NodePositionFactory(AXPlatformNodeCocoa* node) : node_(node) {}
|
| +
|
| + ui::AXPositionPointer GetRoot() const override;
|
| + ui::AXRangePointer GetSelection() const override;
|
| + ui::AXPositionPointer GetFromData(
|
| + const ui::AXPositionData& data) const override;
|
| + id GetAccessibilityObject(const ui::AXPositionData& data) const override;
|
| +
|
| + private:
|
| + AXPlatformNodeCocoa* node_; // Weak. Transitively owns |this|.
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(NodePositionFactory);
|
| +};
|
| +
|
| +AXNodeRange CreateRangeFromTextMarkerRange(id marker_range) {
|
| + ui::AXPositionData start, end;
|
| + if (![TextMarkerHelperMac getRangeDataFromMarkerRange:marker_range
|
| + start:&start
|
| + end:&end]) {
|
| + return AXNodeRange();
|
| + }
|
| +
|
| + return AXNodeRange(AXNodePosition::CreateFromData(start),
|
| + AXNodePosition::CreateFromData(end));
|
| +}
|
| +
|
| +NSString* GetTextForTextMarkerRange(id marker_range) {
|
| + AXNodeRange range = CreateRangeFromTextMarkerRange(marker_range);
|
| + if (range.IsNull())
|
| + return nil;
|
| + return base::SysUTF16ToNSString(range.GetText());
|
| +}
|
| +
|
| +} // namespace
|
| +} // namespace ui
|
| +
|
| @interface AXPlatformNodeCocoa ()
|
| // Helper function for string attributes that don't require extra processing.
|
| - (NSString*)getStringAttribute:(ui::AXStringAttribute)attribute;
|
| // Returns AXValue, or nil if AXValue isn't an NSString.
|
| - (NSString*)getAXValueAsString;
|
| +// Lazily creates a TextMarkerHelper and returns it.
|
| +- (TextMarkerHelperMac*)textMarkerHelper;
|
| @end
|
|
|
| @implementation AXPlatformNodeCocoa {
|
| ui::AXPlatformNodeBase* node_; // Weak. Retains us.
|
| + base::scoped_nsobject<TextMarkerHelperMac> textMarkerHelper_;
|
| }
|
|
|
| @synthesize node = node_;
|
| @@ -274,6 +327,9 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
|
| NSAccessibilityPostNotification(
|
| self, NSAccessibilityUIElementDestroyedNotification);
|
| node_ = nil;
|
| +
|
| + // Nothing retains |textMarkerHelper_|, so this should always dealloc.
|
| + textMarkerHelper_.reset();
|
| }
|
|
|
| - (NSRect)boundsInScreen {
|
| @@ -294,6 +350,16 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
|
| return [value isKindOfClass:[NSString class]] ? value : nil;
|
| }
|
|
|
| +- (TextMarkerHelperMac*)textMarkerHelper {
|
| + if (!textMarkerHelper_ && node_) {
|
| + DLOG(INFO) << "bail";
|
| + return nil;
|
| + textMarkerHelper_.reset([[TextMarkerHelperMac alloc]
|
| + initWithFactory:base::MakeUnique<ui::NodePositionFactory>(self)]);
|
| + }
|
| + return textMarkerHelper_;
|
| +}
|
| +
|
| // NSAccessibility informal protocol implementation.
|
|
|
| - (BOOL)accessibilityIsIgnored {
|
| @@ -393,6 +459,8 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
|
| [axAttributes addObject:kTextAttributes];
|
| if (!node_->GetData().HasState(ui::AX_STATE_PROTECTED))
|
| [axAttributes addObjectsFromArray:kUnprotectedTextAttributes];
|
| + [axAttributes
|
| + addObjectsFromArray:[TextMarkerHelperMac getSupportedAttributes]];
|
| // Fallthrough.
|
| case ui::AX_ROLE_CHECK_BOX:
|
| case ui::AX_ROLE_COMBO_BOX:
|
| @@ -409,6 +477,32 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
|
| default:
|
| break;
|
| }
|
| + if (node_->GetData().role == ui::AX_ROLE_TEXT_FIELD) {
|
| + NSLog(@"%@ reports %@", [self AXValue], axAttributes.get());
|
| + }
|
| + return axAttributes.autorelease();
|
| +}
|
| +
|
| +- (NSArray*)accessibilityParameterizedAttributeNames {
|
| + static NSArray* const kEditableTextAttributes = [@[
|
| + NSAccessibilityLineForIndexParameterizedAttribute,
|
| + NSAccessibilityRangeForLineParameterizedAttribute,
|
| + NSAccessibilityStringForRangeParameterizedAttribute,
|
| + NSAccessibilityRangeForPositionParameterizedAttribute,
|
| + NSAccessibilityRangeForIndexParameterizedAttribute,
|
| + NSAccessibilityBoundsForRangeParameterizedAttribute,
|
| + NSAccessibilityRTFForRangeParameterizedAttribute,
|
| + NSAccessibilityAttributedStringForRangeParameterizedAttribute,
|
| + NSAccessibilityStyleRangeForIndexParameterizedAttribute,
|
| + ] retain];
|
| +
|
| + base::scoped_nsobject<NSMutableArray> axAttributes(
|
| + [[NSMutableArray alloc] init]);
|
| + [axAttributes addObjectsFromArray:kEditableTextAttributes];
|
| + [axAttributes
|
| + addObjectsFromArray:[TextMarkerHelperMac
|
| + getSupportedParameterizedAttributesExtended:YES]];
|
| + NSLog(@"PARAM!: %@ reports %@", [self AXValue], axAttributes.get());
|
| return axAttributes.autorelease();
|
| }
|
|
|
| @@ -489,8 +583,53 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
|
|
|
| - (id)accessibilityAttributeValue:(NSString*)attribute {
|
| SEL selector = NSSelectorFromString(attribute);
|
| + if ([TextMarkerHelperMac instancesRespondToSelector:selector]) {
|
| + DCHECK(![self respondsToSelector:selector]);
|
| + NSLog(@"supported: %@", attribute);
|
| + return [[self textMarkerHelper] performSelector:selector];
|
| + }
|
| + if ([self respondsToSelector:selector]) {
|
| + id result = [self performSelector:selector];
|
| + if (![attribute isEqualToString:@"AXRole"]) {
|
| + NSLog(@"Trying: %@ (%@) -> %@", attribute, [self AXValue], result);
|
| + }
|
| + return result;
|
| + }
|
| + NSLog(@"UNsupported: %@", attribute);
|
| + return nil;
|
| +}
|
| +
|
| +- (id)accessibilityAttributeValue:(NSString*)attribute
|
| + forParameter:(id)parameter {
|
| + SEL selector = NSSelectorFromString([attribute stringByAppendingString:@":"]);
|
| + DCHECK(selector);
|
| + NSLog(@"Trying: %@ for %@", attribute, parameter);
|
| + if ([TextMarkerHelperMac instancesRespondToSelector:selector]) {
|
| + DCHECK(![self respondsToSelector:selector]);
|
| + return
|
| + [[self textMarkerHelper] performSelector:selector withObject:parameter];
|
| + }
|
| +
|
| if ([self respondsToSelector:selector])
|
| - return [self performSelector:selector];
|
| + return [self performSelector:selector withObject:parameter];
|
| +
|
| + // TODO(tapted): Move these to TextMarkerHelper.
|
| + if ([attribute isEqualToString:@"AXStringForTextMarkerRange"])
|
| + return ui::GetTextForTextMarkerRange(parameter);
|
| +
|
| + if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"]) {
|
| + if (NSString* str = ui::GetTextForTextMarkerRange(parameter)) {
|
| + base::scoped_nsobject<NSAttributedString> attrString(
|
| + [[NSAttributedString alloc] initWithString:str]);
|
| + return attrString.autorelease();
|
| + }
|
| + }
|
| +
|
| + if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) {
|
| + NSString* text = ui::GetTextForTextMarkerRange(parameter);
|
| + return [NSNumber numberWithInt:[text length]];
|
| + }
|
| + NSLog(@"Usupported: %@ for %@", attribute, parameter);
|
| return nil;
|
| }
|
|
|
| @@ -533,6 +672,10 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
|
| return [self getStringAttribute:ui::AX_ATTR_DESCRIPTION];
|
| }
|
|
|
| +- (NSString*)AXDescription {
|
| + return [self getStringAttribute:ui::AX_ATTR_DESCRIPTION];
|
| +}
|
| +
|
| - (id)AXValue {
|
| switch (node_->GetData().role) {
|
| case ui::AX_ROLE_TAB:
|
| @@ -620,6 +763,10 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
|
| return [NSValue valueWithRange:{std::min(start, end), abs(end - start)}];
|
| }
|
|
|
| +- (NSArray*)AXSelectedTextRanges {
|
| + return @[ [self AXSelectedTextRange] ];
|
| +}
|
| +
|
| - (NSNumber*)AXNumberOfCharacters {
|
| return @([[self getAXValueAsString] length]);
|
| }
|
| @@ -633,6 +780,43 @@ void NotifyMacEvent(AXPlatformNodeCocoa* target, ui::AXEvent event_type) {
|
| return @0;
|
| }
|
|
|
| +- (id)AXStringForRange:(id)parameter {
|
| + DCHECK([parameter isKindOfClass:[NSValue class]]);
|
| + return [[self getAXValueAsString] substringWithRange:[parameter rangeValue]];
|
| +}
|
| +
|
| +- (id)AXAttributedStringForRange:(id)parameter {
|
| + base::scoped_nsobject<NSAttributedString> attributedString(
|
| + [[NSAttributedString alloc]
|
| + initWithString:[self AXStringForRange:parameter]]);
|
| + return attributedString.autorelease();
|
| +}
|
| +
|
| +- (id)AXRangeForLine:(id)parameter {
|
| + DCHECK([parameter isKindOfClass:[NSNumber class]]);
|
| + DCHECK_EQ(0, [parameter intValue]);
|
| + id r = [NSValue valueWithRange:{0, [[self getAXValueAsString] length]}];
|
| + NSLog(@"-> %@", r);
|
| + return r;
|
| +}
|
| +
|
| +- (id)AXLineForIndex:(id)parameter {
|
| + DCHECK([parameter isKindOfClass:[NSNumber class]]);
|
| + return @0;
|
| +}
|
| +
|
| +- (id)AXOwns {
|
| + return @[];
|
| +}
|
| +
|
| +- (id)AXSharedTextUIElements {
|
| + return @[ self ];
|
| +}
|
| +
|
| +- (id)AXSharedCharacterRange {
|
| + return [NSValue valueWithRange:{0, [[self getAXValueAsString] length]}];
|
| +}
|
| +
|
| @end
|
|
|
| namespace ui {
|
| @@ -693,4 +877,26 @@ int AXPlatformNodeMac::GetIndexInParent() {
|
| return -1;
|
| }
|
|
|
| +AXPositionPointer NodePositionFactory::GetRoot() const {
|
| + if (![node_ node])
|
| + return nullptr;
|
| +
|
| + return AXNodePosition::CreateTextPosition(1, [node_ node]->unique_id(), 0,
|
| + AX_TEXT_AFFINITY_DOWNSTREAM);
|
| +}
|
| +
|
| +AXRangePointer NodePositionFactory::GetSelection() const {
|
| + return AXRangePointer(nullptr, nullptr);
|
| +}
|
| +
|
| +AXPositionPointer NodePositionFactory::GetFromData(
|
| + const AXPositionData& data) const {
|
| + return AXNodePosition::CreateFromData(data);
|
| +}
|
| +
|
| +id NodePositionFactory::GetAccessibilityObject(
|
| + const AXPositionData& data) const {
|
| + return node_;
|
| +}
|
| +
|
| } // namespace ui
|
|
|