| OLD | NEW |
| 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 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 std::string attributeValue; | 284 std::string attributeValue; |
| 285 if (node_->GetStringAttribute(attribute, &attributeValue)) | 285 if (node_->GetStringAttribute(attribute, &attributeValue)) |
| 286 return base::SysUTF8ToNSString(attributeValue); | 286 return base::SysUTF8ToNSString(attributeValue); |
| 287 return nil; | 287 return nil; |
| 288 } | 288 } |
| 289 | 289 |
| 290 // NSAccessibility informal protocol implementation. | 290 // NSAccessibility informal protocol implementation. |
| 291 | 291 |
| 292 - (BOOL)accessibilityIsIgnored { | 292 - (BOOL)accessibilityIsIgnored { |
| 293 return [[self AXRole] isEqualToString:NSAccessibilityUnknownRole] || | 293 return [[self AXRole] isEqualToString:NSAccessibilityUnknownRole] || |
| 294 node_->GetData().HasStateFlag(ui::AX_STATE_INVISIBLE); | 294 node_->GetData().HasState(ui::AX_STATE_INVISIBLE); |
| 295 } | 295 } |
| 296 | 296 |
| 297 - (id)accessibilityHitTest:(NSPoint)point { | 297 - (id)accessibilityHitTest:(NSPoint)point { |
| 298 for (AXPlatformNodeCocoa* child in [self AXChildren]) { | 298 for (AXPlatformNodeCocoa* child in [self AXChildren]) { |
| 299 if (NSPointInRect(point, child.boundsInScreen)) | 299 if (NSPointInRect(point, child.boundsInScreen)) |
| 300 return [child accessibilityHitTest:point]; | 300 return [child accessibilityHitTest:point]; |
| 301 } | 301 } |
| 302 return NSAccessibilityUnignoredAncestor(self); | 302 return NSAccessibilityUnignoredAncestor(self); |
| 303 } | 303 } |
| 304 | 304 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 NSString* const kTextfieldAttributes = | 374 NSString* const kTextfieldAttributes = |
| 375 NSAccessibilityPlaceholderValueAttribute; | 375 NSAccessibilityPlaceholderValueAttribute; |
| 376 | 376 |
| 377 base::scoped_nsobject<NSMutableArray> axAttributes( | 377 base::scoped_nsobject<NSMutableArray> axAttributes( |
| 378 [[NSMutableArray alloc] init]); | 378 [[NSMutableArray alloc] init]); |
| 379 | 379 |
| 380 [axAttributes addObjectsFromArray:kAllRoleAttributes]; | 380 [axAttributes addObjectsFromArray:kAllRoleAttributes]; |
| 381 switch (node_->GetData().role) { | 381 switch (node_->GetData().role) { |
| 382 case ui::AX_ROLE_TEXT_FIELD: | 382 case ui::AX_ROLE_TEXT_FIELD: |
| 383 [axAttributes addObject:kTextfieldAttributes]; | 383 [axAttributes addObject:kTextfieldAttributes]; |
| 384 if (!ui::AXNodeData::IsFlagSet(node_->GetData().state, | 384 if (!node_->GetData().HasState(ui::AX_STATE_PROTECTED)) |
| 385 ui::AX_STATE_PROTECTED)) { | |
| 386 [axAttributes addObjectsFromArray:kUnprotectedTextfieldAttributes]; | 385 [axAttributes addObjectsFromArray:kUnprotectedTextfieldAttributes]; |
| 387 } | |
| 388 // Fallthrough. | 386 // Fallthrough. |
| 389 case ui::AX_ROLE_CHECK_BOX: | 387 case ui::AX_ROLE_CHECK_BOX: |
| 390 case ui::AX_ROLE_COMBO_BOX: | 388 case ui::AX_ROLE_COMBO_BOX: |
| 391 case ui::AX_ROLE_MENU_ITEM_CHECK_BOX: | 389 case ui::AX_ROLE_MENU_ITEM_CHECK_BOX: |
| 392 case ui::AX_ROLE_MENU_ITEM_RADIO: | 390 case ui::AX_ROLE_MENU_ITEM_RADIO: |
| 393 case ui::AX_ROLE_RADIO_BUTTON: | 391 case ui::AX_ROLE_RADIO_BUTTON: |
| 394 case ui::AX_ROLE_SEARCH_BOX: | 392 case ui::AX_ROLE_SEARCH_BOX: |
| 395 case ui::AX_ROLE_SLIDER: | 393 case ui::AX_ROLE_SLIDER: |
| 396 case ui::AX_ROLE_SLIDER_THUMB: | 394 case ui::AX_ROLE_SLIDER_THUMB: |
| 397 case ui::AX_ROLE_TOGGLE_BUTTON: | 395 case ui::AX_ROLE_TOGGLE_BUTTON: |
| 398 [axAttributes addObjectsFromArray:kValueAttributes]; | 396 [axAttributes addObjectsFromArray:kValueAttributes]; |
| 399 break; | 397 break; |
| 400 // TODO(tapted): Add additional attributes based on role. | 398 // TODO(tapted): Add additional attributes based on role. |
| 401 default: | 399 default: |
| 402 break; | 400 break; |
| 403 } | 401 } |
| 404 return axAttributes.autorelease(); | 402 return axAttributes.autorelease(); |
| 405 } | 403 } |
| 406 | 404 |
| 407 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName { | 405 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName { |
| 408 if (node_->GetData().HasStateFlag(ui::AX_STATE_DISABLED)) | 406 if (node_->GetData().HasState(ui::AX_STATE_DISABLED)) |
| 409 return NO; | 407 return NO; |
| 410 | 408 |
| 411 // Allow certain attributes to be written via an accessibility client. A | 409 // Allow certain attributes to be written via an accessibility client. A |
| 412 // writable attribute will only appear as such if the accessibility element | 410 // writable attribute will only appear as such if the accessibility element |
| 413 // has a value set for that attribute. | 411 // has a value set for that attribute. |
| 414 if ([attributeName | 412 if ([attributeName |
| 415 isEqualToString:NSAccessibilitySelectedChildrenAttribute] || | 413 isEqualToString:NSAccessibilitySelectedChildrenAttribute] || |
| 416 [attributeName | 414 [attributeName |
| 417 isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) { | 415 isEqualToString:NSAccessibilityVisibleCharacterRangeAttribute]) { |
| 418 return NO; | 416 return NO; |
| 419 } | 417 } |
| 420 | 418 |
| 421 if ([attributeName isEqualToString:NSAccessibilityValueAttribute]) { | 419 if ([attributeName isEqualToString:NSAccessibilityValueAttribute]) { |
| 422 // NSSecureTextField doesn't allow values to be edited (despite showing up | 420 // NSSecureTextField doesn't allow values to be edited (despite showing up |
| 423 // as editable), match its behavior. | 421 // as editable), match its behavior. |
| 424 if (node_->GetData().HasStateFlag(ui::AX_STATE_PROTECTED)) | 422 if (node_->GetData().HasState(ui::AX_STATE_PROTECTED)) |
| 425 return NO; | 423 return NO; |
| 426 // Since tabs use the Radio Button role on Mac, the standard way to set | 424 // Since tabs use the Radio Button role on Mac, the standard way to set |
| 427 // them is via the value attribute rather than the selected attribute. | 425 // them is via the value attribute rather than the selected attribute. |
| 428 if (node_->GetData().role == ui::AX_ROLE_TAB) | 426 if (node_->GetData().role == ui::AX_ROLE_TAB) |
| 429 return !node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED); | 427 return !node_->GetData().HasState(ui::AX_STATE_SELECTED); |
| 430 } | 428 } |
| 431 | 429 |
| 432 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] || | 430 if ([attributeName isEqualToString:NSAccessibilityValueAttribute] || |
| 433 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute] || | 431 [attributeName isEqualToString:NSAccessibilitySelectedTextAttribute] || |
| 434 [attributeName | 432 [attributeName |
| 435 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { | 433 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { |
| 436 return !ui::AXNodeData::IsFlagSet(node_->GetData().state, | 434 return !node_->GetData().HasState(ui::AX_STATE_READ_ONLY); |
| 437 ui::AX_STATE_READ_ONLY); | |
| 438 } | 435 } |
| 439 | 436 |
| 440 if ([attributeName isEqualToString:NSAccessibilityFocusedAttribute]) { | 437 if ([attributeName isEqualToString:NSAccessibilityFocusedAttribute]) { |
| 441 return ui::AXNodeData::IsFlagSet(node_->GetData().state, | 438 return node_->GetData().HasState(ui::AX_STATE_FOCUSABLE); |
| 442 ui::AX_STATE_FOCUSABLE); | |
| 443 } | 439 } |
| 444 | 440 |
| 445 // TODO(patricialor): Add callbacks for updating the above attributes except | 441 // TODO(patricialor): Add callbacks for updating the above attributes except |
| 446 // NSAccessibilityValueAttribute and return YES. | 442 // NSAccessibilityValueAttribute and return YES. |
| 447 return NO; | 443 return NO; |
| 448 } | 444 } |
| 449 | 445 |
| 450 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute { | 446 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute { |
| 451 ui::AXActionData data; | 447 ui::AXActionData data; |
| 452 | 448 |
| 453 // Check for attributes first. Only the |data.action| should be set here - any | 449 // Check for attributes first. Only the |data.action| should be set here - any |
| 454 // type-specific information, if needed, should be set below. | 450 // type-specific information, if needed, should be set below. |
| 455 if ([attribute isEqualToString:NSAccessibilityValueAttribute] && | 451 if ([attribute isEqualToString:NSAccessibilityValueAttribute] && |
| 456 !node_->GetData().HasStateFlag(ui::AX_STATE_PROTECTED)) { | 452 !node_->GetData().HasState(ui::AX_STATE_PROTECTED)) { |
| 457 data.action = node_->GetData().role == ui::AX_ROLE_TAB | 453 data.action = node_->GetData().role == ui::AX_ROLE_TAB |
| 458 ? ui::AX_ACTION_SET_SELECTION | 454 ? ui::AX_ACTION_SET_SELECTION |
| 459 : ui::AX_ACTION_SET_VALUE; | 455 : ui::AX_ACTION_SET_VALUE; |
| 460 } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) { | 456 } else if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) { |
| 461 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT; | 457 data.action = ui::AX_ACTION_REPLACE_SELECTED_TEXT; |
| 462 } else if ([attribute | 458 } else if ([attribute |
| 463 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { | 459 isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) { |
| 464 data.action = ui::AX_ACTION_SET_SELECTION; | 460 data.action = ui::AX_ACTION_SET_SELECTION; |
| 465 } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { | 461 } else if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) { |
| 466 if ([value isKindOfClass:[NSNumber class]]) { | 462 if ([value isKindOfClass:[NSNumber class]]) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 default: | 508 default: |
| 513 break; | 509 break; |
| 514 } | 510 } |
| 515 return NSAccessibilityRoleDescription([self AXRole], [self AXSubrole]); | 511 return NSAccessibilityRoleDescription([self AXRole], [self AXSubrole]); |
| 516 } | 512 } |
| 517 | 513 |
| 518 - (NSString*)AXSubrole { | 514 - (NSString*)AXSubrole { |
| 519 ui::AXRole role = node_->GetData().role; | 515 ui::AXRole role = node_->GetData().role; |
| 520 switch (role) { | 516 switch (role) { |
| 521 case ui::AX_ROLE_TEXT_FIELD: | 517 case ui::AX_ROLE_TEXT_FIELD: |
| 522 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, | 518 if (node_->GetData().HasState(ui::AX_STATE_PROTECTED)) |
| 523 ui::AX_STATE_PROTECTED)) | |
| 524 return NSAccessibilitySecureTextFieldSubrole; | 519 return NSAccessibilitySecureTextFieldSubrole; |
| 525 break; | 520 break; |
| 526 default: | 521 default: |
| 527 break; | 522 break; |
| 528 } | 523 } |
| 529 return [AXPlatformNodeCocoa nativeSubroleFromAXRole:role]; | 524 return [AXPlatformNodeCocoa nativeSubroleFromAXRole:role]; |
| 530 } | 525 } |
| 531 | 526 |
| 532 - (NSString*)AXHelp { | 527 - (NSString*)AXHelp { |
| 533 return [self getStringAttribute:ui::AX_ATTR_DESCRIPTION]; | 528 return [self getStringAttribute:ui::AX_ATTR_DESCRIPTION]; |
| 534 } | 529 } |
| 535 | 530 |
| 536 - (id)AXValue { | 531 - (id)AXValue { |
| 537 if (node_->GetData().role == ui::AX_ROLE_TAB) | 532 if (node_->GetData().role == ui::AX_ROLE_TAB) |
| 538 return [self AXSelected]; | 533 return [self AXSelected]; |
| 539 return [self getStringAttribute:ui::AX_ATTR_VALUE]; | 534 return [self getStringAttribute:ui::AX_ATTR_VALUE]; |
| 540 } | 535 } |
| 541 | 536 |
| 542 - (NSNumber*)AXEnabled { | 537 - (NSNumber*)AXEnabled { |
| 543 return @(!ui::AXNodeData::IsFlagSet(node_->GetData().state, | 538 return @(!node_->GetData().HasState(ui::AX_STATE_DISABLED)); |
| 544 ui::AX_STATE_DISABLED)); | |
| 545 } | 539 } |
| 546 | 540 |
| 547 - (NSNumber*)AXFocused { | 541 - (NSNumber*)AXFocused { |
| 548 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, | 542 if (node_->GetData().HasState(ui::AX_STATE_FOCUSABLE)) |
| 549 ui::AX_STATE_FOCUSABLE)) | |
| 550 return | 543 return |
| 551 @(node_->GetDelegate()->GetFocus() == node_->GetNativeViewAccessible()); | 544 @(node_->GetDelegate()->GetFocus() == node_->GetNativeViewAccessible()); |
| 552 return @NO; | 545 return @NO; |
| 553 } | 546 } |
| 554 | 547 |
| 555 - (id)AXParent { | 548 - (id)AXParent { |
| 556 if (!node_) | 549 if (!node_) |
| 557 return nil; | 550 return nil; |
| 558 return NSAccessibilityUnignoredAncestor(node_->GetParent()); | 551 return NSAccessibilityUnignoredAncestor(node_->GetParent()); |
| 559 } | 552 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 584 return [NSValue valueWithSize:self.boundsInScreen.size]; | 577 return [NSValue valueWithSize:self.boundsInScreen.size]; |
| 585 } | 578 } |
| 586 | 579 |
| 587 - (NSString*)AXTitle { | 580 - (NSString*)AXTitle { |
| 588 return [self getStringAttribute:ui::AX_ATTR_NAME]; | 581 return [self getStringAttribute:ui::AX_ATTR_NAME]; |
| 589 } | 582 } |
| 590 | 583 |
| 591 // Misc attributes. | 584 // Misc attributes. |
| 592 | 585 |
| 593 - (NSNumber*)AXSelected { | 586 - (NSNumber*)AXSelected { |
| 594 return @(node_->GetData().HasStateFlag(ui::AX_STATE_SELECTED)); | 587 return @(node_->GetData().HasState(ui::AX_STATE_SELECTED)); |
| 595 } | 588 } |
| 596 | 589 |
| 597 - (NSString*)AXPlaceholderValue { | 590 - (NSString*)AXPlaceholderValue { |
| 598 return [self getStringAttribute:ui::AX_ATTR_PLACEHOLDER]; | 591 return [self getStringAttribute:ui::AX_ATTR_PLACEHOLDER]; |
| 599 } | 592 } |
| 600 | 593 |
| 601 // Text-specific attributes. | 594 // Text-specific attributes. |
| 602 | 595 |
| 603 - (NSString*)AXSelectedText { | 596 - (NSString*)AXSelectedText { |
| 604 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, ui::AX_STATE_PROTECTED)) | 597 if (node_->GetData().HasState(ui::AX_STATE_PROTECTED)) |
| 605 return nil; | 598 return nil; |
| 606 | 599 |
| 607 NSRange selectedTextRange; | 600 NSRange selectedTextRange; |
| 608 [[self AXSelectedTextRange] getValue:&selectedTextRange]; | 601 [[self AXSelectedTextRange] getValue:&selectedTextRange]; |
| 609 return [[self AXValue] substringWithRange:selectedTextRange]; | 602 return [[self AXValue] substringWithRange:selectedTextRange]; |
| 610 } | 603 } |
| 611 | 604 |
| 612 - (NSValue*)AXSelectedTextRange { | 605 - (NSValue*)AXSelectedTextRange { |
| 613 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, ui::AX_STATE_PROTECTED)) | 606 if (node_->GetData().HasState(ui::AX_STATE_PROTECTED)) |
| 614 return nil; | 607 return nil; |
| 615 | 608 |
| 616 int textDir, start, end; | 609 int textDir, start, end; |
| 617 node_->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, &textDir); | 610 node_->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION, &textDir); |
| 618 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &start); | 611 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, &start); |
| 619 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &end); | 612 node_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &end); |
| 620 // NSRange cannot represent the direction the text was selected in, so make | 613 // NSRange cannot represent the direction the text was selected in, so make |
| 621 // sure the correct selection index is used when creating a new range, taking | 614 // sure the correct selection index is used when creating a new range, taking |
| 622 // into account the textfield text direction as well. | 615 // into account the textfield text direction as well. |
| 623 bool isReversed = (textDir == ui::AX_TEXT_DIRECTION_RTL) || | 616 bool isReversed = (textDir == ui::AX_TEXT_DIRECTION_RTL) || |
| 624 (textDir == ui::AX_TEXT_DIRECTION_BTT); | 617 (textDir == ui::AX_TEXT_DIRECTION_BTT); |
| 625 int beginSelectionIndex = (end > start && !isReversed) ? start : end; | 618 int beginSelectionIndex = (end > start && !isReversed) ? start : end; |
| 626 return [NSValue valueWithRange:{beginSelectionIndex, abs(end - start)}]; | 619 return [NSValue valueWithRange:{beginSelectionIndex, abs(end - start)}]; |
| 627 } | 620 } |
| 628 | 621 |
| 629 - (NSNumber*)AXNumberOfCharacters { | 622 - (NSNumber*)AXNumberOfCharacters { |
| 630 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, ui::AX_STATE_PROTECTED)) | 623 if (node_->GetData().HasState(ui::AX_STATE_PROTECTED)) |
| 631 return nil; | 624 return nil; |
| 632 return @([[self AXValue] length]); | 625 return @([[self AXValue] length]); |
| 633 } | 626 } |
| 634 | 627 |
| 635 - (NSValue*)AXVisibleCharacterRange { | 628 - (NSValue*)AXVisibleCharacterRange { |
| 636 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, ui::AX_STATE_PROTECTED)) | 629 if (node_->GetData().HasState(ui::AX_STATE_PROTECTED)) |
| 637 return nil; | 630 return nil; |
| 638 return [NSValue valueWithRange:{0, [[self AXNumberOfCharacters] intValue]}]; | 631 return [NSValue valueWithRange:{0, [[self AXNumberOfCharacters] intValue]}]; |
| 639 } | 632 } |
| 640 | 633 |
| 641 - (NSNumber*)AXInsertionPointLineNumber { | 634 - (NSNumber*)AXInsertionPointLineNumber { |
| 642 if (ui::AXNodeData::IsFlagSet(node_->GetData().state, ui::AX_STATE_PROTECTED)) | 635 if (node_->GetData().HasState(ui::AX_STATE_PROTECTED)) |
| 643 return nil; | 636 return nil; |
| 644 // Multiline is not supported on views. | 637 // Multiline is not supported on views. |
| 645 return @0; | 638 return @0; |
| 646 } | 639 } |
| 647 | 640 |
| 648 @end | 641 @end |
| 649 | 642 |
| 650 namespace ui { | 643 namespace ui { |
| 651 | 644 |
| 652 // static | 645 // static |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 699 } | 692 } |
| 700 NotifyMacEvent(native_node_, event_type); | 693 NotifyMacEvent(native_node_, event_type); |
| 701 } | 694 } |
| 702 | 695 |
| 703 int AXPlatformNodeMac::GetIndexInParent() { | 696 int AXPlatformNodeMac::GetIndexInParent() { |
| 704 // TODO(dmazzoni): implement this. http://crbug.com/396137 | 697 // TODO(dmazzoni): implement this. http://crbug.com/396137 |
| 705 return -1; | 698 return -1; |
| 706 } | 699 } |
| 707 | 700 |
| 708 } // namespace ui | 701 } // namespace ui |
| OLD | NEW |