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