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

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: Update to allow selection range changes when read-only. 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
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 352 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 [axAttributes addObjectsFromArray:kValueAttributes]; 363 [axAttributes addObjectsFromArray:kValueAttributes];
364 break; 364 break;
365 // TODO(tapted): Add additional attributes based on role. 365 // TODO(tapted): Add additional attributes based on role.
366 default: 366 default:
367 break; 367 break;
368 } 368 }
369 return axAttributes.autorelease(); 369 return axAttributes.autorelease();
370 } 370 }
371 371
372 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName { 372 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName {
373 if (node_->GetData().HasStateFlag(ui::AX_STATE_DISABLED))
374 return NO;
375
373 // Allow certain attributes to be written via an accessibility client. A 376 // Allow certain attributes to be written via an accessibility client. A
374 // writable attribute will only appear as such if the accessibility element 377 // writable attribute will only appear as such if the accessibility element
375 // has a value set for that attribute. 378 // has a value set for that attribute.
376 if ([attributeName 379 if ([attributeName
377 isEqualToString:NSAccessibilitySelectedChildrenAttribute] || 380 isEqualToString:NSAccessibilitySelectedChildrenAttribute] ||
378 [attributeName 381 [attributeName
379 isEqualToString:NSAccessibilitySelectedTextRangeAttribute] ||
380 [attributeName
381 isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) { 382 isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) {
382 return NO; 383 return NO;
383 } 384 }
384 385
386 if ([attributeName
387 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
388 return YES;
389 }
390
385 // Since tabs use the Radio Button role on Mac, the standard way to set them 391 // Since tabs use the Radio Button role on Mac, the standard way to set them
386 // is via the value attribute rather than the selected attribute. 392 // is via the value attribute rather than the selected attribute.
387 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] && 393 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] &&
388 node_->GetData().role == ui::AX_ROLE_TAB) { 394 node_->GetData().role == ui::AX_ROLE_TAB) {
389 return !node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED); 395 return !node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED);
390 } 396 }
391 397
392 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] || 398 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] ||
393 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute]) { 399 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute]) {
394 return !ui::AXNodeData::IsFlagSet(node_->GetData().state, 400 return !ui::AXNodeData::IsFlagSet(node_->GetData().state,
(...skipping 14 matching lines...) Expand all
409 ui::AXActionData data; 415 ui::AXActionData data;
410 416
411 // Check for attributes first. Only the |data.action| should be set here - any 417 // Check for attributes first. Only the |data.action| should be set here - any
412 // type-specific information, if needed, should be set below. 418 // type-specific information, if needed, should be set below.
413 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) { 419 if ([attribute isEqualToString:NSAccessibilityValueAttribute]) {
414 data.action = node_->GetData().role == ui::AX_ROLE_TAB 420 data.action = node_->GetData().role == ui::AX_ROLE_TAB
415 ? ui::AX_ACTION_SET_SELECTION 421 ? ui::AX_ACTION_SET_SELECTION
416 : ui::AX_ACTION_SET_VALUE; 422 : ui::AX_ACTION_SET_VALUE;
417 } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) { 423 } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
418 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT; 424 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT;
425 } else if ([attribute
426 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
427 data.action = ui::AX_ACTION_SET_SELECTION;
419 } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { 428 } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
420 if ([value isKindOfClass:[NSNumber class]]) { 429 if ([value isKindOfClass:[NSNumber class]]) {
421 data.action = 430 data.action =
422 [value boolValue] ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR; 431 [value boolValue] ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR;
423 } 432 }
424 } 433 }
425 434
426 // Set type-specific information as necessary for actions set above. 435 // Set type-specific information as necessary for actions set above.
427 if ([value isKindOfClass:[NSString class]]) 436 if ([value isKindOfClass:[NSString class]]) {
428 data.value = base::SysNSStringToUTF16(value); 437 data.value = base::SysNSStringToUTF16(value);
438 } else if (data.action == ui::AX_ACTION_SET_SELECTION &&
439 [value isKindOfClass:[NSValue class]]) {
440 NSRange range = [value rangeValue];
441 data.anchor_offset = range.location;
442 data.focus_offset = NSMaxRange(range);
443 }
429 444
430 if (data.action != ui::AX_ACTION_NONE) 445 if (data.action != ui::AX_ACTION_NONE)
431 node_->GetDelegate()->AccessibilityPerformAction(data); 446 node_->GetDelegate()->AccessibilityPerformAction(data);
432 447
433 // TODO(patricialor): Plumb through all the other writable attributes as 448 // TODO(patricialor): Plumb through all the other writable attributes as
434 // specified in accessibilityIsAttributeSettable. 449 // specified in accessibilityIsAttributeSettable.
435 } 450 }
436 451
437 - (id)accessibilityAttributeValue:(NSString*)attribute { 452 - (id)accessibilityAttributeValue:(NSString*)attribute {
438 SEL selector = NSSelectorFromString(attribute); 453 SEL selector = NSSelectorFromString(attribute);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 return [self getStringAttribute:ui::AX_ATTR_DESCRIPTION]; 496 return [self getStringAttribute:ui::AX_ATTR_DESCRIPTION];
482 } 497 }
483 498
484 - (id)AXValue { 499 - (id)AXValue {
485 if (node_->GetData().role == ui::AX_ROLE_TAB) 500 if (node_->GetData().role == ui::AX_ROLE_TAB)
486 return [self AXSelected]; 501 return [self AXSelected];
487 return [self getStringAttribute:ui::AX_ATTR_VALUE]; 502 return [self getStringAttribute:ui::AX_ATTR_VALUE];
488 } 503 }
489 504
490 - (NSNumber*)AXEnabled { 505 - (NSNumber*)AXEnabled {
491 return [NSNumber 506 return @(!ui::AXNodeData::IsFlagSet(node_->GetData().state,
492 numberWithBool:!ui::AXNodeData::IsFlagSet(node_->GetData().state, 507 ui::AX_STATE_DISABLED));
493 ui::AX_STATE_DISABLED)];
494 } 508 }
495 509
496 - (NSNumber*)AXFocused { 510 - (NSNumber*)AXFocused {
497 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, 511 if (ui::AXNodeData::IsFlagSet(node_->GetData().state,
498 ui::AX_STATE_FOCUSABLE)) 512 ui::AX_STATE_FOCUSABLE))
499 return [NSNumber numberWithBool:(node_->GetDelegate()->GetFocus() == 513 return
500 node_->GetNativeViewAccessible())]; 514 @(node_->GetDelegate()->GetFocus() == node_->GetNativeViewAccessible());
501 return [NSNumber numberWithBool:NO]; 515 return @NO;
502 } 516 }
503 517
504 - (id)AXParent { 518 - (id)AXParent {
505 if (!node_) 519 if (!node_)
506 return nil; 520 return nil;
507 return NSAccessibilityUnignoredAncestor(node_->GetParent()); 521 return NSAccessibilityUnignoredAncestor(node_->GetParent());
508 } 522 }
509 523
510 - (NSArray*)AXChildren { 524 - (NSArray*)AXChildren {
511 if (!node_) 525 if (!node_)
(...skipping 21 matching lines...) Expand all
533 return [NSValue valueWithSize:self.boundsInScreen.size]; 547 return [NSValue valueWithSize:self.boundsInScreen.size];
534 } 548 }
535 549
536 - (NSString*)AXTitle { 550 - (NSString*)AXTitle {
537 return [self getStringAttribute:ui::AX_ATTR_NAME]; 551 return [self getStringAttribute:ui::AX_ATTR_NAME];
538 } 552 }
539 553
540 // Misc attributes. 554 // Misc attributes.
541 555
542 - (NSNumber*)AXSelected { 556 - (NSNumber*)AXSelected {
543 return [NSNumber 557 return @(node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED));
544 numberWithBool:node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED)];
545 } 558 }
546 559
547 - (NSString*)AXPlaceholderValue { 560 - (NSString*)AXPlaceholderValue {
548 return [self getStringAttribute:ui::AX_ATTR_PLACEHOLDER]; 561 return [self getStringAttribute:ui::AX_ATTR_PLACEHOLDER];
549 } 562 }
550 563
551 // Text-specific attributes. 564 // Text-specific attributes.
552 565
553 - (NSString*)AXSelectedText { 566 - (NSString*)AXSelectedText {
554 NSRange selectedTextRange; 567 NSRange selectedTextRange;
555 [[self AXSelectedTextRange] getValue:&selectedTextRange]; 568 [[self AXSelectedTextRange] getValue:&selectedTextRange];
556 return [[self AXValue] substringWithRange:selectedTextRange]; 569 return [[self AXValue] substringWithRange:selectedTextRange];
557 } 570 }
558 571
559 - (NSValue*)AXSelectedTextRange { 572 - (NSValue*)AXSelectedTextRange {
560 int textDir, start, end; 573 int textDir, start, end;
561 node_->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, &textDir); 574 node_->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, &textDir);
562 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &start); 575 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &start);
563 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &end); 576 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &end);
564 // NSRange cannot represent the direction the text was selected in, so make 577 // NSRange cannot represent the direction the text was selected in, so make
565 // sure the correct selection index is used when creating a new range, taking 578 // sure the correct selection index is used when creating a new range, taking
566 // into account the textfield text direction as well. 579 // into account the textfield text direction as well.
567 bool isReversed = (textDir == ui::AX_TEXT_DIRECTION_RTL) || 580 bool isReversed = (textDir == ui::AX_TEXT_DIRECTION_RTL) ||
568 (textDir == ui::AX_TEXT_DIRECTION_BTT); 581 (textDir == ui::AX_TEXT_DIRECTION_BTT);
569 int beginSelectionIndex = (end > start && !isReversed) ? start : end; 582 int beginSelectionIndex = (end > start && !isReversed) ? start : end;
570 return [NSValue 583 return [NSValue valueWithRange:{beginSelectionIndex, abs(end - start)}];
571 valueWithRange:NSMakeRange(beginSelectionIndex, abs(end - start))];
572 } 584 }
573 585
574 - (NSNumber*)AXNumberOfCharacters { 586 - (NSNumber*)AXNumberOfCharacters {
575 return [NSNumber numberWithInteger:[[self AXValue] length]]; 587 return @([[self AXValue] length]);
576 } 588 }
577 589
578 - (NSValue*)AXVisibleCharacterRange { 590 - (NSValue*)AXVisibleCharacterRange {
579 return [NSValue 591 return [NSValue valueWithRange:{0, [[self AXNumberOfCharacters] intValue]}];
580 valueWithRange:NSMakeRange(0, [[self AXNumberOfCharacters] intValue])];
581 } 592 }
582 593
583 - (NSNumber*)AXInsertionPointLineNumber { 594 - (NSNumber*)AXInsertionPointLineNumber {
584 // Multiline is not supported on views. 595 // Multiline is not supported on views.
585 return [NSNumber numberWithInteger:0]; 596 return @0;
586 } 597 }
587 598
588 @end 599 @end
589 600
590 namespace ui { 601 namespace ui {
591 602
592 // static 603 // static
593 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) { 604 AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
594 AXPlatformNodeBase* node = new AXPlatformNodeMac(); 605 AXPlatformNodeBase* node = new AXPlatformNodeMac();
595 node->Init(delegate); 606 node->Init(delegate);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
631 } 642 }
632 NotifyMacEvent(native_node_, event_type); 643 NotifyMacEvent(native_node_, event_type);
633 } 644 }
634 645
635 int AXPlatformNodeMac::GetIndexInParent() { 646 int AXPlatformNodeMac::GetIndexInParent() {
636 // TODO(dmazzoni): implement this. http://crbug.com/396137 647 // TODO(dmazzoni): implement this. http://crbug.com/396137
637 return -1; 648 return -1;
638 } 649 }
639 650
640 } // namespace ui 651 } // namespace ui
OLDNEW
« no previous file with comments | « no previous file | ui/views/controls/textfield/textfield.cc » ('j') | ui/views/controls/textfield/textfield.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698