diff options
author | Chris Sherlock <chris.sherlock79@gmail.com> | 2014-05-11 15:56:15 +1000 |
---|---|---|
committer | Chris Sherlock <chris.sherlock79@gmail.com> | 2014-05-13 08:13:53 +1000 |
commit | 58b1c41d60ecb2dd8ef4ba3d48ca74e809430430 (patch) | |
tree | 4638dca889c9ec29fd25a272f4c1c491eafe75e1 /vcl/source/window/accessibility.cxx | |
parent | 0fe375a17d42e3214ef23f2ff5b5f88edc4f0338 (diff) |
VCL: Move accessibility functions to accessibility.cxx
Change-Id: Ieb128c2ea121bacd9cd952a9400a85f2b9da5a7e
Diffstat (limited to 'vcl/source/window/accessibility.cxx')
-rw-r--r-- | vcl/source/window/accessibility.cxx | 728 |
1 files changed, 728 insertions, 0 deletions
diff --git a/vcl/source/window/accessibility.cxx b/vcl/source/window/accessibility.cxx new file mode 100644 index 000000000000..2b4749e56002 --- /dev/null +++ b/vcl/source/window/accessibility.cxx @@ -0,0 +1,728 @@ +/* -*- 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 <config_features.h> + +#include <i18nlangtag/mslangid.hxx> + +#include "tools/time.hxx" +#include "tools/debug.hxx" +#include "tools/rc.h" + +#include "unotools/fontcfg.hxx" +#include "unotools/confignode.hxx" + +#include "vcl/layout.hxx" +#include "vcl/salgtype.hxx" +#include "vcl/event.hxx" +#include "vcl/fixed.hxx" +#include "vcl/help.hxx" +#include "vcl/cursor.hxx" +#include "vcl/svapp.hxx" +#include "vcl/window.hxx" +#include "vcl/syswin.hxx" +#include "vcl/syschild.hxx" +#include "vcl/dockwin.hxx" +#include "vcl/menu.hxx" +#include "vcl/wrkwin.hxx" +#include "vcl/wall.hxx" +#include "vcl/gradient.hxx" +#include "vcl/button.hxx" +#include "vcl/taskpanelist.hxx" +#include "vcl/dialog.hxx" +#include "vcl/unowrap.hxx" +#include "vcl/gdimtf.hxx" +#include "vcl/pdfextoutdevdata.hxx" +#include "vcl/popupmenuwindow.hxx" +#include "vcl/lazydelete.hxx" +#include "vcl/virdev.hxx" +#include "vcl/settings.hxx" + +// declare system types in sysdata.hxx +#include "svsys.h" +#include "vcl/sysdata.hxx" + +#include "salframe.hxx" +#include "salobj.hxx" +#include "salinst.hxx" +#include "salgdi.hxx" +#include "svdata.hxx" +#include "dbggui.hxx" +#include "outfont.hxx" +#include "window.h" +#include "toolbox.h" +#include "outdev.h" +#include "PhysicalFontCollection.hxx" +#include "brdwin.hxx" +#include "helpwin.hxx" +#include "sallayout.hxx" +#include "dndlcon.hxx" +#include "dndevdis.hxx" + +#include "com/sun/star/accessibility/XAccessible.hpp" +#include "com/sun/star/accessibility/AccessibleRole.hpp" +#include "com/sun/star/awt/XWindowPeer.hpp" +#include "com/sun/star/awt/XTopWindow.hpp" +#include "com/sun/star/awt/XWindow.hpp" +#include "com/sun/star/awt/XDisplayConnection.hpp" +#include "com/sun/star/datatransfer/dnd/XDragSource.hpp" +#include "com/sun/star/datatransfer/dnd/XDropTarget.hpp" +#include "com/sun/star/datatransfer/clipboard/XClipboard.hpp" +#include "com/sun/star/datatransfer/clipboard/SystemClipboard.hpp" +#include "com/sun/star/lang/XInitialization.hpp" +#include "com/sun/star/lang/XComponent.hpp" +#include "com/sun/star/lang/XServiceName.hpp" +#include "com/sun/star/rendering/CanvasFactory.hpp" +#include "com/sun/star/rendering/XCanvas.hpp" +#include "com/sun/star/rendering/XSpriteCanvas.hpp" +#include "comphelper/processfactory.hxx" + +#include <sal/macros.h> +#include <rtl/strbuf.hxx> + +#include <set> +#include <typeinfo> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::datatransfer::clipboard; +using namespace ::com::sun::star::datatransfer::dnd; +using namespace ::com::sun::star; +using namespace com::sun; + +using ::com::sun::star::awt::XTopWindow; + +ImplAccessibleInfos::ImplAccessibleInfos() +{ + nAccessibleRole = 0xFFFF; + pAccessibleName = NULL; + pAccessibleDescription = NULL; + pLabeledByWindow = NULL; + pLabelForWindow = NULL; + pMemberOfWindow = NULL; +} + +ImplAccessibleInfos::~ImplAccessibleInfos() +{ + delete pAccessibleName; + delete pAccessibleDescription; +} + +::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > Window::GetAccessible( bool bCreate ) +{ + // do not optimize hierarchy for the top level border win (ie, when there is no parent) + /* // do not optimize accessible hierarchy at all to better reflect real VCL hierarchy + if ( GetParent() && ( GetType() == WINDOW_BORDERWINDOW ) && ( GetChildCount() == 1 ) ) + //if( !ImplIsAccessibleCandidate() ) + { + Window* pChild = GetAccessibleChildWindow( 0 ); + if ( pChild ) + return pChild->GetAccessible(); + } + */ + if ( !mpWindowImpl->mxAccessible.is() && bCreate ) + mpWindowImpl->mxAccessible = CreateAccessible(); + + return mpWindowImpl->mxAccessible; +} + +::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > Window::CreateAccessible() +{ + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > xAcc( GetComponentInterface( sal_True ), ::com::sun::star::uno::UNO_QUERY ); + return xAcc; +} + +void Window::SetAccessible( ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > x ) +{ + mpWindowImpl->mxAccessible = x; +} + +// skip all border windows that are no top level frames +bool Window::ImplIsAccessibleCandidate() const +{ + if( !mpWindowImpl->mbBorderWin ) + return true; + else + // #101741 do not check for WB_CLOSEABLE because undecorated floaters (like menus!) are closeable + if( mpWindowImpl->mbFrame && mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) ) + return true; + else + return false; +} + +bool Window::ImplIsAccessibleNativeFrame() const +{ + if( mpWindowImpl->mbFrame ) + // #101741 do not check for WB_CLOSEABLE because undecorated floaters (like menus!) are closeable + if( (mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE)) ) + return true; + else + return false; + else + return false; +} + +sal_uInt16 Window::ImplGetAccessibleCandidateChildWindowCount( sal_uInt16 nFirstWindowType ) const +{ + sal_uInt16 nChildren = 0; + Window* pChild = GetWindow( nFirstWindowType ); + while ( pChild ) + { + if( pChild->ImplIsAccessibleCandidate() ) + nChildren++; + else + nChildren = sal::static_int_cast<sal_uInt16>(nChildren + pChild->ImplGetAccessibleCandidateChildWindowCount( WINDOW_FIRSTCHILD )); + pChild = pChild->mpWindowImpl->mpNext; + } + return nChildren; +} + +Window* Window::ImplGetAccessibleCandidateChild( sal_uInt16 nChild, sal_uInt16& rChildCount, sal_uInt16 nFirstWindowType, bool bTopLevel ) const +{ + + if( bTopLevel ) + rChildCount = 0; + + Window* pChild = GetWindow( nFirstWindowType ); + while ( pChild ) + { + Window *pTmpChild = pChild; + + if( !pChild->ImplIsAccessibleCandidate() ) + pTmpChild = pChild->ImplGetAccessibleCandidateChild( nChild, rChildCount, WINDOW_FIRSTCHILD, false ); + + if ( nChild == rChildCount ) + return pTmpChild; + pChild = pChild->mpWindowImpl->mpNext; + rChildCount++; + } + + return NULL; +} + +Window* Window::GetAccessibleParentWindow() const +{ + if ( ImplIsAccessibleNativeFrame() ) + return NULL; + + Window* pParent = mpWindowImpl->mpParent; + if( GetType() == WINDOW_MENUBARWINDOW ) + { + // report the menubar as a child of THE workwindow + Window *pWorkWin = GetParent()->mpWindowImpl->mpFirstChild; + while( pWorkWin && (pWorkWin == this) ) + pWorkWin = pWorkWin->mpWindowImpl->mpNext; + pParent = pWorkWin; + } + // If this is a floating window which has a native border window, then that border should be reported as + // the accessible parent, unless the floating window is a PopupMenuFloatingWindow + + // The logic here has to match that of AccessibleFactory::createAccessibleContext in + // accessibility/source/helper/acc_factory.cxx to avoid PopupMenuFloatingWindow + // becoming a11y parents of themselves + else if( GetType() == WINDOW_FLOATINGWINDOW && + mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame && + !PopupMenuFloatingWindow::isPopupMenu(this)) + { + pParent = mpWindowImpl->mpBorderWindow; + } + else if( pParent && !pParent->ImplIsAccessibleCandidate() ) + { + pParent = pParent->mpWindowImpl->mpParent; + } + return pParent; +} + +sal_uInt16 Window::GetAccessibleChildWindowCount() +{ + sal_uInt16 nChildren = 0; + Window* pChild = mpWindowImpl->mpFirstChild; + while( pChild ) + { + if( pChild->IsVisible() ) + nChildren++; + pChild = pChild->mpWindowImpl->mpNext; + } + + // #107176# ignore overlapwindows + // this only affects non-system floating windows + // which are either not accessible (like the HelpAgent) or should be changed to system windows anyway + /* + if( ImplIsOverlapWindow() ) + { + Window* pOverlap = GetWindow( WINDOW_FIRSTOVERLAP ); + while ( pOverlap ) + { + if( pOverlap->IsVisible() ) + nChildren++; + pOverlap = pOverlap->GetWindow( WINDOW_NEXT ); + } + } + */ + + // report the menubarwindow as a child of THE workwindow + if( GetType() == WINDOW_BORDERWINDOW ) + { + if( ((ImplBorderWindow *) this)->mpMenuBarWindow && + ((ImplBorderWindow *) this)->mpMenuBarWindow->IsVisible() + ) + --nChildren; + } + else if( GetType() == WINDOW_WORKWINDOW ) + { + if( ((WorkWindow *) this)->GetMenuBar() && + ((WorkWindow *) this)->GetMenuBar()->GetWindow() && + ((WorkWindow *) this)->GetMenuBar()->GetWindow()->IsVisible() + ) + ++nChildren; + } + + return nChildren; +} + +Window* Window::GetAccessibleChildWindow( sal_uInt16 n ) +{ + // report the menubarwindow as a the first child of THE workwindow + if( GetType() == WINDOW_WORKWINDOW && ((WorkWindow *) this)->GetMenuBar() ) + { + if( n == 0 ) + { + MenuBar *pMenuBar = ((WorkWindow *) this)->GetMenuBar(); + if( pMenuBar->GetWindow() && pMenuBar->GetWindow()->IsVisible() ) + return pMenuBar->GetWindow(); + } + else + --n; + } + + // transform n to child number including invisible children + sal_uInt16 nChildren = n; + Window* pChild = mpWindowImpl->mpFirstChild; + while( pChild ) + { + if( pChild->IsVisible() ) + { + if( ! nChildren ) + break; + nChildren--; + } + pChild = pChild->mpWindowImpl->mpNext; + } + + if( GetType() == WINDOW_BORDERWINDOW && pChild && pChild->GetType() == WINDOW_MENUBARWINDOW ) + { + do pChild = pChild->mpWindowImpl->mpNext; while( pChild && ! pChild->IsVisible() ); + DBG_ASSERT( pChild, "GetAccessibleChildWindow(): wrong index in border window"); + } + if ( !pChild ) + { + // #107176# ignore overlapwindows + /* + if( ImplIsOverlapWindow() ) + { + Window* pOverlap = GetWindow( WINDOW_FIRSTOVERLAP ); + while ( !pChild && pOverlap ) + { + if ( !nChildren && pOverlap->IsVisible() ) + { + pChild = pOverlap; + break; + } + pOverlap = pOverlap->GetWindow( WINDOW_NEXT ); + if( pOverlap && pOverlap->IsVisible() ) + nChildren--; + } + } + */ + + } + if ( pChild && ( pChild->GetType() == WINDOW_BORDERWINDOW ) && ( pChild->GetChildCount() == 1 ) ) + { + pChild = pChild->GetChild( 0 ); + } + return pChild; +} + +void Window::SetAccessibleRole( sal_uInt16 nRole ) +{ + if ( !mpWindowImpl->mpAccessibleInfos ) + mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos; + + DBG_ASSERT( mpWindowImpl->mpAccessibleInfos->nAccessibleRole == 0xFFFF, "AccessibleRole already set!" ); + mpWindowImpl->mpAccessibleInfos->nAccessibleRole = nRole; +} + +sal_uInt16 Window::getDefaultAccessibleRole() const +{ + sal_uInt16 nRole = 0xFFFF; + switch ( GetType() ) + { + case WINDOW_MESSBOX: // MT: Would be nice to have special roles! + case WINDOW_INFOBOX: + case WINDOW_WARNINGBOX: + case WINDOW_ERRORBOX: + case WINDOW_QUERYBOX: nRole = accessibility::AccessibleRole::ALERT; break; + + case WINDOW_MODELESSDIALOG: + case WINDOW_MODALDIALOG: + case WINDOW_SYSTEMDIALOG: + case WINDOW_PRINTERSETUPDIALOG: + case WINDOW_PRINTDIALOG: + case WINDOW_TABDIALOG: + case WINDOW_BUTTONDIALOG: + case WINDOW_DIALOG: nRole = accessibility::AccessibleRole::DIALOG; break; + + case WINDOW_PUSHBUTTON: + case WINDOW_OKBUTTON: + case WINDOW_CANCELBUTTON: + case WINDOW_HELPBUTTON: + case WINDOW_IMAGEBUTTON: + case WINDOW_MOREBUTTON: + case WINDOW_SPINBUTTON: + case WINDOW_BUTTON: nRole = accessibility::AccessibleRole::PUSH_BUTTON; break; + case WINDOW_MENUBUTTON: nRole = accessibility::AccessibleRole::BUTTON_MENU; break; + + case WINDOW_PATHDIALOG: nRole = accessibility::AccessibleRole::DIRECTORY_PANE; break; + case WINDOW_FILEDIALOG: nRole = accessibility::AccessibleRole::FILE_CHOOSER; break; + case WINDOW_COLORDIALOG: nRole = accessibility::AccessibleRole::COLOR_CHOOSER; break; + case WINDOW_FONTDIALOG: nRole = accessibility::AccessibleRole::FONT_CHOOSER; break; + + case WINDOW_RADIOBUTTON: nRole = accessibility::AccessibleRole::RADIO_BUTTON; break; + case WINDOW_TRISTATEBOX: + case WINDOW_CHECKBOX: nRole = accessibility::AccessibleRole::CHECK_BOX; break; + + case WINDOW_MULTILINEEDIT: nRole = accessibility::AccessibleRole::SCROLL_PANE; break; + + case WINDOW_PATTERNFIELD: + case WINDOW_CALCINPUTLINE: + case WINDOW_EDIT: nRole = ( GetStyle() & WB_PASSWORD ) ? (accessibility::AccessibleRole::PASSWORD_TEXT) : (accessibility::AccessibleRole::TEXT); break; + + case WINDOW_PATTERNBOX: + case WINDOW_NUMERICBOX: + case WINDOW_METRICBOX: + case WINDOW_CURRENCYBOX: + case WINDOW_LONGCURRENCYBOX: + case WINDOW_COMBOBOX: nRole = accessibility::AccessibleRole::COMBO_BOX; break; + + case WINDOW_LISTBOX: + case WINDOW_MULTILISTBOX: nRole = accessibility::AccessibleRole::LIST; break; + + case WINDOW_TREELISTBOX: nRole = accessibility::AccessibleRole::TREE; break; + + case WINDOW_FIXEDTEXT: nRole = accessibility::AccessibleRole::LABEL; break; + case WINDOW_FIXEDLINE: + if( !GetText().isEmpty() ) + nRole = accessibility::AccessibleRole::LABEL; + else + nRole = accessibility::AccessibleRole::SEPARATOR; + break; + + case WINDOW_FIXEDBITMAP: + case WINDOW_FIXEDIMAGE: nRole = accessibility::AccessibleRole::ICON; break; + case WINDOW_GROUPBOX: nRole = accessibility::AccessibleRole::GROUP_BOX; break; + case WINDOW_SCROLLBAR: nRole = accessibility::AccessibleRole::SCROLL_BAR; break; + + case WINDOW_SLIDER: + case WINDOW_SPLITTER: + case WINDOW_SPLITWINDOW: nRole = accessibility::AccessibleRole::SPLIT_PANE; break; + + case WINDOW_DATEBOX: + case WINDOW_TIMEBOX: + case WINDOW_DATEFIELD: + case WINDOW_TIMEFIELD: nRole = accessibility::AccessibleRole::DATE_EDITOR; break; + + case WINDOW_NUMERICFIELD: + case WINDOW_METRICFIELD: + case WINDOW_CURRENCYFIELD: + case WINDOW_LONGCURRENCYFIELD: + case WINDOW_SPINFIELD: nRole = accessibility::AccessibleRole::SPIN_BOX; break; + + case WINDOW_TOOLBOX: nRole = accessibility::AccessibleRole::TOOL_BAR; break; + case WINDOW_STATUSBAR: nRole = accessibility::AccessibleRole::STATUS_BAR; break; + + case WINDOW_TABPAGE: nRole = accessibility::AccessibleRole::PANEL; break; + case WINDOW_TABCONTROL: nRole = accessibility::AccessibleRole::PAGE_TAB_LIST; break; + + case WINDOW_DOCKINGWINDOW: + case WINDOW_SYSWINDOW: nRole = (mpWindowImpl->mbFrame) ? accessibility::AccessibleRole::FRAME : + accessibility::AccessibleRole::PANEL; break; + + case WINDOW_FLOATINGWINDOW: nRole = ( mpWindowImpl->mbFrame || + (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) || + (GetStyle() & WB_OWNERDRAWDECORATION) ) ? accessibility::AccessibleRole::FRAME : + accessibility::AccessibleRole::WINDOW; break; + + case WINDOW_WORKWINDOW: nRole = accessibility::AccessibleRole::ROOT_PANE; break; + + case WINDOW_SCROLLBARBOX: nRole = accessibility::AccessibleRole::FILLER; break; + + case WINDOW_HELPTEXTWINDOW: nRole = accessibility::AccessibleRole::TOOL_TIP; break; + + case WINDOW_RULER: nRole = accessibility::AccessibleRole::RULER; break; + + case WINDOW_SCROLLWINDOW: nRole = accessibility::AccessibleRole::SCROLL_PANE; break; + + case WINDOW_WINDOW: + case WINDOW_CONTROL: + case WINDOW_BORDERWINDOW: + case WINDOW_SYSTEMCHILDWINDOW: + default: + if (ImplIsAccessibleNativeFrame() ) + nRole = accessibility::AccessibleRole::FRAME; + else if( IsScrollable() ) + nRole = accessibility::AccessibleRole::SCROLL_PANE; + else if( ((Window*)this)->ImplGetWindow()->IsMenuFloatingWindow() ) + nRole = accessibility::AccessibleRole::WINDOW; // #106002#, contextmenus are windows (i.e. toplevel) + else + // #104051# WINDOW seems to be a bad default role, use LAYEREDPANE instead + // a WINDOW is interpreted as a top-level window, which is typically not the case + //nRole = accessibility::AccessibleRole::WINDOW; + nRole = accessibility::AccessibleRole::PANEL; + } + return nRole; +} + +sal_uInt16 Window::GetAccessibleRole() const +{ + using namespace ::com::sun::star; + + sal_uInt16 nRole = mpWindowImpl->mpAccessibleInfos ? mpWindowImpl->mpAccessibleInfos->nAccessibleRole : 0xFFFF; + if ( nRole == 0xFFFF ) + nRole = getDefaultAccessibleRole(); + return nRole; +} + +void Window::SetAccessibleName( const OUString& rName ) +{ + if ( !mpWindowImpl->mpAccessibleInfos ) + mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos; + + OUString oldName = GetAccessibleName(); + + delete mpWindowImpl->mpAccessibleInfos->pAccessibleName; + mpWindowImpl->mpAccessibleInfos->pAccessibleName = new OUString( rName ); + + ImplCallEventListeners( VCLEVENT_WINDOW_FRAMETITLECHANGED, &oldName ); +} + +OUString Window::GetAccessibleName() const +{ + if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleName) + return *mpWindowImpl->mpAccessibleInfos->pAccessibleName; + return getDefaultAccessibleName(); +} + +OUString Window::getDefaultAccessibleName() const +{ + OUString aAccessibleName; + switch ( GetType() ) + { + case WINDOW_MULTILINEEDIT: + case WINDOW_PATTERNFIELD: + case WINDOW_NUMERICFIELD: + case WINDOW_METRICFIELD: + case WINDOW_CURRENCYFIELD: + case WINDOW_LONGCURRENCYFIELD: + case WINDOW_CALCINPUTLINE: + case WINDOW_EDIT: + + case WINDOW_DATEBOX: + case WINDOW_TIMEBOX: + case WINDOW_CURRENCYBOX: + case WINDOW_LONGCURRENCYBOX: + case WINDOW_DATEFIELD: + case WINDOW_TIMEFIELD: + case WINDOW_SPINFIELD: + + case WINDOW_COMBOBOX: + case WINDOW_LISTBOX: + case WINDOW_MULTILISTBOX: + case WINDOW_TREELISTBOX: + case WINDOW_METRICBOX: + { + Window *pLabel = GetAccessibleRelationLabeledBy(); + if ( pLabel && pLabel != this ) + aAccessibleName = pLabel->GetText(); + if (aAccessibleName.isEmpty()) + aAccessibleName = GetQuickHelpText(); + } + break; + + case WINDOW_IMAGEBUTTON: + case WINDOW_PUSHBUTTON: + aAccessibleName = GetText(); + if (aAccessibleName.isEmpty()) + { + aAccessibleName = GetQuickHelpText(); + if (aAccessibleName.isEmpty()) + aAccessibleName = GetHelpText(); + } + break; + + case WINDOW_TOOLBOX: + aAccessibleName = GetText(); + if( aAccessibleName.isEmpty() ) + aAccessibleName = "Tool Bar"; + break; + + case WINDOW_MOREBUTTON: + aAccessibleName = mpWindowImpl->maText; + break; + + default: + aAccessibleName = GetText(); + break; + } + + return GetNonMnemonicString( aAccessibleName ); +} + +void Window::SetAccessibleDescription( const OUString& rDescription ) +{ + if ( ! mpWindowImpl->mpAccessibleInfos ) + mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos; + + DBG_ASSERT( !mpWindowImpl->mpAccessibleInfos->pAccessibleDescription, "AccessibleDescription already set!" ); + delete mpWindowImpl->mpAccessibleInfos->pAccessibleDescription; + mpWindowImpl->mpAccessibleInfos->pAccessibleDescription = new OUString( rDescription ); +} + +OUString Window::GetAccessibleDescription() const +{ + OUString aAccessibleDescription; + if ( mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleDescription ) + { + aAccessibleDescription = *mpWindowImpl->mpAccessibleInfos->pAccessibleDescription; + } + else + { + // Special code for help text windows. ZT asks the border window for the + // description so we have to forward this request to our inner window. + const Window* pWin = ((Window *)this)->ImplGetWindow(); + if ( pWin->GetType() == WINDOW_HELPTEXTWINDOW ) + aAccessibleDescription = pWin->GetHelpText(); + else + aAccessibleDescription = GetHelpText(); + } + + return aAccessibleDescription; +} + +void Window::SetAccessibleRelationLabeledBy( Window* pLabeledBy ) +{ + if ( !mpWindowImpl->mpAccessibleInfos ) + mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos; + mpWindowImpl->mpAccessibleInfos->pLabeledByWindow = pLabeledBy; +} + +void Window::SetAccessibleRelationLabelFor( Window* pLabelFor ) +{ + if ( !mpWindowImpl->mpAccessibleInfos ) + mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos; + mpWindowImpl->mpAccessibleInfos->pLabelForWindow = pLabelFor; +} + +void Window::SetAccessibleRelationMemberOf( Window* pMemberOfWin ) +{ + if ( !mpWindowImpl->mpAccessibleInfos ) + mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos; + mpWindowImpl->mpAccessibleInfos->pMemberOfWindow = pMemberOfWin; +} + +Window* Window::GetAccessibleRelationMemberOf() const +{ + if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pMemberOfWindow) + return mpWindowImpl->mpAccessibleInfos->pMemberOfWindow; + + if (!isContainerWindow(this) && !isContainerWindow(GetParent())) + return getLegacyNonLayoutAccessibleRelationMemberOf(); + + return NULL; +} + +Window* Window::getAccessibleRelationLabelFor() const +{ + if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pLabelForWindow) + return mpWindowImpl->mpAccessibleInfos->pLabelForWindow; + + return NULL; +} + +Window* Window::GetAccessibleRelationLabelFor() const +{ + Window* pWindow = getAccessibleRelationLabelFor(); + + if (pWindow) + return pWindow; + + if (!isContainerWindow(this) && !isContainerWindow(GetParent())) + return getLegacyNonLayoutAccessibleRelationLabelFor(); + + return NULL; +} + +Window* Window::GetAccessibleRelationLabeledBy() const +{ + if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pLabeledByWindow) + return mpWindowImpl->mpAccessibleInfos->pLabeledByWindow; + + std::vector<FixedText*> aMnemonicLabels(list_mnemonic_labels()); + if (!aMnemonicLabels.empty()) + { + //if we have multiple labels, then prefer the first that is visible + for (std::vector<FixedText*>::iterator + aI = aMnemonicLabels.begin(), aEnd = aMnemonicLabels.end(); aI != aEnd; ++aI) + { + Window *pCandidate = *aI; + if (pCandidate->IsVisible()) + return pCandidate; + } + return aMnemonicLabels[0]; + } + + if (!isContainerWindow(this) && !isContainerWindow(GetParent())) + return getLegacyNonLayoutAccessibleRelationLabeledBy(); + + return NULL; +} + +bool Window::IsAccessibilityEventsSuppressed( bool bTraverseParentPath ) +{ + if( !bTraverseParentPath ) + return mpWindowImpl->mbSuppressAccessibilityEvents; + else + { + Window *pParent = this; + while ( pParent && pParent->mpWindowImpl) + { + if( pParent->mpWindowImpl->mbSuppressAccessibilityEvents ) + return true; + else + pParent = pParent->mpWindowImpl->mpParent; // do not use GetParent() to find borderwindows that are frames + } + return false; + } +} + +void Window::SetAccessibilityEventsSuppressed(bool bSuppressed) +{ + mpWindowImpl->mbSuppressAccessibilityEvents = bSuppressed; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |