/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
void SwAccessibleContext::ScrolledIn()
{ // This accessible should be freshly created, because it // was not visible before. Therefore, its visible area must already // reflect the scrolling.
OSL_ENSURE( GetVisArea() == GetMap()->GetVisArea(), "Visible area of child is wrong. Did it exist already?" );
// Send child event at parent. That's all we have to do here. const SwFrame* pParent = GetParent();
::rtl::Reference< SwAccessibleContext > xParentImpl(
GetMap()->GetContextImpl( pParent, false ) ); if( !xParentImpl.is() ) return;
// First of all, update the children. That's required to dispose // all children that are existing only if they are visible. They // are not disposed by the recursive Dispose call that follows later on, // because this call will only dispose children that are in the // new visible area. The children we want to dispose however are in the // old visible area all.
ChildrenScrolled( GetFrame(), rOldVisArea );
// Broadcast a state changed event for the showing state. // It might be that the child is freshly created just to send // the child event. In this case no listener will exist.
FireStateChangedEvent( AccessibleStateType::SHOWING, false );
// this Dispose call was removed by IAccessibility2 implementation // without giving any reason why - without it we get stale // entries in SwAccessibleMap::mpFrameMap.
Dispose(true);
}
// #i27301# - use new type definition for <_nStates> void SwAccessibleContext::InvalidateChildrenStates( const SwFrame* _pFrame,
AccessibleStates _nStates )
{ const SwAccessibleChildSList aVisList( GetVisArea(), *_pFrame, *(GetMap()) );
void SwAccessibleContext::DisposeChildren(const SwFrame *pFrame, bool bRecursive, bool bCanSkipInvisible)
{ const SwAccessibleChildSList aVisList( GetVisArea(), *pFrame, *(GetMap()) );
SwAccessibleChildSList::const_iterator aIter( aVisList.begin() ); while( aIter != aVisList.end() )
{ const SwAccessibleChild& rLower = *aIter; const SwFrame* pLower = rLower.GetSwFrame(); if( pLower )
{ // tdf#117601 dispose the darn thing if it ever was accessible
::rtl::Reference<SwAccessibleContext> xAccImpl = GetMap()->GetContextImpl(pLower, false); if( xAccImpl.is() )
xAccImpl->Dispose( bRecursive ); else
{ // it's possible that the xAccImpl *does* exist with a // ref-count of 0 and blocked in its dtor in another thread - // this call here could be from SwAccessibleMap dtor so // remove it from any maps now!
GetMap()->RemoveContext(pLower); // in this case the context will check with a weak_ptr // that the map is still alive so it's not necessary // to clear its m_pMap here. if (bRecursive)
{
DisposeChildren(pLower, bRecursive, bCanSkipInvisible);
}
}
} elseif ( rLower.GetDrawObject() )
{
::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl(
GetMap()->GetContextImpl( rLower.GetDrawObject(), this, false ) ); if( xAccImpl.is() )
DisposeShape( rLower.GetDrawObject(), xAccImpl.get() );
} elseif ( rLower.GetWindow() )
{
DisposeChild(rLower, false, bCanSkipInvisible);
}
++aIter;
}
}
// SHOWING if (m_isShowingState)
rStateSet |= AccessibleStateType::SHOWING;
// EDITABLE if (m_isEditableState) //Set editable state to graphic and other object when the document is editable
{
rStateSet |= AccessibleStateType::EDITABLE;
rStateSet |= AccessibleStateType::RESIZABLE;
rStateSet |= AccessibleStateType::MOVEABLE;
} // ENABLED
rStateSet |= AccessibleStateType::ENABLED;
// OPAQUE if (m_isOpaqueState)
rStateSet |= AccessibleStateType::OPAQUE;
SwAccessibleContext::~SwAccessibleContext()
{ // must have for 2 reasons: 2. as long as this thread has SolarMutex // another thread cannot destroy the SwAccessibleMap so our temporary // taking a hard ref to SwAccessibleMap won't delay its destruction
SolarMutexGuard aGuard; // must check with weak_ptr that m_pMap is still alive
std::shared_ptr<SwAccessibleMap> pMap(m_wMap.lock()); if (m_isRegisteredAtAccessibleMap && GetFrame() && pMap)
{
pMap->RemoveContext( GetFrame() );
}
}
uno::Reference< XAccessibleRelationSet> SAL_CALL
SwAccessibleContext::getAccessibleRelationSet()
{ // by default there are no relations
uno::Reference< XAccessibleRelationSet> xRet( new utl::AccessibleRelationSetHelper() ); return xRet;
}
SolarMutexGuard aGuard;
sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, xListener ); if ( !nListenerCount )
{ // no listeners anymore // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), // and at least to us not firing any events anymore, in case somebody calls // NotifyAccessibleEvent, again
comphelper::AccessibleEventNotifier::revokeClient( m_nClientId );
m_nClientId = 0;
}
}
// set defunc state (it's not required to broadcast a state changed // event if the object is disposed afterwards)
{
std::scoped_lock aDefuncStateGuard( m_Mutex );
m_isDefuncState = true;
}
// note: InvalidatePosOrSize must call InvalidateContent_ so that // SwAccessibleParagraph updates its portions, or dispose it // (see accmap.cxx: INVALID_CONTENT is contained in POS_CHANGED) if( !bIsNewShowingState &&
SwAccessibleChild( GetParent() ).IsVisibleChildrenOnly() )
{ // this Dispose call was removed by IAccessibility2 implementation // without giving any reason why - without it we get stale // entries in SwAccessibleMap::mpFrameMap.
Dispose(true);
} else
{
InvalidateContent_( true );
}
}
// this happens during layout, e.g. when a page is deleted and next page's // header/footer moves backward such an event is generated
SAL_INFO_IF(rChildFrameOrObj.GetSwFrame() &&
rChildFrameOrObj.GetSwFrame()->getFrameArea().IsEmpty(), "sw.a11y", "child context should have a size");
if ( rChildFrameOrObj.AlwaysIncludeAsChild() )
{ // nothing to do; return;
}
constbool bVisibleChildrenOnly = SwAccessibleChild( GetFrame() ).IsVisibleChildrenOnly(); constbool bNew = rOldFrame.IsEmpty() ||
( rOldFrame.Left() == 0 && rOldFrame.Top() == 0 ); if( IsShowing( *(GetMap()), rChildFrameOrObj ) )
{ // If the object could have existed before, then there is nothing to do, // because no wrapper exists now and therefore no one is interested to // get notified of the movement. if( bNew || (bVisibleChildrenOnly && !IsShowing( rOldFrame )) )
{ if( rChildFrameOrObj.GetSwFrame() )
{ // The frame becomes visible. A child event must be send.
::rtl::Reference< SwAccessibleContext > xAccImpl =
GetMap()->GetContextImpl( rChildFrameOrObj.GetSwFrame() );
xAccImpl->ScrolledIn();
} elseif ( rChildFrameOrObj.GetDrawObject() )
{
::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
GetMap()->GetContextImpl( rChildFrameOrObj.GetDrawObject(), this ); // #i37790# if ( xAccImpl.is() )
{
ScrolledInShape( xAccImpl.get() );
} else
{
OSL_FAIL( "<SwAccessibleContext::InvalidateChildPosOrSize(..)> - no accessible shape found." );
}
} elseif ( rChildFrameOrObj.GetWindow() )
{
FireAccessibleEvent(AccessibleEventId::CHILD, uno::Any(),
uno::Any(rChildFrameOrObj.GetWindow()->GetAccessible()));
}
}
} else
{ // If the frame was visible before, then a child event for the parent // needs to be send. However, there is no wrapper existing, and so // no notifications for grandchildren are required. If the are // grandgrandchildren, they would be notified by the layout. if( bVisibleChildrenOnly &&
!bNew && IsShowing( rOldFrame ) )
{ if( rChildFrameOrObj.GetSwFrame() )
{
::rtl::Reference< SwAccessibleContext > xAccImpl =
GetMap()->GetContextImpl( rChildFrameOrObj.GetSwFrame() );
xAccImpl->SetParent( this );
xAccImpl->Dispose( true );
} elseif ( rChildFrameOrObj.GetDrawObject() )
{
::rtl::Reference< ::accessibility::AccessibleShape > xAccImpl =
GetMap()->GetContextImpl( rChildFrameOrObj.GetDrawObject(), this );
DisposeShape( rChildFrameOrObj.GetDrawObject(),
xAccImpl.get() );
} elseif ( rChildFrameOrObj.GetWindow() )
{
OSL_FAIL( "<SwAccessibleContext::InvalidateChildPosOrSize(..)> - not expected to handle dispose of child of type <vcl::Window>." );
}
}
}
}
bool bRet = false; if( pObj )
{ if( pFEShell )
{
sal_uInt8 nFlags = bAdd ? SW_ADD_SELECT : 0;
pFEShell->SelectObj( Point(), nFlags, pObj );
bRet = true;
}
} elseif( pPaM )
{ // Get rid of frame selection. If there is one, make text cursor // visible again. bool bCallShowCursor = false; if( pFEShell && (pFEShell->IsFrameSelected() ||
pFEShell->GetSelectedObjCount()) )
{
Point aPt( LONG_MIN, LONG_MIN );
pFEShell->SelectObj( aPt );
bCallShowCursor = true;
}
pCursorShell->KillPams(); if( pWrtShell && pPaM->HasMark() ) // We have to do this or SwWrtShell can't figure out that it needs // to kill the selection later, when the user moves the cursor.
pWrtShell->SttSelect();
pCursorShell->SetSelection( *pPaM ); if( pPaM->HasMark() && *pPaM->GetPoint() == *pPaM->GetMark()) // Setting a "Selection" that starts and ends at the same spot // should remove the selection rather than create an empty one, so // that we get defined behavior if accessibility sets the cursor // later.
pCursorShell->ClearMark(); if( bCallShowCursor )
pCursorShell->ShowCursor();
bRet = true;
}
void SwAccessibleContext::RemoveFrameFromAccessibleMap()
{
assert(m_refCount > 0); // must be alive to do this without using m_wMap if (m_isRegisteredAtAccessibleMap && GetFrame() && GetMap())
GetMap()->RemoveContext( GetFrame() );
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.