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_toolkit.hxx" 26 27 28 #include <com/sun/star/accessibility/AccessibleRole.hpp> 29 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 30 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 31 #include <com/sun/star/accessibility/XAccessibleEventListener.hpp> 32 #include <com/sun/star/accessibility/AccessibleRelationType.hpp> 33 #include <toolkit/awt/vclxaccessiblecomponent.hxx> 34 #include <toolkit/helper/externallock.hxx> 35 #include <toolkit/awt/vclxwindow.hxx> 36 #include <toolkit/helper/convert.hxx> 37 #include <toolkit/awt/vclxfont.hxx> 38 #include <vcl/dialog.hxx> 39 #include <vcl/window.hxx> 40 #include <tools/debug.hxx> 41 #include <unotools/accessiblestatesethelper.hxx> 42 #include <unotools/accessiblerelationsethelper.hxx> 43 #include <vcl/svapp.hxx> 44 #include <vcl/menu.hxx> 45 46 #ifndef VCLEVENT_WINDOW_FRAMETITLECHANGED 47 #define VCLEVENT_WINDOW_FRAMETITLECHANGED 1018 // pData = XubString* = oldTitle 48 #endif 49 50 using namespace ::com::sun::star; 51 using namespace ::comphelper; 52 53 54 DBG_NAME(VCLXAccessibleComponent) 55 56 57 // ---------------------------------------------------- 58 // class VCLXAccessibleComponent 59 // ---------------------------------------------------- 60 VCLXAccessibleComponent::VCLXAccessibleComponent( VCLXWindow* pVCLXindow ) 61 : AccessibleExtendedComponentHelper_BASE( new VCLExternalSolarLock() ) 62 , OAccessibleImplementationAccess( ) 63 { 64 DBG_CTOR( VCLXAccessibleComponent, 0 ); 65 mpVCLXindow = pVCLXindow; 66 mxWindow = pVCLXindow; 67 68 m_pSolarLock = static_cast< VCLExternalSolarLock* >( getExternalLock( ) ); 69 70 DBG_ASSERT( pVCLXindow->GetWindow(), "VCLXAccessibleComponent - no window!" ); 71 if ( pVCLXindow->GetWindow() ) 72 { 73 pVCLXindow->GetWindow()->AddEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) ); 74 pVCLXindow->GetWindow()->AddChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) ); 75 } 76 77 // announce the XAccessible of our creator to the base class 78 lateInit( pVCLXindow ); 79 } 80 81 VCLXAccessibleComponent::~VCLXAccessibleComponent() 82 { 83 DBG_DTOR( VCLXAccessibleComponent, 0 ); 84 85 ensureDisposed(); 86 87 if ( mpVCLXindow && mpVCLXindow->GetWindow() ) 88 { 89 mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) ); 90 mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) ); 91 } 92 93 delete m_pSolarLock; 94 m_pSolarLock = NULL; 95 // This is not completely safe. If we assume that the base class dtor calls some method which 96 // uses this lock, the we crash. However, as the base class' dtor does not have a chance to call _out_ 97 // virtual methods, this is no problem as long as the base class is safe, i.e. does not use the external 98 // lock from within it's dtor. At the moment, we _know_ the base class is safe in this respect, so 99 // let's assume it keeps this way. 100 // @see OAccessibleContextHelper::OAccessibleContextHelper( IMutex* ) 101 } 102 103 IMPLEMENT_FORWARD_XINTERFACE3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE ) 104 IMPLEMENT_FORWARD_XTYPEPROVIDER3( VCLXAccessibleComponent, AccessibleExtendedComponentHelper_BASE, OAccessibleImplementationAccess, VCLXAccessibleComponent_BASE ) 105 106 ::rtl::OUString VCLXAccessibleComponent::getImplementationName() throw (uno::RuntimeException) 107 { 108 return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleWindow" ); 109 } 110 111 sal_Bool VCLXAccessibleComponent::supportsService( const ::rtl::OUString& rServiceName ) throw (uno::RuntimeException) 112 { 113 uno::Sequence< ::rtl::OUString > aNames( getSupportedServiceNames() ); 114 const ::rtl::OUString* pNames = aNames.getConstArray(); 115 const ::rtl::OUString* pEnd = pNames + aNames.getLength(); 116 for ( ; pNames != pEnd && !pNames->equals( rServiceName ); ++pNames ) 117 ; 118 119 return pNames != pEnd; 120 } 121 122 uno::Sequence< ::rtl::OUString > VCLXAccessibleComponent::getSupportedServiceNames() throw (uno::RuntimeException) 123 { 124 uno::Sequence< ::rtl::OUString > aNames(1); 125 aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleWindow" ); 126 return aNames; 127 } 128 129 IMPL_LINK( VCLXAccessibleComponent, WindowEventListener, VclSimpleEvent*, pEvent ) 130 { 131 DBG_CHKTHIS(VCLXAccessibleComponent,0); 132 133 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" ); 134 135 /* Ignore VCLEVENT_WINDOW_ENDPOPUPMODE, because the UNO accessibility wrapper 136 * might have been destroyed by the previous VCLEventListener (if no AT tool 137 * is running), e.g. sub-toolbars in impress. 138 */ 139 if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #122218# */ && (pEvent->GetId() != VCLEVENT_WINDOW_ENDPOPUPMODE) ) 140 { 141 DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" ); 142 if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() || ( pEvent->GetId() == VCLEVENT_OBJECT_DYING ) ) 143 { 144 ProcessWindowEvent( *(VclWindowEvent*)pEvent ); 145 } 146 } 147 return 0; 148 } 149 150 IMPL_LINK( VCLXAccessibleComponent, WindowChildEventListener, VclSimpleEvent*, pEvent ) 151 { 152 DBG_CHKTHIS(VCLXAccessibleComponent,0); 153 154 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" ); 155 if ( pEvent && pEvent->ISA( VclWindowEvent ) && mxWindow.is() /* #i68079# */ ) 156 { 157 DBG_ASSERT( ((VclWindowEvent*)pEvent)->GetWindow(), "Window???" ); 158 if( !((VclWindowEvent*)pEvent)->GetWindow()->IsAccessibilityEventsSuppressed() ) 159 { 160 // #103087# to prevent an early release of the component 161 uno::Reference< accessibility::XAccessibleContext > xTmp = this; 162 163 ProcessWindowChildEvent( *(VclWindowEvent*)pEvent ); 164 } 165 } 166 return 0; 167 } 168 169 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::GetChildAccessible( const VclWindowEvent& rVclWindowEvent ) 170 { 171 // checks if the data in the window event is our direct child 172 // and returns its accessible 173 174 // MT: Change this later, normaly a show/hide event shouldn't have the Window* in pData. 175 Window* pChildWindow = (Window *) rVclWindowEvent.GetData(); 176 if( pChildWindow && GetWindow() == pChildWindow->GetAccessibleParentWindow() ) 177 return pChildWindow->GetAccessible( rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW ); 178 else 179 return uno::Reference< accessibility::XAccessible > (); 180 } 181 182 void VCLXAccessibleComponent::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent ) 183 { 184 uno::Any aOldValue, aNewValue; 185 uno::Reference< accessibility::XAccessible > xAcc; 186 187 switch ( rVclWindowEvent.GetId() ) 188 { 189 case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children 190 { 191 xAcc = GetChildAccessible( rVclWindowEvent ); 192 if( xAcc.is() ) 193 { 194 aNewValue <<= xAcc; 195 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue ); 196 } 197 } 198 break; 199 case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children 200 { 201 xAcc = GetChildAccessible( rVclWindowEvent ); 202 if( xAcc.is() ) 203 { 204 aOldValue <<= xAcc; 205 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue ); 206 } 207 } 208 break; 209 } 210 } 211 212 void VCLXAccessibleComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) 213 { 214 uno::Any aOldValue, aNewValue; 215 216 Window* pAccWindow = rVclWindowEvent.GetWindow(); 217 DBG_ASSERT( pAccWindow, "VCLXAccessibleComponent::ProcessWindowEvent - Window?" ); 218 219 switch ( rVclWindowEvent.GetId() ) 220 { 221 case VCLEVENT_OBJECT_DYING: 222 { 223 pAccWindow->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) ); 224 pAccWindow->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) ); 225 mxWindow.clear(); 226 mpVCLXindow = NULL; 227 } 228 break; 229 // 230 // dont handle CHILDCREATED events here 231 // they are handled separately as child events, see ProcessWindowChildEvent above 232 // 233 /* 234 case VCLEVENT_WINDOW_CHILDCREATED: 235 { 236 Window* pWindow = (Window*) rVclWindowEvent.GetData(); 237 DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDCREATED - Window=?" ); 238 aNewValue <<= pWindow->GetAccessible(); 239 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue ); 240 } 241 break; 242 */ 243 case VCLEVENT_WINDOW_CHILDDESTROYED: 244 { 245 Window* pWindow = (Window*) rVclWindowEvent.GetData(); 246 DBG_ASSERT( pWindow, "VCLEVENT_WINDOW_CHILDDESTROYED - Window=?" ); 247 if ( pWindow->GetAccessible( sal_False ).is() ) 248 { 249 aOldValue <<= pWindow->GetAccessible( sal_False ); 250 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue ); 251 } 252 } 253 break; 254 255 // 256 // show and hide will be handled as child events only and are 257 // responsible for sending create/destroy events, see ProcessWindowChildEvent above 258 // 259 /* 260 case VCLEVENT_WINDOW_SHOW: 261 { 262 aNewValue <<= accessibility::AccessibleStateType::VISIBLE; 263 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 264 265 aNewValue <<= accessibility::AccessibleStateType::SHOWING; 266 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 267 268 aNewValue.clear(); 269 aOldValue <<= accessibility::AccessibleStateType::INVALID; 270 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 271 } 272 break; 273 case VCLEVENT_WINDOW_HIDE: 274 { 275 aOldValue <<= accessibility::AccessibleStateType::VISIBLE; 276 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 277 278 aOldValue <<= accessibility::AccessibleStateType::SHOWING; 279 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 280 281 aOldValue.clear(); 282 aNewValue <<= accessibility::AccessibleStateType::INVALID; 283 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 284 } 285 break; 286 */ 287 case VCLEVENT_WINDOW_ACTIVATE: 288 { 289 // avoid notification if a child frame is already active 290 // only one frame may be active at a given time 291 if ( !pAccWindow->HasActiveChildFrame() && 292 ( getAccessibleRole() == accessibility::AccessibleRole::FRAME || 293 getAccessibleRole() == accessibility::AccessibleRole::ALERT || 294 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891# 295 { 296 aNewValue <<= accessibility::AccessibleStateType::ACTIVE; 297 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 298 } 299 } 300 break; 301 case VCLEVENT_WINDOW_DEACTIVATE: 302 { 303 if ( getAccessibleRole() == accessibility::AccessibleRole::FRAME || 304 getAccessibleRole() == accessibility::AccessibleRole::ALERT || 305 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) // #i18891# 306 { 307 aOldValue <<= accessibility::AccessibleStateType::ACTIVE; 308 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 309 } 310 } 311 break; 312 case VCLEVENT_WINDOW_GETFOCUS: 313 case VCLEVENT_CONTROL_GETFOCUS: 314 { 315 if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_GETFOCUS) || 316 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_GETFOCUS) ) 317 { 318 // if multiple listeners were registered it is possible that the 319 // focus was changed during event processing (eg SfxTopWindow ) 320 // #106082# allow ChildPathFocus only for CompoundControls, for windows the focus must be in the window itself 321 if( (pAccWindow->IsCompoundControl() && pAccWindow->HasChildPathFocus()) || 322 (!pAccWindow->IsCompoundControl() && pAccWindow->HasFocus()) ) 323 { 324 aNewValue <<= accessibility::AccessibleStateType::FOCUSED; 325 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 326 } 327 } 328 } 329 break; 330 case VCLEVENT_WINDOW_LOSEFOCUS: 331 case VCLEVENT_CONTROL_LOSEFOCUS: 332 { 333 if( (pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_CONTROL_LOSEFOCUS) || 334 (!pAccWindow->IsCompoundControl() && rVclWindowEvent.GetId() == VCLEVENT_WINDOW_LOSEFOCUS) ) 335 { 336 aOldValue <<= accessibility::AccessibleStateType::FOCUSED; 337 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 338 } 339 } 340 break; 341 case VCLEVENT_WINDOW_FRAMETITLECHANGED: 342 { 343 ::rtl::OUString aOldName( *((::rtl::OUString*) rVclWindowEvent.GetData()) ); 344 ::rtl::OUString aNewName( getAccessibleName() ); 345 aOldValue <<= aOldName; 346 aNewValue <<= aNewName; 347 NotifyAccessibleEvent( accessibility::AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue ); 348 } 349 break; 350 case VCLEVENT_WINDOW_ENABLED: 351 { 352 aNewValue <<= accessibility::AccessibleStateType::ENABLED; 353 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 354 aNewValue <<= accessibility::AccessibleStateType::SENSITIVE; 355 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 356 } 357 break; 358 case VCLEVENT_WINDOW_DISABLED: 359 { 360 aOldValue <<= accessibility::AccessibleStateType::SENSITIVE; 361 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 362 363 aOldValue <<= accessibility::AccessibleStateType::ENABLED; 364 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 365 } 366 break; 367 case VCLEVENT_WINDOW_MOVE: 368 case VCLEVENT_WINDOW_RESIZE: 369 { 370 NotifyAccessibleEvent( accessibility::AccessibleEventId::BOUNDRECT_CHANGED, aOldValue, aNewValue ); 371 } 372 break; 373 case VCLEVENT_WINDOW_MENUBARADDED: 374 { 375 MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData(); 376 if ( pMenuBar ) 377 { 378 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() ); 379 if ( xChild.is() ) 380 { 381 aNewValue <<= xChild; 382 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue ); 383 } 384 } 385 } 386 break; 387 case VCLEVENT_WINDOW_MENUBARREMOVED: 388 { 389 MenuBar* pMenuBar = (MenuBar*) rVclWindowEvent.GetData(); 390 if ( pMenuBar ) 391 { 392 uno::Reference< accessibility::XAccessible > xChild( pMenuBar->GetAccessible() ); 393 if ( xChild.is() ) 394 { 395 aOldValue <<= xChild; 396 NotifyAccessibleEvent( accessibility::AccessibleEventId::CHILD, aOldValue, aNewValue ); 397 } 398 } 399 } 400 break; 401 case VCLEVENT_WINDOW_MINIMIZE: 402 { 403 aNewValue <<= accessibility::AccessibleStateType::ICONIFIED; 404 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 405 } 406 break; 407 case VCLEVENT_WINDOW_NORMALIZE: 408 { 409 aOldValue <<= accessibility::AccessibleStateType::ICONIFIED; 410 NotifyAccessibleEvent( accessibility::AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); 411 } 412 break; 413 default: 414 { 415 } 416 break; 417 } 418 } 419 420 void VCLXAccessibleComponent::disposing() 421 { 422 if ( mpVCLXindow && mpVCLXindow->GetWindow() ) 423 { 424 mpVCLXindow->GetWindow()->RemoveEventListener( LINK( this, VCLXAccessibleComponent, WindowEventListener ) ); 425 mpVCLXindow->GetWindow()->RemoveChildEventListener( LINK( this, VCLXAccessibleComponent, WindowChildEventListener ) ); 426 } 427 428 AccessibleExtendedComponentHelper_BASE::disposing(); 429 430 mxWindow.clear(); 431 mpVCLXindow = NULL; 432 } 433 434 Window* VCLXAccessibleComponent::GetWindow() const 435 { 436 return GetVCLXWindow() ? GetVCLXWindow()->GetWindow() : NULL; 437 } 438 439 void VCLXAccessibleComponent::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet ) 440 { 441 Window* pWindow = GetWindow(); 442 if ( pWindow ) 443 { 444 Window *pLabeledBy = pWindow->GetAccessibleRelationLabeledBy(); 445 if ( pLabeledBy && pLabeledBy != pWindow ) 446 { 447 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1); 448 aSequence[0] = pLabeledBy->GetAccessible(); 449 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABELED_BY, aSequence ) ); 450 } 451 452 Window* pLabelFor = pWindow->GetAccessibleRelationLabelFor(); 453 if ( pLabelFor && pLabelFor != pWindow ) 454 { 455 uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1); 456 aSequence[0] = pLabelFor->GetAccessible(); 457 rRelationSet.AddRelation( accessibility::AccessibleRelation( accessibility::AccessibleRelationType::LABEL_FOR, aSequence ) ); 458 } 459 } 460 } 461 462 void VCLXAccessibleComponent::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet ) 463 { 464 Window* pWindow = GetWindow(); 465 if ( pWindow ) 466 { 467 if ( pWindow->IsVisible() ) 468 { 469 rStateSet.AddState( accessibility::AccessibleStateType::VISIBLE ); 470 rStateSet.AddState( accessibility::AccessibleStateType::SHOWING ); 471 } 472 else 473 { 474 rStateSet.AddState( accessibility::AccessibleStateType::INVALID ); 475 } 476 477 if ( pWindow->IsEnabled() ) 478 { 479 rStateSet.AddState( accessibility::AccessibleStateType::ENABLED ); 480 rStateSet.AddState( accessibility::AccessibleStateType::SENSITIVE ); 481 } 482 483 if ( pWindow->HasChildPathFocus() && 484 ( getAccessibleRole() == accessibility::AccessibleRole::FRAME || 485 getAccessibleRole() == accessibility::AccessibleRole::ALERT || 486 getAccessibleRole() == accessibility::AccessibleRole::DIALOG ) ) // #i18891# 487 rStateSet.AddState( accessibility::AccessibleStateType::ACTIVE ); 488 489 // #104290# MT: This way, a ComboBox doesn't get state FOCUSED. 490 // I also don't understand 491 // a) why WINDOW_FIRSTCHILD is used here (which btw is a border window in the case of a combo box) 492 // b) why HasFocus() is nout "enough" for a compound control 493 /* 494 Window* pChild = pWindow->GetWindow( WINDOW_FIRSTCHILD ); 495 if ( ( !pWindow->IsCompoundControl() && pWindow->HasFocus() ) || 496 ( pWindow->IsCompoundControl() && pChild && pChild->HasFocus() ) ) 497 rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED ); 498 */ 499 if ( pWindow->HasFocus() || ( pWindow->IsCompoundControl() && pWindow->HasChildPathFocus() ) ) 500 rStateSet.AddState( accessibility::AccessibleStateType::FOCUSED ); 501 502 if ( pWindow->IsWait() ) 503 rStateSet.AddState( accessibility::AccessibleStateType::BUSY ); 504 505 if ( pWindow->GetStyle() & WB_SIZEABLE ) 506 rStateSet.AddState( accessibility::AccessibleStateType::RESIZABLE ); 507 508 if( pWindow->IsDialog() ) 509 { 510 Dialog *pDlg = static_cast< Dialog* >( pWindow ); 511 if( pDlg->IsInExecute() ) 512 rStateSet.AddState( accessibility::AccessibleStateType::MODAL ); 513 } 514 } 515 else 516 { 517 rStateSet.AddState( accessibility::AccessibleStateType::DEFUNC ); 518 } 519 520 /* 521 522 MUST BE SET FROM DERIVED CLASSES: 523 524 CHECKED 525 COLLAPSED 526 EXPANDED 527 EXPANDABLE 528 EDITABLE 529 FOCUSABLE 530 HORIZONTAL 531 VERTICAL 532 ICONIFIED 533 MULTILINE 534 MULTI_SELECTABLE 535 PRESSED 536 SELECTABLE 537 SELECTED 538 SINGLE_LINE 539 TRANSIENT 540 541 */ 542 } 543 544 545 // accessibility::XAccessibleContext 546 sal_Int32 VCLXAccessibleComponent::getAccessibleChildCount() throw (uno::RuntimeException) 547 { 548 OExternalLockGuard aGuard( this ); 549 550 sal_Int32 nChildren = 0; 551 if ( GetWindow() ) 552 nChildren = GetWindow()->GetAccessibleChildWindowCount(); 553 554 return nChildren; 555 } 556 557 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) 558 { 559 OExternalLockGuard aGuard( this ); 560 561 if ( i >= getAccessibleChildCount() ) 562 throw lang::IndexOutOfBoundsException(); 563 564 uno::Reference< accessibility::XAccessible > xAcc; 565 if ( GetWindow() ) 566 { 567 Window* pChild = GetWindow()->GetAccessibleChildWindow( (sal_uInt16)i ); 568 if ( pChild ) 569 xAcc = pChild->GetAccessible(); 570 } 571 572 return xAcc; 573 } 574 575 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getVclParent() const 576 { 577 uno::Reference< accessibility::XAccessible > xAcc; 578 if ( GetWindow() ) 579 { 580 Window* pParent = GetWindow()->GetAccessibleParentWindow(); 581 if ( pParent ) 582 xAcc = pParent->GetAccessible(); 583 } 584 return xAcc; 585 } 586 587 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleParent( ) throw (uno::RuntimeException) 588 { 589 OExternalLockGuard aGuard( this ); 590 591 uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() ); 592 if ( !xAcc.is() ) 593 // we do _not_ have a foreign-controlled parent -> default to our VCL parent 594 xAcc = getVclParent(); 595 596 return xAcc; 597 } 598 599 sal_Int32 VCLXAccessibleComponent::getAccessibleIndexInParent( ) throw (uno::RuntimeException) 600 { 601 OExternalLockGuard aGuard( this ); 602 603 sal_Int32 nIndex = -1; 604 605 uno::Reference< accessibility::XAccessible > xAcc( implGetForeignControlledParent() ); 606 if ( xAcc.is() ) 607 { // we _do_ have a foreign-controlled parent -> use the base class' implementation, 608 // which goes the UNO way 609 nIndex = AccessibleExtendedComponentHelper_BASE::getAccessibleIndexInParent( ); 610 } 611 else 612 { 613 if ( GetWindow() ) 614 { 615 Window* pParent = GetWindow()->GetAccessibleParentWindow(); 616 if ( pParent ) 617 { 618 /* 619 for ( sal_uInt16 n = pParent->GetAccessibleChildWindowCount(); n; ) 620 { 621 Window* pChild = pParent->GetAccessibleChildWindow( --n ); 622 if ( pChild == GetWindow() ) 623 { 624 nIndex = n; 625 break; 626 } 627 } 628 */ 629 // Iterate over all the parent's children and search for this object. 630 // this should be compatible with the code in SVX 631 uno::Reference< accessibility::XAccessible > xParentAcc( pParent->GetAccessible() ); 632 if ( xParentAcc.is() ) 633 { 634 uno::Reference< accessibility::XAccessibleContext > xParentContext ( xParentAcc->getAccessibleContext() ); 635 if ( xParentContext.is() ) 636 { 637 sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); 638 for ( sal_Int32 i=0; i<nChildCount; i++ ) 639 { 640 uno::Reference< accessibility::XAccessible > xChild( xParentContext->getAccessibleChild(i) ); 641 if ( xChild.is() ) 642 { 643 uno::Reference< accessibility::XAccessibleContext > xChildContext = xChild->getAccessibleContext(); 644 if ( xChildContext == (accessibility::XAccessibleContext*) this ) 645 { 646 nIndex = i; 647 break; 648 } 649 } 650 } 651 } 652 } 653 } 654 } 655 } 656 return nIndex; 657 } 658 659 sal_Int16 VCLXAccessibleComponent::getAccessibleRole( ) throw (uno::RuntimeException) 660 { 661 OExternalLockGuard aGuard( this ); 662 663 sal_Int16 nRole = 0; 664 665 if ( GetWindow() ) 666 nRole = GetWindow()->GetAccessibleRole(); 667 668 return nRole; 669 } 670 671 ::rtl::OUString VCLXAccessibleComponent::getAccessibleDescription( ) throw (uno::RuntimeException) 672 { 673 OExternalLockGuard aGuard( this ); 674 675 ::rtl::OUString aDescription; 676 677 if ( GetWindow() ) 678 aDescription = GetWindow()->GetAccessibleDescription(); 679 680 return aDescription; 681 } 682 683 ::rtl::OUString VCLXAccessibleComponent::getAccessibleName( ) throw (uno::RuntimeException) 684 { 685 OExternalLockGuard aGuard( this ); 686 687 ::rtl::OUString aName; 688 if ( GetWindow() ) 689 { 690 aName = GetWindow()->GetAccessibleName(); 691 #if OSL_DEBUG_LEVEL > 1 692 aName += String( RTL_CONSTASCII_USTRINGPARAM( " (Type = " ) ); 693 aName += String::CreateFromInt32( GetWindow()->GetType() ); 694 aName += String( RTL_CONSTASCII_USTRINGPARAM( ")" ) ); 695 #endif 696 } 697 return aName; 698 } 699 700 uno::Reference< accessibility::XAccessibleRelationSet > VCLXAccessibleComponent::getAccessibleRelationSet( ) throw (uno::RuntimeException) 701 { 702 OExternalLockGuard aGuard( this ); 703 704 utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper; 705 uno::Reference< accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper; 706 FillAccessibleRelationSet( *pRelationSetHelper ); 707 return xSet; 708 } 709 710 uno::Reference< accessibility::XAccessibleStateSet > VCLXAccessibleComponent::getAccessibleStateSet( ) throw (uno::RuntimeException) 711 { 712 OExternalLockGuard aGuard( this ); 713 714 utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper; 715 uno::Reference< accessibility::XAccessibleStateSet > xSet = pStateSetHelper; 716 FillAccessibleStateSet( *pStateSetHelper ); 717 return xSet; 718 } 719 720 lang::Locale VCLXAccessibleComponent::getLocale() throw (accessibility::IllegalAccessibleComponentStateException, uno::RuntimeException) 721 { 722 OExternalLockGuard aGuard( this ); 723 724 return Application::GetSettings().GetLocale(); 725 } 726 727 uno::Reference< accessibility::XAccessible > VCLXAccessibleComponent::getAccessibleAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException) 728 { 729 OExternalLockGuard aGuard( this ); 730 731 uno::Reference< accessibility::XAccessible > xChild; 732 for ( sal_uInt32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i ) 733 { 734 uno::Reference< accessibility::XAccessible > xAcc = getAccessibleChild( i ); 735 if ( xAcc.is() ) 736 { 737 uno::Reference< accessibility::XAccessibleComponent > xComp( xAcc->getAccessibleContext(), uno::UNO_QUERY ); 738 if ( xComp.is() ) 739 { 740 Rectangle aRect = VCLRectangle( xComp->getBounds() ); 741 Point aPos = VCLPoint( rPoint ); 742 if ( aRect.IsInside( aPos ) ) 743 { 744 xChild = xAcc; 745 break; 746 } 747 } 748 } 749 } 750 751 return xChild; 752 } 753 754 // accessibility::XAccessibleComponent 755 awt::Rectangle VCLXAccessibleComponent::implGetBounds() throw (uno::RuntimeException) 756 { 757 awt::Rectangle aBounds ( 0, 0, 0, 0 ); 758 759 Window* pWindow = GetWindow(); 760 if ( pWindow ) 761 { 762 Rectangle aRect = pWindow->GetWindowExtentsRelative( NULL ); 763 aBounds = AWTRectangle( aRect ); 764 Window* pParent = pWindow->GetAccessibleParentWindow(); 765 if ( pParent ) 766 { 767 Rectangle aParentRect = pParent->GetWindowExtentsRelative( NULL ); 768 awt::Point aParentScreenLoc = AWTPoint( aParentRect.TopLeft() ); 769 aBounds.X -= aParentScreenLoc.X; 770 aBounds.Y -= aParentScreenLoc.Y; 771 } 772 } 773 774 uno::Reference< accessibility::XAccessible > xParent( implGetForeignControlledParent() ); 775 if ( xParent.is() ) 776 { // hmm, we can't rely on our VCL coordinates, as in the Accessibility Hierarchy, somebody gave 777 // us a parent which is different from our VCL parent 778 // (actually, we did not check if it's really different ...) 779 780 // the screen location of the foreign parent 781 uno::Reference< accessibility::XAccessibleComponent > xParentComponent( xParent->getAccessibleContext(), uno::UNO_QUERY ); 782 DBG_ASSERT( xParentComponent.is(), "VCLXAccessibleComponent::implGetBounds: invalid (foreign) parent component!" ); 783 784 awt::Point aScreenLocForeign( 0, 0 ); 785 if ( xParentComponent.is() ) 786 aScreenLocForeign = xParentComponent->getLocationOnScreen(); 787 788 // the screen location of the VCL parent 789 xParent = getVclParent(); 790 if ( xParent.is() ) 791 xParentComponent = xParentComponent.query( xParent->getAccessibleContext() ); 792 793 awt::Point aScreenLocVCL( 0, 0 ); 794 if ( xParentComponent.is() ) 795 aScreenLocVCL = xParentComponent->getLocationOnScreen(); 796 797 // the difference between them 798 awt::Size aOffset( aScreenLocVCL.X - aScreenLocForeign.X, aScreenLocVCL.Y - aScreenLocForeign.Y ); 799 // move the bounds 800 aBounds.X += aOffset.Width; 801 aBounds.Y += aOffset.Height; 802 } 803 804 return aBounds; 805 } 806 807 awt::Point VCLXAccessibleComponent::getLocationOnScreen( ) throw (uno::RuntimeException) 808 { 809 OExternalLockGuard aGuard( this ); 810 811 awt::Point aPos; 812 if ( GetWindow() ) 813 { 814 Rectangle aRect = GetWindow()->GetWindowExtentsRelative( NULL ); 815 aPos.X = aRect.Left(); 816 aPos.Y = aRect.Top(); 817 } 818 819 return aPos; 820 } 821 822 void VCLXAccessibleComponent::grabFocus( ) throw (uno::RuntimeException) 823 { 824 OExternalLockGuard aGuard( this ); 825 826 uno::Reference< accessibility::XAccessibleStateSet > xStates = getAccessibleStateSet(); 827 if ( mxWindow.is() && xStates.is() && xStates->contains( accessibility::AccessibleStateType::FOCUSABLE ) ) 828 mxWindow->setFocus(); 829 } 830 831 sal_Int32 SAL_CALL VCLXAccessibleComponent::getForeground( ) throw (uno::RuntimeException) 832 { 833 OExternalLockGuard aGuard( this ); 834 835 sal_Int32 nColor = 0; 836 Window* pWindow = GetWindow(); 837 if ( pWindow ) 838 { 839 if ( pWindow->IsControlForeground() ) 840 nColor = pWindow->GetControlForeground().GetColor(); 841 else 842 { 843 Font aFont; 844 if ( pWindow->IsControlFont() ) 845 aFont = pWindow->GetControlFont(); 846 else 847 aFont = pWindow->GetFont(); 848 nColor = aFont.GetColor().GetColor(); 849 } 850 } 851 852 return nColor; 853 } 854 855 sal_Int32 SAL_CALL VCLXAccessibleComponent::getBackground( ) throw (uno::RuntimeException) 856 { 857 OExternalLockGuard aGuard( this ); 858 859 sal_Int32 nColor = 0; 860 Window* pWindow = GetWindow(); 861 if ( pWindow ) 862 { 863 if ( pWindow->IsControlBackground() ) 864 nColor = pWindow->GetControlBackground().GetColor(); 865 else 866 nColor = pWindow->GetBackground().GetColor().GetColor(); 867 } 868 869 return nColor; 870 } 871 872 // XAccessibleExtendedComponent 873 874 uno::Reference< awt::XFont > SAL_CALL VCLXAccessibleComponent::getFont( ) throw (uno::RuntimeException) 875 { 876 OExternalLockGuard aGuard( this ); 877 878 uno::Reference< awt::XFont > xFont; 879 Window* pWindow = GetWindow(); 880 if ( pWindow ) 881 { 882 uno::Reference< awt::XDevice > xDev( pWindow->GetComponentInterface(), uno::UNO_QUERY ); 883 if ( xDev.is() ) 884 { 885 Font aFont; 886 if ( pWindow->IsControlFont() ) 887 aFont = pWindow->GetControlFont(); 888 else 889 aFont = pWindow->GetFont(); 890 VCLXFont* pVCLXFont = new VCLXFont; 891 pVCLXFont->Init( *xDev.get(), aFont ); 892 xFont = pVCLXFont; 893 } 894 } 895 896 return xFont; 897 } 898 899 ::rtl::OUString SAL_CALL VCLXAccessibleComponent::getTitledBorderText( ) throw (uno::RuntimeException) 900 { 901 OExternalLockGuard aGuard( this ); 902 903 ::rtl::OUString sRet; 904 if ( GetWindow() ) 905 sRet = GetWindow()->GetText(); 906 907 return sRet; 908 } 909 910 ::rtl::OUString SAL_CALL VCLXAccessibleComponent::getToolTipText( ) throw (uno::RuntimeException) 911 { 912 OExternalLockGuard aGuard( this ); 913 914 ::rtl::OUString sRet; 915 if ( GetWindow() ) 916 sRet = GetWindow()->GetQuickHelpText(); 917 918 return sRet; 919 } 920 921