Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(953)

Side by Side Diff: ui/accessibility/platform/ax_platform_node_mac.mm

Issue 2684203002: MacViews/a11y: Allow accessibility clients to set new selections in Textfields. (Closed)
Patch Set: Rebase. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ui/views/widget/native_widget_mac_accessibility_unittest.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ui/accessibility/platform/ax_platform_node_mac.h" 5 #import "ui/accessibility/platform/ax_platform_node_mac.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include "base/macros.h" 10 #include "base/macros.h"
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 [axAttributes addObjectsFromArray:kValueAttributes]; 385 [axAttributes addObjectsFromArray:kValueAttributes];
386 break; 386 break;
387 // TODO(tapted): Add additional attributes based on role. 387 // TODO(tapted): Add additional attributes based on role.
388 default: 388 default:
389 break; 389 break;
390 } 390 }
391 return axAttributes.autorelease(); 391 return axAttributes.autorelease();
392 } 392 }
393 393
394 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName { 394 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName {
395 if (node_->GetData().HasStateFlag(ui::AX_STATE_DISABLED))
396 return NO;
397
395 // Allow certain attributes to be written via an accessibility client. A 398 // Allow certain attributes to be written via an accessibility client. A
396 // writable attribute will only appear as such if the accessibility element 399 // writable attribute will only appear as such if the accessibility element
397 // has a value set for that attribute. 400 // has a value set for that attribute.
398 if ([attributeName 401 if ([attributeName
399 isEqualToString:NSAccessibilitySelectedChildrenAttribute] || 402 isEqualToString:NSAccessibilitySelectedChildrenAttribute] ||
400 [attributeName 403 [attributeName
401 isEqualToString:NSAccessibilitySelectedTextRangeAttribute] ||
402 [attributeName
403 isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) { 404 isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
404 return NO; 405 return NO;
405 } 406 }
406 407
407 // Since tabs use the Radio Button role on Mac, the standard way to set them 408 // Since tabs use the Radio Button role on Mac, the standard way to set them
408 // is via the value attribute rather than the selected attribute. 409 // is via the value attribute rather than the selected attribute.
409 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] && 410 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] &&
410 node_->GetData().role == ui::AX_ROLE_TAB) { 411 node_->GetData().role == ui::AX_ROLE_TAB) {
411 return !node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED); 412 return !node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED);
412 } 413 }
413 414
414 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] || 415 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] ||
415 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute]) { 416 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute] ||
417 [attributeName
418 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
416 return !ui::AXNodeData::IsFlagSet(node_->GetData().state, 419 return !ui::AXNodeData::IsFlagSet(node_->GetData().state,
417 ui::AX_STATE_READ_ONLY); 420 ui::AX_STATE_READ_ONLY);
418 } 421 }
419 422
420 if ([attributeName isEqualToString:NSAccessibilityFocusedAttribute]) { 423 if ([attributeName isEqualToString:NSAccessibilityFocusedAttribute]) {
421 return ui::AXNodeData::IsFlagSet(node_->GetData().state, 424 return ui::AXNodeData::IsFlagSet(node_->GetData().state,
422 ui::AX_STATE_FOCUSABLE); 425 ui::AX_STATE_FOCUSABLE);
423 } 426 }
424 427
425 // TODO(patricialor): Add callbacks for updating the above attributes except 428 // TODO(patricialor): Add callbacks for updating the above attributes except
426 // NSAccessibilityValueAttribute and return YES. 429 // NSAccessibilityValueAttribute and return YES.
427 return NO; 430 return NO;
428 } 431 }
429 432
430 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute { 433 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute {
431 ui::AXActionData data; 434 ui::AXActionData data;
432 435
433 // Check for attributes first. Only the |data.action| should be set here - any 436 // Check for attributes first. Only the |data.action| should be set here - any
434 // type-specific information, if needed, should be set below. 437 // type-specific information, if needed, should be set below.
435 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { 438 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
436 data.action = node_->GetData().role == ui::AX_ROLE_TAB 439 data.action = node_->GetData().role == ui::AX_ROLE_TAB
437 ? ui::AX_ACTION_SET_SELECTION 440 ? ui::AX_ACTION_SET_SELECTION
438 : ui::AX_ACTION_SET_VALUE; 441 : ui::AX_ACTION_SET_VALUE;
439 } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) { 442 } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
440 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT; 443 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT;
444 } else if ([attribute
445 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
446 data.action = ui::AX_ACTION_SET_SELECTION;
441 } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { 447 } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
442 if ([value isKindOfClass:[NSNumber class]]) { 448 if ([value isKindOfClass:[NSNumber class]]) {
443 data.action = 449 data.action =
444 [value boolValue] ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR; 450 [value boolValue] ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR;
445 } 451 }
446 } 452 }
447 453
448 // Set type-specific information as necessary for actions set above. 454 // Set type-specific information as necessary for actions set above.
449 if ([value isKindOfClass:[NSString class]]) 455 if ([value isKindOfClass:[NSString class]]) {
450 data.value = base::SysNSStringToUTF16(value); 456 data.value = base::SysNSStringToUTF16(value);
457 } else if (data.action == ui::AX_ACTION_SET_SELECTION &&
458 [value isKindOfClass:[NSValue class]]) {
459 NSRange range = [value rangeValue];
460 data.anchor_offset = range.location;
461 data.focus_offset = NSMaxRange(range);
462 }
451 463
452 if (data.action != ui::AX_ACTION_NONE) 464 if (data.action != ui::AX_ACTION_NONE)
453 node_->GetDelegate()->AccessibilityPerformAction(data); 465 node_->GetDelegate()->AccessibilityPerformAction(data);
454 466
455 // TODO(patricialor): Plumb through all the other writable attributes as 467 // TODO(patricialor): Plumb through all the other writable attributes as
456 // specified in accessibilityIsAttributeSettable. 468 // specified in accessibilityIsAttributeSettable.
457 } 469 }
458 470
459 - (id)accessibilityAttributeValue:(NSString*)attribute { 471 - (id)accessibilityAttributeValue:(NSString*)attribute {
460 SEL selector = NSSelectorFromString(attribute); 472 SEL selector = NSSelectorFromString(attribute);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 return [self getStringAttribute:ui::AX_ATTR_DESCRIPTION]; 515 return [self getStringAttribute:ui::AX_ATTR_DESCRIPTION];
504 } 516 }
505 517
506 - (id)AXValue { 518 - (id)AXValue {
507 if (node_->GetData().role == ui::AX_ROLE_TAB) 519 if (node_->GetData().role == ui::AX_ROLE_TAB)
508 return [self AXSelected]; 520 return [self AXSelected];
509 return [self getStringAttribute:ui::AX_ATTR_VALUE]; 521 return [self getStringAttribute:ui::AX_ATTR_VALUE];
510 } 522 }
511 523
512 - (NSNumber*)AXEnabled { 524 - (NSNumber*)AXEnabled {
513 return [NSNumber 525 return @(!ui::AXNodeData::IsFlagSet(node_->GetData().state,
514 numberWithBool:!ui::AXNodeData::IsFlagSet(node_->GetData().state, 526 ui::AX_STATE_DISABLED));
515 ui::AX_STATE_DISABLED)];
516 } 527 }
517 528
518 - (NSNumber*)AXFocused { 529 - (NSNumber*)AXFocused {
519 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, 530 if (ui::AXNodeData::IsFlagSet(node_->GetData().state,
520 ui::AX_STATE_FOCUSABLE)) 531 ui::AX_STATE_FOCUSABLE))
521 return [NSNumber numberWithBool:(node_->GetDelegate()->GetFocus() == 532 return
522 node_->GetNativeViewAccessible())]; 533 @(node_->GetDelegate()->GetFocus() == node_->GetNativeViewAccessible());
523 return [NSNumber numberWithBool:NO]; 534 return @NO;
524 } 535 }
525 536
526 - (id)AXParent { 537 - (id)AXParent {
527 if (!node_) 538 if (!node_)
528 return nil; 539 return nil;
529 return NSAccessibilityUnignoredAncestor(node_->GetParent()); 540 return NSAccessibilityUnignoredAncestor(node_->GetParent());
530 } 541 }
531 542
532 - (NSArray*)AXChildren { 543 - (NSArray*)AXChildren {
533 if (!node_) 544 if (!node_)
(...skipping 21 matching lines...) Expand all
555 return [NSValue valueWithSize:self.boundsInScreen.size]; 566 return [NSValue valueWithSize:self.boundsInScreen.size];
556 } 567 }
557 568
558 - (NSString*)AXTitle { 569 - (NSString*)AXTitle {
559 return [self getStringAttribute:ui::AX_ATTR_NAME]; 570 return [self getStringAttribute:ui::AX_ATTR_NAME];
560 } 571 }
561 572
562 // Misc attributes. 573 // Misc attributes.
563 574
564 - (NSNumber*)AXSelected { 575 - (NSNumber*)AXSelected {
565 return [NSNumber 576 return @(node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED));
566 numberWithBool:node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED)];
567 } 577 }
568 578
569 - (NSString*)AXPlaceholderValue { 579 - (NSString*)AXPlaceholderValue {
570 return [self getStringAttribute:ui::AX_ATTR_PLACEHOLDER]; 580 return [self getStringAttribute:ui::AX_ATTR_PLACEHOLDER];
571 } 581 }
572 582
573 // Text-specific attributes. 583 // Text-specific attributes.
574 584
575 - (NSString*)AXSelectedText { 585 - (NSString*)AXSelectedText {
576 NSRange selectedTextRange; 586 NSRange selectedTextRange;
577 [[self AXSelectedTextRange] getValue:&selectedTextRange]; 587 [[self AXSelectedTextRange] getValue:&selectedTextRange];
578 return [[self AXValue] substringWithRange:selectedTextRange]; 588 return [[self AXValue] substringWithRange:selectedTextRange];
579 } 589 }
580 590
581 - (NSValue*)AXSelectedTextRange { 591 - (NSValue*)AXSelectedTextRange {
582 int textDir, start, end; 592 int textDir, start, end;
583 node_->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, &textDir); 593 node_->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, &textDir);
584 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &start); 594 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &start);
585 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &end); 595 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &end);
586 // NSRange cannot represent the direction the text was selected in, so make 596 // NSRange cannot represent the direction the text was selected in, so make
587 // sure the correct selection index is used when creating a new range, taking 597 // sure the correct selection index is used when creating a new range, taking
588 // into account the textfield text direction as well. 598 // into account the textfield text direction as well.
589 bool isReversed = (textDir == ui::AX_TEXT_DIRECTION_RTL) || 599 bool isReversed = (textDir == ui::AX_TEXT_DIRECTION_RTL) ||
590 (textDir == ui::AX_TEXT_DIRECTION_BTT); 600 (textDir == ui::AX_TEXT_DIRECTION_BTT);
591 int beginSelectionIndex = (end > start && !isReversed) ? start : end; 601 int beginSelectionIndex = (end > start && !isReversed) ? start : end;
592 return [NSValue 602 return [NSValue valueWithRange:{beginSelectionIndex, abs(end - start)}];
593 valueWithRange:NSMakeRange(beginSelectionIndex, abs(end - start))];
594 } 603 }
595 604
596 - (NSNumber*)AXNumberOfCharacters { 605 - (NSNumber*)AXNumberOfCharacters {
597 return [NSNumber numberWithInteger:[[self AXValue] length]]; 606 return @([[self AXValue] length]);
598 } 607 }
599 608
600 - (NSValue*)AXVisibleCharacterRange { 609 - (NSValue*)AXVisibleCharacterRange {
601 return [NSValue 610 return [NSValue valueWithRange:{0, [[self AXNumberOfCharacters] intValue]}];
602 valueWithRange:NSMakeRange(0, [[self AXNumberOfCharacters] intValue])];
603 } 611 }
604 612
605 - (NSNumber*)AXInsertionPointLineNumber { 613 - (NSNumber*)AXInsertionPointLineNumber {
606 // Multiline is not supported on views. 614 // Multiline is not supported on views.
607 return [NSNumber numberWithInteger:0]; 615 return @0;
608 } 616 }
609 617
610 @end 618 @end
611 619
612 namespace ui { 620 namespace ui {
613 621
614 // static 622 // static
615 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) { 623 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
616 AXPlatformNodeBase* node = new AXPlatformNodeMac(); 624 AXPlatformNodeBase* node = new AXPlatformNodeMac();
617 node->Init(delegate); 625 node->Init(delegate);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 } 661 }
654 NotifyMacEvent(native_node_, event_type); 662 NotifyMacEvent(native_node_, event_type);
655 } 663 }
656 664
657 int AXPlatformNodeMac::GetIndexInParent() { 665 int AXPlatformNodeMac::GetIndexInParent() {
658 // TODO(dmazzoni): implement this. http://crbug.com/396137 666 // TODO(dmazzoni): implement this. http://crbug.com/396137
659 return -1; 667 return -1;
660 } 668 }
661 669
662 } // namespace ui 670 } // namespace ui
OLDNEW
« no previous file with comments | « no previous file | ui/views/widget/native_widget_mac_accessibility_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698