1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_accessibility.hxx" 26 #include "accessibility/extended/AccessibleBrowseBoxBase.hxx" 27 #include <svtools/accessibletableprovider.hxx> 28 #include <rtl/uuid.h> 29 // 30 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 31 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 32 #include <unotools/accessiblerelationsethelper.hxx> 33 34 // ============================================================================ 35 36 using ::rtl::OUString; 37 38 using ::com::sun::star::uno::Reference; 39 using ::com::sun::star::uno::Sequence; 40 using ::com::sun::star::uno::Any; 41 42 using namespace ::com::sun::star; 43 using namespace ::com::sun::star::accessibility; 44 using namespace ::comphelper; 45 using namespace ::svt; 46 47 48 // ============================================================================ 49 50 namespace accessibility { 51 52 using namespace com::sun::star::accessibility::AccessibleStateType; 53 // ============================================================================ 54 55 // Ctor/Dtor/disposing -------------------------------------------------------- 56 57 DBG_NAME( AccessibleBrowseBoxBase ) 58 59 AccessibleBrowseBoxBase::AccessibleBrowseBoxBase( 60 const Reference< XAccessible >& rxParent, 61 IAccessibleTableProvider& rBrowseBox, 62 const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& _xFocusWindow, 63 AccessibleBrowseBoxObjType eObjType ) : 64 AccessibleBrowseBoxImplHelper( m_aMutex ), 65 mxParent( rxParent ), 66 mpBrowseBox( &rBrowseBox ), 67 m_xFocusWindow(_xFocusWindow), 68 maName( rBrowseBox.GetAccessibleObjectName( eObjType ) ), 69 maDescription( rBrowseBox.GetAccessibleObjectDescription( eObjType ) ), 70 meObjType( eObjType ), 71 m_aClientId(0) 72 { 73 DBG_CTOR( AccessibleBrowseBoxBase, NULL ); 74 if ( m_xFocusWindow.is() ) 75 m_xFocusWindow->addFocusListener( this ); 76 } 77 78 AccessibleBrowseBoxBase::AccessibleBrowseBoxBase( 79 const Reference< XAccessible >& rxParent, 80 IAccessibleTableProvider& rBrowseBox, 81 const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& _xFocusWindow, 82 AccessibleBrowseBoxObjType eObjType, 83 const ::rtl::OUString& rName, 84 const ::rtl::OUString& rDescription ) : 85 AccessibleBrowseBoxImplHelper( m_aMutex ), 86 mxParent( rxParent ), 87 mpBrowseBox( &rBrowseBox ), 88 m_xFocusWindow(_xFocusWindow), 89 maName( rName ), 90 maDescription( rDescription ), 91 meObjType( eObjType ), 92 m_aClientId(0) 93 { 94 DBG_CTOR( AccessibleBrowseBoxBase, NULL ); 95 if ( m_xFocusWindow.is() ) 96 m_xFocusWindow->addFocusListener( this ); 97 } 98 99 AccessibleBrowseBoxBase::~AccessibleBrowseBoxBase() 100 { 101 DBG_DTOR( AccessibleBrowseBoxBase, NULL ); 102 103 if( isAlive() ) 104 { 105 // increment ref count to prevent double call of Dtor 106 osl_incrementInterlockedCount( &m_refCount ); 107 dispose(); 108 } 109 } 110 111 void SAL_CALL AccessibleBrowseBoxBase::disposing() 112 { 113 ::osl::MutexGuard aGuard( getOslMutex() ); 114 if ( m_xFocusWindow.is() ) 115 { 116 BBSolarGuard aSolarGuard; 117 m_xFocusWindow->removeFocusListener( this ); 118 } 119 120 if ( getClientId( ) ) 121 { 122 AccessibleEventNotifier::TClientId nId( getClientId( ) ); 123 setClientId( 0 ); 124 AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this ); 125 } 126 127 mxParent = NULL; 128 mpBrowseBox = NULL; 129 } 130 131 // XAccessibleContext --------------------------------------------------------- 132 133 Reference< XAccessible > SAL_CALL AccessibleBrowseBoxBase::getAccessibleParent() 134 { 135 ::osl::MutexGuard aGuard( getOslMutex() ); 136 ensureIsAlive(); 137 return mxParent; 138 } 139 140 sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getAccessibleIndexInParent() 141 { 142 ::osl::MutexGuard aGuard( getOslMutex() ); 143 ensureIsAlive(); 144 145 // -1 for child not found/no parent (according to specification) 146 sal_Int32 nRet = -1; 147 148 Reference< uno::XInterface > xMeMyselfAndI( static_cast< XAccessibleContext* >( this ), uno::UNO_QUERY ); 149 150 // iterate over parent's children and search for this object 151 if( mxParent.is() ) 152 { 153 Reference< XAccessibleContext > 154 xParentContext( mxParent->getAccessibleContext() ); 155 if( xParentContext.is() ) 156 { 157 Reference< uno::XInterface > xChild; 158 159 sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); 160 for( sal_Int32 nChild = 0; nChild < nChildCount; ++nChild ) 161 { 162 xChild = xChild.query( xParentContext->getAccessibleChild( nChild ) ); 163 164 if ( xMeMyselfAndI.get() == xChild.get() ) 165 { 166 nRet = nChild; 167 break; 168 } 169 } 170 } 171 } 172 return nRet; 173 } 174 175 OUString SAL_CALL AccessibleBrowseBoxBase::getAccessibleDescription() 176 { 177 ::osl::MutexGuard aGuard( getOslMutex() ); 178 ensureIsAlive(); 179 return maDescription; 180 } 181 182 OUString SAL_CALL AccessibleBrowseBoxBase::getAccessibleName() 183 { 184 ::osl::MutexGuard aGuard( getOslMutex() ); 185 ensureIsAlive(); 186 return maName; 187 } 188 189 Reference< XAccessibleRelationSet > SAL_CALL 190 AccessibleBrowseBoxBase::getAccessibleRelationSet() 191 { 192 ensureIsAlive(); 193 // BrowseBox does not have relations. 194 return new utl::AccessibleRelationSetHelper; 195 } 196 197 Reference< XAccessibleStateSet > SAL_CALL 198 AccessibleBrowseBoxBase::getAccessibleStateSet() 199 { 200 BBSolarGuard aSolarGuard; 201 ::osl::MutexGuard aGuard( getOslMutex() ); 202 // don't check whether alive -> StateSet may contain DEFUNC 203 return implCreateStateSetHelper(); 204 } 205 206 lang::Locale SAL_CALL AccessibleBrowseBoxBase::getLocale() 207 { 208 ::osl::MutexGuard aGuard( getOslMutex() ); 209 ensureIsAlive(); 210 if( mxParent.is() ) 211 { 212 Reference< XAccessibleContext > 213 xParentContext( mxParent->getAccessibleContext() ); 214 if( xParentContext.is() ) 215 return xParentContext->getLocale(); 216 } 217 throw IllegalAccessibleComponentStateException(); 218 } 219 220 // XAccessibleComponent ------------------------------------------------------- 221 222 sal_Bool SAL_CALL AccessibleBrowseBoxBase::containsPoint( const awt::Point& rPoint ) 223 { 224 return Rectangle( Point(), getBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint ) ); 225 } 226 227 awt::Rectangle SAL_CALL AccessibleBrowseBoxBase::getBounds() 228 { 229 return AWTRectangle( getBoundingBox() ); 230 } 231 232 awt::Point SAL_CALL AccessibleBrowseBoxBase::getLocation() 233 { 234 return AWTPoint( getBoundingBox().TopLeft() ); 235 } 236 237 awt::Point SAL_CALL AccessibleBrowseBoxBase::getLocationOnScreen() 238 { 239 return AWTPoint( getBoundingBoxOnScreen().TopLeft() ); 240 } 241 242 awt::Size SAL_CALL AccessibleBrowseBoxBase::getSize() 243 { 244 return AWTSize( getBoundingBox().GetSize() ); 245 } 246 247 sal_Bool SAL_CALL AccessibleBrowseBoxBase::isShowing() 248 { 249 BBSolarGuard aSolarGuard; 250 ::osl::MutexGuard aGuard( getOslMutex() ); 251 ensureIsAlive(); 252 return implIsShowing(); 253 } 254 255 sal_Bool SAL_CALL AccessibleBrowseBoxBase::isVisible() 256 { 257 Reference< XAccessibleStateSet > xStateSet = getAccessibleStateSet(); 258 return xStateSet.is() ? 259 xStateSet->contains( AccessibleStateType::VISIBLE ) : sal_False; 260 } 261 262 sal_Bool SAL_CALL AccessibleBrowseBoxBase::isFocusTraversable() 263 { 264 Reference< XAccessibleStateSet > xStateSet = getAccessibleStateSet(); 265 return xStateSet.is() ? 266 xStateSet->contains( AccessibleStateType::FOCUSABLE ) : sal_False; 267 } 268 269 void SAL_CALL AccessibleBrowseBoxBase::focusGained( const ::com::sun::star::awt::FocusEvent& ) 270 { 271 com::sun::star::uno::Any aFocused; 272 com::sun::star::uno::Any aEmpty; 273 aFocused <<= FOCUSED; 274 275 commitEvent(AccessibleEventId::STATE_CHANGED,aFocused,aEmpty); 276 } 277 // ----------------------------------------------------------------------------- 278 279 void SAL_CALL AccessibleBrowseBoxBase::focusLost( const ::com::sun::star::awt::FocusEvent& ) 280 { 281 com::sun::star::uno::Any aFocused; 282 com::sun::star::uno::Any aEmpty; 283 aFocused <<= FOCUSED; 284 285 commitEvent(AccessibleEventId::STATE_CHANGED,aEmpty,aFocused); 286 } 287 // XAccessibleEventBroadcaster ------------------------------------------------ 288 289 void SAL_CALL AccessibleBrowseBoxBase::addEventListener( 290 const Reference< XAccessibleEventListener>& _rxListener ) 291 { 292 if ( _rxListener.is() ) 293 { 294 ::osl::MutexGuard aGuard( getOslMutex() ); 295 if ( !getClientId( ) ) 296 setClientId( AccessibleEventNotifier::registerClient( ) ); 297 298 AccessibleEventNotifier::addEventListener( getClientId( ), _rxListener ); 299 } 300 } 301 302 void SAL_CALL AccessibleBrowseBoxBase::removeEventListener( 303 const Reference< XAccessibleEventListener>& _rxListener ) 304 { 305 if( _rxListener.is() && getClientId( ) ) 306 { 307 ::osl::MutexGuard aGuard( getOslMutex() ); 308 sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( getClientId( ), _rxListener ); 309 if ( !nListenerCount ) 310 { 311 // no listeners anymore 312 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), 313 // and at least to us not firing any events anymore, in case somebody calls 314 // NotifyAccessibleEvent, again 315 316 AccessibleEventNotifier::TClientId nId( getClientId( ) ); 317 setClientId( 0 ); 318 AccessibleEventNotifier::revokeClient( nId ); 319 } 320 } 321 } 322 323 // XTypeProvider -------------------------------------------------------------- 324 325 Sequence< sal_Int8 > SAL_CALL AccessibleBrowseBoxBase::getImplementationId() 326 { 327 ::osl::MutexGuard aGuard( getOslGlobalMutex() ); 328 static Sequence< sal_Int8 > aId; 329 implCreateUuid( aId ); 330 return aId; 331 } 332 333 // XServiceInfo --------------------------------------------------------------- 334 335 sal_Bool SAL_CALL AccessibleBrowseBoxBase::supportsService( 336 const OUString& rServiceName ) 337 { 338 ::osl::MutexGuard aGuard( getOslMutex() ); 339 340 Sequence< OUString > aSupportedServices( getSupportedServiceNames() ); 341 const OUString* pArrBegin = aSupportedServices.getConstArray(); 342 const OUString* pArrEnd = pArrBegin + aSupportedServices.getLength(); 343 const OUString* pString = pArrBegin; 344 345 for( ; ( pString != pArrEnd ) && ( rServiceName != *pString ); ++pString ) 346 ; 347 348 return pString != pArrEnd; 349 } 350 351 Sequence< OUString > SAL_CALL AccessibleBrowseBoxBase::getSupportedServiceNames() 352 { 353 const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleContext" ) ); 354 return Sequence< OUString >( &aServiceName, 1 ); 355 } 356 357 // other public methods ------------------------------------------------------- 358 359 void AccessibleBrowseBoxBase::setAccessibleName( const OUString& rName ) 360 { 361 ::osl::ClearableMutexGuard aGuard( getOslMutex() ); 362 Any aOld; 363 aOld <<= maName; 364 maName = rName; 365 366 aGuard.clear(); 367 368 commitEvent( 369 AccessibleEventId::NAME_CHANGED, 370 uno::makeAny( maName ), 371 aOld ); 372 } 373 374 void AccessibleBrowseBoxBase::setAccessibleDescription( const OUString& rDescription ) 375 { 376 ::osl::ClearableMutexGuard aGuard( getOslMutex() ); 377 Any aOld; 378 aOld <<= maDescription; 379 maDescription = rDescription; 380 381 aGuard.clear(); 382 383 commitEvent( 384 AccessibleEventId::DESCRIPTION_CHANGED, 385 uno::makeAny( maDescription ), 386 aOld ); 387 } 388 389 // internal virtual methods --------------------------------------------------- 390 391 sal_Bool AccessibleBrowseBoxBase::implIsShowing() 392 { 393 sal_Bool bShowing = sal_False; 394 if( mxParent.is() ) 395 { 396 Reference< XAccessibleComponent > 397 xParentComp( mxParent->getAccessibleContext(), uno::UNO_QUERY ); 398 if( xParentComp.is() ) 399 bShowing = implGetBoundingBox().IsOver( 400 VCLRectangle( xParentComp->getBounds() ) ); 401 } 402 return bShowing; 403 } 404 405 ::utl::AccessibleStateSetHelper* AccessibleBrowseBoxBase::implCreateStateSetHelper() 406 { 407 ::utl::AccessibleStateSetHelper* 408 pStateSetHelper = new ::utl::AccessibleStateSetHelper; 409 410 if( isAlive() ) 411 { 412 // SHOWING done with mxParent 413 if( implIsShowing() ) 414 pStateSetHelper->AddState( AccessibleStateType::SHOWING ); 415 // BrowseBox fills StateSet with states depending on object type 416 mpBrowseBox->FillAccessibleStateSet( *pStateSetHelper, getType() ); 417 } 418 else 419 pStateSetHelper->AddState( AccessibleStateType::DEFUNC ); 420 421 return pStateSetHelper; 422 } 423 424 // internal helper methods ---------------------------------------------------- 425 426 sal_Bool AccessibleBrowseBoxBase::isAlive() const 427 { 428 return !rBHelper.bDisposed && !rBHelper.bInDispose && mpBrowseBox; 429 } 430 431 void AccessibleBrowseBoxBase::ensureIsAlive() const 432 { 433 if( !isAlive() ) 434 throw lang::DisposedException(); 435 } 436 437 Rectangle AccessibleBrowseBoxBase::getBoundingBox() 438 { 439 BBSolarGuard aSolarGuard; 440 ::osl::MutexGuard aGuard( getOslMutex() ); 441 ensureIsAlive(); 442 Rectangle aRect = implGetBoundingBox(); 443 if ( 0 == aRect.Left() && 0 == aRect.Top() && 0 == aRect.Right() && 0 == aRect.Bottom() ) 444 { 445 DBG_ERRORFILE( "shit" ); 446 } 447 return aRect; 448 } 449 450 Rectangle AccessibleBrowseBoxBase::getBoundingBoxOnScreen() 451 { 452 BBSolarGuard aSolarGuard; 453 ::osl::MutexGuard aGuard( getOslMutex() ); 454 ensureIsAlive(); 455 Rectangle aRect = implGetBoundingBoxOnScreen(); 456 if ( 0 == aRect.Left() && 0 == aRect.Top() && 0 == aRect.Right() && 0 == aRect.Bottom() ) 457 { 458 DBG_ERRORFILE( "shit" ); 459 } 460 return aRect; 461 } 462 463 void AccessibleBrowseBoxBase::commitEvent( 464 sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue ) 465 { 466 ::osl::ClearableMutexGuard aGuard( getOslMutex() ); 467 if ( !getClientId( ) ) 468 // if we don't have a client id for the notifier, then we don't have listeners, then 469 // we don't need to notify anything 470 return; 471 472 // build an event object 473 AccessibleEventObject aEvent; 474 aEvent.Source = *this; 475 aEvent.EventId = _nEventId; 476 aEvent.OldValue = _rOldValue; 477 aEvent.NewValue = _rNewValue; 478 479 // let the notifier handle this event 480 481 AccessibleEventNotifier::addEvent( getClientId( ), aEvent ); 482 } 483 // ----------------------------------------------------------------------------- 484 485 void AccessibleBrowseBoxBase::implCreateUuid( Sequence< sal_Int8 >& rId ) 486 { 487 if( !rId.hasElements() ) 488 { 489 rId.realloc( 16 ); 490 rtl_createUuid( reinterpret_cast< sal_uInt8* >( rId.getArray() ), 0, sal_True ); 491 } 492 } 493 // ----------------------------------------------------------------------------- 494 sal_Int16 SAL_CALL AccessibleBrowseBoxBase::getAccessibleRole() 495 { 496 ensureIsAlive(); 497 sal_Int16 nRole = AccessibleRole::UNKNOWN; 498 switch ( meObjType ) 499 { 500 case BBTYPE_ROWHEADERCELL: 501 nRole = AccessibleRole::ROW_HEADER; 502 break; 503 case BBTYPE_COLUMNHEADERCELL: 504 nRole = AccessibleRole::COLUMN_HEADER; 505 break; 506 case BBTYPE_COLUMNHEADERBAR: 507 case BBTYPE_ROWHEADERBAR: 508 case BBTYPE_TABLE: 509 nRole = AccessibleRole::TABLE; 510 break; 511 case BBTYPE_TABLECELL: 512 nRole = AccessibleRole::TABLE_CELL; 513 break; 514 case BBTYPE_BROWSEBOX: 515 nRole = AccessibleRole::PANEL; 516 break; 517 case BBTYPE_CHECKBOXCELL: 518 nRole = AccessibleRole::CHECK_BOX; 519 break; 520 } 521 return nRole; 522 } 523 // ----------------------------------------------------------------------------- 524 Any SAL_CALL AccessibleBrowseBoxBase::getAccessibleKeyBinding() 525 { 526 return Any(); 527 } 528 // ----------------------------------------------------------------------------- 529 Reference<XAccessible > SAL_CALL AccessibleBrowseBoxBase::getAccessibleAtPoint( const ::com::sun::star::awt::Point& ) 530 { 531 return NULL; 532 } 533 // ----------------------------------------------------------------------------- 534 void SAL_CALL AccessibleBrowseBoxBase::disposing( const ::com::sun::star::lang::EventObject& ) 535 { 536 m_xFocusWindow = NULL; 537 } 538 // ----------------------------------------------------------------------------- 539 sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getForeground( ) 540 { 541 BBSolarGuard aSolarGuard; 542 ::osl::MutexGuard aGuard( getOslMutex() ); 543 ensureIsAlive(); 544 545 sal_Int32 nColor = 0; 546 Window* pInst = mpBrowseBox->GetWindowInstance(); 547 if ( pInst ) 548 { 549 if ( pInst->IsControlForeground() ) 550 nColor = pInst->GetControlForeground().GetColor(); 551 else 552 { 553 Font aFont; 554 if ( pInst->IsControlFont() ) 555 aFont = pInst->GetControlFont(); 556 else 557 aFont = pInst->GetFont(); 558 nColor = aFont.GetColor().GetColor(); 559 } 560 } 561 562 return nColor; 563 } 564 // ----------------------------------------------------------------------------- 565 sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getBackground( ) 566 { 567 BBSolarGuard aSolarGuard; 568 ::osl::MutexGuard aGuard( getOslMutex() ); 569 ensureIsAlive(); 570 sal_Int32 nColor = 0; 571 Window* pInst = mpBrowseBox->GetWindowInstance(); 572 if ( pInst ) 573 { 574 if ( pInst->IsControlBackground() ) 575 nColor = pInst->GetControlBackground().GetColor(); 576 else 577 nColor = pInst->GetBackground().GetColor().GetColor(); 578 } 579 580 return nColor; 581 } 582 583 // ============================================================================ 584 DBG_NAME( BrowseBoxAccessibleElement ) 585 586 // XInterface ----------------------------------------------------------------- 587 IMPLEMENT_FORWARD_XINTERFACE2( BrowseBoxAccessibleElement, AccessibleBrowseBoxBase, BrowseBoxAccessibleElement_Base ) 588 589 // XTypeProvider -------------------------------------------------------------- 590 IMPLEMENT_FORWARD_XTYPEPROVIDER2( BrowseBoxAccessibleElement, AccessibleBrowseBoxBase, BrowseBoxAccessibleElement_Base ) 591 592 // XAccessible ---------------------------------------------------------------- 593 594 Reference< XAccessibleContext > SAL_CALL BrowseBoxAccessibleElement::getAccessibleContext() 595 { 596 ensureIsAlive(); 597 return this; 598 } 599 600 // ---------------------------------------------------------------------------- 601 BrowseBoxAccessibleElement::BrowseBoxAccessibleElement( const Reference< XAccessible >& rxParent, IAccessibleTableProvider& rBrowseBox, 602 const Reference< awt::XWindow >& _xFocusWindow, AccessibleBrowseBoxObjType eObjType ) 603 :AccessibleBrowseBoxBase( rxParent, rBrowseBox, _xFocusWindow, eObjType ) 604 { 605 DBG_CTOR( BrowseBoxAccessibleElement, NULL ); 606 } 607 608 // ---------------------------------------------------------------------------- 609 BrowseBoxAccessibleElement::BrowseBoxAccessibleElement( const Reference< XAccessible >& rxParent, IAccessibleTableProvider& rBrowseBox, 610 const Reference< awt::XWindow >& _xFocusWindow, AccessibleBrowseBoxObjType eObjType, 611 const ::rtl::OUString& rName, const ::rtl::OUString& rDescription ) 612 :AccessibleBrowseBoxBase( rxParent, rBrowseBox, _xFocusWindow, eObjType, rName, rDescription ) 613 { 614 DBG_CTOR( BrowseBoxAccessibleElement, NULL ); 615 } 616 617 // ---------------------------------------------------------------------------- 618 BrowseBoxAccessibleElement::~BrowseBoxAccessibleElement( ) 619 { 620 DBG_DTOR( BrowseBoxAccessibleElement, NULL ); 621 } 622 623 // ============================================================================ 624 625 } // namespace accessibility 626 627 // ============================================================================ 628