1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: acccontext.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
35 #include <tools/string.hxx>
39 #include <tools/stream.hxx>
41 #endif // #if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
42 #include <tools/debug.hxx>
43 #include <vcl/window.hxx>
45 #include "swtypes.hxx"
47 #include <com/sun/star/accessibility/XAccessible.hpp>
48 #include <com/sun/star/accessibility/XAccessibleStateSet.hpp>
49 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
50 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
51 #include <vos/mutex.hxx>
52 #include <vcl/svapp.hxx>
53 #include <unotools/accessiblestatesethelper.hxx>
54 #include <unotools/accessiblerelationsethelper.hxx>
61 #include <viewimp.hxx>
63 #include <accfrmobjslist.hxx>
64 #ifndef _ACCCONTEXT_HXX
65 #include <acccontext.hxx>
67 #include <svx/AccessibleShape.hxx>
68 #include <comphelper/accessibleeventnotifier.hxx>
70 #if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
71 #define DBG_MSG( _msg ) \
72 lcl_SwAccessibleContext_DbgMsg( this, _msg, 0, sal_False );
73 #define DBG_MSG_CD( _msg ) \
74 lcl_SwAccessibleContext_DbgMsg( this, _msg, 0, sal_True );
75 #define DBG_MSG_PARAM( _msg, _param ) \
76 lcl_SwAccessibleContext_DbgMsg( this, _msg, _param, sal_False );
77 #define DBG_MSG_THIS_PARAM( _msg, _this, _param ) \
78 lcl_SwAccessibleContext_DbgMsg( _this, _msg, _param, sal_False );
80 void lcl_SwAccessibleContext_DbgMsg( SwAccessibleContext
*pThisAcc
,
82 SwAccessibleContext
*pChildAcc
,
83 sal_Bool bConstrDestr
);
85 #define DBG_MSG( _msg )
86 #define DBG_MSG_PARAM( _msg, _param )
87 #define DBG_MSG_THIS_PARAM( _msg, _this, _param )
88 #define DBG_MSG_CD( _msg )
91 using namespace ::com::sun::star
;
92 using namespace ::com::sun::star::accessibility
;
93 using ::rtl::OUString
;
95 void SwAccessibleContext::InitStates()
97 bIsShowingState
= IsShowing();
99 ViewShell
*pVSh
= GetMap()->GetShell();
100 bIsEditableState
= pVSh
&& IsEditable( pVSh
);
101 bIsOpaqueState
= pVSh
&& IsOpaque( pVSh
);
102 bIsDefuncState
= sal_False
;
105 void SwAccessibleContext::SetParent( SwAccessibleContext
*pParent
)
107 vos::OGuard
aGuard( aMutex
);
109 uno::Reference
< XAccessible
> xParent( pParent
);
110 xWeakParent
= xParent
;
113 uno::Reference
< XAccessible
> SwAccessibleContext::GetWeakParent() const
115 vos::OGuard
aGuard( aMutex
);
117 uno::Reference
< XAccessible
> xParent( xWeakParent
);
121 Window
*SwAccessibleContext::GetWindow()
127 const ViewShell
*pVSh
= GetMap()->GetShell();
128 ASSERT( pVSh
, "no view shell" );
130 pWin
= pVSh
->GetWin();
132 ASSERT( pWin
, "no window" );
138 // get ViewShell from accessibility map, and cast to cursor shell
139 SwCrsrShell
* SwAccessibleContext::GetCrsrShell()
141 SwCrsrShell
* pCrsrShell
;
142 ViewShell
* pViewShell
= GetMap() ? GetMap()->GetShell() : 0;
143 ASSERT( pViewShell
, "no view shell" );
144 if( pViewShell
&& pViewShell
->ISA( SwCrsrShell
) )
145 pCrsrShell
= static_cast<SwCrsrShell
*>( pViewShell
);
152 const SwCrsrShell
* SwAccessibleContext::GetCrsrShell() const
154 // just like non-const GetCrsrShell
155 const SwCrsrShell
* pCrsrShell
;
156 const ViewShell
* pViewShell
= GetMap() ? GetMap()->GetShell() : 0;
157 ASSERT( pViewShell
, "no view shell" );
158 if( pViewShell
&& pViewShell
->ISA( SwCrsrShell
) )
159 pCrsrShell
= static_cast<const SwCrsrShell
*>( pViewShell
);
167 enum Action
{ NONE
, SCROLLED
, SCROLLED_WITHIN
,
168 SCROLLED_IN
, SCROLLED_OUT
};
170 void SwAccessibleContext::ChildrenScrolled( const SwFrm
*pFrm
,
171 const SwRect
& rOldVisArea
)
173 const SwRect
& rNewVisArea
= GetVisArea();
174 SwFrmOrObj
aFrm( pFrm
);
175 sal_Bool bVisibleOnly
= aFrm
.IsVisibleChildrenOnly();
177 uno::Reference
< XAccessible
> xAcc
;
179 const SwFrmOrObjSList
aList( pFrm
);
180 SwFrmOrObjSList::const_iterator
aIter( aList
.begin() );
181 while( aIter
!= aList
.end() )
183 const SwFrmOrObj
& rLower
= *aIter
;
184 const SwFrm
*pLower
= rLower
.GetSwFrm();
185 SwRect
aBox( rLower
.GetBox() );
186 if( rLower
.IsAccessible( GetShell()->IsPreView() ) )
188 Action eAction
= NONE
;
189 if( aBox
.IsOver( rNewVisArea
) )
191 if( aBox
.IsOver( rOldVisArea
) )
193 eAction
= SCROLLED_WITHIN
;
198 eAction
= SCROLLED_IN
;
203 else if( aBox
.IsOver( rOldVisArea
) )
206 eAction
= SCROLLED_OUT
;
210 else if( !bVisibleOnly
)
212 // This wouldn't be required if the SwAccessibleFrame,
213 // wouldn't know about the vis area.
216 if( NONE
!= eAction
)
220 ::vos::ORef
< SwAccessibleContext
> xAccImpl
=
221 GetMap()->GetContextImpl( pLower
, SCROLLED_OUT
== eAction
||
222 SCROLLED_IN
== eAction
);
223 if( xAccImpl
.isValid() )
228 xAccImpl
->Scrolled( rOldVisArea
);
230 case SCROLLED_WITHIN
:
231 xAccImpl
->ScrolledWithin( rOldVisArea
);
234 xAccImpl
->ScrolledIn();
237 xAccImpl
->ScrolledOut( rOldVisArea
);
245 ChildrenScrolled( pLower
, rOldVisArea
);
250 ::vos::ORef
< ::accessibility::AccessibleShape
> xAccImpl
=
251 GetMap()->GetContextImpl( rLower
.GetSdrObject(),
253 SCROLLED_OUT
== eAction
||
254 SCROLLED_IN
== eAction
);
255 if( xAccImpl
.isValid() )
260 case SCROLLED_WITHIN
:
261 xAccImpl
->ViewForwarderChanged(
262 ::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA
,
266 ScrolledInShape( rLower
.GetSdrObject(),
267 xAccImpl
.getBodyPtr() );
271 xAccImpl
->ViewForwarderChanged(
272 ::accessibility::IAccessibleViewForwarderListener::VISIBLE_AREA
,
274 DisposeShape( rLower
.GetSdrObject(),
275 xAccImpl
.getBodyPtr() );
285 else if( pLower
&& (!bVisibleOnly
||
286 aBox
.IsOver( rOldVisArea
) ||
287 aBox
.IsOver( rNewVisArea
)) )
289 // There are no unaccessible SdrObjects that need to be notified
290 ChildrenScrolled( pLower
, rOldVisArea
);
296 void SwAccessibleContext::Scrolled( const SwRect
& rOldVisArea
)
298 SetVisArea( GetMap()->GetVisArea() );
300 ChildrenScrolled( GetFrm(), rOldVisArea
);
302 sal_Bool bIsOldShowingState
;
303 sal_Bool bIsNewShowingState
= IsShowing();
305 vos::OGuard
aGuard( aMutex
);
306 bIsOldShowingState
= bIsShowingState
;
307 bIsShowingState
= bIsNewShowingState
;
310 if( bIsOldShowingState
!= bIsNewShowingState
)
311 FireStateChangedEvent( AccessibleStateType::SHOWING
,
312 bIsNewShowingState
);
315 void SwAccessibleContext::ScrolledWithin( const SwRect
& rOldVisArea
)
317 SetVisArea( GetMap()->GetVisArea() );
319 ChildrenScrolled( GetFrm(), rOldVisArea
);
321 FireVisibleDataEvent();
324 void SwAccessibleContext::ScrolledIn()
326 // This accessible should be freshly created, because it
327 // was not visisble before. Therefor, its vis area must already
328 // reflect the scrolling.
329 ASSERT( GetVisArea() == GetMap()->GetVisArea(),
330 "Vis area of child is wrong. Did it exist already?" );
332 // Send child event at parent. That's all we have to do here.
333 const SwFrm
*pParent
= GetParent();
334 ::vos::ORef
< SwAccessibleContext
> xParentImpl(
335 GetMap()->GetContextImpl( pParent
, sal_False
) );
336 uno::Reference
< XAccessibleContext
> xThis( this );
337 if( xParentImpl
.isValid() )
339 SetParent( xParentImpl
.getBodyPtr() );
341 AccessibleEventObject aEvent
;
342 aEvent
.EventId
= AccessibleEventId::CHILD
;
343 aEvent
.NewValue
<<= xThis
;
345 xParentImpl
->FireAccessibleEvent( aEvent
);
346 DBG_MSG_PARAM( "AccessibleChild (added)", xChildImpl
.getBodyPtr() );
350 Window
*pWin
= GetWindow();
351 if( pWin
&& pWin
->HasFocus() )
353 FireStateChangedEvent( AccessibleStateType::FOCUSED
, sal_True
);
360 void SwAccessibleContext::ScrolledOut( const SwRect
& rOldVisArea
)
362 SetVisArea( GetMap()->GetVisArea() );
364 // First of all, update the children. That's required to dispose
365 // all children that are existing only if they are visible. They
366 // are not disposed by the recusive Dispose call that follows later on,
367 // because this call will only dispose children that are in the
368 // new vis area. The children we want to dispode however are in the
370 ChildrenScrolled( GetFrm(), rOldVisArea
);
372 // Broadcast a state changed event for the showing state.
373 // It might be that the child is freshly created just to send
374 // the child event. In this case no listener will exist.
375 FireStateChangedEvent( AccessibleStateType::SHOWING
, sal_False
);
377 // We now dispose the frame
381 // --> OD 2005-12-12 #i27301# - use new type definition for <_nStates>
382 void SwAccessibleContext::InvalidateChildrenStates( const SwFrm
* _pFrm
,
383 tAccessibleStates _nStates
)
385 const SwFrmOrObjSList
aVisList( GetVisArea(), _pFrm
);
387 SwFrmOrObjSList::const_iterator
aIter( aVisList
.begin() );
388 while( aIter
!= aVisList
.end() )
390 const SwFrmOrObj
& rLower
= *aIter
;
391 const SwFrm
*pLower
= rLower
.GetSwFrm();
394 ::vos::ORef
< SwAccessibleContext
> xAccImpl
;
395 if( rLower
.IsAccessible( GetShell()->IsPreView() ) )
396 xAccImpl
= GetMap()->GetContextImpl( pLower
, sal_False
);
397 if( xAccImpl
.isValid() )
398 xAccImpl
->InvalidateStates( _nStates
);
400 InvalidateChildrenStates( pLower
, _nStates
);
411 void SwAccessibleContext::DisposeChildren( const SwFrm
*pFrm
,
412 sal_Bool bRecursive
)
414 const SwFrmOrObjSList
aVisList( GetVisArea(), pFrm
);
415 SwFrmOrObjSList::const_iterator
aIter( aVisList
.begin() );
416 while( aIter
!= aVisList
.end() )
418 const SwFrmOrObj
& rLower
= *aIter
;
419 const SwFrm
*pLower
= rLower
.GetSwFrm();
422 ::vos::ORef
< SwAccessibleContext
> xAccImpl
;
423 if( rLower
.IsAccessible( GetShell()->IsPreView() ) )
424 xAccImpl
= GetMap()->GetContextImpl( pLower
, sal_False
);
425 if( xAccImpl
.isValid() )
426 xAccImpl
->Dispose( bRecursive
);
427 else if( bRecursive
)
428 DisposeChildren( pLower
, bRecursive
);
432 ::vos::ORef
< ::accessibility::AccessibleShape
> xAccImpl(
433 GetMap()->GetContextImpl( rLower
.GetSdrObject(),
435 if( xAccImpl
.isValid() )
436 DisposeShape( rLower
.GetSdrObject(), xAccImpl
.getBodyPtr() );
442 void SwAccessibleContext::_InvalidateContent( sal_Bool
)
446 void SwAccessibleContext::_InvalidateCursorPos()
450 void SwAccessibleContext::_InvalidateFocus()
454 void SwAccessibleContext::FireAccessibleEvent( AccessibleEventObject
& rEvent
)
456 ASSERT( GetFrm(), "fire event for diposed frame?" );
460 if( !rEvent
.Source
.is() )
462 uno::Reference
< XAccessibleContext
> xThis( this );
463 rEvent
.Source
= xThis
;
467 comphelper::AccessibleEventNotifier::addEvent( nClientId
, rEvent
);
470 void SwAccessibleContext::FireVisibleDataEvent()
472 AccessibleEventObject aEvent
;
473 aEvent
.EventId
= AccessibleEventId::VISIBLE_DATA_CHANGED
;
475 FireAccessibleEvent( aEvent
);
476 DBG_MSG( "AccessibleVisibleData" )
479 void SwAccessibleContext::FireStateChangedEvent( sal_Int16 nState
,
482 AccessibleEventObject aEvent
;
484 aEvent
.EventId
= AccessibleEventId::STATE_CHANGED
;
486 aEvent
.NewValue
<<= nState
;
488 aEvent
.OldValue
<<= nState
;
490 FireAccessibleEvent( aEvent
);
491 DBG_MSG( "StateChanged" )
494 void SwAccessibleContext::GetStates(
495 ::utl::AccessibleStateSetHelper
& rStateSet
)
497 vos::OGuard
aGuard(Application::GetSolarMutex());
500 if( bIsShowingState
)
501 rStateSet
.AddState( AccessibleStateType::SHOWING
);
504 if( bIsEditableState
)
505 rStateSet
.AddState( AccessibleStateType::EDITABLE
);
508 rStateSet
.AddState( AccessibleStateType::ENABLED
);
512 rStateSet
.AddState( AccessibleStateType::OPAQUE
);
515 rStateSet
.AddState( AccessibleStateType::VISIBLE
);
518 rStateSet
.AddState( AccessibleStateType::DEFUNC
);
521 sal_Bool
SwAccessibleContext::IsEditableState()
525 vos::OGuard
aGuard( aMutex
);
526 bRet
= bIsEditableState
;
532 SwAccessibleContext::SwAccessibleContext( SwAccessibleMap
*pM
,
535 SwAccessibleFrame( pM
->GetVisArea().SVRect(), pF
,
536 pM
->GetShell()->IsPreView() ),
540 bDisposing( sal_False
),
541 // --> OD 2008-03-10 #i85634#
542 bRegisteredAtAccessibleMap( true )
546 DBG_MSG_CD( "constructed" )
549 SwAccessibleContext::~SwAccessibleContext()
551 vos::OGuard
aGuard(Application::GetSolarMutex());
553 DBG_MSG_CD( "destructed" )
554 // --> OD 2008-03-10 #i85634#
555 // if( GetFrm() && GetMap() )
556 // GetMap()->RemoveContext( GetFrm() );
557 RemoveFrmFromAccessibleMap();
561 uno::Reference
< XAccessibleContext
> SAL_CALL
562 SwAccessibleContext::getAccessibleContext( void )
563 throw (uno::RuntimeException
)
565 uno::Reference
< XAccessibleContext
> xRet( this );
569 sal_Int32 SAL_CALL
SwAccessibleContext::getAccessibleChildCount( void )
570 throw (uno::RuntimeException
)
572 vos::OGuard
aGuard(Application::GetSolarMutex());
574 CHECK_FOR_DEFUNC( XAccessibleContext
)
576 return bDisposing
? 0 : GetChildCount();
579 uno::Reference
< XAccessible
> SAL_CALL
580 SwAccessibleContext::getAccessibleChild( sal_Int32 nIndex
)
581 throw (uno::RuntimeException
, lang::IndexOutOfBoundsException
)
583 vos::OGuard
aGuard(Application::GetSolarMutex());
585 CHECK_FOR_DEFUNC( XAccessibleContext
)
587 const SwFrmOrObj
aChild( GetChild( nIndex
) );
588 if( !aChild
.IsValid() )
590 uno::Reference
< XAccessibleContext
> xThis( this );
591 lang::IndexOutOfBoundsException
aExcept(
592 OUString( RTL_CONSTASCII_USTRINGPARAM("index out of bounds") ),
597 uno::Reference
< XAccessible
> xChild
;
598 if( aChild
.GetSwFrm() )
600 ::vos::ORef
< SwAccessibleContext
> xChildImpl(
601 GetMap()->GetContextImpl( aChild
.GetSwFrm(), !bDisposing
) );
602 if( xChildImpl
.isValid() )
604 xChildImpl
->SetParent( this );
605 xChild
= xChildImpl
.getBodyPtr();
610 ::vos::ORef
< ::accessibility::AccessibleShape
> xChildImpl(
611 GetMap()->GetContextImpl( aChild
.GetSdrObject(),
612 this, !bDisposing
) );
613 if( xChildImpl
.isValid() )
614 xChild
= xChildImpl
.getBodyPtr();
620 uno::Reference
< XAccessible
> SAL_CALL
SwAccessibleContext::getAccessibleParent (void)
621 throw (uno::RuntimeException
)
623 vos::OGuard
aGuard(Application::GetSolarMutex());
625 CHECK_FOR_DEFUNC( XAccessibleContext
)
627 const SwFrm
*pUpper
= GetParent();
628 ASSERT( pUpper
!= 0 || bDisposing
, "no upper found" );
630 uno::Reference
< XAccessible
> xAcc
;
632 xAcc
= GetMap()->GetContext( pUpper
, !bDisposing
);
634 ASSERT( xAcc
.is() || bDisposing
, "no parent found" );
636 // Remember the parent as weak ref.
638 vos::OGuard
aWeakParentGuard( aMutex
);
645 sal_Int32 SAL_CALL
SwAccessibleContext::getAccessibleIndexInParent (void)
646 throw (uno::RuntimeException
)
648 vos::OGuard
aGuard(Application::GetSolarMutex());
650 CHECK_FOR_DEFUNC( XAccessibleContext
)
652 const SwFrm
*pUpper
= GetParent();
653 ASSERT( pUpper
!= 0 || bDisposing
, "no upper found" );
655 sal_Int32 nIndex
= -1;
658 ::vos::ORef
< SwAccessibleContext
> xAccImpl(
659 GetMap()->GetContextImpl( pUpper
, !bDisposing
) );
660 ASSERT( xAccImpl
.isValid() || bDisposing
, "no parent found" );
661 if( xAccImpl
.isValid() )
662 nIndex
= xAccImpl
->GetChildIndex( GetFrm() );
668 sal_Int16 SAL_CALL
SwAccessibleContext::getAccessibleRole (void)
669 throw (uno::RuntimeException
)
674 OUString SAL_CALL
SwAccessibleContext::getAccessibleDescription (void)
675 throw (uno::RuntimeException
)
677 ASSERT( !this, "description needs to be overloaded" );
678 THROW_RUNTIME_EXCEPTION( XAccessibleContext
, "internal error (method must be overloaded)" );
681 OUString SAL_CALL
SwAccessibleContext::getAccessibleName (void)
682 throw (uno::RuntimeException
)
687 uno::Reference
< XAccessibleRelationSet
> SAL_CALL
688 SwAccessibleContext::getAccessibleRelationSet (void)
689 throw (uno::RuntimeException
)
691 // by default there are no relations
692 uno::Reference
< XAccessibleRelationSet
> xRet( new utl::AccessibleRelationSetHelper() );
696 uno::Reference
<XAccessibleStateSet
> SAL_CALL
697 SwAccessibleContext::getAccessibleStateSet (void)
698 throw (uno::RuntimeException
)
700 vos::OGuard
aGuard(Application::GetSolarMutex());
702 CHECK_FOR_DEFUNC( XAccessibleContext
)
704 ::utl::AccessibleStateSetHelper
*pStateSet
=
705 new ::utl::AccessibleStateSetHelper
;
707 uno::Reference
<XAccessibleStateSet
> xStateSet( pStateSet
);
708 GetStates( *pStateSet
);
713 lang::Locale SAL_CALL
SwAccessibleContext::getLocale (void)
714 throw (IllegalAccessibleComponentStateException
, uno::RuntimeException
)
716 vos::OGuard
aGuard(Application::GetSolarMutex());
718 lang::Locale
aLoc( Application::GetSettings().GetLocale() );
722 void SAL_CALL
SwAccessibleContext::addEventListener(
723 const uno::Reference
< XAccessibleEventListener
>& xListener
)
724 throw (uno::RuntimeException
)
726 DBG_MSG( "accessible event listener added" )
730 vos::OGuard
aGuard(Application::GetSolarMutex());
732 nClientId
= comphelper::AccessibleEventNotifier::registerClient( );
733 comphelper::AccessibleEventNotifier::addEventListener( nClientId
, xListener
);
737 void SAL_CALL
SwAccessibleContext::removeEventListener(
738 const uno::Reference
< XAccessibleEventListener
>& xListener
)
739 throw (uno::RuntimeException
)
741 DBG_MSG( "accessible event listener removed" )
745 vos::OGuard
aGuard(Application::GetSolarMutex());
746 sal_Int32 nListenerCount
= comphelper::AccessibleEventNotifier::removeEventListener( nClientId
, xListener
);
747 if ( !nListenerCount
)
749 // no listeners anymore
750 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
751 // and at least to us not firing any events anymore, in case somebody calls
752 // NotifyAccessibleEvent, again
753 comphelper::AccessibleEventNotifier::revokeClient( nClientId
);
759 static sal_Bool
lcl_PointInRectangle(const awt::Point
& aPoint
,
760 const awt::Rectangle
& aRect
)
762 long nDiffX
= aPoint
.X
- aRect
.X
;
763 long nDiffY
= aPoint
.Y
- aRect
.Y
;
766 nDiffX
>= 0 && nDiffX
< aRect
.Width
&& nDiffY
>= 0 &&
767 nDiffY
< aRect
.Height
;
771 sal_Bool SAL_CALL
SwAccessibleContext::containsPoint(
772 const awt::Point
& aPoint
)
773 throw (uno::RuntimeException
)
775 awt::Rectangle aPixBounds
= getBoundsImpl(sal_True
);
779 return lcl_PointInRectangle(aPoint
, aPixBounds
);
782 uno::Reference
< XAccessible
> SAL_CALL
SwAccessibleContext::getAccessibleAtPoint(
783 const awt::Point
& aPoint
)
784 throw (uno::RuntimeException
)
786 vos::OGuard
aGuard(Application::GetSolarMutex());
788 CHECK_FOR_DEFUNC( XAccessibleComponent
)
790 uno::Reference
< XAccessible
> xAcc
;
792 Window
*pWin
= GetWindow();
793 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
)
795 Point
aPixPoint( aPoint
.X
, aPoint
.Y
); // px rel to parent
796 if( !GetFrm()->IsRootFrm() )
798 SwRect
aLogBounds( GetBounds( GetFrm() ) ); // twip rel to doc root
799 Point
aPixPos( GetMap()->CoreToPixel( aLogBounds
.SVRect() ).TopLeft() );
800 aPixPoint
.X() += aPixPos
.X();
801 aPixPoint
.Y() += aPixPos
.Y();
804 const SwFrmOrObj
aChild( GetChildAtPixel( aPixPoint
, GetMap() ) );
805 if( aChild
.GetSwFrm() )
807 xAcc
= GetMap()->GetContext( aChild
.GetSwFrm() );
809 else if( aChild
.GetSdrObject() )
811 xAcc
= GetMap()->GetContext( aChild
.GetSdrObject(), this );
825 Return bounding box relative to parent if parent is no root
826 frame. Otherwise return the absolute bounding box.
830 Return the absolute bounding box.
833 true: Use relative mode.
834 false: Use absolute mode.
836 awt::Rectangle SAL_CALL
SwAccessibleContext::getBoundsImpl(sal_Bool bRelative
)
837 throw (uno::RuntimeException
)
839 vos::OGuard
aGuard(Application::GetSolarMutex());
841 CHECK_FOR_DEFUNC( XAccessibleComponent
)
843 const SwFrm
*pParent
= GetParent();
844 ASSERT( pParent
, "no Parent found" );
845 Window
*pWin
= GetWindow();
847 CHECK_FOR_WINDOW( XAccessibleComponent
, pWin
&& pParent
)
849 SwRect
aLogBounds( GetBounds( GetFrm() ) ); // twip rel to doc root
850 Rectangle
aPixBounds( 0, 0, 0, 0 );
851 if( GetFrm()->IsPageFrm() &&
852 static_cast < const SwPageFrm
* >( GetFrm() )->IsEmptyPage() )
854 ASSERT( GetShell()->IsPreView(), "empty page accessible?" );
855 if( GetShell()->IsPreView() )
857 // OD 15.01.2003 #103492# - adjust method call <GetMap()->GetPreViewPageSize()>
858 sal_uInt16 nPageNum
=
859 static_cast < const SwPageFrm
* >( GetFrm() )->GetPhyPageNum();
860 aLogBounds
.SSize( GetMap()->GetPreViewPageSize( nPageNum
) );
863 if( !aLogBounds
.IsEmpty() )
865 aPixBounds
= GetMap()->CoreToPixel( aLogBounds
.SVRect() );
866 if( !pParent
->IsRootFrm() && bRelative
)
868 SwRect
aParentLogBounds( GetBounds( pParent
) ); // twip rel to doc root
869 Point
aParentPixPos( GetMap()->CoreToPixel( aParentLogBounds
.SVRect() ).TopLeft() );
870 aPixBounds
.Move( -aParentPixPos
.X(), -aParentPixPos
.Y() );
874 awt::Rectangle
aBox( aPixBounds
.Left(), aPixBounds
.Top(),
875 aPixBounds
.GetWidth(), aPixBounds
.GetHeight() );
881 awt::Rectangle SAL_CALL
SwAccessibleContext::getBounds()
882 throw (uno::RuntimeException
)
884 return getBoundsImpl(sal_True
);
887 awt::Point SAL_CALL
SwAccessibleContext::getLocation()
888 throw (uno::RuntimeException
)
890 awt::Rectangle aRect
= getBoundsImpl(sal_True
);
891 awt::Point
aPoint(aRect
.X
, aRect
.Y
);
898 awt::Point SAL_CALL
SwAccessibleContext::getLocationOnScreen()
899 throw (uno::RuntimeException
)
901 awt::Rectangle aRect
= getBoundsImpl(sal_False
);
903 Point
aPixPos(aRect
.X
, aRect
.Y
);
905 /* getBoundsImpl already checked that GetWindow returns valid pointer. */
906 aPixPos
= GetWindow()->OutputToAbsoluteScreenPixel(aPixPos
);
907 awt::Point
aPoint(aPixPos
.X(), aPixPos
.Y());
913 awt::Size SAL_CALL
SwAccessibleContext::getSize()
914 throw (uno::RuntimeException
)
916 awt::Rectangle aRect
= getBoundsImpl(sal_False
);
917 awt::Size
aSize( aRect
.Width
, aRect
.Height
);
922 void SAL_CALL
SwAccessibleContext::grabFocus()
923 throw (uno::RuntimeException
)
925 vos::OGuard
aGuard(Application::GetSolarMutex());
927 CHECK_FOR_DEFUNC( XAccessibleContext
);
929 if( GetFrm()->IsFlyFrm() )
931 const SdrObject
*pObj
=
932 static_cast < const SwFlyFrm
* >( GetFrm() )->GetVirtDrawObj();
934 Select( const_cast < SdrObject
* >( pObj
), sal_False
);
938 const SwCntntFrm
*pCFrm
= 0;
939 if( GetFrm()->IsCntntFrm() )
940 pCFrm
= static_cast< const SwCntntFrm
* >( GetFrm() );
941 else if( GetFrm()->IsLayoutFrm() )
942 pCFrm
= static_cast< const SwLayoutFrm
* >( GetFrm() )->ContainsCntnt();
944 if( pCFrm
&& pCFrm
->IsTxtFrm() )
946 const SwTxtFrm
*pTxtFrm
= static_cast< const SwTxtFrm
* >( pCFrm
);
947 const SwTxtNode
*pTxtNd
= pTxtFrm
->GetTxtNode();
950 // create pam for selection
951 SwIndex
aIndex( const_cast< SwTxtNode
* >( pTxtNd
),
952 pTxtFrm
->GetOfst() );
953 SwPosition
aStartPos( *pTxtNd
, aIndex
);
954 SwPaM
aPaM( aStartPos
);
956 // set PaM at cursor shell
964 uno::Any SAL_CALL
SwAccessibleContext::getAccessibleKeyBinding()
965 throw (uno::RuntimeException
)
967 // There are no key bindings
971 sal_Int32 SAL_CALL
SwAccessibleContext::getForeground()
972 throw (uno::RuntimeException
)
977 sal_Int32 SAL_CALL
SwAccessibleContext::getBackground()
978 throw (uno::RuntimeException
)
984 OUString SAL_CALL
SwAccessibleContext::getImplementationName()
985 throw( uno::RuntimeException
)
987 ASSERT( !this, "implementation name needs to be overloaded" );
989 THROW_RUNTIME_EXCEPTION( lang::XServiceInfo
, "implementation name needs to be overloaded" )
993 SwAccessibleContext::supportsService (const ::rtl::OUString
& )
994 throw (uno::RuntimeException
)
996 ASSERT( !this, "supports service needs to be overloaded" );
997 THROW_RUNTIME_EXCEPTION( lang::XServiceInfo
, "supports service needs to be overloaded" )
1000 uno::Sequence
< OUString
> SAL_CALL
SwAccessibleContext::getSupportedServiceNames()
1001 throw( uno::RuntimeException
)
1003 ASSERT( !this, "supported services names needs to be overloaded" );
1004 THROW_RUNTIME_EXCEPTION( lang::XServiceInfo
, "supported services needs to be overloaded" )
1007 void SwAccessibleContext::DisposeShape( const SdrObject
*pObj
,
1008 ::accessibility::AccessibleShape
*pAccImpl
)
1010 ::vos::ORef
< ::accessibility::AccessibleShape
> xAccImpl( pAccImpl
);
1011 if( !xAccImpl
.isValid() )
1012 xAccImpl
= GetMap()->GetContextImpl( pObj
, this, sal_True
);
1014 AccessibleEventObject aEvent
;
1015 aEvent
.EventId
= AccessibleEventId::CHILD
;
1016 uno::Reference
< XAccessible
> xAcc( xAccImpl
.getBodyPtr() );
1017 aEvent
.OldValue
<<= xAcc
;
1018 FireAccessibleEvent( aEvent
);
1020 GetMap()->RemoveContext( pObj
);
1021 xAccImpl
->dispose();
1024 void SwAccessibleContext::ScrolledInShape( const SdrObject
* ,
1025 ::accessibility::AccessibleShape
*pAccImpl
)
1027 AccessibleEventObject aEvent
;
1028 aEvent
.EventId
= AccessibleEventId::CHILD
;
1029 uno::Reference
< XAccessible
> xAcc( pAccImpl
);
1030 aEvent
.NewValue
<<= xAcc
;
1031 FireAccessibleEvent( aEvent
);
1033 if( pAccImpl
->GetState( AccessibleStateType::FOCUSED
) )
1035 Window
*pWin
= GetWindow();
1036 if( pWin
&& pWin
->HasFocus() )
1038 AccessibleEventObject aStateChangedEvent
;
1039 aStateChangedEvent
.EventId
= AccessibleEventId::STATE_CHANGED
;
1040 aStateChangedEvent
.NewValue
<<= AccessibleStateType::FOCUSED
;
1041 aStateChangedEvent
.Source
= xAcc
;
1043 FireAccessibleEvent( aStateChangedEvent
);
1048 void SwAccessibleContext::Dispose( sal_Bool bRecursive
)
1050 vos::OGuard
aGuard(Application::GetSolarMutex());
1052 ASSERT( GetFrm() && GetMap(), "already disposed" );
1053 ASSERT( GetMap()->GetVisArea() == GetVisArea(),
1054 "invalid vis area for dispose" );
1056 bDisposing
= sal_True
;
1060 DisposeChildren( GetFrm(), bRecursive
);
1063 uno::Reference
< XAccessible
> xParent( GetWeakParent() );
1064 uno::Reference
< XAccessibleContext
> xThis( this );
1066 // send child event at parent
1069 SwAccessibleContext
*pAcc
= (SwAccessibleContext
*)xParent
.get();
1071 AccessibleEventObject aEvent
;
1072 aEvent
.EventId
= AccessibleEventId::CHILD
;
1073 aEvent
.OldValue
<<= xThis
;
1074 pAcc
->FireAccessibleEvent( aEvent
);
1075 DBG_MSG_THIS_PARAM( "AccessibleChild (removed)", pAcc
, this )
1078 // set defunc state (its not required to broadcast a state changed
1079 // event if the object is diposed afterwards)
1081 vos::OGuard
aDefuncStateGuard( aMutex
);
1082 bIsDefuncState
= sal_True
;
1085 // broadcast dispose event
1088 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId
, *this );
1090 DBG_MSG_CD( "dispose" )
1093 // --> OD 2008-03-10 #i85634#
1094 // if( GetFrm() && GetMap() )
1095 // GetMap()->RemoveContext( GetFrm() );
1096 RemoveFrmFromAccessibleMap();
1101 bDisposing
= sal_False
;
1104 void SwAccessibleContext::DisposeChild( const SwFrmOrObj
& rChildFrmOrObj
,
1105 sal_Bool bRecursive
)
1107 vos::OGuard
aGuard(Application::GetSolarMutex());
1109 SwFrmOrObj
aFrmOrObj( GetFrm() );
1110 if( IsShowing( rChildFrmOrObj
) || !aFrmOrObj
.IsVisibleChildrenOnly() )
1112 // If the object could have existed before, than there is nothing to do,
1113 // because no wrapper exists now and therefor no one is interested to
1114 // get notified of the movement.
1115 if( rChildFrmOrObj
.GetSwFrm() )
1117 ::vos::ORef
< SwAccessibleContext
> xAccImpl
=
1118 GetMap()->GetContextImpl( rChildFrmOrObj
.GetSwFrm(),
1120 xAccImpl
->Dispose( bRecursive
);
1124 ::vos::ORef
< ::accessibility::AccessibleShape
> xAccImpl
=
1125 GetMap()->GetContextImpl( rChildFrmOrObj
.GetSdrObject(),
1127 DisposeShape( rChildFrmOrObj
.GetSdrObject(),
1128 xAccImpl
.getBodyPtr() );
1131 else if( bRecursive
&& rChildFrmOrObj
.GetSwFrm() )
1132 DisposeChildren( rChildFrmOrObj
.GetSwFrm(), bRecursive
);
1135 void SwAccessibleContext::InvalidatePosOrSize( const SwRect
& )
1137 vos::OGuard
aGuard(Application::GetSolarMutex());
1139 ASSERT( GetFrm() && !GetFrm()->Frm().IsEmpty(), "context should have a size" );
1141 sal_Bool bIsOldShowingState
;
1142 sal_Bool bIsNewShowingState
= IsShowing();
1144 vos::OGuard
aShowingStateGuard( aMutex
);
1145 bIsOldShowingState
= bIsShowingState
;
1146 bIsShowingState
= bIsNewShowingState
;
1149 if( bIsOldShowingState
!= bIsNewShowingState
)
1151 FireStateChangedEvent( AccessibleStateType::SHOWING
,
1152 bIsNewShowingState
);
1154 else if( bIsNewShowingState
)
1156 // The frame stays visible -> broadcast event
1157 FireVisibleDataEvent();
1160 SwFrmOrObj
aParent( GetParent() );
1161 if( !bIsNewShowingState
&& aParent
.IsVisibleChildrenOnly() )
1163 // The frame is now invisible -> dispose it
1164 Dispose( sal_True
);
1168 _InvalidateContent( sal_True
);
1172 void SwAccessibleContext::InvalidateChildPosOrSize(
1173 const SwFrmOrObj
& rChildFrmOrObj
,
1174 const SwRect
& rOldFrm
)
1176 vos::OGuard
aGuard(Application::GetSolarMutex());
1178 ASSERT( !rChildFrmOrObj
.GetSwFrm() ||
1179 !rChildFrmOrObj
.GetSwFrm()->Frm().IsEmpty(),
1180 "child context should have a size" );
1182 SwFrmOrObj
aFrm( GetFrm() );
1183 sal_Bool bNew
= rOldFrm
.IsEmpty() ||
1184 (rOldFrm
.Left() == 0 && rOldFrm
.Top() == 0);
1185 if( IsShowing( rChildFrmOrObj
) )
1187 // If the object could have existed before, than there is nothing to do,
1188 // because no wrapper exists now and therefor no one is interested to
1189 // get notified of the movement.
1190 if( bNew
|| (aFrm
.IsVisibleChildrenOnly() && !IsShowing( rOldFrm
)) )
1192 if( rChildFrmOrObj
.GetSwFrm() )
1194 // The frame becomes visible. A child event must be send.
1195 ::vos::ORef
< SwAccessibleContext
> xAccImpl
=
1196 GetMap()->GetContextImpl( rChildFrmOrObj
.GetSwFrm(),
1198 xAccImpl
->ScrolledIn();
1202 ::vos::ORef
< ::accessibility::AccessibleShape
> xAccImpl
=
1203 GetMap()->GetContextImpl( rChildFrmOrObj
.GetSdrObject(),
1205 // --> OD 2004-11-29 #i37790#
1206 if ( xAccImpl
.isValid() )
1208 ScrolledInShape( rChildFrmOrObj
.GetSdrObject(),
1209 xAccImpl
.getBodyPtr() );
1214 "<SwAccessibleContext::InvalidateChildPosOrSize(..)> - no accessible shape found." );
1222 // If the frame was visible before, than a child event for the parent
1223 // needs to be send. However, there is no wrapper existing, and so
1224 // no notifications for grandchildren are required. If the are
1225 // grandgrandchildren, they would be notified by the layout.
1226 if( aFrm
.IsVisibleChildrenOnly() &&
1227 !bNew
&& IsShowing( rOldFrm
) )
1229 if( rChildFrmOrObj
.GetSwFrm() )
1231 ::vos::ORef
< SwAccessibleContext
> xAccImpl
=
1232 GetMap()->GetContextImpl( rChildFrmOrObj
.GetSwFrm(),
1234 xAccImpl
->SetParent( this );
1235 xAccImpl
->Dispose( sal_True
);
1239 ::vos::ORef
< ::accessibility::AccessibleShape
> xAccImpl
=
1240 GetMap()->GetContextImpl( rChildFrmOrObj
.GetSdrObject(),
1242 DisposeShape( rChildFrmOrObj
.GetSdrObject(),
1243 xAccImpl
.getBodyPtr() );
1249 void SwAccessibleContext::InvalidateContent()
1251 vos::OGuard
aGuard(Application::GetSolarMutex());
1253 _InvalidateContent( sal_False
);
1256 void SwAccessibleContext::InvalidateCursorPos()
1258 vos::OGuard
aGuard(Application::GetSolarMutex());
1260 _InvalidateCursorPos();
1263 void SwAccessibleContext::InvalidateFocus()
1265 vos::OGuard
aGuard(Application::GetSolarMutex());
1270 // --> OD 2005-12-12 #i27301# - use new type definition for <_nStates>
1271 void SwAccessibleContext::InvalidateStates( tAccessibleStates _nStates
)
1275 ViewShell
*pVSh
= GetMap()->GetShell();
1278 if( (_nStates
& ACC_STATE_EDITABLE
) != 0 )
1280 sal_Bool bIsOldEditableState
;
1281 sal_Bool bIsNewEditableState
= IsEditable( pVSh
);
1283 vos::OGuard
aGuard( aMutex
);
1284 bIsOldEditableState
= bIsEditableState
;
1285 bIsEditableState
= bIsNewEditableState
;
1288 if( bIsOldEditableState
!= bIsNewEditableState
)
1289 FireStateChangedEvent( AccessibleStateType::EDITABLE
,
1290 bIsNewEditableState
);
1292 if( (_nStates
& ACC_STATE_OPAQUE
) != 0 )
1294 sal_Bool bIsOldOpaqueState
;
1295 sal_Bool bIsNewOpaqueState
= IsOpaque( pVSh
);
1297 vos::OGuard
aGuard( aMutex
);
1298 bIsOldOpaqueState
= bIsOpaqueState
;
1299 bIsOpaqueState
= bIsNewOpaqueState
;
1302 if( bIsOldOpaqueState
!= bIsNewOpaqueState
)
1303 FireStateChangedEvent( AccessibleStateType::OPAQUE
,
1304 bIsNewOpaqueState
);
1308 InvalidateChildrenStates( GetFrm(), _nStates
);
1313 void SwAccessibleContext::InvalidateRelation( sal_uInt16 nType
)
1315 AccessibleEventObject aEvent
;
1316 aEvent
.EventId
= nType
;
1318 FireAccessibleEvent( aEvent
);
1321 /** text selection has changed
1323 OD 2005-12-14 #i27301#
1327 void SwAccessibleContext::InvalidateTextSelection()
1329 AccessibleEventObject aEvent
;
1330 aEvent
.EventId
= AccessibleEventId::TEXT_SELECTION_CHANGED
;
1332 FireAccessibleEvent( aEvent
);
1335 /** attributes has changed
1337 OD 2009-01-06 #i88069#
1341 void SwAccessibleContext::InvalidateAttr()
1343 AccessibleEventObject aEvent
;
1344 aEvent
.EventId
= AccessibleEventId::TEXT_ATTRIBUTE_CHANGED
;
1346 FireAccessibleEvent( aEvent
);
1349 sal_Bool
SwAccessibleContext::HasCursor()
1354 sal_Bool
SwAccessibleContext::Select( SwPaM
*pPaM
, SdrObject
*pObj
,
1357 SwCrsrShell
* pCrsrShell
= GetCrsrShell();
1361 SwFEShell
* pFEShell
= pCrsrShell
->ISA( SwFEShell
)
1362 ? static_cast<SwFEShell
*>( pCrsrShell
)
1364 // Get rid of activated OLE object
1366 pFEShell
->FinishOLEObj();
1368 sal_Bool bRet
= sal_False
;
1374 sal_uInt8 nFlags
= bAdd
? SW_ADD_SELECT
: 0;
1375 pFEShell
->SelectObj( aDummy
, nFlags
, pObj
);
1381 // Get rid of frame selection. If there is one, make text cursor
1383 sal_Bool bCallShowCrsr
= sal_False
;
1384 if( pFEShell
&& (pFEShell
->IsFrmSelected() ||
1385 pFEShell
->IsObjSelected()) )
1387 Point
aPt( LONG_MIN
, LONG_MIN
);
1388 pFEShell
->SelectObj( aPt
, 0 );
1389 bCallShowCrsr
= sal_True
;
1391 pCrsrShell
->KillPams();
1392 pCrsrShell
->SetSelection( *pPaM
);
1394 pCrsrShell
->ShowCrsr();
1401 OUString
SwAccessibleContext::GetResource( sal_uInt16 nResId
,
1402 const OUString
*pArg1
,
1403 const OUString
*pArg2
)
1407 vos::OGuard
aGuard(Application::GetSolarMutex());
1409 sStr
= SW_RES( nResId
);
1414 sStr
.SearchAndReplace( String::CreateFromAscii(
1415 RTL_CONSTASCII_STRINGPARAM( "$(ARG1)" )),
1420 sStr
.SearchAndReplace( String::CreateFromAscii(
1421 RTL_CONSTASCII_STRINGPARAM( "$(ARG2)" )),
1425 return OUString( sStr
);
1428 // --> OD 2008-03-10 #i85634#
1429 void SwAccessibleContext::RemoveFrmFromAccessibleMap()
1431 if( bRegisteredAtAccessibleMap
&& GetFrm() && GetMap() )
1432 GetMap()->RemoveContext( GetFrm() );
1436 #if (OSL_DEBUG_LEVEL > 1) && defined TEST_MIB
1437 void lcl_SwAccessibleContext_DbgMsg( SwAccessibleContext
*pThisAcc
,
1439 SwAccessibleContext
*pChildAcc
,
1440 sal_Bool bConstrDestr
)
1442 static SvFileStream
aStrm( String::CreateFromAscii("j:\\acc.log"),
1443 STREAM_WRITE
|STREAM_TRUNC
|STREAM_SHARE_DENYNONE
);
1444 ByteString
aName( String(pThisAcc
->GetName()),
1445 RTL_TEXTENCODING_ISO_8859_1
);
1448 aStrm
<< aName
.GetBuffer()
1454 ByteString
aChild( String(pChildAcc
->GetName()),
1455 RTL_TEXTENCODING_ISO_8859_1
);
1457 << aChild
.GetBuffer();
1463 ByteString
aDesc( String(pThisAcc
->getAccessibleDescription()),
1464 RTL_TEXTENCODING_ISO_8859_1
);
1465 aStrm
<< aDesc
.GetBuffer()
1469 Rectangle
aVisArea( pThisAcc
->GetVisArea() );
1471 << ByteString::CreateFromInt32( aVisArea
.Left() ).GetBuffer()
1473 << ByteString::CreateFromInt32( aVisArea
.Top() ).GetBuffer()
1475 << ByteString::CreateFromInt32( aVisArea
.GetWidth() ).GetBuffer()
1477 << ByteString::CreateFromInt32( aVisArea
.GetHeight() ).GetBuffer();
1479 if( pThisAcc
->GetFrm() )
1481 Rectangle
aBounds( pThisAcc
->GetBounds( pThisAcc
->GetFrm() ) );
1483 << ByteString::CreateFromInt32( aBounds
.Left() ).GetBuffer()
1485 << ByteString::CreateFromInt32( aBounds
.Top() ).GetBuffer()
1487 << ByteString::CreateFromInt32( aBounds
.GetWidth() ).GetBuffer()
1489 << ByteString::CreateFromInt32( aBounds
.GetHeight() ).GetBuffer()