tdf#35361 Add a Quick Look plugins for .od* files on macOS
[LibreOffice.git] / sw / source / core / access / acccontext.cxx
blob52a35642a9e9a05e1d08ef9d95c1c66b5a316b2a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vcl/window.hxx>
21 #include <swtypes.hxx>
23 #include <com/sun/star/accessibility/XAccessible.hpp>
24 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
25 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
26 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
27 #include <sal/log.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/settings.hxx>
30 #include <i18nlangtag/languagetag.hxx>
31 #include <unotools/accessiblerelationsethelper.hxx>
32 #include <viewsh.hxx>
33 #include <crsrsh.hxx>
34 #include <fesh.hxx>
35 #include <wrtsh.hxx>
36 #include <txtfrm.hxx>
37 #include <ndtxt.hxx>
38 #include <pagefrm.hxx>
39 #include <flyfrm.hxx>
40 #include <dflyobj.hxx>
41 #include <pam.hxx>
42 #include <accmap.hxx>
43 #include "accfrmobjslist.hxx"
44 #include "acccontext.hxx"
45 #include <svx/AccessibleShape.hxx>
46 #include <comphelper/accessibleeventnotifier.hxx>
47 #include <cppuhelper/supportsservice.hxx>
48 #include <PostItMgr.hxx>
50 using namespace sw::access;
51 using namespace ::com::sun::star;
52 using namespace ::com::sun::star::accessibility;
54 void SwAccessibleContext::InitStates()
56 m_isShowingState = GetMap() && IsShowing( *(GetMap()) );
58 SwViewShell *pVSh = GetMap()->GetShell();
59 m_isEditableState = pVSh && IsEditable( pVSh );
60 m_isOpaqueState = pVSh && IsOpaque( pVSh );
61 m_isDefuncState = false;
64 void SwAccessibleContext::SetParent( SwAccessibleContext *pParent )
66 std::scoped_lock aGuard( m_Mutex );
68 m_xWeakParent = pParent;
71 rtl::Reference< SwAccessibleContext > SwAccessibleContext::GetWeakParent() const
73 std::scoped_lock aGuard( m_Mutex );
75 return m_xWeakParent.get();
78 vcl::Window *SwAccessibleContext::GetWindow()
80 vcl::Window *pWin = nullptr;
82 if( GetMap() )
84 const SwViewShell *pVSh = GetMap()->GetShell();
85 OSL_ENSURE( pVSh, "no view shell" );
86 if( pVSh )
87 pWin = pVSh->GetWin();
89 OSL_ENSURE( pWin, "no window" );
92 return pWin;
95 // get SwViewShell from accessibility map, and cast to cursor shell
96 SwCursorShell* SwAccessibleContext::GetCursorShell()
98 SwViewShell* pViewShell = GetMap() ? GetMap()->GetShell() : nullptr;
99 OSL_ENSURE( pViewShell, "no view shell" );
100 return dynamic_cast<SwCursorShell*>( pViewShell);
103 const SwCursorShell* SwAccessibleContext::GetCursorShell() const
105 // just like non-const GetCursorShell
106 const SwViewShell* pViewShell = GetMap() ? GetMap()->GetShell() : nullptr;
107 OSL_ENSURE( pViewShell, "no view shell" );
108 return dynamic_cast<const SwCursorShell*>( pViewShell);
111 namespace {
113 enum class Action { NONE, SCROLLED, SCROLLED_WITHIN,
114 SCROLLED_IN, SCROLLED_OUT };
118 void SwAccessibleContext::ChildrenScrolled( const SwFrame *pFrame,
119 const SwRect& rOldVisArea )
121 const SwRect& rNewVisArea = GetVisArea();
122 const bool bVisibleChildrenOnly = SwAccessibleChild( pFrame ).IsVisibleChildrenOnly();
124 const SwAccessibleChildSList aList( *pFrame, *(GetMap()) );
125 SwAccessibleChildSList::const_iterator aIter( aList.begin() );
126 while( aIter != aList.end() )
128 const SwAccessibleChild& rLower = *aIter;
129 const SwRect aBox( rLower.GetBox( *(GetMap()) ) );
130 if( rLower.IsAccessible( GetShell()->IsPreview() ) )
132 Action eAction = Action::NONE;
133 if( aBox.Overlaps( rNewVisArea ) )
135 if( aBox.Overlaps( rOldVisArea ) )
137 eAction = Action::SCROLLED_WITHIN;
139 else
141 if ( bVisibleChildrenOnly &&
142 !rLower.AlwaysIncludeAsChild() )
144 eAction = Action::SCROLLED_IN;
146 else
148 eAction = Action::SCROLLED;
152 else if( aBox.Overlaps( rOldVisArea ) )
154 if ( bVisibleChildrenOnly &&
155 !rLower.AlwaysIncludeAsChild() )
157 eAction = Action::SCROLLED_OUT;
159 else
161 eAction = Action::SCROLLED;
164 else if( !bVisibleChildrenOnly ||
165 rLower.AlwaysIncludeAsChild() )
167 // This wouldn't be required if the SwAccessibleFrame,
168 // wouldn't know about the visible area.
169 eAction = Action::SCROLLED;
171 if( Action::NONE != eAction )
173 if ( rLower.GetSwFrame() )
175 OSL_ENSURE( !rLower.AlwaysIncludeAsChild(),
176 "<SwAccessibleContext::ChildrenScrolled(..)> - always included child not considered!" );
177 const SwFrame* pLower( rLower.GetSwFrame() );
178 ::rtl::Reference< SwAccessibleContext > xAccImpl =
179 GetMap()->GetContextImpl( pLower );
180 if( xAccImpl.is() )
182 switch( eAction )
184 case Action::SCROLLED:
185 xAccImpl->Scrolled( rOldVisArea );
186 break;
187 case Action::SCROLLED_WITHIN:
188 xAccImpl->ScrolledWithin( rOldVisArea );
189 break;
190 case Action::SCROLLED_IN:
191 xAccImpl->ScrolledIn();
192 break;
193 case Action::SCROLLED_OUT:
194 xAccImpl->ScrolledOut( rOldVisArea );
195 break;
196 case Action::NONE:
197 break;
200 else
202 ChildrenScrolled( pLower, rOldVisArea );
205 else if ( rLower.GetDrawObject() )
207 OSL_ENSURE( !rLower.AlwaysIncludeAsChild(),
208 "<SwAccessibleContext::ChildrenScrolled(..)> - always included child not considered!" );
209 ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
210 GetMap()->GetContextImpl( rLower.GetDrawObject(),
211 this );
212 if( xAccImpl.is() )
214 switch( eAction )
216 case Action::SCROLLED:
217 case Action::SCROLLED_WITHIN:
218 xAccImpl->ViewForwarderChanged();
219 break;
220 case Action::SCROLLED_IN:
221 ScrolledInShape( xAccImpl.get() );
222 break;
223 case Action::SCROLLED_OUT:
225 xAccImpl->ViewForwarderChanged();
226 // this DisposeShape call was removed by
227 // IAccessibility2 implementation
228 // without giving any reason why
229 DisposeShape( rLower.GetDrawObject(),
230 xAccImpl.get() );
232 break;
233 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
234 case Action::NONE:
235 break;
239 else if ( rLower.GetWindow() )
241 // nothing to do - as such children are always included as children.
242 OSL_ENSURE( rLower.AlwaysIncludeAsChild(),
243 "<SwAccessibleContext::ChildrenScrolled(..)> - not always included child not considered!" );
247 else if ( rLower.GetSwFrame() &&
248 ( !bVisibleChildrenOnly ||
249 aBox.Overlaps( rOldVisArea ) ||
250 aBox.Overlaps( rNewVisArea ) ) )
252 // There are no unaccessible SdrObjects that need to be notified
253 ChildrenScrolled( rLower.GetSwFrame(), rOldVisArea );
255 ++aIter;
259 void SwAccessibleContext::Scrolled( const SwRect& rOldVisArea )
261 SetVisArea( GetMap()->GetVisArea() );
263 ChildrenScrolled( GetFrame(), rOldVisArea );
265 bool bIsOldShowingState;
266 bool bIsNewShowingState = IsShowing( *(GetMap()) );
268 std::scoped_lock aGuard( m_Mutex );
269 bIsOldShowingState = m_isShowingState;
270 m_isShowingState = bIsNewShowingState;
273 if( bIsOldShowingState != bIsNewShowingState )
274 FireStateChangedEvent( AccessibleStateType::SHOWING,
275 bIsNewShowingState );
278 void SwAccessibleContext::ScrolledWithin( const SwRect& rOldVisArea )
280 SetVisArea( GetMap()->GetVisArea() );
282 ChildrenScrolled( GetFrame(), rOldVisArea );
284 FireVisibleDataEvent();
287 void SwAccessibleContext::ScrolledIn()
289 // This accessible should be freshly created, because it
290 // was not visible before. Therefore, its visible area must already
291 // reflect the scrolling.
292 OSL_ENSURE( GetVisArea() == GetMap()->GetVisArea(),
293 "Visible area of child is wrong. Did it exist already?" );
295 // Send child event at parent. That's all we have to do here.
296 const SwFrame* pParent = GetParent();
297 ::rtl::Reference< SwAccessibleContext > xParentImpl(
298 GetMap()->GetContextImpl( pParent, false ) );
299 uno::Reference < XAccessibleContext > xThis( this );
300 if( !xParentImpl.is() )
301 return;
303 SetParent( xParentImpl.get() );
305 AccessibleEventObject aEvent;
306 aEvent.EventId = AccessibleEventId::CHILD;
307 aEvent.NewValue <<= xThis;
308 aEvent.IndexHint = -1;
310 xParentImpl->FireAccessibleEvent( aEvent );
312 if( HasCursor() )
314 vcl::Window *pWin = GetWindow();
315 if( pWin && pWin->HasFocus() )
317 FireStateChangedEvent( AccessibleStateType::FOCUSED, true );
322 void SwAccessibleContext::ScrolledOut( const SwRect& rOldVisArea )
324 SetVisArea( GetMap()->GetVisArea() );
326 // First of all, update the children. That's required to dispose
327 // all children that are existing only if they are visible. They
328 // are not disposed by the recursive Dispose call that follows later on,
329 // because this call will only dispose children that are in the
330 // new visible area. The children we want to dispose however are in the
331 // old visible area all.
332 ChildrenScrolled( GetFrame(), rOldVisArea );
334 // Broadcast a state changed event for the showing state.
335 // It might be that the child is freshly created just to send
336 // the child event. In this case no listener will exist.
337 FireStateChangedEvent( AccessibleStateType::SHOWING, false );
339 // this Dispose call was removed by IAccessibility2 implementation
340 // without giving any reason why - without it we get stale
341 // entries in SwAccessibleMap::mpFrameMap.
342 Dispose(true);
345 // #i27301# - use new type definition for <_nStates>
346 void SwAccessibleContext::InvalidateChildrenStates( const SwFrame* _pFrame,
347 AccessibleStates _nStates )
349 const SwAccessibleChildSList aVisList( GetVisArea(), *_pFrame, *(GetMap()) );
351 SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
352 while( aIter != aVisList.end() )
354 const SwAccessibleChild& rLower = *aIter;
355 const SwFrame* pLower = rLower.GetSwFrame();
356 if( pLower )
358 ::rtl::Reference< SwAccessibleContext > xAccImpl;
359 if( rLower.IsAccessible( GetShell()->IsPreview() ) )
360 xAccImpl = GetMap()->GetContextImpl( pLower, false );
361 if( xAccImpl.is() )
362 xAccImpl->InvalidateStates( _nStates );
363 else
364 InvalidateChildrenStates( pLower, _nStates );
366 else if ( rLower.GetDrawObject() )
368 // TODO: SdrObjects
370 else if ( rLower.GetWindow() )
372 // nothing to do ?
375 ++aIter;
379 void SwAccessibleContext::DisposeChildren(const SwFrame *pFrame,
380 bool bRecursive,
381 bool bCanSkipInvisible)
383 const SwAccessibleChildSList aVisList( GetVisArea(), *pFrame, *(GetMap()) );
384 SwAccessibleChildSList::const_iterator aIter( aVisList.begin() );
385 while( aIter != aVisList.end() )
387 const SwAccessibleChild& rLower = *aIter;
388 const SwFrame* pLower = rLower.GetSwFrame();
389 if( pLower )
391 // tdf#117601 dispose the darn thing if it ever was accessible
392 ::rtl::Reference<SwAccessibleContext> xAccImpl = GetMap()->GetContextImpl(pLower, false);
393 if( xAccImpl.is() )
394 xAccImpl->Dispose( bRecursive );
395 else
397 // it's possible that the xAccImpl *does* exist with a
398 // ref-count of 0 and blocked in its dtor in another thread -
399 // this call here could be from SwAccessibleMap dtor so
400 // remove it from any maps now!
401 GetMap()->RemoveContext(pLower);
402 // in this case the context will check with a weak_ptr
403 // that the map is still alive so it's not necessary
404 // to clear its m_pMap here.
405 if (bRecursive)
407 DisposeChildren(pLower, bRecursive, bCanSkipInvisible);
411 else if ( rLower.GetDrawObject() )
413 ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl(
414 GetMap()->GetContextImpl( rLower.GetDrawObject(),
415 this, false ) );
416 if( xAccImpl.is() )
417 DisposeShape( rLower.GetDrawObject(), xAccImpl.get() );
419 else if ( rLower.GetWindow() )
421 DisposeChild(rLower, false, bCanSkipInvisible);
423 ++aIter;
427 void SwAccessibleContext::InvalidateContent_( bool )
431 void SwAccessibleContext::InvalidateCursorPos_()
435 void SwAccessibleContext::InvalidateFocus_()
439 void SwAccessibleContext::FireAccessibleEvent( AccessibleEventObject& rEvent )
441 if( !GetFrame() )
443 SAL_INFO("sw.a11y", "SwAccessibleContext::FireAccessibleEvent called for already disposed frame?");
444 return;
447 if( !rEvent.Source.is() )
449 uno::Reference < XAccessibleContext > xThis( this );
450 rEvent.Source = xThis;
453 if (m_nClientId)
454 comphelper::AccessibleEventNotifier::addEvent( m_nClientId, rEvent );
457 void SwAccessibleContext::FireVisibleDataEvent()
459 AccessibleEventObject aEvent;
460 aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
462 FireAccessibleEvent( aEvent );
465 void SwAccessibleContext::FireStateChangedEvent( sal_Int64 nState,
466 bool bNewState )
468 AccessibleEventObject aEvent;
470 aEvent.EventId = AccessibleEventId::STATE_CHANGED;
471 if( bNewState )
472 aEvent.NewValue <<= nState;
473 else
474 aEvent.OldValue <<= nState;
476 FireAccessibleEvent( aEvent );
479 void SwAccessibleContext::GetStates( sal_Int64& rStateSet )
481 std::scoped_lock aGuard( m_Mutex );
483 // SHOWING
484 if (m_isShowingState)
485 rStateSet |= AccessibleStateType::SHOWING;
487 // EDITABLE
488 if (m_isEditableState)
489 //Set editable state to graphic and other object when the document is editable
491 rStateSet |= AccessibleStateType::EDITABLE;
492 rStateSet |= AccessibleStateType::RESIZABLE;
493 rStateSet |= AccessibleStateType::MOVEABLE;
495 // ENABLED
496 rStateSet |= AccessibleStateType::ENABLED;
498 // OPAQUE
499 if (m_isOpaqueState)
500 rStateSet |= AccessibleStateType::OPAQUE;
502 // VISIBLE
503 rStateSet |= AccessibleStateType::VISIBLE;
505 if (m_isDefuncState)
506 rStateSet |= AccessibleStateType::DEFUNC;
509 bool SwAccessibleContext::IsEditableState()
511 bool bRet;
513 std::scoped_lock aGuard( m_Mutex );
514 bRet = m_isEditableState;
517 return bRet;
520 bool SwAccessibleContext::IsDisposed() const
522 return !(GetFrame() && GetMap());
525 void SwAccessibleContext::ThrowIfDisposed()
527 if (IsDisposed())
529 throw lang::DisposedException(u"object is nonfunctional"_ustr,
530 getXWeak());
534 SwAccessibleContext::SwAccessibleContext(std::shared_ptr<SwAccessibleMap> const& pMap,
535 sal_Int16 const nRole,
536 const SwFrame *pF )
537 : SwAccessibleFrame( pMap->GetVisArea(), pF,
538 pMap->GetShell()->IsPreview() )
539 , m_pMap(pMap.get())
540 , m_wMap(pMap)
541 , m_nClientId(0)
542 , m_nRole(nRole)
543 , m_isDisposing( false )
544 , m_isRegisteredAtAccessibleMap( true )
545 , m_isSelectedInDoc(false)
547 InitStates();
550 SwAccessibleContext::~SwAccessibleContext()
552 // must have for 2 reasons: 2. as long as this thread has SolarMutex
553 // another thread cannot destroy the SwAccessibleMap so our temporary
554 // taking a hard ref to SwAccessibleMap won't delay its destruction
555 SolarMutexGuard aGuard;
556 // must check with weak_ptr that m_pMap is still alive
557 std::shared_ptr<SwAccessibleMap> pMap(m_wMap.lock());
558 if (m_isRegisteredAtAccessibleMap && GetFrame() && pMap)
560 pMap->RemoveContext( GetFrame() );
564 uno::Reference< XAccessibleContext > SAL_CALL
565 SwAccessibleContext::getAccessibleContext()
567 uno::Reference < XAccessibleContext > xRet( this );
568 return xRet;
571 sal_Int64 SAL_CALL SwAccessibleContext::getAccessibleChildCount()
573 SolarMutexGuard aGuard;
575 ThrowIfDisposed();
577 return m_isDisposing ? 0 : GetChildCount( *(GetMap()) );
580 uno::Reference< XAccessible> SAL_CALL
581 SwAccessibleContext::getAccessibleChild( sal_Int64 nIndex )
583 SolarMutexGuard aGuard;
585 ThrowIfDisposed();
587 if (nIndex < 0 || nIndex >= getAccessibleChildCount())
588 throw lang::IndexOutOfBoundsException();
590 const SwAccessibleChild aChild( GetChild( *(GetMap()), nIndex ) );
591 if( !aChild.IsValid() )
593 uno::Reference < XAccessibleContext > xThis( this );
594 lang::IndexOutOfBoundsException aExcept(
595 u"index out of bounds"_ustr,
596 xThis );
597 throw aExcept;
600 uno::Reference< XAccessible > xChild;
601 if( aChild.GetSwFrame() )
603 ::rtl::Reference < SwAccessibleContext > xChildImpl(
604 GetMap()->GetContextImpl( aChild.GetSwFrame(), !m_isDisposing ) );
605 if( xChildImpl.is() )
607 xChildImpl->SetParent( this );
608 xChild = xChildImpl.get();
611 else if ( aChild.GetDrawObject() )
613 ::rtl::Reference < ::accessibility::AccessibleShape > xChildImpl(
614 GetMap()->GetContextImpl( aChild.GetDrawObject(),
615 this, !m_isDisposing) );
616 if( xChildImpl.is() )
617 xChild = xChildImpl.get();
619 else if ( aChild.GetWindow() )
621 xChild = aChild.GetWindow()->GetAccessible();
624 return xChild;
627 css::uno::Sequence<uno::Reference<XAccessible>> SAL_CALL
628 SwAccessibleContext::getAccessibleChildren()
630 SolarMutexGuard aGuard;
632 ThrowIfDisposed();
634 std::list< sw::access::SwAccessibleChild > aChildren;
635 GetChildren( *GetMap(), aChildren );
637 std::vector<uno::Reference<XAccessible>> aRet;
638 aRet.reserve(aChildren.size());
639 for (const auto & rSwChild : aChildren)
641 uno::Reference< XAccessible > xChild;
642 if( rSwChild.GetSwFrame() )
644 ::rtl::Reference < SwAccessibleContext > xChildImpl(
645 GetMap()->GetContextImpl( rSwChild.GetSwFrame(), !m_isDisposing ) );
646 if( xChildImpl.is() )
648 xChildImpl->SetParent( this );
649 xChild = xChildImpl.get();
652 else if ( rSwChild.GetDrawObject() )
654 ::rtl::Reference < ::accessibility::AccessibleShape > xChildImpl(
655 GetMap()->GetContextImpl( rSwChild.GetDrawObject(),
656 this, !m_isDisposing) );
657 if( xChildImpl.is() )
658 xChild = xChildImpl.get();
660 else if ( rSwChild.GetWindow() )
662 xChild = rSwChild.GetWindow()->GetAccessible();
664 aRet.push_back(xChild);
666 return comphelper::containerToSequence(aRet);
669 rtl::Reference< SwAccessibleContext> SwAccessibleContext::getAccessibleParentImpl()
671 SolarMutexGuard aGuard;
673 const SwFrame *pUpper = GetParent();
674 OSL_ENSURE( pUpper != nullptr || m_isDisposing, "no upper found" );
676 rtl::Reference< SwAccessibleContext > xAcc;
677 if( pUpper )
678 xAcc = GetMap()->GetContextImpl( pUpper, !m_isDisposing );
680 OSL_ENSURE( xAcc.is() || m_isDisposing, "no parent found" );
682 // Remember the parent as weak ref.
684 std::scoped_lock aWeakParentGuard( m_Mutex );
685 m_xWeakParent = xAcc.get();
688 return xAcc;
691 uno::Reference< XAccessible> SAL_CALL SwAccessibleContext::getAccessibleParent()
693 SolarMutexGuard aGuard;
695 ThrowIfDisposed();
697 return getAccessibleParentImpl();
700 sal_Int64 SAL_CALL SwAccessibleContext::getAccessibleIndexInParent()
702 SolarMutexGuard aGuard;
704 ThrowIfDisposed();
706 const SwFrame *pUpper = GetParent();
707 OSL_ENSURE( pUpper != nullptr || m_isDisposing, "no upper found" );
709 sal_Int64 nIndex = -1;
710 if( pUpper )
712 ::rtl::Reference < SwAccessibleContext > xAccImpl(
713 GetMap()->GetContextImpl(pUpper, !m_isDisposing) );
714 OSL_ENSURE( xAccImpl.is() || m_isDisposing, "no parent found" );
715 if( xAccImpl.is() )
716 nIndex = xAccImpl->GetChildIndex( *(GetMap()), SwAccessibleChild(GetFrame()) );
719 return nIndex;
722 sal_Int16 SAL_CALL SwAccessibleContext::getAccessibleRole()
724 return m_nRole;
727 OUString SAL_CALL SwAccessibleContext::getAccessibleName()
729 return m_sName;
732 uno::Reference< XAccessibleRelationSet> SAL_CALL
733 SwAccessibleContext::getAccessibleRelationSet()
735 // by default there are no relations
736 uno::Reference< XAccessibleRelationSet> xRet( new utl::AccessibleRelationSetHelper() );
737 return xRet;
740 sal_Int64 SAL_CALL SwAccessibleContext::getAccessibleStateSet()
742 SolarMutexGuard aGuard;
744 ThrowIfDisposed();
746 sal_Int64 nStateSet = 0;
748 if (m_isSelectedInDoc)
749 nStateSet |= AccessibleStateType::SELECTED;
751 GetStates( nStateSet );
753 return nStateSet;
756 lang::Locale SAL_CALL SwAccessibleContext::getLocale()
758 SolarMutexGuard aGuard;
760 lang::Locale aLoc( Application::GetSettings().GetLanguageTag().getLocale() );
761 return aLoc;
764 void SAL_CALL SwAccessibleContext::addAccessibleEventListener(
765 const uno::Reference< XAccessibleEventListener >& xListener )
767 if (xListener.is())
769 SolarMutexGuard aGuard;
770 if (!m_nClientId)
771 m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
772 comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, xListener );
776 void SAL_CALL SwAccessibleContext::removeAccessibleEventListener(
777 const uno::Reference< XAccessibleEventListener >& xListener )
779 if (!(xListener.is() && m_nClientId))
780 return;
782 SolarMutexGuard aGuard;
783 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, xListener );
784 if ( !nListenerCount )
786 // no listeners anymore
787 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
788 // and at least to us not firing any events anymore, in case somebody calls
789 // NotifyAccessibleEvent, again
790 comphelper::AccessibleEventNotifier::revokeClient( m_nClientId );
791 m_nClientId = 0;
795 static bool lcl_PointInRectangle(const awt::Point & aPoint,
796 const awt::Rectangle & aRect)
798 tools::Long nDiffX = aPoint.X - aRect.X;
799 tools::Long nDiffY = aPoint.Y - aRect.Y;
801 return
802 nDiffX >= 0 && nDiffX < aRect.Width && nDiffY >= 0 &&
803 nDiffY < aRect.Height;
807 sal_Bool SAL_CALL SwAccessibleContext::containsPoint(
808 const awt::Point& aPoint )
810 awt::Rectangle aPixBounds = getBoundsImpl(true);
811 aPixBounds.X = 0;
812 aPixBounds.Y = 0;
814 return lcl_PointInRectangle(aPoint, aPixBounds);
817 uno::Reference< XAccessible > SAL_CALL SwAccessibleContext::getAccessibleAtPoint(
818 const awt::Point& aPoint )
820 SolarMutexGuard aGuard;
822 ThrowIfDisposed();
824 uno::Reference< XAccessible > xAcc;
826 vcl::Window *pWin = GetWindow();
827 if (!pWin)
829 throw uno::RuntimeException(u"no Window"_ustr, getXWeak());
832 Point aPixPoint( aPoint.X, aPoint.Y ); // px rel to parent
833 if( !GetFrame()->IsRootFrame() )
835 SwRect aLogBounds( GetBounds( *(GetMap()), GetFrame() ) ); // twip rel to doc root
836 Point aPixPos( GetMap()->CoreToPixel( aLogBounds ).TopLeft() );
837 aPixPoint.setX(aPixPoint.getX() + aPixPos.getX());
838 aPixPoint.setY(aPixPoint.getY() + aPixPos.getY());
841 const SwAccessibleChild aChild( GetChildAtPixel( aPixPoint, *(GetMap()) ) );
842 if( aChild.GetSwFrame() )
844 xAcc = GetMap()->GetContext( aChild.GetSwFrame() );
846 else if( aChild.GetDrawObject() )
848 xAcc = GetMap()->GetContext( aChild.GetDrawObject(), this );
850 else if ( aChild.GetWindow() )
852 xAcc = aChild.GetWindow()->GetAccessible();
855 return xAcc;
859 Get bounding box.
861 There are two modes.
863 - relative
865 Return bounding box relative to parent if parent is no root
866 frame. Otherwise return the absolute bounding box.
868 - absolute
870 Return the absolute bounding box.
872 @param bRelative
873 true: Use relative mode.
874 false: Use absolute mode.
876 awt::Rectangle SwAccessibleContext::getBoundsImpl(bool bRelative)
878 SolarMutexGuard aGuard;
880 ThrowIfDisposed();
882 const SwFrame *pParent = GetParent();
883 OSL_ENSURE( pParent, "no Parent found" );
884 vcl::Window *pWin = GetWindow();
886 if (!pParent)
888 throw uno::RuntimeException(u"no Parent"_ustr, getXWeak());
890 if (!pWin)
892 throw uno::RuntimeException(u"no Window"_ustr, getXWeak());
895 SwRect aLogBounds( GetBounds( *(GetMap()), GetFrame() ) ); // twip relative to document root
896 tools::Rectangle aPixBounds( 0, 0, 0, 0 );
897 if( GetFrame()->IsPageFrame() &&
898 static_cast < const SwPageFrame * >( GetFrame() )->IsEmptyPage() )
900 OSL_ENSURE( GetShell()->IsPreview(), "empty page accessible?" );
901 if( GetShell()->IsPreview() )
903 // adjust method call <GetMap()->GetPreviewPageSize()>
904 sal_uInt16 nPageNum =
905 static_cast < const SwPageFrame * >( GetFrame() )->GetPhyPageNum();
906 aLogBounds.SSize( GetMap()->GetPreviewPageSize( nPageNum ) );
909 if( !aLogBounds.IsEmpty() )
911 aPixBounds = GetMap()->CoreToPixel( aLogBounds );
912 if( !pParent->IsRootFrame() && bRelative)
914 SwRect aParentLogBounds( GetBounds( *(GetMap()), pParent ) ); // twip rel to doc root
915 Point aParentPixPos( GetMap()->CoreToPixel( aParentLogBounds ).TopLeft() );
916 aPixBounds.Move( -aParentPixPos.getX(), -aParentPixPos.getY() );
920 awt::Rectangle aBox( aPixBounds.Left(), aPixBounds.Top(),
921 aPixBounds.GetWidth(), aPixBounds.GetHeight() );
923 return aBox;
926 awt::Rectangle SAL_CALL SwAccessibleContext::getBounds()
928 return getBoundsImpl(true);
931 awt::Point SAL_CALL SwAccessibleContext::getLocation()
933 awt::Rectangle aRect = getBoundsImpl(true);
934 awt::Point aPoint(aRect.X, aRect.Y);
936 return aPoint;
939 awt::Point SAL_CALL SwAccessibleContext::getLocationOnScreen()
941 awt::Rectangle aRect = getBoundsImpl(false);
943 Point aPixPos(aRect.X, aRect.Y);
945 vcl::Window *pWin = GetWindow();
946 if (!pWin)
948 throw uno::RuntimeException(u"no Window"_ustr, getXWeak());
951 AbsoluteScreenPixelPoint aPixPosAbs = pWin->OutputToAbsoluteScreenPixel(aPixPos);
952 awt::Point aPoint(aPixPosAbs.getX(), aPixPosAbs.getY());
954 return aPoint;
957 awt::Size SAL_CALL SwAccessibleContext::getSize()
959 awt::Rectangle aRect = getBoundsImpl(false);
960 awt::Size aSize( aRect.Width, aRect.Height );
962 return aSize;
965 void SAL_CALL SwAccessibleContext::grabFocus()
967 SolarMutexGuard aGuard;
969 ThrowIfDisposed();
971 if( GetFrame()->IsFlyFrame() )
973 const SdrObject *pObj =
974 static_cast < const SwFlyFrame * >( GetFrame() )->GetVirtDrawObj();
975 if( pObj )
976 Select( const_cast < SdrObject * >( pObj ), false );
978 else
980 const SwContentFrame *pCFrame = nullptr;
981 if( GetFrame()->IsContentFrame() )
982 pCFrame = static_cast< const SwContentFrame * >( GetFrame() );
983 else if( GetFrame()->IsLayoutFrame() )
984 pCFrame = static_cast< const SwLayoutFrame * >( GetFrame() )->ContainsContent();
986 if( pCFrame && pCFrame->IsTextFrame() )
988 const SwTextFrame *pTextFrame = static_cast< const SwTextFrame * >( pCFrame );
989 const SwTextNode *pTextNd = pTextFrame->GetTextNodeFirst();
990 assert(pTextNd); // can it actually be null? probably not=>simplify
991 if( pTextNd )
993 // create pam for selection
994 SwPosition const aStartPos(pTextFrame->MapViewToModelPos(pTextFrame->GetOffset()));
995 SwPaM aPaM( aStartPos );
997 // set PaM at cursor shell
998 Select( aPaM );
1004 sal_Int32 SAL_CALL SwAccessibleContext::getForeground()
1006 return sal_Int32(COL_BLACK);
1009 sal_Int32 SAL_CALL SwAccessibleContext::getBackground()
1011 return sal_Int32(COL_WHITE);
1014 sal_Bool SAL_CALL SwAccessibleContext::supportsService (const OUString& ServiceName)
1016 return cppu::supportsService(this, ServiceName);
1019 void SwAccessibleContext::DisposeShape( const SdrObject *pObj,
1020 ::accessibility::AccessibleShape *pAccImpl )
1022 ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl( pAccImpl );
1023 if( !xAccImpl.is() )
1024 xAccImpl = GetMap()->GetContextImpl( pObj, this );
1026 AccessibleEventObject aEvent;
1027 aEvent.EventId = AccessibleEventId::CHILD;
1028 uno::Reference< XAccessible > xAcc( xAccImpl );
1029 aEvent.OldValue <<= xAcc;
1030 aEvent.IndexHint = -1;
1031 FireAccessibleEvent( aEvent );
1033 GetMap()->RemoveContext( pObj );
1034 xAccImpl->dispose();
1037 void SwAccessibleContext::ScrolledInShape( ::accessibility::AccessibleShape *pAccImpl )
1039 if(nullptr == pAccImpl)
1041 return ;
1043 AccessibleEventObject aEvent;
1044 aEvent.EventId = AccessibleEventId::CHILD;
1045 uno::Reference< XAccessible > xAcc( pAccImpl );
1046 aEvent.NewValue <<= xAcc;
1047 aEvent.IndexHint = -1;
1048 FireAccessibleEvent( aEvent );
1050 if( !pAccImpl->GetState( AccessibleStateType::FOCUSED ) )
1051 return;
1053 vcl::Window *pWin = GetWindow();
1054 if( pWin && pWin->HasFocus() )
1056 AccessibleEventObject aStateChangedEvent;
1057 aStateChangedEvent.EventId = AccessibleEventId::STATE_CHANGED;
1058 aStateChangedEvent.NewValue <<= AccessibleStateType::FOCUSED;
1059 aStateChangedEvent.Source = xAcc;
1061 FireAccessibleEvent( aStateChangedEvent );
1065 void SwAccessibleContext::Dispose(bool bRecursive, bool bCanSkipInvisible)
1067 SolarMutexGuard aGuard;
1069 OSL_ENSURE( GetFrame() && GetMap(), "already disposed" );
1070 OSL_ENSURE( GetMap()->GetVisArea() == GetVisArea(),
1071 "invalid visible area for dispose" );
1073 m_isDisposing = true;
1075 // dispose children
1076 if( bRecursive )
1077 DisposeChildren(GetFrame(), bRecursive, bCanSkipInvisible);
1079 // get parent
1080 uno::Reference< XAccessible > xParent( GetWeakParent() );
1081 uno::Reference < XAccessibleContext > xThis( this );
1083 // send child event at parent
1084 if( xParent.is() )
1086 SwAccessibleContext *pAcc = static_cast<SwAccessibleContext *>(xParent.get());
1088 AccessibleEventObject aEvent;
1089 aEvent.EventId = AccessibleEventId::CHILD;
1090 aEvent.OldValue <<= xThis;
1091 aEvent.IndexHint = -1;
1092 pAcc->FireAccessibleEvent( aEvent );
1095 // set defunc state (it's not required to broadcast a state changed
1096 // event if the object is disposed afterwards)
1098 std::scoped_lock aDefuncStateGuard( m_Mutex );
1099 m_isDefuncState = true;
1102 // broadcast dispose event
1103 if (m_nClientId)
1105 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( m_nClientId, *this );
1106 m_nClientId = 0;
1109 RemoveFrameFromAccessibleMap();
1110 ClearFrame();
1111 m_pMap = nullptr;
1112 m_wMap.reset();
1114 m_isDisposing = false;
1117 void SwAccessibleContext::DisposeChild( const SwAccessibleChild& rChildFrameOrObj,
1118 bool bRecursive, bool bCanSkipInvisible )
1120 SolarMutexGuard aGuard;
1122 if ( !bCanSkipInvisible ||
1123 rChildFrameOrObj.AlwaysIncludeAsChild() ||
1124 IsShowing( *(GetMap()), rChildFrameOrObj ) ||
1125 !SwAccessibleChild( GetFrame() ).IsVisibleChildrenOnly() )
1127 // If the object could have existed before, then there is nothing to do,
1128 // because no wrapper exists now and therefore no one is interested to
1129 // get notified of the movement.
1130 if( rChildFrameOrObj.GetSwFrame() )
1132 ::rtl::Reference< SwAccessibleContext > xAccImpl =
1133 GetMap()->GetContextImpl( rChildFrameOrObj.GetSwFrame(), false );
1134 if (xAccImpl)
1135 xAccImpl->Dispose( bRecursive );
1137 else if ( rChildFrameOrObj.GetDrawObject() )
1139 ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
1140 GetMap()->GetContextImpl( rChildFrameOrObj.GetDrawObject(),
1141 this, false );
1142 if (xAccImpl)
1143 DisposeShape( rChildFrameOrObj.GetDrawObject(),
1144 xAccImpl.get() );
1146 else if ( rChildFrameOrObj.GetWindow() )
1148 AccessibleEventObject aEvent;
1149 aEvent.EventId = AccessibleEventId::CHILD;
1150 uno::Reference< XAccessible > xAcc =
1151 rChildFrameOrObj.GetWindow()->GetAccessible();
1152 aEvent.OldValue <<= xAcc;
1153 aEvent.IndexHint = -1;
1154 FireAccessibleEvent( aEvent );
1157 else if( bRecursive && rChildFrameOrObj.GetSwFrame() )
1158 DisposeChildren(rChildFrameOrObj.GetSwFrame(), bRecursive, bCanSkipInvisible);
1161 void SwAccessibleContext::InvalidatePosOrSize( const SwRect& )
1163 SolarMutexGuard aGuard;
1165 OSL_ENSURE( GetFrame() && !GetFrame()->getFrameArea().IsEmpty(), "context should have a size" );
1167 bool bIsOldShowingState;
1168 bool bIsNewShowingState = IsShowing( *(GetMap()) );
1170 std::scoped_lock aShowingStateGuard( m_Mutex );
1171 bIsOldShowingState = m_isShowingState;
1172 m_isShowingState = bIsNewShowingState;
1175 if( bIsOldShowingState != bIsNewShowingState )
1177 FireStateChangedEvent( AccessibleStateType::SHOWING,
1178 bIsNewShowingState );
1180 else if( bIsNewShowingState )
1182 // The frame stays visible -> broadcast event
1183 FireVisibleDataEvent();
1186 // note: InvalidatePosOrSize must call InvalidateContent_ so that
1187 // SwAccessibleParagraph updates its portions, or dispose it
1188 // (see accmap.cxx: INVALID_CONTENT is contained in POS_CHANGED)
1189 if( !bIsNewShowingState &&
1190 SwAccessibleChild( GetParent() ).IsVisibleChildrenOnly() )
1192 // this Dispose call was removed by IAccessibility2 implementation
1193 // without giving any reason why - without it we get stale
1194 // entries in SwAccessibleMap::mpFrameMap.
1195 Dispose(true);
1197 else
1199 InvalidateContent_( true );
1203 void SwAccessibleContext::InvalidateChildPosOrSize(
1204 const SwAccessibleChild& rChildFrameOrObj,
1205 const SwRect& rOldFrame )
1207 SolarMutexGuard aGuard;
1209 // this happens during layout, e.g. when a page is deleted and next page's
1210 // header/footer moves backward such an event is generated
1211 SAL_INFO_IF(rChildFrameOrObj.GetSwFrame() &&
1212 rChildFrameOrObj.GetSwFrame()->getFrameArea().IsEmpty(),
1213 "sw.a11y", "child context should have a size");
1215 if ( rChildFrameOrObj.AlwaysIncludeAsChild() )
1217 // nothing to do;
1218 return;
1221 const bool bVisibleChildrenOnly = SwAccessibleChild( GetFrame() ).IsVisibleChildrenOnly();
1222 const bool bNew = rOldFrame.IsEmpty() ||
1223 ( rOldFrame.Left() == 0 && rOldFrame.Top() == 0 );
1224 if( IsShowing( *(GetMap()), rChildFrameOrObj ) )
1226 // If the object could have existed before, then there is nothing to do,
1227 // because no wrapper exists now and therefore no one is interested to
1228 // get notified of the movement.
1229 if( bNew || (bVisibleChildrenOnly && !IsShowing( rOldFrame )) )
1231 if( rChildFrameOrObj.GetSwFrame() )
1233 // The frame becomes visible. A child event must be send.
1234 ::rtl::Reference< SwAccessibleContext > xAccImpl =
1235 GetMap()->GetContextImpl( rChildFrameOrObj.GetSwFrame() );
1236 xAccImpl->ScrolledIn();
1238 else if ( rChildFrameOrObj.GetDrawObject() )
1240 ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
1241 GetMap()->GetContextImpl( rChildFrameOrObj.GetDrawObject(),
1242 this );
1243 // #i37790#
1244 if ( xAccImpl.is() )
1246 ScrolledInShape( xAccImpl.get() );
1248 else
1250 OSL_FAIL( "<SwAccessibleContext::InvalidateChildPosOrSize(..)> - no accessible shape found." );
1253 else if ( rChildFrameOrObj.GetWindow() )
1255 AccessibleEventObject aEvent;
1256 aEvent.EventId = AccessibleEventId::CHILD;
1257 aEvent.NewValue <<= rChildFrameOrObj.GetWindow()->GetAccessible();
1258 FireAccessibleEvent( aEvent );
1262 else
1264 // If the frame was visible before, then a child event for the parent
1265 // needs to be send. However, there is no wrapper existing, and so
1266 // no notifications for grandchildren are required. If the are
1267 // grandgrandchildren, they would be notified by the layout.
1268 if( bVisibleChildrenOnly &&
1269 !bNew && IsShowing( rOldFrame ) )
1271 if( rChildFrameOrObj.GetSwFrame() )
1273 ::rtl::Reference< SwAccessibleContext > xAccImpl =
1274 GetMap()->GetContextImpl( rChildFrameOrObj.GetSwFrame() );
1275 xAccImpl->SetParent( this );
1276 xAccImpl->Dispose( true );
1278 else if ( rChildFrameOrObj.GetDrawObject() )
1280 ::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
1281 GetMap()->GetContextImpl( rChildFrameOrObj.GetDrawObject(),
1282 this );
1283 DisposeShape( rChildFrameOrObj.GetDrawObject(),
1284 xAccImpl.get() );
1286 else if ( rChildFrameOrObj.GetWindow() )
1288 OSL_FAIL( "<SwAccessibleContext::InvalidateChildPosOrSize(..)> - not expected to handle dispose of child of type <vcl::Window>." );
1294 void SwAccessibleContext::InvalidateContent()
1296 SolarMutexGuard aGuard;
1298 InvalidateContent_( false );
1301 void SwAccessibleContext::InvalidateCursorPos()
1303 SolarMutexGuard aGuard;
1305 InvalidateCursorPos_();
1308 void SwAccessibleContext::InvalidateFocus()
1310 SolarMutexGuard aGuard;
1312 InvalidateFocus_();
1315 // #i27301# - use new type definition for <_nStates>
1316 void SwAccessibleContext::InvalidateStates( AccessibleStates _nStates )
1318 if( !GetMap() )
1319 return;
1321 SwViewShell *pVSh = GetMap()->GetShell();
1322 if( pVSh )
1324 if( _nStates & AccessibleStates::EDITABLE )
1326 bool bIsOldEditableState;
1327 bool bIsNewEditableState = IsEditable( pVSh );
1329 std::scoped_lock aGuard( m_Mutex );
1330 bIsOldEditableState = m_isEditableState;
1331 m_isEditableState = bIsNewEditableState;
1334 if( bIsOldEditableState != bIsNewEditableState )
1335 FireStateChangedEvent( AccessibleStateType::EDITABLE,
1336 bIsNewEditableState );
1338 if( _nStates & AccessibleStates::OPAQUE )
1340 bool bIsOldOpaqueState;
1341 bool bIsNewOpaqueState = IsOpaque( pVSh );
1343 std::scoped_lock aGuard( m_Mutex );
1344 bIsOldOpaqueState = m_isOpaqueState;
1345 m_isOpaqueState = bIsNewOpaqueState;
1348 if( bIsOldOpaqueState != bIsNewOpaqueState )
1349 FireStateChangedEvent( AccessibleStateType::OPAQUE,
1350 bIsNewOpaqueState );
1354 InvalidateChildrenStates( GetFrame(), _nStates );
1357 void SwAccessibleContext::InvalidateRelation( sal_uInt16 nType )
1359 AccessibleEventObject aEvent;
1360 aEvent.EventId = nType;
1362 FireAccessibleEvent( aEvent );
1365 /** #i27301# - text selection has changed */
1366 void SwAccessibleContext::InvalidateTextSelection()
1368 AccessibleEventObject aEvent;
1369 aEvent.EventId = AccessibleEventId::TEXT_SELECTION_CHANGED;
1371 FireAccessibleEvent( aEvent );
1374 /** #i88069# - attributes has changed */
1375 void SwAccessibleContext::InvalidateAttr()
1377 AccessibleEventObject aEvent;
1378 aEvent.EventId = AccessibleEventId::TEXT_ATTRIBUTE_CHANGED;
1380 FireAccessibleEvent( aEvent );
1383 bool SwAccessibleContext::HasCursor()
1385 return false;
1388 bool SwAccessibleContext::Select( SwPaM *pPaM, SdrObject *pObj,
1389 bool bAdd )
1391 SwCursorShell* pCursorShell = GetCursorShell();
1392 if( !pCursorShell )
1393 return false;
1395 SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCursorShell);
1396 // Get rid of activated OLE object
1397 if( pFEShell )
1398 pFEShell->FinishOLEObj();
1400 SwWrtShell* pWrtShell = dynamic_cast<SwWrtShell*>(pCursorShell);
1402 bool bRet = false;
1403 if( pObj )
1405 if( pFEShell )
1407 sal_uInt8 nFlags = bAdd ? SW_ADD_SELECT : 0;
1408 pFEShell->SelectObj( Point(), nFlags, pObj );
1409 bRet = true;
1412 else if( pPaM )
1414 // Get rid of frame selection. If there is one, make text cursor
1415 // visible again.
1416 bool bCallShowCursor = false;
1417 if( pFEShell && (pFEShell->IsFrameSelected() ||
1418 pFEShell->IsObjSelected()) )
1420 Point aPt( LONG_MIN, LONG_MIN );
1421 pFEShell->SelectObj( aPt );
1422 bCallShowCursor = true;
1424 pCursorShell->KillPams();
1425 if( pWrtShell && pPaM->HasMark() )
1426 // We have to do this or SwWrtShell can't figure out that it needs
1427 // to kill the selection later, when the user moves the cursor.
1428 pWrtShell->SttSelect();
1429 pCursorShell->SetSelection( *pPaM );
1430 if( pPaM->HasMark() && *pPaM->GetPoint() == *pPaM->GetMark())
1431 // Setting a "Selection" that starts and ends at the same spot
1432 // should remove the selection rather than create an empty one, so
1433 // that we get defined behavior if accessibility sets the cursor
1434 // later.
1435 pCursorShell->ClearMark();
1436 if( bCallShowCursor )
1437 pCursorShell->ShowCursor();
1438 bRet = true;
1441 return bRet;
1444 OUString SwAccessibleContext::GetResource(TranslateId pResId,
1445 const OUString *pArg1,
1446 const OUString *pArg2)
1448 OUString sStr = SwResId(pResId);
1450 if( pArg1 )
1452 sStr = sStr.replaceFirst( "$(ARG1)", *pArg1 );
1454 if( pArg2 )
1456 sStr = sStr.replaceFirst( "$(ARG2)", *pArg2 );
1459 return sStr;
1462 void SwAccessibleContext::RemoveFrameFromAccessibleMap()
1464 assert(m_refCount > 0); // must be alive to do this without using m_wMap
1465 if (m_isRegisteredAtAccessibleMap && GetFrame() && GetMap())
1466 GetMap()->RemoveContext( GetFrame() );
1469 bool SwAccessibleContext::HasAdditionalAccessibleChildren()
1471 bool bRet( false );
1473 if ( GetFrame()->IsTextFrame() )
1475 SwPostItMgr* pPostItMgr = GetMap()->GetShell()->GetPostItMgr();
1476 if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
1478 bRet = pPostItMgr->HasFrameConnectedSidebarWins( *(GetFrame()) );
1482 return bRet;
1485 /** #i88070# - get additional accessible child by index */
1486 vcl::Window* SwAccessibleContext::GetAdditionalAccessibleChild( const sal_Int32 nIndex )
1488 vcl::Window* pAdditionalAccessibleChild( nullptr );
1490 if ( GetFrame()->IsTextFrame() )
1492 SwPostItMgr* pPostItMgr = GetMap()->GetShell()->GetPostItMgr();
1493 if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
1495 pAdditionalAccessibleChild =
1496 pPostItMgr->GetSidebarWinForFrameByIndex( *(GetFrame()), nIndex );
1500 return pAdditionalAccessibleChild;
1503 /** #i88070# - get all additional accessible children */
1504 void SwAccessibleContext::GetAdditionalAccessibleChildren( std::vector< vcl::Window* >* pChildren )
1506 if ( GetFrame()->IsTextFrame() )
1508 SwPostItMgr* pPostItMgr = GetMap()->GetShell()->GetPostItMgr();
1509 if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
1511 pPostItMgr->GetAllSidebarWinForFrame( *(GetFrame()), pChildren );
1516 bool SwAccessibleContext::SetSelectedState(bool const bSelected)
1518 if (m_isSelectedInDoc != bSelected)
1520 m_isSelectedInDoc = bSelected;
1521 FireStateChangedEvent( AccessibleStateType::SELECTED, bSelected );
1522 return true;
1524 return false;
1527 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */