1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2/* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 21#include <osx/salinst.h> 22#include <osx/saldata.hxx> 23 24#include <osx/a11ywrapper.h> 25#include <osx/a11ylistener.hxx> 26#include <osx/a11yfactory.h> 27#include <osx/a11yfocustracker.hxx> 28 29#include <quartz/utils.h> 30 31#include "a11yfocuslistener.hxx" 32#include "a11yactionwrapper.h" 33#include "a11ycomponentwrapper.h" 34#include "a11yselectionwrapper.h" 35#include "a11ytablewrapper.h" 36#include "a11ytextwrapper.h" 37#include "a11yvaluewrapper.h" 38#include "a11yrolehelper.h" 39 40#include <com/sun/star/accessibility/AccessibleRole.hpp> 41#include <com/sun/star/accessibility/AccessibleStateType.hpp> 42#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp> 43#include <com/sun/star/awt/Size.hpp> 44#include <com/sun/star/accessibility/XAccessibleRelationSet.hpp> 45#include <com/sun/star/accessibility/AccessibleRelationType.hpp> 46#include <com/sun/star/lang/DisposedException.hpp> 47 48#include <sal/log.hxx> 49#include <osl/diagnose.h> 50 51using namespace ::com::sun::star::accessibility; 52using namespace ::com::sun::star::awt; 53using namespace ::com::sun::star::lang; 54using namespace ::com::sun::star::uno; 55 56@interface SalFrameWindow : NSWindow 57{ 58} 59-(Reference<XAccessibleContext>)accessibleContext; 60@end 61 62static bool isPopupMenuOpen = false; 63 64static std::ostream &operator<<(std::ostream &s, NSObject *obj) { 65 return s << [[obj description] UTF8String]; 66} 67 68@implementation AquaA11yWrapper : NSView 69 70#pragma mark - 71#pragma mark Init and dealloc 72 73-(id)initWithAccessibleContext: (Reference < XAccessibleContext >) rxAccessibleContext { 74 self = [ super init ]; 75 if ( self ) { 76 [ self setDefaults: rxAccessibleContext ]; 77 } 78 return self; 79} 80 81-(void) setDefaults: (Reference < XAccessibleContext >) rxAccessibleContext { 82 mpReferenceWrapper = new ReferenceWrapper; 83 mActsAsRadioGroup = NO; 84 mpReferenceWrapper -> rAccessibleContext = rxAccessibleContext; 85 mIsTableCell = NO; 86 // Querying all supported interfaces 87 try { 88 // XAccessibleComponent 89 mpReferenceWrapper->rAccessibleComponent.set( rxAccessibleContext, UNO_QUERY ); 90 // XAccessibleExtendedComponent 91 mpReferenceWrapper->rAccessibleExtendedComponent.set( rxAccessibleContext, UNO_QUERY ); 92 // XAccessibleSelection 93 mpReferenceWrapper->rAccessibleSelection.set( rxAccessibleContext, UNO_QUERY ); 94 // XAccessibleTable 95 mpReferenceWrapper->rAccessibleTable.set( rxAccessibleContext, UNO_QUERY ); 96 // XAccessibleText 97 mpReferenceWrapper->rAccessibleText.set( rxAccessibleContext, UNO_QUERY ); 98 // XAccessibleEditableText 99 mpReferenceWrapper->rAccessibleEditableText.set( rxAccessibleContext, UNO_QUERY ); 100 // XAccessibleValue 101 mpReferenceWrapper->rAccessibleValue.set( rxAccessibleContext, UNO_QUERY ); 102 // XAccessibleAction 103 mpReferenceWrapper->rAccessibleAction.set( rxAccessibleContext, UNO_QUERY ); 104 // XAccessibleTextAttributes 105 mpReferenceWrapper->rAccessibleTextAttributes.set( rxAccessibleContext, UNO_QUERY ); 106 // XAccessibleMultiLineText 107 mpReferenceWrapper->rAccessibleMultiLineText.set( rxAccessibleContext, UNO_QUERY ); 108 // XAccessibleTextMarkup 109 mpReferenceWrapper->rAccessibleTextMarkup.set( rxAccessibleContext, UNO_QUERY ); 110 // XAccessibleEventBroadcaster 111 #if 0 112 /* #i102033# NSAccessibility does not seemt to know an equivalent for transient children. 113 That means we need to cache this, else e.g. tree list boxes are not accessible (moreover 114 it crashes by notifying dead objects - which would seemt o be another bug) 115 116 FIXME: 117 Unfortunately this can increase memory consumption drastically until the non transient parent 118 is destroyed and finally all the transients are released. 119 */ 120 if ( ! rxAccessibleContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::TRANSIENT ) ) 121 #endif 122 { 123 Reference< XAccessibleEventBroadcaster > xBroadcaster(rxAccessibleContext, UNO_QUERY); 124 if( xBroadcaster.is() ) { 125 /* 126 * We intentionally do not hold a reference to the event listener in the wrapper object, 127 * but let the listener control the life cycle of the wrapper instead .. 128 */ 129 xBroadcaster->addAccessibleEventListener( new AquaA11yEventListener( self, rxAccessibleContext -> getAccessibleRole() ) ); 130 } 131 } 132 // TABLE_CELL 133 if ( rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TABLE_CELL ) { 134 mIsTableCell = YES; 135 } 136 } catch ( const Exception ) { 137 } 138} 139 140-(void)dealloc { 141 if ( mpReferenceWrapper ) { 142 delete mpReferenceWrapper; 143 } 144 [ super dealloc ]; 145} 146 147#pragma mark - 148#pragma mark Utility Section 149 150// generates selectors for attribute name AXAttributeNameHere 151// (getter without parameter) attributeNameHereAttribute 152// (getter with parameter) attributeNameHereAttributeForParameter: 153// (setter) setAttributeNameHereAttributeForElement:to: 154-(SEL)selectorForAttribute:(NSString *)attribute asGetter:(BOOL)asGetter withGetterParameter:(BOOL)withGetterParameter { 155 SEL selector = static_cast<SEL>(nil); 156 NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; 157 @try { 158 // step 1: create method name from attribute name 159 NSMutableString * methodName = [ NSMutableString string ]; 160 if ( ! asGetter ) { 161 [ methodName appendString: @"set" ]; 162 } 163 NSRange const aRange = { 2, 1 }; 164 NSString * firstChar = [ attribute substringWithRange: aRange ]; // drop leading "AX" and get first char 165 if ( asGetter ) { 166 [ methodName appendString: [ firstChar lowercaseString ] ]; 167 } else { 168 [ methodName appendString: firstChar ]; 169 } 170 [ methodName appendString: [ attribute substringFromIndex: 3 ] ]; // append rest of attribute name 171 // append rest of method name 172 [ methodName appendString: @"Attribute" ]; 173 if ( ! asGetter ) { 174 [ methodName appendString: @"ForElement:to:" ]; 175 } else if ( asGetter && withGetterParameter ) { 176 [ methodName appendString: @"ForParameter:" ]; 177 } 178 // step 2: create selector 179 selector = NSSelectorFromString ( methodName ); 180 } @catch ( id ) { 181 selector = static_cast<SEL>(nil); 182 } 183 [ pool release ]; 184 return selector; 185} 186 187-(Reference < XAccessible >)getFirstRadioButtonInGroup { 188 Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet(); 189 if( rxAccessibleRelationSet.is() ) 190 { 191 AccessibleRelation relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF ); 192 if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() ) 193 return Reference < XAccessible > ( relationMemberOf.TargetSet[0], UNO_QUERY ); 194 } 195 return Reference < XAccessible > (); 196} 197 198-(BOOL)isFirstRadioButtonInGroup { 199 Reference < XAccessible > rFirstMateAccessible = [ self getFirstRadioButtonInGroup ]; 200 if ( rFirstMateAccessible.is() && rFirstMateAccessible -> getAccessibleContext().get() == [ self accessibleContext ] ) { 201 return YES; 202 } 203 return NO; 204} 205 206#pragma mark - 207#pragma mark Attribute Value Getters 208// ( called via Reflection by accessibilityAttributeValue ) 209 210/* 211 Radiobutton grouping is done differently in NSAccessibility and the UNO-API. In UNO related radio buttons share an entry in their 212 RelationSet. In NSAccessibility the relationship is expressed through the hierarchy. An AXRadioGroup contains two or more AXRadioButton 213 objects. Since this group is not available in the UNO hierarchy, an extra wrapper is used for it. This wrapper shares almost all 214 attributes with the first radio button of the group, except for the role, subrole, role description, parent and children attributes. 215 So in this five methods there is a special treatment for radio buttons and groups. 216*/ 217 218-(id)roleAttribute { 219 if ( mActsAsRadioGroup ) { 220 return NSAccessibilityRadioGroupRole; 221 } 222 else { 223 return [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ]; 224 } 225} 226 227-(id)subroleAttribute { 228 if ( mActsAsRadioGroup ) { 229 return @""; 230 } else { 231 NSString * subRole = [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ]; 232 if ( ! [ subRole isEqualToString: @"" ] ) { 233 return subRole; 234 } else { 235 [ subRole release ]; 236 SAL_WNODEPRECATED_DECLARATIONS_PUSH 237 //TODO: 10.10 accessibilityAttributeValue: 238 return [ super accessibilityAttributeValue: NSAccessibilitySubroleAttribute ]; 239 SAL_WNODEPRECATED_DECLARATIONS_POP 240 } 241 } 242} 243 244-(id)titleAttribute { 245 return CreateNSString ( [ self accessibleContext ] -> getAccessibleName() ); 246} 247 248-(id)descriptionAttribute { 249 if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { 250 return [ self titleAttribute ]; 251 } else if ( [ self accessibleExtendedComponent ] ) { 252 return [ AquaA11yComponentWrapper descriptionAttributeForElement: self ]; 253 } else { 254 return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ); 255 } 256} 257 258-(id)enabledAttribute { 259 if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) { 260 return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::ENABLED ) ]; 261 } else { 262 return nil; 263 } 264} 265 266-(id)focusedAttribute { 267 if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) { 268 id isFocused = nil; 269 Reference < XAccessible > rxParent = [ self accessibleContext ] -> getAccessibleParent(); 270 if ( rxParent.is() ) { 271 Reference < XAccessibleContext > rxContext = rxParent -> getAccessibleContext(); 272 if ( rxContext.is() && rxContext -> getAccessibleStateSet().is() ) { 273 isFocused = [ NSNumber numberWithBool: rxContext -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ]; 274 } 275 } 276 return isFocused; 277 } else if ( [ self accessibleContext ] -> getAccessibleStateSet().is() ) { 278 return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::FOCUSED ) ]; 279 } else { 280 return nil; 281 } 282} 283 284-(id)parentAttribute { 285 if ( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON && ! mActsAsRadioGroup ) { 286 Reference < XAccessible > rxAccessible = [ self getFirstRadioButtonInGroup ]; 287 if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) { 288 Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext(); 289 id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessibleContext createIfNotExists: YES asRadioGroup: YES ]; 290 [ parent_wrapper autorelease ]; 291 return NSAccessibilityUnignoredAncestor( parent_wrapper ); 292 } 293 return nil; 294 } 295 try { 296 Reference< XAccessible > xParent( [ self accessibleContext ] -> getAccessibleParent() ); 297 if ( xParent.is() ) { 298 Reference< XAccessibleContext > xContext( xParent -> getAccessibleContext() ); 299 if ( xContext.is() ) { 300 id parent_wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xContext ]; 301 [ parent_wrapper autorelease ]; 302 return NSAccessibilityUnignoredAncestor( parent_wrapper ); 303 } 304 } 305 } catch (const Exception&) { 306 } 307 308 OSL_ASSERT( false ); 309 return nil; 310} 311 312-(id)childrenAttribute { 313 if ( mActsAsRadioGroup ) { 314 NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; 315 Reference < XAccessibleRelationSet > rxAccessibleRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet(); 316 AccessibleRelation const relationMemberOf = rxAccessibleRelationSet -> getRelationByType ( AccessibleRelationType::MEMBER_OF ); 317 if ( relationMemberOf.RelationType == AccessibleRelationType::MEMBER_OF && relationMemberOf.TargetSet.hasElements() ) { 318 for ( const auto& i : relationMemberOf.TargetSet ) { 319 Reference < XAccessible > rMateAccessible( i, UNO_QUERY ); 320 if ( rMateAccessible.is() ) { 321 Reference< XAccessibleContext > rMateAccessibleContext( rMateAccessible -> getAccessibleContext() ); 322 if ( rMateAccessibleContext.is() ) { 323 id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: rMateAccessibleContext ]; 324 [ children addObject: wrapper ]; 325 [ wrapper release ]; 326 } 327 } 328 } 329 } 330 return children; 331 } else if ( [ self accessibleTable ] ) 332 { 333 AquaA11yTableWrapper* pTable = [self isKindOfClass: [AquaA11yTableWrapper class]] ? static_cast<AquaA11yTableWrapper*>(self) : nil; 334 return [ AquaA11yTableWrapper childrenAttributeForElement: pTable ]; 335 } else { 336 try { 337 NSMutableArray * children = [ [ NSMutableArray alloc ] init ]; 338 Reference< XAccessibleContext > xContext( [ self accessibleContext ] ); 339 340 sal_Int32 cnt = xContext -> getAccessibleChildCount(); 341 for ( sal_Int32 i = 0; i < cnt; i++ ) { 342 Reference< XAccessible > xChild( xContext -> getAccessibleChild( i ) ); 343 if( xChild.is() ) { 344 Reference< XAccessibleContext > xChildContext( xChild -> getAccessibleContext() ); 345 // the menubar is already accessible (including Apple- and Application-Menu) through NSApplication => omit it here 346 if ( xChildContext.is() && AccessibleRole::MENU_BAR != xChildContext -> getAccessibleRole() ) { 347 id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: xChildContext ]; 348 [ children addObject: wrapper ]; 349 [ wrapper release ]; 350 } 351 } 352 } 353 354 // if not already acting as RadioGroup now is the time to replace RadioButtons with RadioGroups and remove RadioButtons 355 if ( ! mActsAsRadioGroup ) { 356 NSEnumerator * enumerator = [ children objectEnumerator ]; 357 AquaA11yWrapper * element; 358 while ( ( element = static_cast<AquaA11yWrapper *>([ enumerator nextObject ]) ) ) { 359 if ( [ element accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON ) { 360 if ( [ element isFirstRadioButtonInGroup ] ) { 361 id wrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ element accessibleContext ] createIfNotExists: YES asRadioGroup: YES ]; 362 [ children replaceObjectAtIndex: [ children indexOfObjectIdenticalTo: element ] withObject: wrapper ]; 363 } 364 [ children removeObject: element ]; 365 } 366 } 367 } 368 369 [ children autorelease ]; 370 return NSAccessibilityUnignoredChildren( children ); 371 } catch (const Exception &) { 372 // TODO: Log 373 return nil; 374 } 375 } 376} 377 378-(id)windowAttribute { 379 // go upstairs until reaching the broken connection 380 AquaA11yWrapper * aWrapper = self; 381 int loops = 0; 382 while ( [ aWrapper accessibleContext ] -> getAccessibleParent().is() ) { 383 AquaA11yWrapper *aTentativeParentWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ aWrapper accessibleContext ] -> getAccessibleParent() -> getAccessibleContext() ]; 384 // Quick-and-dirty fix for infinite loop after fixing crash in 385 // fdo#47275 386 if ( aTentativeParentWrapper == aWrapper ) 387 break; 388 // Even dirtier fix for infinite loop in fdo#55156 389 if ( loops++ == 100 ) 390 break; 391 aWrapper = aTentativeParentWrapper; 392 [ aWrapper autorelease ]; 393 } 394 // get associated NSWindow 395 NSWindow* theWindow = [ aWrapper windowForParent ]; 396 return theWindow; 397} 398 399-(id)topLevelUIElementAttribute { 400 return [ self windowAttribute ]; 401} 402 403-(id)sizeAttribute { 404 if ( [ self accessibleComponent ] ) { 405 return [ AquaA11yComponentWrapper sizeAttributeForElement: self ]; 406 } else { 407 return nil; 408 } 409} 410 411-(id)positionAttribute { 412 if ( [ self accessibleComponent ] ) { 413 return [ AquaA11yComponentWrapper positionAttributeForElement: self ]; 414 } else { 415 return nil; 416 } 417} 418 419-(id)helpAttribute { 420 return CreateNSString ( [ self accessibleContext ] -> getAccessibleDescription() ); 421} 422 423-(id)roleDescriptionAttribute { 424 if ( mActsAsRadioGroup ) { 425 return [ AquaA11yRoleHelper getRoleDescriptionFrom: NSAccessibilityRadioGroupRole with: @"" ]; 426 } else if( [ self accessibleContext ] -> getAccessibleRole() == AccessibleRole::RADIO_BUTTON ) { 427 // FIXME: VO should read this because of hierarchy, this is just a workaround 428 // get parent and its children 429 AquaA11yWrapper * parent = [ self parentAttribute ]; 430 NSArray * children = [ parent childrenAttribute ]; 431 // find index of self 432 int index = 1; 433 NSEnumerator * enumerator = [ children objectEnumerator ]; 434 AquaA11yWrapper * child = nil; 435 while ( ( child = [ enumerator nextObject ] ) ) { 436 if ( self == child ) { 437 break; 438 } 439 index++; 440 } 441 // build string 442 NSNumber * nIndex = [ NSNumber numberWithInt: index ]; 443 NSNumber * nGroupsize = [ NSNumber numberWithInt: [ children count ] ]; 444 NSMutableString * value = [ [ NSMutableString alloc ] init ]; 445 [ value appendString: @"radio button " ]; 446 [ value appendString: [ nIndex stringValue ] ]; 447 [ value appendString: @" of " ]; 448 [ value appendString: [ nGroupsize stringValue ] ]; 449 // clean up and return string 450 [ nIndex release ]; 451 [ nGroupsize release ]; 452 [ children release ]; 453 return value; 454 } else { 455 return [ AquaA11yRoleHelper getRoleDescriptionFrom: 456 [ AquaA11yRoleHelper getNativeRoleFrom: [ self accessibleContext ] ] 457 with: [ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ] ]; 458 } 459} 460 461-(id)valueAttribute { 462 if ( [ [ self roleAttribute ] isEqualToString: NSAccessibilityMenuItemRole ] ) { 463 return nil; 464 } else if ( [ self accessibleText ] ) { 465 return [ AquaA11yTextWrapper valueAttributeForElement: self ]; 466 } else if ( [ self accessibleValue ] ) { 467 return [ AquaA11yValueWrapper valueAttributeForElement: self ]; 468 } else { 469 return nil; 470 } 471} 472 473-(id)minValueAttribute { 474 if ( [ self accessibleValue ] ) { 475 return [ AquaA11yValueWrapper minValueAttributeForElement: self ]; 476 } else { 477 return nil; 478 } 479} 480 481-(id)maxValueAttribute { 482 if ( [ self accessibleValue ] ) { 483 return [ AquaA11yValueWrapper maxValueAttributeForElement: self ]; 484 } else { 485 return nil; 486 } 487} 488 489-(id)contentsAttribute { 490 return [ self childrenAttribute ]; 491} 492 493-(id)selectedChildrenAttribute { 494 return [ AquaA11ySelectionWrapper selectedChildrenAttributeForElement: self ]; 495} 496 497-(id)numberOfCharactersAttribute { 498 if ( [ self accessibleText ] ) { 499 return [ AquaA11yTextWrapper numberOfCharactersAttributeForElement: self ]; 500 } else { 501 return nil; 502 } 503} 504 505-(id)selectedTextAttribute { 506 if ( [ self accessibleText ] ) { 507 return [ AquaA11yTextWrapper selectedTextAttributeForElement: self ]; 508 } else { 509 return nil; 510 } 511} 512 513-(id)selectedTextRangeAttribute { 514 if ( [ self accessibleText ] ) { 515 return [ AquaA11yTextWrapper selectedTextRangeAttributeForElement: self ]; 516 } else { 517 return nil; 518 } 519} 520 521-(id)visibleCharacterRangeAttribute { 522 if ( [ self accessibleText ] ) { 523 return [ AquaA11yTextWrapper visibleCharacterRangeAttributeForElement: self ]; 524 } else { 525 return nil; 526 } 527} 528 529-(id)tabsAttribute { 530 return self; // TODO ??? 531} 532 533-(id)sharedTextUIElementsAttribute { 534 if ( [ self accessibleText ] ) { 535 return [ AquaA11yTextWrapper sharedTextUIElementsAttributeForElement: self ]; 536 } else { 537 return nil; 538 } 539} 540 541-(id)sharedCharacterRangeAttribute { 542 if ( [ self accessibleText ] ) { 543 return [ AquaA11yTextWrapper sharedCharacterRangeAttributeForElement: self ]; 544 } else { 545 return nil; 546 } 547} 548 549-(id)expandedAttribute { 550 return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::EXPANDED ) ]; 551} 552 553-(id)selectedAttribute { 554 return [ NSNumber numberWithBool: [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::SELECTED ) ]; 555} 556 557-(id)stringForRangeAttributeForParameter:(id)range { 558 if ( [ self accessibleText ] ) { 559 return [ AquaA11yTextWrapper stringForRangeAttributeForElement: self forParameter: range ]; 560 } else { 561 return nil; 562 } 563} 564 565-(id)attributedStringForRangeAttributeForParameter:(id)range { 566 if ( [ self accessibleText ] ) { 567 return [ AquaA11yTextWrapper attributedStringForRangeAttributeForElement: self forParameter: range ]; 568 } else { 569 return nil; 570 } 571} 572 573-(id)rangeForIndexAttributeForParameter:(id)index { 574 if ( [ self accessibleText ] ) { 575 return [ AquaA11yTextWrapper rangeForIndexAttributeForElement: self forParameter: index ]; 576 } else { 577 return nil; 578 } 579} 580 581-(id)rangeForPositionAttributeForParameter:(id)point { 582 if ( [ self accessibleText ] ) { 583 return [ AquaA11yTextWrapper rangeForPositionAttributeForElement: self forParameter: point ]; 584 } else { 585 return nil; 586 } 587} 588 589-(id)boundsForRangeAttributeForParameter:(id)range { 590 if ( [ self accessibleText ] ) { 591 return [ AquaA11yTextWrapper boundsForRangeAttributeForElement: self forParameter: range ]; 592 } else { 593 return nil; 594 } 595} 596 597-(id)styleRangeForIndexAttributeForParameter:(id)index { 598 if ( [ self accessibleText ] ) { 599 return [ AquaA11yTextWrapper styleRangeForIndexAttributeForElement: self forParameter: index ]; 600 } else { 601 return nil; 602 } 603} 604 605-(id)rTFForRangeAttributeForParameter:(id)range { 606 if ( [ self accessibleText ] ) { 607 return [ AquaA11yTextWrapper rTFForRangeAttributeForElement: self forParameter: range ]; 608 } else { 609 return nil; 610 } 611} 612 613-(id)orientationAttribute { 614 NSString * orientation = nil; 615 Reference < XAccessibleStateSet > stateSet = [ self accessibleContext ] -> getAccessibleStateSet(); 616 if ( stateSet -> contains ( AccessibleStateType::HORIZONTAL ) ) { 617 orientation = NSAccessibilityHorizontalOrientationValue; 618 } else if ( stateSet -> contains ( AccessibleStateType::VERTICAL ) ) { 619 orientation = NSAccessibilityVerticalOrientationValue; 620 } 621 return orientation; 622} 623 624-(id)titleUIElementAttribute { 625 if ( [ self accessibleContext ] -> getAccessibleRelationSet().is() ) { 626 NSString * title = [ self titleAttribute ]; 627 id titleElement = nil; 628 if ( [ title length ] == 0 ) { 629 AccessibleRelation relationLabeledBy = [ self accessibleContext ] -> getAccessibleRelationSet() -> getRelationByType ( AccessibleRelationType::LABELED_BY ); 630 if ( relationLabeledBy.RelationType == AccessibleRelationType::LABELED_BY && relationLabeledBy.TargetSet.hasElements() ) { 631 Reference < XAccessible > rxAccessible ( relationLabeledBy.TargetSet[0], UNO_QUERY ); 632 titleElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ]; 633 } 634 } 635 if ( title ) { 636 [ title release ]; 637 } 638 return titleElement; 639 } else { 640 return nil; 641 } 642} 643 644-(id)servesAsTitleForUIElementsAttribute { 645 if ( [ self accessibleContext ] -> getAccessibleRelationSet().is() ) { 646 id titleForElement = nil; 647 AccessibleRelation relationLabelFor = [ self accessibleContext ] -> getAccessibleRelationSet() -> getRelationByType ( AccessibleRelationType::LABEL_FOR ); 648 if ( relationLabelFor.RelationType == AccessibleRelationType::LABEL_FOR && relationLabelFor.TargetSet.hasElements() ) { 649 Reference < XAccessible > rxAccessible ( relationLabelFor.TargetSet[0], UNO_QUERY ); 650 titleForElement = [ AquaA11yFactory wrapperForAccessibleContext: rxAccessible -> getAccessibleContext() ]; 651 } 652 return titleForElement; 653 } else { 654 return nil; 655 } 656} 657 658-(id)lineForIndexAttributeForParameter:(id)index { 659 if ( [ self accessibleMultiLineText ] ) { 660 return [ AquaA11yTextWrapper lineForIndexAttributeForElement: self forParameter: index ]; 661 } else { 662 return nil; 663 } 664} 665 666-(id)rangeForLineAttributeForParameter:(id)line { 667 if ( [ self accessibleMultiLineText ] ) { 668 return [ AquaA11yTextWrapper rangeForLineAttributeForElement: self forParameter: line ]; 669 } else { 670 return nil; 671 } 672} 673 674#pragma mark - 675#pragma mark Accessibility Protocol 676 677-(id)accessibilityAttributeValue:(NSString *)attribute { 678 SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeValue:" << attribute << "]"); 679 // #i90575# guard NSAccessibility protocol against unwanted access 680 if ( isPopupMenuOpen ) { 681 return nil; 682 } 683 684 id value = nil; 685 // if we are no longer in the wrapper repository, we have been disposed 686 AquaA11yWrapper * theWrapper = [ AquaA11yFactory wrapperForAccessibleContext: [ self accessibleContext ] createIfNotExists: NO ]; 687 if ( theWrapper || mIsTableCell ) { 688 try { 689 SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: NO ]; 690 if ( [ self respondsToSelector: methodSelector ] ) { 691 value = [ self performSelector: methodSelector ]; 692 } 693 } catch ( const DisposedException & ) { 694 mIsTableCell = NO; // just to be sure 695 [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ]; 696 return nil; 697 } catch ( const Exception & ) { 698 // empty 699 } 700 } 701 if ( theWrapper ) { 702 [ theWrapper release ]; // the above called method calls retain on the returned Wrapper 703 } 704 return value; 705} 706 707-(BOOL)accessibilityIsIgnored { 708 SAL_INFO("vcl.a11y", "[" << self << " accessibilityIsIgnored]"); 709 // #i90575# guard NSAccessibility protocol against unwanted access 710 if ( isPopupMenuOpen ) { 711 return NO; 712 } 713 bool ignored = false; 714 sal_Int16 nRole = [ self accessibleContext ] -> getAccessibleRole(); 715 switch ( nRole ) { 716 //case AccessibleRole::PANEL: 717 case AccessibleRole::FRAME: 718 case AccessibleRole::ROOT_PANE: 719 case AccessibleRole::SEPARATOR: 720 case AccessibleRole::FILLER: 721 case AccessibleRole::DIALOG: 722 ignored = true; 723 break; 724 default: 725 ignored = ! ( [ self accessibleContext ] -> getAccessibleStateSet() -> contains ( AccessibleStateType::VISIBLE ) ); 726 break; 727 } 728 return ignored; // TODO: to be completed 729} 730 731-(NSArray *)accessibilityAttributeNames { 732 SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeNames]"); 733 // #i90575# guard NSAccessibility protocol against unwanted access 734 if ( isPopupMenuOpen ) { 735 return nil; 736 } 737 NSString * nativeSubrole = nil; 738 NSString * title = nil; 739 NSMutableArray * attributeNames = nil; 740 sal_Int32 nAccessibleChildren = 0; 741 try { 742 // Default Attributes 743 attributeNames = [ NSMutableArray arrayWithObjects: 744 NSAccessibilityRoleAttribute, 745 NSAccessibilityDescriptionAttribute, 746 NSAccessibilityParentAttribute, 747 NSAccessibilityWindowAttribute, 748 NSAccessibilityHelpAttribute, 749 NSAccessibilityTopLevelUIElementAttribute, 750 NSAccessibilityRoleDescriptionAttribute, 751 nil ]; 752 nativeSubrole = static_cast<NSString *>([ AquaA11yRoleHelper getNativeSubroleFrom: [ self accessibleContext ] -> getAccessibleRole() ]); 753 title = static_cast<NSString *>([ self titleAttribute ]); 754 Reference < XAccessibleRelationSet > rxRelationSet = [ self accessibleContext ] -> getAccessibleRelationSet(); 755 // Special Attributes depending on attribute values 756 if ( nativeSubrole && ! [ nativeSubrole isEqualToString: @"" ] ) { 757 [ attributeNames addObject: NSAccessibilitySubroleAttribute ]; 758 } 759 try 760 { 761 nAccessibleChildren = [ self accessibleContext ] -> getAccessibleChildCount(); 762 if ( nAccessibleChildren > 0 ) { 763 [ attributeNames addObject: NSAccessibilityChildrenAttribute ]; 764 } 765 } 766 catch( DisposedException& ) {} 767 catch( RuntimeException& ) {} 768 769 if ( title && ! [ title isEqualToString: @"" ] ) { 770 [ attributeNames addObject: NSAccessibilityTitleAttribute ]; 771 } 772 if ( [ title length ] == 0 && rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABELED_BY ) ) { 773 [ attributeNames addObject: NSAccessibilityTitleUIElementAttribute ]; 774 } 775 if ( rxRelationSet.is() && rxRelationSet -> containsRelation ( AccessibleRelationType::LABEL_FOR ) ) { 776 [ attributeNames addObject: NSAccessibilityServesAsTitleForUIElementsAttribute ]; 777 } 778 // Special Attributes depending on interface 779 if( [self accessibleContext ] -> getAccessibleRole() == AccessibleRole::TABLE ) 780 [AquaA11yTableWrapper addAttributeNamesTo: attributeNames object: self]; 781 782 if ( [ self accessibleText ] ) { 783 [ AquaA11yTextWrapper addAttributeNamesTo: attributeNames ]; 784 } 785 if ( [ self accessibleComponent ] ) { 786 [ AquaA11yComponentWrapper addAttributeNamesTo: attributeNames ]; 787 } 788 if ( [ self accessibleSelection ] ) { 789 [ AquaA11ySelectionWrapper addAttributeNamesTo: attributeNames ]; 790 } 791 if ( [ self accessibleValue ] ) { 792 [ AquaA11yValueWrapper addAttributeNamesTo: attributeNames ]; 793 } 794 [ nativeSubrole release ]; 795 [ title release ]; 796 return attributeNames; 797 } catch ( DisposedException & ) { // Object is no longer available 798 if ( nativeSubrole ) { 799 [ nativeSubrole release ]; 800 } 801 if ( title ) { 802 [ title release ]; 803 } 804 if ( attributeNames ) { 805 [ attributeNames release ]; 806 } 807 [ AquaA11yFactory removeFromWrapperRepositoryFor: [ self accessibleContext ] ]; 808 return [ [ NSArray alloc ] init ]; 809 } 810} 811 812-(BOOL)accessibilityIsAttributeSettable:(NSString *)attribute { 813 SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeIsSettable:" << attribute << "]"); 814 bool isSettable = false; 815 if ( [ self accessibleText ] ) { 816 isSettable = [ AquaA11yTextWrapper isAttributeSettable: attribute forElement: self ]; 817 } 818 if ( ! isSettable && [ self accessibleComponent ] ) { 819 isSettable = [ AquaA11yComponentWrapper isAttributeSettable: attribute forElement: self ]; 820 } 821 if ( ! isSettable && [ self accessibleSelection ] ) { 822 isSettable = [ AquaA11ySelectionWrapper isAttributeSettable: attribute forElement: self ]; 823 } 824 if ( ! isSettable && [ self accessibleValue ] ) { 825 isSettable = [ AquaA11yValueWrapper isAttributeSettable: attribute forElement: self ]; 826 } 827 return isSettable; // TODO: to be completed 828} 829 830-(NSArray *)accessibilityParameterizedAttributeNames { 831 SAL_INFO("vcl.a11y", "[" << self << " accessibilityParameterizedAttributeNames]"); 832 NSMutableArray * attributeNames = [ [ NSMutableArray alloc ] init ]; 833 // Special Attributes depending on interface 834 if ( [ self accessibleText ] ) { 835 [ AquaA11yTextWrapper addParameterizedAttributeNamesTo: attributeNames ]; 836 } 837 return attributeNames; // TODO: to be completed 838} 839 840-(id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter { 841 SAL_INFO("vcl.a11y", "[" << self << " accessibilityAttributeValue:" << attribute << " forParameter:" << (static_cast<NSObject*>(parameter)) << "]"); 842 SEL methodSelector = [ self selectorForAttribute: attribute asGetter: YES withGetterParameter: YES ]; 843 if ( [ self respondsToSelector: methodSelector ] ) { 844 return [ self performSelector: methodSelector withObject: parameter ]; 845 } 846 return nil; // TODO: to be completed 847} 848 849-(BOOL)accessibilitySetOverrideValue:(id)value forAttribute:(NSString *)attribute 850{ 851 SAL_INFO("vcl.a11y", "[" << self << " accessibilitySetOverrideValue:" << (static_cast<NSObject*>(value)) << " forAttribute:" << attribute << "]"); 852 return NO; // TODO 853} 854 855-(void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute { 856 SAL_INFO("vcl.a11y", "[" << self << " accessibilitySetValue:" << (static_cast<NSObject*>(value)) << " forAttribute:" << attribute << "]"); 857 SEL methodSelector = [ self selectorForAttribute: attribute asGetter: NO withGetterParameter: NO ]; 858 if ( [ AquaA11yComponentWrapper respondsToSelector: methodSelector ] ) { 859 [ AquaA11yComponentWrapper performSelector: methodSelector withObject: self withObject: value ]; 860 } 861 if ( [ AquaA11yTextWrapper respondsToSelector: methodSelector ] ) { 862 [ AquaA11yTextWrapper performSelector: methodSelector withObject: self withObject: value ]; 863 } 864 if ( [ AquaA11ySelectionWrapper respondsToSelector: methodSelector ] ) { 865 [ AquaA11ySelectionWrapper performSelector: methodSelector withObject: self withObject: value ]; 866 } 867 if ( [ AquaA11yValueWrapper respondsToSelector: methodSelector ] ) { 868 [ AquaA11yValueWrapper performSelector: methodSelector withObject: self withObject: value ]; 869 } 870} 871 872-(id)accessibilityFocusedUIElement { 873 SAL_INFO("vcl.a11y", "[" << self << " accessibilityFocusedUIElement]"); 874 // #i90575# guard NSAccessibility protocol against unwanted access 875 if ( isPopupMenuOpen ) { 876 return nil; 877 } 878 879 // as this seems to be the first API call on a newly created SalFrameView object, 880 // make sure self gets registered in the repository .. 881 [ self accessibleContext ]; 882 883 AquaA11yWrapper * focusedUIElement = AquaA11yFocusListener::get()->getFocusedUIElement(); 884// AquaA11yWrapper * ancestor = focusedUIElement; 885 886 // Make sure the focused object is a descendant of self 887// do { 888// if( self == ancestor ) 889 return focusedUIElement; 890 891// ancestor = [ ancestor accessibilityAttributeValue: NSAccessibilityParentAttribute ]; 892// } while( nil != ancestor ); 893 894 return self; 895} 896 897-(NSString *)accessibilityActionDescription:(NSString *)action { 898 SAL_INFO("vcl.a11y", "[" << self << " accessibilityActionDescription:" << action << "]"); 899 return NSAccessibilityActionDescription(action); 900} 901 902-(AquaA11yWrapper *)actionResponder { 903 AquaA11yWrapper * wrapper = nil; 904 // get some information 905 NSString * role = static_cast<NSString *>([ self accessibilityAttributeValue: NSAccessibilityRoleAttribute ]); 906 id enabledAttr = [ self enabledAttribute ]; 907 bool enabled = [ enabledAttr boolValue ]; 908 NSView * parent = static_cast<NSView *>([ self accessibilityAttributeValue: NSAccessibilityParentAttribute ]); 909 AquaA11yWrapper * parentAsWrapper = nil; 910 if ( [ parent isKindOfClass: [ AquaA11yWrapper class ] ] ) { 911 parentAsWrapper = static_cast<AquaA11yWrapper *>(parent); 912 } 913 SAL_WNODEPRECATED_DECLARATIONS_PUSH 914 //TODO: 10.10 accessibilityAttributeValue: 915 NSString * parentRole = static_cast<NSString *>([ parent accessibilityAttributeValue: NSAccessibilityRoleAttribute ]); 916 SAL_WNODEPRECATED_DECLARATIONS_POP 917 // if we are a textarea inside a combobox, then the combobox is the action responder 918 if ( enabled 919 && [ role isEqualToString: NSAccessibilityTextAreaRole ] 920 && [ parentRole isEqualToString: NSAccessibilityComboBoxRole ] 921 && parentAsWrapper ) { 922 wrapper = parentAsWrapper; 923 } else if ( enabled && [ self accessibleAction ] ) { 924 wrapper = self ; 925 } 926 [ parentRole release ]; 927 [ enabledAttr release ]; 928 [ role release ]; 929 return wrapper; 930} 931 932-(void)accessibilityPerformAction:(NSString *)action { 933 SAL_INFO("vcl.a11y", "[" << self << " accessibilityPerformAction:" << action << "]"); 934 AquaA11yWrapper * actionResponder = [ self actionResponder ]; 935 if ( actionResponder ) { 936 [ AquaA11yActionWrapper doAction: action ofElement: actionResponder ]; 937 } 938} 939 940-(NSArray *)accessibilityActionNames { 941 SAL_INFO("vcl.a11y", "[" << self << " accessibilityActionNames]"); 942 NSArray * actionNames = nil; 943 AquaA11yWrapper * actionResponder = [ self actionResponder ]; 944 if ( actionResponder ) { 945 actionNames = [ AquaA11yActionWrapper actionNamesForElement: actionResponder ]; 946 } else { 947 actionNames = [ [ NSArray alloc ] init ]; 948 } 949 return actionNames; 950} 951 952#pragma mark - 953#pragma mark Hit Test 954 955-(BOOL)isViewElement:(NSObject *)viewElement hitByPoint:(NSPoint)point { 956 bool hit = false; 957 NSAutoreleasePool * pool = [ [ NSAutoreleasePool alloc ] init ]; 958 SAL_WNODEPRECATED_DECLARATIONS_PUSH 959 //TODO: 10.10 accessibilityAttributeValue: 960 NSValue * position = [ viewElement accessibilityAttributeValue: NSAccessibilityPositionAttribute ]; 961 NSValue * size = [ viewElement accessibilityAttributeValue: NSAccessibilitySizeAttribute ]; 962 SAL_WNODEPRECATED_DECLARATIONS_POP 963 if ( position && size ) { 964 float minX = [ position pointValue ].x; 965 float minY = [ position pointValue ].y; 966 float maxX = minX + [ size sizeValue ].width; 967 float maxY = minY + [ size sizeValue ].height; 968 if ( minX < point.x && maxX > point.x && minY < point.y && maxY > point.y ) { 969 hit = true; 970 } 971 } 972 [ pool release ]; 973 return hit; 974} 975 976static Reference < XAccessibleContext > hitTestRunner ( css::awt::Point point, 977 Reference < XAccessibleContext > const & rxAccessibleContext ) { 978 Reference < XAccessibleContext > hitChild; 979 Reference < XAccessibleContext > emptyReference; 980 try { 981 Reference < XAccessibleComponent > rxAccessibleComponent ( rxAccessibleContext, UNO_QUERY ); 982 if ( rxAccessibleComponent.is() ) { 983 css::awt::Point location = rxAccessibleComponent -> getLocationOnScreen(); 984 css::awt::Point hitPoint ( point.X - location.X , point.Y - location.Y); 985 Reference < XAccessible > rxAccessible = rxAccessibleComponent -> getAccessibleAtPoint ( hitPoint ); 986 if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() && 987 rxAccessible -> getAccessibleContext() -> getAccessibleChildCount() == 0 ) { 988 hitChild = rxAccessible -> getAccessibleContext(); 989 } 990 } 991 992 // iterate the hierarchy looking doing recursive hit testing. 993 // apparently necessary as a special treatment for e.g. comboboxes 994 if ( !hitChild.is() ) { 995 bool bSafeToIterate = true; 996 sal_Int32 nCount = rxAccessibleContext -> getAccessibleChildCount(); 997 998 if (nCount < 0 || nCount > SAL_MAX_UINT16 /* slow enough for anyone */) 999 bSafeToIterate = false; 1000 else { // manages descendants is an horror from the a11y standards guys. 1001 Reference< XAccessibleStateSet > xStateSet; 1002 xStateSet = rxAccessibleContext -> getAccessibleStateSet(); 1003 if (xStateSet.is() && xStateSet -> contains(AccessibleStateType::MANAGES_DESCENDANTS ) ) 1004 bSafeToIterate = false; 1005 } 1006 1007 if( bSafeToIterate ) { 1008 for ( int i = 0; i < rxAccessibleContext -> getAccessibleChildCount(); i++ ) { 1009 Reference < XAccessible > rxAccessibleChild = rxAccessibleContext -> getAccessibleChild ( i ); 1010 if ( rxAccessibleChild.is() && rxAccessibleChild -> getAccessibleContext().is() && rxAccessibleChild -> getAccessibleContext() -> getAccessibleRole() != AccessibleRole::LIST ) { 1011 Reference < XAccessibleContext > myHitChild = hitTestRunner ( point, rxAccessibleChild -> getAccessibleContext() ); 1012 if ( myHitChild.is() ) { 1013 hitChild = myHitChild; 1014 break; 1015 } 1016 } 1017 } 1018 } 1019 } 1020 } catch ( RuntimeException ) { 1021 return emptyReference; 1022 } 1023 return hitChild; 1024} 1025 1026-(id)accessibilityHitTest:(NSPoint)point { 1027 SAL_INFO("vcl.a11y", "[" << self << " accessibilityHitTest:" << point << "]"); 1028 static id wrapper = nil; 1029 if ( nil != wrapper ) { 1030 [ wrapper release ]; 1031 wrapper = nil; 1032 } 1033 Reference < XAccessibleContext > hitChild; 1034 NSRect screenRect = [ [ NSScreen mainScreen ] frame ]; 1035 css::awt::Point hitPoint ( static_cast<sal_Int32>(point.x) , static_cast<sal_Int32>(screenRect.size.height - point.y) ); 1036 // check child windows first 1037 NSWindow * window = static_cast<NSWindow *>([ self accessibilityAttributeValue: NSAccessibilityWindowAttribute ]); 1038 NSArray * childWindows = [ window childWindows ]; 1039 if ( [ childWindows count ] > 0 ) { 1040 NSWindow * element = nil; 1041 NSEnumerator * enumerator = [ childWindows objectEnumerator ]; 1042 while ( ( element = [ enumerator nextObject ] ) && !hitChild.is() ) { 1043 if ( [ element isKindOfClass: [ SalFrameWindow class ] ] && [ self isViewElement: element hitByPoint: point ] ) { 1044 // we have a child window that is hit 1045 Reference < XAccessibleRelationSet > relationSet = [ static_cast<SalFrameWindow *>(element) accessibleContext ] -> getAccessibleRelationSet(); 1046 if ( relationSet.is() && relationSet -> containsRelation ( AccessibleRelationType::SUB_WINDOW_OF )) { 1047 // we have a valid relation to the parent element 1048 AccessibleRelation const relation = relationSet -> getRelationByType ( AccessibleRelationType::SUB_WINDOW_OF ); 1049 for ( const auto & i : relation.TargetSet ) { 1050 Reference < XAccessible > rxAccessible ( i, UNO_QUERY ); 1051 if ( rxAccessible.is() && rxAccessible -> getAccessibleContext().is() ) { 1052 // hit test for children of parent 1053 hitChild = hitTestRunner ( hitPoint, rxAccessible -> getAccessibleContext() ); 1054 if (hitChild.is()) 1055 break; 1056 } 1057 } 1058 } 1059 } 1060 } 1061 } 1062 // nothing hit yet, so check ourself 1063 if ( ! hitChild.is() ) { 1064 if ( !mpReferenceWrapper ) { 1065 [ self setDefaults: [ self accessibleContext ] ]; 1066 } 1067 hitChild = hitTestRunner ( hitPoint, mpReferenceWrapper -> rAccessibleContext ); 1068 } 1069 if ( hitChild.is() ) { 1070 wrapper = [ AquaA11yFactory wrapperForAccessibleContext: hitChild ]; 1071 } 1072 if ( wrapper ) { 1073 [ wrapper retain ]; // TODO: retain only when transient ? 1074 } 1075 return wrapper; 1076} 1077 1078#pragma mark - 1079#pragma mark Access Methods 1080 1081-(XAccessibleAction *)accessibleAction { 1082 return mpReferenceWrapper -> rAccessibleAction.get(); 1083} 1084 1085-(XAccessibleContext *)accessibleContext { 1086 return mpReferenceWrapper -> rAccessibleContext.get(); 1087} 1088 1089-(XAccessibleComponent *)accessibleComponent { 1090 return mpReferenceWrapper -> rAccessibleComponent.get(); 1091} 1092 1093-(XAccessibleExtendedComponent *)accessibleExtendedComponent { 1094 return mpReferenceWrapper -> rAccessibleExtendedComponent.get(); 1095} 1096 1097-(XAccessibleSelection *)accessibleSelection { 1098 return mpReferenceWrapper -> rAccessibleSelection.get(); 1099} 1100 1101-(XAccessibleTable *)accessibleTable { 1102 return mpReferenceWrapper -> rAccessibleTable.get(); 1103} 1104 1105-(XAccessibleText *)accessibleText { 1106 return mpReferenceWrapper -> rAccessibleText.get(); 1107} 1108 1109-(XAccessibleEditableText *)accessibleEditableText { 1110 return mpReferenceWrapper -> rAccessibleEditableText.get(); 1111} 1112 1113-(XAccessibleValue *)accessibleValue { 1114 return mpReferenceWrapper -> rAccessibleValue.get(); 1115} 1116 1117-(XAccessibleTextAttributes *)accessibleTextAttributes { 1118 return mpReferenceWrapper -> rAccessibleTextAttributes.get(); 1119} 1120 1121-(XAccessibleMultiLineText *)accessibleMultiLineText { 1122 return mpReferenceWrapper -> rAccessibleMultiLineText.get(); 1123} 1124 1125-(XAccessibleTextMarkup *)accessibleTextMarkup { 1126 return mpReferenceWrapper -> rAccessibleTextMarkup.get(); 1127} 1128 1129-(NSWindow*)windowForParent { 1130 return [self window]; 1131} 1132 1133-(void)setActsAsRadioGroup:(BOOL)actsAsRadioGroup { 1134 mActsAsRadioGroup = actsAsRadioGroup; 1135} 1136 1137-(BOOL)actsAsRadioGroup { 1138 return mActsAsRadioGroup; 1139} 1140 1141+(void)setPopupMenuOpen:(BOOL)popupMenuOpen { 1142 isPopupMenuOpen = popupMenuOpen; 1143} 1144 1145@end 1146 1147/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 1148