build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / window / accessibility.cxx
blobab2ac82bee8507ff1debf1a3ea0cf9624e0d4a56
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 <config_features.h>
22 #include <i18nlangtag/mslangid.hxx>
24 #include "tools/time.hxx"
25 #include "tools/debug.hxx"
26 #include "tools/rc.h"
28 #include "unotools/fontcfg.hxx"
29 #include "unotools/confignode.hxx"
31 #include <vcl/layout.hxx>
32 #include <vcl/salgtype.hxx>
33 #include <vcl/event.hxx>
34 #include <vcl/fixed.hxx>
35 #include <vcl/help.hxx>
36 #include <vcl/cursor.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/window.hxx>
39 #include <vcl/syswin.hxx>
40 #include <vcl/syschild.hxx>
41 #include <vcl/dockwin.hxx>
42 #include <vcl/menu.hxx>
43 #include <vcl/wrkwin.hxx>
44 #include <vcl/wall.hxx>
45 #include <vcl/gradient.hxx>
46 #include <vcl/button.hxx>
47 #include <vcl/taskpanelist.hxx>
48 #include <vcl/dialog.hxx>
49 #include <vcl/unowrap.hxx>
50 #include <vcl/gdimtf.hxx>
51 #include <vcl/pdfextoutdevdata.hxx>
52 #include <vcl/popupmenuwindow.hxx>
53 #include <vcl/lazydelete.hxx>
54 #include <vcl/virdev.hxx>
55 #include <vcl/settings.hxx>
57 // declare system types in sysdata.hxx
58 #include <vcl/sysdata.hxx>
60 #include "salframe.hxx"
61 #include "salobj.hxx"
62 #include "salinst.hxx"
63 #include "salgdi.hxx"
64 #include "svdata.hxx"
65 #include "fontinstance.hxx"
66 #include "window.h"
67 #include "toolbox.h"
68 #include "outdev.h"
69 #include "PhysicalFontCollection.hxx"
70 #include "brdwin.hxx"
71 #include "helpwin.hxx"
72 #include "sallayout.hxx"
73 #include "dndlistenercontainer.hxx"
74 #include "dndeventdispatcher.hxx"
76 #include "com/sun/star/accessibility/XAccessible.hpp"
77 #include "com/sun/star/accessibility/AccessibleRole.hpp"
78 #include "com/sun/star/datatransfer/dnd/XDragSource.hpp"
79 #include "com/sun/star/datatransfer/dnd/XDropTarget.hpp"
80 #include "com/sun/star/datatransfer/clipboard/XClipboard.hpp"
81 #include "com/sun/star/datatransfer/clipboard/SystemClipboard.hpp"
82 #include "com/sun/star/lang/XInitialization.hpp"
83 #include "com/sun/star/lang/XComponent.hpp"
84 #include "com/sun/star/lang/XServiceName.hpp"
85 #include "comphelper/processfactory.hxx"
87 #include <sal/macros.h>
88 #include <rtl/strbuf.hxx>
90 #include <set>
91 #include <typeinfo>
93 using namespace ::com::sun::star::uno;
94 using namespace ::com::sun::star::lang;
95 using namespace ::com::sun::star::datatransfer::clipboard;
96 using namespace ::com::sun::star::datatransfer::dnd;
97 using namespace ::com::sun::star;
100 ImplAccessibleInfos::ImplAccessibleInfos()
102 nAccessibleRole = 0xFFFF;
103 pAccessibleName = nullptr;
104 pAccessibleDescription = nullptr;
105 pLabeledByWindow = nullptr;
106 pLabelForWindow = nullptr;
107 pMemberOfWindow = nullptr;
110 ImplAccessibleInfos::~ImplAccessibleInfos()
112 delete pAccessibleName;
113 delete pAccessibleDescription;
116 namespace vcl {
118 css::uno::Reference< css::accessibility::XAccessible > Window::GetAccessible( bool bCreate )
120 // do not optimize hierarchy for the top level border win (ie, when there is no parent)
121 /* // do not optimize accessible hierarchy at all to better reflect real VCL hierarchy
122 if ( GetParent() && ( GetType() == WINDOW_BORDERWINDOW ) && ( GetChildCount() == 1 ) )
123 //if( !ImplIsAccessibleCandidate() )
125 vcl::Window* pChild = GetAccessibleChildWindow( 0 );
126 if ( pChild )
127 return pChild->GetAccessible();
130 if ( !mpWindowImpl )
131 return css::uno::Reference< css::accessibility::XAccessible >();
132 if ( !mpWindowImpl->mxAccessible.is() && bCreate )
133 mpWindowImpl->mxAccessible = CreateAccessible();
135 return mpWindowImpl->mxAccessible;
138 css::uno::Reference< css::accessibility::XAccessible > Window::CreateAccessible()
140 css::uno::Reference< css::accessibility::XAccessible > xAcc( GetComponentInterface(), css::uno::UNO_QUERY );
141 return xAcc;
144 void Window::SetAccessible( const css::uno::Reference< css::accessibility::XAccessible >& x )
146 assert(mpWindowImpl);
147 mpWindowImpl->mxAccessible = x;
150 // skip all border windows that are no top level frames
151 bool Window::ImplIsAccessibleCandidate() const
153 if( !mpWindowImpl->mbBorderWin )
154 return true;
155 else
156 // #101741 do not check for WB_CLOSEABLE because undecorated floaters (like menus!) are closeable
157 if( mpWindowImpl->mbFrame && mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE) )
158 return true;
159 else
160 return false;
163 bool Window::ImplIsAccessibleNativeFrame() const
165 if( mpWindowImpl->mbFrame )
166 // #101741 do not check for WB_CLOSEABLE because undecorated floaters (like menus!) are closeable
167 if( (mpWindowImpl->mnStyle & (WB_MOVEABLE | WB_SIZEABLE)) )
168 return true;
169 else
170 return false;
171 else
172 return false;
175 vcl::Window* Window::GetAccessibleParentWindow() const
177 if ( ImplIsAccessibleNativeFrame() )
178 return nullptr;
180 vcl::Window* pParent = mpWindowImpl->mpParent;
181 if( GetType() == WINDOW_MENUBARWINDOW )
183 // report the menubar as a child of THE workwindow
184 vcl::Window *pWorkWin = GetParent()->mpWindowImpl->mpFirstChild;
185 while( pWorkWin && (pWorkWin == this) )
186 pWorkWin = pWorkWin->mpWindowImpl->mpNext;
187 pParent = pWorkWin;
189 // If this is a floating window which has a native border window, then that border should be reported as
190 // the accessible parent, unless the floating window is a PopupMenuFloatingWindow
192 // The logic here has to match that of AccessibleFactory::createAccessibleContext in
193 // accessibility/source/helper/acc_factory.cxx to avoid PopupMenuFloatingWindow
194 // becoming a11y parents of themselves
195 else if( GetType() == WINDOW_FLOATINGWINDOW &&
196 mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame &&
197 !PopupMenuFloatingWindow::isPopupMenu(this))
199 pParent = mpWindowImpl->mpBorderWindow;
201 else if( pParent && !pParent->ImplIsAccessibleCandidate() )
203 pParent = pParent->mpWindowImpl->mpParent;
205 return pParent;
208 sal_uInt16 Window::GetAccessibleChildWindowCount()
210 sal_uInt16 nChildren = 0;
211 vcl::Window* pChild = mpWindowImpl->mpFirstChild;
212 while( pChild )
214 if( pChild->IsVisible() )
215 nChildren++;
216 pChild = pChild->mpWindowImpl->mpNext;
219 // report the menubarwindow as a child of THE workwindow
220 if( GetType() == WINDOW_BORDERWINDOW )
222 ImplBorderWindow *pBorderWindow = static_cast<ImplBorderWindow*>(this);
223 if( pBorderWindow->mpMenuBarWindow &&
224 pBorderWindow->mpMenuBarWindow->IsVisible()
226 --nChildren;
228 else if( GetType() == WINDOW_WORKWINDOW )
230 WorkWindow *pWorkWindow = static_cast<WorkWindow*>(this);
231 if( pWorkWindow->GetMenuBar() &&
232 pWorkWindow->GetMenuBar()->GetWindow() &&
233 pWorkWindow->GetMenuBar()->GetWindow()->IsVisible()
235 ++nChildren;
238 return nChildren;
241 vcl::Window* Window::GetAccessibleChildWindow( sal_uInt16 n )
243 // report the menubarwindow as a the first child of THE workwindow
244 if( GetType() == WINDOW_WORKWINDOW && static_cast<WorkWindow *>(this)->GetMenuBar() )
246 if( n == 0 )
248 MenuBar *pMenuBar = static_cast<WorkWindow *>(this)->GetMenuBar();
249 if( pMenuBar->GetWindow() && pMenuBar->GetWindow()->IsVisible() )
250 return pMenuBar->GetWindow();
252 else
253 --n;
256 // transform n to child number including invisible children
257 sal_uInt16 nChildren = n;
258 vcl::Window* pChild = mpWindowImpl->mpFirstChild;
259 while( pChild )
261 if( pChild->IsVisible() )
263 if( ! nChildren )
264 break;
265 nChildren--;
267 pChild = pChild->mpWindowImpl->mpNext;
270 if( GetType() == WINDOW_BORDERWINDOW && pChild && pChild->GetType() == WINDOW_MENUBARWINDOW )
272 do pChild = pChild->mpWindowImpl->mpNext; while( pChild && ! pChild->IsVisible() );
273 SAL_WARN_IF( !pChild, "vcl", "GetAccessibleChildWindow(): wrong index in border window");
276 if ( pChild && ( pChild->GetType() == WINDOW_BORDERWINDOW ) && ( pChild->GetChildCount() == 1 ) )
278 pChild = pChild->GetChild( 0 );
280 return pChild;
283 void Window::SetAccessibleRole( sal_uInt16 nRole )
285 if ( !mpWindowImpl->mpAccessibleInfos )
286 mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
288 SAL_WARN_IF( mpWindowImpl->mpAccessibleInfos->nAccessibleRole != 0xFFFF, "vcl", "AccessibleRole already set!" );
289 mpWindowImpl->mpAccessibleInfos->nAccessibleRole = nRole;
292 sal_uInt16 Window::getDefaultAccessibleRole() const
294 sal_uInt16 nRole = 0xFFFF;
295 switch ( GetType() )
297 case WINDOW_MESSBOX: // MT: Would be nice to have special roles!
298 case WINDOW_INFOBOX:
299 case WINDOW_WARNINGBOX:
300 case WINDOW_ERRORBOX:
301 case WINDOW_QUERYBOX: nRole = accessibility::AccessibleRole::ALERT; break;
303 case WINDOW_MODELESSDIALOG:
304 case WINDOW_MODALDIALOG:
305 case WINDOW_SYSTEMDIALOG:
306 case WINDOW_PRINTERSETUPDIALOG:
307 case WINDOW_PRINTDIALOG:
308 case WINDOW_TABDIALOG:
309 case WINDOW_BUTTONDIALOG:
310 case WINDOW_DIALOG: nRole = accessibility::AccessibleRole::DIALOG; break;
312 case WINDOW_PUSHBUTTON:
313 case WINDOW_OKBUTTON:
314 case WINDOW_CANCELBUTTON:
315 case WINDOW_HELPBUTTON:
316 case WINDOW_IMAGEBUTTON:
317 case WINDOW_MOREBUTTON:
318 case WINDOW_SPINBUTTON:
319 case WINDOW_BUTTON: nRole = accessibility::AccessibleRole::PUSH_BUTTON; break;
320 case WINDOW_MENUBUTTON: nRole = accessibility::AccessibleRole::BUTTON_MENU; break;
322 case WINDOW_PATHDIALOG: nRole = accessibility::AccessibleRole::DIRECTORY_PANE; break;
323 case WINDOW_FILEDIALOG: nRole = accessibility::AccessibleRole::FILE_CHOOSER; break;
324 case WINDOW_COLORDIALOG: nRole = accessibility::AccessibleRole::COLOR_CHOOSER; break;
325 case WINDOW_FONTDIALOG: nRole = accessibility::AccessibleRole::FONT_CHOOSER; break;
327 case WINDOW_RADIOBUTTON: nRole = accessibility::AccessibleRole::RADIO_BUTTON; break;
328 case WINDOW_TRISTATEBOX:
329 case WINDOW_CHECKBOX: nRole = accessibility::AccessibleRole::CHECK_BOX; break;
331 case WINDOW_MULTILINEEDIT: nRole = accessibility::AccessibleRole::SCROLL_PANE; break;
333 case WINDOW_PATTERNFIELD:
334 case WINDOW_CALCINPUTLINE:
335 case WINDOW_EDIT: nRole = ( GetStyle() & WB_PASSWORD ) ? (accessibility::AccessibleRole::PASSWORD_TEXT) : (accessibility::AccessibleRole::TEXT); break;
337 case WINDOW_PATTERNBOX:
338 case WINDOW_NUMERICBOX:
339 case WINDOW_METRICBOX:
340 case WINDOW_CURRENCYBOX:
341 case WINDOW_LONGCURRENCYBOX:
342 case WINDOW_COMBOBOX: nRole = accessibility::AccessibleRole::COMBO_BOX; break;
344 case WINDOW_LISTBOX:
345 case WINDOW_MULTILISTBOX: nRole = accessibility::AccessibleRole::LIST; break;
347 case WINDOW_TREELISTBOX: nRole = accessibility::AccessibleRole::TREE; break;
349 case WINDOW_FIXEDTEXT: nRole = accessibility::AccessibleRole::LABEL; break;
350 case WINDOW_FIXEDLINE:
351 if( !GetText().isEmpty() )
352 nRole = accessibility::AccessibleRole::LABEL;
353 else
354 nRole = accessibility::AccessibleRole::SEPARATOR;
355 break;
357 case WINDOW_FIXEDBITMAP:
358 case WINDOW_FIXEDIMAGE: nRole = accessibility::AccessibleRole::ICON; break;
359 case WINDOW_GROUPBOX: nRole = accessibility::AccessibleRole::GROUP_BOX; break;
360 case WINDOW_SCROLLBAR: nRole = accessibility::AccessibleRole::SCROLL_BAR; break;
362 case WINDOW_SLIDER:
363 case WINDOW_SPLITTER:
364 case WINDOW_SPLITWINDOW: nRole = accessibility::AccessibleRole::SPLIT_PANE; break;
366 case WINDOW_DATEBOX:
367 case WINDOW_TIMEBOX:
368 case WINDOW_DATEFIELD:
369 case WINDOW_TIMEFIELD: nRole = accessibility::AccessibleRole::DATE_EDITOR; break;
371 case WINDOW_NUMERICFIELD:
372 case WINDOW_METRICFIELD:
373 case WINDOW_CURRENCYFIELD:
374 case WINDOW_LONGCURRENCYFIELD:
375 case WINDOW_SPINFIELD: nRole = accessibility::AccessibleRole::SPIN_BOX; break;
377 case WINDOW_TOOLBOX: nRole = accessibility::AccessibleRole::TOOL_BAR; break;
378 case WINDOW_STATUSBAR: nRole = accessibility::AccessibleRole::STATUS_BAR; break;
380 case WINDOW_TABPAGE: nRole = accessibility::AccessibleRole::PANEL; break;
381 case WINDOW_TABCONTROL: nRole = accessibility::AccessibleRole::PAGE_TAB_LIST; break;
383 case WINDOW_DOCKINGWINDOW:
384 case WINDOW_SYSWINDOW: nRole = (mpWindowImpl->mbFrame) ? accessibility::AccessibleRole::FRAME :
385 accessibility::AccessibleRole::PANEL; break;
387 case WINDOW_FLOATINGWINDOW: nRole = ( mpWindowImpl->mbFrame ||
388 (mpWindowImpl->mpBorderWindow && mpWindowImpl->mpBorderWindow->mpWindowImpl->mbFrame) ||
389 (GetStyle() & WB_OWNERDRAWDECORATION) ) ? accessibility::AccessibleRole::FRAME :
390 accessibility::AccessibleRole::WINDOW; break;
392 case WINDOW_WORKWINDOW: nRole = accessibility::AccessibleRole::ROOT_PANE; break;
394 case WINDOW_SCROLLBARBOX: nRole = accessibility::AccessibleRole::FILLER; break;
396 case WINDOW_HELPTEXTWINDOW: nRole = accessibility::AccessibleRole::TOOL_TIP; break;
398 case WINDOW_RULER: nRole = accessibility::AccessibleRole::RULER; break;
400 case WINDOW_SCROLLWINDOW: nRole = accessibility::AccessibleRole::SCROLL_PANE; break;
402 case WINDOW_WINDOW:
403 case WINDOW_CONTROL:
404 case WINDOW_BORDERWINDOW:
405 case WINDOW_SYSTEMCHILDWINDOW:
406 default:
407 if (ImplIsAccessibleNativeFrame() )
408 nRole = accessibility::AccessibleRole::FRAME;
409 else if( IsScrollable() )
410 nRole = accessibility::AccessibleRole::SCROLL_PANE;
411 else if( const_cast<vcl::Window*>(this)->ImplGetWindow()->IsMenuFloatingWindow() )
412 nRole = accessibility::AccessibleRole::WINDOW; // #106002#, contextmenus are windows (i.e. toplevel)
413 else
414 // #104051# WINDOW seems to be a bad default role, use LAYEREDPANE instead
415 // a WINDOW is interpreted as a top-level window, which is typically not the case
416 //nRole = accessibility::AccessibleRole::WINDOW;
417 nRole = accessibility::AccessibleRole::PANEL;
419 return nRole;
422 sal_uInt16 Window::GetAccessibleRole() const
424 using namespace ::com::sun::star;
426 sal_uInt16 nRole = mpWindowImpl->mpAccessibleInfos ? mpWindowImpl->mpAccessibleInfos->nAccessibleRole : 0xFFFF;
427 if ( nRole == 0xFFFF )
428 nRole = getDefaultAccessibleRole();
429 return nRole;
432 void Window::SetAccessibleName( const OUString& rName )
434 if ( !mpWindowImpl->mpAccessibleInfos )
435 mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
437 OUString oldName = GetAccessibleName();
439 delete mpWindowImpl->mpAccessibleInfos->pAccessibleName;
440 mpWindowImpl->mpAccessibleInfos->pAccessibleName = new OUString( rName );
442 CallEventListeners( VCLEVENT_WINDOW_FRAMETITLECHANGED, &oldName );
445 OUString Window::GetAccessibleName() const
447 if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleName)
448 return *mpWindowImpl->mpAccessibleInfos->pAccessibleName;
449 return getDefaultAccessibleName();
452 OUString Window::getDefaultAccessibleName() const
454 OUString aAccessibleName;
455 switch ( GetType() )
457 case WINDOW_MULTILINEEDIT:
458 case WINDOW_PATTERNFIELD:
459 case WINDOW_NUMERICFIELD:
460 case WINDOW_METRICFIELD:
461 case WINDOW_CURRENCYFIELD:
462 case WINDOW_LONGCURRENCYFIELD:
463 case WINDOW_CALCINPUTLINE:
464 case WINDOW_EDIT:
466 case WINDOW_DATEBOX:
467 case WINDOW_TIMEBOX:
468 case WINDOW_CURRENCYBOX:
469 case WINDOW_LONGCURRENCYBOX:
470 case WINDOW_DATEFIELD:
471 case WINDOW_TIMEFIELD:
472 case WINDOW_SPINFIELD:
474 case WINDOW_COMBOBOX:
475 case WINDOW_LISTBOX:
476 case WINDOW_MULTILISTBOX:
477 case WINDOW_TREELISTBOX:
478 case WINDOW_METRICBOX:
480 vcl::Window *pLabel = GetAccessibleRelationLabeledBy();
481 if ( pLabel && pLabel != this )
482 aAccessibleName = pLabel->GetText();
483 if (aAccessibleName.isEmpty())
484 aAccessibleName = GetQuickHelpText();
486 break;
488 case WINDOW_IMAGEBUTTON:
489 case WINDOW_PUSHBUTTON:
490 aAccessibleName = GetText();
491 if (aAccessibleName.isEmpty())
493 aAccessibleName = GetQuickHelpText();
494 if (aAccessibleName.isEmpty())
495 aAccessibleName = GetHelpText();
497 break;
499 case WINDOW_TOOLBOX:
500 aAccessibleName = GetText();
501 break;
503 case WINDOW_MOREBUTTON:
504 aAccessibleName = mpWindowImpl->maText;
505 break;
507 default:
508 aAccessibleName = GetText();
509 break;
512 return GetNonMnemonicString( aAccessibleName );
515 void Window::SetAccessibleDescription( const OUString& rDescription )
517 if ( ! mpWindowImpl->mpAccessibleInfos )
518 mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
520 SAL_WARN_IF( mpWindowImpl->mpAccessibleInfos->pAccessibleDescription, "vcl", "AccessibleDescription already set!" );
521 delete mpWindowImpl->mpAccessibleInfos->pAccessibleDescription;
522 mpWindowImpl->mpAccessibleInfos->pAccessibleDescription = new OUString( rDescription );
525 OUString Window::GetAccessibleDescription() const
527 OUString aAccessibleDescription;
528 if ( mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pAccessibleDescription )
530 aAccessibleDescription = *mpWindowImpl->mpAccessibleInfos->pAccessibleDescription;
532 else
534 // Special code for help text windows. ZT asks the border window for the
535 // description so we have to forward this request to our inner window.
536 const vcl::Window* pWin = const_cast<vcl::Window *>(this)->ImplGetWindow();
537 if ( pWin->GetType() == WINDOW_HELPTEXTWINDOW )
538 aAccessibleDescription = pWin->GetHelpText();
539 else
540 aAccessibleDescription = GetHelpText();
543 return aAccessibleDescription;
546 void Window::SetAccessibleRelationLabeledBy( vcl::Window* pLabeledBy )
548 if ( !mpWindowImpl->mpAccessibleInfos )
549 mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
550 mpWindowImpl->mpAccessibleInfos->pLabeledByWindow = pLabeledBy;
553 void Window::SetAccessibleRelationLabelFor( vcl::Window* pLabelFor )
555 if ( !mpWindowImpl->mpAccessibleInfos )
556 mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
557 mpWindowImpl->mpAccessibleInfos->pLabelForWindow = pLabelFor;
560 void Window::SetAccessibleRelationMemberOf( vcl::Window* pMemberOfWin )
562 if ( !mpWindowImpl->mpAccessibleInfos )
563 mpWindowImpl->mpAccessibleInfos = new ImplAccessibleInfos;
564 mpWindowImpl->mpAccessibleInfos->pMemberOfWindow = pMemberOfWin;
567 vcl::Window* Window::GetAccessibleRelationMemberOf() const
569 if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pMemberOfWindow)
570 return mpWindowImpl->mpAccessibleInfos->pMemberOfWindow;
572 if (!isContainerWindow(this) && !isContainerWindow(GetParent()))
573 return getLegacyNonLayoutAccessibleRelationMemberOf();
575 return nullptr;
578 vcl::Window* Window::getAccessibleRelationLabelFor() const
580 if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pLabelForWindow)
581 return mpWindowImpl->mpAccessibleInfos->pLabelForWindow;
583 return nullptr;
586 vcl::Window* Window::GetAccessibleRelationLabelFor() const
588 vcl::Window* pWindow = getAccessibleRelationLabelFor();
590 if (pWindow)
591 return pWindow;
593 if (!isContainerWindow(this) && !isContainerWindow(GetParent()))
594 return getLegacyNonLayoutAccessibleRelationLabelFor();
596 return nullptr;
599 vcl::Window* Window::GetAccessibleRelationLabeledBy() const
601 if (mpWindowImpl->mpAccessibleInfos && mpWindowImpl->mpAccessibleInfos->pLabeledByWindow)
602 return mpWindowImpl->mpAccessibleInfos->pLabeledByWindow;
604 std::vector<VclPtr<FixedText> > aMnemonicLabels(list_mnemonic_labels());
605 if (!aMnemonicLabels.empty())
607 //if we have multiple labels, then prefer the first that is visible
608 for (auto const & rCandidate : aMnemonicLabels)
610 if (rCandidate->IsVisible())
611 return rCandidate;
613 return aMnemonicLabels[0];
616 if (!isContainerWindow(this) && !isContainerWindow(GetParent()))
617 return getLegacyNonLayoutAccessibleRelationLabeledBy();
619 return nullptr;
622 bool Window::IsAccessibilityEventsSuppressed( bool bTraverseParentPath )
624 if( !bTraverseParentPath )
625 return mpWindowImpl->mbSuppressAccessibilityEvents;
626 else
628 vcl::Window *pParent = this;
629 while ( pParent && pParent->mpWindowImpl)
631 if( pParent->mpWindowImpl->mbSuppressAccessibilityEvents )
632 return true;
633 else
634 pParent = pParent->mpWindowImpl->mpParent; // do not use GetParent() to find borderwindows that are frames
636 return false;
640 void Window::SetAccessibilityEventsSuppressed(bool bSuppressed)
642 mpWindowImpl->mbSuppressAccessibilityEvents = bSuppressed;
645 } /* namespace vcl */
647 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */