1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 #include <vcl/window.hxx> 31 #include <rootfrm.hxx> 32 33 34 #include <com/sun/star/accessibility/AccessibleRole.hpp> 35 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 36 #include <com/sun/star/beans/XPropertyChangeListener.hpp> 37 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 38 #include <unotools/accessiblestatesethelper.hxx> 39 #include <tools/link.hxx> 40 #include <sfx2/viewsh.hxx> 41 #include <vos/mutex.hxx> 42 #include <vcl/svapp.hxx> 43 #include <viewsh.hxx> 44 #include <doc.hxx> 45 #include <accmap.hxx> 46 #include <accdoc.hxx> 47 #ifndef _ACCESS_HRC 48 #include "access.hrc" 49 #endif 50 #include <pagefrm.hxx> 51 52 const sal_Char sServiceName[] = "com.sun.star.text.AccessibleTextDocumentView"; 53 const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleDocumentView"; 54 55 56 using namespace ::com::sun::star; 57 using namespace ::com::sun::star::accessibility; 58 using ::rtl::OUString; 59 60 using lang::IndexOutOfBoundsException; 61 62 63 64 // 65 // SwAccessibleDocumentBase: base class for SwAccessibleDocument and 66 // SwAccessiblePreview 67 // 68 69 SwAccessibleDocumentBase::SwAccessibleDocumentBase ( SwAccessibleMap *_pMap ) : 70 SwAccessibleContext( _pMap, AccessibleRole::DOCUMENT, 71 _pMap->GetShell()->GetLayout() ),//swmod 071107//swmod 071225 72 mxParent( _pMap->GetShell()->GetWin()->GetAccessibleParentWindow()->GetAccessible() ), 73 mpChildWin( 0 ) 74 { 75 } 76 77 SwAccessibleDocumentBase::~SwAccessibleDocumentBase() 78 { 79 } 80 81 void SwAccessibleDocumentBase::SetVisArea() 82 { 83 vos::OGuard aGuard(Application::GetSolarMutex()); 84 85 SwRect aOldVisArea( GetVisArea() ); 86 const SwRect& rNewVisArea = GetMap()->GetVisArea(); 87 if( aOldVisArea != rNewVisArea ) 88 { 89 SwAccessibleFrame::SetVisArea( GetMap()->GetVisArea() ); 90 // --> OD 2007-12-07 #i58139# 91 // showing state of document view needs also be updated. 92 // Thus, call method <Scrolled(..)> instead of <ChildrenScrolled(..)> 93 // ChildrenScrolled( GetFrm(), aOldVisArea ); 94 Scrolled( aOldVisArea ); 95 // <-- 96 } 97 } 98 99 void SwAccessibleDocumentBase::AddChild( Window *pWin, sal_Bool bFireEvent ) 100 { 101 vos::OGuard aGuard(Application::GetSolarMutex()); 102 103 ASSERT( !mpChildWin, "only one child window is supported" ); 104 if( !mpChildWin ) 105 { 106 mpChildWin = pWin; 107 108 if( bFireEvent ) 109 { 110 AccessibleEventObject aEvent; 111 aEvent.EventId = AccessibleEventId::CHILD; 112 aEvent.NewValue <<= mpChildWin->GetAccessible(); 113 FireAccessibleEvent( aEvent ); 114 } 115 } 116 } 117 118 void SwAccessibleDocumentBase::RemoveChild( Window *pWin ) 119 { 120 vos::OGuard aGuard(Application::GetSolarMutex()); 121 122 ASSERT( !mpChildWin || pWin == mpChildWin, "invalid child window to remove" ); 123 if( mpChildWin && pWin == mpChildWin ) 124 { 125 AccessibleEventObject aEvent; 126 aEvent.EventId = AccessibleEventId::CHILD; 127 aEvent.OldValue <<= mpChildWin->GetAccessible(); 128 FireAccessibleEvent( aEvent ); 129 130 mpChildWin = 0; 131 } 132 } 133 134 sal_Int32 SAL_CALL SwAccessibleDocumentBase::getAccessibleChildCount( void ) 135 throw (uno::RuntimeException) 136 { 137 vos::OGuard aGuard(Application::GetSolarMutex()); 138 139 // CHECK_FOR_DEFUNC is called by parent 140 141 sal_Int32 nChildren = SwAccessibleContext::getAccessibleChildCount(); 142 if( !IsDisposing() && mpChildWin ) 143 nChildren++; 144 145 return nChildren; 146 } 147 148 uno::Reference< XAccessible> SAL_CALL 149 SwAccessibleDocumentBase::getAccessibleChild( sal_Int32 nIndex ) 150 throw (uno::RuntimeException, 151 lang::IndexOutOfBoundsException) 152 { 153 vos::OGuard aGuard(Application::GetSolarMutex()); 154 155 if( mpChildWin ) 156 { 157 CHECK_FOR_DEFUNC( XAccessibleContext ) 158 if ( nIndex == GetChildCount( *(GetMap()) ) ) 159 { 160 return mpChildWin->GetAccessible(); 161 } 162 } 163 164 return SwAccessibleContext::getAccessibleChild( nIndex ); 165 } 166 167 168 uno::Reference< XAccessible> SAL_CALL SwAccessibleDocumentBase::getAccessibleParent (void) 169 throw (uno::RuntimeException) 170 { 171 return mxParent; 172 } 173 174 sal_Int32 SAL_CALL SwAccessibleDocumentBase::getAccessibleIndexInParent (void) 175 throw (uno::RuntimeException) 176 { 177 vos::OGuard aGuard(Application::GetSolarMutex()); 178 179 uno::Reference < XAccessibleContext > xAcc( mxParent->getAccessibleContext() ); 180 uno::Reference < XAccessible > xThis( this ); 181 sal_Int32 nCount = xAcc->getAccessibleChildCount(); 182 183 for( sal_Int32 i=0; i < nCount; i++ ) 184 { 185 if( xAcc->getAccessibleChild( i ) == xThis ) 186 return i; 187 } 188 return -1L; 189 } 190 191 OUString SAL_CALL SwAccessibleDocumentBase::getAccessibleDescription (void) 192 throw (uno::RuntimeException) 193 { 194 return GetResource( STR_ACCESS_DOC_DESC ); 195 } 196 197 awt::Rectangle SAL_CALL SwAccessibleDocumentBase::getBounds() 198 throw (uno::RuntimeException) 199 { 200 vos::OGuard aGuard(Application::GetSolarMutex()); 201 202 Window *pWin = GetWindow(); 203 204 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ) 205 206 Rectangle aPixBounds( pWin->GetWindowExtentsRelative( pWin->GetAccessibleParentWindow() ) ); 207 awt::Rectangle aBox( aPixBounds.Left(), aPixBounds.Top(), 208 aPixBounds.GetWidth(), aPixBounds.GetHeight() ); 209 210 return aBox; 211 } 212 213 214 awt::Point SAL_CALL SwAccessibleDocumentBase::getLocation() 215 throw (uno::RuntimeException) 216 { 217 vos::OGuard aGuard(Application::GetSolarMutex()); 218 219 Window *pWin = GetWindow(); 220 221 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ) 222 223 Point aPixPos( pWin->GetWindowExtentsRelative( pWin->GetAccessibleParentWindow() ).TopLeft() ); 224 awt::Point aLoc( aPixPos.X(), aPixPos.Y() ); 225 226 return aLoc; 227 } 228 229 230 ::com::sun::star::awt::Point SAL_CALL SwAccessibleDocumentBase::getLocationOnScreen() 231 throw (uno::RuntimeException) 232 { 233 vos::OGuard aGuard(Application::GetSolarMutex()); 234 235 Window *pWin = GetWindow(); 236 237 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ) 238 239 Point aPixPos( pWin->GetWindowExtentsRelative( 0 ).TopLeft() ); 240 awt::Point aLoc( aPixPos.X(), aPixPos.Y() ); 241 242 return aLoc; 243 } 244 245 246 ::com::sun::star::awt::Size SAL_CALL SwAccessibleDocumentBase::getSize() 247 throw (uno::RuntimeException) 248 { 249 vos::OGuard aGuard(Application::GetSolarMutex()); 250 251 Window *pWin = GetWindow(); 252 253 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ) 254 255 Size aPixSize( pWin->GetWindowExtentsRelative( 0 ).GetSize() ); 256 awt::Size aSize( aPixSize.Width(), aPixSize.Height() ); 257 258 return aSize; 259 } 260 261 sal_Bool SAL_CALL SwAccessibleDocumentBase::containsPoint( 262 const awt::Point& aPoint ) 263 throw (uno::RuntimeException) 264 { 265 vos::OGuard aGuard(Application::GetSolarMutex()); 266 267 Window *pWin = GetWindow(); 268 269 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ) 270 271 Rectangle aPixBounds( pWin->GetWindowExtentsRelative( 0 ) ); 272 aPixBounds.Move(-aPixBounds.Left(), -aPixBounds.Top()); 273 274 Point aPixPoint( aPoint.X, aPoint.Y ); 275 return aPixBounds.IsInside( aPixPoint ); 276 } 277 278 uno::Reference< XAccessible > SAL_CALL SwAccessibleDocumentBase::getAccessibleAtPoint( 279 const awt::Point& aPoint ) 280 throw (uno::RuntimeException) 281 { 282 vos::OGuard aGuard(Application::GetSolarMutex()); 283 284 if( mpChildWin ) 285 { 286 CHECK_FOR_DEFUNC( XAccessibleComponent ) 287 288 Window *pWin = GetWindow(); 289 CHECK_FOR_WINDOW( XAccessibleComponent, pWin ) 290 291 Point aPixPoint( aPoint.X, aPoint.Y ); // px rel to window 292 if( mpChildWin->GetWindowExtentsRelative( pWin ).IsInside( aPixPoint ) ) 293 return mpChildWin->GetAccessible(); 294 } 295 296 return SwAccessibleContext::getAccessibleAtPoint( aPoint ); 297 } 298 299 // 300 // SwAccessibeDocument 301 // 302 303 void SwAccessibleDocument::GetStates( 304 ::utl::AccessibleStateSetHelper& rStateSet ) 305 { 306 SwAccessibleContext::GetStates( rStateSet ); 307 308 // MULTISELECTABLE 309 rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE ); 310 } 311 312 313 SwAccessibleDocument::SwAccessibleDocument ( SwAccessibleMap* pInitMap ) : 314 SwAccessibleDocumentBase( pInitMap ), 315 maSelectionHelper( *this ) 316 { 317 SetName( GetResource( STR_ACCESS_DOC_NAME ) ); 318 Window *pWin = pInitMap->GetShell()->GetWin(); 319 if( pWin ) 320 { 321 pWin->AddChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener )); 322 sal_uInt16 nCount = pWin->GetChildCount(); 323 for( sal_uInt16 i=0; i < nCount; i++ ) 324 { 325 Window* pChildWin = pWin->GetChild( i ); 326 if( pChildWin && 327 AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() ) 328 AddChild( pChildWin, sal_False ); 329 } 330 } 331 } 332 333 SwAccessibleDocument::~SwAccessibleDocument() 334 { 335 Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : 0; 336 if( pWin ) 337 pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener )); 338 } 339 340 void SwAccessibleDocument::Dispose( sal_Bool bRecursive ) 341 { 342 ASSERT( GetFrm() && GetMap(), "already disposed" ); 343 344 Window *pWin = GetMap() ? GetMap()->GetShell()->GetWin() : 0; 345 if( pWin ) 346 pWin->RemoveChildEventListener( LINK( this, SwAccessibleDocument, WindowChildEventListener )); 347 SwAccessibleContext::Dispose( bRecursive ); 348 } 349 350 IMPL_LINK( SwAccessibleDocument, WindowChildEventListener, VclSimpleEvent*, pEvent ) 351 { 352 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" ); 353 if ( pEvent && pEvent->ISA( VclWindowEvent ) ) 354 { 355 VclWindowEvent *pVclEvent = static_cast< VclWindowEvent * >( pEvent ); 356 DBG_ASSERT( pVclEvent->GetWindow(), "Window???" ); 357 switch ( pVclEvent->GetId() ) 358 { 359 case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children 360 { 361 Window* pChildWin = static_cast< Window* >( pVclEvent->GetData() ); 362 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() ) 363 { 364 AddChild( pChildWin ); 365 } 366 } 367 break; 368 case VCLEVENT_WINDOW_HIDE: // send destroy on hide for direct accessible children 369 { 370 Window* pChildWin = static_cast< Window* >( pVclEvent->GetData() ); 371 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() ) 372 { 373 RemoveChild( pChildWin ); 374 } 375 } 376 break; 377 case VCLEVENT_OBJECT_DYING: // send destroy on hide for direct accessible children 378 { 379 Window* pChildWin = pVclEvent->GetWindow(); 380 if( pChildWin && AccessibleRole::EMBEDDED_OBJECT == pChildWin->GetAccessibleRole() ) 381 { 382 RemoveChild( pChildWin ); 383 } 384 } 385 break; 386 } 387 } 388 return 0; 389 } 390 391 392 OUString SAL_CALL SwAccessibleDocument::getImplementationName() 393 throw( uno::RuntimeException ) 394 { 395 return OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName)); 396 } 397 398 sal_Bool SAL_CALL SwAccessibleDocument::supportsService( 399 const ::rtl::OUString& sTestServiceName) 400 throw (uno::RuntimeException) 401 { 402 return sTestServiceName.equalsAsciiL( sServiceName, 403 sizeof(sServiceName)-1 ) || 404 sTestServiceName.equalsAsciiL( sAccessibleServiceName, 405 sizeof(sAccessibleServiceName)-1 ); 406 } 407 408 uno::Sequence< OUString > SAL_CALL SwAccessibleDocument::getSupportedServiceNames() 409 throw( uno::RuntimeException ) 410 { 411 uno::Sequence< OUString > aRet(2); 412 OUString* pArray = aRet.getArray(); 413 pArray[0] = OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) ); 414 pArray[1] = OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) ); 415 return aRet; 416 } 417 418 //===== XInterface ====================================================== 419 420 uno::Any SwAccessibleDocument::queryInterface( 421 const uno::Type& rType ) 422 throw ( uno::RuntimeException ) 423 { 424 uno::Any aRet; 425 if ( rType == ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) ) ) 426 { 427 uno::Reference<XAccessibleSelection> aSelect = this; 428 aRet <<= aSelect; 429 } 430 else 431 aRet = SwAccessibleContext::queryInterface( rType ); 432 return aRet; 433 } 434 435 //====== XTypeProvider ==================================================== 436 uno::Sequence< uno::Type > SAL_CALL SwAccessibleDocument::getTypes() 437 throw(uno::RuntimeException) 438 { 439 uno::Sequence< uno::Type > aTypes( SwAccessibleDocumentBase::getTypes() ); 440 441 sal_Int32 nIndex = aTypes.getLength(); 442 aTypes.realloc( nIndex + 1 ); 443 444 uno::Type* pTypes = aTypes.getArray(); 445 pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) ); 446 447 return aTypes; 448 } 449 450 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleDocument::getImplementationId() 451 throw(uno::RuntimeException) 452 { 453 vos::OGuard aGuard(Application::GetSolarMutex()); 454 static uno::Sequence< sal_Int8 > aId( 16 ); 455 static sal_Bool bInit = sal_False; 456 if(!bInit) 457 { 458 rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True ); 459 bInit = sal_True; 460 } 461 return aId; 462 } 463 464 //===== XAccessibleSelection ============================================ 465 466 void SwAccessibleDocument::selectAccessibleChild( 467 sal_Int32 nChildIndex ) 468 throw ( lang::IndexOutOfBoundsException, 469 uno::RuntimeException ) 470 { 471 maSelectionHelper.selectAccessibleChild(nChildIndex); 472 } 473 474 sal_Bool SwAccessibleDocument::isAccessibleChildSelected( 475 sal_Int32 nChildIndex ) 476 throw ( lang::IndexOutOfBoundsException, 477 uno::RuntimeException ) 478 { 479 return maSelectionHelper.isAccessibleChildSelected(nChildIndex); 480 } 481 482 void SwAccessibleDocument::clearAccessibleSelection( ) 483 throw ( uno::RuntimeException ) 484 { 485 maSelectionHelper.clearAccessibleSelection(); 486 } 487 488 void SwAccessibleDocument::selectAllAccessibleChildren( ) 489 throw ( uno::RuntimeException ) 490 { 491 maSelectionHelper.selectAllAccessibleChildren(); 492 } 493 494 sal_Int32 SwAccessibleDocument::getSelectedAccessibleChildCount( ) 495 throw ( uno::RuntimeException ) 496 { 497 return maSelectionHelper.getSelectedAccessibleChildCount(); 498 } 499 500 uno::Reference<XAccessible> SwAccessibleDocument::getSelectedAccessibleChild( 501 sal_Int32 nSelectedChildIndex ) 502 throw ( lang::IndexOutOfBoundsException, 503 uno::RuntimeException) 504 { 505 return maSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex); 506 } 507 508 // --> OD 2004-11-16 #111714# - index has to be treated as global child index. 509 void SwAccessibleDocument::deselectAccessibleChild( 510 sal_Int32 nChildIndex ) 511 throw ( lang::IndexOutOfBoundsException, 512 uno::RuntimeException ) 513 { 514 maSelectionHelper.deselectAccessibleChild( nChildIndex ); 515 } 516