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

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

Powered by Google App Engine
This is Rietveld 408576698