/* -*- 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 . */ #include "accfrmobj.hxx" #include #include "acccontext.hxx" #include #include #include #include #include #include #include #include #include #include #include namespace sw::access { SwAccessibleChild::SwAccessibleChild() : mpFrame( nullptr ) , mpDrawObj( nullptr ) , mpWindow( nullptr ) {} SwAccessibleChild::SwAccessibleChild( const SdrObject* pDrawObj ) : mpFrame( nullptr ) , mpDrawObj( nullptr ) , mpWindow( nullptr ) { Init( pDrawObj ); } SwAccessibleChild::SwAccessibleChild( const SwFrame* pFrame ) : mpFrame( nullptr ) , mpDrawObj( nullptr ) , mpWindow( nullptr ) { Init( pFrame ); } SwAccessibleChild::SwAccessibleChild( vcl::Window* pWindow ) : mpFrame( nullptr ) , mpDrawObj( nullptr ) , mpWindow( nullptr ) { Init( pWindow ); } SwAccessibleChild::SwAccessibleChild( const SwFrame* pFrame, const SdrObject* pDrawObj, vcl::Window* pWindow ) : mpFrame( nullptr ) , mpDrawObj( nullptr ) , mpWindow( nullptr ) { if ( pFrame ) { Init( pFrame ); } else if ( pDrawObj ) { Init( pDrawObj ); } else if ( pWindow ) { Init( pWindow ); } OSL_ENSURE( (!pFrame || pFrame == mpFrame) && (!pDrawObj || pDrawObj == mpDrawObj) && (!pWindow || pWindow == mpWindow), "invalid frame/object/window combination" ); } SwAccessibleChild::~SwAccessibleChild() = default; void SwAccessibleChild::Init( const SdrObject* pDrawObj ) { mpDrawObj = pDrawObj; const SwVirtFlyDrawObj* pFlyDrawObj = dynamic_cast(mpDrawObj); mpFrame = pFlyDrawObj ? pFlyDrawObj->GetFlyFrame() : nullptr; mpWindow = nullptr; } void SwAccessibleChild::Init( const SwFrame* pFrame ) { mpFrame = pFrame; mpDrawObj = mpFrame && mpFrame->IsFlyFrame() ? static_cast < const SwFlyFrame * >( mpFrame )->GetVirtDrawObj() : nullptr; mpWindow = nullptr; } void SwAccessibleChild::Init( vcl::Window* pWindow ) { mpWindow = pWindow; mpFrame = nullptr; mpDrawObj = nullptr; } bool SwAccessibleChild::IsAccessible( bool bPagePreview ) const { bool bRet( false ); if ( mpFrame ) { bRet = mpFrame->IsAccessibleFrame() && ( !mpFrame->IsCellFrame() || static_cast( mpFrame )->GetTabBox()->GetSttNd() != nullptr ) && !mpFrame->IsInCoveredCell() && ( bPagePreview || !mpFrame->IsPageFrame() ); } else if ( mpDrawObj ) { bRet = true; } else if ( mpWindow ) { bRet = true; } return bRet; } bool SwAccessibleChild::IsBoundAsChar() const { bool bRet( false ); if ( mpFrame ) { bRet = mpFrame->IsFlyFrame() && static_cast< const SwFlyFrame *>(mpFrame)->IsFlyInContentFrame(); } else if ( mpDrawObj ) { const SwFrameFormat* pFrameFormat = ::FindFrameFormat( mpDrawObj ); bRet = pFrameFormat && (RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId()); } else if ( mpWindow ) { bRet = false; } return bRet; } SwAccessibleChild& SwAccessibleChild::operator=( const SdrObject* pDrawObj ) { Init( pDrawObj ); return *this; } SwAccessibleChild& SwAccessibleChild::operator=( const SwFrame* pFrame ) { Init( pFrame ); return *this; } SwAccessibleChild& SwAccessibleChild::operator=( vcl::Window* pWindow ) { Init( pWindow ); return *this; } bool SwAccessibleChild::IsValid() const { return mpFrame != nullptr || mpDrawObj != nullptr || mpWindow != nullptr; } bool SwAccessibleChild::IsVisibleChildrenOnly() const { bool bRet( false ); if ( !mpFrame ) { bRet = true; } else { bRet = mpFrame->IsRootFrame() || !( mpFrame->IsTabFrame() || mpFrame->IsInTab() || ( IsBoundAsChar() && static_cast(mpFrame)->GetAnchorFrame()->IsInTab() ) ); } return bRet; } SwRect SwAccessibleChild::GetBox( const SwAccessibleMap& rAccMap ) const { SwRect aBox; if ( mpFrame ) { if ( mpFrame->IsPageFrame() && static_cast< const SwPageFrame * >( mpFrame )->IsEmptyPage() ) { aBox = SwRect( mpFrame->getFrameArea().Left(), mpFrame->getFrameArea().Top()-1, 1, 1 ); } else if ( mpFrame->IsTabFrame() ) { aBox = mpFrame->getFrameArea(); aBox.Intersection( mpFrame->GetUpper()->getFrameArea() ); } else { aBox = mpFrame->getFrameArea(); } } else if( mpDrawObj ) { const SwContact* const pContact = ::GetUserCall(mpDrawObj); // assume that a) the SwVirt* objects that don't have this are handled // by the mpFrame case above b) for genuine SdrObject this must be set // if it's connected to layout assert(dynamic_cast(pContact)); SwPageFrame const*const pPage(const_cast( pContact->GetAnchoredObj(mpDrawObj))->FindPageFrameOfAnchor()); if (pPage) // may end up here with partial layout -> not visible { aBox = SwRect( mpDrawObj->GetCurrentBoundRect() ); // tdf#91260 drawing object may be partially off-page aBox.Intersection(pPage->getFrameArea()); } } else if ( mpWindow ) { vcl::Window *pWin = rAccMap.GetShell()->GetWin(); if (pWin) { aBox = SwRect( pWin->PixelToLogic( tools::Rectangle( mpWindow->GetPosPixel(), mpWindow->GetSizePixel() ) ) ); } } return aBox; } SwRect SwAccessibleChild::GetBounds( const SwAccessibleMap& rAccMap ) const { SwRect aBound; if( mpFrame ) { if( mpFrame->IsPageFrame() && static_cast< const SwPageFrame * >( mpFrame )->IsEmptyPage() ) { aBound = SwRect( mpFrame->getFrameArea().Left(), mpFrame->getFrameArea().Top()-1, 0, 0 ); } else aBound = mpFrame->GetPaintArea(); } else if( mpDrawObj ) { aBound = GetBox( rAccMap ); } else if ( mpWindow ) { aBound = GetBox( rAccMap ); } return aBound; } bool SwAccessibleChild::AlwaysIncludeAsChild() const { bool bAlwaysIncludedAsChild( false ); if ( mpWindow ) { bAlwaysIncludedAsChild = true; } return bAlwaysIncludedAsChild; } const SwFrame* SwAccessibleChild::GetParent( const bool bInPagePreview ) const { const SwFrame* pParent( nullptr ); if ( mpFrame ) { if( mpFrame->IsFlyFrame() ) { const SwFlyFrame* pFly = static_cast< const SwFlyFrame *>( mpFrame ); if( pFly->IsFlyInContentFrame() ) { // For RndStdIds::FLY_AS_CHAR the parent is the anchor pParent = pFly->GetAnchorFrame(); OSL_ENSURE( SwAccessibleChild( pParent ).IsAccessible( bInPagePreview ), "parent is not accessible" ); } else { // In any other case the parent is the root frm // (in page preview, the page frame) if( bInPagePreview ) pParent = pFly->FindPageFrame(); else pParent = pFly->getRootFrame(); } } else { SwAccessibleChild aUpper( mpFrame->GetUpper() ); while( aUpper.GetSwFrame() && !aUpper.IsAccessible(bInPagePreview) ) { aUpper = aUpper.GetSwFrame()->GetUpper(); } pParent = aUpper.GetSwFrame(); } } else if( mpDrawObj ) { const SwDrawContact *pContact = static_cast< const SwDrawContact* >( GetUserCall( mpDrawObj ) ); OSL_ENSURE( pContact, "sdr contact is missing" ); if( pContact ) { const SwFrameFormat *pFrameFormat = pContact->GetFormat(); OSL_ENSURE( pFrameFormat, "frame format is missing" ); if( pFrameFormat && RndStdIds::FLY_AS_CHAR == pFrameFormat->GetAnchor().GetAnchorId() ) { // For RndStdIds::FLY_AS_CHAR the parent is the anchor pParent = pContact->GetAnchorFrame(); OSL_ENSURE( SwAccessibleChild( pParent ).IsAccessible( bInPagePreview ), "parent is not accessible" ); } else { // In any other case the parent is the root frm SwFrame const*const pAnchor(pContact->GetAnchorFrame()); if (pAnchor) // null if object removed from layout { if (bInPagePreview) pParent = pAnchor->FindPageFrame(); else pParent = pAnchor->getRootFrame(); } } } } else if ( mpWindow ) { css::uno::Reference < css::accessibility::XAccessible > xAcc = mpWindow->GetAccessible(); if ( xAcc.is() ) { css::uno::Reference < css::accessibility::XAccessibleContext > xAccContext = xAcc->getAccessibleContext(); if ( xAccContext.is() ) { css::uno::Reference < css::accessibility::XAccessible > xAccParent = xAccContext->getAccessibleParent(); if ( xAccParent.is() ) { SwAccessibleContext* pAccParentImpl = dynamic_cast< SwAccessibleContext *>( xAccParent.get() ); if ( pAccParentImpl ) { pParent = pAccParentImpl->GetFrame(); } } } } } return pParent; } } // namespace sw::access /* vim:set shiftwidth=4 softtabstop=4 expandtab: */